summaryrefslogtreecommitdiff
path: root/src/controls
diff options
context:
space:
mode:
Diffstat (limited to 'src/controls')
-rw-r--r--src/controls/AbstractCheckable.qml149
-rw-r--r--src/controls/ApplicationWindow.qml175
-rw-r--r--src/controls/Button.qml79
-rw-r--r--src/controls/CheckBox.qml147
-rw-r--r--src/controls/ComboBox.qml172
-rw-r--r--src/controls/ContextMenu.qml105
-rw-r--r--src/controls/GroupBox.qml193
-rw-r--r--src/controls/Label.qml86
-rw-r--r--src/controls/Menu.qml293
-rw-r--r--src/controls/MenuBar.qml209
-rw-r--r--src/controls/Page.qml99
-rw-r--r--src/controls/PageAnimation.qml60
-rw-r--r--src/controls/PageStack.qml991
-rw-r--r--src/controls/PageTransition.qml71
-rw-r--r--src/controls/ProgressBar.qml132
-rw-r--r--src/controls/RadioButton.qml74
-rw-r--r--src/controls/ScrollArea.qml284
-rw-r--r--src/controls/Slider.qml284
-rw-r--r--src/controls/SpinBox.qml325
-rw-r--r--src/controls/Splitter.qml401
-rw-r--r--src/controls/StatusBar.qml77
-rw-r--r--src/controls/Tab.qml56
-rw-r--r--src/controls/TabFrame.qml155
-rw-r--r--src/controls/TableView.qml676
-rw-r--r--src/controls/TableViewColumn.qml85
-rw-r--r--src/controls/TextArea.qml662
-rw-r--r--src/controls/TextField.qml564
-rw-r--r--src/controls/ToolBar.qml82
-rw-r--r--src/controls/ToolButton.qml82
-rw-r--r--src/controls/controls.pro45
-rw-r--r--src/controls/doc/images/placeholder.pngbin0 -> 9878 bytes
-rw-r--r--src/controls/doc/images/tableview.pngbin0 -> 55512 bytes
-rw-r--r--src/controls/doc/qtquickcontrols.qdocconf90
-rw-r--r--src/controls/doc/src/applicationwindow.qdoc31
-rw-r--r--src/controls/doc/src/containers.qdoc31
-rw-r--r--src/controls/doc/src/controls.qdoc31
-rw-r--r--src/controls/doc/src/indicators.qdoc31
-rw-r--r--src/controls/doc/src/menus.qdoc31
-rw-r--r--src/controls/doc/src/navigation.qdoc31
-rw-r--r--src/controls/doc/src/qtquickcontrols-examples.qdoc33
-rw-r--r--src/controls/doc/src/qtquickcontrols-index.qdoc79
-rw-r--r--src/controls/doc/src/qtquickcontrols-overview.qdoc32
-rw-r--r--src/controls/doc/src/qtquickcontrols.qdoc45
-rw-r--r--src/controls/doc/src/styles.qdoc45
-rw-r--r--src/controls/doc/src/views.qdoc33
-rw-r--r--src/controls/plugin.cpp104
-rw-r--r--src/controls/plugin.json1
-rw-r--r--src/controls/plugin.pri27
-rw-r--r--src/controls/plugin_p.h61
-rw-r--r--src/controls/plugins.qmltypes405
-rw-r--r--src/controls/qmldir30
-rw-r--r--src/controls/qpagestatus.h65
-rw-r--r--src/controls/qquicklayout.cpp205
-rw-r--r--src/controls/qquicklayout_p.h141
-rw-r--r--src/controls/qquicklayoutengine.cpp294
-rw-r--r--src/controls/qquicklayoutengine_p.h88
-rw-r--r--src/controls/qquicklinearlayout.cpp269
-rw-r--r--src/controls/qquicklinearlayout_p.h115
-rw-r--r--src/controls/qtaction.cpp284
-rw-r--r--src/controls/qtaction_p.h148
-rw-r--r--src/controls/qtexclusivegroup.cpp185
-rw-r--r--src/controls/qtexclusivegroup_p.h78
-rw-r--r--src/controls/qtmenu.cpp385
-rw-r--r--src/controls/qtmenu_p.h166
-rw-r--r--src/controls/qtmenubar.cpp116
-rw-r--r--src/controls/qtmenubar_p.h89
-rw-r--r--src/controls/qtmenuitem.cpp437
-rw-r--r--src/controls/qtmenuitem_p.h170
-rw-r--r--src/controls/qtmenupopupwindow.cpp150
-rw-r--r--src/controls/qtmenupopupwindow_p.h83
70 files changed, 11452 insertions, 0 deletions
diff --git a/src/controls/AbstractCheckable.qml b/src/controls/AbstractCheckable.qml
new file mode 100644
index 00000000..206361e2
--- /dev/null
+++ b/src/controls/AbstractCheckable.qml
@@ -0,0 +1,149 @@
+import QtQuick 2.0
+import QtQuick.Controls.Private 1.0
+
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+
+/*!
+ \qmltype AbstractCheckable
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief An abstract representation of a checkable control
+ \qmlabstract
+*/
+
+Control {
+ id: abstractCheckable
+
+ /*!
+ Emitted whenever the radio button is clicked.
+ */
+ signal clicked
+
+ /*!
+ \qmlproperty bool RadioButton::pressed
+
+ This property is \c true if the radio button is pressed.
+ Set this property to manually invoke a mouse click.
+ */
+ readonly property alias pressed: mouseArea.effectivePressed
+
+ /*!
+ This property is \c true if the radio button is checked, and determines
+ whether \l checkedState is \c Qt.Checked or \c Qt.UnChecked.
+
+ If \l partiallyCheckedEnabled is \c true, this property will be
+ \c false.
+ */
+ property bool checked: false
+
+ /*!
+ \qmlproperty bool RadioButton::containsMouse
+
+ This property is \c true if the radio button currently contains the
+ mouse cursor.
+ */
+ readonly property alias containsMouse: mouseArea.containsMouse
+
+ /*!
+ This property is \c true if the radio button takes the focus when it is
+ pressed; \l{QQuickItem::forceActiveFocus()}{forceActiveFocus()} will be
+ called on the radio button.
+ */
+ property bool activeFocusOnPress: false
+
+ /*!
+ \qmlproperty ExclusiveGroup RadioButton::exclusiveGroup
+
+ This property stores the ExclusiveGroup that the radio button belongs
+ to.
+ */
+ property ExclusiveGroup exclusiveGroup: null
+
+ /*!
+ This property holds the text that the label should display.
+ */
+ property string text
+
+ /*! \internal */
+ property var __cycleStatesHandler: cycleRadioButtonStates
+
+ /*! \internal */
+ onExclusiveGroupChanged: {
+ if (exclusiveGroup)
+ exclusiveGroup.registerCheckable(abstractCheckable)
+ }
+
+ MouseArea {
+ id: mouseArea
+ focus: true
+ anchors.fill: parent
+ hoverEnabled: true
+ enabled: !keyPressed
+
+ property bool keyPressed: false
+ property bool effectivePressed: pressed && containsMouse || keyPressed
+
+ onClicked: abstractCheckable.clicked();
+
+ onPressed: if (activeFocusOnPress) forceActiveFocus();
+
+ onReleased: {
+ if (containsMouse && (!exclusiveGroup || !checked))
+ __cycleStatesHandler();
+ }
+ }
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Space && !event.isAutoRepeat && !mouseArea.pressed)
+ mouseArea.keyPressed = true;
+ }
+
+ Keys.onReleased: {
+ if (event.key === Qt.Key_Space && !event.isAutoRepeat && mouseArea.keyPressed) {
+ mouseArea.keyPressed = false;
+ __cycleStatesHandler();
+ clicked();
+ }
+ }
+}
diff --git a/src/controls/ApplicationWindow.qml b/src/controls/ApplicationWindow.qml
new file mode 100644
index 00000000..6a33c26f
--- /dev/null
+++ b/src/controls/ApplicationWindow.qml
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Window 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+
+/*!
+ \qmltype ApplicationWindow
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup applicationwindow
+ \brief ApplicationWindow provides a top-level application window.
+
+ AppliactionWindow is a \l Window, but adds convenience
+ for positioning items such as \l MenuBar, \l ToolBar and \l StatusBar in a platform
+ independent manner.
+
+ \code
+ ApplicationWindow {
+ id: window
+ menuBar: MenuBar {
+ Menu { MenuItem {...} }
+ Menu { MenuItem {...} }
+ }
+
+ toolBar: ToolBar {
+ RowLayout {
+ anchors.fill: parent
+ ToolButton{}
+ }
+ }
+ }
+
+ TabFrame {
+ id: myContent
+ anchors.fill: parent
+ ...
+ }
+ }
+ \endcode
+*/
+
+Window {
+ id: root
+
+ width: 320
+ height: 240
+
+ /*!
+ \qmlproperty MenuBar ApplicationWindow::menuBar
+
+ This property holds the \l MenuBar
+
+ By default this value is not set.
+ */
+ property MenuBar menuBar: null
+
+ /*!
+ \qmlproperty Item ApplicationWindow::toolBar
+
+ This property holds the tool bar \l Item.
+
+ It can be set to any Item type but is generally used with \l ToolBar.
+
+ By default this value is not set. When you set the toolBar Item, it will
+ be anchored automatically into the AppliacationWindow.
+ */
+ property alias toolBar: toolBarArea.data
+
+ /*!
+ \qmlproperty Item ApplicationWindow::statusBar
+
+ This property holds the status bar \l Item.
+
+ It can be set to any Item type but is generally used with \l StatusBar.
+
+ By default this value is not set. When you set the toolBar Item, it will
+ be anchored automatically into the AppliacationWindow.
+ */
+ property alias statusBar: statusBarArea.data
+
+ /*! \internal */
+ default property alias data: contentArea.data
+ property alias backgroundColor: syspal.window
+
+ SystemPalette {id: syspal}
+
+ Rectangle {
+ id: backgroundItem
+ anchors.fill: parent
+ color: backgroundColor
+
+ Row {
+ id: toolBarArea
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ Item {
+ id: contentArea
+ anchors.top: toolBarArea.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: statusBarArea.top
+ }
+
+ Row {
+ id: statusBarArea
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ states: State {
+ name: "hasMenuBar"
+ when: menuBar && !menuBar.isNative
+
+ ParentChange {
+ target: menuBar
+ parent: backgroundItem
+ }
+
+ PropertyChanges {
+ target: menuBar
+ x: 0
+ y: 0
+ width: backgroundItem.width
+ }
+
+ AnchorChanges {
+ target: toolBarArea
+ anchors.top: menuBar.bottom
+ }
+ }
+ }
+}
diff --git a/src/controls/Button.qml b/src/controls/Button.qml
new file mode 100644
index 00000000..529d602a
--- /dev/null
+++ b/src/controls/Button.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype Button
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief A normal button
+
+ A normal command button. Similar to the QPushButton widget.
+
+ The push button is perhaps the most commonly used widget in any graphical user interface.
+ Push (click) a button to command the computer to perform some action, or to answer a question.
+ Typical buttons are OK, Apply, Cancel, Close, Yes, No and Help.
+
+ */
+BasicButton {
+ id: button
+
+ /*! This property holds whether the push button is the default button.
+ Default buttons decide what happens when the user presses enter in a dialog without giving a button explicit focus.
+ Note : This property is currently ignored by Dialog
+ */
+ property bool defaultbutton: false
+
+ /*! This property holds the text shown on the button.
+ If the button has no text, the \l text property will be an empty string. */
+ property string text
+
+ /*! This property holds the icon shown on the button.
+ If the button has no icon, the \l iconSource property will be an empty string. */
+ property url iconSource
+
+ Accessible.name: text
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/ButtonStyle.qml", button)
+}
diff --git a/src/controls/CheckBox.qml b/src/controls/CheckBox.qml
new file mode 100644
index 00000000..574f35e5
--- /dev/null
+++ b/src/controls/CheckBox.qml
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import "Styles/Settings.js" as Settings
+import QtQuick.Controls.Private 1.0
+
+/*!
+ \qmltype CheckBox
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief A checkbox with a text label
+
+ A CheckBox is an option button that can be toggled on (checked) or off
+ (unchecked). Checkboxes are typically used to represent features in an
+ application that can be enabled or disabled without affecting others.
+
+ The state of the checkbox can be set with the \l checked property.
+
+ In addition to the checked and unchecked states, there is a third state:
+ partially checked. This state indicates that the
+ regular checked/unchecked state can not be determined; generally because of
+ other states that affect the checkbox. This state is useful when several
+ child nodes are selected in a treeview, for example.
+
+ The partially checked state can be made available to the user by setting
+ \l partiallyCheckedEnabled to \c true, or set directly by setting
+ \l checkedState to \c Qt.PartiallyChecked. \l checkedState behaves
+ identically to \l checked when \l partiallyCheckedEnabled is \c false;
+ setting one will appropriately set the other.
+
+ The text of the label shown next to the checkbox can be set with the \l text
+ property.
+
+ Whenever a CheckBox is clicked, it emits the clicked() signal.
+*/
+
+AbstractCheckable {
+ id: checkBox
+
+ /*!
+ This property indicates the current checked state of the checkbox.
+
+ Possible values:
+ \c Qt.UnChecked - The checkbox is not checked (default).
+ \c Qt.Checked - The checkbox is checked.
+ \c Qt.PartiallyChecked - The checkbox is in a partially checked (or
+ "mixed") state.
+ */
+ property int checkedState: checked ? Qt.Checked : Qt.Unchecked
+
+ /*!
+ This property determines whether the \c Qt.PartiallyChecked state is
+ available.
+
+ A checkbox may be in a partially checked state when the regular checked
+ state can not be determined.
+
+ Setting \l checkedState to \c Qt.PartiallyChecked will implicitly set
+ this property to \c true.
+
+ By default, this property is \c false.
+ */
+ property bool partiallyCheckedEnabled: false
+
+ /*!
+ True if onCheckedChanged should be ignored because we were reacting
+ to onCheckedStateChanged.
+ */
+ property bool ignoreChecked: false
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/CheckBoxStyle.qml", checkBox)
+
+ Accessible.role: Accessible.CheckBox
+ Accessible.name: text
+
+ __cycleStatesHandler: cycleCheckBoxStates
+
+ /*! \internal */
+ onCheckedChanged: {
+ if (!ignoreChecked)
+ checkedState = checked ? Qt.Checked : Qt.Unchecked;
+ }
+
+ /*! \internal */
+ onCheckedStateChanged: {
+ ignoreChecked = true;
+ if (checkedState === Qt.PartiallyChecked) {
+ partiallyCheckedEnabled = true;
+ checked = false;
+ } else {
+ checked = checkedState === Qt.Checked;
+ }
+ ignoreChecked = false;
+ }
+
+ /*! \internal */
+ function cycleCheckBoxStates() {
+ if (!partiallyCheckedEnabled) {
+ checked = !checked;
+ } else {
+ switch (checkedState) {
+ case Qt.Unchecked: checkedState = Qt.Checked; break;
+ case Qt.Checked: checkedState = Qt.PartiallyChecked; break;
+ case Qt.PartiallyChecked: checkedState = Qt.Unchecked; break;
+ }
+ }
+ }
+}
diff --git a/src/controls/ComboBox.qml b/src/controls/ComboBox.qml
new file mode 100644
index 00000000..5458807b
--- /dev/null
+++ b/src/controls/ComboBox.qml
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype ComboBox
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief ComboBox is a combined button and popup list. The popup menu itself is platform
+ native, and cannot by styled from QML code.
+
+ Add menu items to the comboBox by either adding MenuItem children inside the popup, or
+ assign it a ListModel (or both).
+
+ The ComboBox contains the following API (in addition to the BasicButton API):
+
+ ListModel model - this model will be used, in addition to MenuItem children, to
+ create items inside the popup menu
+ bool popupOpen - setting this property to 'true' will open the popup.
+ int selectedIndex - the index of the selected item in the popup menu.
+ string selectedText - the text of the selected menu item.
+
+ Example 1:
+
+ \qml
+ ComboBox {
+ model: ListModel {
+ id: menuItems
+ ListElement { text: "Banana"; color: "Yellow" }
+ ListElement { text: "Apple"; color: "Green" }
+ ListElement { text: "Coconut"; color: "Brown" }
+ }
+ width: 200
+ onSelectedIndexChanged: console.debug(selectedText + ", " + menuItems.get(selectedIndex).color)
+ }
+ \endqml
+
+ Example 2:
+
+ \qml
+ ComboBox {
+ width: 200
+ MenuItem {
+ text: "Pineapple"
+ onSelected: console.debug(text)
+
+ }
+ MenuItem {
+ text: "Grape"
+ onSelected: console.debug(text)
+ }
+ }
+ \endqml
+*/
+
+Control {
+ id: comboBox
+
+ default property alias menuItems: popup.menuItems
+ property alias model: popup.model
+ property alias textRole: popup.textRole
+ property bool popupOpen: false
+
+ property alias selectedIndex: popup.selectedIndex
+ readonly property alias selectedText: popup.selectedText
+
+ readonly property bool pressed: mouseArea.pressed || popup.popupVisible
+ property alias containsMouse: mouseArea.containsMouse
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/ComboBoxStyle.qml", comboBox)
+
+ Accessible.role: Accessible.ComboBox
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onPressedChanged: if (pressed) popup.show()
+ }
+
+ ExclusiveGroup { id: eg }
+
+ StyleItem { id: styleItem }
+ Component.onCompleted: {
+ if (selectedIndex === -1)
+ selectedIndex = 0
+ if (styleItem.style == "mac") {
+ popup.x -= 10
+ popup.y += 4
+ popup.font.pointSize = 13
+ }
+ }
+
+ ContextMenu {
+ id: popup
+
+ style: __style.popupStyle
+
+ // 'centerSelectedText' means that the menu will be positioned
+ // so that the selected text' top left corner will be at x, y.
+ property bool centerSelectedText: true
+
+ property int x: 0
+ property int y: centerSelectedText ? 0 : comboBox.height
+ minimumWidth: comboBox.width
+
+ function finalizeItem(item) {
+ item.action.checkable = true
+ item.action.exclusiveGroup = eg
+ }
+
+ function show() {
+ comboBox.popupOpen = true
+ menuItems[comboBox.selectedIndex].checked = true
+ currentIndex = comboBox.selectedIndex
+ showPopup(x, y, centerSelectedText ? comboBox.selectedIndex : 0, comboBox)
+ }
+
+ onMenuClosed: popupOpen = false
+ }
+
+ // The key bindings below will only be in use when popup is
+ // not visible. Otherwise, native popup key handling will take place:
+ Keys.onSpacePressed: {
+ if (!popupOpen)
+ popup.show()
+ else
+ popupOpen = false
+ }
+ Keys.onUpPressed: { if (selectedIndex > 0) selectedIndex-- }
+ Keys.onDownPressed: { if (selectedIndex < model.count - 1) selectedIndex++ }
+}
diff --git a/src/controls/ContextMenu.qml b/src/controls/ContextMenu.qml
new file mode 100644
index 00000000..42c2adcb
--- /dev/null
+++ b/src/controls/ContextMenu.qml
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+
+Menu {
+ id: root
+ property string selectedText: menuItems[selectedIndex] ? menuItems[selectedIndex].text : ""
+ property string textRole
+
+ onModelChanged: if (Component.status === Component.Ready && model !== undefined) rebuildMenu()
+
+ Component.onCompleted: if (model !== undefined) rebuildMenu()
+
+ onSelectedIndexChanged: {
+ if (0 <= selectedIndex && selectedIndex < menuItems.length)
+ menuItems[selectedIndex].triggered()
+ }
+
+ function rebuildMenu()
+ {
+ clearMenuItems();
+
+ var nativeModel = root.hasNativeModel()
+
+ if (model !== undefined) {
+ var modelCount = nativeModel ? root.modelCount() : model.count;
+ for (var j = 0 ; j < modelCount; ++j) {
+ var textValue
+ if (nativeModel) {
+ textValue = root.modelTextAt(j);
+ } else {
+ if (textRole !== "")
+ textValue = model.get(j)[textRole]
+ else if (model.count > 0 && root.model.get && root.model.get(0)) {
+ // ListModel with one role
+ var listElement = root.model.get(0)
+ var oneRole = true
+ var roleName = ""
+ var roleCount = 0
+ for (var role in listElement) {
+ if (!roleName || role === "text")
+ roleName = role
+ ++roleCount
+ }
+ if (roleCount > 1 && roleName !== "text") {
+ oneRole = false
+ console.log("Warning: No textRole set for ComboBox.")
+ break
+ }
+
+ if (oneRole) {
+ root.textRole = roleName
+ textValue = root.model.get(j)[textRole]
+ }
+ }
+ }
+
+ var item = addMenuItem(textValue)
+ if (root["finalizeItem"])
+ finalizeItem(item)
+ }
+ }
+
+ menuItemsChanged()
+ }
+}
diff --git a/src/controls/GroupBox.qml b/src/controls/GroupBox.qml
new file mode 100644
index 00000000..2e5b35d6
--- /dev/null
+++ b/src/controls/GroupBox.qml
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype GroupBox
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief GroupBox provides a group box frame with a title
+
+ A group box provides a frame, a title on top and displays various other controls inside itself. Group boxes can also be checkable.
+
+ Child controls in checkable group boxes are enabled or disabled depending on whether or not the group box is checked.
+
+ You can minimize the space consumption of a group box by enabling the flat property.
+ In most styles, enabling this property results in the removal of the left, right and bottom edges of the frame.
+
+ GroupBox doesn't automatically lay out the child controls (which are often \l{CheckBox}{CheckBoxes} or \l{RadioButton}{RadioButtons} but can be any controls).
+ The following example shows how we can set up a GroupBox with a column:
+
+ \qml
+ GroupBox {
+ title: "Package selection"
+ adjustToContentSize: true
+ Column {
+ CheckBox {
+ text: "Update system"
+ }
+ CheckBox {
+ text: "Update applications"
+ }
+ CheckBox {
+ text: "Update documentation"
+ }
+ }
+ }
+ \endqml
+*/
+
+Item {
+ id: groupbox
+
+ /*!
+ This property holds the group box title text.
+
+ There is no default title text.
+ */
+ property string title
+
+ /*!
+ This property holds whether the group box is painted flat or has a frame.
+
+ A group box usually consists of a surrounding frame with a title at the top.
+ If this property is enabled, only the top part of the frame is drawn in most styles;
+ otherwise, the whole frame is drawn.
+
+ By default, this property is disabled, i.e., group boxes are not flat unless explicitly specified.
+
+ \note In some styles, flat and non-flat group boxes have similar representations and may not be as
+ distinguishable as they are in other styles.
+ */
+ property bool flat: false
+
+ /*!
+ This property holds whether the group box has a checkbox in its title.
+
+ If this property is true, the group box displays its title using a checkbox in place of an ordinary label.
+ If the checkbox is checked, the group box's children are enabled; otherwise, they are disabled and inaccessible.
+
+ By default, group boxes are not checkable.
+ */
+ property bool checkable: false
+
+ /*!
+ \qmlproperty bool GroupBox::checked
+
+ This property holds whether the group box is checked.
+
+ If the group box is checkable, it is displayed with a check box. If the check box is checked, the group
+ box's children are enabled; otherwise, the children are disabled and are inaccessible to the user.
+
+ By default, checkable group boxes are also checked.
+ */
+ property alias checked: check.checked
+
+ /*!
+ This property holds the width of the content.
+ */
+ readonly property real contentWidth: content.childrenRect.width
+
+ /*!
+ This property holds the height of the content.
+ */
+ readonly property real contentHeight: content.childrenRect.height
+
+ /*!
+ This property holds whether the group box resizes itself to fit the contents.
+
+ By default, group boxes do not resize itself to fit the contents.
+
+ \note When adjustToContentSize is enabled, children cannot be anchored.
+ */
+ property bool adjustToContentSize: false
+
+ /*! \internal */
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/GroupBoxStyle.qml", groupbox)
+
+ /*! \internal */
+ default property alias data: content.data
+
+ /*! \internal */
+ property alias __checkbox: check
+
+ implicitWidth: Math.max(200, contentWidth + (loader.item ? loader.item.implicitWidth: 0) )
+ implicitHeight: contentHeight + (loader.item ? loader.item.implicitHeight : 0) + 4
+
+ Accessible.role: Accessible.Grouping
+ Accessible.name: title
+
+ Loader {
+ id: loader
+ property alias control: groupbox
+ anchors.fill: parent
+ property int topMargin: title.length > 0 || checkable ? 22 : 4
+ property int bottomMargin: 4
+ property int leftMargin: 4
+ property int rightMargin: 4
+ sourceComponent: style
+ onLoaded: item.z = -1
+ }
+
+ CheckBox {
+ id: check
+ checked: true
+ visible: checkable
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: loader.topMargin
+ }
+
+ Item {
+ id:content
+ z: 1
+ focus: true
+ anchors.topMargin: loader.topMargin
+ anchors.leftMargin: 8
+ anchors.rightMargin: 8
+ anchors.bottomMargin: 8
+ anchors.fill: parent
+ enabled: (!checkable || checkbox.checked)
+ }
+}
diff --git a/src/controls/Label.qml b/src/controls/Label.qml
new file mode 100644
index 00000000..0dd5dec2
--- /dev/null
+++ b/src/controls/Label.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+
+/*!
+ \qmltype Label
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief Label is a text display.
+
+ In addition to the normal \l Text element, Label follows the font and
+ color scheme of the system.
+ Use the \c text property to assign a text to the label. For other properties
+ check \l Text.
+
+ A simple label looks like this:
+ \qml
+ Label {
+ text: "Hello world"
+ }
+ \endqml
+
+ You can use the properties of \l Text to change the appearance
+ of the text as desired:
+ \qml
+ Label {
+ text: "Hello world"
+ font.pixelSize: 22
+ font.italic: true
+ color: "steelblue"
+ }
+ \endqml
+
+ \sa Text, TextField, TextEdit
+*/
+
+Text {
+ /*!
+ \qmlproperty string Label::text
+
+ The text to display. Use this property to get and set it.
+ */
+
+ id: label
+ font.pixelSize: 11
+ color: pal.text
+ SystemPalette {id:pal}
+}
diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
new file mode 100644
index 00000000..3176436f
--- /dev/null
+++ b/src/controls/Menu.qml
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Styles 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype Menu
+ \inqmlmodule QtQuick.Controls 1.0
+ \inherits MenuItem
+ \brief Menu provides a menu component for use in menu bars, context menus, and other popup menus.
+
+ \code
+ Menu {
+ text: "Edit"
+
+ MenuItem {
+ text: "Cut"
+ shortcut: "Ctrl+X"
+ onTriggered: ...
+ }
+
+ MenuItem {
+ text: "Copy"
+ shortcut: "Ctrl+C"
+ onTriggered: ...
+ }
+
+ MenuItem {
+ text: "Paste"
+ shortcut: "Ctrl+V"
+ onTriggered: ...
+ }
+
+ MenuSeparator { }
+
+ Menu {
+ text: "More Stuff"
+
+ MenuItem {
+ text: "Do Nothing"
+ }
+ }
+ }
+ \endcode
+
+ \sa MenuBar, MenuItem, MenuSeparator
+*/
+MenuPrivate {
+ id: root
+
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/MenuStyle.qml", root)
+
+ //! internal
+ property var menuBar: null
+ //! internal
+ property int currentIndex: -1
+
+ //! internal
+ menuContentItem: Loader {
+ sourceComponent: menuComponent
+ active: !root.isNative && root.popupVisible
+ focus: true
+ }
+
+ //! internal
+ property Component menuComponent: Loader {
+ id: menuFrameLoader
+
+ property Style __style: styleLoader.item
+ property Component menuItemStyle: __style ? __style.menuItem : null
+
+ property var control: root
+ property alias contentWidth: column.width
+ property alias contentHeight: column.height
+
+ property int subMenuXPos: width + (item && item["subMenuOverlap"] || 0)
+
+ visible: status === Loader.Ready
+ sourceComponent: __style ? __style.frame : undefined
+
+ Loader {
+ id: styleLoader
+ active: !root.isNative
+ sourceComponent: root.style
+ onStatusChanged: {
+ if (status === Loader.Error)
+ console.error("Failed to load Style for", root)
+ }
+ }
+
+ focus: true
+ Keys.forwardTo: menuBar ? [menuBar] : []
+ Keys.onEscapePressed: root.dismissMenu()
+
+ Keys.onDownPressed: {
+ if (root.currentIndex < 0) {
+ root.currentIndex = 0
+ return
+ }
+
+ for (var i = root.currentIndex + 1;
+ i < root.menuItems.length && !canBeHovered(i); i++)
+ ;
+ }
+
+ Keys.onUpPressed: {
+ for (var i = root.currentIndex - 1;
+ i >= 0 && !canBeHovered(i); i--)
+ ;
+ }
+
+ function canBeHovered(index) {
+ var item = itemsRepeater.itemAt(index)
+ if (!item["isSeparator"] && item.enabled) {
+ root.currentIndex = index
+ return true
+ }
+ return false
+ }
+
+ Keys.onLeftPressed: {
+ if (root.parentMenu)
+ closeMenu()
+ }
+
+ Keys.onRightPressed: {
+ var item = itemsRepeater.itemAt(root.currentIndex)
+ if (item && item.hasSubmenu) {
+ item.menuItem.showPopup(menuFrameLoader.subMenuXPos, 0, -1, item)
+ item.menuItem.currentIndex = 0
+ }
+ }
+
+ Keys.onSpacePressed: menuFrameLoader.triggerAndDismiss()
+ Keys.onReturnPressed: menuFrameLoader.triggerAndDismiss()
+ Keys.onEnterPressed: menuFrameLoader.triggerAndDismiss()
+
+ function triggerAndDismiss() {
+ var item = itemsRepeater.itemAt(root.currentIndex)
+ if (item && !item.isSeparator) {
+ root.selectedIndex = root.currentIndex
+ item.menuItem.trigger()
+ root.dismissMenu()
+ }
+ }
+
+ Binding {
+ // Make sure the styled frame is in the background
+ target: menuFrameLoader.item
+ property: "z"
+ value: menuMouseArea.z - 1
+ }
+
+ MouseArea {
+ id: menuMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ onExited: root.currentIndex = -1 // TODO Test for any submenu open
+
+ // Each menu item has its own mouse area, and for events to be
+ // propagated to the menu mouse area, they need to be embedded.
+ Column {
+ id: column
+
+ Repeater {
+ id: itemsRepeater
+ model: root.menuItems
+
+ Loader {
+ id: menuItemLoader
+
+ property var menuItem: modelData
+ property int contentWidth: column.width
+ property int contentHeight: column.height
+ property bool isSeparator: menuItem ? !menuItem.hasOwnProperty("text") : false
+ property bool hasSubmenu: menuItem ? !!menuItem["menuItems"] : false
+ property bool selected: !isSeparator && root.currentIndex === index
+
+ sourceComponent: menuFrameLoader.menuItemStyle
+ enabled: !isSeparator && !!menuItem && menuItem.enabled
+
+ MouseArea {
+ id: itemMouseArea
+ width: menuFrameLoader.width
+ height: parent.height
+ y: menuItemLoader.item ? menuItemLoader.item.y : 0 // Adjust mouse area for style offset
+ hoverEnabled: true
+
+ onClicked: {
+ if (hasSubmenu)
+ menuItem.closeMenu()
+ menuFrameLoader.triggerAndDismiss()
+ }
+
+ onEntered: {
+ if (menuItemLoader.hasSubmenu && !menuItem.popupVisible)
+ openMenuTimer.start()
+ }
+
+ onExited: {
+ if (!pressed && menuItemLoader.hasSubmenu)
+ closeMenuTimer.start()
+ }
+
+ onPositionChanged: root.currentIndex = index
+
+ Connections {
+ target: menuMouseArea
+ onEntered: {
+ if (!itemMouseArea.containsMouse && menuItemLoader.hasSubmenu)
+ closeMenuTimer.start()
+ }
+ }
+ }
+
+ Timer {
+ id: openMenuTimer
+ interval: 50
+ onTriggered: {
+ if (itemMouseArea.containsMouse)
+ menuItem.showPopup(menuFrameLoader.subMenuXPos, 0, -1, menuItemLoader)
+ }
+ }
+
+ Timer {
+ id: closeMenuTimer
+ interval: 1
+ onTriggered: {
+ if (menuMouseArea.containsMouse && !itemMouseArea.pressed && !itemMouseArea.containsMouse)
+ menuItem.closeMenu()
+ }
+ }
+
+ Binding {
+ target: menuItem
+ property: "__visualItem"
+ value: menuItemLoader
+ }
+ }
+ }
+
+ onWidthChanged: {
+ for (var i = 0; i < children.length; i++) {
+ var item = children[i]["item"]
+ if (item)
+ item.implicitWidth = Math.max(root.minimumWidth, implicitWidth)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/controls/MenuBar.qml b/src/controls/MenuBar.qml
new file mode 100644
index 00000000..db1cb3f6
--- /dev/null
+++ b/src/controls/MenuBar.qml
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Styles 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype MenuBar
+ \inqmlmodule QtQuick.Controls 1.0
+ \inherits Item
+ \brief The MenuBar item provides a horizontal menu bar.
+
+ \code
+ MenuBar {
+ Menu {
+ text: "File"
+ MenuItem { text: "Open..." }
+ MenuItem { text: "Close" }
+ }
+
+ Menu {
+ text: "Edit"
+ MenuItem { text: "Cut" }
+ MenuItem { text: "Copy" }
+ MenuItem { text: "Paste" }
+ }
+ }
+ \endcode
+
+ \sa ApplicationWindow::menuBar
+*/
+
+MenuBarPrivate {
+ id: root
+
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/MenuBarStyle.qml", root)
+
+ height: !isNative ? topLoader.height : 0
+ data: [
+ Loader {
+ id: topLoader
+ sourceComponent: menuBarComponent
+ active: !root.isNative
+ focus: true
+ },
+
+ Component {
+ id: menuBarComponent
+
+ Loader {
+ id: menuBarLoader
+
+ property Style __style: styleLoader.item
+ property Component menuItemStyle: __style ? __style.menuItem : null
+
+ property var control: root
+ onStatusChanged: if (status === Loader.Error) console.error("Failed to load panel for", root)
+
+ visible: status === Loader.Ready
+ active: !root.isNative
+ sourceComponent: __style ? __style.frame : undefined
+
+ Loader {
+ id: styleLoader
+ sourceComponent: root.style
+ onStatusChanged: {
+ if (status === Loader.Error)
+ console.error("Failed to load Style for", root)
+ }
+ }
+
+ property int openedMenuIndex: -1
+ property bool preselectMenuItem: false
+ property alias contentHeight: row.height
+
+ Binding {
+ // Make sure the styled menu bar is in the background
+ target: menuBarLoader.item
+ property: "z"
+ value: menuMouseArea.z - 1
+ }
+
+ focus: openedMenuIndex !== -1
+
+ Keys.onLeftPressed: {
+ if (openedMenuIndex > 0) {
+ preselectMenuItem = true
+ openedMenuIndex--
+ }
+ }
+
+ Keys.onRightPressed: {
+ if (openedMenuIndex < root.menus.length - 1) {
+ preselectMenuItem = true
+ openedMenuIndex++
+ }
+ }
+
+ MouseArea {
+ id: menuMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ Row {
+ id: row
+
+ Repeater {
+ id: itemsRepeater
+ model: root.menus
+ Loader {
+ id: menuItemLoader
+
+ property var menuItem: root.isNative ? null : modelData
+ property bool selected: menuItem.popupVisible || itemMouseArea.pressed || menuBarLoader.openedMenuIndex === index
+
+ sourceComponent: menuBarLoader.menuItemStyle
+
+ MouseArea {
+ id: itemMouseArea
+ anchors.fill:parent
+ hoverEnabled: true
+
+ onClicked: {
+ menuBarLoader.preselectMenuItem = false
+ menuBarLoader.openedMenuIndex = index
+ }
+ onPositionChanged: {
+ if ((pressed || menuMouseArea.pressed || menuBarLoader.openedMenuIndex !== -1)
+ && menuBarLoader.openedMenuIndex !== index) {
+ menuBarLoader.openedMenuIndex = index
+ menuBarLoader.preselectMenuItem = false
+ }
+ }
+ }
+
+ Connections {
+ target: menuBarLoader
+ onOpenedMenuIndexChanged: {
+ if (menuBarLoader.openedMenuIndex === index) {
+ menuItem.showPopup(0, root.height, 0, menuItemLoader)
+ if (menuBarLoader.preselectMenuItem)
+ menuItem.currentIndex = 0
+ } else {
+ menuItem.closeMenu()
+ }
+ }
+ }
+
+ Connections {
+ target: menuItem
+ onMenuClosed: {
+ if (menuBarLoader.openedMenuIndex === index)
+ menuBarLoader.openedMenuIndex = -1
+ }
+ }
+
+ Binding {
+ target: menuItem
+ property: "menuBar"
+ value: menuBarLoader
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ]
+}
diff --git a/src/controls/Page.qml b/src/controls/Page.qml
new file mode 100644
index 00000000..c7d08c29
--- /dev/null
+++ b/src/controls/Page.qml
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+
+/*!
+ \qmltype Page
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup navigation
+ \brief A Page is an Item you can push on a PageStack
+
+ A \a Page is the main Item pushed onto a \l PageStack. It normally contains a discrete
+ set of information and interaction elements meant for the user to solve a specific task, and
+ contains properties to use when working with a PageStack.
+ See \l PageStack for more information.
+
+ \qml
+ \endqml
+*/
+
+Item {
+ id: root
+
+ /*! \readonly
+ The status of the page. It can have one of the following values:
+ \list
+ \li \c PageStatus.Inactive: the page is not visible
+ \li \c PageStatus.Activating: the page is transitioning into becoming an active page on the stack
+ \li \c PageStatus.Active: the page is on top of the stack
+ \li \c PageStatus.Deactivating: the page is transitioning into becoming inactive
+ \endlist */
+ readonly property alias status: root.__status
+ /*! \readonly
+ This property contains the PageStack the page is in. If the page is not inside
+ a PageStack, \a pageStack will be \c null. */
+ readonly property alias pageStack: root.__pageStack
+ /*! \readonly
+ This property contains the index of the page inside \l{pageStack}{PageStack}, so
+ that \l{PageStack::get()}{pageStack.get(index)} will
+ return the page itself. If \l{Page::pageStack}{pageStack} is \c null, \a index
+ will be \c -1. */
+ readonly property alias index: root.__index
+ /*! This property can be set to override the default animations used
+ during a page transition. To better understand how to use this
+ property, refer to the \l{PageStack#Transitions}{transition documentation} in PageStack.
+ \sa {PageStack::animations}{PageStack.animations} */
+ property PageTransition pageTransition
+
+ visible: false // PageStack will show/hide the page as needed
+ width: parent.width
+ height: parent.height
+
+ // ********** PRIVATE API **********
+
+ /*! \internal */
+ property int __status: PageStatus.Inactive
+ /*! \internal */
+ property PageStack __pageStack: null
+ /*! \internal */
+ property int __index: -1
+}
diff --git a/src/controls/PageAnimation.qml b/src/controls/PageAnimation.qml
new file mode 100644
index 00000000..ace0e2e4
--- /dev/null
+++ b/src/controls/PageAnimation.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+
+ParallelAnimation {
+ id: root
+ /*! The name of the animation that is running. Can be one of the following:
+ \list
+ \li 'PushAnimation'
+ \li 'PopAnimation'
+ \li 'ReplaceAnimation'
+ \endlist
+ */
+ property string name
+ /*! The page that is transitioning in. */
+ property Item enterPage
+ /*! The page that is transitioning out */
+ property Item exitPage
+ /*! Set to \c true if the animation is told to
+ fast-forward directly to its end-state */
+ property bool immediate
+}
diff --git a/src/controls/PageStack.qml b/src/controls/PageStack.qml
new file mode 100644
index 00000000..42483443
--- /dev/null
+++ b/src/controls/PageStack.qml
@@ -0,0 +1,991 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Private/PageStack.js" as JSArray
+
+/*!
+ \qmltype PageStack
+ \inherits Item
+ \inqmlmodule QtQuick.Controls 1.0
+
+ \brief The central component for building page-based applications
+
+ PageStack implements a stack-based navigation model for an application.
+ A stack-based navigation model means that "pages" (discrete views of information)
+ are pushed onto a stack as the user navigates
+ deeper into the application page hierarchy. Similarily, the user can return back to
+ previous pages at a later point, which from a stack point of view means popping pages from the
+ top of the stack and re-activating them (make them visible on screen).
+
+ Pages can - but do not have to - use \l{Page} as the root item.
+ \l{Page} defines a contract for how the page and the page stack works together.
+ Namely the page can be notified when it becomes active or inactive
+ through the \l{Page::status} {Page.status} property. Status will be
+ \c PageStatus.Activating when a
+ page is transitioning into being the current page on screen, and \c PageStatus.Active
+ once the transition stops. When it leaves the screen, it will be
+ \c PageStatus.Deactivating, and then \c PageStatus.Inactive. When the page is
+ inactive, it will be hidden.
+
+ \section1 Using PageStack in an Application
+ Using the PageStack in the application is typically a simple matter of adding
+ the PageStack as a child to e.g the applications top-level
+ \l{http://doc.qt.nokia.com/latest/qml-item.html} {Item}. The stack is usually
+ anchored to the edges of the window, except at the top or bottom where it might
+ be anchored to a status bar, or some other similar UI component.
+ The stack can then be used by invoking its navigation methods. The first page
+ to show in the PageStack is commonly loaded assigning it to \l initialPage.
+
+ \section1 Basic Navigation
+ There are three primary navigation operations in PageStack: push(), pop() and
+ replace (you replace by specifying argument \c replace to push()).
+ These correspond to classic stack operations where "push" adds a page to the
+ top of a stack, "pop" removes the top page from the stack, and "replace" is like a
+ pop followed by a push in that it replaces the topmost page on the stack with
+ a new page (but the applied transtition might be different). The topmost page
+ in the stack corresponds to the one that is \l{PageStack::currentPage} {current},
+ i.e. the one that is visible on
+ screen. That means that "push" is the logical equivalent of navigating forward or
+ deeper into the application, "pop" is the equivalent of navigation back and
+ "replace" is the equivalent of replacing the current page with a different page.
+
+ Sometimes it is necessary to go back more than a single step in the stack, e.g.
+ to return to a "main" page or some kind of section page in the application.
+ For this use case, pop() can be provided with a page to pop to. This is called
+ an "unwind" operation as the stack gets unwound to the specified page. If the
+ page is not found then the stack unwinds until there is only a single page in
+ the stack, which becomes the current page. To explicitly unwind to the bottom
+ of the stack it is recommended to use \l{pop()} {pop(null)}, though technically any
+ non-existent page will do.
+
+ Given the stack [A, B, C]:
+
+ \list
+ \li \l{push()}{push(D)} => [A, B, C, D] - "push" transition animation between C and D
+ \li pop() => [A, B] - "pop" transition animation between C and B
+ \li \l{push()}{push(D, replace)} => [A, B, D] - "replace" transition between C and D
+ \li \l{pop()}{pop(A)} => [A] - "pop" transition between C and A
+ \endlist
+
+ Note that when the stack is empty, a push() will not perform a
+ transition animation because there is nothing to transition from (which will
+ typically happend during application start-up). A pop() on a stack with
+ depth 1 or 0 is a no-operation. If removing all pages from the stack is
+ needed, a separate function clear() is available.
+
+ Calling push() returns the page that was pushed onto the stack.
+ Calling pop() returns the page that was popped off the stack. When pop() is
+ called in an unwind operation the top-most page (the first page that was
+ popped, which will also be the one transitioning out) is returned.
+
+ \section1 Deep Linking
+ Deep linking means launching an application into a particular state. For example
+ a Newspaper application could be launched into showing a particular article,
+ bypassing the front page (and possible a section page) that would normally have
+ to be navigated through to get to the article in question. In terms of page
+ stacks deep linking means the ability to modify the state of the stack so that
+ you e.g. push a set of pages to the top of the stack, or that you completely reset
+ the stack to a given state.
+
+ The API for deep linking in PageStack is the same as for basic navigation. If
+ you push an array instead of a single page then all the pages in that array will
+ be pushed onto the stack. The transition animation, however, will be conducted as
+ if only the last page in the array was pushed onto the stack. The normal semantics
+ of push() apply for deep linking, meaning that push() adds whatever you push onto
+ the stack. Note also that only the last item in the array will actually be loaded
+ (in case of a \l{http://doc.qt.nokia.com/latest/qml-url.html}{URL} or
+ \l{http://doc.qt.nokia.com/latest/qml-component.html}{Component}).
+ The rest will be lazy loaded as needed when entering
+ the screen upon subsequent calls to pop (or when requesting the page by using \a get).
+
+ This gives us the following result, given the stack [A, B, C]:
+
+ \list
+ \li \l{push()}{push([D, E, F])} => [A, B, C, D, E, F] - "push" transition animation between C and F
+ \li \l{push()}{push([D, E, F], replace)} => [A, B, D, E, F] - "replace" transition animation between C and F
+ \li clear(); \l{push()}{push([D, E, F])} => [D, E, F] - no transition animation (since the stack was empty)
+ \endlist
+
+ \section1 Pushing pages
+
+ A page you push onto the PageStack can be either a \l Page, a \l{http://doc.qt.nokia.com/latest/qml-url.html}{URL}, a
+ string with a URL, an \l{http://doc.qt.nokia.com/latest/qml-item.html}{Item}, or a
+ \l{http://doc.qt.nokia.com/latest/qml-component.html}{Component}. To push it, you assign it
+ to a property "page" inside a property list, and send it as argument to \l{PageStack::push}{push}:
+
+ \code
+ pageStack.push({page: yourPage})
+ \endcode
+
+ The list can contain several properties that controls how the page should be pushed:
+ \list
+ \li \c page: This property is required, and holds the page you want to push.
+ \li \c properties: You can set a property list of QML properties that should be assigned
+ to the page upon push. These properties will be copied into the page at the
+ time the page is loaded, or about to become the current page (normally upon push).
+ \li \c immediate: Set this property to \c true to skip transition effects. When pushing
+ an array, you only need to set this property on the first element to make the
+ whole operation immediate.
+ \li \c replace: Set this property to replace the current page on the stack. When pushing
+ an array, you only need to set this property on the first element to replace
+ as many elements on the stack as inside the array.
+ \li \c destroyOnPop: Set this property to be explicit to whether or not PageStack should
+ destroy the page when its popped off the stack. By default (if \a destroyOnPop is
+ not specified), PageStack will destroy pages pushed as components or URLs. Pages
+ not destroyed will be reparented back to the original parents they had before being
+ pushed onto the stack, and hidden. If you need to set this property, do it with
+ care, so that pages are not leaked.
+ \endlist
+
+ If the only argument needed is "page", you can also, as a short-hand
+ notation, do:
+
+ \code
+ pageStack.push(yourPage).
+ \endcode
+
+ You can push several pages in one go by using an array of property lists. This is
+ optimizing compared to pushing pages one by one, since PageStack then can load only the
+ last page in the list. The rest will be loaded as they are about to become
+ the current page (which happends when the stack is popped). The following example shows how
+ to push an array of pages:
+
+ \code
+ pageStack.push([{page: yourPage1}, {page: yourPage2}])
+ \endcode
+
+ If inline pages/items are pushed, the page gets re-parented into an internal
+ container in the PageStack. When the page is later popped off, it gets
+ re-parented back to its original owner. If, however, a page is pushed
+ as a component or a URL, the actual page will be created as a page from that component. This
+ happens automatically when the page is about to become the current page in the stack. Ownership
+ over the item will then normally be taken by the PageStack. It will as such automatically
+ destroy the page when it is later popped off. The component that declared the page, by
+ contrast, remains in the ownership of the application and is not destroyed by the page stack.
+ You can override this behavior if needed by explicitly setting "destroyOnPop" in the list
+ argument given to push.
+
+ If you specify the \c properties property to push, these properties will be copied into
+ the page at the time the page is loaded (in case of a component or URL), or instead when
+ its about to become the current page (in case of an inline item). This normally happends when
+ the page is pushed. The following example shows how this can be done:
+
+ \code
+ pageStack.push({page: examplePage, properties: {fgcolor: "red", bgcolor: "blue"}});
+ \endcode
+
+ Note that if a page is declared in an item that is destroyed - even if a component
+ was used - then that page also gets destroyed.
+ This follows normal Qt parent-child destruction rules but sometimes comes as a surprise
+ for developers. In practice this means that if you declare a page B as a child of
+ page A and then do a replace from page A to page B, then page B will be destroyed when
+ page A was destroyed (as it was popped off the stack) and the application will effectively
+ be switching to a page that has been destroyed.
+
+ \section1 Lifecycle
+ The page lifecycle goes from instantiation to inactive, activating, active, deactivating,
+ inactive, and when no longer needed, destruction.
+ It can move any number of times between inactive and active. When a page is activated,
+ it's visible on the screen and is considered to be the current item. A page
+ in a page stack that is not visible is not activated, even if the page is currently the
+ top-most page in the stack. When the stack becomes visible the page that is top-most gets
+ activated. Likewise if the page stack is then hidden the top-most page would be deactivated.
+ Popping the page off the top of the stack at this point would not result in further
+ deactivation since the page is not active.
+
+ There is a \l{Page::status}{status} property that tracks the lifecycle. The value of status is
+ an enumeration with values \c PageStatus.Inactive, \c PageStatus.Activating, \c PageStatus.Active
+ and \c PageStatus.Deactivating. Combined with the normal \c Component.onComplete and
+ \c Component.onDestruction signals the entire lifecycle is thus:
+
+ \list
+ \li Created: Component.onCompleted()
+ \li Activating: onStatusChanged (status is PageStatus.Activating)
+ \li Acivated: onStatusChanged (status is PageStatus.Active)
+ \li Deactivating: onStatusChanged (status is PageStatus.Deactivating)
+ \li Deactivated: onStatusChanged (status is PageStatus.Inactive)
+ \li Destruction: Component.onDestruction()
+ \endlist
+
+ \section1 Finding Pages
+ Sometimes it is necessary to search for a page, e.g. in order to unwind the stack to
+ a page to which the application does not have a reference. This is facilitated using a
+ function find() in the page stack. The find() function takes a callback function as its
+ only argument. The callback gets invoked for each page in the stack (starting at the top).
+ If the callback returns true then it signals that a match has been found and the find()
+ function returns that page. If the callback fails to return true (i.e. no match is found)
+ then find() returns \c null.
+
+ The code below searches for a page in the stack that has a name "foo" and then unwinds to
+ that page. Note that since find() returns null if no page is found and since pop unwinds to
+ the bottom of the stack if null is given as the target page, the code works well even in the
+ case that no matching page was found.
+
+ \code
+ pageStack.pop(pageStack.find(function(page) {
+ return page.name == "foo";
+ }));
+ \endcode
+
+ You can also get to a page in the page stack using get(index). You should use
+ this function if your page depends on another page in the stack, as the function will
+ ensure that the page at the given index gets loaded before it is returned.
+
+ \code
+ previousPage = pageStack.get(myPage.index - 1));
+ \endcode
+
+ \section1 Transitions
+
+ A transition is performed whenever a page is pushed or popped, and consists of
+ two pages: enterPage and exitPage. The pagestack itself will never move pages
+ around, but instead delegate the job to an external animation set by the style
+ or the application developer. How pages should visually enter and leave the stack
+ is therefore completely controlled from the outside.
+
+ When the transition starts, the pagestack will search for an animation that
+ matches the operation executed. There are three animations to choose
+ from: pushAnimation, popAnimation, and replaceAnimation. Each implements how
+ enterPage should animate in, and exitPage out. The animations are
+ collected inside a PageTransition object assigned to
+ \l {PageStack::pageTransition}{pageTransition}. By default, popAnimation and
+ replaceAnimation will be the same as PushAnimation, unless you set them
+ to something else.
+
+ A simple fade transition could be implemented as:
+
+ \qml
+ PageStack {
+ pageTransition: PageTransition {
+ function cleanupAnimation(properties)
+ {
+ properties.exitPage.opacity = 1
+ }
+
+ property Component pushAnimation: PageAnimation {
+ PropertyAnimation {
+ target: enterPage
+ property: "opacity"
+ from: 0
+ to: 1
+ }
+ PropertyAnimation {
+ target: exitPage
+ property: "opacity"
+ from: 1
+ to: 0
+ }
+ }
+ }
+ }
+ \endqml
+
+ PushAnimation needs to inherit from PageAnimation, which is a ParallelAnimation that
+ contains the properties \c enterPage and \c exitPage. You set the target of your
+ inner animations to those pages. Since the same page instance can be pushed several
+ times to a pagestack, and since pages also can override transitions, your PageTransition
+ always need to override
+ \l {PageTransition::cleanupAnimation(properties)}{PageTransition.cleanupAnimation(properties)}.
+ Implement this function to reset any properties animated on the exitPage so that later
+ transitions can expect the pages to be in a default state.
+
+ A more complex example could look like the following. Here, the pages slides in lying on the side before
+ they are rotated up in an upright position:
+
+ \qml
+ PageStack {
+ pageTransition: PageTransition {
+ function cleanupAnimation(properties)
+ {
+ properties.exitPage.x = 0
+ properties.exitPage.rotation = 0
+ }
+
+ property Component pushAnimation: PageAnimation {
+ SequentialAnimation {
+ ScriptAction {
+ script: enterPage.rotation = 90
+ }
+ PropertyAnimation {
+ target: enterPage
+ property: "x"
+ from: enterPage.width
+ to: 0
+ }
+ PropertyAnimation {
+ target: enterPage
+ property: "rotation"
+ from: 90
+ to: 0
+ }
+ }
+ PropertyAnimation {
+ target: exitPage
+ property: "x"
+ from: 0
+ to: -exitPage.width
+ }
+ }
+ }
+ }
+ \endqml
+
+ A single Page can also override the transition to use when itself is pushed or popped. This can
+ be done by just assigning another PageTransition object to \l{Page::pageTransition}{Page.pageTransition}.
+
+ \section2 Advanced usage
+
+ After PageStack finds the correct transition to use (it first checks
+ \l{Page::pageTransition}{Page.pageTransition}, then \l {PageStack::pageTransition}{pageTransition})
+ it calls \l {PageTransition::getAnimation(properties)}{PageTransition.getAnimation(properties)}.
+ The base implementation of this function just looks for a property named \c properties.name inside
+ itself (root), which is how it finds \c {property Component pushAnimation} in the examples above.
+
+ \code
+ function getAnimation(properties)
+ {
+ return root[properties.name]
+ }
+ \endcode
+
+ You can override this function for your transition if you need extra logic to decide which
+ animation to run. You could for example introspect the pages, and return different animations
+ depending on the their internal state. PageStack will expect you to return a Component that
+ contains a PageAnimation, or a PageAnimation directly. The former is easier, as PageStack will
+ then create the animation and later destroy it when it's done, while avoiding any sideeffects
+ caused by the animation being alive long after it ran. Returning a PageAnimation directly
+ can be useful if you need to write some sort of animation caching for performance reasons.
+ As an optimization, you can also return \c null to signal that you just want to show/hide the pages
+ immediately without creating or running any animations.
+
+ \c properties contains the same properties that will be assigned to the PageAnimation object by
+ PageStack. In fact, you can add more properties to this object during the call
+ if you need to initialize additional properties of your custom PageAnimation when the returned
+ component is instanciated.
+
+ The following example shows how you can decide run-time which animation to use:
+
+ \qml
+ PageTransition {
+ function getAnimation(properties)
+ {
+ return (properties.enterPage.index % 2) ? horizontalAnimation : verticalAnimation
+ }
+
+ function cleanupAnimation(properties)
+ {
+ properties.exitPage.x = 0
+ properties.exitPage.y = 0
+ }
+
+ property Component horizontalAnimation: PageAnimation {
+ PropertyAnimation {
+ target: enterPage
+ property: "x"
+ from: target.width
+ to: 0
+ duration: 300
+ }
+ PropertyAnimation {
+ target: exitPage
+ property: "x"
+ from: 0
+ to: target.width
+ duration: 300
+ }
+ }
+
+ property Component verticalAnimation: PageAnimation {
+ PropertyAnimation {
+ target: enterPage
+ property: "y"
+ from: target.height
+ to: 0
+ duration: 300
+ }
+ PropertyAnimation {
+ target: exitPage
+ property: "y"
+ from: 0
+ to: target.height
+ duration: 300
+ }
+ }
+ }
+ \endqml
+*/
+
+Item {
+ id: root
+
+ /*! \qmlproperty int QtQuickComponents.Mt1.0::PageStack::depth
+ \readonly
+ The number of pages currently pushed onto the stack.
+ */
+ readonly property alias depth: root.__depth
+
+ /*! \qmlproperty Item QtQuickComponents.Mt1.0::PageStack::currentPage
+ \readonly
+ The currently top-most page in the stack.
+ */
+ readonly property alias currentPage: root.__currentPage
+
+ /*! The first \l Page that should be shown when the PageStack is created.
+ \a initialPage can take same value as the first argument to \l{PageStack::push()}
+ {PageStack.push()}. Note that this is just a convenience for writing
+ \c{Component.onCompleted: pageStack.push(myInitialPage)}
+
+ Examples:
+
+ \list
+ \li initialPage: Qt.resolvedUrl("MyPage.qml")
+ \li initialPage: myItem
+ \li initialPage: {"page" : Qt.resolvedUrl("MyPage.qml"), "properties" : {"color" : "red"}}
+ \endlist
+ \sa push
+ */
+ property variant initialPage: null
+
+ /*! \readonly
+ \a busy is \c true if a page transition is running, and \c false otherwise. */
+ readonly property bool busy: __currentTransition !== null
+
+ /*! The animations to use for page transitions.
+ For better understanding on how to apply custom page transitions, read \l{Transitions}.
+ \sa {Page::animations}{Page.transitions} */
+ property PageTransition pageTransition: PageSlideTransition {}
+
+ /*! Pushes a page onto the stack. The function takes a property list as argument, which
+ should contain one or more of the following properties:
+ \list
+ \li \c page: This property is required, and holds the page you want to push.
+ It can be a \l Page, a \l{http://doc.qt.nokia.com/latest/qml-url.html}{URL}, a string with a
+ URL, an \l{http://doc.qt.nokia.com/latest/qml-item.html}{Item}, a
+ \l{http://doc.qt.nokia.com/latest/qml-component.html}{Component}.
+ \li \c properties: You can set a property list of QML properties that should be assigned
+ to the page upon push. These properties will be copied into the page at the
+ time the page is loaded (in case of a component or URL), or else the first time it
+ becomes the current page (normally upon push).
+ \li \c immediate: Set this property to \c true to skip transition effects. When pushing
+ an array, you only need to set this property on the first element to make the
+ whole operation immediate.
+ \li \c replace: Set this property to replace the current page on the stack. When pushing
+ an array, you only need to set this property on the first element to replace
+ as many elements on the stack as inside the array.
+ \li \c destroyOnPop: Set this property to be explicit to whether or not PageStack should
+ destroy the page when its popped off the stack. By default (if \a destroyOnPop is
+ not specified), PageStack will destroy pages pushed as components or URLs. Pages
+ not destroyed will be reparented back to the original parents they had before being
+ pushed onto the stack, and hidden. If you need to set this property, do it with
+ care, so that pages are not leaked.
+ \endlist
+
+ You can also push an array of pages (property lists) if you need to push several pages
+ in one go. A transition will then only occur between the current page and the last
+ page in the list. The other pages will be deferred loaded until needed.
+
+ Examples:
+ \list
+ \li pageStack.push({page:aPage})
+ \li pageStack.push({page:aURL, immediate: true, replace: true})
+ \li pageStack.push({page:aRectangle, properties:{color:"red"}})
+ \li pageStack.push({page:aComponent, properties:{color:"red"}})
+ \li pageStack.push({page:aComponent.createObject(), destroyOnPop:true})
+ \li pageStack.push([{page:aPage, immediate:true}, {page:aURL}])
+ \endlist
+
+ Note: If the only argument needed is "page", you can also, as a short-hand
+ notation, do: \c{pageStack.push(aPage)}.
+
+ Returns the page that became current.
+
+ \sa initialPage
+ \sa {Pushing pages}
+ */
+ function push(page) {
+ // Note: we support two different APIs in this function; The old meego API, and
+ // the new "property list" API. Hence the reason for hiding the fact that you
+ // can pass more arguments than shown in the signature:
+ if (__recursionGuard(true))
+ return
+ var properties = arguments[1]
+ var immediate = arguments[2]
+ var replace = arguments[3]
+ var arrayPushed = (page instanceof Array)
+ var firstPage = arrayPushed ? page[0] : page
+ immediate = (immediate || JSArray.pageStack.length === 0)
+
+ if (firstPage && firstPage.page && firstPage.hasOwnProperty("x") === false) {
+ // Property list API used:
+ immediate = immediate || firstPage.immediate
+ replace = replace || firstPage.replace
+ }
+
+ // Create, and push, a new javascript object, called "element", onto the stack.
+ // This element contains all the information necessary to construct the page, and
+ // will, after loaded, also contain the loaded page:
+ if (arrayPushed) {
+ if (page.length === 0)
+ return
+ var outElement = replace ? JSArray.pop() : JSArray.current()
+ for (var i=0; i<page.length; ++i)
+ JSArray.push({"pageComponent" : page[i], loaded: false, index: __depth, properties: properties});
+ } else {
+ outElement = replace ? JSArray.pop() : JSArray.current()
+ JSArray.push({"pageComponent" : page, loaded: false, index: __depth, properties: properties})
+ }
+
+ var currentElement = JSArray.current()
+ var transition = {
+ inElement: currentElement,
+ outElement: outElement,
+ transitionElement: currentElement,
+ immediate: immediate,
+ replace: replace,
+ push: true
+ }
+ __performPageTransition(transition)
+ __recursionGuard(false)
+ return __currentPage
+ }
+
+ /*! Pops one or more pages off the stack. The function takes a property list as argument
+ which can contain one or more of the following properties:
+ \list
+ \li \c page: If specified, all pages down to (but not including) \a page will be
+ popped off. if \a page is \c null, all pages down to (but not including) the
+ first page will be popped. If not specified, only the current page will be
+ popped.
+ \li \c immediate: Set this property to \c true to skip transition effects.
+ \endlist
+
+ Examples:
+ \list
+ \li pageStack.pop()
+ \li pageStack.pop({page:somePage, immediate: true})
+ \li pageStack.pop({immediate: true})
+ \li pageStack.pop(null)
+ \endlist
+
+ Note: If the only argument needed is "page", you can also, as a short-hand
+ notation, do: \c{pageStack.pop(aPage)}.
+
+ Returns the page that was popped off
+ \sa clear()
+ */
+ function pop(page) {
+ if (__depth <= 1)
+ return null
+ if (page && page.hasOwnProperty("x") === false) {
+ // Property list API used:
+ var immediate = (page.immediate === true)
+ page = page.page
+ } else {
+ immediate = (arguments[1] === true)
+ }
+
+ if (page === __currentPage)
+ return
+
+ if (__recursionGuard(true))
+ return
+
+ var outElement = JSArray.pop()
+ var transitionElement = outElement
+ var inElement = JSArray.current()
+
+ if (__depth > 1 && page !== undefined && page !== inElement.page) {
+ // Pop from the top until we find 'page', and return the corresponding
+ // element. Skip all non-loaded pages (except the first), since no one
+ // has any references to such pages anyway:
+ while (__depth > 1 && !JSArray.current().loaded)
+ JSArray.pop()
+ inElement = JSArray.current()
+ while (__depth > 1 && page !== inElement.page) {
+ JSArray.pop()
+ __cleanup(inElement)
+ while (__depth > 1 && !JSArray.current().loaded)
+ JSArray.pop()
+ inElement = JSArray.current()
+ }
+ }
+
+ var transition = {
+ inElement: inElement,
+ outElement: outElement,
+ transitionElement: transitionElement,
+ immediate: immediate,
+ replace: false,
+ push: false
+ }
+ __performPageTransition(transition)
+ __recursionGuard(false)
+ return outElement.page;
+ }
+
+ /*! Remove all pages from the stack. No animations will be applied. */
+ function clear() {
+ if (__recursionGuard(true))
+ return
+ if (__currentTransition)
+ __currentTransition.animation.complete()
+ __currentPage = null
+ var count = __depth
+ for (var i=0; i<count; ++i) {
+ var element = JSArray.pop()
+ if (element.page)
+ __cleanup(element);
+ }
+ __recursionGuard(false)
+ }
+
+ /*! Search for a specific page inside the stack. \a func will
+ be called for each page in the stack (with the page as argument)
+ until the function returns true. Return value will be the page found. E.g:
+ find(function(page, index) { return page.isTheOne })
+ Set \a onlySearchLoadedPages to \c true to not load pages that are
+ not loaded into memory */
+ function find(func, onlySearchLoadedPages) {
+ for (var i=__depth-1; i>=0; --i) {
+ var element = JSArray.pageStack[i];
+ if (onlySearchLoadedPages !== true)
+ __loadElement(element)
+ else if (!element.page)
+ continue
+ if (func(element.page))
+ return element.page
+ }
+ return null;
+ }
+
+ /*! Returns the page at position \a index in
+ the page stack. If \a dontLoad is true, the
+ page will not be forced to load (and \c null
+ will be returned if not yet loaded) */
+ function get(index, dontLoad)
+ {
+ if (index < 0 || index >= JSArray.pageStack.length)
+ return null
+ var element = JSArray.pageStack[index]
+ if (dontLoad !== true) {
+ __loadElement(element)
+ return element.page
+ } else if (element.page) {
+ return element.page
+ } else {
+ return null
+ }
+ }
+
+ /*! Immediately completes any ongoing transition.
+ /sa Animation.complete
+ */
+ function completeTransition()
+ {
+ if (__recursionGuard(true))
+ return
+ if (__currentTransition)
+ __currentTransition.animation.complete()
+ __recursionGuard(false)
+ }
+
+ /********* DEPRECATED API *********/
+
+ /*! \internal
+ \deprecated Use Push() instead */
+ function replace(page, properties, immediate) {
+ push(page, properties, immediate, true)
+ }
+
+ /********* PRIVATE API *********/
+
+ width: parent ? parent.width : 0
+ height: parent ? parent.height : 0
+
+ /*! \internal The currently top-most page in the stack. */
+ property Item __currentPage: null
+ /*! \internal The number of pages currently pushed onto the stack. */
+ property int __depth: 0
+ /*! \internal Stores the transition info while a transition is ongoing */
+ property var __currentTransition: null
+ /*! \internal Stops the user from pushing pages while preparing a transition */
+ property bool __guard: false
+
+ /*! \internal */
+ Component.onCompleted: {
+ if (initialPage)
+ push(initialPage)
+ }
+
+ /*! \internal */
+ Component.onDestruction: {
+ if (__currentTransition)
+ __currentTransition.animation.complete()
+ __currentPage = null
+ }
+
+ /*! \internal */
+ function __recursionGuard(use)
+ {
+ if (use && __guard) {
+ console.warn("Warning: PageStack: You cannot push/pop recursively!")
+ console.trace()
+ return true
+ }
+ __guard = use
+ }
+
+ /*! \internal */
+ function __loadElement(element)
+ {
+ if (element.loaded) {
+ if (!element.page) {
+ element.page = invalidPageReplacement.createObject(root)
+ element.page.text = "\nError: The page has been deleted outside PageStack!"
+ }
+ return
+ }
+ if (!element.pageComponent) {
+ element.page = invalidPageReplacement.createObject(root)
+ element.page.text = "\nError: Invalid page (page was 'null'). "
+ + "This might indicate that the page was deleted outside PageStack!"
+ return
+ }
+
+ var comp = __resolvePageComponent(element.pageComponent, element)
+
+ // Assign properties to Page:
+ if (!element.properties)
+ element.properties = {}
+ element.properties.__index = element.index
+ element.properties.__pageStack = root
+
+ if (comp.hasOwnProperty("createObject")) {
+ if (comp.status === Component.Error) {
+ element.page = invalidPageReplacement.createObject(root)
+ element.page.text = "\nError: Could not load: " + comp.errorString()
+ } else {
+ element.page = comp.createObject(root, element.properties)
+ // Destroy pages we create unless the user specified something else:
+ if (!element.hasOwnProperty("destroyOnPop"))
+ element.destroyOnPop = true
+ }
+ } else {
+ // comp is already an Item, so just reparent it into the pagestack:
+ element.page = comp
+ element.originalParent = parent
+ element.page.parent = root
+ for (var prop in element.properties) {
+ if (element.page.hasOwnProperty(prop))
+ element.page[prop] = element.properties[prop];
+ }
+ // Do not destroy pages we didn't create, unless the user specified something else:
+ if (!element.hasOwnProperty("destroyOnPop"))
+ element.destroyOnPop = false
+ }
+
+ delete element.properties.__index
+ delete element.properties.__pageStack
+ element.loaded = true
+ }
+
+ /*! \internal */
+ function __resolvePageComponent(unknownObjectType, element)
+ {
+ // We need this extra resolve function since we dont really
+ // know what kind of object the user pushed. So we try to
+ // figure it out by inspecting the object:
+ if (unknownObjectType.hasOwnProperty("createObject")) {
+ return unknownObjectType
+ } else if (typeof unknownObjectType == "string") {
+ return Qt.createComponent(unknownObjectType)
+ } else if (unknownObjectType.hasOwnProperty("x")) {
+ return unknownObjectType
+ } else if (unknownObjectType.hasOwnProperty("page")) {
+ // INVARIANT: user pushed a JS-object
+ element.properties = unknownObjectType.properties
+ if (!unknownObjectType.page)
+ unknownObjectType.page = invalidPageReplacement
+ if (unknownObjectType.hasOwnProperty("destroyOnPop"))
+ element.destroyOnPop = unknownObjectType.destroyOnPop
+ return __resolvePageComponent(unknownObjectType.page, element)
+ } else {
+ // We cannot determine the type, so assume its a URL:
+ return Qt.createComponent(unknownObjectType)
+ }
+ }
+
+ /*! \internal */
+ function __cleanup(element) {
+ // INVARIANT: element has been removed from JSArray. Destroy its
+ // page, or reparent it back to the parent it had before it was pushed:
+ var page = element.page
+ if (element.destroyOnPop) {
+ page.destroy()
+ } else {
+ // Mark the page as no longer part of the PageStack. It
+ // might reenter on pop if pushed several times:
+ page.visible = false
+ __setPageStatus(page, PageStatus.Inactive)
+ if (page.hasOwnProperty("__pageStack"))
+ page.__pageStack = null
+ if (page.hasOwnProperty("__index"))
+ page.__index = -1
+ if (element.originalParent)
+ page.parent = element.originalParent
+ }
+ }
+
+ /*! \internal */
+ function __setPageStatus(page, status) {
+ if (page.hasOwnProperty("__status"))
+ page.__status = status
+ }
+
+ /*! \internal */
+ function __performPageTransition(transition)
+ {
+ // Animate page in "outElement" out, and page in "inElement" in. Set a guard to protect
+ // the user from pushing new pages on signals that will fire while preparing for the transition
+ // (e.g Page.onCompleted, Page.onStatusChanged, Page.onIndexChanged etc). Otherwise, we will enter
+ // this function several times, which causes the pages to be half-way updated.
+ if (__currentTransition)
+ __currentTransition.animation.complete()
+ __loadElement(transition.inElement)
+
+ transition.name = transition.replace ? "replaceAnimation" : (transition.push ? "pushAnimation" : "popAnimation")
+ var enterPage = transition.inElement.page
+ transition.enterPage = enterPage
+
+ // Since a page can be pushed several times, we need to update its properties:
+ enterPage.parent = root
+ if (enterPage.hasOwnProperty("__pageStack"))
+ enterPage.__pageStack = root
+ if (enterPage.hasOwnProperty("__index"))
+ enterPage.__index = transition.inElement.index
+ __currentPage = enterPage
+
+ if (!transition.outElement) {
+ // A transition consists of two pages, but we got just one. So just show the page:
+ enterPage.visible = true
+ __setPageStatus(enterPage, PageStatus.Activating)
+ __setPageStatus(enterPage, PageStatus.Active)
+ return
+ }
+
+ var exitPage = transition.outElement.page
+ transition.exitPage = exitPage
+ if (enterPage === exitPage)
+ return
+
+ __searchForAnimationIn(transition.transitionElement.page, transition)
+ if (!transition.animation)
+ __searchForAnimationIn(root, transition)
+ if (!transition.animation) {
+ console.warn("Warning: PageStack: no", transition.name, "found!")
+ return
+ }
+
+ if (enterPage.anchors.fill || exitPage.anchors.fill)
+ console.warn("Warning: PageStack: cannot transition a page that is anchored!")
+
+ __currentTransition = transition
+ __setPageStatus(exitPage, PageStatus.Deactivating)
+ enterPage.visible = true
+ __setPageStatus(enterPage, PageStatus.Activating)
+ transition.animation.runningChanged.connect(animationFinished)
+ transition.animation.start()
+ // NB! For empty animations, "animationFinished" is already
+ // executed at this point, leaving __animation === null:
+ if (transition.immediate === true && transition.animation)
+ transition.animation.complete()
+ }
+
+ /*! \internal */
+ function __searchForAnimationIn(obj, transition)
+ {
+ var t = obj.pageTransition
+ if (t) {
+ transition.pageTransition = t
+ transition.properties = {
+ "name":transition.name,
+ "enterPage":transition.enterPage,
+ "exitPage":transition.exitPage,
+ "immediate":transition.immediate }
+ var anim = t.getAnimation(transition.properties)
+ if (anim.createObject) {
+ anim = anim.createObject(null, transition.properties)
+ anim.runningChanged.connect(function(){ if (anim.running === false) anim.destroy() })
+ }
+ transition.animation = anim
+ }
+ }
+
+ /*! \internal */
+ function animationFinished()
+ {
+ if (!__currentTransition || __currentTransition.animation.running)
+ return
+
+ __currentTransition.animation.runningChanged.disconnect(animationFinished)
+ __currentTransition.exitPage.visible = false
+ __setPageStatus(__currentTransition.exitPage, PageStatus.Inactive);
+ __setPageStatus(__currentTransition.enterPage, PageStatus.Active);
+ __currentTransition.properties.animation = __currentTransition.animation
+ __currentTransition.pageTransition.cleanupAnimation(__currentTransition.properties)
+
+ if (!__currentTransition.push || __currentTransition.replace)
+ __cleanup(__currentTransition.outElement)
+
+ __currentTransition = null
+ }
+
+ /*! \internal */
+ property Component invalidPageReplacement: Component {
+ Text {
+ width: parent.width
+ height: parent.height
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ }
+ }
+}
diff --git a/src/controls/PageTransition.qml b/src/controls/PageTransition.qml
new file mode 100644
index 00000000..bd69dc5a
--- /dev/null
+++ b/src/controls/PageTransition.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+
+/*!
+ \qmltype PageTransition
+ \inqmlmodule QtQuick.Controls 1.0
+
+ \brief The component for managing page transitions
+
+ See the documentation for the \l {QtQuick.Controls1::PageStack} {PageStack}
+ component.
+
+*/
+QtObject {
+ id: root
+
+ function getAnimation(properties)
+ {
+ return root[properties.name]
+ }
+
+ function cleanupAnimation(properties)
+ {
+ console.warn("Warning: PageTransition: the current transition did not override "
+ + "cleanupAnimation(properties). This can cause the exit page to "
+ + "be left in a state that makes it unusable for further usage!")
+ }
+
+ property Component pushAnimation: PageAnimation {}
+ property Component popAnimation: root["pushAnimation"]
+ property Component replaceAnimation: root["pushAnimation"]
+}
diff --git a/src/controls/ProgressBar.qml b/src/controls/ProgressBar.qml
new file mode 100644
index 00000000..9d67b690
--- /dev/null
+++ b/src/controls/ProgressBar.qml
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype ProgressBar
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup indicators
+ \brief A progress bar
+
+ The ProgressBar is used to give an indication of the progress of an operation.
+ \l value is updated regularly and must be between \l minimumValue and \l maximumValue.
+
+*/
+
+Control {
+ id: progressbar
+
+ /*! This property holds the progress bar's current value.
+ Attempting to change the current value to one outside the minimum-maximum
+ range has no effect on the current value.
+ The default value is \c 0
+ */
+ property real value: 0
+
+ /*! This property is the progress bar's minimum value
+ The \l value is clamped to this value.
+ The default value is \c 0
+ */
+ property real minimumValue: 0
+
+ /*! This property is the progress bar's maximum value
+ The \l value is clamped to this value.
+ If maximumValue is smaller than \l minimumValue, \l minimumValue will be enforced.
+ The default value is \c 1
+ */
+ property real maximumValue: 1
+
+ /*! This property toggles indeterminate mode.
+ When the actual progress is unknown, use this option.
+ The progress bar will be animated as a busy indicator instead.
+ The default value is \c false
+ */
+ property bool indeterminate: false
+
+ /*! \qmlproperty enum orientation
+
+ This property holds the orientation of the progress bar.
+
+ \list
+ \li Qt.Horizontal - Horizontal orientation. (Default)
+ \li Qt.Vertical - Vertical orientation.
+ \endlist
+ */
+ property int orientation: Qt.Horizontal
+
+ /*! \internal */
+ style: Qt.createComponent(Settings.THEME_PATH + "/ProgressBarStyle.qml", progressbar)
+
+ /*! \internal */
+ onMaximumValueChanged: setValue(value)
+ /*! \internal */
+ onMinimumValueChanged: setValue(value)
+ /*! \internal */
+ Component.onCompleted: setValue(value)
+ /*! \internal */
+ onValueChanged: setValue(value)
+
+ Accessible.role: Accessible.ProgressBar
+ Accessible.name: value
+
+ implicitWidth: orientation === Qt.Horizontal ? 200 : (__panel ? __panel.implicitHeight : 0)
+ implicitHeight: orientation === Qt.Horizontal ? (__panel ? __panel.implicitHeight : 0) : 200
+
+ /* \internal */
+ function setValue(v) {
+ var newval = parseFloat(v)
+ if (!isNaN(newval)) {
+ // we give minimumValue priority over maximum if they are inconsistent
+ if (newval > maximumValue) {
+ if (maximumValue >= minimumValue)
+ newval = maximumValue;
+ else
+ newval = minimumValue
+ } else if (v < minimumValue) {
+ newval = minimumValue
+ }
+ value = newval
+ }
+ }
+}
diff --git a/src/controls/RadioButton.qml b/src/controls/RadioButton.qml
new file mode 100644
index 00000000..ce819164
--- /dev/null
+++ b/src/controls/RadioButton.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import "Styles/Settings.js" as Settings
+
+// jb : Size should not depend on background, we should make it consistent
+
+/*!
+ \qmltype RadioButton
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief A radio button with a text label
+
+ A RadioButton is an option button that can be switched on (checked) or off
+ (unchecked). Radio buttons typically present the user with a "one of many"
+ choice. In a group of radio buttons, only one radio button at a time can be
+ checked; if the user selects another button, the previously selected button
+ is switched off.
+*/
+
+AbstractCheckable {
+ id: radioButton
+
+ Accessible.role: Accessible.RadioButton
+
+ /*!
+ The style that should be applied to the radio button. Custom style
+ components can be created with:
+
+ \codeline Qt.createComponent("path/to/style.qml", radioButtonId);
+ */
+ style: Qt.createComponent(Settings.THEME_PATH + "/RadioButtonStyle.qml", radioButton)
+
+ __cycleStatesHandler: function() { checked = !checked; }
+}
diff --git a/src/controls/ScrollArea.qml b/src/controls/ScrollArea.qml
new file mode 100644
index 00000000..8a48303e
--- /dev/null
+++ b/src/controls/ScrollArea.qml
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+
+/*!
+ \qmltype ScrollArea
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup navigation
+ \brief The ScrollArea class provides a scrolling view onto another Item.
+
+ A ScrollArea can be used either instead of a \l Flickable or to decorate an
+ existing Flickable. Depending on the platform it will add scroll bars and
+ a content frame.
+
+ Only one Item can be a direct child of the ScrollArea and the child is implicitly anchored
+ to fill the scroll view.
+
+ Example:
+ \code
+ ScrollArea {
+ Image { imageSource: "largeImage.png" }
+ }
+ \endcode
+
+ In the previous example the Image item will implicitly get scroll behavior as if it was
+ used within a \l Flickable. The width and height of the child item will be used to
+ define the size of the content area.
+
+ Example:
+ \code
+ ScrollArea {
+ ListView {
+ ...
+ }
+ }
+ \endcode
+
+ In this case the content size of the ScrollArea will simply mirror that of its contained
+ \l flickableItem.
+
+*/
+
+FocusScope {
+ id: root
+ implicitWidth: 200
+ implicitHeight: 100
+
+ /*!
+ This property tells the scroll area if it should render
+ a frame around it's content.
+
+ The default value is \c false
+ */
+ property bool frame: false
+
+ /*!
+ This property controls if there should be a highlight
+ around the frame when the ScrollArea has input focus.
+
+ The default value is \c false
+
+ \note This property is only applicable on some platforms, such
+ as Mac OS.
+ */
+ property bool highlightOnFocus: false
+
+ /*!
+ \qmlproperty Item ScrollArea::viewport
+
+ The viewport determines the current "window" on to the contentItem.
+ In other words it clips it and the size of the viewport tells you
+ how much of the content area is visible.
+ */
+ property alias viewport: viewportItem
+
+ /*!
+ \qmlproperty Item ScrollArea::flickableItem
+
+ The flickableItem of the ScrollArea. If the contentItem provided
+ to the ScrollArea is a Flickable, it will be the \l contentItem.
+ */
+ readonly property alias flickableItem: internal.flickableItem
+
+ /*!
+ The contentItem of the ScrollArea. This is set by the user.
+
+ Note that the definition of contentItem is somewhat different to that
+ of a Flickable, where the contentItem is implicitly created.
+ */
+ default property Item contentItem
+
+ /*! \internal */
+ property Item __scroller: scroller
+ /*! \internal */
+ property int __scrollBarTopMargin: 0
+ /*! \internal */
+ property alias horizontalScrollBar: scroller.horizontalScrollBar
+ /*! \internal */
+ property alias verticalScrollBar: scroller.verticalScrollBar
+
+ /*! \internal */
+ onContentItemChanged: {
+
+ if (contentItem.hasOwnProperty("contentY") && // Check if flickable
+ contentItem.hasOwnProperty("contentHeight")) {
+ internal.flickableItem = contentItem // "Use content if it is a flickable
+ } else {
+ internal.flickableItem = flickableComponent.createObject(this)
+ contentItem.parent = flickableItem.contentItem
+ }
+ internal.flickableItem.parent = viewportItem
+ internal.flickableItem.anchors.fill = viewportItem
+ }
+
+
+ children: Item {
+ id: internal
+
+ property Flickable flickableItem
+
+ Binding {
+ target: flickableItem
+ property: "contentHeight"
+ when: contentItem !== flickableItem
+ value: contentItem ? contentItem.height : 0
+ }
+
+ Binding {
+ target: flickableItem
+ when: contentItem !== flickableItem
+ property: "contentWidth"
+ value: contentItem ? contentItem.width : 0
+ }
+
+ Connections {
+ target: flickableItem
+
+ onContentYChanged: {
+ scroller.blockUpdates = true
+ scroller.verticalScrollBar.value = flickableItem.contentY
+ scroller.blockUpdates = false
+ }
+
+ onContentXChanged: {
+ scroller.blockUpdates = true
+ scroller.horizontalScrollBar.value = flickableItem.contentX
+ scroller.blockUpdates = false
+ }
+
+ }
+
+ anchors.fill: parent
+
+ Component {
+ id: flickableComponent
+ Flickable {}
+ }
+
+ WheelArea {
+ id: wheelArea
+ parent: flickableItem
+
+ // ### Note this is needed due to broken mousewheel behavior in Flickable.
+
+ anchors.fill: parent
+
+ property int acceleration: 40
+ property int flickThreshold: 20
+ property double speedThreshold: 3
+ property double ignored: 0.001 // ## flick() does not work with 0 yVelocity
+ property int maxFlick: 400
+
+ property bool horizontalRecursionGuard: false
+ property bool verticalRecursionGuard: false
+
+ horizontalMaximumValue: flickableItem ? flickableItem.contentWidth - viewport.width : 0
+ verticalMaximumValue: flickableItem ? flickableItem.contentHeight - viewport.height : 0
+
+ Connections {
+ target: flickableItem
+ onContentYChanged: {
+ wheelArea.verticalRecursionGuard = true
+ wheelArea.verticalValue = flickableItem.contentY
+ wheelArea.verticalRecursionGuard = false
+ }
+ onContentXChanged: {
+ wheelArea.horizontalRecursionGuard = true
+ wheelArea.horizontalValue = flickableItem.contentX
+ wheelArea.horizontalRecursionGuard = false
+ }
+ }
+
+ onVerticalValueChanged: {
+ if (!verticalRecursionGuard) {
+ if (flickableItem.contentY < flickThreshold && verticalDelta > speedThreshold) {
+ flickableItem.flick(ignored, Math.min(maxFlick, acceleration * verticalDelta))
+ } else if (flickableItem.contentY > flickableItem.contentHeight
+ - flickThreshold - viewport.height && verticalDelta < -speedThreshold) {
+ flickableItem.flick(ignored, Math.max(-maxFlick, acceleration * verticalDelta))
+ } else {
+ flickableItem.contentY = verticalValue
+ }
+ }
+ }
+
+ onHorizontalValueChanged: {
+ if (!horizontalRecursionGuard)
+ flickableItem.contentX = horizontalValue
+ }
+ }
+
+ ScrollAreaHelper {
+ id: scroller
+ anchors.fill: parent
+ property int frameWidth: frame ? styleitem.pixelMetric("defaultframewidth") : 0
+ property bool outerFrame: !frame || !styleitem.styleHint("frameOnlyAroundContents")
+ property int scrollBarSpacing: outerFrame ? 0 : styleitem.pixelMetric("scrollbarspacing")
+ property int verticalScrollbarOffset: verticalScrollBar.visible && !verticalScrollBar.isTransient ?
+ verticalScrollBar.width + scrollBarSpacing : 0
+ property int horizontalScrollbarOffset: horizontalScrollBar.visible && !horizontalScrollBar.isTransient ?
+ horizontalScrollBar.height + scrollBarSpacing : 0
+
+ StyleItem {
+ id: styleitem
+ elementType: "frame"
+ sunken: true
+ visible: frame
+ anchors.fill: parent
+ anchors.rightMargin: scroller.outerFrame ? 0 : scroller.verticalScrollbarOffset
+ anchors.bottomMargin: scroller.outerFrame ? 0 : scroller.horizontalScrollbarOffset
+ }
+
+ Item {
+ id: viewportItem
+ anchors.fill: styleitem
+ anchors.margins: scroller.frameWidth
+ anchors.rightMargin: scroller.frameWidth + (scroller.outerFrame ? scroller.verticalScrollbarOffset : 0)
+ anchors.bottomMargin: scroller.frameWidth + (scroller.outerFrame ? scroller.horizontalScrollbarOffset : 0)
+ clip: true
+ }
+ }
+ FocusFrame { visible: highlightOnFocus && area.activeFocus }
+ }
+}
diff --git a/src/controls/Slider.qml b/src/controls/Slider.qml
new file mode 100644
index 00000000..9c274463
--- /dev/null
+++ b/src/controls/Slider.qml
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype Slider
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief Slider provides a vertical or horizontal slider control.
+
+ The slider is the classic control for providing a bounded value. It lets
+ the user move a slider handle along a horizontal or vertical groove
+ and translates the handle's position into a value within the legal range.
+
+ \code
+ Slider {
+ onValueChanged: print(value)
+ }
+ \endcode
+
+ The Slider value is by default in the range [0, 1]. If integer values are
+ needed, you can set the \l stepSize.
+*/
+
+Control {
+ id: slider
+
+ /*!
+ \qmlproperty enum Slider::orientation
+
+ This property holds the layout orientation of the slider.
+ The default value is \c Qt.Horizontal
+ */
+ property int orientation: Qt.Horizontal
+
+ /*!
+ \qmlproperty double Slider::minimumValue
+
+ This property holds the minimum value of the Slider
+ The default value is \c 0.0
+ */
+ property alias minimumValue: range.minimumValue
+
+ /*!
+ \qmlproperty double Slider::maximumValue
+
+ This property holds the maximum value of the Slider
+ The default value is \c 1.0
+ */
+ property alias maximumValue: range.maximumValue
+
+ /*! \internal */
+ property alias inverted: range.inverted
+
+
+ /*!
+ \qmlproperty bool Slider::updateValueWhileDragging
+
+ This property indicates if the current \l value should update while
+ the user is moving the slider handle or only when the button has been released.
+ The property can for instance be used if changing the slider value can be
+ time consuming.
+
+ The default value is \c true
+ */
+ property bool updateValueWhileDragging: true
+
+ /*!
+ \qmlproperty bool Slider::pressed
+
+ This property indicates if slider handle is currently being pressed
+ */
+ property alias pressed: mouseArea.pressed
+
+ /*!
+ \qmlproperty double Slider::stepSize
+
+ This property indicates the slider step size.
+
+ A value of 0 indicates that the value of the slider operates in a
+ continuous range between \l minimumValue and \l maximumValue.
+
+ Any non 0 value indicates a discrete stepSize. The following example
+ will generate a slider with integer values in the range [0-5]
+
+ \qml
+ Slider {
+ maximumValue: 5.0
+ stepSize: 1.0
+ }
+ \endqml
+
+ The default value is \c 0
+ */
+ property alias stepSize: range.stepSize
+
+ /*!
+ \qmlproperty double Slider::value
+
+ This property holds the current value of the Slider
+ The default value is \c 0.0
+ */
+ property alias value: range.value
+
+ /*! \internal */
+ property bool containsMouse: mouseArea.containsMouse
+
+ /*!
+ \qmlproperty bool Slider::activeFocusOnPress
+
+ This property indicates if the Slider should receive active focus when
+ pressed.
+ */
+ property bool activeFocusOnPress: false
+
+ /*!
+ \qmlproperty bool Slider::tickmarksEnabled
+
+ This property indicates if the Slider should display tickmarks
+ at step intervals.
+
+ The default value is \c false
+ */
+ property bool tickmarksEnabled: false
+
+ /*! \internal */
+ property string tickPosition: "Below" // "Above", "Below", "BothSides"
+
+ Accessible.role: Accessible.Slider
+ Accessible.name: value
+
+ /*!
+ \qmlmethod Slider::formatValue
+
+ This method returns the current slider value in a way that is more suitable
+ for user display, such as the \l value rounded to only two decimal places.
+
+ By default this function returns the nearest \c int value.
+ */
+
+ function formatValue(v) {
+ return Math.round(v);
+ }
+
+ /* \internal */
+ style: Qt.createComponent(Settings.THEME_PATH + "/SliderStyle.qml", slider)
+
+ Keys.onRightPressed: value += (maximumValue - minimumValue)/10.0
+ Keys.onLeftPressed: value -= (maximumValue - minimumValue)/10.0
+
+ RangeModel {
+ id: range
+ minimumValue: 0.0
+ maximumValue: 1.0
+ value: 0
+ stepSize: 0.0
+ inverted: false
+
+ positionAtMinimum: 0
+ positionAtMaximum: slider.width
+ }
+
+ Item { id: fakeHandle }
+
+ MouseArea {
+ id: mouseArea
+
+ hoverEnabled: true
+ anchors.centerIn: parent
+
+ width: parent.width
+ height: parent.height
+
+ drag.target: fakeHandle
+ drag.axis: Drag.XAxis
+ drag.minimumX: range.positionAtMinimum
+ drag.maximumX: range.positionAtMaximum
+
+ onPressed: {
+ if (activeFocusOnPress)
+ slider.focus = true;
+
+ // Clamp the value
+ var newX = Math.max(mouse.x, drag.minimumX);
+ newX = Math.min(newX, drag.maximumX);
+
+ // Debounce the press: a press event inside the handler will not
+ // change its position, the user needs to drag it.
+
+ // Note this really messes up things for scrollbar
+ // if (Math.abs(newX - fakeHandle.x) > handleLoader.width / 2)
+ range.position = newX;
+ }
+
+ onReleased: {
+ // If we don't update while dragging, this is the only
+ // moment that the range is updated.
+ if (!slider.updateValueWhileDragging)
+ range.position = fakeHandle.x;
+ }
+ }
+
+
+
+ // Range position normally follow fakeHandle, except when
+ // 'updateValueWhileDragging' is false. In this case it will only follow
+ // if the user is not pressing the handle.
+ Binding {
+ when: updateValueWhileDragging || !mouseArea.pressed
+ target: range
+ property: "position"
+ value: fakeHandle.x
+ }
+
+ // During the drag, we simply ignore position set from the range, this
+ // means that setting a value while dragging will not "interrupt" the
+ // dragging activity.
+ Binding {
+ when: !mouseArea.drag.active
+ target: fakeHandle
+ property: "x"
+ value: range.position
+ }
+
+
+ WheelArea {
+ id: wheelarea
+ anchors.fill: parent
+ horizontalMinimumValue: slider.minimumValue
+ horizontalMaximumValue: slider.maximumValue
+ verticalMinimumValue: slider.minimumValue
+ verticalMaximumValue: slider.maximumValue
+ property double step: (slider.maximumValue - slider.minimumValue)/100
+
+ onVerticalWheelMoved: {
+ value += verticalDelta/4*step
+ }
+
+ onHorizontalWheelMoved: {
+ value += horizontalDelta/4*step
+ }
+ }
+}
diff --git a/src/controls/SpinBox.qml b/src/controls/SpinBox.qml
new file mode 100644
index 00000000..25c70fc6
--- /dev/null
+++ b/src/controls/SpinBox.qml
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype SpinBox
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief SpinBox provides a spin box control.
+
+ SpinBox allows the user to choose a value by clicking the up/down buttons or pressing up/down on the keyboard to increase/decrease
+ the value currently displayed. The user can also type the value in manually.
+
+ By default the SpinBox provides discrete values in the range [0-99] with a \l stepSize of 1 and 0 \l decimals.
+
+ \code
+ SpinBox {
+ id: spinbox
+ }
+ \endcode
+
+ Note that if you require decimal values you will need to set the \l decimals to a non 0 value.
+
+ \code
+ SpinBox {
+ id: spinbox
+ decimals: 2
+ }
+ \endcode
+
+*/
+
+Control {
+ id: spinbox
+
+ /*!
+ The value of this SpinBox, clamped to \l minimumValue and \l maximumValue.
+
+ The default value is \c 0
+ */
+ property real value: 0
+
+ /*!
+ The minimum value of the SpinBox range.
+ The \l value is clamped to this value.
+
+ The default value is \c 0
+ */
+ property real minimumValue: 0
+
+ /*!
+ The maximum value of the SpinBox range.
+ The \l value is clamped to this value. If maximumValue is smaller than
+ \l minimumValue, \l minimumValue will be enforced.
+
+ The default value is \c 99
+ */
+ property real maximumValue: 99
+
+ /*!
+ The amount by which the \l value is incremented/decremented when a
+ spin button is pressed.
+
+ The default value is 1.0.
+ */
+ property real stepSize: 1.0
+
+ /*! The suffix for the value. I.e "cm" */
+ property string suffix
+
+ /*! The prefix for the value. I.e "$" */
+ property string prefix
+
+ /*! This property indicates the amount of decimals.
+ Note that if you enter more decimals than specified, they will
+ be truncated to the specified amount of decimal places.
+ The default value is \c 0
+ */
+ property int decimals: 0
+
+ /*! \qmlproperty font SpinBox::font
+
+ This property indicates the current font used by the SpinBox.
+ */
+ property alias font: input.font
+
+ /*! This property indicates if the Spinbox should get active
+ focus when pressed.
+ The default value is \c true
+ */
+ property bool activeFocusOnPress: true
+
+ /*! \internal */
+ style: Qt.createComponent(Settings.THEME_PATH + "/SpinBoxStyle.qml", spinbox)
+
+ /*! \internal */
+ function __increment() {
+ input.setValue(input.text)
+ value += stepSize
+ if (value > maximumValue)
+ value = maximumValue
+ input.text = value.toFixed(decimals)
+ }
+
+ /*! \internal */
+ function __decrement() {
+ input.setValue(input.text)
+ value -= stepSize
+ if (value < minimumValue)
+ value = minimumValue
+ input.text = value.toFixed(decimals)
+ }
+
+ /*! \internal */
+ readonly property bool __upEnabled: value != maximumValue;
+ /*! \internal */
+ readonly property bool __downEnabled: value != minimumValue;
+ /*! \internal */
+ readonly property alias __upPressed: mouseUp.pressed
+ /*! \internal */
+ readonly property alias __downPressed: mouseDown.pressed
+ /*! \internal */
+ property alias __upHovered: mouseUp.containsMouse
+ /*! \internal */
+ property alias __downHovered: mouseDown.containsMouse
+ /*! \internal */
+ property alias __containsMouse: mouseArea.containsMouse
+ /*! \internal */
+ property alias __text: input.text
+ /*! \internal */
+ readonly property int __contentHeight: Math.max(input.implicitHeight, 20)
+ /*! \internal */
+ readonly property int __contentWidth: suffixItem.implicitWidth +
+ Math.max(maxSizeHint.implicitWidth,
+ minSizeHint.implicitWidth) +
+ prefixItem.implicitWidth
+ Text {
+ id: maxSizeHint
+ text: maximumValue.toFixed(decimals)
+ font: input.font
+ visible: false
+ }
+
+ Text {
+ id: minSizeHint
+ text: minimumValue.toFixed(decimals)
+ font: input.font
+ visible: false
+ }
+
+ /*! \internal */
+ onDecimalsChanged: input.setValue(value)
+ /*! \internal */
+ onMaximumValueChanged: input.setValue(value)
+ /*! \internal */
+ onMinimumValueChanged: input.setValue(value)
+ /*! \internal */
+ Component.onCompleted: input.setValue(value)
+ /*! \internal */
+ onValueChanged: input.setValue(value)
+
+ Accessible.name: input.text
+ Accessible.role: Accessible.SpinBox
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onPressed: if (activeFocusOnPress) input.forceActiveFocus()
+ }
+
+ Row {
+ id: textLayout
+ anchors.fill: parent
+ spacing: 1
+ clip: true
+ anchors.leftMargin: __panel ? __panel.leftMargin : 0
+ anchors.topMargin: __panel ? __panel.topMargin : 0
+ anchors.rightMargin: __panel ? __panel.rightMargin: 0
+ anchors.bottomMargin: __panel ? __panel.bottomMargin: 0
+
+ Text {
+ id: prefixItem
+ text: prefix
+ color: __panel ? __panel.foregroundColor : "black"
+ anchors.verticalCenter: parent.verticalCenter
+ renderType: Text.NativeRendering
+ }
+
+ TextInput {
+ id: input
+ anchors.verticalCenter: parent.verticalCenter
+ activeFocusOnPress: spinbox.activeFocusOnPress
+ function setValue(v) {
+ var newval = parseFloat(v)
+
+ if (!isNaN(newval)) {
+ // we give minimumValue priority over maximum if they are inconsistent
+ if (newval > maximumValue && maximumValue >= minimumValue)
+ newval = maximumValue
+ else if (v < minimumValue)
+ newval = minimumValue
+ newval = newval.toFixed(decimals)
+ spinbox.value = parseFloat(newval)
+ input.text = newval
+ } else {
+ input.text = parseFloat(spinbox.value)
+ }
+ }
+
+ horizontalAlignment: __panel ? __panel.horizontalTextAlignment : Qt.AlignLeft
+ verticalAlignment: __panel ? __panel.verticalTextAlignment : Qt.AlignVCenter
+ selectByMouse: true
+
+ validator: DoubleValidator { bottom: minimumValue; top: maximumValue; }
+ onAccepted: setValue(input.text)
+ color: __panel ? __panel.foregroundColor : "black"
+ selectionColor: __panel ? __panel.selectionColor : "black"
+ selectedTextColor: __panel ? __panel.selectedTextColor : "black"
+
+ opacity: parent.enabled ? 1 : 0.5
+ renderType: Text.NativeRendering
+ }
+ Text {
+ id: suffixItem
+ text: suffix
+ color: __panel ? __panel.foregroundColor : "black"
+ anchors.verticalCenter: parent.verticalCenter
+ renderType: Text.NativeRendering
+ }
+ }
+
+ // Spinbox increment button
+
+ MouseArea {
+ id: mouseUp
+ hoverEnabled: true
+
+ property var upRect: __panel ? __panel.upRect : null
+
+ anchors.left: parent.left
+ anchors.top: parent.top
+
+ anchors.leftMargin: upRect ? upRect.x : 0
+ anchors.topMargin: upRect ? upRect.y : 0
+
+ width: upRect ? upRect.width : 0
+ height: upRect ? upRect.height : 0
+
+ onClicked: __increment()
+
+ property bool autoincrement: false;
+ onReleased: autoincrement = false
+ Timer { running: mouseUp.pressed; interval: 350 ; onTriggered: mouseUp.autoincrement = true }
+ Timer { running: mouseUp.autoincrement; interval: 60 ; repeat: true ; onTriggered: __increment() }
+ }
+
+ // Spinbox decrement button
+
+ MouseArea {
+ id: mouseDown
+ hoverEnabled: true
+
+ onClicked: __decrement()
+ property var downRect: __panel ? __panel.downRect : null
+
+ anchors.left: parent.left
+ anchors.top: parent.top
+
+ anchors.leftMargin: downRect ? downRect.x : 0
+ anchors.topMargin: downRect ? downRect.y : 0
+
+ width: downRect ? downRect.width : 0
+ height: downRect ? downRect.height : 0
+
+ property bool autoincrement: false;
+ onReleased: autoincrement = false
+ Timer { running: mouseDown.pressed; interval: 350 ; onTriggered: mouseDown.autoincrement = true }
+ Timer { running: mouseDown.autoincrement; interval: 60 ; repeat: true ; onTriggered: __decrement() }
+ }
+
+ Keys.onUpPressed: __increment()
+ Keys.onDownPressed: __decrement()
+}
diff --git a/src/controls/Splitter.qml b/src/controls/Splitter.qml
new file mode 100644
index 00000000..16796f1a
--- /dev/null
+++ b/src/controls/Splitter.qml
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0 as Private
+
+/*!
+ \qmltype Splitter
+ \inqmlmodule QtQuick.Controls 1.0
+ \brief Splitter is a component that lays out items horisontally or
+ vertically with a draggable splitter between each item.
+*/
+
+/*
+*
+* Splitter
+*
+* Splitter is a component that lays out items horisontally or
+* vertically with a draggable splitter between each item.
+*
+* There will always be one (and only one) item in the Splitter that is 'expanding'.
+* Being expanding means that the item will get all the remaining space when other
+* items have been laid out according to their own width and height.
+* By default, the last visible child of the Splitter will be expanding, but
+* this can changed by setting Layout.horizontalSizePolicy to \c Layout.Expanding.
+* Since the expanding item will automatically be resized to fit the extra space, it
+* will ignore explicit assignments to width and height.
+*
+* A handle can belong to the item on the left/top side, or the right/bottom side, of the
+* handle. Which one depends on the expaning item. If the expanding item is to the right
+* of the handle, the handle will belong to the item on the left. If it is to the left, it
+* will belong to the item on the right. This will again control which item that gets resized
+* when the user drags a handle, and which handle that gets hidden when an item is told to hide.
+*
+* The Splitter contains the following API:
+*
+* int orientation - the orientation of the splitter. Can be either Qt.Horizontal
+* or Qt.Vertical.
+* Component handleDelegate - delegate that will be instanciated between each
+* child item. Inside the delegate, the following properties are available:
+* int handleIndex - specifies the index of the splitter handle. The handle
+* between the first and the second item will get index 0, the next handle index 1 etc.
+* bool containsMouse - the mouse hovers the handle.
+* bool pressed: the handle is being pressed.
+* bool dragged: the handle is being dragged.
+*
+* Splitter supports setting Layout properties on child items, which means that you
+* can control minimumWidth, minimumHeight, maximumWidth and maximumHeight (in addition
+* to horizontalSizePolicy/verticalSizePolicy) for each child.
+*
+* Example:
+*
+* To create a Splitter with three items, and let
+* the center item be expanding, one could do the following:
+*
+* Splitter {
+* anchors.fill: parent
+* orientation: Qt.Horizontal
+*
+* Rectangle {
+* width: 200
+* Layout.maximumWidth: 400
+* color: "gray"
+* }
+* Rectangle {
+* id: centerItem
+* Layout.minimumWidth: 50
+* Layout.horizontalSizePolicy: Layout.Expanding
+* color: "darkgray"
+* }
+* Rectangle {
+* width: 200
+* color: "gray"
+* }
+* }
+*/
+
+Item {
+ id: root
+ property int orientation: Qt.Horizontal
+
+ property Component handleDelegate:
+ Rectangle{
+ width: 1
+ height: 1
+ color: Qt.darker(pal.window, 1.5)
+ }
+
+ // **** PRIVATE ****
+
+ clip: true
+ default property alias __items: splitterItems.children
+ property alias __handles: splitterHandles.children
+ Component.onCompleted: d.init()
+ onWidthChanged: d.updateLayout()
+ onHeightChanged: d.updateLayout()
+
+ SystemPalette { id: pal }
+
+ QtObject {
+ id: d
+ property bool horizontal: orientation == Qt.Horizontal
+ property string minimum: horizontal ? "minimumWidth" : "minimumHeight"
+ property string maximum: horizontal ? "maximumWidth" : "maximumHeight"
+ property string offset: horizontal ? "x" : "y"
+ property string otherOffset: horizontal ? "y" : "x"
+ property string size: horizontal ? "width" : "height"
+ property string otherSize: horizontal ? "height" : "width"
+
+ property int expandingIndex: -1
+ property bool updateLayoutGuard: true
+
+ function init()
+ {
+ for (var i=0; i<__items.length; ++i) {
+ var item = __items[i];
+ item.widthChanged.connect(d.updateLayout);
+ item.heightChanged.connect(d.updateLayout);
+ item.Layout.maximumWidthChanged.connect(d.updateLayout);
+ item.Layout.minimumWidthChanged.connect(d.updateLayout);
+ item.Layout.maximumHeightChanged.connect(d.updateLayout);
+ item.Layout.minimumHeightChanged.connect(d.updateLayout);
+ item.Layout.horizontalSizePolicyChanged.connect(d.updateExpandingIndex)
+ item.Layout.verticalSizePolicyChanged.connect(d.updateExpandingIndex)
+ d.listenForVisibleChanged(item)
+ if (i < __items.length-1)
+ handleLoader.createObject(splitterHandles, {"handleIndex":i});
+ }
+
+ d.updateExpandingIndex()
+ d.updateLayoutGuard = false
+ d.updateLayout()
+ }
+
+ function listenForVisibleChanged(item) {
+ item.visibleChanged.connect(function() {
+ if (!root.visible)
+ return
+ if (item.visible) {
+ // Try to keep all items within the SplitterRow. When an item
+ // has been hidden, the expanding item might no longer be large enough
+ // to give away space to the new items width. So we need to resize:
+ var overflow = d.accumulatedSize(0, __items.length, true) - root[d.size];
+ if (overflow > 0)
+ item[d.size] -= overflow
+ }
+ updateExpandingIndex()
+ });
+ }
+
+ function updateExpandingIndex()
+ {
+ var policy = (root.orientation === Qt.Horizontal) ? "horizontalSizePolicy" : "verticalSizePolicy"
+ for (var i=__items.length-1; i>=0; --i) {
+ if (__items[i].visible && __items[i].Layout[policy] === Layout.Expanding) {
+ d.expandingIndex = i
+ break;
+ }
+ }
+
+ if (i === -1) {
+ for (i=__items.length-1; i>0; --i) {
+ if (__items[i].visible)
+ break;
+ }
+ }
+
+ d.expandingIndex = i
+ d.updateLayout()
+ }
+
+ function accumulatedSize(firstIndex, lastIndex, includeExpandingMinimum)
+ {
+ // Go through items and handles, and
+ // calculate their acummulated width.
+ var w = 0
+ for (var i=firstIndex; i<lastIndex; ++i) {
+ var item = __items[i]
+ if (item.visible) {
+ if (i !== d.expandingIndex)
+ w += item[d.size];
+ else if (includeExpandingMinimum && item.Layout[minimum] !== undefined)
+ w += item.Layout[minimum]
+ }
+
+ var handle = __handles[i]
+ if (handle && __items[i + ((d.expandingIndex > i) ? 0 : 1)].visible)
+ w += handle[d.size]
+ }
+ return w
+ }
+
+ function updateLayout()
+ {
+ // This function will reposition both handles and
+ // items according to the their width/height:
+ if (__items.length === 0)
+ return;
+ if (d.updateLayoutGuard === true)
+ return
+ d.updateLayoutGuard = true
+
+ // Ensure all items within their min/max:
+ for (var i=0; i<__items.length; ++i) {
+ if (i !== d.expandingIndex) {
+ var item = __items[i];
+ if (item.Layout[maximum] !== undefined) {
+ if (item[d.size] > item.Layout[maximum])
+ item[d.size] = item.Layout[maximum]
+ }
+ if (item.Layout[minimum] !== undefined) {
+ if (item[d.size] < item.Layout[minimum])
+ item[d.size] = item.Layout[minimum]
+ }
+ }
+ }
+
+ // Set size of expanding item to remaining available space:
+ var expandingItem = __items[expandingIndex]
+ var min = expandingItem.Layout[minimum] !== undefined ? expandingItem.Layout[minimum] : 0
+ expandingItem[d.size] = Math.max(min, root[d.size] - d.accumulatedSize(0, __items.length, false))
+
+ // Then, position items and handles according to their width:
+ var lastVisibleItem, lastVisibleHandle, handle
+ var implicitSize = min - expandingItem[d.size]
+
+ for (i=0; i<__items.length; ++i) {
+ // Position item to the right of the previous visible handle:
+ item = __items[i];
+ if (item.visible) {
+ item[d.offset] = lastVisibleHandle ? lastVisibleHandle[d.offset] + lastVisibleHandle[d.size] : 0
+ item[d.otherOffset] = 0
+ item[d.otherSize] = root[d.otherSize]
+ implicitSize += item[d.size]
+ lastVisibleItem = item
+ }
+
+ // Position handle to the right of the previous visible item. We use an alterative way of
+ // checking handle visibility because that property might not have updated correctly yet:
+ handle = __handles[i]
+ if (handle && __items[i + ((d.expandingIndex > i) ? 0 : 1)].visible) {
+ handle[d.offset] = lastVisibleItem[d.offset] + Math.max(0, lastVisibleItem[d.size])
+ handle[d.otherOffset] = 0
+ handle[d.otherSize] = root[d.otherSize]
+ implicitSize += handle[d.size]
+ lastVisibleHandle = handle
+ }
+ }
+
+ if (root.orientation === Qt.horizontal) {
+ root.implicitWidth = implicitSize
+ root.implicitHeight = 0
+ } else {
+ root.implicitWidth = 0
+ root.implicitHeight = implicitSize
+ }
+
+ d.updateLayoutGuard = false
+ }
+ }
+
+ Component {
+ id: handleLoader
+ Loader {
+ id: itemHandle
+ property int handleIndex: -1
+ property alias containsMouse: mouseArea.containsMouse
+ property alias pressed: mouseArea.pressed
+ property bool dragged: mouseArea.drag.active
+
+ visible: __items[handleIndex + ((d.expandingIndex > handleIndex) ? 0 : 1)].visible
+ sourceComponent: handleDelegate
+ onWidthChanged: d.updateLayout()
+ onHeightChanged: d.updateLayout()
+ onXChanged: moveHandle()
+ onYChanged: moveHandle()
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ anchors.leftMargin: (parent.width <= 1) ? -2 : 0
+ anchors.rightMargin: (parent.width <= 1) ? -2 : 0
+ anchors.topMargin: (parent.height <= 1) ? -2 : 0
+ anchors.bottomMargin: (parent.height <= 1) ? -2 : 0
+ hoverEnabled: true
+ drag.target: parent
+ drag.axis: root.orientation === Qt.Horizontal ? Drag.XAxis : Drag.YAxis
+ cursorShape: root.orientation === Qt.Horizontal ? Qt.SplitHCursor : Qt.SplitVCursor
+ }
+
+ function moveHandle() {
+ // Moving the handle means resizing an item. Which one,
+ // left or right, depends on where the expanding item is.
+ // 'updateLayout' will override in case new width violates max/min.
+ // And 'updateLayout will be triggered when an item changes width.
+ if (d.updateLayoutGuard)
+ return
+
+ var leftHandle, leftItem, rightItem, rightHandle
+ var leftEdge, rightEdge, newWidth, leftStopX, rightStopX
+ var i
+
+ if (d.expandingIndex > handleIndex) {
+ // Resize item to the left.
+ // Ensure that the handle is not crossing other handles. So
+ // find the first visible handle to the left to determine the left edge:
+ leftEdge = 0
+ for (i=handleIndex-1; i>=0; --i) {
+ leftHandle = __handles[i]
+ if (leftHandle.visible) {
+ leftEdge = leftHandle[d.offset] + leftHandle[d.size]
+ break;
+ }
+ }
+
+ // Ensure: leftStopX >= itemHandle[d.offset] >= rightStopX
+ var min = d.accumulatedSize(handleIndex+1, __items.length, true)
+ rightStopX = root[d.size] - min - itemHandle[d.size]
+ leftStopX = Math.max(leftEdge, itemHandle[d.offset])
+ itemHandle[d.offset] = Math.min(rightStopX, Math.max(leftStopX, itemHandle[d.offset]))
+
+ newWidth = itemHandle[d.offset] - leftEdge
+ leftItem = __items[handleIndex]
+ // The next line will trigger 'updateLayout':
+ leftItem[d.size] = newWidth
+ } else {
+ // Resize item to the right.
+ // Ensure that the handle is not crossing other handles. So
+ // find the first visible handle to the right to determine the right edge:
+ rightEdge = root[d.size]
+ for (i=handleIndex+1; i<__handles.length; ++i) {
+ rightHandle = __handles[i]
+ if (rightHandle.visible) {
+ rightEdge = rightHandle[d.offset]
+ break;
+ }
+ }
+
+ // Ensure: leftStopX <= itemHandle[d.offset] <= rightStopX
+ min = d.accumulatedSize(0, handleIndex+1, true)
+ leftStopX = min - itemHandle[d.size]
+ rightStopX = Math.min((rightEdge - itemHandle[d.size]), itemHandle[d.offset])
+ itemHandle[d.offset] = Math.max(leftStopX, Math.min(itemHandle[d.offset], rightStopX))
+
+ newWidth = rightEdge - (itemHandle[d.offset] + itemHandle[d.size])
+ rightItem = __items[handleIndex+1]
+ // The next line will trigger 'updateLayout':
+ rightItem[d.size] = newWidth
+ }
+ }
+ }
+ }
+
+ Item {
+ id: splitterItems
+ anchors.fill: parent
+ }
+ Item {
+ id: splitterHandles
+ anchors.fill: parent
+ }
+
+}
diff --git a/src/controls/StatusBar.qml b/src/controls/StatusBar.qml
new file mode 100644
index 00000000..965af47b
--- /dev/null
+++ b/src/controls/StatusBar.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+
+/*!
+ \qmltype StatusBar
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup applicationwindow
+ \brief StatusBar is for containing status informating in your app
+
+ The common way of using StatusBar is in relation to \l ApplicationWindow.
+
+ Note that the StatusBar does not provide a layout of its own but requires you to
+ position its contents, for instance by creating a Row.
+
+ \code
+ ApplicationWindow {
+ statusBar: StatusBar {
+ Label {
+ text: "Read Only"
+ anchors.centerIn: parent
+ }
+ }
+ }
+ \endcode
+*/
+
+Item {
+ id: statusbar
+ implicitHeight: 20
+ implicitWidth: parent ? parent.width : style.implicitWidth
+ StyleItem {
+ id: style
+ anchors.fill: parent
+ elementType: "statusbar"
+ }
+}
diff --git a/src/controls/Tab.qml b/src/controls/Tab.qml
new file mode 100644
index 00000000..014bb023
--- /dev/null
+++ b/src/controls/Tab.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+
+/*!
+ \qmltype Tab
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup navigation
+ \brief Tab is doing bla...bla...
+*/
+
+Item {
+ id:tab
+ anchors.fill: parent
+ property string title
+ property int contentMargin
+ Accessible.role: Accessible.PageTab
+}
diff --git a/src/controls/TabFrame.qml b/src/controls/TabFrame.qml
new file mode 100644
index 00000000..91ea18f6
--- /dev/null
+++ b/src/controls/TabFrame.qml
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype TabFrame
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup navigation
+ \brief Represents a control that contains multiple items that share the same space on the screen.
+
+*/
+
+Item {
+ id: tabWidget
+ width: 100
+ height: 100
+
+ property int current: 0
+ property int count: 0
+ property bool frame: true
+ property bool tabsVisible: true
+ property string position: "North"
+ default property alias tabs : stack.children
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/TabFrameStyle.qml", tabWidget)
+ property var __styleItem: loader.item
+
+ onCurrentChanged: __setOpacities()
+ Component.onCompleted: __setOpacities()
+
+ function __setOpacities() {
+ var tabCount = 0;
+ for (var i = 0; i < stack.children.length; ++i) {
+ stack.children[i].visible = (i == current ? true : false)
+ // count real tabs - ignore for instance Repeater
+ if (stack.children[i].Accessible.role == Accessible.PageTab)
+ ++tabCount;
+ }
+ tabWidget.count = tabCount;
+ }
+
+ Component {
+ id: tabcomp
+ Tab {}
+ }
+
+ function addTab(component, title) {
+ var tab = tabcomp.createObject(this);
+ component.createObject(tab)
+ tab.parent = stack
+ tab.title = title
+ __setOpacities()
+ return tab
+ }
+
+ function removeTab(id) {
+ var tab = tabs[id]
+ tab.destroy()
+ if (current > 0)
+ current-=1
+ }
+
+ Loader {
+ id: loader
+ sourceComponent: style
+ property var control: tabWidget
+ }
+
+ Loader {
+ id: frameLoader
+
+ anchors.fill: parent
+ anchors.topMargin: tabbarItem && tabsVisible && position == "North" ? Math.max(0, tabbarItem.height - stack.baseOverlap) : 0
+ anchors.bottomMargin: tabbarItem && tabsVisible && position == "South" ? Math.max(0, tabbarItem.height - stack.baseOverlap) : 0
+ sourceComponent: frame && loader.item ? loader.item.frame : null
+ property var control: tabWidget
+
+ Item {
+ id: stack
+ anchors.fill: parent
+ anchors.margins: (frame ? frameWidth : 0)
+ anchors.topMargin: anchors.margins + (style =="mac" ? 6 : 0)
+ anchors.bottomMargin: anchors.margins + (style =="mac" ? 6 : 0)
+ property int frameWidth
+ property string style
+ property int baseOverlap
+ }
+ onLoaded: { item.z = -1 }
+ }
+
+ TabBar {
+ id: tabbarItem
+ tabFrame: tabWidget
+ style: loader.item
+ anchors.top: parent.top
+ anchors.left: tabWidget.left
+ anchors.right: tabWidget.right
+ }
+
+ states: [
+ State {
+ name: "South"
+ when: position == "South" && tabbarItem != undefined
+ PropertyChanges {
+ target: tabbarItem
+ anchors.topMargin: tabbarItem.height
+ }
+ AnchorChanges {
+ target: tabbarItem
+ anchors.top: undefined
+ anchors.bottom: tabWidget.bottom
+ }
+ }
+ ]
+}
diff --git a/src/controls/TableView.qml b/src/controls/TableView.qml
new file mode 100644
index 00000000..bcfc8d8b
--- /dev/null
+++ b/src/controls/TableView.qml
@@ -0,0 +1,676 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+
+/*!
+ \qmltype TableView
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup views
+ \brief Provides a list view with scroll bars, styling and header sections.
+
+ \image tableview.png
+
+ A TableView is similar to \l ListView and adds scroll bars, selection and
+ resizable header sections. As with \l ListView, data for each row is provided through a \l model:
+
+ \code
+ ListModel {
+ id: libraryModel
+ ListElement{ title: "A Masterpiece" ; author: "Gabriel" }
+ ListElement{ title: "Brilliance" ; author: "Jens" }
+ ListElement{ title: "Outstanding" ; author: "Frederik" }
+ }
+ \endcode
+
+ You provide title and size of a column header
+ by adding a \l TableViewColumn to the default \l header property
+ as demonstrated below.
+ \code
+
+ TableView {
+ TableViewColumn{ role: "title" ; title: "Title" ; width: 100 }
+ TableViewColumn{ role: "author" ; title: "Author" ; width: 200 }
+ model: libraryModel
+ }
+ \endcode
+
+ The header sections are attached to values in the \l model by defining
+ the model role they attach to. Each property in the model, will
+ then be shown in their corresponding column.
+
+ You can customize the look by overriding the \l itemDelegate,
+ \l rowDelegate or \l headerDelegate properties.
+
+ The view itself does not provide sorting. This has to
+ be done on the model itself. However you can provide sorting
+ on the model and enable sort indicators on headers.
+
+\list
+ \li sortColumn - The index of the currently selected sort header
+ \li sortIndicatorVisible - If sort indicators should be enabled
+ \li sortIndicatorDirection - "up" or "down" depending on state
+\endlist
+*/
+
+ScrollArea {
+ id: root
+
+ /*! This property holds the model providing data for the list.
+
+ The model provides the set of data that is used to create the items in the view.
+ Models can be created directly in QML using ListModel, XmlListModel or VisualItemModel,
+ or provided by C++ model classes. \sa ListView::model
+
+ Example model:
+
+ \code
+ model: ListModel {
+ ListElement{ column1: "value 1" ; column2: "value 2" }
+ ListElement{ column1: "value 3" ; column2: "value 4" }
+ }
+ \endcode */
+ property variant model
+
+ width: 200
+ height: 200
+
+ /*! \internal */
+ __scrollBarTopMargin: styleitem.style == "mac" ? headerrow.height : 0
+
+ /*! This property sets if the frame should paint the focus frame around its contents.
+ The default value is \c false.
+ \note Only certain platforms such as Mac OS X will be affected by this property */
+ property bool highlightOnFocus: false
+
+ /*! This property is set to \c true if the view alternates the row color.
+ The default value is \c true. */
+ property bool alternateRowColor: true
+
+ /*! This property determines if the header is visible.
+ The default value is \c true. */
+ property bool headerVisible: true
+
+ /*! This property defines a delegate to draw a specific cell.
+
+ In the item delegate you have access to the following special properties:
+ \list
+ \li itemHeight - default platform size of item
+ \li itemWidth - default platform width of item
+ \li itemSelected - if the row is currently selected
+ \li itemValue - The text for this item
+ \li itemForeground - The default text color for an item
+ \endlist
+ Example:
+ \code
+ itemDelegate: Item {
+ Text {
+ anchors.verticalCenter: parent.verticalCenter
+ color: itemForeground
+ elide: Text.ElideRight
+ text: itemValue
+ }
+ }
+ \endcode */
+ property Component itemDelegate: standardDelegate
+
+ /*! This property defines a delegate to draw a row. */
+ property Component rowDelegate: rowDelegate
+
+ /*! This property defines a delegate to draw a header. */
+ property Component headerDelegate: headerDelegate
+
+ /*! \qmlproperty color TableView::backgroundColor
+
+ This property sets the background color of the viewport.
+ The default value is the base color of the SystemPalette. */
+ property alias backgroundColor: colorRect.color
+
+ /*! This property sets if the frame should be visible.
+ The default value is \c true. */
+ frame: true
+
+ /*! Index of the currently selected sort column
+ The default value is \c 0. */
+ property int sortColumn
+
+ /*! This property shows or hides the sort indicator
+ The default value is \c false.
+ \note The view itself does not sort the data. */
+ property bool sortIndicatorVisible: false
+
+ /*! This sets the sorting direction of the sort indicator
+ The allowed values are:
+ \list
+ \li "up"
+ \li "down" - the default
+ \endlist */
+ property string sortIndicatorDirection: "down"
+
+ /*! \qmlproperty Component TableView::header
+ This property contains the TableViewHeader items */
+ default property alias header: listView.columnheader
+
+ /*! \qmlproperty Component TableView::contentHeader
+ This is the content header of the TableView */
+ property alias contentHeader: listView.header
+
+ /*! \qmlproperty Component TableView::contentFooter
+ This is the content footer of the TableView */
+ property alias contentFooter: listView.footer
+
+ /*! \qmlproperty Item TableView::currentItem
+ This is the current item of the TableView */
+ property alias currentItem: listView.currentItem
+
+ /*! \qmlproperty int TableView::count
+ The current number of rows */
+ property alias count: listView.count
+
+ /*! \qmlproperty string TableView::section
+ The section of the view. \sa ListView::section */
+ readonly property alias section: listView.section
+
+ /*! \qmlproperty int TableView::currentIndex
+ The current row index of the view. */
+ property alias currentIndex: listView.currentIndex
+
+ Accessible.role: Accessible.Table
+
+ /*! \qmlsignal TableView::activated()
+ Emitted when a new row is selected by the user. */
+ signal activated
+
+ /*! \internal */
+ function __decrementCurrentIndex() {
+ __scroller.blockUpdates = true;
+ listView.decrementCurrentIndex();
+ __scroller.blockUpdates = false;
+ }
+
+ /*! \internal */
+ function __incrementCurrentIndex() {
+ __scroller.blockUpdates = true;
+ listView.incrementCurrentIndex();
+ __scroller.blockUpdates = false;
+ }
+
+ ListView {
+ id: listView
+ anchors.topMargin: tableHeader.height
+ anchors.fill: parent
+
+ flickableDirection: Flickable.HorizontalFlick
+ SystemPalette {
+ id: palette
+ colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
+ }
+
+ Rectangle {
+ id: colorRect
+ parent: viewport
+ anchors.fill: parent
+ color: palette.base
+ z: -1
+ }
+
+ StyleItem {
+ id: itemstyle
+ elementType: "item"
+ visible: false
+ }
+
+ MouseArea {
+ id: mousearea
+
+ anchors.fill: listView
+
+ property bool autoincrement: false
+ property bool autodecrement: false
+
+ onReleased: {
+ autoincrement = false
+ autodecrement = false
+ }
+
+ // Handle vertical scrolling whem dragging mouse outside boundraries
+ Timer { running: mousearea.autoincrement && __scroller.verticalScrollBar.visible; repeat: true; interval: 20 ; onTriggered: __incrementCurrentIndex()}
+ Timer { running: mousearea.autodecrement && __scroller.verticalScrollBar.visible; repeat: true; interval: 20 ; onTriggered: __decrementCurrentIndex()}
+
+ onPositionChanged: {
+ if (mouseY > listView.height && pressed) {
+ if (autoincrement) return;
+ autodecrement = false;
+ autoincrement = true;
+ } else if (mouseY < 0 && pressed) {
+ if (autodecrement) return;
+ autoincrement = false;
+ autodecrement = true;
+ } else {
+ autoincrement = false;
+ autodecrement = false;
+ }
+ var y = Math.min(flickableItem.contentY + listView.height - 5, Math.max(mouseY + flickableItem.contentY, flickableItem.contentY));
+ var newIndex = listView.indexAt(0, y);
+ if (newIndex >= 0)
+ listView.currentIndex = listView.indexAt(0, y);
+ }
+
+ onPressed: {
+ listView.forceActiveFocus()
+ var x = Math.min(flickableItem.contentWidth - 5, Math.max(mouseX + flickableItem.contentX, 0))
+ var y = Math.min(flickableItem.contentHeight - 5, Math.max(mouseY + flickableItem.contentY, 0))
+ listView.currentIndex = listView.indexAt(x, y)
+ }
+
+ onDoubleClicked: { root.activated() }
+
+ // Note by prevent stealing we are keeping the flickable from
+ // eating our mouse press events
+ preventStealing: true
+ }
+
+ // Fills extra rows with alternate color
+ Column {
+ id: rowfiller
+ property int rowHeight: flickableItem.contentHeight/count
+ property int paddedRowCount: height/rowHeight
+ property int count: flickableItem.count
+ y: flickableItem.contentHeight
+ width: parent.width
+ visible: flickableItem.contentHeight > 0 && alternateRowColor
+ height: viewport.height - flickableItem.contentHeight
+ Repeater {
+ model: visible ? parent.paddedRowCount : 0
+ Loader {
+ width: rowfiller.width
+ height: rowfiller.rowHeight
+ sourceComponent: root.rowDelegate
+ property bool itemAlternateBackground: (index + count) % 2 === 1
+ property bool itemSelected: false
+ property variant model: listView.model
+ property variant modelData: null
+ }
+ }
+ }
+
+ property list<TableViewColumn> columnheader
+ highlightFollowsCurrentItem: true
+ model: root.model
+
+ Keys.onUpPressed: root.decrementCurrentIndex()
+ Keys.onDownPressed: root.incrementCurrentIndex()
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_PageUp) {
+ verticalScrollBar.value = __scroller.verticalScrollBar.value - listView.height
+ } else if (event.key === Qt.Key_PageDown)
+ verticalScrollBar.value = __scroller.verticalScrollBar.value + listView.height
+ }
+
+ Keys.onReturnPressed: root.activated();
+
+ delegate: Item {
+ id: rowitem
+ width: row.width
+ height: rowstyle.height
+
+ property int rowIndex: model.index
+ property bool itemAlternateBackground: alternateRowColor && rowIndex % 2 == 1
+ property variant itemModelData: typeof modelData == "undefined" ? null : modelData
+ property variant itemModel: model
+
+ Loader {
+ id: rowstyle
+ // row delegate
+ sourceComponent: root.rowDelegate
+ // Row fills the view width regardless of item size
+ // But scrollbar should not adjust to it
+ width: parent.width + __scroller.horizontalScrollBar.width
+ x: flickableItem.contentX
+
+ property bool itemAlternateBackground: rowitem.itemAlternateBackground
+ property bool itemSelected: rowitem.ListView.isCurrentItem
+ property int index: rowitem.rowIndex
+ property variant model: listView.model
+ property variant modelData: rowitem.itemModelData
+ property variant itemModel: rowitem.itemModel
+ }
+ Row {
+ id: row
+ anchors.left: parent.left
+ height: parent.height
+ Repeater {
+ id: repeater
+ model: root.header.length
+ Loader {
+ id: itemDelegateLoader
+ height: parent.height
+ visible: header[index].visible
+ sourceComponent: header[index].delegate ? header[index].delegate : itemDelegate
+ property variant model: listView.model
+ property variant role: header[index].role
+ property variant modelData: itemModelData
+
+ width: header[index].width
+
+ function getValue() {
+ if (header[index].role.length && itemModel.hasOwnProperty(header[index].role))
+ return itemModel[header[index].role] // Qml ListModel and QAbstractItemModel
+ else if (modelData != undefined && modelData.hasOwnProperty(header[index].role))
+ return modelData[header[index].role] // QObjectList / QObject
+ else if (modelData != undefined)
+ return modelData // Models without role
+ else
+ return ""
+ }
+ property variant itemValue: getValue()
+ property bool itemSelected: rowitem.ListView.isCurrentItem
+ property color itemForeground: itemSelected ? rowstyleitem.highlightedTextColor : rowstyleitem.textColor
+ property int rowIndex: rowitem.rowIndex
+ property int columnIndex: index
+ property int itemElideMode: header[index].elideMode
+ property int itemTextAlignment: header[index].horizontalAlignment
+ }
+ }
+ onWidthChanged: listView.contentWidth = width
+ }
+ }
+
+ Text{ id:text }
+
+ Item {
+ id: tableHeader
+ clip: true
+ parent: __scroller
+ visible: headerVisible
+ anchors.top: parent.top
+ anchors.margins: viewport.anchors.margins
+ anchors.rightMargin: __scroller.frameWidth +
+ (__scroller.outerFrame && __scrollBarTopMargin ? 0 : __scroller.verticalScrollBar.width
+ + __scroller.scrollBarSpacing)
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ height: headerVisible ? headerrow.height : 0
+
+ Behavior on height { NumberAnimation{ duration: 80 } }
+
+ Row {
+ id: headerrow
+ x: -listView.contentX
+
+ Repeater {
+ id: repeater
+
+ property int targetIndex: -1
+ property int dragIndex: -1
+
+ model: header.length
+
+ delegate: Item {
+ z:-index
+ width: header[index].width
+ visible: header[index].visible
+ height: headerStyle.height
+
+ Loader {
+ id: headerStyle
+ sourceComponent: root.headerDelegate
+ anchors.left: parent.left
+ anchors.right: parent.right
+ property string itemValue: header[index].title
+ property string itemSort: (sortIndicatorVisible && index == sortColumn) ? (sortIndicatorDirection == "up" ? "up" : "down") : "";
+ property bool itemPressed: headerClickArea.pressed
+ property bool itemContainsMouse: headerClickArea.containsMouse
+ property string itemPosition: header.length === 1 ? "only" :
+ index===header.length-1 ? "end" :
+ index===0 ? "beginning" : ""
+ }
+ Rectangle{
+ id: targetmark
+ width: parent.width
+ height:parent.height
+ opacity: (index == repeater.targetIndex && repeater.targetIndex != repeater.dragIndex) ? 0.5 : 0
+ Behavior on opacity { NumberAnimation{duration:160}}
+ color: palette.highlight
+ }
+
+ MouseArea{
+ id: headerClickArea
+ drag.axis: Qt.YAxis
+ hoverEnabled: true
+ anchors.fill: parent
+ onClicked: {
+ if (sortColumn == index)
+ sortIndicatorDirection = sortIndicatorDirection === "up" ? "down" : "up"
+ sortColumn = index
+ }
+ // Here we handle moving header sections
+ // NOTE: the direction is different from the master branch
+ // so this indicates that I am using an invalid assumption on item ordering
+ onPositionChanged: {
+ if (pressed) { // only do this while dragging
+ for (var h = header.length-1 ; h >= 0 ; --h) {
+ if (drag.target.x > headerrow.children[h].x) {
+ repeater.targetIndex = h
+ break
+ }
+ }
+ }
+ }
+
+ onPressed: {
+ repeater.dragIndex = index
+ draghandle.x = parent.x
+ }
+
+ onReleased: {
+ if (repeater.targetIndex >= 0 && repeater.targetIndex != index ) {
+ // Rearrange the header sections
+ var items = new Array
+ for (var i = 0 ; i< header.length ; ++i)
+ items.push(header[i])
+ items.splice(index, 1);
+ items.splice(repeater.targetIndex, 0, header[index]);
+ header = items
+ if (sortColumn == index)
+ sortColumn = repeater.targetIndex
+ }
+ repeater.targetIndex = -1
+ }
+ drag.maximumX: 1000
+ drag.minimumX: -1000
+ drag.target: draghandle
+ }
+
+ Loader {
+ id: draghandle
+ property string itemValue: header[index].title
+ property string itemSort: (sortIndicatorVisible && index == sortColumn) ? (sortIndicatorDirection == "up" ? "up" : "down") : "";
+ property bool itemPressed: headerClickArea.pressed
+ property bool itemContainsMouse: headerClickArea.containsMouse
+ property string itemPosition
+
+ parent: tableHeader
+ width: header[index].width
+ height: parent.height
+ sourceComponent: root.headerDelegate
+ visible: headerClickArea.pressed
+ opacity: 0.5
+ }
+
+
+ MouseArea {
+ id: headerResizeHandle
+ property int offset: 0
+ property int minimumSize: 20
+ anchors.rightMargin: -width/2
+ width: 16 ; height: parent.height
+ anchors.right: parent.right
+ onPositionChanged: {
+ var newHeaderWidth = header[index].width + (mouseX - offset)
+ header[index].width = Math.max(minimumSize, newHeaderWidth)
+ }
+ property bool found:false
+
+ onDoubleClicked: {
+ var row
+ var minWidth = 0
+ var listdata = listView.children[0]
+ for (row = 0 ; row < listdata.children.length ; ++row){
+ var item = listdata.children[row+1]
+ if (item && item.children[1] && item.children[1].children[index] &&
+ item.children[1].children[index].children[0].hasOwnProperty("implicitWidth"))
+ minWidth = Math.max(minWidth, item.children[1].children[index].children[0].implicitWidth)
+ }
+ if (minWidth)
+ header[index].width = minWidth
+ }
+ onPressedChanged: if (pressed) offset=mouseX
+ cursorShape: Qt.SplitHCursor
+ }
+ }
+ }
+ }
+ Loader {
+ id: loader
+ property string itemValue
+ property string itemSort
+ property bool itemPressed
+ property bool itemContainsMouse
+ property string itemPosition
+
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.bottom: headerrow.bottom
+ anchors.rightMargin: -2
+ sourceComponent: root.headerDelegate
+ width: root.width - headerrow.width + 2
+ visible: root.header.length
+ z:-1
+ }
+
+ Component {
+ id: standardDelegate
+ Item {
+ height: Math.max(16, styleitem.implicitHeight)
+ property int implicitWidth: sizehint.paintedWidth + 4
+ Text {
+ id: label
+ objectName: "label"
+ width: parent.width
+ anchors.margins: 6
+ font: itemstyle.font
+ anchors.left: parent.left
+ anchors.right: parent.right
+ horizontalAlignment: itemTextAlignment
+ anchors.verticalCenter: parent.verticalCenter
+ elide: itemElideMode
+ text: itemValue != undefined ? itemValue : ""
+ color: itemForeground
+ renderType: Text.NativeRendering
+ }
+ Text {
+ id: sizehint
+ font: label.font
+ text: itemValue ? itemValue : ""
+ visible: false
+ }
+ }
+ }
+
+ Component {
+ id: nativeDelegate
+ // This gives more native styling, but might be less performant
+ StyleItem {
+ elementType: "item"
+ text: itemValue
+ selected: itemSelected
+ active: root.activeFocus
+ }
+ }
+
+ Component {
+ id: headerDelegate
+ StyleItem {
+ elementType: "header"
+ activeControl: itemSort
+ raised: true
+ sunken: itemPressed
+ text: itemValue
+ hover: itemContainsMouse
+ hints: itemPosition
+ }
+ }
+
+ Component {
+ id: rowDelegate
+ StyleItem {
+ id: rowstyle
+ elementType: "itemrow"
+ activeControl: itemAlternateBackground ? "alternate" : ""
+ selected: itemSelected ? true : false
+ height: Math.max(16, styleitem.implicitHeight)
+ active: root.activeFocus
+ }
+ }
+
+ StyleItem {
+ id: styleitem
+ elementType: "header"
+ visible:false
+ contentWidth: 16
+ contentHeight: font.pixelSize
+ }
+
+ StyleItem {
+ id: rowstyleitem
+ property color textColor: styleHint("textColor")
+ property color highlightedTextColor: styleHint("highlightedTextColor")
+ elementType: "item"
+ visible: false
+ }
+ }
+ }
+}
diff --git a/src/controls/TableViewColumn.qml b/src/controls/TableViewColumn.qml
new file mode 100644
index 00000000..f14b3f03
--- /dev/null
+++ b/src/controls/TableViewColumn.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+
+/*!
+ \qmltype TableViewColumn
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup views
+ \brief Used by the \l TableView to define a column header.
+*/
+
+QtObject {
+ /*! The title text of the column. */
+ property string title
+
+ /*! The model \c role of the column. */
+ property string role
+
+ /*! The current width of the column
+ The default value depends on platform. */
+ property int width: 160
+
+ /*! The horizontal offset of the column. */
+ property int x
+
+ /*! The visible status of the column.*/
+ property bool visible: true
+
+ /*! The text elide mode of the column.
+ Allowed values are:
+ \list
+ \li Text.AlignLeft - the default
+ \li Text.AligntRight
+ \li Text.AlignHCenter
+ \li Text.AlignJustify
+ \endlist
+ \sa Text::elide */
+ property int elideMode: Text.ElideRight
+
+ /*! The text elide mode of the column.
+ \sa Text::horizontalAlignment: */
+ property int horizontalAlignment: Text.AlignLeft
+
+ /*! The delegate of the column. This can be used to set the
+ \l TableView::itemDelegate for a specific column. */
+ property Component delegate
+}
diff --git a/src/controls/TextArea.qml b/src/controls/TextArea.qml
new file mode 100644
index 00000000..bcedbe75
--- /dev/null
+++ b/src/controls/TextArea.qml
@@ -0,0 +1,662 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+/*!
+ \qmltype TextArea
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief TextArea displays multiple lines of editable formatted text.
+
+ It can display both plain and rich text. For example:
+
+ \qml
+ TextArea {
+ width: 240
+ text: "<b>Hello</b> <i>World!</i>"
+ }
+ \endqml
+
+ Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
+ be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
+ from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
+
+ You can translate between cursor positions (characters from the start of the document) and pixel
+ points using positionAt() and positionToRectangle().
+
+ \sa TextField, TextEdit
+*/
+
+ScrollArea {
+ id: area
+
+ /*!
+ \qmlproperty bool TextArea::activeFocusOnPress
+
+ Whether the TextEdit should gain active focus on a mouse press. By default this is
+ set to true.
+ */
+ property alias activeFocusOnPress: edit.activeFocusOnPress
+
+ /*!
+ \qmlproperty url TextArea::baseUrl
+
+ This property specifies a base URL which is used to resolve relative URLs
+ within the text.
+
+ The default value is the url of the QML file instantiating the TextArea item.
+ */
+ property alias baseUrl: edit.baseUrl
+
+ /*!
+ \qmlproperty bool TextArea::canPaste
+
+ Returns true if the TextArea is writable and the content of the clipboard is
+ suitable for pasting into the TextArea.
+ */
+ readonly property alias canPaste: edit.canPaste
+
+ /*!
+ \qmlproperty bool TextArea::canRedo
+
+ Returns true if the TextArea is writable and there are \l {undo}{undone}
+ operations that can be redone.
+ */
+ readonly property alias canRedo: edit.canRedo
+
+ /*!
+ \qmlproperty bool TextArea::canUndo
+
+ Returns true if the TextArea is writable and there are previous operations
+ that can be undone.
+ */
+ readonly property alias canUndo: edit.canUndo
+
+ /*!
+ \qmlproperty color TextArea::textColor
+
+ The text color.
+
+ \qml
+ TextArea { color: "orange" }
+ \endqml
+ */
+ property alias textColor: edit.color
+
+ /*!
+ \qmlproperty int TextArea::cursorPosition
+ The position of the cursor in the TextArea.
+ */
+ property alias cursorPosition: edit.cursorPosition
+
+ /*! \qmlproperty font TextArea::font
+
+ The font of the TextArea.
+ */
+ property alias font: edit.font
+
+ /*!
+ \qmlproperty enumeration TextArea::horizontalAlignment
+
+ Sets the alignment of the text within the TextArea item's width.
+
+ By default, the horizontal text alignment follows the natural alignment of the text,
+ for example text that is read from left to right will be aligned to the left.
+
+ The valid values for \c horizontalAlignment are:
+ \list
+ \li TextEdit.AlignLeft (Default)
+ \li TextEdit.AlignRight
+ \li TextEdit.AlignHCenter
+ \endlist
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextArea, use the read-only property \c effectiveHorizontalAlignment.
+ */
+ property alias horizontalAlignment: edit.horizontalAlignment
+
+ /*!
+ \qmlproperty enumeration TextArea::effectiveHorizontalAlignment
+
+ Gets the effective horizontal alignment of the text within the TextArea item's width.
+
+ To set/get the default horizontal alignment of TextArea, use the property \c horizontalAlignment.
+
+ */
+ readonly property alias effectiveHorizontalAlignment: edit.effectiveHorizontalAlignment
+
+ /*!
+ \qmlproperty enumeration TextArea::verticalAlignment
+
+ Sets the alignment of the text within the TextArea item's height.
+
+ The valid values for \c verticalAlignment are:
+ \list
+ \li TextEdit.AlignTop
+ \li TextEdit.AlignBottom
+ \li TextEdit.AlignVCenter (Default)
+ \endlist
+ */
+ property alias verticalAlignment: edit.verticalAlignment
+
+ /*!
+ \qmlproperty enumeration TextArea::inputMethodHints
+
+ Provides hints to the input method about the expected content of the text edit and how it
+ should operate.
+
+ The value is a bit-wise combination of flags or Qt.ImhNone if no hints are set.
+
+ The default value is \c Qt.ImhNone.
+
+ Flags that alter behavior are:
+
+ \list
+ \li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords.
+ \li Qt.ImhSensitiveData - Typed text should not be stored by the active input method
+ in any persistent storage like predictive user dictionary.
+ \li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case
+ when a sentence ends.
+ \li Qt.ImhPreferNumbers - Numbers are preferred (but not required).
+ \li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required).
+ \li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required).
+ \li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing.
+
+ \li Qt.ImhDate - The text editor functions as a date field.
+ \li Qt.ImhTime - The text editor functions as a time field.
+ \endlist
+
+ Flags that restrict input (exclusive flags) are:
+
+ \list
+ \li Qt.ImhDigitsOnly - Only digits are allowed.
+ \li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign.
+ \li Qt.ImhUppercaseOnly - Only upper case letter input is allowed.
+ \li Qt.ImhLowercaseOnly - Only lower case letter input is allowed.
+ \li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed.
+ \li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed.
+ \li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed.
+ \endlist
+
+ Masks:
+
+ \list
+ \li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used.
+ \endlist
+ */
+ property alias inputMethodHints: edit.inputMethodHints
+
+ /*!
+ \qmlproperty int TextArea::length
+
+ Returns the total number of plain text characters in the TextArea item.
+
+ As this number doesn't include any formatting markup it may not be the same as the
+ length of the string returned by the \l text property.
+
+ This property can be faster than querying the length the \l text property as it doesn't
+ require any copying or conversion of the TextArea's internal string data.
+ */
+ readonly property alias length: edit.length
+
+ /*!
+ \qmlproperty int TextArea::lineCount
+
+ Returns the total number of lines in the TextArea item.
+ */
+ readonly property alias lineCount: edit.lineCount
+
+ /*!
+ \qmlproperty bool TextArea::readOnly
+
+ Whether the user can interact with the TextArea item.
+
+ The difference from a disabled text field is that it will appear
+ to be active and text can be selected and copied.
+
+ If this property is set to true the text cannot be edited by user interaction.
+
+ By default this property is \c false.
+ */
+ property alias readOnly: edit.readOnly
+
+ /*!
+ \qmlproperty string TextArea::selectedText
+
+ This read-only property provides the text currently selected in the
+ text edit.
+ */
+ readonly property alias selectedText: edit.selectedText
+
+ /*!
+ \qmlproperty int TextArea::selectionEnd
+
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+ */
+ readonly property alias selectionEnd: edit.selectionEnd
+
+ /*!
+ \qmlproperty int TextArea::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionEnd, cursorPosition, selectedText
+ */
+ readonly property alias selectionStart: edit.selectionStart
+
+ /*!
+ \qmlproperty bool TextArea::tabChangesFocus
+
+ This property holds whether Tab changes focus or is accepted as input.
+
+ Defaults to \c false.
+ */
+ property bool tabChangesFocus: false
+
+ /*!
+ \qmlproperty string TextArea::text
+
+ The text to display. If the text format is AutoText the text edit will
+ automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+ */
+ property alias text: edit.text
+
+ /*!
+ \qmlproperty enumeration TextArea::textFormat
+
+ The way the text property should be displayed.
+
+ \list
+ \li TextEdit.AutoText
+ \li TextEdit.PlainText
+ \li TextEdit.RichText
+ \endlist
+
+ The default is TextEdit.PlainText. If the text format is TextEdit.AutoText the text edit
+ will automatically determine whether the text should be treated as
+ rich text. This determination is made using Qt::mightBeRichText().
+ */
+ property alias textFormat: edit.textFormat
+
+ /*!
+ \qmlproperty enumeration TextArea::wrapMode
+
+ Set this property to wrap the text to the TextArea item's width.
+ The text will only wrap if an explicit width has been set.
+
+ \list
+ \li TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
+ \li TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
+ \li TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
+ \li TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
+ \endlist
+
+ The default is \c TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
+ */
+ property alias wrapMode: edit.wrapMode
+
+ /*!
+ \qmlsignal TextArea::linkActivated(string link)
+
+ This signal is emitted when the user clicks on a link embedded in the text.
+ The link must be in rich text or HTML format and the
+ \a link string provides access to the particular link.
+ */
+ signal linkActivated(string link)
+
+ /*!
+ \qmlmethod TextArea::append(string)
+
+ Appends \a string as a new line to the end of the text area.
+ */
+ function append (string) {
+ if (length)
+ string = "\n" + string
+ text += string
+ verticalScrollBar.value = verticalScrollBar.maximumValue
+ }
+
+ /*!
+ \qmlmethod TextArea::copy()
+
+ Copies the currently selected text to the system clipboard.
+ */
+ function copy() {
+ edit.copy();
+ }
+
+ /*!
+ \qmlmethod TextArea::cut()
+
+ Moves the currently selected text to the system clipboard.
+ */
+ function cut() {
+ edit.cut();
+ }
+
+ /*!
+ \qmlmethod TextArea::deselect()
+
+ Removes active text selection.
+ */
+ function deselect() {
+ edit.deselect();
+ }
+
+ /*!
+ \qmlmethod string TextArea::getFormattedText(int start, int end)
+
+ Returns the section of text that is between the \a start and \a end positions.
+
+ The returned text will be formatted according the \l textFormat property.
+ */
+ function getFormattedText(start, end) {
+ return edit.getFormattedText(start, end);
+ }
+
+ /*!
+ \qmlmethod string TextArea::getText(int start, int end)
+
+ Returns the section of text that is between the \a start and \a end positions.
+
+ The returned text does not include any rich text formatting.
+ */
+ function getText(start, end) {
+ return edit.getText(start, end);
+ }
+
+ /*!
+ \qmlmethod TextArea::insert(int position, string text)
+
+ Inserts \a text into the TextArea at position.
+ */
+ function insert(position, text) {
+ edit.insert(position, text);
+ }
+
+ /*!
+ \qmlmethod TextArea::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+ */
+ function isRightToLeft(start, end) {
+ return edit.isRightToLeft(start, end);
+ }
+
+ /*!
+ \qmlmethod TextArea::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
+
+ Moves the cursor to \a position and updates the selection according to the optional \a mode
+ parameter. (To only move the cursor, set the \l cursorPosition property.)
+
+ When this method is called it additionally sets either the
+ selectionStart or the selectionEnd (whichever was at the previous cursor position)
+ to the specified position. This allows you to easily extend and contract the selected
+ text range.
+
+ The selection mode specifies whether the selection is updated on a per character or a per word
+ basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
+
+ \list
+ \li TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+ the previous cursor position) to the specified position.
+ \li TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+ words between the specified position and the previous cursor position. Words partially in the
+ range are included.
+ \endlist
+
+ For example, take this sequence of calls:
+
+ \code
+ cursorPosition = 5
+ moveCursorSelection(9, TextEdit.SelectCharacters)
+ moveCursorSelection(7, TextEdit.SelectCharacters)
+ \endcode
+
+ This moves the cursor to position 5, extend the selection end from 5 to 9
+ and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+ selected (the 6th and 7th characters).
+
+ The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
+ before or on position 5 and extend the selection end to a word boundary on or past position 9.
+ */
+ function moveCursorSelection(position, mode) {
+ edit.moveCursorSelection(position, mode);
+ }
+
+ /*!
+ \qmlmethod TextArea::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+ */
+ function paste() {
+ edit.paste();
+ }
+
+ /*!
+ \qmlmethod int TextArea::positionAt(int x, int y)
+
+ Returns the text position closest to pixel position (\a x, \a y).
+
+ Position 0 is before the first character, position 1 is after the first character
+ but before the second, and so on until position \l {text}.length, which is after all characters.
+ */
+ function positionAt(x, y) {
+ return edit.positionAt(x, y);
+ }
+
+ /*!
+ \qmlmethod rectangle TextArea::positionToRectangle(position)
+
+ Returns the rectangle at the given \a position in the text. The x, y,
+ and height properties correspond to the cursor that would describe
+ that position.
+ */
+ function positionToRectangle(position) {
+ return edit.positionToRectangle(position);
+ }
+
+ /*!
+ \qmlmethod TextArea::redo()
+
+ Redoes the last operation if redo is \l {canRedo}{available}.
+ */
+ function redo() {
+ edit.redo();
+ }
+
+ /*!
+ \qmlmethod string TextArea::remove(int start, int end)
+
+ Removes the section of text that is between the \a start and \a end positions from the TextArea.
+ */
+ function remove(start, end) {
+ return edit.remove(start, end);
+ }
+
+ /*!
+ \qmlmethod TextArea::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+ */
+ function select(start, end) {
+ edit.select(start, end);
+ }
+
+ /*!
+ \qmlmethod TextArea::selectAll()
+
+ Causes all text to be selected.
+ */
+ function selectAll() {
+ edit.selectAll();
+ }
+
+ /*!
+ \qmlmethod TextArea::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+ */
+ function selectWord() {
+ edit.selectWord();
+ }
+
+ /*!
+ \qmlmethod TextArea::undo()
+
+ Undoes the last operation if undo is \l {canUndo}{available}. Deselects any
+ current selection, and updates the selection start to the current cursor
+ position.
+ */
+ function undo() {
+ edit.undo();
+ }
+
+ /*!
+ \qmlproperty color ScrollArea:backgroundColor
+
+ This property sets the background color of the viewport.
+
+ The default value is the base color of the SystemPalette.
+ */
+ property alias backgroundColor: colorRect.color
+
+ /*! \internal */
+ property int documentMargins: 4
+
+ width: 280
+ height: 120
+
+ flickableItem.contentWidth: edit.paintedWidth + (2 * documentMargins)
+ frame: true
+
+ Accessible.role: Accessible.EditableText
+
+ // FIXME: probably implement text interface
+ Accessible.name: text
+
+ TextEdit {
+ id: edit
+ focus: true
+
+ SystemPalette {
+ id: palette
+ colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
+ }
+
+ Rectangle {
+ id: colorRect
+ parent: viewport
+ anchors.fill: parent
+ color: palette.base
+ z: -1
+ }
+
+
+ renderType: Text.NativeRendering
+
+ color: palette.text
+ selectionColor: palette.highlight
+ selectedTextColor: palette.highlightedText
+ wrapMode: TextEdit.WordWrap
+ width: area.viewport.width - (2 * documentMargins)
+ height: Math.max(area.viewport.height - (2 * documentMargins), paintedHeight + (2 * documentMargins))
+ x: documentMargins
+ y: documentMargins
+
+ selectByMouse: true
+ readOnly: false
+
+ KeyNavigation.priority: KeyNavigation.BeforeItem
+ KeyNavigation.tab: area.tabChangesFocus ? area.KeyNavigation.tab : null
+ KeyNavigation.backtab: area.tabChangesFocus ? area.KeyNavigation.backtab : null
+
+ // keep textcursor within scrollarea
+ onCursorPositionChanged: {
+ if (cursorRectangle.y >= flickableItem.contentY + viewport.height - 1.5*cursorRectangle.height - documentMargins)
+ flickableItem.contentY = cursorRectangle.y - viewport.height + 1.5*cursorRectangle.height + documentMargins
+ else if (cursorRectangle.y < flickableItem.contentY)
+ flickableItem.contentY = cursorRectangle.y
+
+ if (cursorRectangle.x >= flickableItem.contentX + viewport.width - documentMargins) {
+ flickableItem.contentX = cursorRectangle.x - viewport.width + documentMargins
+ } else if (cursorRectangle.x < flickableItem.contentX)
+ flickableItem.contentX = cursorRectangle.x
+ }
+ onLinkActivated: area.linkActivated(link)
+
+ MouseArea {
+ parent: area.viewport
+ anchors.fill: parent
+ cursorShape: Qt.IBeamCursor
+ acceptedButtons: Qt.NoButton
+ }
+ }
+
+ Keys.onPressed: {
+ if (event.key == Qt.Key_PageUp) {
+ verticalValue = verticalValue - area.height
+ } else if (event.key == Qt.Key_PageDown)
+ verticalValue = verticalValue + area.height
+ }
+
+}
diff --git a/src/controls/TextField.qml b/src/controls/TextField.qml
new file mode 100644
index 00000000..c209e532
--- /dev/null
+++ b/src/controls/TextField.qml
@@ -0,0 +1,564 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+import "Styles"
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype TextField
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup controls
+ \brief TextField displays a single line of editable plain text
+
+ TextField is used to accept a line of text input. Input constraints
+ can be placed on a TextField item (for example, through a \l validator or \l inputMask),
+ and setting \l echoMode to an appropriate value enables TextField to be used for
+ a password input field.
+
+ \sa TextArea, TextInput
+*/
+
+Control {
+ id: textfield
+
+ /*!
+ \qmlproperty bool TextField::acceptableInput
+
+ This property is always true unless a validator or input mask has been set.
+ If a validator or input mask has been set, this property will only be true
+ if the current text is acceptable to the validator or input mask as a final
+ string (not as an intermediate string).
+
+ \sa validator, inputMask
+
+ */
+ readonly property alias acceptableInput: textInput.acceptableInput // read only
+
+ /*!
+ \qmlproperty bool TextField::activeFocusOnPress
+
+ Whether the TextField should gain active focus on a mouse press. By default this is
+ set to \c true.
+ */
+ property alias activeFocusOnPress: textInput.activeFocusOnPress
+
+ /*!
+ \qmlproperty bool TextField::canPaste
+
+ Returns true if the TextField is writable and the content of the clipboard is
+ suitable for pasting into the TextField.
+ */
+ readonly property alias canPaste: textInput.canPaste
+
+ /*!
+ \qmlproperty bool TextField::canRedo
+
+ Returns true if the TextField is writable and there are \l {undo}{undone}
+ operations that can be redone.
+ */
+ readonly property alias canRedo: textInput.canRedo
+
+ /*!
+ \qmlproperty bool TextField::canUndo
+
+ Returns true if the TextField is writable and there are previous operations
+ that can be undone.
+ */
+ readonly property alias canUndo: textInput.canUndo
+
+ /*!
+ \qmlproperty color TextField::textColor
+
+ The text color.
+ */
+ property alias textColor: textInput.color
+
+ /*!
+ \qmlproperty int TextField::cursorPosition
+ The position of the cursor in the TextField.
+ */
+ property alias cursorPosition: textInput.cursorPosition
+
+ /*!
+ \qmlproperty string TextField::displayText
+
+ This is the text displayed in the TextField.
+
+ If \l echoMode is set to TextInput::Normal, this holds the
+ same value as the TextField::text property. Otherwise,
+ this property holds the text visible to the user, while
+ the \l text property holds the actual entered text.
+ */
+ readonly property alias displayText: textInput.displayText
+
+ /*!
+ \qmlproperty enumeration TextField::echoMode
+
+ Specifies how the text should be displayed in the TextField.
+ \list
+ \li TextInput.Normal - Displays the text as it is. (Default)
+ \li TextInput.Password - Displays asterisks instead of characters.
+ \li TextInput.NoEcho - Displays nothing.
+ \li TextInput.PasswordEchoOnEdit - Displays characters as they are entered
+ while editing, otherwise displays asterisks.
+ \endlist
+ */
+ property alias echoMode: textInput.echoMode
+
+ /*!
+ \qmlproperty font TextField::font
+
+ The font of the TextField.
+ */
+ property alias font: textInput.font
+
+ /*!
+ \qmlproperty enumeration TextField::horizontalAlignment
+
+ Sets the alignment of the text within the TextField item's width.
+
+ By default, the horizontal text alignment follows the natural alignment of the text,
+ for example text that is read from left to right will be aligned to the left.
+
+ The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
+ \c TextInput.AlignHCenter.
+
+ When using the attached property LayoutMirroring::enabled to mirror application
+ layouts, the horizontal alignment of text will also be mirrored. However, the property
+ \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+ of TextField, use the read-only property \c effectiveHorizontalAlignment.
+ */
+ property alias horizontalAlignment: textInput.horizontalAlignment
+
+ /*!
+ \qmlproperty enumeration TextField::effectiveHorizontalAlignment
+
+ Gets the effective horizontal alignment of the text within the TextField item's width.
+
+ To set/get the default horizontal alignment of TextField, use the property \c horizontalAlignment.
+
+ */
+ readonly property alias effectiveHorizontalAlignment: textInput.effectiveHorizontalAlignment
+
+ /*!
+ \qmlproperty enumeration TextField::verticalAlignment
+
+ Sets the alignment of the text within the TextField item's height.
+
+ The valid valid values for \c verticalAlignment are \c TextInput.AlignTop,
+ \c TextInput.AlignBottom \c TextInput.AlignVCenter (default).
+ */
+ property alias verticalAlignment: textInput.verticalAlignment
+
+ /*!
+ \qmlproperty string TextField::inputMask
+
+ Allows you to set an input mask on the TextField, restricting the allowable
+ text inputs. See QLineEdit::inputMask for further details, as the exact
+ same mask strings are used by TextField.
+
+ \sa acceptableInput, validator
+ */
+ property alias inputMask: textInput.inputMask
+
+ /*!
+ \qmlproperty enumeration TextField::inputMethodHints
+
+ Provides hints to the input method about the expected content of the text field and how it
+ should operate.
+
+ The value is a bit-wise combination of flags, or Qt.ImhNone if no hints are set.
+
+ The default value is Qt.ImhNone.
+
+ Flags that alter behavior are:
+
+ \list
+ \li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords.
+ This is automatically set when setting echoMode to \c TextInput.Password.
+ \li Qt.ImhSensitiveData - Typed text should not be stored by the active input method
+ in any persistent storage like predictive user dictionary.
+ \li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case
+ when a sentence ends.
+ \li Qt.ImhPreferNumbers - Numbers are preferred (but not required).
+ \li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required).
+ \li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required).
+ \li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing.
+
+ \li Qt.ImhDate - The text editor functions as a date field.
+ \li Qt.ImhTime - The text editor functions as a time field.
+ \endlist
+
+ Flags that restrict input (exclusive flags) are:
+
+ \list
+ \li Qt.ImhDigitsOnly - Only digits are allowed.
+ \li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign.
+ \li Qt.ImhUppercaseOnly - Only upper case letter input is allowed.
+ \li Qt.ImhLowercaseOnly - Only lower case letter input is allowed.
+ \li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed.
+ \li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed.
+ \li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed.
+ \endlist
+
+ Masks:
+
+ \list
+ \li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used.
+ \endlist
+ */
+ property alias inputMethodHints: textInput.inputMethodHints
+
+ /*!
+ \qmlproperty int TextField::length
+
+ Returns the total number of characters in the TextField item.
+
+ If the TextField has an inputMask the length will include mask characters and may differ
+ from the length of the string returned by the \l text property.
+
+ This property can be faster than querying the length the \l text property as it doesn't
+ require any copying or conversion of the TextField's internal string data.
+ */
+ readonly property alias length: textInput.length
+
+ /*!
+ \qmlproperty int TextField::maximumLength
+ The maximum permitted length of the text in the TextField.
+
+ If the text is too long, it is truncated at the limit.
+ */
+ property alias maximumLength: textInput.maximumLength
+
+ /*!
+ \qmlproperty string TextField::placeholderText
+
+ The text that is shown in the text field when the text field is empty
+ and has no focus.
+ */
+ property alias placeholderText: placeholderTextComponent.text
+
+ /*!
+ \qmlproperty bool TextField::readOnly
+
+ Sets whether user input can modify the contents of the TextField.
+ The difference from a disabled text field is that it will appear
+ to be active and text can be selected and copied.
+
+ If readOnly is set to true, then user input will not affect the text
+ property. Any bindings or attempts to set the text property will still
+ work.
+ */
+ property alias readOnly: textInput.readOnly
+
+ /*!
+ \qmlproperty string TextField::selectedText
+
+ This read-only property provides the text currently selected in the
+ text input.
+
+ It is equivalent to the following snippet, but is faster and easier
+ to use.
+
+ \js
+ myTextField.text.toString().substring(myTextField.selectionStart, myTextField.selectionEnd);
+ \endjs
+ */
+ readonly property alias selectedText: textInput.selectedText
+
+ /*!
+ \qmlproperty int TextField::selectionEnd
+
+ The cursor position after the last character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionStart, cursorPosition, selectedText
+ */
+ readonly property alias selectionEnd: textInput.selectionEnd
+
+ /*!
+ \qmlproperty int TextField::selectionStart
+
+ The cursor position before the first character in the current selection.
+
+ This property is read-only. To change the selection, use select(start,end),
+ selectAll(), or selectWord().
+
+ \sa selectionEnd, cursorPosition, selectedText
+ */
+ readonly property alias selectionStart: textInput.selectionStart
+
+ /*!
+ \qmlproperty string TextField::text
+
+ The text in the TextField.
+ */
+ property alias text: textInput.text
+
+ /*!
+ \qmlproperty Validator TextField::validator
+
+ Allows you to set a validator on the TextField. When a validator is set
+ the TextField will only accept input which leaves the text property in
+ an or intermediate state. The accepted signal will only be sent
+ if the text is in an acceptable state when enter is pressed.
+
+ Currently supported validators are IntValidator, DoubleValidator and
+ RegExpValidator. An example of using validators is shown below, which allows
+ input of integers between 11 and 31 into the text input:
+
+ \code
+ import QtQuick 2.0
+ import QtQuick.Controls 1.0
+
+ TextField {
+ validator: IntValidator {bottom: 11; top: 31;}
+ focus: true
+ }
+ \endcode
+
+ \sa acceptableInput, inputMask
+ */
+ property alias validator: textInput.validator
+
+ /*!
+ \qmlsignal TextField::accepted()
+
+ This signal is emitted when the Return or Enter key is pressed.
+ Note that if there is a \l validator or \l inputMask set on the text
+ field, the signal will only be emitted if the input is in an acceptable
+ state.
+ */
+ signal accepted()
+
+ /*!
+ \qmlmethod TextField::copy()
+
+ Copies the currently selected text to the system clipboard.
+ */
+ function copy() {
+ textInput.copy()
+ }
+
+ /*!
+ \qmlmethod TextField::cut()
+
+ Moves the currently selected text to the system clipboard.
+ */
+ function cut() {
+ textInput.cut()
+ }
+
+ /*!
+ \qmlmethod TextField::deselect()
+
+ Removes active text selection.
+ */
+ function deselect() {
+ textInput.deselect();
+ }
+
+ /*!
+ \qmlmethod string TextField::getText(int start, int end)
+
+ Removes the section of text that is between the \a start and \a end positions from the TextField.
+ */
+ function getText(start, end) {
+ return textInput.getText(start, end);
+ }
+
+ /*!
+ \qmlmethod TextField::insert(int position, string text)
+
+ Inserts \a text into the TextField at position.
+ */
+ function insert(position, text) {
+ textInput.insert(position, text);
+ }
+
+ /*!
+ \qmlmethod bool TextField::isRightToLeft(int start, int end)
+
+ Returns true if the natural reading direction of the editor text
+ found between positions \a start and \a end is right to left.
+ */
+ function isRightToLeft(start, end) {
+ return textInput.isRightToLeft(start, end);
+ }
+
+ /*!
+ \qmlmethod TextField::paste()
+
+ Replaces the currently selected text by the contents of the system clipboard.
+ */
+ function paste() {
+ textInput.paste()
+ }
+
+ /*!
+ \qmlmethod TextField::redo()
+
+ Redoes the last operation if redo is \l {canRedo}{available}.
+ */
+ function redo() {
+ textInput.redo();
+ }
+
+ /*!
+ \qmlmethod TextField::select(int start, int end)
+
+ Causes the text from \a start to \a end to be selected.
+
+ If either start or end is out of range, the selection is not changed.
+
+ After calling this, selectionStart will become the lesser
+ and selectionEnd will become the greater (regardless of the order passed
+ to this method).
+
+ \sa selectionStart, selectionEnd
+ */
+ function select(start, end) {
+ textInput.select(start, end)
+ }
+
+ /*!
+ \qmlmethod TextField::selectAll()
+
+ Causes all text to be selected.
+ */
+ function selectAll() {
+ textInput.selectAll()
+ }
+
+ /*!
+ \qmlmethod TextField::selectWord()
+
+ Causes the word closest to the current cursor position to be selected.
+ */
+ function selectWord() {
+ textInput.selectWord()
+ }
+
+ /*!
+ \qmlmethod TextField::undo()
+
+ Undoes the last operation if undo is \l {canUndo}{available}. Deselects any
+ current selection, and updates the selection start to the current cursor
+ position.
+ */
+ function undo() {
+ textInput.undo();
+ }
+
+ /*! \internal */
+ property alias __containsMouse: mouseArea.containsMouse
+
+ /*! \internal */
+ property alias __contentHeight: textInput.contentHeight
+
+ /*! \internal */
+ property alias __contentWidth: textInput.contentWidth
+
+ /*! \internal */
+ style: Qt.createComponent(Settings.THEME_PATH + "/TextFieldStyle.qml", textInput)
+
+ /*! \internal */
+ onFocusChanged: {
+ if (textfield.activeFocus)
+ textInput.forceActiveFocus();
+ }
+
+ Accessible.name: text
+ Accessible.role: Accessible.EditableText
+ Accessible.description: placeholderText
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: textfield.forceActiveFocus()
+ }
+
+ TextInput {
+ id: textInput
+ selectByMouse: true
+ selectionColor: __panel ? __panel.selectionColor : "darkred"
+ selectedTextColor: __panel ? __panel.selectedTextColor : "white"
+
+ font: __panel ? __panel.font : font
+ anchors.leftMargin: __panel ? __panel.leftMargin : 0
+ anchors.topMargin: __panel ? __panel.topMargin : 0
+ anchors.rightMargin: __panel ? __panel.rightMargin : 0
+ anchors.bottomMargin: __panel ? __panel.bottomMargin : 0
+
+ anchors.fill: parent
+ verticalAlignment: Text.AlignVCenter
+
+ color: __panel ? __panel.foregroundColor : "darkgray"
+ clip: true
+ renderType: Text.NativeRendering
+
+ onAccepted: textfield.accepted()
+ }
+
+ Text {
+ id: placeholderTextComponent
+ anchors.fill: textInput
+ font: textInput.font
+ horizontalAlignment: textInput.horizontalAlignment
+ verticalAlignment: textInput.verticalAlignment
+ opacity: !textInput.text.length && !textInput.activeFocus ? 1 : 0
+ color: __panel ? __panel.placeholderTextColor : "darkgray"
+ clip: true
+ elide: Text.ElideRight
+ renderType: Text.NativeRendering
+ Behavior on opacity { NumberAnimation { duration: 90 } }
+ }
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.IBeamCursor
+ acceptedButtons: Qt.NoButton
+ }
+}
diff --git a/src/controls/ToolBar.qml b/src/controls/ToolBar.qml
new file mode 100644
index 00000000..2c359239
--- /dev/null
+++ b/src/controls/ToolBar.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0
+
+/*!
+ \qmltype ToolBar
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup applicationwindow
+ \brief ToolBar is for containing ToolButton and related controls.
+
+ The common way of using ToolBar is in relation to \l ApplicationWindow.
+ It provides styling and is generally designed to work well with ToolButton as well
+ as other controls.
+
+ Note that the ToolBar does not provide a layout of its own but requires you to
+ position its contents, for instance by creating a Row.
+
+ \code
+ ApplicationWindow {
+ toolBar: ToolBar {
+ Row {
+ ToolButton { ... }
+ ToolButton { ... }
+ ToolButton { ... }
+ }
+ }
+ }
+ \endcode
+*/
+
+Item {
+ width: toolbar.width
+ height: toolbar.height
+ implicitHeight: toolbar.implicitHeight
+ implicitWidth: parent ? parent.width : toolbar.implicitWidth
+ Accessible.role: Accessible.ToolBar
+ StyleItem {
+ id: toolbar
+ anchors.fill: parent
+ elementType: "toolbar"
+ }
+}
diff --git a/src/controls/ToolButton.qml b/src/controls/ToolButton.qml
new file mode 100644
index 00000000..d3fd441a
--- /dev/null
+++ b/src/controls/ToolButton.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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 2.0
+import QtQuick.Controls 1.0
+import QtQuick.Controls.Private 1.0 as Private
+import "Styles/Settings.js" as Settings
+
+/*!
+ \qmltype ToolButton
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup applicationwindow
+ \brief ToolButton provides a button type that is typically used within a ToolBar
+
+ ToolButton is functionally similar to \l Button but can provide a look that is more
+ suitable within a \l ToolBar.
+
+ \code
+ ToolButton {
+ iconSource: "edit-cut.png"
+ }
+ \endcode
+*/
+
+Private.BasicButton {
+ id: button
+
+ /*! The image label source. */
+ property url iconSource
+
+ /*! The label text. */
+ property string text
+
+ Image {
+ id: image
+ anchors.centerIn: parent
+ source: button.iconSource
+ width: Math.min(button.width, image.implicitWidth)
+ height: Math.min(button.height, image.implicitHeight)
+ fillMode: Image.PreserveAspectFit
+ }
+ Accessible.name: text
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/ToolButtonStyle.qml", button)
+}
diff --git a/src/controls/controls.pro b/src/controls/controls.pro
new file mode 100644
index 00000000..7af5a965
--- /dev/null
+++ b/src/controls/controls.pro
@@ -0,0 +1,45 @@
+CXX_MODULE = qml
+TARGET = plugin
+TARGETPATH = QtQuick/Controls
+
+QT += qml quick widgets gui-private core-private
+
+QMAKE_DOCS = $$PWD/doc/qtquickcontrols.qdocconf
+
+QML_FILES = \
+ AbstractCheckable.qml \
+ ApplicationWindow.qml \
+ Button.qml \
+ CheckBox.qml \
+ ComboBox.qml \
+ ContextMenu.qml \
+ GroupBox.qml \
+ Label.qml \
+ MenuBar.qml \
+ Menu.qml \
+ Page.qml \
+ PageAnimation.qml \
+ PageStack.qml \
+ PageTransition.qml \
+ ProgressBar.qml \
+ RadioButton.qml \
+ ScrollArea.qml \
+ Slider.qml \
+ SpinBox.qml \
+ Splitter.qml \
+ StatusBar.qml \
+ Tab.qml \
+ TabFrame.qml \
+ TableView.qml \
+ TableViewColumn.qml \
+ TextArea.qml \
+ TextField.qml \
+ ToolBar.qml \
+ ToolButton.qml
+
+include(plugin.pri)
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+
+load(qml_plugin)
diff --git a/src/controls/doc/images/placeholder.png b/src/controls/doc/images/placeholder.png
new file mode 100644
index 00000000..c64ff5bd
--- /dev/null
+++ b/src/controls/doc/images/placeholder.png
Binary files differ
diff --git a/src/controls/doc/images/tableview.png b/src/controls/doc/images/tableview.png
new file mode 100644
index 00000000..e7e5e27d
--- /dev/null
+++ b/src/controls/doc/images/tableview.png
Binary files differ
diff --git a/src/controls/doc/qtquickcontrols.qdocconf b/src/controls/doc/qtquickcontrols.qdocconf
new file mode 100644
index 00000000..3977be50
--- /dev/null
+++ b/src/controls/doc/qtquickcontrols.qdocconf
@@ -0,0 +1,90 @@
+include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+
+# Name of the project.
+project = QtQuickControls
+description = Qt Quick Controls Documentation
+
+depends = qtqml qtquick qtwidgets qtdoc
+
+# Directories in which to search for files to document and images.
+# By default set to the root directory of the project for sources
+# and headers and qdoc will therefore generate output for each file.
+# Images should be placed in <rootdir>/dic/images and examples in
+# <rootdir>/examples.
+# Paths are relative to the location of this file.
+
+exampledirs += ../../../examples/
+
+headerdirs += ../
+
+sourcedirs += ../
+
+sources += ../../private/qstyleitem.cpp \
+ ../../private/BasicButton.qml \
+ ../../private/ButtonBehavior.qml \
+ ../../private/FocusFrame.qml \
+ ../../private/ModalPopupBehavior.qml \
+ ../../private/PageSlideTransition.qml \
+ ../../private/ScrollAreaHelper.qml \
+ ../../private/ScrollBar.qml \
+ ../../private/SplitterBase.qml \
+ ../../private/TabBar.qml \
+ ../../private/Control.qml \
+ ../../styles/Style.qml \
+ ../../styles/ButtonStyle.qml \
+ ../../styles/CheckBoxStyle.qml \
+ ../../styles/ComboBoxStyle.qml \
+ ../../styles/GroupBoxStyle.qml \
+ ../../styles/MenuBarItemStyle.qml \
+ ../../styles/MenuBarStyle.qml \
+ ../../styles/MenuFrameStyle.qml \
+ ../../styles/MenuItemStyle.qml \
+ ../../styles/ProgressBarStyle.qml \
+ ../../styles/RadioButtonStyle.qml \
+ ../../styles/ScrollAreaStyle.qml \
+ ../../styles/ScrollBarStyle.qml \
+ ../../styles/SliderStyle.qml \
+ ../../styles/SpinBoxStyle.qml \
+ ../../styles/TabFrameStyle.qml \
+ ../../styles/TextFieldStyle.qml \
+ ../../styles/ToolBarStyle.qml \
+ ../../styles/ToolButtonStyle.qml
+
+imagedirs += images
+
+# The following parameters are for creating a qhp file, the qhelpgenerator
+# program can convert the qhp file into a qch file which can be opened in
+# Qt Assistant and/or Qt Creator.
+
+# Defines the name of the project. You cannot use operators (+, =, -) in
+# the name. Properties for this project are set using a qhp.<projectname>.property
+# format.
+qhp.projects = qtquickcontrols
+
+# Sets the name of the output qhp file.
+qhp.qtquickcontrols.file = qtquickcontrols.qhp
+
+# Namespace for the output file. This namespace is used to distinguish between
+# different documentation files in Creator/Assistant.
+qhp.qtquickcontrols.namespace = qtquickcontrols.100
+
+# Title for the package, will be the main title for the package in
+# Assistant/Creator.
+qhp.qtquickcontrols.indexTitle = Qt Quick Controls
+
+# Extra files to add to the output which are not linked to from anywhere
+# using a qdoc \l command.
+#qhp.qtquickcontrols.extraFiles = style/qtquickcontrols.css
+
+# Only update the name of the project for the next variables.
+qhp.qtquickcontrols.virtualFolder = qtquickcontrols
+
+qhp.qtquickcontrols.subprojects = qtquickcontrolsqmltypes styleqmltypes
+qhp.qtquickcontrols.subprojects.qtquickcontrolsqmltypes.title = Qt Quick Controls QML Types
+qhp.qtquickcontrols.subprojects.qtquickcontrolsqmltypes.indexTitle = Qt Quick Controls QML Types
+qhp.qtquickcontrols.subprojects.qtquickcontrolsqmltypes.selectors = class fake:headerfile
+qhp.qtquickcontrols.subprojects.qtquickcontrolsqmltypes.sortPages = true
+qhp.qtquickcontrols.subprojects.styleqmltypes.title = Styles QML Types
+qhp.qtquickcontrols.subprojects.styleqmltypes.indexTitle = Qt Quick Controls Styles QML Types
+qhp.qtquickcontrols.subprojects.styleqmltypes.selectors = class fake:headerfile
+qhp.qtquickcontrols.subprojects.styleqmltypes.sortPages = true
diff --git a/src/controls/doc/src/applicationwindow.qdoc b/src/controls/doc/src/applicationwindow.qdoc
new file mode 100644
index 00000000..f9e2d97f
--- /dev/null
+++ b/src/controls/doc/src/applicationwindow.qdoc
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group applicationwindow
+ \title Application Window
+*/
diff --git a/src/controls/doc/src/containers.qdoc b/src/controls/doc/src/containers.qdoc
new file mode 100644
index 00000000..6a0ab02d
--- /dev/null
+++ b/src/controls/doc/src/containers.qdoc
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group containers
+ \title Layout and Containers
+*/
diff --git a/src/controls/doc/src/controls.qdoc b/src/controls/doc/src/controls.qdoc
new file mode 100644
index 00000000..d1e4d052
--- /dev/null
+++ b/src/controls/doc/src/controls.qdoc
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group controls
+ \title Buttons and Controls
+*/
diff --git a/src/controls/doc/src/indicators.qdoc b/src/controls/doc/src/indicators.qdoc
new file mode 100644
index 00000000..f31dec9e
--- /dev/null
+++ b/src/controls/doc/src/indicators.qdoc
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group indicators
+ \title Status Indicators
+*/
diff --git a/src/controls/doc/src/menus.qdoc b/src/controls/doc/src/menus.qdoc
new file mode 100644
index 00000000..ae8554ea
--- /dev/null
+++ b/src/controls/doc/src/menus.qdoc
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group menus
+ \title Application Menus
+*/
diff --git a/src/controls/doc/src/navigation.qdoc b/src/controls/doc/src/navigation.qdoc
new file mode 100644
index 00000000..b1bd8ef8
--- /dev/null
+++ b/src/controls/doc/src/navigation.qdoc
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group navigation
+ \title Application Navigation
+*/
diff --git a/src/controls/doc/src/qtquickcontrols-examples.qdoc b/src/controls/doc/src/qtquickcontrols-examples.qdoc
new file mode 100644
index 00000000..04fa1f4a
--- /dev/null
+++ b/src/controls/doc/src/qtquickcontrols-examples.qdoc
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group qtquickcontrols_examples
+ \ingroup all-examples
+ \title Qt Quick Controls Examples
+ \brief Demonstrates the ... functionality provided by Qt.
+*/
diff --git a/src/controls/doc/src/qtquickcontrols-index.qdoc b/src/controls/doc/src/qtquickcontrols-index.qdoc
new file mode 100644
index 00000000..1f3ab44e
--- /dev/null
+++ b/src/controls/doc/src/qtquickcontrols-index.qdoc
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtquickcontrols-index.html
+ \title Qt Quick Controls
+
+ \brief The Qt Quick Controls module is an add-on module of Qt.
+
+ \image placeholder.png
+
+ \section1 Getting started
+
+ The QML types can be imported into your applciation using the following import statement in your \c {.qml} file.
+
+ \code
+ import QtQuick.Controls 1.0
+ import QtQuick.Controls.Styles 1.0
+ \endcode
+
+ \section1 Components
+
+ \section2 Application
+ \list
+ \li \l{Application Window}{Window}
+ \li \l{Application Menus}{Menus}
+ \li \l{Application Navigation}{Navigation}
+ \endlist
+
+ \section2 Controls and Layout
+ \list
+ \li \l{Buttons and Controls}
+ \li \l{Layout and Containers}
+ \li \l{Tables}
+ \li \l{Status Indicators}
+ \endlist
+
+ \section1 Related information
+
+ \section2 Guides
+ \list
+ \li \l{Qt Quick Controls Overview}
+ \endlist
+
+ \section2 Reference
+ \list
+ \li \l{Qt Quick Controls QML Types}{Qt Quick Controls QML Types}
+ \li \l{Qt Quick Controls Styles QML Types}{Qt Quick Controls Styles QML Types}
+ \endlist
+
+ \section2 Examples
+ \list
+ \li \l{Qt Quick Controls Examples}
+ \endlist
+*/
diff --git a/src/controls/doc/src/qtquickcontrols-overview.qdoc b/src/controls/doc/src/qtquickcontrols-overview.qdoc
new file mode 100644
index 00000000..82da0b22
--- /dev/null
+++ b/src/controls/doc/src/qtquickcontrols-overview.qdoc
@@ -0,0 +1,32 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtquickcontrols-overview.html
+ \title Qt Quick Controls Overview
+ \brief A set of APIs for working with ...
+*/
diff --git a/src/controls/doc/src/qtquickcontrols.qdoc b/src/controls/doc/src/qtquickcontrols.qdoc
new file mode 100644
index 00000000..ddbfc5d6
--- /dev/null
+++ b/src/controls/doc/src/qtquickcontrols.qdoc
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmlmodule QtQuick.Controls 1
+ \title Qt Quick Controls QML Types
+ \ingroup qmlmodules
+ \brief Provides QML types for qt quick controls support.
+
+ This is just a demo page.
+
+ \section1 Overview
+
+ The QML types for Qt Quick Controls support the basic use cases such as:
+ \list
+ \li sth 1,
+ \li sth 2,
+ \endlist
+
+ \section1 QML types
+*/
diff --git a/src/controls/doc/src/styles.qdoc b/src/controls/doc/src/styles.qdoc
new file mode 100644
index 00000000..36dc302f
--- /dev/null
+++ b/src/controls/doc/src/styles.qdoc
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmlmodule QtQuick.Controls.Styles 1
+ \title Qt Quick Controls Styles QML Types
+ \ingroup qmlmodules
+ \brief Provides QML types for qt quick controls styles support.
+
+ This is just a demo page.
+
+ \section1 Overview
+
+ The QML types for Qt Quick Controls Styles support the basic use cases such as:
+ \list
+ \li sth 1,
+ \li sth 2,
+ \endlist
+
+ \section1 QML types
+*/
diff --git a/src/controls/doc/src/views.qdoc b/src/controls/doc/src/views.qdoc
new file mode 100644
index 00000000..c92cb7da
--- /dev/null
+++ b/src/controls/doc/src/views.qdoc
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group views
+ \title Views
+
+ \image placeholder.png
+*/
diff --git a/src/controls/plugin.cpp b/src/controls/plugin.cpp
new file mode 100644
index 00000000..d8bdd9ef
--- /dev/null
+++ b/src/controls/plugin.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include <qqml.h>
+#include "plugin_p.h"
+#include "qtaction_p.h"
+#include "qtexclusivegroup_p.h"
+#include "qtmenu_p.h"
+#include "qtmenubar_p.h"
+#include "qquicklinearlayout_p.h"
+#include "qpagestatus.h"
+#include <qqmlextensionplugin.h>
+
+#include <qqmlengine.h>
+#include <qquickimageprovider.h>
+#include <QtWidgets/QApplication>
+#include <QtQuick/QQuickWindow>
+#include <QImage>
+
+QT_BEGIN_NAMESPACE
+
+// Load icons from desktop theme
+class DesktopIconProvider : public QQuickImageProvider
+{
+public:
+ DesktopIconProvider()
+ : QQuickImageProvider(QQuickImageProvider::Pixmap)
+ {
+ }
+
+ QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
+ {
+ Q_UNUSED(requestedSize);
+ Q_UNUSED(size);
+ int pos = id.lastIndexOf('/');
+ QString iconName = id.right(id.length() - pos);
+ int width = requestedSize.width();
+ return QIcon::fromTheme(iconName).pixmap(width);
+ }
+};
+
+void StylePlugin::registerTypes(const char *uri)
+{
+ qmlRegisterType<QtAction>(uri, 1, 0, "Action");
+ qmlRegisterType<QtExclusiveGroup>(uri, 1, 0, "ExclusiveGroup");
+ qmlRegisterType<QtMenu>(uri, 1, 0, "MenuPrivate");
+ qmlRegisterType<QtMenuBar>(uri, 1, 0, "MenuBarPrivate");
+ qmlRegisterType<QtMenuItem>(uri, 1, 0, "MenuItem");
+ qmlRegisterType<QtMenuSeparator>(uri, 1, 0, "MenuSeparator");
+ qmlRegisterUncreatableType<QtMenuBase>(uri, 1, 0, "NativeMenuBase",
+ QLatin1String("Do not create objects of type NativeMenuBase"));
+
+ qmlRegisterType<QQuickComponentsRowLayout>(uri, 1, 0, "RowLayout");
+ qmlRegisterType<QQuickComponentsColumnLayout>(uri, 1, 0, "ColumnLayout");
+ qmlRegisterUncreatableType<QQuickComponentsLayout>(uri, 1, 0, "Layout",
+ QLatin1String("Do not create objects of type Layout"));
+
+ qmlRegisterUncreatableType<QPageStatus>(uri, 1, 0, "PageStatus", QLatin1String("Do not create objects of type PageStatus"));
+}
+
+void StylePlugin::initializeEngine(QQmlEngine *engine, const char *uri)
+{
+ Q_UNUSED(uri);
+ engine->addImageProvider("desktoptheme", new DesktopIconProvider);
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/plugin.json b/src/controls/plugin.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/src/controls/plugin.json
@@ -0,0 +1 @@
+{}
diff --git a/src/controls/plugin.pri b/src/controls/plugin.pri
new file mode 100644
index 00000000..5637e75c
--- /dev/null
+++ b/src/controls/plugin.pri
@@ -0,0 +1,27 @@
+HEADERS += \
+ $$PWD/qquicklayout_p.h \
+ $$PWD/qquicklayoutengine_p.h \
+ $$PWD/qquicklinearlayout_p.h \
+ $$PWD/plugin_p.h \
+ $$PWD/qtaction_p.h \
+ $$PWD/qtexclusivegroup_p.h \
+ $$PWD/qtmenu_p.h \
+ $$PWD/qtmenubar_p.h \
+ $$PWD/qtmenuitem_p.h \
+ $$PWD/qtmenupopupwindow_p.h \
+ $$PWD/qpagestatus.h
+
+SOURCES += \
+ $$PWD/qquicklayout.cpp \
+ $$PWD/qquicklayoutengine.cpp \
+ $$PWD/qquicklinearlayout.cpp \
+ $$PWD/plugin.cpp \
+ $$PWD/qtaction.cpp \
+ $$PWD/qtexclusivegroup.cpp \
+ $$PWD/qtmenu.cpp \
+ $$PWD/qtmenubar.cpp \
+ $$PWD/qtmenuitem.cpp \
+ $$PWD/qtmenupopupwindow.cpp
+
+OTHER_FILES += \
+ $$PWD/plugin.json
diff --git a/src/controls/plugin_p.h b/src/controls/plugin_p.h
new file mode 100644
index 00000000..c6c3fee3
--- /dev/null
+++ b/src/controls/plugin_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QSTYLEPLUGIN_P_H
+#define QSTYLEPLUGIN_P_H
+
+#include <QQmlExtensionPlugin>
+#include <QtCore/QTimer>
+#include <QtWidgets/QFileSystemModel>
+
+QT_BEGIN_NAMESPACE
+
+class StylePlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.playground.qtquickcontrols.QQmlExtensionInterface" FILE "plugin.json")
+public:
+ void registerTypes(const char *uri);
+ void initializeEngine(QQmlEngine *engine, const char *uri);
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTYLEPLUGIN_P_H
diff --git a/src/controls/plugins.qmltypes b/src/controls/plugins.qmltypes
new file mode 100644
index 00000000..734c3878
--- /dev/null
+++ b/src/controls/plugins.qmltypes
@@ -0,0 +1,405 @@
+import QtQuick.tooling 1.1
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated with the command 'qmlplugindump QtDesktop 1.0 imports/'.
+
+Module {
+ Component {
+ name: "QDesktopItem"
+ prototype: "QObject"
+ exports: ["Desktop 1.0"]
+ Property { name: "screenWidth"; type: "int"; isReadonly: true }
+ Property { name: "screenHeight"; type: "int"; isReadonly: true }
+ Property { name: "availableWidth"; type: "int"; isReadonly: true }
+ Property { name: "availableHeight"; type: "int"; isReadonly: true }
+ Property { name: "screenCount"; type: "int"; isReadonly: true }
+ Signal { name: "screenGeometryChanged" }
+ Signal { name: "availableGeometryChanged" }
+ Method {
+ name: "screenGeometry"
+ type: "QRect"
+ Parameter { name: "screen"; type: "int" }
+ }
+ Method {
+ name: "availableGeometry"
+ type: "QRect"
+ Parameter { name: "screen"; type: "int" }
+ }
+ }
+ Component {
+ name: "QFileDialogItem"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["FileDialog 1.0"]
+ Property { name: "visible"; type: "bool" }
+ Property { name: "modal"; type: "bool" }
+ Property { name: "title"; type: "string" }
+ Property { name: "selectExisting"; type: "bool" }
+ Property { name: "selectMultiple"; type: "bool" }
+ Property { name: "selectFolder"; type: "bool" }
+ Property { name: "folder"; type: "string" }
+ Property { name: "nameFilters"; type: "QStringList" }
+ Property { name: "filePath"; type: "string"; isReadonly: true }
+ Property { name: "filePaths"; type: "QStringList"; isReadonly: true }
+ Signal { name: "modalityChanged" }
+ Signal { name: "accepted" }
+ Signal { name: "rejected" }
+ Method { name: "open" }
+ Method { name: "close" }
+ }
+ Component {
+ name: "QFileSystemModel"
+ prototype: "QAbstractItemModel"
+ exports: ["FileSystemModel 1.0"]
+ Property { name: "resolveSymlinks"; type: "bool" }
+ Property { name: "readOnly"; type: "bool" }
+ Property { name: "nameFilterDisables"; type: "bool" }
+ Signal {
+ name: "rootPathChanged"
+ Parameter { name: "newPath"; type: "string" }
+ }
+ Signal {
+ name: "fileRenamed"
+ Parameter { name: "path"; type: "string" }
+ Parameter { name: "oldName"; type: "string" }
+ Parameter { name: "newName"; type: "string" }
+ }
+ Signal {
+ name: "directoryLoaded"
+ Parameter { name: "path"; type: "string" }
+ }
+ }
+ Component {
+ name: "QQuickComponentsColumnLayout"
+ defaultProperty: "data"
+ prototype: "QQuickComponentsLinearLayout"
+ exports: ["ColumnLayout 1.0"]
+ }
+ Component {
+ name: "QQuickComponentsLayout"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["Layout 1.0"]
+ attachedType: "QQuickComponentsLayoutAttached"
+ Enum {
+ name: "SizePolicy"
+ values: {
+ "Fixed": 0,
+ "Expanding": 1
+ }
+ }
+ }
+ Component {
+ name: "QQuickComponentsLayoutAttached"
+ prototype: "QObject"
+ Property { name: "minimumWidth"; type: "double" }
+ Property { name: "minimumHeight"; type: "double" }
+ Property { name: "maximumWidth"; type: "double" }
+ Property { name: "maximumHeight"; type: "double" }
+ Property { name: "verticalSizePolicy"; type: "QQuickComponentsLayout::SizePolicy" }
+ Property { name: "horizontalSizePolicy"; type: "QQuickComponentsLayout::SizePolicy" }
+ }
+ Component {
+ name: "QQuickComponentsLinearLayout"
+ defaultProperty: "data"
+ prototype: "QQuickComponentsLayout"
+ Property { name: "spacing"; type: "double" }
+ Signal { name: "orientationChanged" }
+ }
+ Component {
+ name: "QQuickComponentsPrivate"
+ prototype: "QObject"
+ exports: ["PrivateHelper 1.0"]
+ Method {
+ name: "showToolTip"
+ Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
+ Parameter { name: "pos"; type: "QPointF" }
+ Parameter { name: "text"; type: "string" }
+ }
+ Method { name: "hideToolTip" }
+ }
+ Component {
+ name: "QQuickComponentsRowLayout"
+ defaultProperty: "data"
+ prototype: "QQuickComponentsLinearLayout"
+ exports: ["RowLayout 1.0"]
+ }
+ Component {
+ name: "QRangeModel"
+ prototype: "QObject"
+ exports: ["RangeModel 1.0"]
+ Property { name: "value"; type: "double" }
+ Property { name: "minimumValue"; type: "double" }
+ Property { name: "maximumValue"; type: "double" }
+ Property { name: "stepSize"; type: "double" }
+ Property { name: "position"; type: "double" }
+ Property { name: "positionAtMinimum"; type: "double" }
+ Property { name: "positionAtMaximum"; type: "double" }
+ Property { name: "inverted"; type: "bool" }
+ Signal {
+ name: "valueChanged"
+ Parameter { name: "value"; type: "double" }
+ }
+ Signal {
+ name: "positionChanged"
+ Parameter { name: "position"; type: "double" }
+ }
+ Signal {
+ name: "stepSizeChanged"
+ Parameter { name: "stepSize"; type: "double" }
+ }
+ Signal {
+ name: "invertedChanged"
+ Parameter { name: "inverted"; type: "bool" }
+ }
+ Signal {
+ name: "minimumChanged"
+ Parameter { name: "min"; type: "double" }
+ }
+ Signal {
+ name: "maximumChanged"
+ Parameter { name: "max"; type: "double" }
+ }
+ Signal {
+ name: "positionAtMinimumChanged"
+ Parameter { name: "min"; type: "double" }
+ }
+ Signal {
+ name: "positionAtMaximumChanged"
+ Parameter { name: "max"; type: "double" }
+ }
+ Method { name: "toMinimum" }
+ Method { name: "toMaximum" }
+ Method {
+ name: "setValue"
+ Parameter { name: "value"; type: "double" }
+ }
+ Method {
+ name: "setPosition"
+ Parameter { name: "position"; type: "double" }
+ }
+ Method {
+ name: "valueForPosition"
+ type: "double"
+ Parameter { name: "position"; type: "double" }
+ }
+ Method {
+ name: "positionForValue"
+ type: "double"
+ Parameter { name: "value"; type: "double" }
+ }
+ }
+ Component {
+ name: "QStyleItem"
+ defaultProperty: "data"
+ prototype: "QQuickPaintedItem"
+ exports: ["StyleItem 1.0"]
+ Property { name: "sunken"; type: "bool" }
+ Property { name: "raised"; type: "bool" }
+ Property { name: "active"; type: "bool" }
+ Property { name: "selected"; type: "bool" }
+ Property { name: "hasFocus"; type: "bool" }
+ Property { name: "on"; type: "bool" }
+ Property { name: "hover"; type: "bool" }
+ Property { name: "horizontal"; type: "bool" }
+ Property { name: "elementType"; type: "string" }
+ Property { name: "text"; type: "string" }
+ Property { name: "activeControl"; type: "string" }
+ Property { name: "info"; type: "string" }
+ Property { name: "style"; type: "string"; isReadonly: true }
+ Property { name: "hint"; type: "string" }
+ Property { name: "font"; type: "QFont"; isReadonly: true }
+ Property { name: "minimum"; type: "int" }
+ Property { name: "maximum"; type: "int" }
+ Property { name: "value"; type: "int" }
+ Property { name: "step"; type: "int" }
+ Property { name: "paintMargins"; type: "int" }
+ Property { name: "contentWidth"; type: "int" }
+ Property { name: "contentHeight"; type: "int" }
+ Signal {
+ name: "contentWidthChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Signal {
+ name: "contentHeightChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "pixelMetric"
+ type: "int"
+ Parameter { type: "string" }
+ }
+ Method {
+ name: "styleHint"
+ type: "QVariant"
+ Parameter { type: "string" }
+ }
+ Method { name: "updateSizeHint" }
+ Method { name: "updateItem" }
+ Method {
+ name: "hitTest"
+ type: "string"
+ Parameter { name: "x"; type: "int" }
+ Parameter { name: "y"; type: "int" }
+ }
+ Method {
+ name: "subControlRect"
+ type: "QRectF"
+ Parameter { name: "subcontrolString"; type: "string" }
+ }
+ Method {
+ name: "elidedText"
+ type: "string"
+ Parameter { name: "text"; type: "string" }
+ Parameter { name: "elideMode"; type: "int" }
+ Parameter { name: "width"; type: "int" }
+ }
+ Method {
+ name: "textWidth"
+ type: "int"
+ Parameter { type: "string" }
+ }
+ Method {
+ name: "hasThemeIcon"
+ type: "bool"
+ Parameter { type: "string" }
+ }
+ Method {
+ name: "setContentWidth"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setContentHeight"
+ Parameter { name: "arg"; type: "int" }
+ }
+ }
+ Component {
+ name: "QWheelArea"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["WheelArea 1.0"]
+ Property { name: "verticalDelta"; type: "double" }
+ Property { name: "horizontalDelta"; type: "double" }
+ Property { name: "horizontalMinimumValue"; type: "double" }
+ Property { name: "horizontalMaximumValue"; type: "double" }
+ Property { name: "verticalMinimumValue"; type: "double" }
+ Property { name: "verticalMaximumValue"; type: "double" }
+ Property { name: "horizontalValue"; type: "double" }
+ Property { name: "verticalValue"; type: "double" }
+ Property { name: "scrollSpeed"; type: "double" }
+ Signal { name: "verticalWheelMoved" }
+ Signal { name: "horizontalWheelMoved" }
+ }
+ Component {
+ name: "QWindowItem"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["Window 0.1", "Window 1.0"]
+ Property { name: "minimumHeight"; type: "int" }
+ Property { name: "maximumHeight"; type: "int" }
+ Property { name: "minimumWidth"; type: "int" }
+ Property { name: "maximumWidth"; type: "int" }
+ Property { name: "visible"; type: "bool" }
+ Property { name: "windowDecoration"; type: "bool" }
+ Property { name: "modal"; type: "bool" }
+ Property { name: "deleteOnClose"; type: "bool" }
+ Property { name: "windowState"; type: "Qt::WindowState" }
+ Property { name: "title"; type: "string" }
+ Signal { name: "modalityChanged" }
+ Method { name: "close" }
+ }
+ Component {
+ name: "QtMenu"
+ defaultProperty: "menuItems"
+ prototype: "QtMenuBase"
+ exports: ["Menu 1.0"]
+ Property { name: "text"; type: "string" }
+ Property { name: "model"; type: "QVariant" }
+ Property { name: "selectedIndex"; type: "int" }
+ Property { name: "hoveredIndex"; type: "int" }
+ Property { name: "menuItems"; type: "QtMenuBase"; isList: true; isReadonly: true }
+ Signal { name: "menuClosed" }
+ Signal {
+ name: "modelChanged"
+ Parameter { name: "newModel"; type: "QVariant" }
+ }
+ Signal { name: "rebuldMenu" }
+ Method {
+ name: "setModel"
+ Parameter { name: "newModel"; type: "QVariant" }
+ }
+ Method { name: "minimumWidth"; type: "int" }
+ Method {
+ name: "setMinimumWidth"
+ Parameter { name: "w"; type: "int" }
+ }
+ Method {
+ name: "showPopup"
+ Parameter { name: "x"; type: "double" }
+ Parameter { name: "y"; type: "double" }
+ Parameter { name: "atActionIndex"; type: "int" }
+ }
+ Method {
+ name: "showPopup"
+ Parameter { name: "x"; type: "double" }
+ Parameter { name: "y"; type: "double" }
+ }
+ Method { name: "hidePopup" }
+ Method { name: "clearMenuItems" }
+ Method {
+ name: "addMenuItem"
+ Parameter { name: "text"; type: "string" }
+ }
+ Method {
+ name: "itemTextAt"
+ type: "string"
+ Parameter { name: "index"; type: "int" }
+ }
+ Method {
+ name: "modelTextAt"
+ type: "string"
+ Parameter { name: "index"; type: "int" }
+ }
+ Method { name: "modelCount"; type: "int" }
+ Method { name: "hasNativeModel"; type: "bool" }
+ }
+ Component {
+ name: "QtMenuBar"
+ defaultProperty: "menus"
+ prototype: "QQuickItem"
+ exports: ["MenuBar 1.0"]
+ Property { name: "menus"; type: "QtMenu"; isList: true; isReadonly: true }
+ }
+ Component {
+ name: "QtMenuBase"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["NativeMenuBase 0.1"]
+ Property { name: "iconSource"; type: "QUrl" }
+ Property { name: "iconName"; type: "string" }
+ }
+ Component {
+ name: "QtMenuItem"
+ defaultProperty: "data"
+ prototype: "QtMenuBase"
+ exports: ["MenuItem 1.0"]
+ Property { name: "text"; type: "string" }
+ Property { name: "shortcut"; type: "string" }
+ Property { name: "checkable"; type: "bool" }
+ Property { name: "checked"; type: "bool" }
+ Property { name: "enabled"; type: "bool" }
+ Signal { name: "triggered" }
+ Signal {
+ name: "toggled"
+ Parameter { type: "bool" }
+ }
+ }
+ Component {
+ name: "QtMenuSeparator"
+ defaultProperty: "data"
+ prototype: "QtMenuBase"
+ exports: ["Separator 1.0"]
+ }
+}
diff --git a/src/controls/qmldir b/src/controls/qmldir
new file mode 100644
index 00000000..b3de1110
--- /dev/null
+++ b/src/controls/qmldir
@@ -0,0 +1,30 @@
+module QtQuick.Controls
+plugin plugin
+ApplicationWindow 1.0 ApplicationWindow.qml
+Button 1.0 Button.qml
+CheckBox 1.0 CheckBox.qml
+ComboBox 1.0 ComboBox.qml
+ContextMenu 1.0 ContextMenu.qml
+GroupBox 1.0 GroupBox.qml
+Label 1.0 Label.qml
+MenuBar 1.0 MenuBar.qml
+Menu 1.0 Menu.qml
+Page 1.0 Page.qml
+PageAnimation 1.0 PageAnimation.qml
+PageStack 1.0 PageStack.qml
+PageTransition 1.0 PageTransition.qml
+ProgressBar 1.0 ProgressBar.qml
+RadioButton 1.0 RadioButton.qml
+ScrollArea 1.0 ScrollArea.qml
+Slider 1.0 Slider.qml
+SpinBox 1.0 SpinBox.qml
+Splitter 1.0 Splitter.qml
+StatusBar 1.0 StatusBar.qml
+Tab 1.0 Tab.qml
+TabFrame 1.0 TabFrame.qml
+TableView 1.0 TableView.qml
+TableViewColumn 1.0 TableViewColumn.qml
+TextArea 1.0 TextArea.qml
+TextField 1.0 TextField.qml
+ToolBar 1.0 ToolBar.qml
+ToolButton 1.0 ToolButton.qml
diff --git a/src/controls/qpagestatus.h b/src/controls/qpagestatus.h
new file mode 100644
index 00000000..6ba8930a
--- /dev/null
+++ b/src/controls/qpagestatus.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QPAGESTATUS_H
+#define QPAGESTATUS_H
+
+#include <QtQml>
+#include <QtQuick>
+
+QT_BEGIN_NAMESPACE
+
+class QPageStatus : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(PageStatus)
+
+public:
+ enum PageStatus {
+ Inactive = 0,
+ Deactivating = 1,
+ Activating = 2,
+ Active = 3
+ };
+};
+
+QT_END_NAMESPACE
+
+#endif // QPAGESTATUS_H
diff --git a/src/controls/qquicklayout.cpp b/src/controls/qquicklayout.cpp
new file mode 100644
index 00000000..f0decf88
--- /dev/null
+++ b/src/controls/qquicklayout.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qquicklayout_p.h"
+#include <QEvent>
+#include <QApplication>
+#include <QtCore/qnumeric.h>
+
+QT_BEGIN_NAMESPACE
+
+static const qreal q_declarativeLayoutMaxSize = 10e8;
+
+
+QQuickComponentsLayoutAttached::QQuickComponentsLayoutAttached(QObject *parent)
+ : QObject(parent),
+ m_minimumWidth(0),
+ m_minimumHeight(0),
+ m_maximumWidth(q_declarativeLayoutMaxSize),
+ m_maximumHeight(q_declarativeLayoutMaxSize),
+ m_verticalSizePolicy(QQuickComponentsLayout::Fixed),
+ m_horizontalSizePolicy(QQuickComponentsLayout::Fixed)
+{
+
+}
+
+void QQuickComponentsLayoutAttached::setMinimumWidth(qreal width)
+{
+ if (qIsNaN(width) || m_minimumWidth == width)
+ return;
+
+ m_minimumWidth = width;
+ updateLayout();
+ emit minimumWidthChanged();
+}
+
+void QQuickComponentsLayoutAttached::setMinimumHeight(qreal height)
+{
+ if (qIsNaN(height) || m_minimumHeight == height)
+ return;
+
+ m_minimumHeight = height;
+ updateLayout();
+ emit minimumHeightChanged();
+}
+
+void QQuickComponentsLayoutAttached::setMaximumWidth(qreal width)
+{
+ if (qIsNaN(width) || m_maximumWidth == width)
+ return;
+
+ m_maximumWidth = width;
+ updateLayout();
+ emit maximumWidthChanged();
+}
+
+void QQuickComponentsLayoutAttached::setMaximumHeight(qreal height)
+{
+ if (qIsNaN(height) || m_maximumHeight == height)
+ return;
+
+ m_maximumHeight = height;
+ updateLayout();
+ emit maximumHeightChanged();
+}
+
+void QQuickComponentsLayoutAttached::setVerticalSizePolicy(QQuickComponentsLayout::SizePolicy policy)
+{
+ if (m_verticalSizePolicy != policy) {
+ m_verticalSizePolicy = policy;
+ updateLayout();
+ emit verticalSizePolicyChanged();
+ }
+}
+
+void QQuickComponentsLayoutAttached::setHorizontalSizePolicy(QQuickComponentsLayout::SizePolicy policy)
+{
+ if (m_horizontalSizePolicy != policy) {
+ m_horizontalSizePolicy = policy;
+ updateLayout();
+ emit horizontalSizePolicyChanged();
+ }
+}
+
+void QQuickComponentsLayoutAttached::updateLayout()
+{
+ if (m_layout)
+ m_layout->invalidate();
+}
+
+
+
+QQuickComponentsLayout::QQuickComponentsLayout(QQuickItem *parent)
+ : QQuickItem(parent),
+ m_dirty(false)
+{
+
+}
+
+QQuickComponentsLayout::~QQuickComponentsLayout()
+{
+
+}
+
+void QQuickComponentsLayout::setupItemLayout(QQuickItem *item)
+{
+ QObject *attached = qmlAttachedPropertiesObject<QQuickComponentsLayout>(item);
+ QQuickComponentsLayoutAttached *info = static_cast<QQuickComponentsLayoutAttached *>(attached);
+ info->m_layout = this;
+}
+
+QQuickComponentsLayoutAttached *QQuickComponentsLayout::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickComponentsLayoutAttached(object);
+}
+
+bool QQuickComponentsLayout::event(QEvent *e)
+{
+ if (e->type() == QEvent::LayoutRequest)
+ reconfigureTopDown();
+
+ return QQuickItem::event(e);
+}
+
+void QQuickComponentsLayout::invalidate()
+{
+ if (m_dirty)
+ return;
+
+ QQuickComponentsLayout *layout = this;
+ QQuickComponentsLayout *parentLayout = 0;
+
+ while (!layout->m_dirty) {
+ layout->m_dirty = true;
+ parentLayout = qobject_cast<QQuickComponentsLayout *>(layout->parentItem());
+
+ if (!parentLayout)
+ break;
+ else
+ layout = parentLayout;
+ }
+
+ // just post events for top level layouts
+ if (!parentLayout)
+ QApplication::postEvent(layout, new QEvent(QEvent::LayoutRequest));
+}
+
+void QQuickComponentsLayout::reconfigureTopDown()
+{
+ const QList<QQuickItem *> &children = childItems();
+
+ reconfigureLayout();
+
+ foreach (QQuickItem *child, children) {
+ QQuickComponentsLayout *layout = qobject_cast<QQuickComponentsLayout *>(child);
+
+ if (layout && layout->m_dirty)
+ layout->reconfigureTopDown();
+ }
+
+ m_dirty = false;
+}
+
+void QQuickComponentsLayout::reconfigureLayout()
+{
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qquicklayout_p.h b/src/controls/qquicklayout_p.h
new file mode 100644
index 00000000..d435f35f
--- /dev/null
+++ b/src/controls/qquicklayout_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKLAYOUT_P_H
+#define QQUICKLAYOUT_P_H
+
+#include <QPointer>
+#include <QQuickItem>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickComponentsLayoutAttached;
+
+
+class QQuickComponentsLayout : public QQuickItem
+{
+ Q_OBJECT
+ Q_ENUMS(SizePolicy)
+
+public:
+ enum SizePolicy {
+ Fixed,
+ Expanding
+ };
+
+ explicit QQuickComponentsLayout(QQuickItem *parent = 0);
+ ~QQuickComponentsLayout();
+
+ static QQuickComponentsLayoutAttached *qmlAttachedProperties(QObject *object);
+
+protected:
+ void invalidate();
+ bool event(QEvent *e);
+ void reconfigureTopDown();
+ virtual void reconfigureLayout();
+ void setupItemLayout(QQuickItem *item);
+
+private:
+ bool m_dirty;
+
+ friend class QQuickComponentsLayoutAttached;
+};
+
+
+class QQuickComponentsLayoutAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged)
+ Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight NOTIFY minimumHeightChanged)
+ Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth NOTIFY maximumWidthChanged)
+ Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight NOTIFY maximumHeightChanged)
+ Q_PROPERTY(QQuickComponentsLayout::SizePolicy verticalSizePolicy READ verticalSizePolicy WRITE setVerticalSizePolicy NOTIFY verticalSizePolicyChanged)
+ Q_PROPERTY(QQuickComponentsLayout::SizePolicy horizontalSizePolicy READ horizontalSizePolicy WRITE setHorizontalSizePolicy NOTIFY horizontalSizePolicyChanged)
+
+public:
+ QQuickComponentsLayoutAttached(QObject *object);
+
+ qreal minimumWidth() const { return m_minimumWidth; }
+ void setMinimumWidth(qreal width);
+
+ qreal minimumHeight() const { return m_minimumHeight; }
+ void setMinimumHeight(qreal height);
+
+ qreal maximumWidth() const { return m_maximumWidth; }
+ void setMaximumWidth(qreal width);
+
+ qreal maximumHeight() const { return m_maximumHeight; }
+ void setMaximumHeight(qreal height);
+
+ QQuickComponentsLayout::SizePolicy verticalSizePolicy() const { return m_verticalSizePolicy; }
+ void setVerticalSizePolicy(QQuickComponentsLayout::SizePolicy policy);
+
+ QQuickComponentsLayout::SizePolicy horizontalSizePolicy() const { return m_horizontalSizePolicy; }
+ void setHorizontalSizePolicy(QQuickComponentsLayout::SizePolicy policy);
+
+signals:
+ void minimumWidthChanged();
+ void minimumHeightChanged();
+ void maximumWidthChanged();
+ void maximumHeightChanged();
+ void verticalSizePolicyChanged();
+ void horizontalSizePolicyChanged();
+
+protected:
+ void updateLayout();
+
+private:
+ qreal m_minimumWidth;
+ qreal m_minimumHeight;
+ qreal m_maximumWidth;
+ qreal m_maximumHeight;
+ QQuickComponentsLayout::SizePolicy m_verticalSizePolicy;
+ QQuickComponentsLayout::SizePolicy m_horizontalSizePolicy;
+ QPointer<QQuickComponentsLayout> m_layout;
+
+ friend class QQuickComponentsLayout;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickComponentsLayout)
+QML_DECLARE_TYPEINFO(QQuickComponentsLayout, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKLAYOUT_P_H
diff --git a/src/controls/qquicklayoutengine.cpp b/src/controls/qquicklayoutengine.cpp
new file mode 100644
index 00000000..2ede7af9
--- /dev/null
+++ b/src/controls/qquicklayoutengine.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qquicklayoutengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ This function is a modification of qGeomCalc() included in "QtCore/kernel/qlayoutengine_p.h".
+ It is used as a helper function to handle linear layout recalculations for QQuickItems.
+
+ chain contains input and output parameters describing the geometry.
+ count is the count of items in the chain; pos and space give the
+ interval (relative to parentWidget topLeft).
+*/
+void qDeclarativeLayoutCalculate(QVector<QQuickComponentsLayoutInfo> &chain, int start,
+ int count, qreal pos, qreal space, qreal spacer)
+{
+ if (chain.count() == 0)
+ return;
+
+ bool wannaGrow = false;
+ qreal totalStretch = 0;
+ qreal totalSpacing = 0;
+ qreal totalSizeHint = 0;
+ qreal totalMinimumSize = 0;
+
+ const int end = start + count;
+ const int spacerCount = chain.count() - 1;
+
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ data->done = false;
+
+ totalStretch += data->stretch;
+ totalSizeHint += data->smartSizeHint();
+ totalMinimumSize += data->minimumSize;
+
+ // don't count last spacing
+ if (i < end - 1)
+ totalSpacing += data->effectiveSpacer(spacer);
+
+ wannaGrow = (wannaGrow || data->expansive || data->stretch > 0);
+ }
+
+ qreal extraSpace = 0;
+
+ if (space < totalMinimumSize + totalSpacing) {
+ // Less space than minimumSize; take from the biggest first
+ qreal minSize = totalMinimumSize + totalSpacing;
+
+ // shrink the spacers proportionally
+ if (spacer >= 0) {
+ spacer = minSize > 0 ? spacer * space / minSize : 0;
+ totalSpacing = spacer * spacerCount;
+ }
+
+ QList<qreal> list;
+
+ for (int i = start; i < end; i++)
+ list << chain.at(i).minimumSize;
+
+ qSort(list);
+
+ qreal spaceLeft = space - totalSpacing;
+
+ qreal sum = 0;
+ int idx = 0;
+ qreal spaceUsed = 0;
+ qreal current = 0;
+
+ while (idx < count && spaceUsed < spaceLeft) {
+ current = list.at(idx);
+ spaceUsed = sum + current * (count - idx);
+ sum += current;
+ ++idx;
+ }
+
+ --idx;
+
+ int items = count - idx;
+ qreal deficit = spaceUsed - spaceLeft;
+ qreal deficitPerItem = deficit / items;
+ qreal maxval = current - deficitPerItem;
+
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+ data->done = true;
+
+ if (data->minimumSize > 0)
+ data->size = data->minimumSize;
+ else
+ data->size = qMin<qreal>(data->minimumSize, maxval);
+ }
+ } else if (space < totalSizeHint + totalSpacing) {
+ /*
+ Less space than smartSizeHint(), but more than minimumSize.
+ Currently take space equally from each, as in Qt 2.x.
+ Commented-out lines will give more space to stretchier
+ items.
+ */
+ int n = count;
+ qreal spaceLeft = space - totalSpacing;
+ qreal overdraft = totalSizeHint - spaceLeft;
+
+ // first give to the fixed ones
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ if (!data->done && data->minimumSize >= data->smartSizeHint()) {
+ data->done = true;
+ data->size = data->smartSizeHint();
+ spaceLeft -= data->smartSizeHint();
+ n--;
+ }
+ }
+
+ bool finished = (n == 0);
+
+ while (!finished) {
+ finished = true;
+
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ if (data->done)
+ continue;
+
+ qreal w = overdraft / n;
+ data->size = data->smartSizeHint() - w;
+
+ if (data->size < data->minimumSize) {
+ data->done = true;
+ data->size = data->minimumSize;
+ finished = false;
+ overdraft -= data->smartSizeHint() - data->minimumSize;
+ n--;
+ break;
+ }
+ }
+ }
+ } else { // extra space
+ int n = count;
+ qreal spaceLeft = space - totalSpacing;
+
+ // first give to the fixed ones, and handle non-expansiveness
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ if (data->done)
+ continue;
+
+ if (data->maximumSize <= data->smartSizeHint()
+ || (wannaGrow && !data->expansive && data->stretch == 0)
+ || (!data->expansive && data->stretch == 0)) {
+ data->done = true;
+ data->size = data->smartSizeHint();
+ spaceLeft -= data->size;
+ totalStretch -= data->stretch;
+ n--;
+ }
+ }
+
+ extraSpace = spaceLeft;
+
+ /*
+ Do a trial distribution and calculate how much it is off.
+ If there are more deficit pixels than surplus pixels, give
+ the minimum size items what they need, and repeat.
+ Otherwise give to the maximum size items, and repeat.
+
+ Paul Olav Tvete has a wonderful mathematical proof of the
+ correctness of this principle, but unfortunately this
+ comment is too small to contain it.
+ */
+ qreal surplus, deficit;
+
+ do {
+ surplus = deficit = 0;
+
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ if (data->done)
+ continue;
+
+ extraSpace = 0;
+
+ qreal w;
+
+ if (totalStretch <= 0)
+ w = (spaceLeft / n);
+ else
+ w = (spaceLeft * data->stretch) / totalStretch;
+
+ data->size = w;
+
+ if (w < data->smartSizeHint())
+ deficit += data->smartSizeHint() - w;
+ else if (w > data->maximumSize)
+ surplus += w - data->maximumSize;
+ }
+
+ if (deficit > 0 && surplus <= deficit) {
+ // give to the ones that have too little
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ if (!data->done && data->size < data->smartSizeHint()) {
+ data->done = true;
+ data->size = data->smartSizeHint();
+ spaceLeft -= data->smartSizeHint();
+ totalStretch -= data->stretch;
+ n--;
+ }
+ }
+ }
+
+ if (surplus > 0 && surplus >= deficit) {
+ // take from the ones that have too much
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+
+ if (!data->done && data->size > data->maximumSize) {
+ data->done = true;
+ data->size = data->maximumSize;
+ spaceLeft -= data->maximumSize;
+ totalStretch -= data->stretch;
+ n--;
+ }
+ }
+ }
+ } while (n > 0 && surplus != deficit);
+
+ if (n == 0)
+ extraSpace = spaceLeft;
+ }
+
+ /*
+ As a last resort, we distribute the unwanted space equally
+ among the spacers (counting the start and end of the chain). We
+ could, but don't, attempt a sub-pixel allocation of the extra
+ space.
+ */
+ qreal extra = extraSpace / (spacerCount + 2);
+ qreal p = pos + extra;
+
+ for (int i = start; i < end; i++) {
+ QQuickComponentsLayoutInfo *data = &chain[i];
+ data->pos = p;
+ p += data->size;
+ p += data->effectiveSpacer(spacer) + extra;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qquicklayoutengine_p.h b/src/controls/qquicklayoutengine_p.h
new file mode 100644
index 00000000..85eca8c3
--- /dev/null
+++ b/src/controls/qquicklayoutengine_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKLAYOUTENGINE_P_H
+#define QQUICKLAYOUTENGINE_P_H
+
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+struct QQuickComponentsLayoutInfo
+{
+ QQuickComponentsLayoutInfo()
+ : stretch(1),
+ sizeHint(0),
+ spacing(0),
+ minimumSize(0),
+ maximumSize(0),
+ expansive(true),
+ done(false),
+ pos(0),
+ size(0)
+ { }
+
+ inline qreal smartSizeHint() {
+ return (stretch > 0) ? minimumSize : sizeHint;
+ }
+
+ inline qreal effectiveSpacer(qreal value) const {
+ return value + spacing;
+ }
+
+ qreal stretch;
+ qreal sizeHint;
+ qreal spacing;
+ qreal minimumSize;
+ qreal maximumSize;
+ bool expansive;
+
+ // result
+ bool done;
+ qreal pos;
+ qreal size;
+};
+
+void qDeclarativeLayoutCalculate(QVector<QQuickComponentsLayoutInfo> &chain, int start,
+ int count, qreal pos, qreal space, qreal spacer);
+
+QT_END_NAMESPACE
+
+#endif // QQUICKLAYOUTENGINE_P_H
diff --git a/src/controls/qquicklinearlayout.cpp b/src/controls/qquicklinearlayout.cpp
new file mode 100644
index 00000000..015b8cba
--- /dev/null
+++ b/src/controls/qquicklinearlayout.cpp
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qquicklinearlayout_p.h"
+#include "qquicklayoutengine_p.h"
+#include <QtCore/qnumeric.h>
+
+/*!
+ \qmltype RowLayout
+ \instantiates QQuickComponentsRowLayout
+ \inqmlmodule QtQuick.Controls 1.0
+ \brief RowLayout is doing bla...bla...
+*/
+
+/*!
+ \qmltype ColumnLayout
+ \instantiates QQuickComponentsColumnLayout
+ \inqmlmodule QtQuick.Controls 1.0
+ \brief ColumnLayout is doing bla...bla...
+*/
+
+QT_BEGIN_NAMESPACE
+
+static const qreal q_declarativeLayoutDefaultSpacing = 4.0;
+
+
+QQuickComponentsLinearLayout::QQuickComponentsLinearLayout(Orientation orientation,
+ QQuickItem *parent)
+ : QQuickComponentsLayout(parent),
+ m_spacing(q_declarativeLayoutDefaultSpacing),
+ m_orientation(orientation)
+{
+
+}
+
+qreal QQuickComponentsLinearLayout::spacing() const
+{
+ return m_spacing;
+}
+
+void QQuickComponentsLinearLayout::setSpacing(qreal spacing)
+{
+ if (qIsNaN(spacing) || m_spacing == spacing)
+ return;
+
+ m_spacing = spacing;
+ invalidate();
+}
+
+QQuickComponentsLinearLayout::Orientation QQuickComponentsLinearLayout::orientation() const
+{
+ return m_orientation;
+}
+
+void QQuickComponentsLinearLayout::setOrientation(Orientation orientation)
+{
+ if (m_orientation == orientation)
+ return;
+
+ m_orientation = orientation;
+ invalidate();
+
+ emit orientationChanged();
+}
+
+void QQuickComponentsLinearLayout::componentComplete()
+{
+ QQuickComponentsLayout::componentComplete();
+ updateLayoutItems();
+ invalidate();
+}
+
+void QQuickComponentsLinearLayout::updateLayoutItems()
+{
+ const QList<QQuickItem *> &children = childItems();
+ qreal implicitWidth = 0;
+ qreal implicitHeight = 0;
+ foreach (QQuickItem *child, children) {
+ if (m_orientation == Horizontal) {
+ implicitWidth += child->implicitWidth();
+ implicitHeight = qMax(implicitHeight, child->implicitHeight());
+ } else {
+ implicitHeight += child->implicitHeight();
+ implicitWidth = qMax(implicitWidth, child->implicitWidth());
+ }
+ insertLayoutItem(child);
+ }
+ setImplicitWidth(implicitWidth);
+ setImplicitHeight(implicitHeight);
+}
+
+void QQuickComponentsLinearLayout::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ if (isComponentComplete()) {
+ if (change == ItemChildAddedChange)
+ insertLayoutItem(value.item);
+ else if (change == ItemChildRemovedChange)
+ removeLayoutItem(value.item);
+ }
+
+ QQuickComponentsLayout::itemChange(change, value);
+}
+
+void QQuickComponentsLinearLayout::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickComponentsLayout::geometryChanged(newGeometry, oldGeometry);
+ invalidate();
+}
+
+void QQuickComponentsLinearLayout::insertLayoutItem(QQuickItem *item)
+{
+ m_items.append(item);
+ setupItemLayout(item);
+
+ invalidate();
+ QObject::connect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
+ QObject::connect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
+}
+
+void QQuickComponentsLinearLayout::removeLayoutItem(QQuickItem *item)
+{
+ if (!m_items.removeOne(item))
+ return;
+
+ invalidate();
+ QObject::disconnect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
+ QObject::disconnect(item, SIGNAL(visibleChanged()), this, SLOT(onItemVisibleChanged()));
+}
+
+void QQuickComponentsLinearLayout::onItemVisibleChanged()
+{
+ invalidate();
+}
+
+void QQuickComponentsLinearLayout::onItemDestroyed()
+{
+ if (!m_items.removeOne(static_cast<QQuickItem *>(sender())))
+ return;
+
+ invalidate();
+}
+
+void QQuickComponentsLinearLayout::reconfigureLayout()
+{
+ if (!isComponentComplete())
+ return;
+
+ const int count = m_items.count();
+
+ if (count == 0)
+ return;
+
+ qreal totalSpacing = 0;
+ qreal totalSizeHint = 0;
+ qreal totalMinimumSize = 0;
+ qreal totalMaximumSize = 0;
+
+ QVector<QQuickComponentsLayoutInfo> itemData;
+
+ for (int i = 0; i < count; i++) {
+ QQuickItem *item = m_items.at(i);
+ QObject *attached = qmlAttachedPropertiesObject<QQuickComponentsLayout>(item);
+ QQuickComponentsLayoutAttached *info = static_cast<QQuickComponentsLayoutAttached *>(attached);
+
+ QQuickComponentsLayoutInfo data;
+
+ if (item->isVisible()) {
+ if (m_orientation == Horizontal) {
+ data.sizeHint = item->implicitWidth();
+ data.minimumSize = info->minimumWidth();
+ data.maximumSize = info->maximumWidth();
+ data.expansive = (info->horizontalSizePolicy() == QQuickComponentsLayout::Expanding);
+ data.stretch = info->horizontalSizePolicy() == Expanding ? 1.0 : 0;
+ } else {
+ data.sizeHint = item->implicitHeight();
+ data.minimumSize = info->minimumHeight();
+ data.maximumSize = info->maximumHeight();
+ data.expansive = (info->verticalSizePolicy() == QQuickComponentsLayout::Expanding);
+ data.stretch = info->verticalSizePolicy() == Expanding ? 1.0 : 0;
+ }
+
+ itemData.append(data);
+ // sum
+ totalSizeHint += data.sizeHint;
+ totalMinimumSize += data.minimumSize;
+ totalMaximumSize += data.maximumSize;
+
+ // don't count last spacing
+ if (i < count - 1)
+ totalSpacing += data.spacing + m_spacing;
+ }
+ }
+
+ qreal extent = m_orientation == Horizontal ? width() : height();
+ qDeclarativeLayoutCalculate(itemData, 0, itemData.count(), 0, extent, m_spacing);
+
+ int i = 0;
+ int id = 0;
+ while (i < count) {
+ QQuickItem *item = m_items.at(i++);
+ if (!item->isVisible())
+ continue;
+ const QQuickComponentsLayoutInfo &data = itemData.at(id);
+
+ if (m_orientation == Horizontal) {
+ item->setX(data.pos);
+ item->setY(height()/2 - item->height()/2);
+ item->setWidth(data.size);
+ } else {
+ item->setY(data.pos);
+ item->setX(width()/2 - item->width()/2);
+ item->setHeight(data.size);
+ }
+ ++id;
+ }
+
+ // propagate hints to upper levels
+ QObject *attached = qmlAttachedPropertiesObject<QQuickComponentsLayout>(this);
+ QQuickComponentsLayoutAttached *info = static_cast<QQuickComponentsLayoutAttached *>(attached);
+
+ if (m_orientation == Horizontal) {
+ setImplicitWidth(totalSizeHint);
+ info->setMinimumWidth(totalMinimumSize + totalSpacing);
+ info->setMaximumWidth(totalMaximumSize + totalSpacing);
+ } else {
+ setImplicitHeight(totalSizeHint);
+ info->setMinimumHeight(totalMinimumSize + totalSpacing);
+ info->setMaximumHeight(totalMaximumSize + totalSpacing);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qquicklinearlayout_p.h b/src/controls/qquicklinearlayout_p.h
new file mode 100644
index 00000000..9b71c896
--- /dev/null
+++ b/src/controls/qquicklinearlayout_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKLINEARLAYOUT_P_H
+#define QQUICKLINEARLAYOUT_P_H
+
+#include "qquicklayout_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickComponentsLinearLayout : public QQuickComponentsLayout
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
+
+public:
+ enum Orientation {
+ Vertical,
+ Horizontal
+ };
+
+ explicit QQuickComponentsLinearLayout(Orientation orientation,
+ QQuickItem *parent = 0);
+ ~QQuickComponentsLinearLayout() {}
+
+ qreal spacing() const;
+ void setSpacing(qreal spacing);
+
+ Orientation orientation() const;
+ void setOrientation(Orientation orientation);
+
+ void componentComplete();
+
+signals:
+ void spacingChanged();
+ void orientationChanged();
+
+protected:
+ void updateLayoutItems();
+ void reconfigureLayout();
+ void insertLayoutItem(QQuickItem *item);
+ void removeLayoutItem(QQuickItem *item);
+ void itemChange(ItemChange change, const ItemChangeData &data);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+
+protected slots:
+ void onItemVisibleChanged();
+ void onItemDestroyed();
+
+private:
+ qreal m_spacing;
+ Orientation m_orientation;
+ QList<QQuickItem *> m_items;
+};
+
+
+class QQuickComponentsRowLayout : public QQuickComponentsLinearLayout
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickComponentsRowLayout(QQuickItem *parent = 0)
+ : QQuickComponentsLinearLayout(Horizontal, parent) {}
+};
+
+
+class QQuickComponentsColumnLayout : public QQuickComponentsLinearLayout
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickComponentsColumnLayout(QQuickItem *parent = 0)
+ : QQuickComponentsLinearLayout(Vertical, parent) {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKLINEARLAYOUT_P_H
diff --git a/src/controls/qtaction.cpp b/src/controls/qtaction.cpp
new file mode 100644
index 00000000..debdd762
--- /dev/null
+++ b/src/controls/qtaction.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qtaction_p.h"
+#include "qtexclusivegroup_p.h"
+
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Action
+ \instantiates QtAction
+ \inqmlmodule QtQuick.Controls 1.0
+ \brief Action provides an abstract user interface action that can be bound to items
+
+ \sa MenuItem, Menu, ExclusiveGroup
+*/
+
+/*!
+ \qmlproperty string Action::text
+*/
+
+/*!
+ \qmlproperty url Action::iconSource
+*/
+
+/*!
+ \qmlproperty string Action::iconName
+*/
+
+/*!
+ \qmlproperty string Action::toolTip
+*/
+
+/*!
+ \qmlproperty bool Action::enabled
+*/
+
+/*!
+ \qmlproperty bool Action::checkable
+*/
+
+/*!
+ \qmlproperty bool Action::checked
+
+*/
+
+/*!
+ \qmlproperty ExclusiveGroup Action::exclusiveGroup
+
+ \sa ExclusiveGroup
+*/
+
+/*!
+ \qmlproperty string Action::shortcut
+*/
+
+/*!
+ \qmlproperty string Action::mnemonic
+*/
+
+QtAction::QtAction(QObject *parent)
+ : QObject(parent)
+ , m_enabled(true)
+ , m_checkable(false)
+ , m_checked(false)
+ , m_exclusiveGroup(0)
+{
+}
+
+QtAction::~QtAction()
+{
+ setShortcut(QString());
+ setMnemonic(QString());
+}
+
+void QtAction::setText(const QString &text)
+{
+ if (text == m_text)
+ return;
+ m_text = text;
+ emit textChanged();
+}
+
+bool qShortcutContextMatcher(QObject *, Qt::ShortcutContext)
+{
+ // the context matching is only interesting for non window-wide shortcuts
+ // it might be interesting to check for the action's window being active
+ // we currently only support the window wide focus so we can safely ignore this
+ return true;
+}
+
+QString QtAction::shortcut() const
+{
+ return m_shortcut.toString(QKeySequence::NativeText);
+}
+
+void QtAction::setShortcut(const QString &arg)
+{
+ QKeySequence sequence = QKeySequence::fromString(arg);
+ if (sequence == m_shortcut)
+ return;
+
+ if (!m_shortcut.isEmpty())
+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, m_shortcut);
+
+ m_shortcut = sequence;
+
+ if (!m_shortcut.isEmpty()) {
+ Qt::ShortcutContext context = Qt::WindowShortcut;
+ QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, m_shortcut, context, qShortcutContextMatcher);
+ }
+ emit shortcutChanged(shortcut());
+}
+
+QString QtAction::mnemonic() const
+{
+ return m_mnemonic.toString(QKeySequence::NativeText);
+}
+
+void QtAction::setMnemonic(const QString &mnem)
+{
+ QKeySequence sequence = QKeySequence::mnemonic(mnem);
+ if (m_mnemonic == sequence)
+ return;
+
+ if (!m_mnemonic.isEmpty())
+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, m_mnemonic);
+
+ m_mnemonic = sequence;
+
+ if (!m_mnemonic.isEmpty()) {
+ Qt::ShortcutContext context = Qt::WindowShortcut;
+ QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, m_mnemonic, context, qShortcutContextMatcher);
+ }
+ emit mnemonicChanged(mnemonic());
+}
+
+void QtAction::setIconSource(const QUrl &iconSource)
+{
+ if (iconSource == m_iconSource)
+ return;
+
+ m_iconSource = iconSource;
+ QString iconName = m_icon.name();
+ m_icon = QIcon(m_iconSource.toLocalFile());
+ if (!iconName.isEmpty())
+ m_icon = QIcon::fromTheme(iconName, m_icon);
+
+ emit iconSourceChanged();
+ emit iconChanged();
+}
+
+QString QtAction::iconName() const
+{
+ return m_icon.name();
+}
+
+void QtAction::setIconName(const QString &iconName)
+{
+ if (iconName == m_icon.name())
+ return;
+
+ m_icon = QIcon::fromTheme(iconName, QIcon(m_iconSource.toLocalFile()));
+ emit iconNameChanged();
+ emit iconChanged();
+}
+
+void QtAction::setToolTip(const QString &arg)
+{
+ if (m_toolTip != arg) {
+ m_toolTip = arg;
+ emit toolTipChanged(arg);
+ }
+}
+
+void QtAction::setEnabled(bool e)
+{
+ if (e == m_enabled)
+ return;
+ m_enabled = e;
+ emit enabledChanged();
+}
+
+void QtAction::setCheckable(bool c)
+{
+ if (c == m_checkable)
+ return;
+ m_checkable = c;
+ emit checkableChanged();
+}
+
+void QtAction::setChecked(bool c)
+{
+ if (c == m_checked)
+ return;
+ m_checked = c;
+ emit toggled(m_checked);
+}
+
+void QtAction::setExclusiveGroup(QtExclusiveGroup *eg)
+{
+ if (m_exclusiveGroup == eg)
+ return;
+
+ if (m_exclusiveGroup)
+ m_exclusiveGroup->unregisterCheckable(this);
+ m_exclusiveGroup = eg;
+ if (m_exclusiveGroup)
+ m_exclusiveGroup->registerCheckable(this);
+
+ emit exclusiveGroupChanged();
+}
+
+bool QtAction::event(QEvent *e)
+{
+ if (!m_enabled)
+ return false;
+
+ if (e->type() != QEvent::Shortcut)
+ return false;
+
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
+
+ Q_ASSERT_X(se->key() == m_shortcut || se->key() == m_mnemonic,
+ "QtAction::event",
+ "Received shortcut event from incorrect shortcut");
+ if (se->isAmbiguous()) {
+ qWarning("QtAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData());
+ return false;
+ }
+
+ trigger();
+
+ return true;
+}
+
+void QtAction::trigger()
+{
+ if (m_checkable)
+ setChecked(!m_checked);
+
+ emit triggered();
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qtaction_p.h b/src/controls/qtaction_p.h
new file mode 100644
index 00000000..1e44b003
--- /dev/null
+++ b/src/controls/qtaction_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QTACTION_H
+#define QTACTION_H
+
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
+#include <QtGui/QIcon>
+#include <QtGui/qkeysequence.h>
+
+QT_BEGIN_NAMESPACE
+
+class QtExclusiveGroup;
+
+class QtAction : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QUrl iconSource READ iconSource WRITE setIconSource NOTIFY iconSourceChanged)
+ Q_PROPERTY(QString iconName READ iconName WRITE setIconName NOTIFY iconNameChanged)
+ Q_PROPERTY(QVariant __icon READ iconVariant NOTIFY iconChanged)
+ Q_PROPERTY(QString toolTip READ tooltip WRITE setToolTip NOTIFY toolTipChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged)
+ Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
+
+ Q_PROPERTY(QtExclusiveGroup *exclusiveGroup READ exclusiveGroup WRITE setExclusiveGroup NOTIFY exclusiveGroupChanged)
+#ifndef QT_NO_SHORTCUT
+ Q_PROPERTY(QString shortcut READ shortcut WRITE setShortcut NOTIFY shortcutChanged)
+ Q_PROPERTY(QString mnemonic READ mnemonic WRITE setMnemonic NOTIFY mnemonicChanged)
+#endif
+
+public:
+ explicit QtAction(QObject *parent = 0);
+ ~QtAction();
+
+ QString text() const { return m_text; }
+ void setText(const QString &text);
+
+ QString shortcut() const;
+ void setShortcut(const QString &shortcut);
+
+ QString mnemonic() const;
+ void setMnemonic(const QString &mnemonic);
+
+ QString iconName() const;
+ void setIconName(const QString &iconName);
+
+ QUrl iconSource() const { return m_iconSource; }
+ void setIconSource(const QUrl &iconSource);
+
+ QString tooltip() const { return m_toolTip; }
+ void setToolTip(const QString &toolTip);
+
+ bool isEnabled() const { return m_enabled; }
+ void setEnabled(bool e);
+
+ bool isCheckable() const { return m_checkable; }
+ void setCheckable(bool c);
+
+ bool isChecked() const { return m_checked; }
+ void setChecked(bool c);
+
+ QtExclusiveGroup *exclusiveGroup() const { return m_exclusiveGroup; }
+ void setExclusiveGroup(QtExclusiveGroup * arg);
+
+ QIcon icon() const { return m_icon; }
+ QVariant iconVariant() const { return QVariant(m_icon); }
+ void setIcon(QIcon icon) { m_icon = icon; emit iconChanged(); }
+
+ bool event(QEvent *e);
+
+public Q_SLOTS:
+ void trigger();
+
+Q_SIGNALS:
+ void triggered();
+ void toggled(bool);
+
+ void textChanged();
+ void shortcutChanged(QString shortcut);
+ void mnemonicChanged(QString mnemonic);
+
+ void iconChanged();
+ void iconNameChanged();
+ void iconSourceChanged();
+ void toolTipChanged(QString arg);
+ void enabledChanged();
+ void checkableChanged();
+
+ void exclusiveGroupChanged();
+
+private:
+ QString m_text;
+ QUrl m_iconSource;
+ QIcon m_icon;
+ bool m_enabled;
+ bool m_checkable;
+ bool m_checked;
+ QtExclusiveGroup *m_exclusiveGroup;
+ QKeySequence m_shortcut;
+ QKeySequence m_mnemonic;
+ QString m_toolTip;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTACTION_H
diff --git a/src/controls/qtexclusivegroup.cpp b/src/controls/qtexclusivegroup.cpp
new file mode 100644
index 00000000..fde2a9df
--- /dev/null
+++ b/src/controls/qtexclusivegroup.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qtexclusivegroup_p.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+
+#define CHECKED_PROPERTY "checked"
+
+QT_BEGIN_NAMESPACE
+
+static const char *checkableSignals[] = {
+ CHECKED_PROPERTY"Changed()",
+ "toggled(bool)",
+ "toggled()",
+ 0
+};
+
+static bool isChecked(const QObject *o)
+{
+ if (!o) return false;
+ QVariant checkedVariant = o->property(CHECKED_PROPERTY);
+ return checkedVariant.isValid() && checkedVariant.toBool();
+}
+
+/*!
+ \qmltype ExclusiveGroup
+ \instantiates QtExclusiveGroup
+ \inqmlmodule QtQuick.Controls 1.0
+ \ingroup containers
+ \brief ExclusiveGroup provides a way to declare several checkable controls as mutually exclusive.
+
+ \code
+ ExclusiveGroup { id: radioInputGroup }
+
+ Action {
+ id: dabRadioInput
+ text: "DAB"
+ exclusiveGroup: radioInputGroup
+ }
+
+ Action {
+ id: fmRadioInput
+ text: "FM"
+ exclusiveGroup: radioInputGroup
+ }
+
+ Action {
+ id: amRadioInput
+ text: "AM"
+ exclusiveGroup: radioInputGroup
+ }
+
+ \endcode
+
+ For an object, or control, to be compatible with \c ExclusiveGroup, it should have a \c checked
+ property, and either a \c checkedChanged, \c toggled(), or \c toggled(bool) signal. It also needs
+ to be registered with \c ExclusiveGroup::registerCheckable(object) when its \c ExclusiveGroup property is set.
+
+ \sa Action, ButtonBehavior
+*/
+
+/*!
+ \qmlproperty QtObject ExclusiveGroup::current
+
+ The currently selected object.
+*/
+
+/*!
+ \qmlmethod void ExclusiveGroup::registerCheckable(object)
+
+ Register \c object to the exclusive group.
+
+ You should only need to call this function when creating a component you want to be compatible with \c ExclusiveGroup.
+
+ \sa ExclusiveGroup::unregisterCheckable(object)
+*/
+
+/*!
+ \qmlmethod void ExclusiveGroup::unregisterCheckable(object)
+
+ Unregister \c object from the exclusive group.
+
+ You should only need to call this function when creating a component you want to be compatible with \c ExclusiveGroup.
+
+ \sa ExclusiveGroup::registerCheckable(object)
+*/
+
+QtExclusiveGroup::QtExclusiveGroup(QObject *parent)
+ : QObject(parent)
+{
+ int index = metaObject()->indexOfMethod("updateCurrent()");
+ m_updateCurrentMethod = metaObject()->method(index);
+}
+
+void QtExclusiveGroup::setCurrent(QObject * o)
+{
+ if (m_current == o)
+ return;
+
+ if (m_current)
+ m_current->setProperty(CHECKED_PROPERTY, QVariant(false));
+ m_current = o;
+ if (m_current)
+ m_current->setProperty(CHECKED_PROPERTY, QVariant(true));
+ emit currentChanged();
+}
+
+void QtExclusiveGroup::updateCurrent()
+{
+ QObject *checkable = sender();
+ if (isChecked(checkable))
+ setCurrent(checkable);
+}
+
+void QtExclusiveGroup::registerCheckable(QObject *o)
+{
+ for (const char **signalName = checkableSignals; *signalName; signalName++) {
+ int signalIndex = o->metaObject()->indexOfSignal(*signalName);
+ if (signalIndex != -1) {
+ QMetaMethod signalMethod = o->metaObject()->method(signalIndex);
+ connect(o, signalMethod, this, m_updateCurrentMethod, Qt::UniqueConnection);
+ connect(o, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterCheckable(QObject*)), Qt::UniqueConnection);
+ if (!m_current && isChecked(o))
+ setCurrent(o);
+ return;
+ }
+ }
+
+ qWarning() << "QtExclusiveGroup::registerCheckable(): Cannot register" << o;
+}
+
+void QtExclusiveGroup::unregisterCheckable(QObject *o)
+{
+ for (const char **signalName = checkableSignals; *signalName; signalName++) {
+ int signalIndex = o->metaObject()->indexOfSignal(*signalName);
+ if (signalIndex != -1) {
+ QMetaMethod signalMethod = o->metaObject()->method(signalIndex);
+ if (disconnect(o, signalMethod, this, m_updateCurrentMethod)) {
+ disconnect(o, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterCheckable(QObject*)));
+ break;
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qtexclusivegroup_p.h b/src/controls/qtexclusivegroup_p.h
new file mode 100644
index 00000000..7d980bd0
--- /dev/null
+++ b/src/controls/qtexclusivegroup_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QTEXCLUSIVEGROUP_H
+#define QTEXCLUSIVEGROUP_H
+
+#include <QtCore/QObject>
+#include <QtCore/QMetaMethod>
+
+QT_BEGIN_NAMESPACE
+
+class QtExclusiveGroup : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QObject *current READ current WRITE setCurrent NOTIFY currentChanged)
+
+public:
+ explicit QtExclusiveGroup(QObject *parent = 0);
+
+ QObject *current() const { return m_current; }
+ void setCurrent(QObject * o);
+
+public Q_SLOTS:
+ void registerCheckable(QObject *o);
+ void unregisterCheckable(QObject *o);
+
+Q_SIGNALS:
+ void currentChanged();
+
+private Q_SLOTS:
+ void updateCurrent();
+
+private:
+ QObject * m_current;
+ QMetaMethod m_updateCurrentMethod;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTEXCLUSIVEGROUP_H
diff --git a/src/controls/qtmenu.cpp b/src/controls/qtmenu.cpp
new file mode 100644
index 00000000..bd7af0c2
--- /dev/null
+++ b/src/controls/qtmenu.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qtmenu_p.h"
+#include "qdebug.h"
+#include "qtaction_p.h"
+#include "qtmenupopupwindow_p.h"
+#include <qabstractitemmodel.h>
+
+#include "private/qguiapplication_p.h"
+#include <QtGui/qpa/qplatformtheme.h>
+#include <QtGui/qpa/qplatformmenu.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QtMenu
+ \internal
+ */
+
+/*!
+ \qmltype MenuPrivate
+ \instantiates QtMenu
+ \internal
+ \inqmlmodule QtQuick.Controls 1.0
+ */
+
+/*!
+ \qmlproperty readonly list Menu::menuItems
+ \default
+*/
+
+/*!
+ \qmlproperty var Menu::model
+*/
+
+/*!
+ \qmlproperty int Menu::selectedIndex
+*/
+
+/*!
+ \qmlproperty font Menu::font
+
+ Write-only. For styling purposes only.
+*/
+
+/*!
+ \qmlproperty readonly bool Menu::popupVisible
+*/
+
+/*!
+ \qmlmethod void Menu::showPopup(x, y, item, parent)
+
+ Shows the popup related to this menu. It can block on some platforms, so test it accordingly.
+*/
+
+/*!
+ \qmlmethod void Menu::closeMenu()
+
+ Closes current menu (and submenus) only.
+*/
+
+/*!
+ \qmlmethod void Menu::dismissMenu()
+
+ Closes all menus related to this one, including its parent menu.
+*/
+
+QtMenu::QtMenu(QObject *parent)
+ : QtMenuItem(parent),
+ m_selectedIndex(-1),
+ m_highlightedIndex(0),
+ m_hasNativeModel(false),
+ m_minimumWidth(0),
+ m_popupWindow(0),
+ m_popupVisible(false)
+{
+ m_platformMenu = QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
+ if (m_platformMenu) {
+ connect(m_platformMenu, SIGNAL(aboutToHide()), this, SLOT(closeMenu()));
+ if (platformItem())
+ platformItem()->setMenu(m_platformMenu);
+ }
+}
+
+QtMenu::~QtMenu()
+{
+ delete m_platformMenu;
+}
+
+void QtMenu::updateText()
+{
+ if (m_platformMenu)
+ m_platformMenu->setText(text());
+ QtMenuItem::updateText();
+}
+
+void QtMenu::setMinimumWidth(int w)
+{
+ if (w == m_minimumWidth)
+ return;
+
+ m_minimumWidth = w;
+ if (m_platformMenu)
+ m_platformMenu->setMinimumWidth(w);
+
+ emit minimumWidthChanged();
+}
+
+void QtMenu::setFont(const QFont &arg)
+{
+ if (m_platformMenu)
+ m_platformMenu->setFont(arg);
+}
+
+void QtMenu::setSelectedIndex(int index)
+{
+ if (m_selectedIndex == index)
+ return;
+
+ m_selectedIndex = index;
+
+ if (m_selectedIndex >= 0 && m_selectedIndex < m_menuItems.size())
+ if (QtMenuItem *item = qobject_cast<QtMenuItem *>(m_menuItems[m_selectedIndex]))
+ if (item->checkable())
+ item->setChecked(true);
+
+ emit selectedIndexChanged();
+}
+
+QQmlListProperty<QtMenuBase> QtMenu::menuItems()
+{
+ return QQmlListProperty<QtMenuBase>(this, 0, &QtMenu::append_menuItems, &QtMenu::count_menuItems, &QtMenu::at_menuItems, 0);
+}
+
+void QtMenu::showPopup(qreal x, qreal y, int atItemIndex, QObject *reference)
+{
+ if (popupVisible())
+ closeMenu();
+
+ setPopupVisible(true);
+
+ // If atItemIndex is valid, x and y is specified from the
+ // the position of the corresponding QtMenuItem:
+ QtMenuItem *atItem = 0;
+ if (atItemIndex >= 0)
+ while (!atItem && atItemIndex < m_menuItems.size())
+ atItem = qobject_cast<QtMenuItem *>(m_menuItems[atItemIndex++]);
+
+ QQuickItem *item = qobject_cast<QQuickItem *>(reference);
+
+ QQuickWindow *parentWindow = item ? item->window() : qobject_cast<QQuickWindow *>(reference);
+ if (!parentWindow) {
+ QQuickItem *parentAsItem = qobject_cast<QQuickItem *>(parent());
+ parentWindow = visualItem() ? visualItem()->window() : // Menu as menu item case
+ parentAsItem ? parentAsItem->window() : 0; //Menu as context menu/popup case
+ }
+
+ if (m_platformMenu) {
+ QPointF screenPosition(x, y);
+ if (item)
+ screenPosition = item->mapToScene(screenPosition);
+ m_platformMenu->showPopup(parentWindow, screenPosition.toPoint(), atItem ? atItem->platformItem() : 0);
+ } else {
+ m_popupWindow = new QtMenuPopupWindow();
+ m_popupWindow->setParentWindow(parentWindow);
+ m_popupWindow->setMenuContentItem(m_menuContentItem);
+ connect(m_popupWindow, SIGNAL(visibleChanged(bool)), this, SLOT(windowVisibleChanged(bool)));
+
+ if (parentWindow) {
+ if (item) {
+ QPointF pos = item->mapToItem(parentWindow->contentItem(), QPointF(x, y));
+ x = pos.x();
+ y = pos.y();
+ }
+
+ x += parentWindow->geometry().left();
+ y += parentWindow->geometry().top();
+ }
+
+ QQuickItem *visualItem = atItem ? atItem->visualItem() : 0;
+ if (visualItem) {
+ QPointF pos = visualItem->position();
+ x -= pos.x();
+ y -= pos.y();
+ m_popupWindow->setItemAt(visualItem);
+ }
+
+ m_popupWindow->setGeometry(x, y, m_menuContentItem->width(), m_menuContentItem->height());
+ m_popupWindow->show();
+ m_popupWindow->setMouseGrabEnabled(true); // Needs to be done after calling show()
+ m_popupWindow->setKeyboardGrabEnabled(true);
+ }
+}
+
+void QtMenu::closeMenu()
+{
+ setPopupVisible(false);
+ if (m_popupWindow)
+ m_popupWindow->setVisible(false);
+ emit menuClosed();
+}
+
+void QtMenu::dismissMenu()
+{
+ if (m_popupWindow)
+ m_popupWindow->dismissMenu();
+}
+
+void QtMenu::windowVisibleChanged(bool v)
+{
+ if (!v) {
+ if (qobject_cast<QtMenuPopupWindow *>(m_popupWindow->transientParent())) {
+ m_popupWindow->transientParent()->setMouseGrabEnabled(true);
+ m_popupWindow->transientParent()->setKeyboardGrabEnabled(true);
+ }
+ m_popupWindow->deleteLater();
+ m_popupWindow = 0;
+ closeMenu();
+ }
+}
+
+void QtMenu::clearMenuItems()
+{
+ foreach (QtMenuBase *item, m_menuItems) {
+ if (m_platformMenu)
+ m_platformMenu->removeMenuItem(item->platformItem());
+ delete item;
+ }
+ m_menuItems.clear();
+}
+
+QtMenuItem *QtMenu::addMenuItem(const QString &text)
+{
+ QtMenuItem *menuItem = new QtMenuItem(this);
+ menuItem->setText(text);
+ m_menuItems.append(menuItem);
+ if (QPlatformMenuItem *platformItem = menuItem->platformItem()) {
+ if (m_platformMenu)
+ m_platformMenu->insertMenuItem(platformItem, 0 /* append */);
+
+ connect(platformItem, SIGNAL(activated()), this, SLOT(emitSelected()));
+ }
+
+ if (m_menuItems.size() == 1)
+ // Inform QML that the selected action (0) now has changed contents:
+ emit selectedIndexChanged();
+
+ emit menuItemsChanged();
+ return menuItem;
+}
+
+void QtMenu::emitSelected()
+{
+ QPlatformMenuItem *platformItem = qobject_cast<QPlatformMenuItem *>(sender());
+ if (!platformItem)
+ return;
+
+ int index = -1;
+ foreach (QtMenuBase *item, m_menuItems) {
+ ++index;
+ if (item->platformItem() == platformItem)
+ break;
+ }
+
+ setSelectedIndex(index);
+}
+
+QString QtMenu::itemTextAt(int index) const
+{
+ QtMenuItem *mi = 0;
+ if (index >= 0 && index < m_menuItems.size()
+ && (mi = qobject_cast<QtMenuItem *>(m_menuItems.at(index))))
+ return mi->text();
+ else
+ return "";
+}
+
+QString QtMenu::modelTextAt(int index) const
+{
+ if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel*>(m_model.value<QObject*>())) {
+ return model->data(model->index(index, 0)).toString();
+ } else if (m_model.canConvert(QVariant::StringList)) {
+ return m_model.toStringList().at(index);
+ }
+ return "";
+}
+
+int QtMenu::modelCount() const
+{
+ if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel*>(m_model.value<QObject*>())) {
+ return model->rowCount();
+ } else if (m_model.canConvert(QVariant::StringList)) {
+ return m_model.toStringList().count();
+ }
+ return -1;
+}
+
+void QtMenu::append_menuItems(QQmlListProperty<QtMenuBase> *list, QtMenuBase *menuItem)
+{
+ QtMenu *menu = qobject_cast<QtMenu *>(list->object);
+ if (menu) {
+ menuItem->setParent(menu);
+ menu->m_menuItems.append(menuItem);
+ if (menu->m_platformMenu)
+ menu->m_platformMenu->insertMenuItem(menuItem->platformItem(), 0 /* append */);
+ }
+}
+
+int QtMenu::count_menuItems(QQmlListProperty<QtMenuBase> *list)
+{
+ QtMenu *menu = qobject_cast<QtMenu *>(list->object);
+ if (menu)
+ return menu->m_menuItems.size();
+ return 0;
+}
+
+QtMenuBase *QtMenu::at_menuItems(QQmlListProperty<QtMenuBase> *list, int index)
+{
+ QtMenu *menu = qobject_cast<QtMenu *>(list->object);
+ if (menu && 0 <= index && index < menu->m_menuItems.size())
+ return menu->m_menuItems[index];
+ return 0;
+}
+
+
+void QtMenu::setModel(const QVariant &newModel) {
+ if (m_model != newModel) {
+
+ // Clean up any existing connections
+ if (QAbstractItemModel *oldModel = qobject_cast<QAbstractItemModel*>(m_model.value<QObject*>())) {
+ disconnect(oldModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SIGNAL(rebuildMenu()));
+ }
+
+ m_hasNativeModel = false;
+ m_model = newModel;
+
+ if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel*>(newModel.value<QObject*>())) {
+ m_hasNativeModel = true;
+ connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SIGNAL(rebuildMenu()));
+ } else if (newModel.canConvert(QVariant::StringList)) {
+ m_hasNativeModel = true;
+ }
+ emit modelChanged(m_model);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qtmenu_p.h b/src/controls/qtmenu_p.h
new file mode 100644
index 00000000..d34138ac
--- /dev/null
+++ b/src/controls/qtmenu_p.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QTMENU_P_H
+#define QTMENU_P_H
+#include <QtCore/qglobal.h>
+#include <QtQuick/QtQuick>
+#include <QtQml/QtQml>
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/QVariant>
+#include "qtmenuitem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPlatformMenu;
+class QtMenuPopupWindow;
+
+class QtMenu : public QtMenuItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged)
+ Q_PROPERTY(int minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged)
+ Q_PROPERTY(QFont font WRITE setFont)
+ Q_PROPERTY(QQmlListProperty<QtMenuBase> menuItems READ menuItems NOTIFY menuItemsChanged)
+ Q_CLASSINFO("DefaultProperty", "menuItems")
+ Q_PROPERTY(QQuickItem *menuContentItem READ menuContentItem WRITE setMenuContentItem NOTIFY menuContentItemChanged)
+ Q_PROPERTY(bool popupVisible READ popupVisible NOTIFY popupVisibleChanged)
+
+public:
+ QtMenu(QObject *parent = 0);
+ virtual ~QtMenu();
+
+ int selectedIndex() const { return m_selectedIndex; }
+ void setSelectedIndex(int index);
+
+ QQmlListProperty<QtMenuBase> menuItems();
+
+ QPlatformMenu* platformMenu() { return m_platformMenu; }
+
+ int minimumWidth() const { return m_minimumWidth; }
+ void setMinimumWidth(int w);
+
+ void setFont(const QFont &font);
+
+ Q_INVOKABLE void showPopup(qreal x, qreal y, int atActionIndex = -1, QObject *reference = 0);
+ Q_INVOKABLE void clearMenuItems();
+ Q_INVOKABLE QtMenuItem *addMenuItem(const QString &text);
+ Q_INVOKABLE QString itemTextAt(int index) const; // TODO Remove, it's useless
+ Q_INVOKABLE QString modelTextAt(int index) const;
+ Q_INVOKABLE int modelCount() const;
+
+ QVariant model() const { return m_model; }
+ Q_INVOKABLE bool hasNativeModel() const { return m_hasNativeModel; }
+
+ QQuickItem *menuContentItem() const
+ {
+ return m_menuContentItem;
+ }
+
+ bool popupVisible() const
+ {
+ return m_popupVisible;
+ }
+
+public Q_SLOTS:
+ void setModel(const QVariant &newModel);
+ void closeMenu();
+ void dismissMenu();
+
+ void setMenuContentItem(QQuickItem * arg)
+ {
+ if (m_menuContentItem != arg) {
+ m_menuContentItem = arg;
+ emit menuContentItemChanged(arg);
+ }
+ }
+
+ void setPopupVisible(bool arg)
+ {
+ if (m_popupVisible != arg) {
+ m_popupVisible = arg;
+ emit popupVisibleChanged(arg);
+ }
+ }
+
+Q_SIGNALS:
+ void menuClosed();
+ void selectedIndexChanged();
+ void modelChanged(const QVariant &newModel);
+ void rebuildMenu();
+ void minimumWidthChanged();
+ void menuItemsChanged();
+ void menuContentItemChanged(QQuickItem * arg);
+
+ void popupVisibleChanged(bool arg);
+
+protected:
+ bool isNative() { return m_platformMenu != 0; }
+
+protected Q_SLOTS:
+ void emitSelected();
+ void updateText();
+ void windowVisibleChanged(bool);
+
+private:
+ static void append_menuItems(QQmlListProperty<QtMenuBase> *list, QtMenuBase *menuItem);
+ static int count_menuItems(QQmlListProperty<QtMenuBase> *list);
+ static QtMenuBase *at_menuItems(QQmlListProperty<QtMenuBase> *list, int index);
+
+ QPlatformMenu *m_platformMenu;
+ QList<QtMenuBase *> m_menuItems;
+ int m_selectedIndex;
+ int m_highlightedIndex;
+ bool m_hasNativeModel;
+ QVariant m_model;
+ int m_minimumWidth;
+ QtMenuPopupWindow *m_popupWindow;
+ QQuickItem * m_menuContentItem;
+ bool m_popupVisible;
+
+ friend class QtMenuBase;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QtMenu)
+
+#endif // QTMENU_P_H
diff --git a/src/controls/qtmenubar.cpp b/src/controls/qtmenubar.cpp
new file mode 100644
index 00000000..ff4a2031
--- /dev/null
+++ b/src/controls/qtmenubar.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qtmenubar_p.h"
+
+#include "private/qguiapplication_p.h"
+#include <QtGui/qpa/qplatformtheme.h>
+#include <QtGui/qpa/qplatformmenu.h>
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QtMenuBar
+ \internal
+ */
+
+/*!
+ \qmltype MenuBarPrivate
+ \instantiates QtMenuBar
+ \internal
+ \inqmlmodule QtQuick.Controls 1.0
+ */
+QtMenuBar::QtMenuBar(QQuickItem *parent)
+ : QQuickItem(parent)
+{
+ connect(this, SIGNAL(parentChanged(QQuickItem *)), this, SLOT(updateParent(QQuickItem *)));
+ m_platformMenuBar = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
+}
+
+QtMenuBar::~QtMenuBar()
+{
+}
+
+QQmlListProperty<QtMenu> QtMenuBar::menus()
+{
+ return QQmlListProperty<QtMenu>(this, 0, &QtMenuBar::append_menu, &QtMenuBar::count_menu, &QtMenuBar::at_menu, 0);
+}
+
+bool QtMenuBar::isNative() {
+ return m_platformMenuBar != 0;
+}
+
+void QtMenuBar::updateParent(QQuickItem *newParent)
+{
+ QWindow *newParentWindow = newParent ? newParent->window() : 0;
+ if (newParentWindow != window() && m_platformMenuBar)
+ m_platformMenuBar->handleReparent(newParentWindow);
+}
+
+void QtMenuBar::append_menu(QQmlListProperty<QtMenu> *list, QtMenu *menu)
+{
+ if (QtMenuBar *menuBar = qobject_cast<QtMenuBar *>(list->object)) {
+ menu->setParent(menuBar);
+ menuBar->m_menus.append(menu);
+
+ if (menuBar->m_platformMenuBar)
+ menuBar->m_platformMenuBar->insertMenu(menu->platformMenu(), 0 /* append */);
+
+ menuBar->menuChanged();
+ }
+}
+
+int QtMenuBar::count_menu(QQmlListProperty<QtMenu> *list)
+{
+ if (QtMenuBar *menuBar = qobject_cast<QtMenuBar *>(list->object))
+ return menuBar->m_menus.size();
+ return 0;
+}
+
+QtMenu *QtMenuBar::at_menu(QQmlListProperty<QtMenu> *list, int index)
+{
+ QtMenuBar *menuBar = qobject_cast<QtMenuBar *>(list->object);
+ if (menuBar && 0 <= index && index < menuBar->m_menus.size())
+ return menuBar->m_menus[index];
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qtmenubar_p.h b/src/controls/qtmenubar_p.h
new file mode 100644
index 00000000..eb9e8ea5
--- /dev/null
+++ b/src/controls/qtmenubar_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QTMENUBAR_P_H
+#define QTMENUBAR_P_H
+
+#include <QtCore/qglobal.h>
+
+#include <QtQuick/QQuickItem>
+
+#include "qtmenu_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPlatformMenuBar;
+
+class QtMenuBar: public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQmlListProperty<QtMenu> menus READ menus NOTIFY menuChanged)
+ Q_CLASSINFO("DefaultProperty", "menus")
+ Q_PROPERTY(bool isNative READ isNative CONSTANT)
+
+public:
+ QtMenuBar(QQuickItem *parent = 0);
+ ~QtMenuBar();
+
+ QQmlListProperty<QtMenu> menus();
+
+ bool isNative();
+
+signals:
+ void menuChanged();
+
+protected Q_SLOTS:
+ void updateParent(QQuickItem *newParent);
+
+private:
+ static void append_menu(QQmlListProperty<QtMenu> *list, QtMenu *menu);
+ static int count_menu(QQmlListProperty<QtMenu> *list);
+ static QtMenu *at_menu(QQmlListProperty<QtMenu> *list, int index);
+
+private:
+ QList<QtMenu *> m_menus;
+ QPlatformMenuBar *m_platformMenuBar;
+ QQuickWindow *m_parentWindow;
+};
+
+QT_END_NAMESPACE
+
+#endif //QTMENUBAR_P_H
diff --git a/src/controls/qtmenuitem.cpp b/src/controls/qtmenuitem.cpp
new file mode 100644
index 00000000..6da06c4e
--- /dev/null
+++ b/src/controls/qtmenuitem.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qtmenuitem_p.h"
+#include "qtaction_p.h"
+#include "qtmenu_p.h"
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformtheme.h>
+#include <QtGui/qpa/qplatformmenu.h>
+#include <QtQuick/QQuickItem>
+
+QT_BEGIN_NAMESPACE
+
+QtMenuBase::QtMenuBase(QObject *parent)
+ : QObject(parent), m_visualItem(0)
+{
+ m_platformItem = QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
+}
+
+QtMenuBase::~QtMenuBase()
+{
+ delete m_platformItem;
+}
+
+void QtMenuBase::syncWithPlatformMenu()
+{
+ QtMenu *menu = qobject_cast<QtMenu *>(parent());
+ if (menu && menu->platformMenu() && platformItem()
+ && menu->m_menuItems.contains(this)) // If not, it'll be added later and then sync'ed
+ menu->platformMenu()->syncMenuItem(platformItem());
+}
+
+QQuickItem *QtMenuBase::visualItem() const
+{
+ return m_visualItem;
+}
+
+void QtMenuBase::setVisualItem(QQuickItem *item)
+{
+ m_visualItem = item;
+}
+
+
+/*!
+ \qmltype MenuSeparator
+ \instantiates QtMenuSeparator
+ \inqmlmodule QtQuick.Controls 1.0
+ \inherits Item
+ \ingroup menus
+ \brief MenuSeparator provides a separator for your items inside a menu.
+
+ \sa Menu, MenuItem
+*/
+
+QtMenuSeparator::QtMenuSeparator(QObject *parent)
+ : QtMenuBase(parent)
+{
+ if (platformItem())
+ platformItem()->setIsSeparator(true);
+}
+
+
+/*!
+ \qmltype MenuItem
+ \instantiates QtMenuItem
+ \ingroup menus
+ \inqmlmodule QtQuick.Controls 1.0
+ \brief MenuItem provides an item to add in a menu or a menu bar.
+
+ \code
+ Menu {
+ text: "Edit"
+
+ MenuItem {
+ text: "Cut"
+ shortcut: "Ctrl+X"
+ onTriggered: ...
+ }
+
+ MenuItem {
+ text: "Copy"
+ shortcut: "Ctrl+C"
+ onTriggered: ...
+ }
+
+ MenuItem {
+ text: "Paste"
+ shortcut: "Ctrl+V"
+ onTriggered: ...
+ }
+ }
+ \endcode
+
+ \sa MenuBar, Menu, MenuSeparator, Action
+*/
+
+/*!
+ \qmlproperty string MenuItem::text
+
+ Text for the menu item.
+*/
+
+/*!
+ \qmlproperty string MenuItem::shortcut
+
+ Shorcut bound to the menu item.
+
+ \sa Action::shortcut
+*/
+
+/*!
+ \qmlproperty bool MenuItem::checkable
+
+ Whether the menu item can be toggled.
+
+ \sa checked
+*/
+
+/*!
+ \qmlproperty bool MenuItem::checked
+
+ If the menu item is checkable, this property reflects its checked state.
+
+ \sa chekcable, Action::toggled()
+*/
+
+/*!
+ \qmlproperty url MenuItem::iconSource
+
+ \sa iconName, Action::iconSource
+*/
+
+/*!
+ \qmlproperty string MenuItem::iconName
+
+ \sa iconSource, Action::iconName
+*/
+
+/*!
+ \qmlproperty Action MenuItem::action
+
+ The action bound to this menu item.
+
+ \sa Action
+*/
+
+/*! \qmlsignal MenuItem::triggered()
+
+ Emitted when either the menu item or its bound action have been activated.
+
+ \sa trigger(), Action::triggered(), Action::toggled()
+*/
+
+/*! \qmlmethod MenuItem::trigger()
+
+ Manually trigger a menu item. Will also trigger the item's bound action.
+
+ \sa triggered(), Action::trigger()
+*/
+
+QtMenuItem::QtMenuItem(QObject *parent)
+ : QtMenuBase(parent), m_action(0)
+{ }
+
+QtMenuItem::~QtMenuItem()
+{
+ unbindFromAction(m_action);
+}
+
+void QtMenuItem::bindToAction(QtAction *action)
+{
+ m_action = action;
+
+ if (platformItem()) {
+ connect(platformItem(), SIGNAL(activated()), m_action, SLOT(trigger()));
+ }
+
+ connect(m_action, SIGNAL(destroyed(QObject*)), this, SLOT(unbindFromAction(QObject*)));
+
+ connect(m_action, SIGNAL(triggered()), this, SIGNAL(triggered()));
+ connect(m_action, SIGNAL(toggled(bool)), this, SLOT(updateChecked()));
+ connect(m_action, SIGNAL(exclusiveGroupChanged()), this, SIGNAL(exclusiveGroupChanged()));
+ connect(m_action, SIGNAL(enabledChanged()), this, SLOT(updateEnabled()));
+ connect(m_action, SIGNAL(textChanged()), this, SLOT(updateText()));
+ connect(m_action, SIGNAL(shortcutChanged(QString)), this, SLOT(updateShortcut()));
+ connect(m_action, SIGNAL(checkableChanged()), this, SIGNAL(checkableChanged()));
+ connect(m_action, SIGNAL(iconNameChanged()), this, SLOT(updateIconName()));
+ connect(m_action, SIGNAL(iconSourceChanged()), this, SLOT(updateIconSource()));
+
+ if (m_action->parent() != this) {
+ updateText();
+ updateShortcut();
+ updateEnabled();
+ updateIconName();
+ updateIconSource();
+ if (checkable())
+ updateChecked();
+ }
+}
+
+void QtMenuItem::unbindFromAction(QObject *o)
+{
+ if (!o)
+ return;
+
+ if (o == m_action)
+ m_action = 0;
+
+ QtAction *action = qobject_cast<QtAction *>(o);
+ if (!action)
+ return;
+
+ if (platformItem()) {
+ disconnect(platformItem(), SIGNAL(activated()), action, SLOT(trigger()));
+ }
+
+ disconnect(action, SIGNAL(destroyed(QObject*)), this, SLOT(unbindFromAction(QObject*)));
+
+ disconnect(action, SIGNAL(triggered()), this, SIGNAL(triggered()));
+ disconnect(action, SIGNAL(toggled(bool)), this, SLOT(updateChecked()));
+ disconnect(action, SIGNAL(exclusiveGroupChanged()), this, SIGNAL(exclusiveGroupChanged()));
+ disconnect(action, SIGNAL(enabledChanged()), this, SLOT(updateEnabled()));
+ disconnect(action, SIGNAL(textChanged()), this, SLOT(updateText()));
+ disconnect(action, SIGNAL(shortcutChanged(QString)), this, SLOT(updateShortcut()));
+ disconnect(action, SIGNAL(checkableChanged()), this, SIGNAL(checkableChanged()));
+ disconnect(action, SIGNAL(iconNameChanged()), this, SLOT(updateIconName()));
+ disconnect(action, SIGNAL(iconSourceChanged()), this, SLOT(updateIconSource()));
+}
+
+QtAction *QtMenuItem::action()
+{
+ if (!m_action)
+ bindToAction(new QtAction(this));
+ return m_action;
+}
+
+void QtMenuItem::setAction(QtAction *a)
+{
+ if (a == m_action)
+ return;
+
+ if (m_action) {
+ if (m_action->parent() == this)
+ delete m_action;
+ else
+ unbindFromAction(m_action);
+ }
+
+ bindToAction(a);
+ emit actionChanged();
+}
+
+QtMenu *QtMenuItem::parentMenu() const
+{
+ return qobject_cast<QtMenu *>(parent());
+}
+
+QString QtMenuItem::text() const
+{
+ return m_action ? m_action->text() : QString();
+}
+
+void QtMenuItem::setText(const QString &text)
+{
+ action()->setText(text);
+}
+
+void QtMenuItem::updateText()
+{
+ if (platformItem()) {
+ platformItem()->setText(text());
+ syncWithPlatformMenu();
+ }
+ emit textChanged();
+}
+
+QString QtMenuItem::shortcut() const
+{
+ return m_action ? m_action->shortcut() : QString();
+}
+
+void QtMenuItem::setShortcut(const QString &shortcut)
+{
+ action()->setShortcut(shortcut);
+}
+
+void QtMenuItem::updateShortcut()
+{
+ if (platformItem()) {
+ platformItem()->setShortcut(QKeySequence(shortcut()));
+ syncWithPlatformMenu();
+ }
+ emit shortcutChanged();
+}
+
+bool QtMenuItem::checkable() const
+{
+ return m_action ? m_action->isCheckable() : false;
+}
+
+void QtMenuItem::setCheckable(bool checkable)
+{
+ action()->setCheckable(checkable);
+}
+
+bool QtMenuItem::checked() const
+{
+ return m_action ? m_action->isChecked() : false;
+}
+
+void QtMenuItem::setChecked(bool checked)
+{
+ action()->setChecked(checked);
+}
+
+void QtMenuItem::updateChecked()
+{
+ bool checked = this->checked();
+ if (platformItem()) {
+ platformItem()->setChecked(checked);
+ syncWithPlatformMenu();
+ }
+ emit toggled(checked);
+}
+
+QtExclusiveGroup *QtMenuItem::exclusiveGroup() const
+{
+ return m_action ? m_action->exclusiveGroup() : 0;
+}
+
+void QtMenuItem::setExclusiveGroup(QtExclusiveGroup *eg)
+{
+ action()->setExclusiveGroup(eg);
+}
+
+bool QtMenuItem::enabled() const
+{
+ return m_action ? m_action->isEnabled() : false;
+}
+
+void QtMenuItem::setEnabled(bool enabled)
+{
+ action()->setEnabled(enabled);
+}
+
+void QtMenuItem::updateEnabled()
+{
+ if (platformItem()) {
+ platformItem()->setEnabled(enabled());
+ syncWithPlatformMenu();
+ }
+ emit enabledChanged();
+}
+
+QUrl QtMenuItem::iconSource() const
+{
+ return m_action ? m_action->iconSource() : QUrl();
+}
+
+void QtMenuItem::setIconSource(const QUrl &iconSource)
+{
+ action()->setIconSource(iconSource);
+}
+
+void QtMenuItem::updateIconSource()
+{
+ if (platformItem()) {
+ platformItem()->setIcon(m_action->icon());
+ syncWithPlatformMenu();
+ }
+ emit iconSourceChanged();
+}
+
+QString QtMenuItem::iconName() const
+{
+ return m_action ? m_action->iconName() : QString();
+}
+
+void QtMenuItem::setIconName(const QString &iconName)
+{
+ action()->setIconName(iconName);
+}
+
+void QtMenuItem::updateIconName()
+{
+ if (platformItem()) {
+ platformItem()->setIcon(m_action->icon());
+ syncWithPlatformMenu();
+ }
+ emit iconNameChanged();
+}
+
+void QtMenuItem::trigger()
+{
+ if (m_action)
+ m_action->trigger();
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qtmenuitem_p.h b/src/controls/qtmenuitem_p.h
new file mode 100644
index 00000000..f9227f26
--- /dev/null
+++ b/src/controls/qtmenuitem_p.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QTMENUITEM_P_H
+#define QTMENUITEM_P_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPointF>
+#include <QtCore/QPointer>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class QUrl;
+class QPlatformMenuItem;
+class QQuickItem;
+class QtAction;
+class QtExclusiveGroup;
+class QtMenu;
+
+class QtMenuBase: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool isNative READ isNative CONSTANT)
+ Q_PROPERTY(QQuickItem * __visualItem WRITE setVisualItem)
+
+public:
+ QtMenuBase(QObject *parent = 0);
+ ~QtMenuBase();
+
+ inline QPlatformMenuItem *platformItem() { return m_platformItem; }
+
+ void syncWithPlatformMenu();
+
+ QQuickItem *visualItem() const;
+ void setVisualItem(QQuickItem *item);
+
+protected:
+ virtual bool isNative() { return m_platformItem != 0; }
+
+private:
+ QPlatformMenuItem *m_platformItem;
+ QPointer<QQuickItem> m_visualItem;
+};
+
+class QtMenuSeparator : public QtMenuBase
+{
+ Q_OBJECT
+public:
+ QtMenuSeparator(QObject *parent = 0);
+};
+
+class QtMenuItem: public QtMenuBase
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QString shortcut READ shortcut WRITE setShortcut NOTIFY shortcutChanged)
+ Q_PROPERTY(bool checkable READ checkable WRITE setCheckable NOTIFY checkableChanged)
+ Q_PROPERTY(bool checked READ checked WRITE setChecked NOTIFY toggled)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(QUrl iconSource READ iconSource WRITE setIconSource NOTIFY iconSourceChanged)
+ Q_PROPERTY(QString iconName READ iconName WRITE setIconName NOTIFY iconNameChanged)
+ Q_PROPERTY(QtExclusiveGroup *exclusiveGroup READ exclusiveGroup WRITE setExclusiveGroup NOTIFY exclusiveGroupChanged)
+
+ Q_PROPERTY(QtAction *action READ action WRITE setAction NOTIFY actionChanged)
+ Q_PROPERTY(QtMenu *parentMenu READ parentMenu)
+
+public:
+ QtMenuItem(QObject *parent = 0);
+ ~QtMenuItem();
+
+ QtAction *action();
+ void setAction(QtAction *a);
+
+ QtMenu *parentMenu() const;
+
+ QString text() const;
+ void setText(const QString &text);
+
+ QString shortcut() const;
+ void setShortcut(const QString &shortcut);
+
+ bool checkable() const;
+ void setCheckable(bool checkable);
+
+ bool checked() const;
+ void setChecked(bool checked);
+
+ QtExclusiveGroup *exclusiveGroup() const;
+ void setExclusiveGroup(QtExclusiveGroup *);
+
+ bool enabled() const;
+ void setEnabled(bool enabled);
+
+ QUrl iconSource() const;
+ void setIconSource(const QUrl &icon);
+ QString iconName() const;
+ void setIconName(const QString &icon);
+
+Q_SIGNALS:
+ void triggered();
+ void textChanged();
+ void shortcutChanged();
+ void checkableChanged();
+ void exclusiveGroupChanged();
+ void toggled(bool);
+ void enabledChanged();
+
+ void iconSourceChanged();
+ void iconNameChanged();
+
+ void actionChanged();
+
+public Q_SLOTS:
+ void trigger();
+
+protected Q_SLOTS:
+ virtual void updateText();
+ void updateShortcut();
+ void updateChecked();
+ void updateEnabled();
+ void updateIconName();
+ void updateIconSource();
+ void bindToAction(QtAction *action);
+ void unbindFromAction(QObject *action);
+
+private:
+ QtAction *m_action;
+};
+
+QT_END_NAMESPACE
+
+#endif //QTMENUITEM_P_H
diff --git a/src/controls/qtmenupopupwindow.cpp b/src/controls/qtmenupopupwindow.cpp
new file mode 100644
index 00000000..4baec976
--- /dev/null
+++ b/src/controls/qtmenupopupwindow.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#include "qtmenupopupwindow_p.h"
+#include "qtmenu_p.h"
+#include <QtGui/QGuiApplication>
+#include <QtCore/QEvent>
+
+QT_BEGIN_NAMESPACE
+
+QtMenuPopupWindow::QtMenuPopupWindow(QWindow *parent) :
+ QQuickWindow(parent), m_pressedInside(true), m_itemAt(0)
+{
+ setFlags(Qt::Popup);
+ setModality(Qt::WindowModal);
+}
+
+void QtMenuPopupWindow::setMenuContentItem(QQuickItem *contentItem)
+{
+ if (!contentItem)
+ return;
+
+ contentItem->setParentItem(this->contentItem());
+ connect(contentItem, SIGNAL(widthChanged()), this, SLOT(updateSize()));
+ connect(contentItem, SIGNAL(heightChanged()), this, SLOT(updateSize()));
+}
+
+void QtMenuPopupWindow::setItemAt(const QQuickItem *menuItem)
+{
+ if (m_itemAt) {
+ disconnect(m_itemAt, SIGNAL(xChanged()), this, SLOT(updatePosition()));
+ disconnect(m_itemAt, SIGNAL(yChanged()), this, SLOT(updatePosition()));
+ }
+
+ m_itemAt = menuItem;
+ if (menuItem) {
+ m_oldItemPos = menuItem->position().toPoint();
+ connect(menuItem, SIGNAL(xChanged()), this, SLOT(updatePosition()));
+ connect(menuItem, SIGNAL(yChanged()), this, SLOT(updatePosition()));
+ }
+}
+
+void QtMenuPopupWindow::setParentWindow(QQuickWindow *parentWindow)
+{
+ setTransientParent(parentWindow);
+ if (parentWindow) {
+ connect(parentWindow, SIGNAL(destroyed()), this, SLOT(dismissMenu()));
+ if (QtMenuPopupWindow *pw = qobject_cast<QtMenuPopupWindow *>(parentWindow))
+ connect(this, SIGNAL(menuDismissed()), pw, SLOT(dismissMenu()));
+ }
+}
+
+void QtMenuPopupWindow::dismissMenu()
+{
+ close();
+
+ emit menuDismissed();
+}
+
+void QtMenuPopupWindow::updateSize()
+{
+ QSize contentSize = contentItem()->childrenRect().size().toSize();
+ setWidth(contentSize.width());
+ setHeight(contentSize.height());
+}
+
+void QtMenuPopupWindow::updatePosition()
+{
+ QPointF newPos = position() + m_oldItemPos - m_itemAt->position();
+ setPosition(newPos.toPoint());
+}
+
+void QtMenuPopupWindow::mouseMoveEvent(QMouseEvent *e)
+{
+ QRect rect = QRect(QPoint(), size());
+ QWindow *parentMenuWindow = /*qobject_cast<QtMenuPopupWindow*>*/(transientParent());
+ if (parentMenuWindow && !rect.contains(e->pos())) {
+ forwardEventToTransientParent(e);
+ } else {
+ QQuickWindow::mouseMoveEvent(e);
+ }
+}
+
+void QtMenuPopupWindow::mousePressEvent(QMouseEvent *e)
+{
+ QRect rect = QRect(QPoint(), size());
+ m_pressedInside = rect.contains(e->pos());
+ if (m_pressedInside)
+ QQuickWindow::mousePressEvent(e);
+}
+
+void QtMenuPopupWindow::mouseReleaseEvent(QMouseEvent *e)
+{
+ QRect rect = QRect(QPoint(), size());
+ if (rect.contains(e->pos()))
+ QQuickWindow::mouseReleaseEvent(e);
+ else if (!m_pressedInside)
+ dismissMenu();
+ else
+ forwardEventToTransientParent(e);
+}
+
+void QtMenuPopupWindow::forwardEventToTransientParent(QMouseEvent *e)
+{
+ QWindow *parentMenuWindow = /*qobject_cast<QtMenuPopupWindow*>*/(transientParent());
+ if (!parentMenuWindow)
+ return;
+ QPoint parentPos = parentMenuWindow->mapFromGlobal(mapToGlobal(e->pos()));
+ QMouseEvent pe = QMouseEvent(e->type(), parentPos, e->button(), e->buttons(), e->modifiers());
+ QGuiApplication::sendEvent(parentMenuWindow, &pe);
+}
+
+QT_END_NAMESPACE
diff --git a/src/controls/qtmenupopupwindow_p.h b/src/controls/qtmenupopupwindow_p.h
new file mode 100644
index 00000000..b1a9c051
--- /dev/null
+++ b/src/controls/qtmenupopupwindow_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+
+#ifndef QTMENUPOPUPWINDOW_H
+#define QTMENUPOPUPWINDOW_H
+
+#include <QQuickWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QEvent;
+class QQuickItem;
+
+class QtMenuPopupWindow : public QQuickWindow
+{
+ Q_OBJECT
+public:
+ QtMenuPopupWindow(QWindow *parent = 0);
+ void setMenuContentItem(QQuickItem *contentItem);
+ void setItemAt(const QQuickItem *menuItem);
+ void setParentWindow(QQuickWindow *parentWindow);
+
+public Q_SLOTS:
+ void dismissMenu();
+ void updateSize();
+ void updatePosition();
+
+Q_SIGNALS:
+ void menuDismissed();
+
+protected:
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+
+private:
+ void forwardEventToTransientParent(QMouseEvent *);
+
+ bool m_pressedInside;
+ const QQuickItem *m_itemAt;
+ QPointF m_oldItemPos;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTMENUPOPUPWINDOW_H