summaryrefslogtreecommitdiff
path: root/src/qtdesktop
diff options
context:
space:
mode:
Diffstat (limited to 'src/qtdesktop')
-rw-r--r--src/qtdesktop/ApplicationWindow.qml123
-rw-r--r--src/qtdesktop/Button.qml82
-rw-r--r--src/qtdesktop/ButtonColumn.qml90
-rw-r--r--src/qtdesktop/ButtonRow.qml88
-rw-r--r--src/qtdesktop/CheckBox.qml97
-rw-r--r--src/qtdesktop/ComboBox.qml133
-rw-r--r--src/qtdesktop/ContextMenu.qml124
-rw-r--r--src/qtdesktop/Dial.qml161
-rw-r--r--src/qtdesktop/Dialog.qml164
-rw-r--r--src/qtdesktop/Frame.qml71
-rw-r--r--src/qtdesktop/GroupBox.qml100
-rw-r--r--src/qtdesktop/Label.qml48
-rw-r--r--src/qtdesktop/ProgressBar.qml85
-rw-r--r--src/qtdesktop/RadioButton.qml53
-rw-r--r--src/qtdesktop/ScrollArea.qml139
-rw-r--r--src/qtdesktop/ScrollBar.qml206
-rw-r--r--src/qtdesktop/Slider.qml185
-rw-r--r--src/qtdesktop/SpinBox.qml208
-rw-r--r--src/qtdesktop/SplitterColumn.qml161
-rw-r--r--src/qtdesktop/SplitterRow.qml161
-rw-r--r--src/qtdesktop/StatusBar.qml51
-rw-r--r--src/qtdesktop/Tab.qml48
-rw-r--r--src/qtdesktop/TabBar.qml142
-rw-r--r--src/qtdesktop/TabFrame.qml130
-rw-r--r--src/qtdesktop/TableColumn.qml52
-rw-r--r--src/qtdesktop/TableView.qml650
-rw-r--r--src/qtdesktop/TextArea.qml126
-rw-r--r--src/qtdesktop/TextField.qml175
-rw-r--r--src/qtdesktop/ToolBar.qml51
-rw-r--r--src/qtdesktop/ToolButton.qml74
-rw-r--r--src/qtdesktop/plugins.qmltypes451
-rw-r--r--src/qtdesktop/private/BasicButton.qml108
-rw-r--r--src/qtdesktop/private/ButtonBehavior.qml61
-rw-r--r--src/qtdesktop/private/ButtonGroup.js141
-rw-r--r--src/qtdesktop/private/ModalPopupBehavior.qml130
-rw-r--r--src/qtdesktop/private/ScrollAreaHelper.qml123
-rw-r--r--src/qtdesktop/private/Splitter.qml461
-rw-r--r--src/qtdesktop/qdesktopitem.cpp85
-rw-r--r--src/qtdesktop/qdesktopitem.h80
-rw-r--r--src/qtdesktop/qfiledialogitem.cpp323
-rw-r--r--src/qtdesktop/qfiledialogitem.h132
-rw-r--r--src/qtdesktop/qmldir33
-rw-r--r--src/qtdesktop/qquickcomponentsprivate.cpp63
-rw-r--r--src/qtdesktop/qquickcomponentsprivate.h58
-rw-r--r--src/qtdesktop/qquicklayout.cpp196
-rw-r--r--src/qtdesktop/qquicklayout.h129
-rw-r--r--src/qtdesktop/qquicklayoutengine.cpp291
-rw-r--r--src/qtdesktop/qquicklayoutengine_p.h84
-rw-r--r--src/qtdesktop/qquicklinearlayout.cpp233
-rw-r--r--src/qtdesktop/qquicklinearlayout.h111
-rw-r--r--src/qtdesktop/qrangemodel.cpp534
-rw-r--r--src/qtdesktop/qrangemodel.h125
-rw-r--r--src/qtdesktop/qrangemodel_p.h106
-rw-r--r--src/qtdesktop/qstyleitem.cpp1072
-rw-r--r--src/qtdesktop/qstyleitem.h254
-rw-r--r--src/qtdesktop/qstyleplugin.cpp126
-rw-r--r--src/qtdesktop/qstyleplugin.h57
-rw-r--r--src/qtdesktop/qtdesktop.pro58
-rw-r--r--src/qtdesktop/qtmenu.cpp234
-rw-r--r--src/qtdesktop/qtmenu.h121
-rw-r--r--src/qtdesktop/qtmenubar.cpp93
-rw-r--r--src/qtdesktop/qtmenubar.h88
-rw-r--r--src/qtdesktop/qtmenuitem.cpp154
-rw-r--r--src/qtdesktop/qtmenuitem.h126
-rw-r--r--src/qtdesktop/qtsplitterbase.cpp93
-rw-r--r--src/qtdesktop/qtsplitterbase.h123
-rw-r--r--src/qtdesktop/qwheelarea.cpp181
-rw-r--r--src/qtdesktop/qwheelarea.h119
-rw-r--r--src/qtdesktop/styleplugin.json1
-rw-r--r--src/qtdesktop/styleplugin.pri35
70 files changed, 10971 insertions, 0 deletions
diff --git a/src/qtdesktop/ApplicationWindow.qml b/src/qtdesktop/ApplicationWindow.qml
new file mode 100644
index 00000000..fe35b6c8
--- /dev/null
+++ b/src/qtdesktop/ApplicationWindow.qml
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+Window {
+ id: root
+ width: 320
+ height: 240
+
+ property MenuBar menuBar
+ property alias toolBar: toolBarArea.data
+ property alias statusBar: statusBarArea.data
+ default property alias data: contentArea.data
+ property alias backgroundColor: syspal.window
+ property bool showMenuBar: menuBar ? menuBar.showMenuBar : false
+
+ SystemPalette {id: syspal}
+
+ Rectangle {
+ anchors.fill: parent
+ color: backgroundColor
+ }
+
+ StyleItem {
+ id: menuBarArea
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ elementType: "menubar"
+ visible: showMenuBar
+ contentHeight: showMenuBar ? 20 : 0
+ Row {
+ id: row
+ anchors.fill: parent
+ Repeater {
+ model: showMenuBar ? menuBar.menuList.length : 0
+ StyleItem {
+ id: menuItem
+ elementType: "menubaritem"
+ contentWidth: 100
+ contentHeight: 20
+ width: text.paintedWidth + 12
+ height :text.paintedHeight + 4
+ sunken: true
+ selected: mouse.pressed
+ property var menu: menuBar.menuList[index]
+ Text {
+ id: text
+ text: menu.text
+ anchors.centerIn: parent
+ renderType: Text.NativeRendering
+ }
+ MouseArea {
+ id: mouse
+ anchors.fill:parent
+ onPressed: menu.showPopup(menuItem.x, menuBarArea.height, 0, root)
+ }
+ }
+ }
+ }
+ }
+
+ Row {
+ id: toolBarArea
+ anchors.top: menuBarArea.bottom
+ 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
+ }
+}
diff --git a/src/qtdesktop/Button.qml b/src/qtdesktop/Button.qml
new file mode 100644
index 00000000..b82e0ebd
--- /dev/null
+++ b/src/qtdesktop/Button.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 QtDesktop 1.0
+import "private"
+import "Styles/Settings.js" as Settings
+
+BasicButton {
+ id: button
+
+ property bool defaultbutton: false
+ property var styleHintss
+ property string text
+ property url iconSource
+
+ Accessible.name: text
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/ButtonStyle.qml")
+
+// ## TODO: move to style implementation
+// label: Item {
+// // Used as a fallback since I can't pass the imageURL
+// // directly to the style object
+// visible: button.iconSource === ""
+// Row {
+// id: row
+// anchors.centerIn: parent
+// spacing: 4
+// Image {
+// source: iconSource
+// anchors.verticalCenter: parent.verticalCenter
+// fillMode: Image.Stretch //mm Image should shrink if button is too small, depends on QTBUG-14957
+// }
+// Text {
+// id:text
+// color: textColor
+// anchors.verticalCenter: parent.verticalCenter
+// text: button.text
+// horizontalAlignment: Text.Center
+// }
+// }
+// }
+}
+
diff --git a/src/qtdesktop/ButtonColumn.qml b/src/qtdesktop/ButtonColumn.qml
new file mode 100644
index 00000000..50410a32
--- /dev/null
+++ b/src/qtdesktop/ButtonColumn.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 "private/ButtonGroup.js" as Behavior
+
+/*
+ Class: ButtonColumn
+ A ButtonColumn allows you to group Buttons in a column. It provides a selection-behavior as well.
+
+ Note: This component don't support the enabled property.
+ If you need to disable it you should disable all the buttons inside it.
+
+ <code>
+ ButtonColumn {
+ Button { text: "Top" }
+ Button { text: "Bottom" }
+ }
+ </code>
+*/
+Column {
+ id: root
+
+ /*
+ * Property: exclusive
+ * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained
+ * in the group will be exclusive.
+ *
+ * Note that a button in an exclusive group will allways be checkable
+ */
+ property bool exclusive: true
+
+ /*
+ * Property: styleHints
+ * [string] Used to indicate special OS specific button types
+ */
+ property var styleHints:[]
+
+ /*
+ * Property: checkedButton
+ * [string] Contains the last checked Button.
+ */
+ property Item checkedButton;
+
+ Component.onCompleted: {
+ Behavior.create(root, {direction: Qt.Vertical});
+ }
+
+ Component.onDestruction: {
+ Behavior.destroy();
+ }
+
+}
diff --git a/src/qtdesktop/ButtonRow.qml b/src/qtdesktop/ButtonRow.qml
new file mode 100644
index 00000000..9c3c2c16
--- /dev/null
+++ b/src/qtdesktop/ButtonRow.qml
@@ -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 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 "private/ButtonGroup.js" as Behavior
+
+/*
+ Class: ButtonRow
+ A ButtonRow allows you to group Buttons in a row. It provides a selection-behavior as well.
+
+ Note: This component don't support the enabled property.
+ If you need to disable it you should disable all the buttons inside it.
+
+ <code>
+ ButtonRow {
+ Button { text: "Left" }
+ Button { text: "Right" }
+ }
+ </code>
+*/
+Row {
+ id: root
+
+ /*
+ * Property: exclusive
+ * [bool=false] Specifies the grouping behavior. If enabled, the checked property on buttons contained
+ * in the group will be exclusive.
+ *
+ * Note that a button in an exclusive group will allways be checkable
+ */
+ property bool exclusive: false
+
+ /*
+ * Property: styleHints
+ * [string] Used to indicate special OS specific button types
+ */
+ property var styleHints
+ /*
+ * Property: checkedButton
+ * [string] Contains the last checked Button.
+ */
+ property Item checkedButton;
+
+ Component.onCompleted: {
+ Behavior.create(root, {direction: Qt.Horizontal});
+ }
+
+ Component.onDestruction: {
+ Behavior.destroy();
+ }
+}
diff --git a/src/qtdesktop/CheckBox.qml b/src/qtdesktop/CheckBox.qml
new file mode 100644
index 00000000..88f19869
--- /dev/null
+++ b/src/qtdesktop/CheckBox.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+import "private"
+
+
+FocusScope {
+ id: checkBox
+
+ signal clicked
+
+ property alias pressed: behavior.effectivePressed
+ property alias checked: behavior.checked
+ property alias containsMouse: behavior.containsMouse
+ property bool activeFocusOnPress: false
+
+ property string text
+ property var styleHints:[]
+
+ // implementation
+ Accessible.role: Accessible.CheckBox
+ Accessible.name: text
+
+ implicitWidth: Math.max(120, loader.item ? loader.item.implicitWidth : 0)
+ implicitHeight: loader.item ? loader.item.implicitHeight : 0
+
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/CheckBoxStyle.qml")
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ property alias control: checkBox
+ sourceComponent: style
+ }
+
+ ButtonBehavior {
+ id: behavior
+ focus: true
+ anchors.fill: parent
+ checkable: true
+ onClicked: checkBox.clicked();
+ onPressed: if (checkBox.activeFocusOnPress) checkBox.forceActiveFocus();
+ }
+
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Space && !event.isAutoRepeat && !behavior.pressed)
+ behavior.keyPressed = true;
+ }
+
+ Keys.onReleased: {
+ if (event.key == Qt.Key_Space && !event.isAutoRepeat && behavior.keyPressed) {
+ behavior.keyPressed = false;
+ checked = !checked;
+ checkBox.clicked();
+ }
+ }
+}
diff --git a/src/qtdesktop/ComboBox.qml b/src/qtdesktop/ComboBox.qml
new file mode 100644
index 00000000..2b50880f
--- /dev/null
+++ b/src/qtdesktop/ComboBox.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "private" as Private
+import "Styles/Settings.js" as Settings
+
+/*
+*
+* ComboBox (inherits BasicButton)
+*
+* The ComboBox component 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.
+* int hoveredIndex - the index of the highlighted item in the popup menu.
+* string selectedText - the text of the selected menu item.
+* string hoveredText - the text of the highlighted menu item.
+*
+* Example 1:
+*
+* ListModel {
+* id: menuItems
+* ListElement { text: "Banana"; color: "Yellow" }
+* ListElement { text: "Apple"; color: "Green" }
+* ListElement { text: "Coconut"; color: "Brown" }
+* }
+* ComboBox {
+* model: menuItems
+* width: 200
+* onSelectedIndexChanged: console.debug(selectedText + ", " + menuItems.get(selectedIndex).color)
+* }
+*
+* Example 2:
+*
+* ComboBox {
+* width: 200
+* MenuItem {
+* text: "Pineapple"
+* onSelected: console.debug(text)
+*
+* }
+* MenuItem {
+* text: "Grape"
+* onSelected: console.debug(text)
+* }
+* }
+*
+*/
+
+Private.BasicButton {
+ id: comboBox
+
+ default property alias menuItems: popup.menuItems
+ property alias model: popup.model
+ property alias popupOpen: popup.visible
+
+ property alias selectedIndex: popup.selectedIndex
+ property alias hoveredIndex: popup.hoveredIndex
+ property alias selectedText: popup.selectedText
+ property alias hoveredText: popup.hoveredText
+ property var styleHints:[]
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/ComboBoxStyle.qml")
+
+// ToDo: adjust margins so that selected popup label
+// centers directly above button label when
+// popup.centerOnSelectedText === true
+
+ width: implicitWidth
+ height: implicitHeight
+ onWidthChanged: popup.setMinimumWidth(width)
+ checkable: false
+ onPressedChanged: if (pressed) popup.visible = true
+
+ ContextMenu {
+ id: popup
+ property bool center: false
+ centerSelectedText: center
+ y: center ? 0 : comboBox.height
+ }
+
+ // The key bindings below will only be in use when popup is
+ // not visible. Otherwise, native popup key handling will take place:
+ Keys.onSpacePressed: { comboBox.popupOpen = !comboBox.popupOpen }
+ Keys.onUpPressed: { if (selectedIndex < model.count - 1) selectedIndex++ }
+ Keys.onDownPressed: { if (selectedIndex > 0) selectedIndex-- }
+}
diff --git a/src/qtdesktop/ContextMenu.qml b/src/qtdesktop/ContextMenu.qml
new file mode 100644
index 00000000..0ba2a920
--- /dev/null
+++ b/src/qtdesktop/ContextMenu.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+Menu {
+ id: root
+ property string selectedText: itemTextAt(selectedIndex)
+ property string hoveredText: itemTextAt(hoveredIndex)
+ property string textRole
+
+ // '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
+
+ visible: false
+ onMenuClosed: visible = false
+ onModelChanged: if (Component.status === Component.Ready && model !== undefined) rebuildMenu()
+
+ Component.onCompleted: if (model !== undefined) rebuildMenu()
+
+ onHoveredIndexChanged: {
+ if (hoveredIndex < menuItems.length)
+ menuItems[hoveredIndex].hovered()
+ }
+
+ onSelectedIndexChanged: {
+ if (hoveredIndex < menuItems.length)
+ menuItems[hoveredIndex].selected()
+ }
+
+ onVisibleChanged: {
+ if (visible) {
+ var globalPos = mapToItem(null, x, y)
+ showPopup(globalPos.x, globalPos.y, centerSelectedText ? selectedIndex : 0)
+ } else {
+ hidePopup()
+ }
+ }
+
+ function rebuildMenu()
+ {
+ clearMenuItems();
+
+ for (var i=0; i<menuItems.length; ++i)
+ addMenuItem(menuItems[i].text)
+
+ 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]
+ }
+ }
+ }
+ addMenuItem(textValue)
+ }
+ }
+ }
+}
diff --git a/src/qtdesktop/Dial.qml b/src/qtdesktop/Dial.qml
new file mode 100644
index 00000000..e235963d
--- /dev/null
+++ b/src/qtdesktop/Dial.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+// jens: ContainsMouse breaks drag functionality
+
+Item {
+ id: dial
+
+ width: 100
+ height: 100
+
+ property alias maximumValue: range.maximumValue
+ property alias minimumValue: range.minimumValue
+ property alias containsMouse: mouseArea.containsMouse
+ property alias value: range.value
+ property alias stepSize: range.stepSize
+
+ property bool wrapping: false
+ property bool tickmarksEnabled: false
+ property bool activeFocusOnPress: false
+
+ Accessible.role: Accessible.Dial
+ Accessible.name: value
+
+ RangeModel {
+ id: range
+ minimumValue: 0.0
+ maximumValue: 1.0
+ stepSize: 0.0
+ value: 0
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill:parent
+ property bool inDrag
+ hoverEnabled:true
+
+ onPositionChanged: {
+ if (pressed) {
+ value = valueFromPoint(mouseX, mouseY)
+ inDrag = true
+ }
+ }
+ onPressed: {
+ value = valueFromPoint(mouseX, mouseY)
+ if (activeFocusOnPress) dial.focus = true
+ }
+
+ onReleased:inDrag = false;
+ function bound(val) { return Math.max(minimumValue, Math.min(maximumValue, val)); }
+
+ function valueFromPoint(x, y)
+ {
+ var yy = height/2.0 - y;
+ var xx = x - width/2.0;
+ var a = (xx || yy) ? Math.atan2(yy, xx) : 0;
+
+ if (a < Math.PI/ -2)
+ a = a + Math.PI * 2;
+
+ var dist = 0;
+ var minv = minimumValue*100, maxv = maximumValue*100;
+
+ if (minimumValue < 0) {
+ dist = -minimumValue;
+ minv = 0;
+ maxv = maximumValue + dist;
+ }
+
+ var r = maxv - minv;
+ var v;
+ if (wrapping)
+ v = (0.5 + minv + r * (Math.PI * 3 / 2 - a) / (2 * Math.PI));
+ else
+ v = (0.5 + minv + r* (Math.PI * 4 / 3 - a) / (Math.PI * 10 / 6));
+
+ if (dist > 0)
+ v -= dist;
+ return maximumValue - bound(v/100)
+ }
+ }
+ StyleItem {
+ anchors.fill: parent
+ elementType: "dial"
+ hasFocus: dial.focus
+ sunken: mouseArea.pressed
+ maximum: range.maximumValue * 100
+ minimum: range.minimumValue * 100
+ value: visualPos * 100
+ enabled: dial.enabled
+ step: range.stepSize * 100
+ activeControl: tickmarksEnabled ? "tick" : ""
+ property double visualPos : range.value
+
+ Behavior on visualPos {
+ enabled: !mouseArea.inDrag
+ NumberAnimation {
+ duration: 300
+ easing.type: Easing.OutSine
+ }
+ }
+ }
+ WheelArea {
+ id: wheelarea
+ anchors.fill: parent
+ horizontalMinimumValue: dial.minimumValue
+ horizontalMaximumValue: dial.maximumValue
+ verticalMinimumValue: dial.minimumValue
+ verticalMaximumValue: dial.maximumValue
+ property double step: (dial.maximumValue - dial.minimumValue)/100
+
+ onVerticalWheelMoved: {
+ value += verticalDelta/4*step
+ }
+
+ onHorizontalWheelMoved: {
+ value += horizontalDelta/4*step
+ }
+ }
+}
diff --git a/src/qtdesktop/Dialog.qml b/src/qtdesktop/Dialog.qml
new file mode 100644
index 00000000..2cf0e9ad
--- /dev/null
+++ b/src/qtdesktop/Dialog.qml
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** 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
+
+Window {
+ id: dialog
+
+ width: 400
+ height: 200
+
+ signal closed
+ signal accepted
+ signal rejected
+ signal buttonClicked
+
+ property QtObject clickedButton: null
+
+ property int noRole: 0
+ property int acceptRole: 1
+ property int rejectRole: 2
+ property int helpRole: 3
+
+ property int ok: 0x00000400
+ property int cancel: 0x00400000
+ property int close: 0x00200000
+ property int help: 0x02000000
+
+ property int buttons: ok | cancel
+
+ modal: false
+
+ default property alias data: content.data
+
+ Item {
+ id: content
+ anchors.topMargin:16
+ anchors.margins: 16
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.left: parent.left
+ anchors.bottom: buttonrow.top
+ }
+
+ // Dialogs should center on parent
+ onVisibleChanged: center()
+
+ Row {
+ property bool mac: (style.style == "mac")
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.margins: 16
+ anchors.topMargin:0
+ anchors.bottomMargin: style.isMac ? 12 : 8
+ spacing: 6
+
+ Button {
+ id: helpbutton
+ property int role: helpRole
+ visible: buttons & help
+ text: "Help"
+ focus: false
+ Component.onCompleted: if (style.isMac) width = 22
+ delegate: style.isMac ? machelpdelegate : cancelbutton.background
+ onClicked: {
+ clickedButton = helpbutton
+ buttonClicked()
+ }
+ Component {
+ id: machelpdelegate
+ StyleItem {
+ anchors.fill: parent
+ elementType: "machelpbutton"
+ width: 22
+ height: 22
+ sunken: helpbutton.pressed
+ anchors.centerIn: parent
+ }
+ }
+ }
+ }
+ Row {
+ id: buttonrow
+ spacing: 6
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 16
+ anchors.topMargin: 0
+ anchors.bottomMargin: 8
+ layoutDirection: style.isMac ? Qt.LeftToRight : Qt.RightToLeft
+
+ Button {
+ id: cancelbutton
+ visible: buttons & cancel
+ property int role: rejectRole
+ text: "Cancel"
+ onClicked: {
+ visible: dialog.visible = false
+ clickedButton = cancelbutton
+ rejected()
+ closed()
+ buttonClicked(role)
+ }
+ }
+ Button {
+ id: okbutton
+ property int role: acceptRole
+ visible: buttons & ok
+ text: "OK"
+ defaultbutton: true
+ onClicked: {
+ visible: dialog.visible = false
+ clickedButton = okbutton
+ accepted()
+ closed()
+ buttonClicked()
+ }
+ }
+ }
+ StyleItem {
+ id: style
+ visible: false
+ property bool isMac: (style.style == "mac")
+
+ }
+}
diff --git a/src/qtdesktop/Frame.qml b/src/qtdesktop/Frame.qml
new file mode 100644
index 00000000..36627176
--- /dev/null
+++ b/src/qtdesktop/Frame.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
+import QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+Item {
+ id: frame
+ default property alias data: content.data
+ implicitWidth: adjustToContentSize ? content.childrenRect.width + 2 * content.frameWidth : 30
+ implicitHeight: adjustToContentSize ? content.childrenRect.height + 2 * content.frameWidth : 30
+
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/FrameStyle.qml")
+
+ property bool raised
+ property bool sunken
+ property bool adjustToContentSize: false
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ sourceComponent: delegate
+ Item {
+ id: content
+ anchors.fill: parent
+ anchors.margins: frameWidth
+ property int frameWidth
+ }
+ onLoaded: item.z = -1
+ }
+
+
+}
diff --git a/src/qtdesktop/GroupBox.qml b/src/qtdesktop/GroupBox.qml
new file mode 100644
index 00000000..dc2e8ccf
--- /dev/null
+++ b/src/qtdesktop/GroupBox.qml
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+Item {
+ id: groupbox
+ implicitWidth: Math.max(200, contentWidth + (loader.item ? loader.item.implicitWidth: 0) )
+ implicitHeight: contentHeight + (loader.item ? loader.item.implicitHeight : 0) + 4
+
+ default property alias data: content.data
+
+ property string title
+ property bool flat: false
+ property bool checkable: false
+ property int contentWidth: content.childrenRect.width
+ property int contentHeight: content.childrenRect.height
+
+ property Item checkbox: check
+ property alias checked: check.checked
+ property bool adjustToContentSize: false // Resizes groupbox to fit contents.
+ // Note when using this, you cannot anchor children
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/GroupBoxStyle.qml")
+
+ 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/qtdesktop/Label.qml b/src/qtdesktop/Label.qml
new file mode 100644
index 00000000..99d3ac71
--- /dev/null
+++ b/src/qtdesktop/Label.qml
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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
+
+Text {
+ id: label
+ font.pixelSize: 11
+ color: pal.text
+ SystemPalette {id:pal}
+}
diff --git a/src/qtdesktop/ProgressBar.qml b/src/qtdesktop/ProgressBar.qml
new file mode 100644
index 00000000..b9b7fafb
--- /dev/null
+++ b/src/qtdesktop/ProgressBar.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
+import QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+Item {
+ id: progressbar
+
+ property real value: 0
+ property real minimumValue: 0
+ property real maximumValue: 1
+ property bool indeterminate: false
+ property bool containsMouse: mouseArea.containsMouse
+
+ property int minimumWidth: 0
+ property int minimumHeight: 0
+
+ property int orientation: Qt.Horizontal
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/ProgressBarStyle.qml")
+ property var styleHints:[]
+
+ Accessible.role: Accessible.ProgressBar
+ Accessible.name: value
+
+ implicitWidth: orientation === Qt.Horizontal ? 200 : (loader.item ? loader.item.implicitHeight : 0)
+ implicitHeight: orientation === Qt.Horizontal ? (loader.item ? loader.item.implicitHeight : 0) : 200
+
+ Loader {
+ id: loader
+ property alias indeterminate: progressbar.indeterminate
+ property alias value: progressbar.value
+ property alias maximumValue: progressbar.maximumValue
+ property alias minimumValue: progressbar.minimumValue
+
+ property alias control: progressbar
+ sourceComponent: style
+ anchors.fill: parent
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+}
+
diff --git a/src/qtdesktop/RadioButton.qml b/src/qtdesktop/RadioButton.qml
new file mode 100644
index 00000000..f5945535
--- /dev/null
+++ b/src/qtdesktop/RadioButton.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+// jb : Size should not depend on background, we should make it consistent
+
+CheckBox {
+ id: radiobutton
+
+ Accessible.role: Accessible.RadioButton
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/RadioButtonStyle.qml")
+}
diff --git a/src/qtdesktop/ScrollArea.qml b/src/qtdesktop/ScrollArea.qml
new file mode 100644
index 00000000..9415797a
--- /dev/null
+++ b/src/qtdesktop/ScrollArea.qml
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "private" as Private
+
+FocusScope {
+ id: root
+ width: 100
+ height: 100
+
+ // Cosmetic propeties
+ property bool frame: true
+ property bool frameAroundContents: true
+ property bool highlightOnFocus: false
+ property alias color: colorRect.color // background color
+ property int frameWidth: frame ? styleitem.frameWidth : 0
+
+ // Item properties
+ property alias horizontalScrollBar: scroller.horizontalScrollBar
+ property alias verticalScrollBar: scroller.verticalScrollBar
+
+ // Viewport properties
+ property int contentX
+ property int contentY
+ property int contentHeight : content.childrenRect.height
+ property int contentWidth: content.childrenRect.width
+ property int viewportHeight: height - (horizontalScrollBar.visible ? verticalScrollBar.height : 0) - 2 * frameWidth
+ property int viewportWidth: width - (verticalScrollBar.visible ? verticalScrollBar.width : 0) - 2 * frameWidth
+ default property alias data: content.data
+
+ Rectangle {
+ id: colorRect
+ color: "transparent"
+ anchors.fill:styleitem
+ anchors.margins: frameWidth
+ }
+
+ StyleItem {
+ id: styleitem
+ elementType: "frame"
+ sunken: true
+ visible: frame
+ anchors.fill: parent
+ anchors.rightMargin: frame ? (frameAroundContents ? (verticalScrollBar.visible ? verticalScrollBar.width + 2 * frameMargins : 0) : 0) : 0
+ anchors.bottomMargin: frame ? (frameAroundContents ? (horizontalScrollBar.visible ? horizontalScrollBar.height + 2 * frameMargins : 0) : 0) : 0
+ anchors.topMargin: frame ? (frameAroundContents ? 0 : 0) : 0
+ property int frameWidth
+ property int scrollbarspacing: styleitem.pixelMetric("scrollbarspacing");
+ property int frameMargins : frame ? scrollbarspacing : 0
+ Component.onCompleted: {
+ frameWidth = styleitem.pixelMetric("defaultframewidth");
+ frameAroundContents = styleitem.styleHint("framearoundcontents")
+ }
+ }
+
+ onContentYChanged: {
+ scroller.blockUpdates = true
+ verticalScrollBar.value = contentY
+ scroller.verticalValue = contentY
+ scroller.blockUpdates = false
+ }
+
+ onContentXChanged: {
+ scroller.blockUpdates = true
+ horizontalScrollBar.value = contentX
+ scroller.horizontalValue = contentX
+ scroller.blockUpdates = false
+ }
+
+ Item {
+ id: clipper
+ anchors.fill: styleitem
+ anchors.margins: frameWidth
+ clip: true
+ Item {
+ id: content
+ x: -root.contentX
+ y: -root.contentY
+ }
+ }
+
+
+ Private.ScrollAreaHelper {
+ id: scroller
+ anchors.fill: parent
+ }
+
+ StyleItem {
+ z: 2
+ anchors.fill: parent
+
+ anchors.topMargin: -3
+ anchors.leftMargin: -3
+ anchors.rightMargin: -5
+ anchors.bottomMargin: -5
+
+ visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget")
+ elementType: "focusframe"
+ }
+}
diff --git a/src/qtdesktop/ScrollBar.qml b/src/qtdesktop/ScrollBar.qml
new file mode 100644
index 00000000..5e20190c
--- /dev/null
+++ b/src/qtdesktop/ScrollBar.qml
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+Item {
+ id: scrollbar
+
+ property int orientation: Qt.Horizontal
+ property alias minimumValue: slider.minimumValue
+ property alias maximumValue: slider.maximumValue
+ property int pageStep: internal.horizontal ? width : height
+ property int singleStep: 20
+ property alias value: slider.value
+ property bool scrollToClickposition: internal.scrollToClickPosition
+
+ implicitWidth: loader.implicitWidth
+ implicitHeight: loader.implicitHeight
+
+ onValueChanged: internal.updateHandle()
+
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/ScrollBarStyle.qml")
+
+ property bool upPressed
+ property bool downPressed
+
+ property bool pageUpPressed
+ property bool pageDownPressed
+
+ MouseArea {
+ id: internal
+
+ property bool horizontal: orientation === Qt.Horizontal
+ property alias styleItem: loader.item
+
+ anchors.fill: parent
+
+ property bool autoincrement: false
+ property bool scrollToClickPosition: styleItem ? styleItem.scrollToClickPosition : 0
+ property bool handlePressed
+
+ // Update hover item
+ onEntered: styleItem.activeControl = styleItem.hitTest(mouseX, mouseY)
+ onExited: styleItem.activeControl = "none"
+ onMouseXChanged: styleItem.activeControl = styleItem.hitTest(mouseX, mouseY)
+ hoverEnabled: true
+
+ property variant control
+ property variant pressedX
+ property variant pressedY
+ property int oldPosition
+ property int grooveSize
+
+ Timer {
+ running: upPressed || downPressed || pageUpPressed || pageDownPressed
+ interval: 350
+ onTriggered: internal.autoincrement = true
+ }
+
+ Timer {
+ running: internal.autoincrement
+ interval: 60
+ repeat: true
+ onTriggered: upPressed ? internal.decrement() : downPressed ? internal.increment() :
+ pageUpPressed ? internal.decrementPage() :
+ internal.incrementPage()
+ }
+
+ onPositionChanged: {
+ if (pressed && control === "handle") {
+ //slider.positionAtMaximum = grooveSize
+ if (!horizontal)
+ slider.position = oldPosition + (mouseY - pressedY)
+ else
+ slider.position = oldPosition + (mouseX - pressedX)
+ }
+ }
+
+ onPressed: {
+ control = styleItem.hitTest(mouseX, mouseY)
+ scrollToClickposition = scrollToClickPosition
+ grooveSize = horizontal ? styleItem.subControlRect("groove").width -
+ styleItem.subControlRect("handle").width:
+ styleItem.subControlRect("groove").height -
+ styleItem.subControlRect("handle").height;
+ if (control == "handle") {
+ pressedX = mouseX
+ pressedY = mouseY
+ oldPosition = slider.position
+ } else if (control == "up") {
+ decrement();
+ upPressed = true
+ } else if (control == "down") {
+ increment();
+ downPressed = true
+ } else if (!scrollToClickposition){
+ if (control == "upPage") {
+ decrementPage();
+ pageUpPressed = true
+ } else if (control == "downPage") {
+ incrementPage();
+ pageDownPressed = true
+ }
+ } else {
+ slider.position = horizontal ? mouseX - handleRect.width/2
+ : mouseY - handleRect.height/2
+ }
+ }
+
+ onReleased: {
+ autoincrement = false;
+ upPressed = false;
+ downPressed = false;
+ pageUpPressed = false
+ pageDownPressed = false
+ control = ""
+ }
+
+ function incrementPage() {
+ value += pageStep
+ if (value > maximumValue)
+ value = maximumValue
+ }
+
+ function decrementPage() {
+ value -= pageStep
+ if (value < minimumValue)
+ value = minimumValue
+ }
+
+ function increment() {
+ value += singleStep
+ if (value > maximumValue)
+ value = maximumValue
+ }
+
+ function decrement() {
+ value -= singleStep
+ if (value < minimumValue)
+ value = minimumValue
+ }
+
+ Loader {
+ id: loader
+ property Item control: scrollbar
+ sourceComponent: style
+ anchors.fill: parent
+ }
+
+ property rect handleRect: Qt.rect(0,0,0,0)
+ property rect grooveRect: Qt.rect(0,0,0,0)
+ function updateHandle() {
+ internal.handleRect = styleItem.subControlRect("handle")
+ grooveRect = styleItem.subControlRect("groove");
+ }
+
+ RangeModel {
+ id: slider
+ minimumValue: 0.0
+ maximumValue: 1.0
+ value: 0
+ stepSize: 0.0
+ inverted: false
+ positionAtMaximum: internal.grooveSize
+ }
+ }
+}
diff --git a/src/qtdesktop/Slider.qml b/src/qtdesktop/Slider.qml
new file mode 100644
index 00000000..4e00c156
--- /dev/null
+++ b/src/qtdesktop/Slider.qml
@@ -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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+// jens: ContainsMouse breaks drag functionality
+
+Item {
+ id: slider
+
+ // Common API
+ property int orientation: Qt.Horizontal
+ property alias minimumValue: range.minimumValue
+ property alias maximumValue: range.maximumValue
+ property alias inverted: range.inverted
+ property bool updateValueWhileDragging: true
+ property alias pressed: mouseArea.pressed
+ property alias stepSize: range.stepSize
+ property alias hoverEnabled: mouseArea.hoverEnabled
+ property alias value: range.value
+
+ // Destop API
+ property bool containsMouse: mouseArea.containsMouse
+ property bool activeFocusOnPress: false
+ property bool tickmarksEnabled: false
+ property string tickPosition: "Below" // "Above", "Below", "BothSides"
+
+ Accessible.role: Accessible.Slider
+ Accessible.name: value
+
+ // Reimplement this function to control how the value is shown in the
+ // indicator.
+ function formatValue(v) {
+ return Math.round(v);
+ }
+
+ property var styleHints:[]
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/SliderStyle.qml")
+
+ Keys.onRightPressed: value += (maximumValue - minimumValue)/10.0
+ Keys.onLeftPressed: value -= (maximumValue - minimumValue)/10.0
+
+ implicitWidth: loader.item ? loader.item.implicitWidth : 0
+ implicitHeight: loader.item ? loader.item.implicitHeight : 0
+
+ RangeModel {
+ id: range
+ minimumValue: 0.0
+ maximumValue: 1.0
+ value: 0
+ stepSize: 0.0
+ inverted: false
+
+ positionAtMinimum: 0
+ positionAtMaximum: slider.width
+ }
+
+ Loader {
+ id: loader
+ sourceComponent: style
+ anchors.fill: parent
+ property var control: slider
+ function positionForValue(value) { return range.positionForValue(value) }
+ }
+
+ 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/qtdesktop/SpinBox.qml b/src/qtdesktop/SpinBox.qml
new file mode 100644
index 00000000..1ddbc9f6
--- /dev/null
+++ b/src/qtdesktop/SpinBox.qml
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+FocusScope {
+ id: spinbox
+
+ property int minimumWidth: 0
+ property int minimumHeight: 0
+
+ property real value: 0.0
+ property real maximumValue: 99
+ property real minimumValue: 0
+ property real singleStep: 1
+ property string postfix
+ property var styleHints:[]
+
+ property bool upEnabled: value != maximumValue;
+ property bool downEnabled: value != minimumValue;
+ property alias upPressed: mouseUp.pressed
+ property alias downPressed: mouseDown.pressed
+ property alias upHovered: mouseUp.containsMouse
+ property alias downHovered: mouseDown.containsMouse
+ property alias containsMouse: mouseArea.containsMouse
+ property alias font: input.font
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/SpinBoxStyle.qml")
+
+ Accessible.name: input.text
+ Accessible.role: Accessible.SpinBox
+
+ width: implicitWidth
+ height: implicitHeight
+
+ implicitWidth: loader.item ? loader.item.implicitWidth : 0
+ implicitHeight: loader.item ? loader.item.implicitHeight : 0
+
+ function increment() {
+ setValue(input.text)
+ value += singleStep
+ if (value > maximumValue)
+ value = maximumValue
+ input.text = value
+ }
+
+ function decrement() {
+ setValue(input.text)
+ value -= singleStep
+ if (value < minimumValue)
+ value = minimumValue
+ input.text = value
+ }
+
+ function setValue(v) {
+ var newval = parseFloat(v)
+ if (newval > maximumValue)
+ newval = maximumValue
+ else if (v < minimumValue)
+ newval = minimumValue
+ value = newval
+ input.text = value
+ }
+
+ Component.onCompleted: setValue(value)
+
+ onValueChanged: {
+ input.valueUpdate = true
+ input.text = value
+ input.valueUpdate = false
+ }
+
+ Loader {
+ id: loader
+ property alias control: spinbox
+ sourceComponent: style
+ anchors.fill: parent
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+
+ // Spinbox input field
+
+ TextInput {
+ id: input
+
+ property bool valueUpdate: false
+ property Item styleItem: loader.item
+
+ clip: true
+
+ verticalAlignment: Qt.AlignVCenter
+ anchors.fill: parent
+ anchors.leftMargin: styleItem ? styleItem.leftMargin : 0
+ anchors.topMargin: styleItem ? styleItem.topMargin : 0
+ anchors.rightMargin: styleItem ? styleItem.rightMargin: 0
+ anchors.bottomMargin: styleItem ? styleItem.bottomMargin: 0
+ selectByMouse: true
+
+ // validator: DoubleValidator { bottom: minimumValue; top: maximumValue; }
+ onAccepted: {setValue(input.text)}
+ onActiveFocusChanged: setValue(input.text)
+ color: loader.item ? loader.item.foregroundColor : "black"
+ selectionColor: loader.item ? loader.item.selectionColor : "black"
+ selectedTextColor: loader.item ? loader.item.selectedTextColor : "black"
+
+ opacity: parent.enabled ? 1 : 0.5
+ renderType: Text.NativeRendering
+ Text {
+ text: postfix
+ color: loader.item ? loader.item.foregroundColor : "black"
+ anchors.rightMargin: 4
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ // Spinbox increment button
+
+ MouseArea {
+ id: mouseUp
+
+ property var upRect: loader.item ? loader.item.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
+ onClicked: decrement()
+ property var downRect: loader.item ? loader.item.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/qtdesktop/SplitterColumn.qml b/src/qtdesktop/SplitterColumn.qml
new file mode 100644
index 00000000..1ff35afe
--- /dev/null
+++ b/src/qtdesktop/SplitterColumn.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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 "private" as Private
+import QtDesktop 1.0
+
+/*
+*
+* SplitterColumn
+*
+* SplitterColumn is a component that provides a way to layout items horisontally with
+* a draggable splitter added in-between each item.
+*
+* Add items to the SplitterColumn by inserting them as child items. The splitter handle
+* is outsourced as a delegate (handleDelegate). To enable the user to drag the handle,
+* it will need to contain a mouse area that communicates with the SplitterColumn by binding
+* 'drag.target: handle'. The 'handle' property points to the handle item that embeds
+* the delegate. To change handle positions, either change 'y; (or 'height') of 'handle', or
+* change the height of the child items inside the SplitterColumn. If you set the visibility
+* of a child item to false, the corresponding handle will also be hidden, and the
+* SplitterColumn will perform a layout update to fill up available space.
+*
+* There will always be one (and only one) item in the SplitterColumn that is 'expanding'.
+* The expanding item is the child that will get all the remaining space in the SplitterColumn
+* (down to its own mimimumHeight/Height) when all other items have been layed out.
+* This means that that 'height', 'percentageHeight' and 'maximumHeight' will be ignored for this item.
+* By default, the last visible child item of the SplitterColumn will be 'expanding'.
+*
+* A handle can belong to the item on the left side, or the right 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.
+*
+* NB: Since SplitterColumn might modify geometry properties like 'height' and 'y; of child items
+* to e.g. ensure they stay within minimumHeight/maximumHeight, explicit expression bindings
+* to such properties can easily be broken up by the SplitterColumn, and is not recommended.
+*
+* The SplitterColumn contains the following API:
+*
+* 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.
+* Item handle - convenience property that points to the item where the handle background is
+* instanciated as a child. Identical to splitterColumn.handles[handleIndex]. The handle
+* background iteself can be accessed through handle.item.
+* Modify 'handle[d.offset]' to move the handle (or change 'height' of SplitterColumn child items).
+* Item splitterItem - convenience property that points to the child item that the handle controls.
+* Also refer to information about the expanding item above.
+* Item splitterColumn - points to the SplitterColumn that the handle is in.
+* List<Item> items - contains the list of child items in the SplitterColumn. Currently read-only.
+* List<Item> handles - contains the list of splitter handles in the SplitterColumn. Note that this list will
+* be populated after all child items has completed, so accessing it from Component.onCompleted
+* inside a SplitterColumn child item will not work. To get to the handle background, access the
+* 'background' property of the handle, e.g. handles[0].background. Read-only.
+* real preferredHeight/Height - contains the accumulated with of all child items and handles, except
+* the expanding item. If the expanding item has a minimum height, the minimum height will
+* be included.
+*
+* The following attached properties can be used for each child item of SplitterColumn:
+*
+* real Splitter.minimumSize - ensures that the item cannot be resized below the
+* given pixelvalue. A value of -1 will disable it.
+* real Splitter.maximumSize - ensures that the item cannot be resized above the
+* given pixelvalue. A value of -1 will disable it.
+* real percentageHeight - This value specifies a percentage (0 - 100) of the height of the
+* SplitterColumn height. If the height of the SplitterColumn change, the height of the item will
+* change as well. 'percentageHeight' have precedence over 'height', which means that
+* SplitterColumn will ignore any assignments to 'height'. A value of -1 disables it.
+* bool Splitter.expanding - See explanation of 'expanding' above. If set to true, the current item
+* will be the expanding item in the SplitterColumn. If set to false, the SplitterColumn will
+* autmatically choose the last visible child of the SplitterColumn as expanding instead.
+* int Splitter.itemIndex - will be assigned a read-only value with the item index. Can be used to e.g. look-up
+* the handles sourrounding the item (parent.handles[itemIndex])
+*
+* Example:
+*
+* To create a SplitterColumn with three items, and let
+* the center item be the one that should be expanding, one
+* could do the following:
+*
+* SplitterColumn {
+* anchors.fill: parent
+*
+* Rectangle {
+* Splitter.maximumSize: 400
+* color: "gray"
+* height: 200
+* }
+* Rectangle {
+* Splitter.minimumSize: 50
+* Splitter.expanding: true
+* color: "darkgray"
+* }
+* Rectangle {
+* color: "gray"
+* height: 200
+* }
+* }
+*/
+
+Private.Splitter {
+ orientation: Qt.Vertical
+ handleDelegate: StyleItem {
+ id: styleitem
+ elementType: "splitter"
+ height: handleWidth != -1 ? handleWidth : pixelMetric("splitterwidth")
+ horizontal: false
+ property alias pressed: mouseArea.pressed
+ property bool dragged: mouseArea.drag.active
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ anchors.topMargin: (parent.height <= 1) ? -2 : 0
+ anchors.bottomMargin: (parent.height <= 1) ? -2 : 0
+ drag.axis: Drag.XandYAxis // Why doesn't X-axis work?
+ drag.target: handle
+ cursorShape: Qt.SplitVCursor
+ }
+ }
+}
diff --git a/src/qtdesktop/SplitterRow.qml b/src/qtdesktop/SplitterRow.qml
new file mode 100644
index 00000000..14c2ea56
--- /dev/null
+++ b/src/qtdesktop/SplitterRow.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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 "private" as Private
+import QtDesktop 1.0
+
+/*
+*
+* SplitterRow
+*
+* SplitterRow is a component that provides a way to layout items horisontally with
+* a draggable splitter added in-between each item.
+*
+* Add items to the SplitterRow by inserting them as child items. The splitter handle
+* is outsourced as a delegate (handleDelegate). To enable the user to drag the handle,
+* it will need to contain a mouse area that communicates with the SplitterRow by binding
+* 'drag.target: handle'. The 'handle' property points to the handle item that embeds
+* the delegate. To change handle positions, either change 'x' (or 'width') of 'handle', or
+* change the width of the child items inside the SplitterRow. If you set the visibility
+* of a child item to false, the corresponding handle will also be hidden, and the
+* SplitterRow will perform a layout update to fill up available space.
+*
+* There will always be one (and only one) item in the SplitterRow that is 'expanding'.
+* The expanding item is the child that will get all the remaining space in the SplitterRow
+* (down to its own mimimumWidth/Height) when all other items have been layed out.
+* This means that that 'width', 'percentageWidth' and 'maximumWidth' will be ignored for this item.
+* By default, the last visible child item of the SplitterRow will be 'expanding'.
+*
+* A handle can belong to the item on the left side, or the right 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.
+*
+* NB: Since SplitterRow might modify geometry properties like 'width' and 'x' of child items
+* to e.g. ensure they stay within minimumWidth/maximumWidth, explicit expression bindings
+* to such properties can easily be broken up by the SplitterRow, and is not recommended.
+*
+* The SplitterRow contains the following API:
+*
+* 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.
+* Item handle - convenience property that points to the item where the handle background is
+* instanciated as a child. Identical to splitterRow.handles[handleIndex]. The handle
+* background iteself can be accessed through handle.item.
+* Modify 'handle[d.offset]' to move the handle (or change 'width' of SplitterRow child items).
+* Item splitterItem - convenience property that points to the child item that the handle controls.
+* Also refer to information about the expanding item above.
+* Item splitterRow - points to the SplitterRow that the handle is in.
+* List<Item> items - contains the list of child items in the SplitterRow. Currently read-only.
+* List<Item> handles - contains the list of splitter handles in the SplitterRow. Note that this list will
+* be populated after all child items has completed, so accessing it from Component.onCompleted
+* inside a SplitterRow child item will not work. To get to the handle background, access the
+* 'background' property of the handle, e.g. handles[0].background. Read-only.
+* real preferredWidth/Height - contains the accumulated with of all child items and handles, except
+* the expanding item. If the expanding item has a minimum width, the minimum width will
+* be included.
+*
+* The following attached properties can optionally be used for each child item of SplitterRow:
+*
+* real Splitter.minimumSize - ensures that the item cannot be resized below the
+* given pixelvalue. A value of -1 will disable it.
+* real Splitter.maximumSixe - ensures that the item cannot be resized above the
+* given value. A value of -1 will disable it.
+* real Splitter.percentageSize - This value specifies a percentage (0 - 100) of the width of the
+* SplitterRow width. If the width of the SplitterRow change, the width of the item will
+* change as well. 'percentageWidth' have precedence over 'width', which means that
+* SplitterRow will ignore any assignments to 'width'. A value of -1 disables it.
+* bool Splitter.expanding - See explanation of 'expanding' above. If set to true, the current item
+* will be the expanding item in the SplitterRow. If set to false, the SplitterRow will
+* autmatically choose the last visible child of the SplitterRow as expanding instead.
+* int Splitter.itemIndex - will be assigned a read-only value with the item index. Can be used to e.g. look-up
+* the handles sourrounding the item (parent.handles[itemIndex])
+*
+* Example:
+*
+* To create a SplitterRow with three items, and let
+* the center item be the one that should be expanding, one
+* could do the following:
+*
+* SplitterRow {
+* anchors.fill: parent
+*
+* Rectangle {
+* Splitter.maximumWidth: 400
+* color: "gray"
+* width: 200
+* }
+* Rectangle {
+* Splitter.minimumWidth: 50
+* Splitter.expanding: true
+* color: "darkgray"
+* }
+* Rectangle {
+* color: "gray"
+* width: 200
+* }
+* }
+*/
+
+
+Private.Splitter {
+ orientation: Qt.Horizontal
+ handleDelegate: StyleItem {
+ id: styleitem
+ elementType: "splitter"
+ width: handleWidth != -1 ? handleWidth : pixelMetric("splitterwidth")
+ property alias pressed: mouseArea.pressed
+ property bool dragged: mouseArea.drag.active
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ anchors.leftMargin: (parent.width <= 1) ? -2 : 0
+ anchors.rightMargin: (parent.width <= 1) ? -2 : 0
+ drag.axis: Qt.YAxis
+ drag.target: handle
+ cursorShape: Qt.SplitHCursor
+ }
+ }
+}
diff --git a/src/qtdesktop/StatusBar.qml b/src/qtdesktop/StatusBar.qml
new file mode 100644
index 00000000..46641411
--- /dev/null
+++ b/src/qtdesktop/StatusBar.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+Item {
+ width: parent ? parent.width : 200
+ height: 24
+ StyleItem {
+ anchors.fill: parent
+ elementType: "statusbar"
+ }
+}
diff --git a/src/qtdesktop/Tab.qml b/src/qtdesktop/Tab.qml
new file mode 100644
index 00000000..133c3715
--- /dev/null
+++ b/src/qtdesktop/Tab.qml
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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
+
+Item {
+ id:tab
+ anchors.fill: parent
+ property string title
+ property int contentMargin
+}
diff --git a/src/qtdesktop/TabBar.qml b/src/qtdesktop/TabBar.qml
new file mode 100644
index 00000000..0ad47520
--- /dev/null
+++ b/src/qtdesktop/TabBar.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+Item {
+ id: tabbar
+ property int tabHeight: tabrow.height
+ property int tabWidth: tabrow.width
+
+ Keys.onRightPressed: {
+ if (tabFrame && tabFrame.current < tabFrame.count - 1)
+ tabFrame.current = tabFrame.current + 1
+ }
+ Keys.onLeftPressed: {
+ if (tabFrame && tabFrame.current > 0)
+ tabFrame.current = tabFrame.current - 1
+ }
+
+ height: tabHeight
+
+
+ property Item tabFrame
+ onTabFrameChanged: parent = tabFrame
+ visible: tabFrame ? tabFrame.tabsVisible : true
+
+ property int __overlap : loader.item ? loader.item.__overlap : 0
+ property string position: tabFrame ? tabFrame.position : "North"
+ property string tabBarAlignment: loader.item ? loader.item.tabBarAlignment : "Center"
+ property int tabOverlap: loader.item ? loader.item.tabOverlap : 0
+ property int tabBaseOverlap: loader.item ? loader.item.tabBaseOverlap : 0
+ property int tabHSpace: loader.item ? loader.item.tabHSpace : 0
+ property int tabVSpace: loader.item ? loader.item.tabVSpace : 0
+
+ function tab(index) {
+ for (var i = 0; i < tabrow.children.length; ++i) {
+ if (tabrow.children[i].tabindex == index) {
+ return tabrow.children[i]
+ }
+ }
+ return null;
+ }
+
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/TabBarStyle.qml")
+
+ Loader {
+ id: loader
+ sourceComponent: style
+ property alias control: tabbar
+ }
+
+ Row {
+ id: tabrow
+ Accessible.role: Accessible.PageTabList
+ states:
+ State {
+ when: tabBarAlignment == "center"
+ name: "centered"
+ AnchorChanges {
+ target:tabrow
+ anchors.horizontalCenter: tabbar.horizontalCenter
+ }
+ }
+
+ Repeater {
+ id: repeater
+ focus: true
+ model: tabFrame ? tabFrame.tabs.length : null
+ delegate: Item {
+ id: tab
+ focus: true
+
+ property int tabindex: index
+ property bool selectedHelper: selected
+ property bool selected : tabFrame.current == index
+ property bool hover: mousearea.containsMouse
+ property bool first: index === 0
+
+ z: selected ? 1 : -1
+ implicitWidth: Math.min(tabloader.implicitWidth, tabbar.width/tabs.length) + 1
+ implicitHeight: tabloader.implicitHeight
+
+ Loader {
+ id: tabloader
+ sourceComponent: loader.item ? loader.item.tab : null
+ anchors.fill: parent
+ // anchors.margins: -2
+ property alias control: tab
+ property int index: tabindex
+ }
+
+ MouseArea {
+ id: mousearea
+ anchors.fill: parent
+ hoverEnabled: true
+ onPressed: tabFrame.current = index
+ }
+ Accessible.role: Accessible.PageTab
+ Accessible.name: tabFrame.tabs[index].title
+ }
+ }
+ }
+}
diff --git a/src/qtdesktop/TabFrame.qml b/src/qtdesktop/TabFrame.qml
new file mode 100644
index 00000000..533bdb19
--- /dev/null
+++ b/src/qtdesktop/TabFrame.qml
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+Item {
+ id: tabWidget
+ width: 100
+ height: 100
+ property int current: 0
+ property int count: stack.children.length
+ property bool frame: true
+ property bool tabsVisible: true
+ property string position: "North"
+ default property alias tabs : stack.children
+ property Item tabBar: tabbarItem
+ property Component delegate: Qt.createComponent(Settings.THEME_PATH + "/TabFrameStyle.qml")
+
+ onCurrentChanged: __setOpacities()
+ Component.onCompleted: __setOpacities()
+
+ function __setOpacities() {
+ for (var i = 0; i < stack.children.length; ++i) {
+ stack.children[i].visible = (i == current ? true : false)
+ }
+ }
+
+ 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
+ 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: delegate
+ 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
+ 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/qtdesktop/TableColumn.qml b/src/qtdesktop/TableColumn.qml
new file mode 100644
index 00000000..53207070
--- /dev/null
+++ b/src/qtdesktop/TableColumn.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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
+
+QtObject {
+ property string title
+ property string role
+ property int width: 160
+ property int x
+ property bool visible: true
+ property int elideMode: Text.ElideRight
+ property int textAlignment: Text.AlignLeft
+ property Component delegate
+}
diff --git a/src/qtdesktop/TableView.qml b/src/qtdesktop/TableView.qml
new file mode 100644
index 00000000..0e0ed819
--- /dev/null
+++ b/src/qtdesktop/TableView.qml
@@ -0,0 +1,650 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+import "private" as Private
+
+/*
+*
+* TableView
+*
+* This component provides an item-view with resizable
+* header sections.
+*
+* You can style the drawn delegate by overriding the itemDelegate
+* property. The following properties are supported for custom
+* delegates:
+*
+* Note: Currently only row selection is available for this component
+*
+* itemheight - default platform size of item
+* itemwidth - default platform width of item
+* itemselected - if the row is currently selected
+* itemvalue - The text for this item
+* itemforeground - The default text color for an item
+*
+* For example:
+* itemDelegate: Item {
+* Text {
+* anchors.verticalCenter: parent.verticalCenter
+* color: itemForeground
+* elide: Text.ElideRight
+* text: itemValue
+* }
+* }
+*
+* Data for each row is provided through a model:
+*
+* ListModel {
+* ListElement{ column1: "value 1"; column2: "value 2"}
+* ListElement{ column1: "value 3"; column2: "value 4"}
+* }
+*
+* You provide title and size properties on TableColumns
+* by setting the default header property :
+*
+* TableView {
+* TableColumn{ role: "column1" ; title: "Column 1" ; width:100}
+* TableColumn{ role: "column2" ; title: "Column 2" ; width:200}
+* model: datamodel
+* }
+*
+* The header sections are attached to values in the datamodel by defining
+* the listmodel property they attach to. Each property in the model, will
+* then be shown in each column section.
+*
+* 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.
+*
+* sortColumn - The index of the currently selected sort header
+* sortIndicatorVisible - If sort indicators should be enabled
+* sortIndicatorDirection - "up" or "down" depending on state
+*
+*/
+
+FocusScope{
+ id: root
+
+ property variant model
+
+ // Framewidth seems to be 1 regardless of style
+ property int frameWidth: frame ? frameitem.frameWidth : 0;
+ width: 200
+ height: 200
+
+ // Cosmetic properties
+ property bool frame: true
+ property bool frameAroundContents: styleitem.styleHint("framearoundcontents")
+ property bool highlightOnFocus: false
+ property bool alternateRowColor: true
+ property bool headerVisible: true
+
+ // Styling properties
+ property Component itemDelegate: standardDelegate
+ property Component rowDelegate: rowDelegate
+ property Component headerDelegate: headerDelegate
+ property color backgroundColor: "white"
+
+ // Sort properties
+ property int sortColumn // Index of currently selected sort column
+ property bool sortIndicatorVisible: false // enables or disables sort indicator
+ property string sortIndicatorDirection: "down" // "up" or "down" depending on current state
+
+ // Item properties
+ default property alias header: tree.columnheader
+ property alias contentHeader: tree.header
+ property alias contentFooter: tree.footer
+
+ property alias horizontalScrollBar: scroller.horizontalScrollBar
+ property alias verticalScrollBar: scroller.verticalScrollBar
+
+ // Viewport properties
+ property alias contentX: tree.contentX
+ property alias contentY: tree.contentY
+ property alias contentHeight : tree.contentHeight
+ property alias contentWidth: tree.contentWidth
+ property alias viewportWidth: scroller.availableWidth
+ property alias viewportHeight: scroller.availableHeight
+ property alias count: tree.count
+ property alias section: tree.section
+
+ property alias cacheBuffer: tree.cacheBuffer
+ property alias currentIndex: tree.currentIndex // Should this be currentRowIndex?
+
+ Accessible.role: Accessible.Table
+
+ // Signals
+ signal activated
+
+ Component {
+ id: standardDelegate
+ Item {
+ height: Math.max(16, styleitem.implicitHeight)
+ property int implicitWidth: sizehint.paintedWidth + 4
+ Text {
+ id: 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 ? itemValue : ""
+ color: itemForeground
+ renderType: Text.NativeRendering
+ }
+ Text {
+ id: sizehint
+ font: label.font
+ text: itemValue ? itemValue : ""
+ visible: false
+ }
+ }
+ }
+
+ StyleItem {
+ id: itemstyle
+ elementType: "item"
+ visible:false
+ }
+
+ Component {
+ id: nativeDelegate
+ // This gives more native styling, but might be less performant
+ StyleItem {
+ elementType: "item"
+ text: itemValue
+ selected: itemSelected
+ }
+ }
+
+ Component {
+ id: headerDelegate
+ StyleItem {
+ elementType: "header"
+ activeControl: itemSort
+ raised: true
+ sunken: itemPressed
+ text: itemValue
+ hover: itemContainsMouse
+ info: itemPosition
+ }
+ }
+
+ Component {
+ id: rowDelegate
+ StyleItem {
+ id: rowstyle
+ elementType: "itemrow"
+ activeControl: itemAlternateBackground ? "alternate" : ""
+ selected: itemSelected ? true : false
+ height: Math.max(16, styleitem.implicitHeight)
+ }
+ }
+
+ Rectangle {
+ id: colorRect
+ color: backgroundColor
+ anchors.fill: frameitem
+ anchors.margins: frameWidth
+ anchors.rightMargin: (!frameAroundContents && verticalScrollBar.visible ? verticalScrollBar.width : 0) + frameWidth
+ anchors.bottomMargin: (!frameAroundContents && horizontalScrollBar.visible ? horizontalScrollBar.height : 0) +frameWidth
+ }
+
+ StyleItem {
+ id: frameitem
+ elementType: "frame"
+ Component.onCompleted: frameWidth = styleitem.pixelMetric("defaultframewidth");
+ sunken: true
+ visible: frame
+ anchors.fill: parent
+ anchors.rightMargin: frame ? (frameAroundContents ? (verticalScrollBar.visible ? verticalScrollBar.width + 2 * frameMargins : 0) : 0) : 0
+ anchors.bottomMargin: frame ? (frameAroundContents ? (horizontalScrollBar.visible ? horizontalScrollBar.height + 2 * frameMargins : 0) : 0) : 0
+ anchors.topMargin: frame ? frameAroundContents : 0
+ anchors.leftMargin: frame ? frameAroundContents : 0
+ property int frameWidth
+ property int scrollbarspacing: styleitem.pixelMetric("scrollbarspacing");
+ property int frameMargins : frame ? scrollbarspacing : 0
+ }
+ MouseArea {
+ id: mousearea
+
+ anchors.fill: tree
+
+ 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 && verticalScrollBar.visible; repeat: true; interval: 20 ; onTriggered: incrementCurrentIndex()}
+ Timer { running: mousearea.autodecrement && verticalScrollBar.visible; repeat: true; interval: 20 ; onTriggered: decrementCurrentIndex()}
+
+ onPositionChanged: {
+ if (mouseY > tree.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(contentY + tree.height - 5, Math.max(mouseY + contentY, contentY));
+ var newIndex = tree.indexAt(0, y);
+ if (newIndex >= 0)
+ tree.currentIndex = tree.indexAt(0, y);
+ }
+
+ onPressed: {
+ tree.forceActiveFocus()
+ var x = Math.min(contentWidth - 5, Math.max(mouseX + contentX, 0))
+ var y = Math.min(contentHeight - 5, Math.max(mouseY + contentY, 0))
+ tree.currentIndex = tree.indexAt(x, y)
+ }
+
+ onDoubleClicked: {
+ parent.activated()
+ }
+ }
+
+ function decrementCurrentIndex() {
+ scroller.blockUpdates = true;
+ tree.decrementCurrentIndex();
+ scroller.verticalValue = contentY;
+ scroller.blockUpdates = false;
+ }
+
+ function incrementCurrentIndex() {
+ scroller.blockUpdates = true;
+ tree.incrementCurrentIndex();
+ scroller.verticalValue = contentY;
+ scroller.blockUpdates = false;
+ }
+
+ ListView {
+ id: tree
+
+ property list<TableColumn> columnheader
+ highlightFollowsCurrentItem: true
+ model: root.model
+ interactive: false
+
+ anchors.top: tableColumn.bottom
+ anchors.left: frameitem.left
+ anchors.right: frameitem.right
+ anchors.bottom: frameitem.bottom
+ anchors.margins: frameWidth
+ anchors.topMargin: -frameWidth
+ anchors.rightMargin: (!frameAroundContents && verticalScrollBar.visible ? verticalScrollBar.width: 0) + frameWidth
+ anchors.bottomMargin: (!frameAroundContents && horizontalScrollBar.visible ? horizontalScrollBar.height : 0) + frameWidth
+
+ focus: true
+ clip: true
+
+ // Fills extra rows with alternate color
+ Column {
+ id: rowfiller
+ property variant rowHeight: Math.max(1, contentHeight / count)
+ property int rowCount: height/rowHeight
+ y: contentHeight
+ width: parent.width
+ visible: contentHeight > 0 && alternateRowColor && !verticalScrollBar.visible
+ height: parent.height - contentHeight
+ Repeater {
+ model: visible ? rowfiller.rowCount : 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: tree.model
+ property variant modelData: null
+ }
+ }
+ }
+
+ Keys.onUpPressed: root.decrementCurrentIndex()
+ Keys.onDownPressed: root.incrementCurrentIndex()
+
+ Keys.onPressed: {
+ if (event.key == Qt.Key_PageUp) {
+ verticalScrollBar.value = verticalScrollBar.value - tree.height
+ } else if (event.key == Qt.Key_PageDown)
+ verticalScrollBar.value = verticalScrollBar.value + tree.height
+ }
+
+ onContentYChanged: {
+ scroller.blockUpdates = true
+ scroller.verticalValue = tree.contentY
+ verticalScrollBar.value = tree.contentY
+ scroller.blockUpdates = false
+ }
+
+ onContentXChanged: {
+ scroller.blockUpdates = true
+ scroller.horizontalValue = tree.contentX
+ horizontalScrollBar.value = tree.contentX
+ scroller.blockUpdates = false
+ }
+
+ delegate: Item {
+ id: rowitem
+ width: row.width
+ height: rowstyle.height
+
+ anchors.margins: frameWidth
+ property int rowIndex: model.index
+ property bool itemAlternateBackground: alternateRowColor && rowIndex % 2 == 1
+ property variant itemModelData: typeof modelData == "undefined" ? null : modelData
+
+ Loader {
+ id: rowstyle
+ // row delegate
+ sourceComponent: root.rowDelegate
+ // Row fills the tree width regardless of item size
+ // But scrollbar should not adjust to it
+ width: frameitem.width
+ x: contentX
+
+ property bool itemAlternateBackground: rowitem.itemAlternateBackground
+ property bool itemSelected: rowitem.ListView.isCurrentItem
+ property int index: rowitem.rowIndex
+ property variant model: tree.model
+ property variant modelData: rowitem.itemModelData
+ }
+ 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: tree.model
+ property variant role: header[index].role
+ property variant modelData: itemModelData
+
+ width: header[index].width
+
+ function getValue() {
+ if (header[index].role.length && model.get && model.get(rowIndex)[header[index].role])
+ return model.get(rowIndex)[header[index].role]
+ else if (modelData && modelData.hasOwnProperty(header[index].role))
+ return modelData[header[index].role]
+ else if (modelData)
+ return modelData
+ 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].textAlignment
+ }
+ }
+ onWidthChanged: tree.contentWidth = width
+ }
+ }
+ }
+
+
+ Text{ id:text }
+
+ Item {
+ id: tableColumn
+
+ anchors.top: frameitem.top
+ anchors.left: frameitem.left
+ anchors.right: frameitem.right
+ anchors.margins: frameWidth
+
+ clip: true
+ visible: headerVisible
+ height: headerVisible ? headerrow.height : frameWidth
+
+ Behavior on height { NumberAnimation{ duration: 80 } }
+
+ Row {
+ id: headerrow
+ anchors.top: parent.top
+ x: -tree.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
+ SystemPalette{id:palette}
+ }
+
+ 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 Im 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: tableColumn
+ 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 = tree.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
+ }
+ }
+
+ Private.ScrollAreaHelper {
+ id: scroller
+ anchors.fill: parent
+ anchors.topMargin: styleitem.style == "mac" ? tableColumn.height + frameWidth: 0
+ scrollSpeed: 2
+ }
+
+ StyleItem {
+ z: 2
+ anchors.fill: parent
+ anchors.margins: -4
+ visible: highlightOnFocus && parent.activeFocus && styleitem.styleHint("focuswidget")
+ elementType: "focusframe"
+ }
+
+ 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/qtdesktop/TextArea.qml b/src/qtdesktop/TextArea.qml
new file mode 100644
index 00000000..c7f9f81a
--- /dev/null
+++ b/src/qtdesktop/TextArea.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+ScrollArea {
+ id: area
+ color: "white"
+ width: 280
+ height: 120
+ contentWidth: edit.paintedWidth + (2 * documentMargins)
+
+ property alias text: edit.text
+ property alias wrapMode: edit.wrapMode
+ property alias readOnly: edit.readOnly
+ property bool tabChangesFocus: false
+ property alias font: edit.font
+ property alias activeFocusOnPress: edit.activeFocusOnPress
+ property alias horizontalAlignment: edit.horizontalAlignment
+
+ highlightOnFocus: true
+ property int documentMargins: 4
+ frame: true
+
+ function append (string) {
+ text += "\n" + string
+ verticalScrollBar.value = verticalScrollBar.maximumValue
+ }
+
+ Accessible.role: Accessible.EditableText
+ // FIXME: probably implement text interface
+ Accessible.name: text
+
+ TextEdit {
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.IBeamCursor
+ acceptedButtons: Qt.NoButton
+ }
+ renderType: Text.NativeRendering
+
+ id: edit
+ selectionColor: syspal.highlight
+ selectedTextColor: syspal.highlightedText
+ wrapMode: TextEdit.WordWrap;
+ width: area.viewportWidth - (2 * documentMargins)
+ x: documentMargins
+ y: documentMargins
+ // height has to be big enough to handle mouse focus
+ height: Math.max(area.height, paintedHeight)
+
+ selectByMouse: true
+ readOnly: false
+ color: syspal.text
+
+ SystemPalette {
+ id: syspal
+ colorGroup: enabled ? SystemPalette.Active : SystemPalette.Disabled
+ }
+
+ KeyNavigation.priority: KeyNavigation.BeforeItem
+ KeyNavigation.tab: area.tabChangesFocus ? area.KeyNavigation.tab : null
+ KeyNavigation.backtab: area.tabChangesFocus ? area.KeyNavigation.backtab : null
+
+ onContentSizeChanged: {
+ area.contentWidth = paintedWidth + (2 * documentMargins)
+ }
+
+ // keep textcursor within scrollarea
+ onCursorPositionChanged: {
+ if (cursorRectangle.y >= area.contentY + area.viewportHeight - 1.5*cursorRectangle.height - documentMargins)
+ area.contentY = cursorRectangle.y - area.viewportHeight + 1.5*cursorRectangle.height + documentMargins
+ else if (cursorRectangle.y < area.contentY)
+ area.contentY = cursorRectangle.y
+
+ if (cursorRectangle.x >= area.contentX + area.viewportWidth - documentMargins) {
+ area.contentX = cursorRectangle.x - area.viewportWidth + documentMargins
+ } else if (cursorRectangle.x < area.contentX)
+ area.contentX = cursorRectangle.x
+ }
+ }
+
+ 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/qtdesktop/TextField.qml b/src/qtdesktop/TextField.qml
new file mode 100644
index 00000000..f02f50f1
--- /dev/null
+++ b/src/qtdesktop/TextField.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 QtDesktop 1.0
+import "Styles/Settings.js" as Settings
+
+FocusScope {
+ id: textfield
+ property alias text: textInput.text
+ property alias font: textInput.font
+
+ property int minimumWidth: 0
+ property int minimumHeight: 0
+
+ property int inputHint // values tbd
+ property bool acceptableInput: textInput.acceptableInput // read only
+ property alias readOnly: textInput.readOnly // read only
+ property alias placeholderText: placeholderTextComponent.text
+ property bool passwordMode: false
+ property alias selectedText: textInput.selectedText
+ property alias selectionEnd: textInput.selectionEnd
+ property alias selectionStart: textInput.selectionStart
+ property alias validator: textInput.validator
+ property alias inputMask: textInput.inputMask
+ property alias horizontalalignment: textInput.horizontalAlignment
+ property alias echoMode: textInput.echoMode
+ property alias cursorPosition: textInput.cursorPosition
+ property alias inputMethodHints: textInput.inputMethodHints
+ property alias activeFocusOnPress: textInput.activeFocusOnPress
+ property alias containsMouse: mouseArea.containsMouse
+ property Component style: Qt.createComponent(Settings.THEME_PATH + "/TextFieldStyle.qml")
+
+ property var styleHints:[]
+
+ implicitWidth: loader.implicitWidth
+ implicitHeight: loader.implicitHeight
+
+ Accessible.name: text
+ Accessible.role: Accessible.EditableText
+ Accessible.description: placeholderText
+
+
+ function copy() {
+ textInput.copy()
+ }
+
+ function paste() {
+ textInput.paste()
+ }
+
+ function cut() {
+ textInput.cut()
+ }
+
+ function select(start, end) {
+ textInput.select(start, end)
+ }
+
+ function selectAll() {
+ textInput.selectAll()
+ }
+
+ function selectWord() {
+ textInput.selectWord()
+ }
+
+ function positionAt(x) {
+ var p = mapToItem(textInput, x, 0);
+ return textInput.positionAt(p.x);
+ }
+
+ function positionToRectangle(pos) {
+ var p = mapToItem(textInput, pos.x, pos.y);
+ return textInput.positionToRectangle(p);
+ }
+
+ // Implementation
+
+ Loader {
+ id: loader
+ sourceComponent: style
+ anchors.fill: parent
+ property Item control: textfield
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: textfield.forceActiveFocus()
+ }
+
+ onFocusChanged: {
+ if (textfield.activeFocus)
+ textInput.forceActiveFocus();
+ }
+
+ TextInput { // see QTBUG-14936
+ id: textInput
+ selectByMouse: true
+ selectionColor: loader.item ? loader.item.selectionColor : "black"
+ selectedTextColor: loader.item ? loader.item.selectedTextColor : "black"
+
+ property Item styleItem: loader.item
+ anchors.leftMargin: styleItem ? styleItem.leftMargin : 0
+ anchors.topMargin: styleItem ? styleItem.topMargin : 0
+ anchors.rightMargin: styleItem ? styleItem.rightMargin : 0
+ anchors.bottomMargin: styleItem ? styleItem.bottomMargin : 0
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+
+ color: loader.item ? loader.item.foregroundColor : "darkgray"
+ echoMode: passwordMode ? TextInput.Password : TextInput.Normal
+ clip: true
+ renderType: Text.NativeRendering
+ }
+
+ Text {
+ id: placeholderTextComponent
+ anchors.fill: textInput
+ font: textInput.font
+ opacity: !textInput.text.length && !textInput.activeFocus ? 1 : 0
+ color: loader.item ? loader.item.placeholderTextColor : "darkgray"
+ text: "Enter text"
+ 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/qtdesktop/ToolBar.qml b/src/qtdesktop/ToolBar.qml
new file mode 100644
index 00000000..d1aeffab
--- /dev/null
+++ b/src/qtdesktop/ToolBar.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+StyleItem {
+ id: toolbar
+ width: parent ? parent.width : 200
+ height: implicitHeight
+ elementType: "toolbar"
+
+ Accessible.role: Accessible.ToolBar
+}
diff --git a/src/qtdesktop/ToolButton.qml b/src/qtdesktop/ToolButton.qml
new file mode 100644
index 00000000..1cfe087b
--- /dev/null
+++ b/src/qtdesktop/ToolButton.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 QtDesktop 1.0
+import "private" as Private
+import "Styles/Settings.js" as Settings
+
+Private.BasicButton {
+ id: button
+
+ property string iconName
+ property url iconSource
+ property string text
+
+ style: Qt.createComponent(Settings.THEME_PATH + "/ToolButtonStyle.qml")
+
+ Image {
+ id: themeIcon
+ anchors.centerIn: parent
+ opacity: enabled ? 1 : 0.5
+ antialiasing: true
+ sourceSize.width: iconSize
+ //property string iconPath: "image://desktoptheme/" + button.iconName
+ property int iconSize: 24 //(backgroundItem && backgroundItem.style === "mac" && button.styleHint.indexOf("segmented") !== -1) ? 16 : 24
+ //source: iconPath // backgroundItem && backgroundItem.hasThemeIcon(iconName) ? iconPath : ""
+ fillMode: Image.PreserveAspectFit
+ Image {
+ // Use fallback icon
+ anchors.centerIn: parent
+ sourceSize: parent.sourceSize
+ visible: (themeIcon.status != Image.Ready)
+ source: visible ? button.iconSource : ""
+ }
+ }
+ Accessible.name: text
+}
diff --git a/src/qtdesktop/plugins.qmltypes b/src/qtdesktop/plugins.qmltypes
new file mode 100644
index 00000000..79e15ef6
--- /dev/null
+++ b/src/qtdesktop/plugins.qmltypes
@@ -0,0 +1,451 @@
+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"]
+ }
+ Component {
+ name: "QtSplitterAttached"
+ prototype: "QObject"
+ Property { name: "minimumWidth"; type: "double" }
+ Property { name: "maximumWidth"; type: "double" }
+ Property { name: "minimumHeight"; type: "double" }
+ Property { name: "maximumHeight"; type: "double" }
+ Property { name: "percentageSize"; type: "double" }
+ Property { name: "expanding"; type: "bool" }
+ Property { name: "itemIndex"; type: "int" }
+ Signal {
+ name: "minimumWidthChanged"
+ Parameter { name: "arg"; type: "double" }
+ }
+ Signal {
+ name: "maximumWidthChanged"
+ Parameter { name: "arg"; type: "double" }
+ }
+ Signal {
+ name: "minimumHeightChanged"
+ Parameter { name: "arg"; type: "double" }
+ }
+ Signal {
+ name: "maximumHeightChanged"
+ Parameter { name: "arg"; type: "double" }
+ }
+ Signal {
+ name: "expandingChanged"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Signal {
+ name: "percentageWidthSize"
+ Parameter { name: "arg"; type: "double" }
+ }
+ Signal {
+ name: "itemIndexChanged"
+ Parameter { name: "arg"; type: "int" }
+ }
+ }
+ Component {
+ name: "QtSplitterBase"
+ defaultProperty: "data"
+ prototype: "QQuickItem"
+ exports: ["Splitter 1.0"]
+ attachedType: "QtSplitterAttached"
+ }
+}
diff --git a/src/qtdesktop/private/BasicButton.qml b/src/qtdesktop/private/BasicButton.qml
new file mode 100644
index 00000000..7189e6f5
--- /dev/null
+++ b/src/qtdesktop/private/BasicButton.qml
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0 as Internal
+
+Item {
+ id: button
+
+ signal clicked
+ property alias pressed: behavior.effectivePressed
+ property alias containsMouse: behavior.containsMouse
+ property alias checkable: behavior.checkable // button toggles between checked and !checked
+ property alias checked: behavior.checked
+ property bool activeFocusOnPress: false
+ property alias style: loader.sourceComponent
+ property var styleHints: []
+
+ property color textColor: syspal.text
+ property string tooltip
+
+ Accessible.role: Accessible.Button
+ Accessible.description: tooltip
+
+ signal toolTipTriggered
+
+ // implementation
+
+ property string __position: "only"
+ implicitWidth: loader.implicitWidth
+ implicitHeight: loader.implicitHeight
+
+ Keys.onPressed: {
+ if (event.key === Qt.Key_Space && !event.isAutoRepeat && !behavior.pressed)
+ behavior.keyPressed = true;
+ }
+
+ Keys.onReleased: {
+ if (event.key === Qt.Key_Space && !event.isAutoRepeat && behavior.keyPressed) {
+ behavior.keyPressed = false;
+ if (checkable)
+ checked = !checked;
+ button.clicked();
+ }
+ }
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ sourceComponent: style
+ property alias control: button
+ property alias position: button.__position
+ }
+
+ ButtonBehavior {
+ id: behavior
+ anchors.fill: parent
+ onClicked: button.clicked()
+ onExited: Internal.PrivateHelper.hideToolTip()
+ onCanceled: Internal.PrivateHelper.hideToolTip()
+ onPressed: if (activeFocusOnPress) button.forceActiveFocus()
+
+ Timer {
+ interval: 1000
+ running: containsMouse && !pressed && tooltip.length
+ onTriggered: Internal.PrivateHelper.showToolTip(behavior, Qt.point(behavior.mouseX, behavior.mouseY), tooltip)
+ }
+ }
+
+ SystemPalette { id: syspal }
+}
diff --git a/src/qtdesktop/private/ButtonBehavior.qml b/src/qtdesktop/private/ButtonBehavior.qml
new file mode 100644
index 00000000..1119811c
--- /dev/null
+++ b/src/qtdesktop/private/ButtonBehavior.qml
@@ -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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+MouseArea {
+ property bool checkable: false
+ property bool checked: false
+ property bool keyPressed: false
+ property bool effectivePressed: pressed && containsMouse || keyPressed
+
+ hoverEnabled: true
+ enabled: !keyPressed
+
+ onCheckableChanged: {
+ if (!checkable)
+ checked = false;
+ }
+
+ onReleased: {
+ if (checkable && containsMouse)
+ checked = !checked;
+ }
+}
diff --git a/src/qtdesktop/private/ButtonGroup.js b/src/qtdesktop/private/ButtonGroup.js
new file mode 100644
index 00000000..5b0d9adb
--- /dev/null
+++ b/src/qtdesktop/private/ButtonGroup.js
@@ -0,0 +1,141 @@
+var self;
+var checkHandlers = [];
+var visibleButtons = [];
+var nonVisibleButtons = [];
+var direction;
+
+function create(that, options) {
+ self = that;
+ direction = options.direction || Qt.Horizontal;
+ self.childrenChanged.connect(rebuild);
+// self.widthChanged.connect(resizeChildren);
+ build();
+}
+
+function isButton(item) {
+ if (item && item.hasOwnProperty("__position"))
+ return true;
+ return false;
+}
+
+function hasChecked(item) {
+ return (item && item.hasOwnProperty("checked"));
+}
+
+function destroy() {
+ self.childrenChanged.disconnect(rebuild);
+// self.widthChanged.disconnect(resizeChildren);
+ cleanup();
+}
+
+function build() {
+ visibleButtons = [];
+ nonVisibleButtons = [];
+
+ for (var i = 0, item; (item = self.children[i]); i++) {
+
+ if (item.hasOwnProperty("styleHint"))
+ item.styleHint = styleHint;
+
+ if (!hasChecked(item))
+ continue;
+
+ item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app
+ if (!item.visible) {
+ nonVisibleButtons.push(item);
+ continue;
+ }
+ visibleButtons.push(item);
+
+ if (self.exclusive && item.hasOwnProperty("checkable"))
+ item.checkable = true;
+
+ if (self.exclusive) {
+ item.checked = false;
+ checkHandlers.push(checkExclusive(item));
+ item.checkedChanged.connect(checkHandlers[checkHandlers.length - 1]);
+ }
+ }
+
+ var nrButtons = visibleButtons.length;
+ if (nrButtons == 0)
+ return;
+
+ if (self.checkedButton)
+ self.checkedButton.checked = true;
+ else if (self.exclusive) {
+ self.checkedButton = visibleButtons[0];
+ self.checkedButton.checked = true;
+ }
+
+ if (nrButtons == 1) {
+ finishButton(visibleButtons[0], "only");
+ } else {
+ finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top");
+ for (var i = 1; i < nrButtons - 1; i++)
+ finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle");
+ finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom");
+ }
+}
+
+function finishButton(button, position) {
+ if (isButton(button)) {
+ button.__position = position;
+ if (direction == Qt.Vertical) {
+ button.anchors.left = self.left //mm How to make this not cause binding loops? see QTBUG-17162
+ button.anchors.right = self.right
+ }
+ }
+}
+
+function cleanup() {
+ visibleButtons.forEach(function(item, i) {
+ if (checkHandlers[i])
+ item.checkedChanged.disconnect(checkHandlers[i]);
+ item.visibleChanged.disconnect(rebuild);
+ });
+ checkHandlers = [];
+
+ nonVisibleButtons.forEach(function(item, i) {
+ item.visibleChanged.disconnect(rebuild);
+ });
+}
+
+function rebuild() {
+ if (self == undefined)
+ return;
+
+ cleanup();
+ build();
+}
+
+function resizeChildren() {
+ if (direction != Qt.Horizontal)
+ return;
+
+ var extraPixels = self.width % visibleButtons;
+ var buttonSize = (self.width - extraPixels) / visibleButtons;
+ visibleButtons.forEach(function(item, i) {
+ if (!item || !item.visible)
+ return;
+ item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
+ if (extraPixels > 0)
+ extraPixels--;
+ });
+}
+
+function checkExclusive(item) {
+ var button = item;
+ return function() {
+ for (var i = 0, ref; (ref = visibleButtons[i]); i++) {
+ if (ref.checked == (button === ref))
+ continue;
+
+ // Disconnect the signal to avoid recursive calls
+ ref.checkedChanged.disconnect(checkHandlers[i]);
+ ref.checked = !ref.checked;
+ ref.checkedChanged.connect(checkHandlers[i]);
+ }
+ self.checkedButton = button;
+ }
+}
diff --git a/src/qtdesktop/private/ModalPopupBehavior.qml b/src/qtdesktop/private/ModalPopupBehavior.qml
new file mode 100644
index 00000000..1e95f6f1
--- /dev/null
+++ b/src/qtdesktop/private/ModalPopupBehavior.qml
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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
+
+// KNOWN ISSUES
+// none
+
+Item {
+ id: popupBehavior
+
+ property bool showing: false
+ property bool whenAlso: true // modifier to the "showing" property
+ property bool consumeCancelClick: true
+ property int delay: 0 // delay before popout becomes visible
+ property int deallocationDelay: 3000 // 3 seconds
+
+ property Component popupComponent
+
+ property alias popup: popupLoader.item // read-only
+ property alias window: popupBehavior.root // read-only
+
+ signal prepareToShow
+ signal prepareToHide
+ signal cancelledByClick
+
+ // implementation
+
+ anchors.fill: parent
+
+ onShowingChanged: notifyChange()
+ onWhenAlsoChanged: notifyChange()
+ function notifyChange() {
+ if(showing && whenAlso) {
+ if(popupLoader.sourceComponent == undefined) {
+ popupLoader.sourceComponent = popupComponent;
+ }
+ } else {
+ mouseArea.enabled = false; // disable before opacity is changed in case it has fading behavior
+ if(Qt.isQtObject(popupLoader.item)) {
+ popupBehavior.prepareToHide();
+ popupLoader.item.opacity = 0;
+ }
+ }
+ }
+
+ property Item root: findRoot()
+ function findRoot() {
+ var p = parent;
+ while(p.parent != undefined)
+ p = p.parent;
+
+ return p;
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ enabled: false // enabled only when popout is showing
+ onPressed: {
+ popupBehavior.showing = false;
+ mouse.accepted = consumeCancelClick;
+ cancelledByClick();
+ }
+ }
+
+ Loader {
+ id: popupLoader
+ }
+
+ Timer { // visibility timer
+ running: Qt.isQtObject(popupLoader.item) && showing && whenAlso
+ interval: delay
+ onTriggered: {
+ popupBehavior.prepareToShow();
+ mouseArea.enabled = true;
+ popup.opacity = 1;
+ }
+ }
+
+ Timer { // deallocation timer
+ running: Qt.isQtObject(popupLoader.item) && popupLoader.item.opacity == 0
+ interval: deallocationDelay
+ onTriggered: popupLoader.sourceComponent = undefined
+ }
+
+ states: State {
+ name: "active"
+ when: Qt.isQtObject(popupLoader.item) && popupLoader.item.opacity > 0
+ ParentChange { target: popupBehavior; parent: root }
+ }
+ }
+
diff --git a/src/qtdesktop/private/ScrollAreaHelper.qml b/src/qtdesktop/private/ScrollAreaHelper.qml
new file mode 100644
index 00000000..e99b3276
--- /dev/null
+++ b/src/qtdesktop/private/ScrollAreaHelper.qml
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+WheelArea {
+ id: wheelarea
+
+ property alias horizontalScrollBar: hscrollbar
+ property alias verticalScrollBar: vscrollbar
+ property int macOffset: styleitem.style == "mac" ? 1 : 0
+ property bool blockUpdates: false
+ property int availableHeight : height - (hscrollbar.visible ? hscrollbar.height : 0)
+ property int availableWidth: width - vscrollbar.width
+
+ anchors.fill: parent
+ anchors.margins: frameWidth
+ horizontalMinimumValue: hscrollbar.minimumValue
+ horizontalMaximumValue: hscrollbar.maximumValue
+ verticalMinimumValue: vscrollbar.minimumValue
+ verticalMaximumValue: vscrollbar.maximumValue
+
+ onVerticalValueChanged: {
+ if (!blockUpdates)
+ verticalScrollBar.value = verticalValue
+ }
+
+ onHorizontalValueChanged: {
+ if (!blockUpdates)
+ horizontalScrollBar.value = horizontalValue
+ }
+
+ StyleItem {
+ // This is the filled corner between scrollbars
+ id: cornerFill
+ elementType: "scrollareacorner"
+ width: vscrollbar.width
+ anchors.right: parent.right
+ height: hscrollbar.height
+ anchors.bottom: parent.bottom
+ visible: hscrollbar.visible && vscrollbar.visible
+ }
+
+ ScrollBar {
+ id: hscrollbar
+ orientation: Qt.Horizontal
+ visible: contentWidth > availableWidth
+ maximumValue: contentWidth > availableWidth ? root.contentWidth - availableWidth : 0
+ minimumValue: 0
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: parent.macOffset
+ anchors.bottomMargin: -parent.macOffset
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.rightMargin: vscrollbar.visible ? vscrollbar.width -parent.macOffset: 0
+ onValueChanged: {
+ if (!blockUpdates) {
+ contentX = value
+ horizontalValue = value
+ }
+ }
+ }
+
+ ScrollBar {
+ id: vscrollbar
+ orientation: Qt.Vertical
+ // We cannot bind directly to tree.height due to binding loops so we have to redo the calculation here
+ // visible: contentHeight > availableHeight
+ maximumValue: contentHeight > availableHeight ? root.contentHeight - availableHeight : 0
+ minimumValue: 0
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.topMargin: 1//parent.macOffset
+ anchors.rightMargin: -parent.macOffset
+ anchors.bottomMargin: hscrollbar.visible ? hscrollbar.height - parent.macOffset : 0
+
+ onValueChanged: {
+ if (!blockUpdates) {
+ contentY = value
+ verticalValue = value
+ }
+ }
+ }
+}
diff --git a/src/qtdesktop/private/Splitter.qml b/src/qtdesktop/private/Splitter.qml
new file mode 100644
index 00000000..a6c18511
--- /dev/null
+++ b/src/qtdesktop/private/Splitter.qml
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** 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 QtDesktop 1.0
+
+Splitter {
+ id: root
+ default property alias items: splitterItems.children
+ property alias handles: splitterHandles.children
+ property Component handleDelegate: Rectangle { width:3; color: "black" }
+ property int handleWidth: -1
+ property real preferredSize: 0
+ property int orientation: Qt.Horizontal
+
+ clip: true
+ Component.onCompleted: d.init();
+ onWidthChanged: d.updateLayout();
+ onHeightChanged: d.updateLayout();
+
+ QtObject {
+ id: d
+
+ property bool horizontal: orientation == Qt.Horizontal
+ property string size: horizontal ? "width" : "height"
+ property string minimum: horizontal ? "minimumWidth" : "minimumHeight"
+ property string maximum: horizontal ? "maximumWidth" : "maximumHeight"
+
+ property string offset: horizontal ? "x" : "y"
+ property int expandingIndex: -1
+ property bool updateLayoutGuard: true
+ property bool itemWidthGuard: false
+ property bool itemExpandingGuard: true
+
+ function init()
+ {
+ for (var i=0; i<items.length; ++i) {
+ var item = items[i];
+
+ item.Splitter.itemIndex = i
+ // Assign one, and only one, item to be expanding:
+ if (item.Splitter.expanding === true) {
+ if (d.expandingIndex === -1 && item.visible === true)
+ d.expandingIndex = i
+ else
+ item.Splitter.expanding = false
+ }
+
+ // Anchor each item to fill out all space vertically:
+ if (d.horizontal) {
+ item.anchors.top = splitterItems.top
+ item.anchors.bottom = splitterItems.bottom
+ } else {
+ item.anchors.left = splitterItems.left
+ item.anchors.right = splitterItems.right
+
+ }
+
+ // Listen for changes to width and expanding:
+ propertyChangeListener.createObject(item, {"itemIndex":i});
+ if (i < items.length-1) {
+ // Create a handle for the item, unless its the last:
+ var handle = handleloader.createObject(splitterHandles, {"handleIndex":i});
+
+ if (d.horizontal) {
+ handle.anchors.top = splitterHandles.top
+ handle.anchors.bottom = splitterHandles.bottom
+ } else {
+ handle.anchors.left = splitterHandles.left
+ handle.anchors.right = splitterHandles.right
+ }
+ }
+ }
+
+ if (d.expandingIndex === -1) {
+ // INVARIANT: No item was set as expanding.
+ // We then choose the last visible item instead:
+ d.expandingIndex = items.length - 1
+ for (i=items.length-1; i>=0; --i) {
+ var item = items[i]
+ if (item.visible === true) {
+ d.expandingIndex = i
+ item = items[i]
+ break
+ }
+ }
+ if (items.length && item.visible) {
+ item.Splitter.expanding = true
+ }
+ }
+
+ d.itemExpandingGuard = false
+ d.updateLayoutGuard = false
+ 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.Splitter[minimum] != -1)
+ w += item[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 _width of the each item_
+ if (items.length === 0)
+ return;
+ if (d.updateLayoutGuard === true)
+ return
+ d.updateLayoutGuard = true
+
+ // Use a temporary variable to store values to avoid breaking
+ // property bindings when the value does not actually change:
+ var newValue
+
+ // Ensure all items within min/max:
+ for (var i=0; i<items.length; ++i) {
+ if (i !== d.expandingIndex) {
+ item = items[i];
+ // If the item is using percentage width, convert
+ // that number to real width now:
+ if (item.Splitter.percentageSize !== -1) {
+ newValue = item.Splitter.percentageSize * (root[d.size] / 100)
+ if (newValue !== item[d.size])
+ item[d.size] = newValue
+ }
+ // Ensure item width is not more than maximumSize:
+ if (item.Splitter[maximum] !== -1) {
+ newValue = Math.min(item[d.size], item.Splitter[maximum])
+ if (newValue !== item[d.size])
+ item[d.size] = newValue
+ }
+ // Ensure item width is not more less minimumWidth:
+ if (item.Splitter[minimum] !== -1) {
+ newValue = Math.max(item[d.size], item.Splitter[minimum])
+ if (newValue !== item[d.size])
+ item[d.size] = newValue
+ }
+ }
+ }
+
+ // Special case: set width of expanding item to available space:
+ newValue = root[d.size] - d.accumulatedSize(0, items.length, false);
+ var expandingItem = items[d.expandingIndex]
+ var expandingMinimum = 0
+ if (expandingItem.Splitter[minimum] !== -1)
+ expandingMinimum = expandingItem.Splitter[minimum]
+ newValue = Math.max(newValue, expandingMinimum)
+ if (expandingItem[d.size] !== 0 && expandingItem.Splitter.percentageSize !== -1)
+ expandingItem.Splitter.percentageSize = newValue * (100 / root[d.size])
+ if (expandingItem[d.size] !== newValue)
+ expandingItem[d.size] = newValue
+
+ // Then, position items and handles according to their width:
+ var item, lastVisibleItem
+ var handle, lastVisibleHandle
+ var newpreferredSize = expandingMinimum - 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) {
+ if (lastVisibleHandle) {
+ newValue = lastVisibleHandle[d.offset] + lastVisibleHandle[d.size]
+ if (newValue !== item[d.offset])
+ item[d.offset] = newValue
+ } else {
+ newValue = 0
+ if (newValue !== item[d.offset])
+ item[d.offset] = newValue
+ }
+ newpreferredSize += 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) {
+ newValue = lastVisibleItem[d.offset] + Math.max(0, lastVisibleItem[d.size])
+ if (newValue !== handle[d.offset])
+ handle[d.offset] = newValue
+ newpreferredSize += handle[d.size]
+ lastVisibleHandle = handle
+ }
+ }
+
+ root.preferredSize = newpreferredSize
+ d.updateLayoutGuard = false
+ }
+ }
+
+ Component {
+ id: handleloader
+ Loader {
+ id: myHandle
+ property int handleIndex: 0
+ property Item handle: myHandle
+ property Item splitterItem: items[handleIndex + ((d.expandingIndex > handleIndex) ? 0 : 1)]
+
+ // 'splitterRow' should be an alias, but that fails to resolve runtime:
+ property Item splitterRow: root
+ property Item background: item
+
+ visible: splitterItem.visible
+ sourceComponent: handleDelegate
+ onWidthChanged: d.updateLayout()
+
+ onXChanged: {
+ // For some unknown reason, dragging by X axis only not working in MouseArea, so
+ // to enable it Drag.XandYAxis should be used, therefore not only Y coordinate
+ // changes, but also X and we need to filter out this events, if we have splitter,
+ // that should move vertically
+ if (d.horizontal) {
+ moveHandle()
+ }
+ }
+
+ onYChanged: {
+ moveHandle()
+ }
+
+ 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 >= myHandle[d.offset] >= rightStopX
+ var min = d.accumulatedSize(handleIndex+1, items.length, true)
+ rightStopX = root[d.size] - min - myHandle[d.size]
+ leftStopX = Math.max(leftEdge, myHandle[d.offset])
+ myHandle[d.offset] = Math.min(rightStopX, Math.max(leftStopX, myHandle[d.offset]))
+
+ newWidth = myHandle[d.offset] - leftEdge
+ leftItem = items[handleIndex]
+ if (root[d.size] != 0 && leftItem.Splitter.percentageSize !== -1)
+ leftItem.Splitter.percentageSize = newWidth * (100 / root[d.size])
+ // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
+ 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 <= myHandle[d.offset] <= rightStopX
+ var min = d.accumulatedSize(0, handleIndex+1, true)
+ leftStopX = min - myHandle[d.size]
+ rightStopX = Math.min((rightEdge - myHandle[d.size]), myHandle[d.offset])
+ myHandle[d.offset] = Math.max(leftStopX, Math.min(myHandle[d.offset], rightStopX))
+
+ newWidth = rightEdge - (myHandle[d.offset] + myHandle[d.size])
+ rightItem = items[handleIndex+1]
+ if (root[d.size] !== 0 && rightItem[d.percentageSize] !== -1)
+ rightItem.Splitter.percentageSize = newWidth * (100 / root[d.size])
+ // The next line will trigger 'updateLayout' inside 'propertyChangeListener':
+ rightItem[d.size] = newWidth
+ }
+ }
+ }
+ }
+
+ Item {
+ id: splitterItems
+ anchors.fill: parent
+ }
+ Item {
+ id: splitterHandles
+ anchors.fill: parent
+ }
+
+ Component {
+ // This dummy item becomes a child of all
+ // items it the splitter, just to provide a way
+ // to listen for changes to their width, expanding etc.
+ id: propertyChangeListener
+ Item {
+ id: target
+ width: parent[d.size]
+ property bool expanding: parent.Splitter.expanding
+ property real percentageSize: parent.Splitter.percentageSize
+ property real minimumWidth: parent.Splitter[d.minimum]
+ property real maximumSize: parent.Splitter[d.maximum]
+ property int itemIndex: parent.Splitter.itemIndex
+
+ onPercentageSizeChanged: d.updateLayout();
+ onMinimumWidthChanged: d.updateLayout();
+ onMaximumSizeChanged: d.updateLayout();
+ onExpandingChanged: updateExpandingIndex()
+
+ function updateExpandingIndex()
+ {
+ // The following code is needed to avoid a binding
+ // loop, since we might change 'expanding' again to a different item:
+ if (d.itemExpandingGuard === true)
+ return
+ d.itemExpandingGuard = true
+ // break binding:
+ expanding = false
+
+ // 'expanding' follows radio button behavior:
+ // First, find the new expanding item:
+ var newIndex = items.length-1
+ for (var i=0; i<items.length; ++i) {
+ var item = items[i]
+ if (i !== d.expandingIndex && item.Splitter.expanding === true && item.visible === true) {
+ newIndex = i
+ break
+ }
+ }
+ item = items[newIndex]
+ if (item.visible === false) {
+ // So now we ended up with the last item in the splitter to be
+ // expanding, but it turns out to not be visible. So we need to
+ // traverse backwards again to find one that is visible...
+ for (i=items.length-2; i>=0; --i) {
+ var item = items[i]
+ if (item.visible === true) {
+ newIndex = i
+ item = items[newIndex]
+ break
+ }
+ }
+ }
+
+ // Tell the found item that it is expanding:
+ if (item.Splitter.expanding !== true)
+ item.Splitter.expanding = true
+ // ...and the old one that it is not:
+ if (newIndex !== d.expandingIndex) {
+ item = items[d.expandingIndex]
+ if (item.Splitter.expanding !== false)
+ item.Splitter.expanding = false
+ }
+ // update index:
+ d.expandingIndex = newIndex
+ d.updateLayout();
+ // recreate binding:
+ expanding = Qt.binding(function() { return parent.Splitter.expanding })
+ d.itemExpandingGuard = false
+ }
+
+ function handleSizeChanged() {
+ // We need to update the layout.
+ // The following code is needed to avoid a binding
+ // loop, since we might change 'width' again to a different value:
+ if (d.itemWidthGuard === true)
+ return
+ d.itemWidthGuard = true
+ // Break binding:
+ this[d.size] = 0
+
+ d.updateLayout()
+
+ // Restablish binding:
+ width = Qt.binding(function() { return parent[d.size]; })
+ d.itemWidthGuard = false
+ }
+
+ onWidthChanged: handleSizeChanged()
+ onHeightChanged: handleSizeChanged()
+ onVisibleChanged: {
+ // Hiding the expanding item forces us to
+ // select a new one (and therefore not recommended):
+ if (d.expandingIndex === itemIndex) {
+ updateExpandingIndex()
+ } else {
+ if (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)
+ parent[d.size] -= overflow
+ }
+ d.updateLayout()
+ }
+ }
+ }
+ }
+}
diff --git a/src/qtdesktop/qdesktopitem.cpp b/src/qtdesktop/qdesktopitem.cpp
new file mode 100644
index 00000000..15c260af
--- /dev/null
+++ b/src/qtdesktop/qdesktopitem.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qdesktopitem.h"
+
+QDesktopItem::QDesktopItem(QObject* obj) : QObject(obj) {
+ connect(&desktopWidget, SIGNAL(resized(int)), this, SIGNAL(screenGeometryChanged()));
+ connect(&desktopWidget, SIGNAL(resized(int)), this, SIGNAL(availableGeometryChanged()));
+ connect(&desktopWidget, SIGNAL(workAreaResized(int)), this, SIGNAL(availableGeometryChanged()));
+ connect(&desktopWidget, SIGNAL(screenCountChanged(int)), this, SIGNAL(screenCountChanged()));
+}
+
+int QDesktopItem::screenCount() const
+{
+ return desktopWidget.screenCount();
+}
+
+QRect QDesktopItem::screenGeometry(int screen) const {
+ return desktopWidget.screenGeometry(screen);
+}
+
+QRect QDesktopItem::availableGeometry(int screen) const {
+ return desktopWidget.availableGeometry(screen);
+}
+
+int QDesktopItem::screenWidth() const
+{
+ return desktopWidget.screenGeometry().width();
+}
+
+int QDesktopItem::screenHeight() const
+{
+ return desktopWidget.screenGeometry().height();
+}
+
+int QDesktopItem::availableWidth() const
+{
+ return desktopWidget.availableGeometry().width();
+}
+
+int QDesktopItem::availableHeight() const
+{
+ return desktopWidget.availableGeometry().height();
+}
+
+QDesktopItem *QDesktopItem::qmlAttachedProperties(QObject *obj) {
+ return new QDesktopItem(obj);
+}
diff --git a/src/qtdesktop/qdesktopitem.h b/src/qtdesktop/qdesktopitem.h
new file mode 100644
index 00000000..6639b8ee
--- /dev/null
+++ b/src/qtdesktop/qdesktopitem.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QDESKTOPITEM_H
+#define QDESKTOPITEM_H
+
+#include <QtWidgets/QDesktopWidget>
+#include <QtQml>
+
+class QDesktopItem : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int screenWidth READ screenWidth NOTIFY screenGeometryChanged)
+ Q_PROPERTY(int screenHeight READ screenHeight NOTIFY screenGeometryChanged)
+ Q_PROPERTY(int availableWidth READ availableWidth NOTIFY availableGeometryChanged)
+ Q_PROPERTY(int availableHeight READ availableHeight NOTIFY availableGeometryChanged)
+ Q_PROPERTY(int screenCount READ screenCount NOTIFY screenCountChanged)
+
+public:
+ QDesktopItem(QObject* obj);
+
+ int screenCount() const;
+ Q_INVOKABLE QRect screenGeometry(int screen) const;
+ Q_INVOKABLE QRect availableGeometry(int screen) const;
+ int screenWidth() const;
+ int screenHeight() const;
+ int availableWidth() const;
+ int availableHeight() const;
+ static QDesktopItem *qmlAttachedProperties(QObject *obj);
+
+private:
+ QDesktopWidget desktopWidget;
+
+Q_SIGNALS:
+ void screenGeometryChanged();
+ void availableGeometryChanged();
+ void screenCountChanged();
+};
+
+QML_DECLARE_TYPEINFO(QDesktopItem, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QDesktopItemITEM_H
diff --git a/src/qtdesktop/qfiledialogitem.cpp b/src/qtdesktop/qfiledialogitem.cpp
new file mode 100644
index 00000000..f32c77f5
--- /dev/null
+++ b/src/qtdesktop/qfiledialogitem.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Alberto Mardegan <info@mardy.it>
+** Contact: http://www.qt-project.org/
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \qmlclass FileDialog QFileDialogItem
+ \ingroup qt-components
+ \brief Dialog component for choosing files from a local filesystem.
+
+ FileDialog implements a basic file chooser: it allows the user to select
+ existing files and/or directories, or create new filenames.
+*/
+
+/*!
+ \qmlsignal FileDialog::accepted
+
+ The \a accepted signal is emitted when the user has finished using the
+ dialog. You can then inspect the \a filePath or \a filePaths properties to
+ get the selection.
+
+ Example:
+
+ \qml
+ FileDialog {
+ onAccepted: { console.log("Selected file: " + filePath) }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlsignal FileDialog::rejected
+
+ The \a rejected signal is emitted when the user has dismissed the dialog,
+ either by closing the dialog window or by pressing the Cancel button.
+*/
+
+#include "qfiledialogitem.h"
+
+#if QT_VERSION < 0x050000
+#include <QGraphicsScene>
+#endif
+
+QFileDialogItem::QFileDialogItem():
+ _dialog(new QFileDialog),
+ _isOpen(false),
+ _selectExisting(true),
+ _selectMultiple(false),
+ _selectFolder(false)
+{
+ QObject::connect(_dialog, SIGNAL(accepted()), this, SIGNAL(accepted()));
+ QObject::connect(_dialog, SIGNAL(rejected()), this, SIGNAL(rejected()));
+}
+
+QFileDialogItem::~QFileDialogItem()
+{
+ delete _dialog;
+}
+
+/*!
+ \qmlproperty string FileDialog::title
+
+ The title of the dialog window.
+*/
+void QFileDialogItem::setTitle(QString title)
+{
+ _dialog->setWindowTitle(title);
+ emit titleChanged();
+}
+
+/* Intentionally left undocumented, as we might decide to remove it later */
+void QFileDialogItem::setModal(bool modal)
+{
+ bool visible = _dialog->isVisible();
+ _dialog->hide();
+ _dialog->setWindowModality(modal ? Qt::WindowModal : Qt::NonModal);
+
+ if (visible)
+ _dialog->show();
+ emit modalityChanged();
+}
+
+/*!
+ \qmlproperty bool FileDialog::selectExisting
+
+ Whether only existing files or directories can be selected.
+
+ By default, this property is true.
+*/
+void QFileDialogItem::setSelectExisting(bool selectExisting)
+{
+ if (selectExisting == _selectExisting) return;
+ _selectExisting = selectExisting;
+
+ updateFileMode();
+
+ _dialog->setAcceptMode(selectExisting ?
+ QFileDialog::AcceptOpen : QFileDialog::AcceptSave);
+
+ Q_EMIT selectExistingChanged();
+}
+
+/*!
+ \qmlproperty bool FileDialog::selectMultiple
+
+ Whether more than one filename can be selected.
+
+ By default, this property is false.
+*/
+void QFileDialogItem::setSelectMultiple(bool selectMultiple)
+{
+ if (selectMultiple == _selectMultiple) return;
+ _selectMultiple = selectMultiple;
+
+ updateFileMode();
+
+ Q_EMIT selectMultipleChanged();
+}
+
+/*!
+ \qmlproperty bool FileDialog::selectFolder
+
+ Whether the selected item should be a folder.
+
+ By default, this property is false.
+*/
+void QFileDialogItem::setSelectFolder(bool selectFolder)
+{
+ if (selectFolder == _selectFolder) return;
+ _selectFolder = selectFolder;
+
+ updateFileMode();
+
+ Q_EMIT selectFolderChanged();
+}
+
+void QFileDialogItem::updateFileMode()
+{
+ QFileDialog::FileMode mode = QFileDialog::AnyFile;
+
+ if (_selectFolder) {
+ mode = QFileDialog::Directory;
+ _dialog->setOption(QFileDialog::ShowDirsOnly, true);
+ } else if (_selectExisting) {
+ mode = _selectMultiple ?
+ QFileDialog::ExistingFiles : QFileDialog::ExistingFile;
+ _dialog->setOption(QFileDialog::ShowDirsOnly, false);
+ }
+ _dialog->setFileMode(mode);
+}
+
+/*!
+ \qmlproperty string FileDialog::folder
+
+ The path to the currently selected folder. Setting this property before
+ invoking open() will cause the file browser to be initially positioned on
+ the specified folder.
+
+ The value of this property is also updated after the dialog is closed.
+
+ By default, this property is false.
+*/
+void QFileDialogItem::setFolder(const QString &folder)
+{
+ _dialog->setDirectory(folder);
+ Q_EMIT folderChanged();
+}
+
+QString QFileDialogItem::folder() const
+{
+ return _dialog->directory().absolutePath();
+}
+
+/*!
+ \qmlproperty list<string> FileDialog::nameFilters
+
+ A list of strings to be used as file name filters. Each string can be a
+ space-separated list of filters; filters may include the ? and * wildcards.
+ The list of filters can also be enclosed in parentheses and a textual
+ description of the filter can be provided.
+
+ For example:
+
+ \qml
+ FileDialog {
+ nameFilters: [ "Image files (*.jpg *.png)", "All files (*)" ]
+ }
+ \endqml
+
+ \note Directories are not excluded by filters.
+*/
+void QFileDialogItem::setNameFilters(const QStringList &nameFilters)
+{
+ _dialog->setNameFilters(nameFilters);
+ Q_EMIT nameFiltersChanged();
+}
+
+/*!
+ \qmlproperty string FileDialog::filePath
+
+ The path of the file which was selected by the user.
+
+ \note This property is set only if exactly one file was selected. In all
+ other cases, it will return an empty string.
+
+ \sa filePaths
+*/
+QString QFileDialogItem::filePath() const
+{
+ QStringList files = filePaths();
+ return (files.count() == 1) ? files[0] : QString();
+}
+
+/*!
+ \qmlproperty list<string> FileDialog::filePaths
+
+ The list of file paths which were selected by the user.
+*/
+QStringList QFileDialogItem::filePaths() const
+{
+ return _dialog->selectedFiles();
+}
+
+void QFileDialogItem::setVisible(bool visible)
+{
+ if (visible)
+ open();
+ else
+ close();
+}
+
+/*!
+ \qmlmethod void FileDialog::open()
+
+ Shows the dialog to the user.
+*/
+void QFileDialogItem::open()
+{
+#if QT_VERSION < 0x050000
+ /* We must set the QtDeclarative scene as parent widget for the
+ * QDialog, so that it will be positioned on top of it.
+ * This is also necessary for the modality to work.
+ */
+ if (_dialog->parentWidget() == 0) {
+ QList<QGraphicsView *> views = scene()->views();
+ if (!views.isEmpty()) {
+ _dialog->setParent(views[0], Qt::Dialog);
+ }
+ }
+#endif
+
+ if (!isVisible()) {
+ _dialog->show();
+ emit visibleChanged();
+ }
+ _isOpen = true;
+}
+
+/*!
+ \qmlmethod void FileDialog::close()
+
+ Closes the dialog.
+*/
+void QFileDialogItem::close()
+{
+ _isOpen = false;
+ _dialog->hide();
+ emit visibleChanged();
+}
+
+#if QT_VERSION < 0x050000
+QVariant QFileDialogItem::itemChange(GraphicsItemChange change,
+ const QVariant &value)
+{
+ if (change == QGraphicsItem::QGraphicsItem::ItemVisibleHasChanged) {
+ bool visible = value.toBool();
+
+ if (visible && _isOpen) {
+ _dialog->show();
+ } else {
+ _dialog->hide();
+ }
+ emit visibleChanged();
+ }
+
+ return QDeclarativeItem::itemChange(change, value);
+}
+#endif
diff --git a/src/qtdesktop/qfiledialogitem.h b/src/qtdesktop/qfiledialogitem.h
new file mode 100644
index 00000000..1870a3a9
--- /dev/null
+++ b/src/qtdesktop/qfiledialogitem.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Alberto Mardegan <info@mardy.it>
+** Contact: http://www.qt-project.org/
+**
+** 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 QFILEDIALOGITEM_H
+#define QFILEDIALOGITEM_H
+
+#include <QApplication>
+#if QT_VERSION < 0x050000
+#include <QDeclarativeItem>
+#include <QDeclarativeView>
+#else
+#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickView>
+#endif
+#include <QFileDialog>
+
+#if QT_VERSION < 0x050000
+class QFileDialogItem : public QDeclarativeItem
+#else
+class QFileDialogItem : public QQuickItem
+#endif
+{
+ Q_OBJECT
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+ Q_PROPERTY(bool modal READ modal WRITE setModal NOTIFY modalityChanged)
+ Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
+ Q_PROPERTY(bool selectExisting READ selectExisting \
+ WRITE setSelectExisting NOTIFY selectExistingChanged)
+ Q_PROPERTY(bool selectMultiple READ selectMultiple \
+ WRITE setSelectMultiple NOTIFY selectMultipleChanged)
+ Q_PROPERTY(bool selectFolder READ selectFolder \
+ WRITE setSelectFolder NOTIFY selectFolderChanged)
+ Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
+ Q_PROPERTY(QStringList nameFilters READ nameFilters \
+ WRITE setNameFilters NOTIFY nameFiltersChanged)
+ Q_PROPERTY(QString filePath READ filePath NOTIFY accepted)
+ Q_PROPERTY(QStringList filePaths READ filePaths NOTIFY accepted)
+
+public:
+ QFileDialogItem();
+ ~QFileDialogItem();
+
+ bool isVisible() const { return _dialog->isVisible(); }
+ QString title() const { return _dialog->windowTitle(); }
+ bool modal() const { return _dialog->isModal(); }
+ bool selectExisting() const { return _selectExisting; }
+ bool selectMultiple() const { return _selectMultiple; }
+ bool selectFolder() const { return _selectFolder; }
+ QString folder() const;
+ QStringList nameFilters() const { return _dialog->nameFilters(); }
+ QString filePath() const;
+ QStringList filePaths() const;
+
+ void setVisible(bool visible);
+ void setTitle(QString title);
+ void setModal(bool modal);
+ void setSelectExisting(bool selectExisting);
+ void setSelectMultiple(bool selectMultiple);
+ void setSelectFolder(bool selectFolder);
+ void setFolder(const QString &folder);
+ void setNameFilters(const QStringList &nameFilters);
+
+public Q_SLOTS:
+ void open();
+ void close();
+
+Q_SIGNALS:
+ void titleChanged();
+ void modalityChanged();
+ void accepted();
+ void rejected();
+ void selectExistingChanged();
+ void selectMultipleChanged();
+ void selectFolderChanged();
+ void folderChanged();
+ void nameFiltersChanged();
+ void visibleChanged();
+
+protected:
+#if QT_VERSION < 0x050000
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+#endif
+
+private:
+ void updateFileMode();
+
+private:
+ QFileDialog *_dialog;
+ bool _isOpen;
+ bool _selectExisting;
+ bool _selectMultiple;
+ bool _selectFolder;
+};
+
+#endif // QFILEDIALOGITEM_H
diff --git a/src/qtdesktop/qmldir b/src/qtdesktop/qmldir
new file mode 100644
index 00000000..c3863d8c
--- /dev/null
+++ b/src/qtdesktop/qmldir
@@ -0,0 +1,33 @@
+module QtDesktop
+plugin styleplugin plugin
+ApplicationWindow 1.0 ApplicationWindow.qml
+Button 1.0 Button.qml
+ButtonRow 1.0 ButtonRow.qml
+ButtonColumn 1.0 ButtonColumn.qml
+CheckBox 1.0 CheckBox.qml
+ComboBox 1.0 ComboBox.qml
+ContextMenu 1.0 ContextMenu.qml
+Dial 1.0 Dial.qml
+Dialog 1.0 Dialog.qml
+Frame 1.0 Frame.qml
+GroupBox 1.0 GroupBox.qml
+Label 1.0 Label.qml
+ProgressBar 1.0 ProgressBar.qml
+RadioButton 1.0 RadioButton.qml
+ScrollArea 1.0 ScrollArea.qml
+ScrollBar 1.0 ScrollBar.qml
+Slider 1.0 Slider.qml
+SpinBox 1.0 SpinBox.qml
+SplitterRow 1.0 SplitterRow.qml
+SplitterColumn 1.0 SplitterColumn.qml
+StatusBar 1.0 StatusBar.qml
+Tab 1.0 Tab.qml
+TabBar 1.0 TabBar.qml
+TabFrame 1.0 TabFrame.qml
+TableView 1.0 TableView.qml
+TableColumn 1.0 TableColumn.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/qtdesktop/qquickcomponentsprivate.cpp b/src/qtdesktop/qquickcomponentsprivate.cpp
new file mode 100644
index 00000000..54b41b4c
--- /dev/null
+++ b/src/qtdesktop/qquickcomponentsprivate.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 "qquickcomponentsprivate.h"
+#include <QToolTip>
+#include <QQuickWindow>
+
+
+QQuickComponentsPrivate::QQuickComponentsPrivate(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+void QQuickComponentsPrivate::showToolTip(QQuickItem *item, const QPointF &pos, const QString &str)
+{
+ if (!item || !item->window())
+ return;
+
+ QToolTip::showText(item->window()->mapToGlobal(item->mapToScene(pos).toPoint()), str);
+}
+
+void QQuickComponentsPrivate::hideToolTip()
+{
+ QToolTip::hideText();
+}
diff --git a/src/qtdesktop/qquickcomponentsprivate.h b/src/qtdesktop/qquickcomponentsprivate.h
new file mode 100644
index 00000000..5a5fa794
--- /dev/null
+++ b/src/qtdesktop/qquickcomponentsprivate.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 QQUICKCOMPONENTSPRIVATE_H
+#define QQUICKCOMPONENTSPRIVATE_H
+
+#include <QObject>
+#include <QQuickItem>
+
+class QQuickComponentsPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QQuickComponentsPrivate(QObject *parent = 0);
+
+ Q_INVOKABLE void showToolTip(QQuickItem *item, const QPointF &pos, const QString &text);
+ Q_INVOKABLE void hideToolTip();
+};
+
+#endif
diff --git a/src/qtdesktop/qquicklayout.cpp b/src/qtdesktop/qquicklayout.cpp
new file mode 100644
index 00000000..36619359
--- /dev/null
+++ b/src/qtdesktop/qquicklayout.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** 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.h"
+#include <QEvent>
+#include <QApplication>
+#include <QtCore/qnumeric.h>
+
+
+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();
+}
+
+void QQuickComponentsLayoutAttached::setMinimumHeight(qreal height)
+{
+ if (qIsNaN(height) || m_minimumHeight == height)
+ return;
+
+ m_minimumHeight = height;
+ updateLayout();
+}
+
+void QQuickComponentsLayoutAttached::setMaximumWidth(qreal width)
+{
+ if (qIsNaN(width) || m_maximumWidth == width)
+ return;
+
+ m_maximumWidth = width;
+ updateLayout();
+}
+
+void QQuickComponentsLayoutAttached::setMaximumHeight(qreal height)
+{
+ if (qIsNaN(height) || m_maximumHeight == height)
+ return;
+
+ m_maximumHeight = height;
+ updateLayout();
+}
+
+void QQuickComponentsLayoutAttached::setVerticalSizePolicy(QQuickComponentsLayout::SizePolicy policy)
+{
+ if (m_verticalSizePolicy != policy) {
+ m_verticalSizePolicy = policy;
+ updateLayout();
+ }
+}
+
+void QQuickComponentsLayoutAttached::setHorizontalSizePolicy(QQuickComponentsLayout::SizePolicy policy)
+{
+ if (m_horizontalSizePolicy != policy) {
+ m_horizontalSizePolicy = policy;
+ updateLayout();
+ }
+}
+
+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()
+{
+
+}
diff --git a/src/qtdesktop/qquicklayout.h b/src/qtdesktop/qquicklayout.h
new file mode 100644
index 00000000..86f50266
--- /dev/null
+++ b/src/qtdesktop/qquicklayout.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** 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 QDECLARATIVELAYOUT_H
+#define QDECLARATIVELAYOUT_H
+
+#include <QPointer>
+#include <QQuickItem>
+
+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)
+ Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight)
+ Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth)
+ Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight)
+ Q_PROPERTY(QQuickComponentsLayout::SizePolicy verticalSizePolicy READ verticalSizePolicy WRITE setVerticalSizePolicy)
+ Q_PROPERTY(QQuickComponentsLayout::SizePolicy horizontalSizePolicy READ horizontalSizePolicy WRITE setHorizontalSizePolicy)
+
+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);
+
+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;
+};
+
+QML_DECLARE_TYPE(QQuickComponentsLayout)
+QML_DECLARE_TYPEINFO(QQuickComponentsLayout, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif
diff --git a/src/qtdesktop/qquicklayoutengine.cpp b/src/qtdesktop/qquicklayoutengine.cpp
new file mode 100644
index 00000000..f11a2107
--- /dev/null
+++ b/src/qtdesktop/qquicklayoutengine.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** 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"
+
+
+/*
+ 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;
+ }
+}
diff --git a/src/qtdesktop/qquicklayoutengine_p.h b/src/qtdesktop/qquicklayoutengine_p.h
new file mode 100644
index 00000000..c4cdaf08
--- /dev/null
+++ b/src/qtdesktop/qquicklayoutengine_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 QDECLARATIVELAYOUTENGINE_H
+#define QDECLARATIVELAYOUTENGINE_H
+
+#include <QVector>
+
+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);
+
+#endif
diff --git a/src/qtdesktop/qquicklinearlayout.cpp b/src/qtdesktop/qquicklinearlayout.cpp
new file mode 100644
index 00000000..995551d1
--- /dev/null
+++ b/src/qtdesktop/qquicklinearlayout.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** 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.h"
+#include "qquicklayoutengine_p.h"
+#include <QtCore/qnumeric.h>
+
+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();
+
+ foreach (QQuickItem *child, children)
+ insertLayoutItem(child);
+}
+
+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()));
+}
+
+void QQuickComponentsLinearLayout::removeLayoutItem(QQuickItem *item)
+{
+ if (!m_items.removeOne(item))
+ return;
+
+ invalidate();
+ QObject::disconnect(item, SIGNAL(destroyed()), this, SLOT(onItemDestroyed()));
+}
+
+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 (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;
+ }
+
+ if (m_orientation == Horizontal) {
+ qDeclarativeLayoutCalculate(itemData, 0, count, 0, width(), m_spacing);
+
+ for (int i = 0; i < count; i++) {
+ QQuickItem *item = m_items.at(i);
+ const QQuickComponentsLayoutInfo &data = itemData.at(i);
+
+ item->setX(data.pos);
+ item->setY(height()/2 - item->height()/2);
+ item->setWidth(data.size);
+ }
+ } else {
+ qDeclarativeLayoutCalculate(itemData, 0, count, 0, height(), m_spacing);
+
+ for (int i = 0; i < count; i++) {
+ QQuickItem *item = m_items.at(i);
+ const QQuickComponentsLayoutInfo &data = itemData.at(i);
+
+ item->setY(data.pos);
+ item->setX(width()/2 - item->width()/2);
+ item->setHeight(data.size);
+ }
+ }
+
+ // 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);
+ }
+}
diff --git a/src/qtdesktop/qquicklinearlayout.h b/src/qtdesktop/qquicklinearlayout.h
new file mode 100644
index 00000000..8cd73e86
--- /dev/null
+++ b/src/qtdesktop/qquicklinearlayout.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 QDECLARATIVELINEARLAYOUT_H
+#define QDECLARATIVELINEARLAYOUT_H
+
+#include "qquicklayout.h"
+
+
+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 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) {}
+};
+
+#endif
diff --git a/src/qtdesktop/qrangemodel.cpp b/src/qtdesktop/qrangemodel.cpp
new file mode 100644
index 00000000..ac876824
--- /dev/null
+++ b/src/qtdesktop/qrangemodel.cpp
@@ -0,0 +1,534 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+ \class QRangeModel
+ \brief The QRangeModel class, helps users to build components that depend
+ on some value and/or position to be in a certain range previously defined
+
+ With this class, the user sets a value range and a position range, which
+ represent the valid values/positions the model can assume. It is worth telling
+ that the value property always has priority over the position property. A nice use
+ case, would be a Slider implementation with the help of QRangeModel. If the user sets
+ a value range to [0,100], a position range to [50,100] and sets the value
+ to 80, the equivalent position would be 90. After that, if the user decides to
+ resize the slider, the value would be the same, but the knob position would
+ be updated due to the new position range.
+
+ \ingroup qt-components
+*/
+
+#include <QEvent>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QGraphicsSceneEvent>
+#include <QDebug>
+
+#ifndef QT_NO_ACCESSIBILITY
+#include <QAccessible>
+#endif
+
+#include "qrangemodel.h"
+#include "qrangemodel_p.h"
+
+QRangeModelPrivate::QRangeModelPrivate(QRangeModel *qq)
+ : q_ptr(qq)
+{
+}
+
+QRangeModelPrivate::~QRangeModelPrivate()
+{
+}
+
+void QRangeModelPrivate::init()
+{
+ minimum = 0;
+ maximum = 99;
+ stepSize = 0;
+ value = 0;
+ pos = 0;
+ posatmin = 0;
+ posatmax = 0;
+ inverted = false;
+}
+
+/*!
+ Calculates the position that is going to be seen outside by the component
+ that is using QRangeModel. It takes into account the \l stepSize,
+ \l positionAtMinimum, \l positionAtMaximum properties
+ and \a position that is passed as parameter.
+*/
+
+qreal QRangeModelPrivate::publicPosition(qreal position) const
+{
+ // Calculate the equivalent stepSize for the position property.
+ const qreal min = effectivePosAtMin();
+ const qreal max = effectivePosAtMax();
+ const qreal valueRange = maximum - minimum;
+ const qreal positionValueRatio = valueRange ? (max - min) / valueRange : 0;
+ const qreal positionStep = stepSize * positionValueRatio;
+
+ if (positionStep == 0)
+ return (min < max) ? qBound(min, position, max) : qBound(max, position, min);
+
+ const int stepSizeMultiplier = (position - min) / positionStep;
+
+ // Test whether value is below minimum range
+ if (stepSizeMultiplier < 0)
+ return min;
+
+ qreal leftEdge = (stepSizeMultiplier * positionStep) + min;
+ qreal rightEdge = ((stepSizeMultiplier + 1) * positionStep) + min;
+
+ if (min < max) {
+ leftEdge = qMin(leftEdge, max);
+ rightEdge = qMin(rightEdge, max);
+ } else {
+ leftEdge = qMax(leftEdge, max);
+ rightEdge = qMax(rightEdge, max);
+ }
+
+ if (qAbs(leftEdge - position) <= qAbs(rightEdge - position))
+ return leftEdge;
+ return rightEdge;
+}
+
+/*!
+ Calculates the value that is going to be seen outside by the component
+ that is using QRangeModel. It takes into account the \l stepSize,
+ \l minimumValue, \l maximumValue properties
+ and \a value that is passed as parameter.
+*/
+
+qreal QRangeModelPrivate::publicValue(qreal value) const
+{
+ // It is important to do value-within-range check this
+ // late (as opposed to during setPosition()). The reason is
+ // QML bindings; a position that is initially invalid because it lays
+ // outside the range, might become valid later if the range changes.
+
+ if (stepSize == 0)
+ return qBound(minimum, value, maximum);
+
+ const int stepSizeMultiplier = (value - minimum) / stepSize;
+
+ // Test whether value is below minimum range
+ if (stepSizeMultiplier < 0)
+ return minimum;
+
+ const qreal leftEdge = qMin(maximum, (stepSizeMultiplier * stepSize) + minimum);
+ const qreal rightEdge = qMin(maximum, ((stepSizeMultiplier + 1) * stepSize) + minimum);
+ const qreal middle = (leftEdge + rightEdge) / 2;
+
+ return (value <= middle) ? leftEdge : rightEdge;
+}
+
+/*!
+ Checks if the \l value or \l position, that is seen by the user, has changed and emits the changed signal if it
+ has changed.
+*/
+
+void QRangeModelPrivate::emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition)
+{
+ Q_Q(QRangeModel);
+
+ // Effective value and position might have changed even in cases when e.g. d->value is
+ // unchanged. This will be the case when operating with values outside range:
+ const qreal newValue = q->value();
+ const qreal newPosition = q->position();
+ if (!qFuzzyCompare(newValue, oldValue))
+ emit q->valueChanged(newValue);
+ if (!qFuzzyCompare(newPosition, oldPosition))
+ emit q->positionChanged(newPosition);
+}
+
+/*!
+ Constructs a QRangeModel with \a parent
+*/
+
+QRangeModel::QRangeModel(QObject *parent)
+ : QObject(parent), d_ptr(new QRangeModelPrivate(this))
+{
+ Q_D(QRangeModel);
+ d->init();
+}
+
+/*!
+ \internal
+ Constructs a QRangeModel with private class pointer \a dd and \a parent
+*/
+
+QRangeModel::QRangeModel(QRangeModelPrivate &dd, QObject *parent)
+ : QObject(parent), d_ptr(&dd)
+{
+ Q_D(QRangeModel);
+ d->init();
+}
+
+/*!
+ Destroys the QRangeModel
+*/
+
+QRangeModel::~QRangeModel()
+{
+ delete d_ptr;
+ d_ptr = 0;
+}
+
+/*!
+ Sets the range of valid positions, that \l position can assume externally, with
+ \a min and \a max.
+ Such range is represented by \l positionAtMinimum and \l positionAtMaximum
+*/
+
+void QRangeModel::setPositionRange(qreal min, qreal max)
+{
+ Q_D(QRangeModel);
+
+ bool emitPosAtMinChanged = !qFuzzyCompare(min, d->posatmin);
+ bool emitPosAtMaxChanged = !qFuzzyCompare(max, d->posatmax);
+
+ if (!(emitPosAtMinChanged || emitPosAtMaxChanged))
+ return;
+
+ const qreal oldPosition = position();
+ d->posatmin = min;
+ d->posatmax = max;
+
+ // When a new positionRange is defined, the position property must be updated based on the value property.
+ // For instance, imagine that you have a valueRange of [0,100] and a position range of [20,100],
+ // if a user set the value to 50, the position would be 60. If this positionRange is updated to [0,100], then
+ // the new position, based on the value (50), will be 50.
+ // If the newPosition is different than the old one, it must be updated, in order to emit
+ // the positionChanged signal.
+ d->pos = d->equivalentPosition(d->value);
+
+ if (emitPosAtMinChanged)
+ emit positionAtMinimumChanged(d->posatmin);
+ if (emitPosAtMaxChanged)
+ emit positionAtMaximumChanged(d->posatmax);
+
+ d->emitValueAndPositionIfChanged(value(), oldPosition);
+}
+/*!
+ Sets the range of valid values, that \l value can assume externally, with
+ \a min and \a max. The range has the following constraint: \a min must be less or equal \a max
+ Such range is represented by \l minimumValue and \l maximumValue
+*/
+
+void QRangeModel::setRange(qreal min, qreal max)
+{
+ Q_D(QRangeModel);
+
+ bool emitMinimumChanged = !qFuzzyCompare(min, d->minimum);
+ bool emitMaximumChanged = !qFuzzyCompare(max, d->maximum);
+
+ if (!(emitMinimumChanged || emitMaximumChanged))
+ return;
+
+ const qreal oldValue = value();
+ const qreal oldPosition = position();
+
+ d->minimum = min;
+ d->maximum = qMax(min, max);
+
+ // Update internal position if it was changed. It can occurs if internal value changes, due to range update
+ d->pos = d->equivalentPosition(d->value);
+
+ if (emitMinimumChanged)
+ emit minimumChanged(d->minimum);
+ if (emitMaximumChanged)
+ emit maximumChanged(d->maximum);
+
+ d->emitValueAndPositionIfChanged(oldValue, oldPosition);
+}
+
+/*!
+ \property QRangeModel::minimumValue
+ \brief the minimum value that \l value can assume
+
+ This property's default value is 0
+*/
+
+void QRangeModel::setMinimum(qreal min)
+{
+ Q_D(const QRangeModel);
+ setRange(min, d->maximum);
+}
+
+qreal QRangeModel::minimum() const
+{
+ Q_D(const QRangeModel);
+ return d->minimum;
+}
+
+/*!
+ \property QRangeModel::maximumValue
+ \brief the maximum value that \l value can assume
+
+ This property's default value is 99
+*/
+
+void QRangeModel::setMaximum(qreal max)
+{
+ Q_D(const QRangeModel);
+ // if the new maximum value is smaller than
+ // minimum, update minimum too
+ setRange(qMin(d->minimum, max), max);
+}
+
+qreal QRangeModel::maximum() const
+{
+ Q_D(const QRangeModel);
+ return d->maximum;
+}
+
+/*!
+ \property QRangeModel::stepSize
+ \brief the value that is added to the \l value and \l position property
+
+ Example: If a user sets a range of [0,100] and stepSize
+ to 30, the valid values that are going to be seen externally would be: 0, 30, 60, 90, 100.
+*/
+
+void QRangeModel::setStepSize(qreal stepSize)
+{
+ Q_D(QRangeModel);
+
+ stepSize = qMax(qreal(0.0), stepSize);
+ if (qFuzzyCompare(stepSize, d->stepSize))
+ return;
+
+ const qreal oldValue = value();
+ const qreal oldPosition = position();
+ d->stepSize = stepSize;
+
+ emit stepSizeChanged(d->stepSize);
+ d->emitValueAndPositionIfChanged(oldValue, oldPosition);
+}
+
+qreal QRangeModel::stepSize() const
+{
+ Q_D(const QRangeModel);
+ return d->stepSize;
+}
+
+/*!
+ Returns a valid position, respecting the \l positionAtMinimum,
+ \l positionAtMaximum and the \l stepSize properties.
+ Such calculation is based on the parameter \a value (which is valid externally).
+*/
+
+qreal QRangeModel::positionForValue(qreal value) const
+{
+ Q_D(const QRangeModel);
+
+ const qreal unconstrainedPosition = d->equivalentPosition(value);
+ return d->publicPosition(unconstrainedPosition);
+}
+
+/*!
+ \property QRangeModel::position
+ \brief the current position of the model
+
+ Represents a valid external position, based on the \l positionAtMinimum,
+ \l positionAtMaximum and the \l stepSize properties.
+ The user can set it internally with a position, that is not within the current position range,
+ since it can become valid if the user changes the position range later.
+*/
+
+qreal QRangeModel::position() const
+{
+ Q_D(const QRangeModel);
+
+ // Return the internal position but observe boundaries and
+ // stepSize restrictions.
+ return d->publicPosition(d->pos);
+}
+
+void QRangeModel::setPosition(qreal newPosition)
+{
+ Q_D(QRangeModel);
+
+ if (qFuzzyCompare(newPosition, d->pos))
+ return;
+
+ const qreal oldPosition = position();
+ const qreal oldValue = value();
+
+ // Update position and calculate new value
+ d->pos = newPosition;
+ d->value = d->equivalentValue(d->pos);
+ d->emitValueAndPositionIfChanged(oldValue, oldPosition);
+}
+
+/*!
+ \property QRangeModel::positionAtMinimum
+ \brief the minimum value that \l position can assume
+
+ This property's default value is 0
+*/
+
+void QRangeModel::setPositionAtMinimum(qreal min)
+{
+ Q_D(QRangeModel);
+ setPositionRange(min, d->posatmax);
+}
+
+qreal QRangeModel::positionAtMinimum() const
+{
+ Q_D(const QRangeModel);
+ return d->posatmin;
+}
+
+/*!
+ \property QRangeModel::positionAtMaximum
+ \brief the maximum value that \l position can assume
+
+ This property's default value is 0
+*/
+
+void QRangeModel::setPositionAtMaximum(qreal max)
+{
+ Q_D(QRangeModel);
+ setPositionRange(d->posatmin, max);
+}
+
+qreal QRangeModel::positionAtMaximum() const
+{
+ Q_D(const QRangeModel);
+ return d->posatmax;
+}
+
+/*!
+ Returns a valid value, respecting the \l minimumValue,
+ \l maximumValue and the \l stepSize properties.
+ Such calculation is based on the parameter \a position (which is valid externally).
+*/
+
+qreal QRangeModel::valueForPosition(qreal position) const
+{
+ Q_D(const QRangeModel);
+
+ const qreal unconstrainedValue = d->equivalentValue(position);
+ return d->publicValue(unconstrainedValue);
+}
+
+/*!
+ \property QRangeModel::value
+ \brief the current value of the model
+
+ Represents a valid external value, based on the \l minimumValue,
+ \l maximumValue and the \l stepSize properties.
+ The user can set it internally with a value, that is not within the current range,
+ since it can become valid if the user changes the range later.
+*/
+
+qreal QRangeModel::value() const
+{
+ Q_D(const QRangeModel);
+
+ // Return internal value but observe boundaries and
+ // stepSize restrictions
+ return d->publicValue(d->value);
+}
+
+void QRangeModel::setValue(qreal newValue)
+{
+ Q_D(QRangeModel);
+
+ if (qFuzzyCompare(newValue, d->value))
+ return;
+
+ const qreal oldValue = value();
+ const qreal oldPosition = position();
+
+ // Update relative value and position
+ d->value = newValue;
+ d->pos = d->equivalentPosition(d->value);
+ d->emitValueAndPositionIfChanged(oldValue, oldPosition);
+}
+
+/*!
+ \property QRangeModel::inverted
+ \brief the model is inverted or not
+
+ The model can be represented with an inverted behavior, e.g. when \l value assumes
+ the maximum value (represented by \l maximumValue) the \l position will be at its
+ minimum (represented by \l positionAtMinimum).
+*/
+
+void QRangeModel::setInverted(bool inverted)
+{
+ Q_D(QRangeModel);
+ if (inverted == d->inverted)
+ return;
+
+ d->inverted = inverted;
+ emit invertedChanged(d->inverted);
+
+ // After updating the internal value, the position property can change.
+ setPosition(d->equivalentPosition(d->value));
+}
+
+bool QRangeModel::inverted() const
+{
+ Q_D(const QRangeModel);
+ return d->inverted;
+}
+
+/*!
+ Sets the \l value to \l minimumValue.
+*/
+
+void QRangeModel::toMinimum()
+{
+ Q_D(const QRangeModel);
+ setValue(d->minimum);
+}
+
+/*!
+ Sets the \l value to \l maximumValue.
+*/
+
+void QRangeModel::toMaximum()
+{
+ Q_D(const QRangeModel);
+ setValue(d->maximum);
+}
diff --git a/src/qtdesktop/qrangemodel.h b/src/qtdesktop/qrangemodel.h
new file mode 100644
index 00000000..675967ae
--- /dev/null
+++ b/src/qtdesktop/qrangemodel.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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 QRANGEMODEL_H
+#define QRANGEMODEL_H
+
+#include <QtCore/qobject.h>
+//#include <QtGui/qgraphicsitem.h>
+#include <QtWidgets/qabstractslider.h>
+#include <QtQml/qqml.h>
+
+class QRangeModelPrivate;
+
+class QRangeModel : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged USER true)
+ Q_PROPERTY(qreal minimumValue READ minimum WRITE setMinimum NOTIFY minimumChanged)
+ Q_PROPERTY(qreal maximumValue READ maximum WRITE setMaximum NOTIFY maximumChanged)
+ Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged)
+ Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(qreal positionAtMinimum READ positionAtMinimum WRITE setPositionAtMinimum NOTIFY positionAtMinimumChanged)
+ Q_PROPERTY(qreal positionAtMaximum READ positionAtMaximum WRITE setPositionAtMaximum NOTIFY positionAtMaximumChanged)
+ Q_PROPERTY(bool inverted READ inverted WRITE setInverted NOTIFY invertedChanged)
+
+public:
+ QRangeModel(QObject *parent = 0);
+ virtual ~QRangeModel();
+
+ void setRange(qreal min, qreal max);
+ void setPositionRange(qreal min, qreal max);
+
+ void setStepSize(qreal stepSize);
+ qreal stepSize() const;
+
+ void setMinimum(qreal min);
+ qreal minimum() const;
+
+ void setMaximum(qreal max);
+ qreal maximum() const;
+
+ void setPositionAtMinimum(qreal posAtMin);
+ qreal positionAtMinimum() const;
+
+ void setPositionAtMaximum(qreal posAtMax);
+ qreal positionAtMaximum() const;
+
+ void setInverted(bool inverted);
+ bool inverted() const;
+
+ qreal value() const;
+ qreal position() const;
+
+ Q_INVOKABLE qreal valueForPosition(qreal position) const;
+ Q_INVOKABLE qreal positionForValue(qreal value) const;
+
+public Q_SLOTS:
+ void toMinimum();
+ void toMaximum();
+ void setValue(qreal value);
+ void setPosition(qreal position);
+
+Q_SIGNALS:
+ void valueChanged(qreal value);
+ void positionChanged(qreal position);
+
+ void stepSizeChanged(qreal stepSize);
+
+ void invertedChanged(bool inverted);
+
+ void minimumChanged(qreal min);
+ void maximumChanged(qreal max);
+ void positionAtMinimumChanged(qreal min);
+ void positionAtMaximumChanged(qreal max);
+
+protected:
+ QRangeModel(QRangeModelPrivate &dd, QObject *parent);
+ QRangeModelPrivate* d_ptr;
+
+private:
+ Q_DISABLE_COPY(QRangeModel)
+ Q_DECLARE_PRIVATE(QRangeModel)
+
+};
+
+QML_DECLARE_TYPE(QRangeModel)
+
+#endif // QRANGEMODEL_H
diff --git a/src/qtdesktop/qrangemodel_p.h b/src/qtdesktop/qrangemodel_p.h
new file mode 100644
index 00000000..83b28949
--- /dev/null
+++ b/src/qtdesktop/qrangemodel_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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 QRANGEMODEL_P_H
+#define QRANGEMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt Components API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrangemodel.h"
+
+class QRangeModelPrivate
+{
+ Q_DECLARE_PUBLIC(QRangeModel)
+public:
+ QRangeModelPrivate(QRangeModel *qq);
+ virtual ~QRangeModelPrivate();
+
+ void init();
+
+ qreal posatmin, posatmax;
+ qreal minimum, maximum, stepSize, pos, value;
+
+ uint inverted : 1;
+
+ QRangeModel *q_ptr;
+
+ inline qreal effectivePosAtMin() const {
+ return inverted ? posatmax : posatmin;
+ }
+
+ inline qreal effectivePosAtMax() const {
+ return inverted ? posatmin : posatmax;
+ }
+
+ inline qreal equivalentPosition(qreal value) const {
+ // Return absolute position from absolute value
+ const qreal valueRange = maximum - minimum;
+ if (valueRange == 0)
+ return effectivePosAtMin();
+
+ const qreal scale = (effectivePosAtMax() - effectivePosAtMin()) / valueRange;
+ return (value - minimum) * scale + effectivePosAtMin();
+ }
+
+ inline qreal equivalentValue(qreal pos) const {
+ // Return absolute value from absolute position
+ const qreal posRange = effectivePosAtMax() - effectivePosAtMin();
+ if (posRange == 0)
+ return minimum;
+
+ const qreal scale = (maximum - minimum) / posRange;
+ return (pos - effectivePosAtMin()) * scale + minimum;
+ }
+
+ qreal publicPosition(qreal position) const;
+ qreal publicValue(qreal value) const;
+ void emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition);
+};
+
+#endif // QRANGEMODEL_P_H
diff --git a/src/qtdesktop/qstyleitem.cpp b/src/qtdesktop/qstyleitem.cpp
new file mode 100644
index 00000000..1acfb8b5
--- /dev/null
+++ b/src/qtdesktop/qstyleitem.cpp
@@ -0,0 +1,1072 @@
+/****************************************************************************
+**
+** 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 "qstyleitem.h"
+
+#include <QtGui/QPainter>
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QStyleOption>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QGroupBox>
+#include <QtWidgets/QToolBar>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QtWidgets>
+#include <QtCore/QStringBuilder>
+
+#ifdef Q_OS_MAC
+#include <Carbon/Carbon.h>
+
+static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect())
+{
+ return CGRectMake(convertRect.x() + rect.x(), convertRect.y() + rect.y(),
+ convertRect.width() - rect.width(), convertRect.height() - rect.height());
+}
+
+/*! \internal
+
+ Returns the CoreGraphics CGContextRef of the paint device. 0 is
+ returned if it can't be obtained. It is the caller's responsibility to
+ CGContextRelease the context when finished using it.
+
+ \warning This function is only available on Mac OS X.
+ \warning This function is duplicated in qmacstyle_mac.mm
+*/
+CGContextRef qt_mac_cg_context(const QPaintDevice *pdev)
+{
+
+ if (pdev->devType() == QInternal::Image) {
+ const QImage *i = static_cast<const QImage*>(pdev);
+ QImage *image = const_cast< QImage*>(i);
+ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
+ uint flags = kCGImageAlphaPremultipliedFirst;
+ flags |= kCGBitmapByteOrder32Host;
+ CGContextRef ret = 0;
+
+ ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(),
+ 8, image->bytesPerLine(), colorspace, flags);
+
+ CGContextTranslateCTM(ret, 0, image->height());
+ CGContextScaleCTM(ret, 1, -1);
+ return ret;
+ }
+ return 0;
+}
+
+#endif
+
+QStyleItem::QStyleItem(QQuickPaintedItem *parent)
+ : QQuickPaintedItem(parent),
+ m_styleoption(0),
+ m_itemType(Undefined),
+ m_sunken(false),
+ m_raised(false),
+ m_active(true),
+ m_selected(false),
+ m_focus(false),
+ m_hover(false),
+ m_on(false),
+ m_horizontal(true),
+ m_sharedWidget(false),
+ m_minimum(0),
+ m_maximum(100),
+ m_value(0),
+ m_step(0),
+ m_paintMargins(0),
+ m_contentWidth(0),
+ m_contentHeight(0)
+
+{
+ m_font = qApp->font();
+ setFlag(QQuickItem::ItemHasContents, true);
+ setSmooth(false);
+
+ connect(this, SIGNAL(enabledChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(infoChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(onChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(selectedChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(activeChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(textChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(activeChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(raisedChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(sunkenChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(hoverChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(maximumChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(minimumChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(valueChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(horizontalChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(activeControlChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(hasFocusChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(activeControlChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(elementTypeChanged()), this, SLOT(updateItem()));
+ connect(this, SIGNAL(textChanged()), this, SLOT(updateSizeHint()));
+ connect(this, SIGNAL(contentWidthChanged(int)), this, SLOT(updateSizeHint()));
+ connect(this, SIGNAL(contentHeightChanged(int)), this, SLOT(updateSizeHint()));
+}
+
+QStyleItem::~QStyleItem()
+{
+ delete m_styleoption;
+ m_styleoption = 0;
+}
+
+void QStyleItem::initStyleOption()
+{
+ QString type = elementType();
+ if (m_styleoption)
+ m_styleoption->state = 0;
+
+ switch (m_itemType) {
+ case Button: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionButton();
+
+ QStyleOptionButton *opt = qstyleoption_cast<QStyleOptionButton*>(m_styleoption);
+ opt->text = text();
+ opt->features = (activeControl() == "default") ?
+ QStyleOptionButton::DefaultButton :
+ QStyleOptionButton::None;
+ }
+ break;
+ case ItemRow: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionViewItem();
+
+ QStyleOptionViewItem *opt = qstyleoption_cast<QStyleOptionViewItem*>(m_styleoption);
+ opt->features = 0;
+ if (activeControl() == "alternate")
+ opt->features |= QStyleOptionViewItem::Alternate;
+ }
+ break;
+
+ case Splitter: {
+ if (!m_styleoption) {
+ m_styleoption = new QStyleOption;
+ }
+ }
+ break;
+
+ case Item: {
+ if (!m_styleoption) {
+ m_styleoption = new QStyleOptionViewItem();
+ }
+ QStyleOptionViewItem *opt = qstyleoption_cast<QStyleOptionViewItem*>(m_styleoption);
+ opt->features = QStyleOptionViewItem::HasDisplay;
+ opt->text = text();
+ opt->textElideMode = Qt::ElideRight;
+ QPalette pal = m_styleoption->palette;
+ pal.setBrush(QPalette::Base, Qt::NoBrush);
+ m_styleoption->palette = pal;
+ }
+ break;
+ case Header: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionHeader();
+
+ QStyleOptionHeader *opt = qstyleoption_cast<QStyleOptionHeader*>(m_styleoption);
+ opt->text = text();
+ opt->sortIndicator = activeControl() == "down" ?
+ QStyleOptionHeader::SortDown
+ : activeControl() == "up" ?
+ QStyleOptionHeader::SortUp : QStyleOptionHeader::None;
+ if (info() == QLatin1String("beginning"))
+ opt->position = QStyleOptionHeader::Beginning;
+ else if (info() == QLatin1String("end"))
+ opt->position = QStyleOptionHeader::End;
+ else if (info() == QLatin1String("only"))
+ opt->position = QStyleOptionHeader::OnlyOneSection;
+ else
+ opt->position = QStyleOptionHeader::Middle;
+ }
+ break;
+ case ToolButton: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionToolButton();
+
+ QStyleOptionToolButton *opt =
+ qstyleoption_cast<QStyleOptionToolButton*>(m_styleoption);
+ opt->subControls = QStyle::SC_ToolButton;
+ opt->state |= QStyle::State_AutoRaise;
+ opt->activeSubControls = QStyle::SC_ToolButton;
+ }
+ break;
+ case ToolBar: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionToolBar();
+ }
+ break;
+ case Tab: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionTab();
+
+ QStyleOptionTab *opt = qstyleoption_cast<QStyleOptionTab*>(m_styleoption);
+ opt->text = text();
+ opt->shape = info() == "South" ? QTabBar::RoundedSouth : QTabBar::RoundedNorth;
+ if (activeControl() == QLatin1String("beginning"))
+ opt->position = QStyleOptionTab::Beginning;
+ else if (activeControl() == QLatin1String("end"))
+ opt->position = QStyleOptionTab::End;
+ else if (activeControl() == QLatin1String("only"))
+ opt->position = QStyleOptionTab::OnlyOneTab;
+ else
+ opt->position = QStyleOptionTab::Middle;
+
+ } break;
+
+ case Menu: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionMenuItem();
+ }
+ break;
+ case Frame: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionFrame();
+
+ QStyleOptionFrame *opt = qstyleoption_cast<QStyleOptionFrame*>(m_styleoption);
+ opt->frameShape = QFrame::StyledPanel;
+ opt->lineWidth = 1;
+ opt->midLineWidth = 1;
+ }
+ break;
+ case TabFrame: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionTabWidgetFrame();
+ QStyleOptionTabWidgetFrame *opt = qstyleoption_cast<QStyleOptionTabWidgetFrame*>(m_styleoption);
+ opt->shape = (info() == "South") ? QTabBar::RoundedSouth : QTabBar::RoundedNorth;
+ if (minimum())
+ opt->selectedTabRect = QRect(value(), 0, minimum(), height());
+ opt->tabBarSize = QSize(minimum() , height());
+ // oxygen style needs this hack
+ opt->leftCornerWidgetSize = QSize(value(), 0);
+ }
+ break;
+ case MenuItem:
+ case ComboBoxItem:
+ {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionMenuItem();
+
+ QStyleOptionMenuItem *opt = qstyleoption_cast<QStyleOptionMenuItem*>(m_styleoption);
+ opt->checked = false;
+ opt->text = text();
+ }
+ break;
+ case CheckBox:
+ case RadioButton:
+ {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionButton();
+
+ QStyleOptionButton *opt = qstyleoption_cast<QStyleOptionButton*>(m_styleoption);
+ if (!on())
+ opt->state |= QStyle::State_Off;
+ opt->text = text();
+ }
+ break;
+ case Edit: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionFrame();
+
+ QStyleOptionFrame *opt = qstyleoption_cast<QStyleOptionFrame*>(m_styleoption);
+ opt->lineWidth = 1; // this must be non-zero
+ }
+ break;
+ case ComboBox :{
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionComboBox();
+ QStyleOptionComboBox *opt = qstyleoption_cast<QStyleOptionComboBox*>(m_styleoption);
+ opt->currentText = text();
+ }
+ break;
+ case SpinBox: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionSpinBox();
+
+ QStyleOptionSpinBox *opt = qstyleoption_cast<QStyleOptionSpinBox*>(m_styleoption);
+ opt->frame = true;
+ if (value() & 0x1)
+ opt->activeSubControls = QStyle::SC_SpinBoxUp;
+ else if (value() & (1<<1))
+ opt->activeSubControls = QStyle::SC_SpinBoxDown;
+ opt->subControls = QStyle::SC_All;
+ opt->stepEnabled = 0;
+ if (value() & (1<<2))
+ opt->stepEnabled |= QAbstractSpinBox::StepUpEnabled;
+ if (value() & (1<<3))
+ opt->stepEnabled |= QAbstractSpinBox::StepDownEnabled;
+ }
+ break;
+ case Slider:
+ case Dial:
+ {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionSlider();
+
+ QStyleOptionSlider *opt = qstyleoption_cast<QStyleOptionSlider*>(m_styleoption);
+ opt->minimum = minimum();
+ opt->maximum = maximum();
+ opt->sliderPosition = value();
+ opt->singleStep = step();
+
+ if (opt->singleStep) {
+ qreal numOfSteps = (opt->maximum - opt->minimum) / opt->singleStep;
+ // at least 5 pixels between tick marks
+ if (numOfSteps && (width() / numOfSteps < 5))
+ opt->tickInterval = qRound((5*numOfSteps / width()) + 0.5)*step();
+ else
+ opt->tickInterval = opt->singleStep;
+ } else // default Qt-components implementation
+ opt->tickInterval = opt->maximum != opt->minimum ? 1200 / (opt->maximum - opt->minimum) : 0;
+
+ opt->sliderValue = value();
+ opt->subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
+ opt->tickPosition = (activeControl() == "tick" ?
+ QSlider::TicksBelow : QSlider::NoTicks);
+ if (opt->tickPosition != QSlider::NoTicks)
+ opt->subControls |= QStyle::SC_SliderTickmarks;
+
+ opt->activeSubControls = QStyle::SC_None;
+ }
+ break;
+ case ProgressBar: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionProgressBar();
+
+ QStyleOptionProgressBar *opt = qstyleoption_cast<QStyleOptionProgressBar*>(m_styleoption);
+ opt->orientation = horizontal() ? Qt::Horizontal : Qt::Vertical;
+ opt->minimum = minimum();
+ opt->maximum = maximum();
+ opt->progress = value();
+ }
+ break;
+ case GroupBox: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionGroupBox();
+
+ QStyleOptionGroupBox *opt = qstyleoption_cast<QStyleOptionGroupBox*>(m_styleoption);
+ opt->text = text();
+ opt->lineWidth = 1;
+ opt->subControls = QStyle::SC_GroupBoxLabel;
+ opt->features = 0;
+ if (sunken()) { // Qt draws an ugly line here so I ignore it
+ opt->subControls |= QStyle::SC_GroupBoxFrame;
+ } else {
+ opt->features |= QStyleOptionFrame::Flat;
+ }
+ if (activeControl() == "checkbox")
+ opt->subControls |= QStyle::SC_GroupBoxCheckBox;
+
+ }
+ break;
+ case ScrollBar: {
+ if (!m_styleoption)
+ m_styleoption = new QStyleOptionSlider();
+
+ QStyleOptionSlider *opt = qstyleoption_cast<QStyleOptionSlider*>(m_styleoption);
+ opt->minimum = minimum();
+ opt->maximum = maximum();
+ opt->pageStep = qMax(0, int(horizontal() ? width() : height()));
+ opt->orientation = horizontal() ? Qt::Horizontal : Qt::Vertical;
+ opt->sliderPosition = value();
+ opt->sliderValue = value();
+ opt->activeSubControls = (activeControl() == QLatin1String("up"))
+ ? QStyle::SC_ScrollBarSubLine :
+ (activeControl() == QLatin1String("down")) ?
+ QStyle::SC_ScrollBarAddLine:
+ QStyle::SC_ScrollBarSlider;
+
+ opt->sliderValue = value();
+ opt->subControls = QStyle::SC_All;
+
+ }
+ case MenuBar:
+ if (!m_styleoption) {
+ QStyleOptionMenuItem *menuOpt = new QStyleOptionMenuItem();
+ menuOpt->menuItemType = QStyleOptionMenuItem::EmptyArea;
+ m_styleoption = menuOpt;
+ }
+
+ break;
+ case MenuBarItem:
+ if (!m_styleoption) {
+ QStyleOptionMenuItem *menuOpt = new QStyleOptionMenuItem();
+ menuOpt->text = text();
+ menuOpt->menuItemType = QStyleOptionMenuItem::Normal;
+ m_styleoption = menuOpt;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!m_styleoption)
+ m_styleoption = new QStyleOption();
+
+ m_styleoption->styleObject = this;
+ m_styleoption->rect = QRect(m_paintMargins, m_paintMargins, width() - 2* m_paintMargins, height() - 2 * m_paintMargins);
+
+ if (isEnabled())
+ m_styleoption->state |= QStyle::State_Enabled;
+ if (m_active)
+ m_styleoption->state |= QStyle::State_Active;
+ if (m_sunken)
+ m_styleoption->state |= QStyle::State_Sunken;
+ if (m_raised)
+ m_styleoption->state |= QStyle::State_Raised;
+ if (m_selected)
+ m_styleoption->state |= QStyle::State_Selected;
+ if (m_focus)
+ m_styleoption->state |= QStyle::State_HasFocus;
+ if (m_on)
+ m_styleoption->state |= QStyle::State_On;
+ if (m_hover)
+ m_styleoption->state |= QStyle::State_MouseOver;
+ if (m_horizontal)
+ m_styleoption->state |= QStyle::State_Horizontal;
+
+ if (m_hint.indexOf("mini") != -1) {
+ m_styleoption->state |= QStyle::State_Mini;
+ } else if (m_hint.indexOf("small") != -1) {
+ m_styleoption->state |= QStyle::State_Small;
+ }
+
+}
+
+/*
+ * Property style
+ *
+ * Returns a simplified style name.
+ *
+ * QMacStyle = "mac"
+ * QWindowsXPStyle = "windowsxp"
+ * QFusionStyle = "fusion"
+ */
+
+QString QStyleItem::style() const
+{
+ QString style = qApp->style()->metaObject()->className();
+ style = style.toLower();
+ if (style.startsWith(QLatin1Char('q')))
+ style = style.right(style.length() - 1);
+ if (style.endsWith("style"))
+ style = style.left(style.length() - 5);
+ return style.toLower();
+}
+
+QString QStyleItem::hitTest(int px, int py)
+{
+ QStyle::SubControl subcontrol = QStyle::SC_All;
+ switch (m_itemType) {
+ case SpinBox :{
+ subcontrol = qApp->style()->hitTestComplexControl(QStyle::CC_SpinBox,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ QPoint(px,py), 0);
+ if (subcontrol == QStyle::SC_SpinBoxUp)
+ return "up";
+ else if (subcontrol == QStyle::SC_SpinBoxDown)
+ return "down";
+
+ }
+ break;
+
+ case Slider: {
+ subcontrol = qApp->style()->hitTestComplexControl(QStyle::CC_Slider,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ QPoint(px,py), 0);
+ if (subcontrol == QStyle::SC_SliderHandle)
+ return "handle";
+
+ }
+ break;
+ case ScrollBar: {
+ subcontrol = qApp->style()->hitTestComplexControl(QStyle::CC_ScrollBar,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ QPoint(px,py), 0);
+ if (subcontrol == QStyle::SC_ScrollBarSlider)
+ return "handle";
+
+ if (subcontrol == QStyle::SC_ScrollBarSubLine)
+ return "up";
+ else if (subcontrol == QStyle::SC_ScrollBarSubPage)
+ return "upPage";
+
+ if (subcontrol == QStyle::SC_ScrollBarAddLine)
+ return "down";
+ else if (subcontrol == QStyle::SC_ScrollBarAddPage)
+ return "downPage";
+ }
+ break;
+ default:
+ break;
+ }
+ return "none";
+}
+
+QSize QStyleItem::sizeFromContents(int width, int height)
+{
+ initStyleOption();
+
+ QSize size;
+ switch (m_itemType) {
+ case RadioButton:
+ size = qApp->style()->sizeFromContents(QStyle::CT_RadioButton, m_styleoption, QSize(width,height));
+ break;
+ case CheckBox:
+ size = qApp->style()->sizeFromContents(QStyle::CT_CheckBox, m_styleoption, QSize(width,height));
+ break;
+ case ToolBar:
+ size = QSize(200, 40);
+ break;
+ case ToolButton: {
+ QStyleOptionToolButton *btn = qstyleoption_cast<QStyleOptionToolButton*>(m_styleoption);
+ int newWidth = qMax(width, btn->fontMetrics.width(btn->text));
+ int newHeight = qMax(height, btn->fontMetrics.height());
+ size = qApp->style()->sizeFromContents(QStyle::CT_ToolButton, m_styleoption, QSize(newWidth, newHeight)); }
+ break;
+ case Button: {
+ QStyleOptionButton *btn = qstyleoption_cast<QStyleOptionButton*>(m_styleoption);
+ int newWidth = qMax(width, btn->fontMetrics.width(btn->text));
+ int newHeight = qMax(height, btn->fontMetrics.height());
+ size = qApp->style()->sizeFromContents(QStyle::CT_PushButton, m_styleoption, QSize(newWidth, newHeight)); }
+ break;
+ case ComboBox: {
+ QStyleOptionComboBox *btn = qstyleoption_cast<QStyleOptionComboBox*>(m_styleoption);
+ int newWidth = qMax(width, btn->fontMetrics.width(btn->currentText));
+ int newHeight = qMax(height, btn->fontMetrics.height());
+ size = qApp->style()->sizeFromContents(QStyle::CT_ComboBox, m_styleoption, QSize(newWidth, newHeight)); }
+ break;
+ case SpinBox: {
+ QStyleOptionSpinBox *box = qstyleoption_cast<QStyleOptionSpinBox*>(m_styleoption);
+ int newWidth = qMax(width, box->fontMetrics.width(QLatin1String("0.0")));
+ int newHeight = qMax(height, box->fontMetrics.height());
+ size = qApp->style()->sizeFromContents(QStyle::CT_SpinBox, m_styleoption, QSize(newWidth, newHeight)); }
+ break;
+ case Tab:
+ size = qApp->style()->sizeFromContents(QStyle::CT_TabBarTab, m_styleoption, QSize(width,height));
+ break;
+ case Slider:
+ size = qApp->style()->sizeFromContents(QStyle::CT_Slider, m_styleoption, QSize(width,height));
+ break;
+ case ProgressBar:
+ size = qApp->style()->sizeFromContents(QStyle::CT_ProgressBar, m_styleoption, QSize(width,height));
+ break;
+ case Edit:
+ size = qApp->style()->sizeFromContents(QStyle::CT_LineEdit, m_styleoption, QSize(width,height));
+ if (hint().indexOf("rounded") != -1)
+ size += QSize(0, 3);
+ break;
+ case GroupBox:
+ size = qApp->style()->sizeFromContents(QStyle::CT_GroupBox, m_styleoption, QSize(width,height));
+ break;
+ case Header:
+ size = qApp->style()->sizeFromContents(QStyle::CT_HeaderSection, m_styleoption, QSize(width,height));
+#ifdef Q_OS_MAC
+ if (style() =="mac")
+ size.setHeight(15);
+#endif
+ break;
+ case ItemRow:
+ case Item: //fall through
+ size = qApp->style()->sizeFromContents(QStyle::CT_ItemViewItem, m_styleoption, QSize(width,height));
+ break;
+ case MenuBarItem: //fall through
+ size = qApp->style()->sizeFromContents(QStyle::CT_MenuBarItem, m_styleoption, QSize(width,height));
+ break;
+ case MenuBar: //fall through
+ size = qApp->style()->sizeFromContents(QStyle::CT_MenuBar, m_styleoption, QSize(width,height));
+ break;
+ default:
+ break;
+ }
+ return size;
+}
+
+void QStyleItem::updateSizeHint()
+{
+ QSize implicitSize = sizeFromContents(m_contentWidth, m_contentHeight);
+ setImplicitSize(implicitSize.width(), implicitSize.height());
+}
+
+int QStyleItem::pixelMetric(const QString &metric)
+{
+
+ if (metric == "scrollbarExtent")
+ return qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0) + 1;
+ else if (metric == "defaultframewidth")
+ return qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0);
+ else if (metric == "taboverlap")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0 );
+ else if (metric == "tabbaseoverlap")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, 0 );
+ else if (metric == "tabhspace")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarTabHSpace, 0 );
+ else if (metric == "indicatorwidth")
+ return qApp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth, 0 );
+ else if (metric == "tabvspace")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarTabVSpace, 0 );
+ else if (metric == "tabbaseheight")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarBaseHeight, 0 );
+ else if (metric == "tabvshift")
+ return qApp->style()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, 0 );
+ else if (metric == "menuhmargin")
+ return qApp->style()->pixelMetric(QStyle::PM_MenuHMargin, 0 );
+ else if (metric == "menuvmargin")
+ return qApp->style()->pixelMetric(QStyle::PM_MenuVMargin, 0 );
+ else if (metric == "menupanelwidth")
+ return qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0 );
+ else if (metric == "splitterwidth")
+ return qApp->style()->pixelMetric(QStyle::PM_SplitterWidth, 0 );
+ else if (metric == "scrollbarspacing")
+ return abs(qApp->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, 0 ));
+ return 0;
+}
+
+QVariant QStyleItem::styleHint(const QString &metric)
+{
+ initStyleOption();
+ if (metric == "comboboxpopup") {
+ return qApp->style()->styleHint(QStyle::SH_ComboBox_Popup, m_styleoption);
+ } else if (metric == "highlightedTextColor") {
+ return qApp->palette().highlightedText().color().name();
+ } else if (metric == "textColor") {
+ return qApp->palette().text().color().name();
+ } else if (metric == "focuswidget") {
+ return qApp->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget);
+ } else if (metric == "tabbaralignment") {
+ int result = qApp->style()->styleHint(QStyle::SH_TabBar_Alignment);
+ if (result == Qt::AlignCenter)
+ return "center";
+ return "left";
+ } else if (metric == "framearoundcontents") {
+ return qApp->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
+ } else if (metric == "scrollToClickPosition")
+ return qApp->style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition);
+ return 0;
+}
+
+void QStyleItem::setHint(const QStringList &str)
+{
+ if (m_hint != str) {
+ m_hint = str;
+ initStyleOption();
+ updateSizeHint();
+ if (m_styleoption->state & QStyle::State_Mini) {
+ m_font.setPointSize(9.);
+ emit fontChanged();
+ } else if (m_styleoption->state & QStyle::State_Small) {
+ m_font.setPointSize(11.);
+ emit fontChanged();
+ }
+ }
+}
+
+
+void QStyleItem::setElementType(const QString &str)
+{
+ if (m_type == str)
+ return;
+
+ m_type = str;
+
+ emit elementTypeChanged();
+ if (m_styleoption) {
+ delete m_styleoption;
+ m_styleoption = 0;
+ }
+
+ // Only enable visible if the widget can animate
+ if (str == "menu" || str == "menuitem") {
+ m_itemType = (str == "menu") ? Menu : MenuItem;
+ } else if (str == "item" || str == "itemrow" || str == "header") {
+#ifdef Q_OS_MAC
+ m_font.setPointSize(11.0);
+ emit fontChanged();
+#endif
+ if (str == "header") {
+ m_itemType = Header;
+ } else {
+ m_itemType = (str == "item") ? Item : ItemRow;
+ }
+ } else if (str == "groupbox") {
+ m_itemType = GroupBox;
+ } else if (str == "tab") {
+ m_itemType = Tab;
+ } else if (str == "tabframe") {
+ m_itemType = TabFrame;
+ } else if (str == "comboboxitem") {
+ // Gtk uses qobject cast, hence we need to separate this from menuitem
+ // On mac, we temporarily use the menu item because it has more accurate
+ // palette.
+ m_itemType = ComboBoxItem;
+ } else if (str == "toolbar") {
+ m_itemType = ToolBar;
+ } else if (str == "toolbutton") {
+ m_itemType = ToolButton;
+ } else if (str == "slider") {
+ m_itemType = Slider;
+ } else if (str == "frame") {
+ m_itemType = Frame;
+ } else if (str == "combobox") {
+ m_itemType = ComboBox;
+ } else if (str == "splitter") {
+ m_itemType = Splitter;
+ } else if (str == "progressbar") {
+ m_itemType = ProgressBar;
+ } else if (str == "button") {
+ m_itemType = Button;
+ } else if (str == "checkbox") {
+ m_itemType = CheckBox;
+ } else if (str == "radiobutton") {
+ m_itemType = RadioButton;
+ } else if (str == "edit") {
+ m_itemType = Edit;
+ } else if (str == "spinbox") {
+ m_itemType = SpinBox;
+ } else if (str == "scrollbar") {
+ m_itemType = ScrollBar;
+ } else if (str == "widget") {
+ m_itemType = Widget;
+ } else if (str == "focusframe") {
+ m_itemType = FocusFrame;
+ } else if (str == "dial") {
+ m_itemType = Dial;
+ } else if (str == "statusbar") {
+ m_itemType = StatusBar;
+ } else if (str == "machelpbutton") {
+ m_itemType = MacHelpButton;
+ } else if (str == "scrollareacorner") {
+ m_itemType = ScrollAreaCorner;
+ } else if (str == "menubar") {
+ m_itemType = MenuBar;
+ } else if (str == "menubaritem") {
+ m_itemType = MenuBarItem;
+ } else {
+ m_itemType = Undefined;
+ }
+ updateSizeHint();
+}
+
+QRectF QStyleItem::subControlRect(const QString &subcontrolString)
+{
+ QStyle::SubControl subcontrol = QStyle::SC_None;
+ initStyleOption();
+ switch (m_itemType) {
+ case SpinBox:
+ {
+ QStyle::ComplexControl control = QStyle::CC_SpinBox;
+ if (subcontrolString == QLatin1String("down"))
+ subcontrol = QStyle::SC_SpinBoxDown;
+ else if (subcontrolString == QLatin1String("up"))
+ subcontrol = QStyle::SC_SpinBoxUp;
+ else if (subcontrolString == QLatin1String("edit")){
+ subcontrol = QStyle::SC_SpinBoxEditField;
+ }
+ return qApp->style()->subControlRect(control,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ subcontrol);
+
+ }
+ break;
+ case Slider:
+ {
+ QStyle::ComplexControl control = QStyle::CC_Slider;
+ if (subcontrolString == QLatin1String("handle"))
+ subcontrol = QStyle::SC_SliderHandle;
+ else if (subcontrolString == QLatin1String("groove"))
+ subcontrol = QStyle::SC_SliderGroove;
+ return qApp->style()->subControlRect(control,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ subcontrol);
+
+ }
+ break;
+ case ScrollBar:
+ {
+ QStyle::ComplexControl control = QStyle::CC_ScrollBar;
+ if (subcontrolString == QLatin1String("slider"))
+ subcontrol = QStyle::SC_ScrollBarSlider;
+ if (subcontrolString == QLatin1String("groove"))
+ subcontrol = QStyle::SC_ScrollBarGroove;
+ else if (subcontrolString == QLatin1String("handle"))
+ subcontrol = QStyle::SC_ScrollBarSlider;
+ else if (subcontrolString == QLatin1String("add"))
+ subcontrol = QStyle::SC_ScrollBarAddPage;
+ else if (subcontrolString == QLatin1String("sub"))
+ subcontrol = QStyle::SC_ScrollBarSubPage;
+ return qApp->style()->subControlRect(control,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ subcontrol);
+ }
+ break;
+ default:
+ break;
+ }
+ return QRectF();
+}
+
+void QStyleItem::paint(QPainter *painter)
+{
+ if (width() < 1 || height() <1)
+ return;
+
+ initStyleOption();
+
+ switch (m_itemType) {
+ case Button:
+ qApp->style()->drawControl(QStyle::CE_PushButton, m_styleoption, painter);
+ break;
+ case ItemRow :{
+ QPixmap pixmap;
+ // Only draw through style once
+ const QString pmKey = QLatin1Literal("itemrow") % QString::number(m_styleoption->state,16) % activeControl();
+ if (!QPixmapCache::find(pmKey, pixmap) || pixmap.width() < width() || height() != pixmap.height()) {
+ int newSize = width();
+ pixmap = QPixmap(newSize, height());
+ pixmap.fill(Qt::transparent);
+ QPainter pixpainter(&pixmap);
+ qApp->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, m_styleoption, &pixpainter);
+ if (!qApp->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected) && selected())
+ pixpainter.fillRect(m_styleoption->rect, m_styleoption->palette.highlight());
+ QPixmapCache::insert(pmKey, pixmap);
+ }
+ painter->drawPixmap(0, 0, pixmap);
+ }
+ break;
+ case Item:
+ qApp->style()->drawControl(QStyle::CE_ItemViewItem, m_styleoption, painter);
+ break;
+ case Header:
+ qApp->style()->drawControl(QStyle::CE_Header, m_styleoption, painter);
+ break;
+ case ToolButton:
+
+#ifdef Q_OS_MAC
+ if (style() == "mac" && hint().indexOf("segmented") != -1) {
+ const QPaintDevice *target = painter->device();
+ HIThemeSegmentDrawInfo sgi;
+ sgi.version = 0;
+ sgi.state = isEnabled() ? kThemeStateActive : kThemeStateDisabled;
+ if (sunken()) sgi.state |= kThemeStatePressed;
+ sgi.size = kHIThemeSegmentSizeNormal;
+ sgi.kind = kHIThemeSegmentKindTextured;
+ sgi.value = on() && !sunken() ? kThemeButtonOn : kThemeButtonOff;
+
+ sgi.adornment |= kHIThemeSegmentAdornmentLeadingSeparator;
+ if (sunken()) {
+ sgi.adornment |= kHIThemeSegmentAdornmentTrailingSeparator;
+ }
+ SInt32 button_height;
+ GetThemeMetric(kThemeMetricButtonRoundedHeight, &button_height);
+ sgi.position = info() == "leftmost" ? kHIThemeSegmentPositionFirst:
+ info() == "rightmost" ? kHIThemeSegmentPositionLast :
+ info() == "h_middle" ? kHIThemeSegmentPositionMiddle :
+ kHIThemeSegmentPositionOnly;
+ QRect centered = m_styleoption->rect;
+ centered.setHeight(button_height);
+ centered.moveCenter(m_styleoption->rect.center());
+ HIRect hirect = qt_hirectForQRect(centered.translated(0, -1), QRect(0, 0, 0, 0));
+ HIThemeDrawSegment(&hirect, &sgi, qt_mac_cg_context(target), kHIThemeOrientationNormal);
+ } else
+#endif
+ qApp->style()->drawComplexControl(QStyle::CC_ToolButton, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter);
+ break;
+ case Tab:
+ qApp->style()->drawControl(QStyle::CE_TabBarTab, m_styleoption, painter);
+ break;
+ case Frame:
+ qApp->style()->drawControl(QStyle::CE_ShapedFrame, m_styleoption, painter);
+ break;
+ case FocusFrame:
+ if (style() == "mac" && hint().indexOf("rounded") != -1)
+ break; // embedded in the line itself
+ else
+ qApp->style()->drawControl(QStyle::CE_FocusFrame, m_styleoption, painter);
+ break;
+ case TabFrame:
+ qApp->style()->drawPrimitive(QStyle::PE_FrameTabWidget, m_styleoption, painter);
+ break;
+ case MenuBar:
+ qApp->style()->drawControl(QStyle::CE_MenuBarEmptyArea, m_styleoption, painter);
+ break;
+ case MenuBarItem:
+ qApp->style()->drawControl(QStyle::CE_MenuBarItem, m_styleoption, painter);
+ break;
+ case MenuItem:
+ case ComboBoxItem: // fall through
+ qApp->style()->drawControl(QStyle::CE_MenuItem, m_styleoption, painter);
+ break;
+ case CheckBox:
+ qApp->style()->drawControl(QStyle::CE_CheckBox, m_styleoption, painter);
+ break;
+ case RadioButton:
+ qApp->style()->drawControl(QStyle::CE_RadioButton, m_styleoption, painter);
+ break;
+ case Edit: {
+#ifdef Q_OS_MAC
+ if (style() == "mac" && hint().indexOf("rounded") != -1) {
+ const QPaintDevice *target = painter->device();
+ HIThemeFrameDrawInfo fdi;
+ fdi.version = 0;
+ fdi.state = kThemeStateActive;
+ SInt32 frame_size;
+ GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
+ fdi.kind = kHIThemeFrameTextFieldRound;
+ if ((m_styleoption->state & QStyle::State_ReadOnly) || !(m_styleoption->state & QStyle::State_Enabled))
+ fdi.state = kThemeStateInactive;
+ fdi.isFocused = hasFocus();
+ HIRect hirect = qt_hirectForQRect(m_styleoption->rect,
+ QRect(frame_size, frame_size,
+ frame_size * 2, frame_size * 2));
+ HIThemeDrawFrame(&hirect, &fdi, qt_mac_cg_context(target), kHIThemeOrientationNormal);
+ } else
+#endif
+ qApp->style()->drawPrimitive(QStyle::PE_PanelLineEdit, m_styleoption, painter);
+ }
+ break;
+ case MacHelpButton:
+#ifdef Q_OS_MAC
+ {
+ const QPaintDevice *target = painter->device();
+ HIThemeButtonDrawInfo fdi;
+ fdi.kind = kThemeRoundButtonHelp;
+ fdi.version = 0;
+ fdi.adornment = 0;
+ fdi.state = sunken() ? kThemeStatePressed : kThemeStateActive;
+ HIRect hirect = qt_hirectForQRect(m_styleoption->rect,QRect(0, 0, 0, 0));
+ HIThemeDrawButton(&hirect, &fdi, qt_mac_cg_context(target), kHIThemeOrientationNormal, NULL);
+ }
+#endif
+ break;
+ case Widget:
+ qApp->style()->drawPrimitive(QStyle::PE_Widget, m_styleoption, painter);
+ break;
+ case ScrollAreaCorner:
+ qApp->style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, m_styleoption, painter);
+ break;
+ case Splitter:
+ if (m_styleoption->rect.width() == 1)
+ painter->fillRect(0, 0, width(), height(), m_styleoption->palette.dark().color());
+ else
+ qApp->style()->drawControl(QStyle::CE_Splitter, m_styleoption, painter);
+ break;
+ case ComboBox:
+ {
+ qApp->style()->drawComplexControl(QStyle::CC_ComboBox,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ painter);
+ // This is needed on mac as it will use the painter color and ignore the palette
+ QPen pen = painter->pen();
+ painter->setPen(m_styleoption->palette.text().color());
+ qApp->style()->drawControl(QStyle::CE_ComboBoxLabel, m_styleoption, painter);
+ painter->setPen(pen);
+ } break;
+ case SpinBox:
+ qApp->style()->drawComplexControl(QStyle::CC_SpinBox,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ painter);
+ break;
+ case Slider:
+ qApp->style()->drawComplexControl(QStyle::CC_Slider,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ painter);
+ break;
+ case Dial:
+ qApp->style()->drawComplexControl(QStyle::CC_Dial,
+ qstyleoption_cast<QStyleOptionComplex*>(m_styleoption),
+ painter);
+ break;
+ case ProgressBar:
+ qApp->style()->drawControl(QStyle::CE_ProgressBar, m_styleoption, painter);
+ break;
+ case ToolBar:
+ qApp->style()->drawControl(QStyle::CE_ToolBar, m_styleoption, painter);
+ break;
+ case StatusBar:
+ if (style() == "mac") {
+ m_styleoption->rect.adjust(0, 1, 0, 0);
+ qApp->style()->drawControl(QStyle::CE_ToolBar, m_styleoption, painter);
+ m_styleoption->rect.adjust(0, -1, 0, 0);
+ painter->setPen(m_styleoption->palette.dark().color().darker(120));
+ painter->drawLine(m_styleoption->rect.topLeft(), m_styleoption->rect.topRight());
+ } else {
+ qApp->style()->drawPrimitive(QStyle::PE_PanelToolBar, m_styleoption, painter);
+ }
+ break;
+ case GroupBox:
+ qApp->style()->drawComplexControl(QStyle::CC_GroupBox, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter);
+ break;
+ case ScrollBar:
+ qApp->style()->drawComplexControl(QStyle::CC_ScrollBar, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter);
+ break;
+ case Menu: {
+ QStyleHintReturnMask val;
+ qApp->style()->styleHint(QStyle::SH_Menu_Mask, m_styleoption, 0, &val);
+ painter->save();
+ painter->setClipRegion(val.region);
+ painter->fillRect(m_styleoption->rect, m_styleoption->palette.window());
+ painter->restore();
+ qApp->style()->drawPrimitive(QStyle::PE_PanelMenu, m_styleoption, painter);
+
+ QStyleOptionFrame frame;
+ frame.lineWidth = qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth);
+ frame.midLineWidth = 0;
+ frame.rect = m_styleoption->rect;
+ qApp->style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, painter);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+int QStyleItem::textWidth(const QString &text)
+{
+ return QFontMetrics(m_font).boundingRect(text).width();
+}
+
+QString QStyleItem::elidedText(const QString &text, int elideMode, int width)
+{
+ return qApp->fontMetrics().elidedText(text, Qt::TextElideMode(elideMode), width);
+}
+
+bool QStyleItem::hasThemeIcon(const QString &icon) const
+{
+ return QIcon::hasThemeIcon(icon);
+}
diff --git a/src/qtdesktop/qstyleitem.h b/src/qtdesktop/qstyleitem.h
new file mode 100644
index 00000000..6b274060
--- /dev/null
+++ b/src/qtdesktop/qstyleitem.h
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** 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 STYLEWRAPPER_H
+#define STYLEWRAPPER_H
+
+#include <QtQuick/qquickpainteditem.h>
+#include <QtWidgets/QStyle>
+#include <QEvent>
+
+class QStyleItem: public QQuickPaintedItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY( bool sunken READ sunken WRITE setSunken NOTIFY sunkenChanged)
+ Q_PROPERTY( bool raised READ raised WRITE setRaised NOTIFY raisedChanged)
+ Q_PROPERTY( bool active READ active WRITE setActive NOTIFY activeChanged)
+ Q_PROPERTY( bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
+ Q_PROPERTY( bool hasFocus READ hasFocus WRITE sethasFocus NOTIFY hasFocusChanged)
+ Q_PROPERTY( bool on READ on WRITE setOn NOTIFY onChanged)
+ Q_PROPERTY( bool hover READ hover WRITE setHover NOTIFY hoverChanged)
+ Q_PROPERTY( bool horizontal READ horizontal WRITE setHorizontal NOTIFY horizontalChanged)
+
+ Q_PROPERTY( QString elementType READ elementType WRITE setElementType NOTIFY elementTypeChanged)
+ Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY( QString activeControl READ activeControl WRITE setActiveControl NOTIFY activeControlChanged)
+ Q_PROPERTY( QString info READ info WRITE setInfo NOTIFY infoChanged)
+ Q_PROPERTY( QString style READ style NOTIFY styleChanged)
+ Q_PROPERTY( QStringList hint READ hint WRITE setHint NOTIFY hintChanged)
+ Q_PROPERTY( QFont font READ font NOTIFY fontChanged)
+
+ // For range controls
+ Q_PROPERTY( int minimum READ minimum WRITE setMinimum NOTIFY minimumChanged)
+ Q_PROPERTY( int maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
+ Q_PROPERTY( int value READ value WRITE setValue NOTIFY valueChanged)
+ Q_PROPERTY( int step READ step WRITE setStep NOTIFY stepChanged)
+ Q_PROPERTY( int paintMargins READ paintMargins WRITE setPaintMargins NOTIFY paintMarginsChanged)
+
+ Q_PROPERTY( int contentWidth READ contentWidth() WRITE setContentWidth NOTIFY contentWidthChanged)
+ Q_PROPERTY( int contentHeight READ contentHeight() WRITE setContentHeight NOTIFY contentHeightChanged)
+
+public:
+ QStyleItem(QQuickPaintedItem *parent = 0);
+ ~QStyleItem();
+
+ enum Type {
+ Undefined,
+ Button,
+ RadioButton,
+ CheckBox,
+ ComboBox,
+ ComboBoxItem,
+ Dial,
+ ToolBar,
+ ToolButton,
+ Tab,
+ TabFrame,
+ Frame,
+ FocusFrame,
+ SpinBox,
+ Slider,
+ ScrollBar,
+ ProgressBar,
+ Edit,
+ GroupBox,
+ Header,
+ Item,
+ ItemRow,
+ Splitter,
+ Menu,
+ MenuItem,
+ Widget,
+ StatusBar,
+ ScrollAreaCorner,
+ MacHelpButton,
+ MenuBar,
+ MenuBarItem
+ };
+
+ void paint(QPainter *);
+
+ bool sunken() const { return m_sunken; }
+ bool raised() const { return m_raised; }
+ bool active() const { return m_active; }
+ bool selected() const { return m_selected; }
+ bool hasFocus() const { return m_focus; }
+ bool on() const { return m_on; }
+ bool hover() const { return m_hover; }
+ bool horizontal() const { return m_horizontal; }
+
+ int minimum() const { return m_minimum; }
+ int maximum() const { return m_maximum; }
+ int step() const { return m_step; }
+ int value() const { return m_value; }
+ int paintMargins() const { return m_paintMargins; }
+
+ QString elementType() const { return m_type; }
+ QString text() const { return m_text; }
+ QString activeControl() const { return m_activeControl; }
+ QString info() const { return m_info; }
+ QStringList hint() const { return m_hint; }
+ QFont font() const { return m_font;}
+ QString style() const;
+
+ void setSunken(bool sunken) { if (m_sunken != sunken) {m_sunken = sunken; emit sunkenChanged();}}
+ void setRaised(bool raised) { if (m_raised!= raised) {m_raised = raised; emit raisedChanged();}}
+ void setActive(bool active) { if (m_active!= active) {m_active = active; emit activeChanged();}}
+ void setSelected(bool selected) { if (m_selected!= selected) {m_selected = selected; emit selectedChanged();}}
+ void sethasFocus(bool focus) { if (m_focus != focus) {m_focus = focus; emit hasFocusChanged();}}
+ void setOn(bool on) { if (m_on != on) {m_on = on ; emit onChanged();}}
+ void setHover(bool hover) { if (m_hover != hover) {m_hover = hover ; emit hoverChanged();}}
+ void setHorizontal(bool horizontal) { if (m_horizontal != horizontal) {m_horizontal = horizontal; emit horizontalChanged();}}
+ void setMinimum(int minimum) { if (m_minimum!= minimum) {m_minimum = minimum; emit minimumChanged();}}
+ void setMaximum(int maximum) { if (m_maximum != maximum) {m_maximum = maximum; emit maximumChanged();}}
+ void setValue(int value) { if (m_value!= value) {m_value = value; emit valueChanged();}}
+ void setStep(int step) { if (m_step != step) { m_step = step; emit stepChanged(); }}
+ void setPaintMargins(int value) { if (m_paintMargins!= value) {m_paintMargins = value;} }
+ void setElementType(const QString &str);
+ void setText(const QString &str) { if (m_text != str) {m_text = str; emit textChanged();}}
+ void setActiveControl(const QString &str) { if (m_activeControl != str) {m_activeControl = str; emit activeControlChanged();}}
+ void setInfo(const QString &str) { if (m_info != str) {m_info = str; emit infoChanged();}}
+ void setHint(const QStringList &str);
+
+ int contentWidth() const { return m_contentWidth; }
+ int contentHeight() const { return m_contentHeight; }
+
+ virtual void initStyleOption ();
+
+public Q_SLOTS:
+ int pixelMetric(const QString&);
+ QVariant styleHint(const QString&);
+ void updateSizeHint();
+ void updateItem(){initStyleOption(); update();}
+ QString hitTest(int x, int y);
+ QRectF subControlRect(const QString &subcontrolString);
+ QString elidedText(const QString &text, int elideMode, int width);
+ int textWidth(const QString &);
+ bool hasThemeIcon(const QString &) const;
+
+ void setContentWidth(int arg)
+ {
+ if (m_contentWidth != arg) {
+ m_contentWidth = arg;
+ emit contentWidthChanged(arg);
+ }
+ }
+
+ void setContentHeight(int arg)
+ {
+ if (m_contentHeight != arg) {
+ m_contentHeight = arg;
+ emit contentHeightChanged(arg);
+ }
+ }
+
+Q_SIGNALS:
+ void elementTypeChanged();
+ void textChanged();
+ void sunkenChanged();
+ void raisedChanged();
+ void activeChanged();
+ void selectedChanged();
+ void hasFocusChanged();
+ void onChanged();
+ void hoverChanged();
+ void horizontalChanged();
+ void minimumChanged();
+ void maximumChanged();
+ void stepChanged();
+ void valueChanged();
+ void activeControlChanged();
+ void infoChanged();
+ void styleChanged();
+ void paintMarginsChanged();
+ void hintChanged();
+ void fontChanged();
+
+ void contentWidthChanged(int arg);
+ void contentHeightChanged(int arg);
+
+private:
+ QSize sizeFromContents(int width, int height);
+
+protected:
+ QWidget *m_dummywidget;
+ QStyleOption *m_styleoption;
+ Type m_itemType;
+
+ QString m_type;
+ QString m_text;
+ QString m_activeControl;
+ QString m_info;
+ QStringList m_hint;
+ QFont m_font;
+
+ bool m_sunken;
+ bool m_raised;
+ bool m_active;
+ bool m_selected;
+ bool m_focus;
+ bool m_hover;
+ bool m_on;
+ bool m_horizontal;
+ bool m_sharedWidget;
+
+ int m_minimum;
+ int m_maximum;
+ int m_value;
+ int m_step;
+ int m_paintMargins;
+
+ int m_contentWidth;
+ int m_contentHeight;
+
+};
+
+#endif //STYLEWRAPPER_H
diff --git a/src/qtdesktop/qstyleplugin.cpp b/src/qtdesktop/qstyleplugin.cpp
new file mode 100644
index 00000000..500d4ee6
--- /dev/null
+++ b/src/qtdesktop/qstyleplugin.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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 "qstyleplugin.h"
+#include "qstyleitem.h"
+#include "qrangemodel.h"
+#include "qtmenu.h"
+#include "qtmenubar.h"
+#include "qdesktopitem.h"
+#include "qwheelarea.h"
+#include "qtsplitterbase.h"
+#include "qquicklinearlayout.h"
+#include "qquickcomponentsprivate.h"
+#include "qfiledialogitem.h"
+#include <qqmlextensionplugin.h>
+
+#include <qqmlengine.h>
+#include <qquickimageprovider.h>
+#include <QtWidgets/QApplication>
+#include <QtQuick/QQuickWindow>
+#include <QImage>
+
+// 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);
+ }
+};
+
+QObject *registerPrivateModule(QQmlEngine *engine, QJSEngine *jsEngine)
+{
+ Q_UNUSED(engine);
+ Q_UNUSED(jsEngine);
+ return new QQuickComponentsPrivate();
+}
+
+void StylePlugin::registerTypes(const char *uri)
+{
+
+ // Unfortunately animations do not work on mac without this hack
+#ifdef Q_OS_MAC
+ setenv("QML_BAD_GUI_RENDER_LOOP", "1", 0);
+#endif
+
+ qmlRegisterSingletonType<QQuickComponentsPrivate>(uri, 1, 0, "PrivateHelper", registerPrivateModule);
+
+ qmlRegisterType<QStyleItem>(uri, 1, 0, "StyleItem");
+ qmlRegisterType<QRangeModel>(uri, 1, 0, "RangeModel");
+ qmlRegisterType<QWheelArea>(uri, 1, 0, "WheelArea");
+
+ qmlRegisterType<QtMenu>(uri, 1, 0, "Menu");
+ qmlRegisterType<QtMenuBar>(uri, 1, 0, "MenuBar");
+ qmlRegisterType<QtMenuItem>(uri, 1, 0, "MenuItem");
+ qmlRegisterType<QtMenuSeparator>(uri, 1, 0, "Separator");
+
+ 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"));
+
+ qmlRegisterType<QFileDialogItem>(uri, 1, 0, "FileDialog");
+
+ qmlRegisterType<QFileSystemModel>(uri, 1, 0, "FileSystemModel");
+ qmlRegisterType<QtSplitterBase>(uri, 1, 0, "Splitter");
+ qmlRegisterType<QQuickWindow>(uri, 1, 0, "Window");
+
+ qmlRegisterUncreatableType<QtMenuBase>(uri, 1, 0, "NativeMenuBase", QLatin1String("Do not create objects of type NativeMenuBase"));
+ qmlRegisterUncreatableType<QDesktopItem>(uri, 1, 0,"Desktop", QLatin1String("Do not create objects of type Desktop"));
+}
+
+void StylePlugin::initializeEngine(QQmlEngine *engine, const char *uri)
+{
+ Q_UNUSED(uri);
+ engine->addImageProvider("desktoptheme", new DesktopIconProvider);
+}
diff --git a/src/qtdesktop/qstyleplugin.h b/src/qtdesktop/qstyleplugin.h
new file mode 100644
index 00000000..2bdb2a81
--- /dev/null
+++ b/src/qtdesktop/qstyleplugin.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 STYLEPLUGIN_H
+#define STYLEPLUGIN_H
+
+#include <QQmlExtensionPlugin>
+#include <QtCore/QTimer>
+#include <QtWidgets/QFileSystemModel>
+
+class StylePlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.playground.qtdesktopcomponents.QQmlExtensionInterface" FILE "styleplugin.json")
+public:
+ void registerTypes(const char *uri);
+ void initializeEngine(QQmlEngine *engine, const char *uri);
+};
+
+#endif // STYLEPLUGIN_H
diff --git a/src/qtdesktop/qtdesktop.pro b/src/qtdesktop/qtdesktop.pro
new file mode 100644
index 00000000..d348cd71
--- /dev/null
+++ b/src/qtdesktop/qtdesktop.pro
@@ -0,0 +1,58 @@
+QT += qml quick widgets
+
+TARGETPATH = QtDesktop
+
+QML_FILES = \
+ ApplicationWindow.qml \
+ Button.qml \
+ ButtonColumn.qml \
+ ButtonRow.qml \
+ CheckBox.qml \
+ ComboBox.qml \
+ ContextMenu.qml \
+ Dial.qml \
+ Dialog.qml \
+ Frame.qml \
+ GroupBox.qml \
+ Label.qml \
+ ProgressBar.qml \
+ RadioButton.qml \
+ ScrollArea.qml \
+ ScrollBar.qml \
+ Slider.qml \
+ SpinBox.qml \
+ SplitterColumn.qml \
+ SplitterRow.qml \
+ StatusBar.qml \
+ Tab.qml \
+ TabBar.qml \
+ TabFrame.qml \
+ TableColumn.qml \
+ TableView.qml \
+ TextArea.qml \
+ TextField.qml \
+ ToolBar.qml \
+ ToolButton.qml
+
+# private qml files
+QML_FILES += \
+ private/BasicButton.qml \
+ private/ButtonBehavior.qml \
+ private/ButtonGroup.js \
+ private/ModalPopupBehavior.qml \
+ private/ScrollAreaHelper.qml \
+ private/Splitter.qml
+
+include(styleplugin.pri)
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+mac {
+ LIBS += -framework Carbon
+}
+
+load(qml_plugin)
+
+#tmp solution for QTBUG-28200
+TARGET = $$qtLibraryTarget(styleplugin)
+DESTDIR = $$QT.core.qml/QtDesktop/plugin
diff --git a/src/qtdesktop/qtmenu.cpp b/src/qtdesktop/qtmenu.cpp
new file mode 100644
index 00000000..34710293
--- /dev/null
+++ b/src/qtdesktop/qtmenu.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** 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.h"
+#include "qdebug.h"
+#include <qapplication.h>
+#include <qmenubar.h>
+#include <qabstractitemmodel.h>
+
+QtMenu::QtMenu(QQuickItem *parent)
+ : QtMenuBase(parent),
+ dummy(0),
+ m_selectedIndex(0),
+ m_highlightedIndex(0),
+ m_hasNativeModel(false)
+{
+ m_qmenu = new QMenu(0);
+ connect(m_qmenu, SIGNAL(aboutToHide()), this, SIGNAL(menuClosed()));
+}
+
+QtMenu::~QtMenu()
+{
+ delete m_qmenu;
+}
+
+void QtMenu::setText(const QString &text)
+{
+ m_qmenu->setTitle(text);
+ emit textChanged();
+}
+
+QString QtMenu::text() const
+{
+ return m_qmenu->title();
+}
+
+void QtMenu::setSelectedIndex(int index)
+{
+ m_selectedIndex = index;
+ QList<QAction *> actionList = m_qmenu->actions();
+ if (m_selectedIndex >= 0 && m_selectedIndex < actionList.size())
+ m_qmenu->setActiveAction(actionList[m_selectedIndex]);
+ emit selectedIndexChanged();
+}
+
+void QtMenu::setHoveredIndex(int index)
+{
+ m_highlightedIndex = index;
+ QList<QAction *> actionList = m_qmenu->actions();
+ if (m_highlightedIndex >= 0 && m_highlightedIndex < actionList.size())
+ m_qmenu->setActiveAction(actionList[m_highlightedIndex]);
+ emit hoveredIndexChanged();
+}
+
+QQmlListProperty<QtMenuBase> QtMenu::menuItems()
+{
+ return QQmlListProperty<QtMenuBase>(this, 0, &QtMenu::append_qmenuItem, 0, 0, 0);
+}
+
+void QtMenu::showPopup(qreal x, qreal y, int atActionIndex, QQuickWindow * parentWindow)
+{
+ if (m_qmenu->isVisible())
+ return;
+
+ // If atActionIndex is valid, x and y is specified from the
+ // the position of the corresponding QAction:
+ QAction *atAction = 0;
+ if (atActionIndex >= 0 && atActionIndex < m_qmenu->actions().size())
+ atAction = m_qmenu->actions()[atActionIndex];
+
+ QPointF screenPosition(mapToScene(QPoint(x, y)));
+ QWindow *tw = parentWindow ? parentWindow : window();
+ if (tw) {
+ screenPosition = tw->mapToGlobal(QPoint(x, y));
+
+ // calling winId forces a QWindow to be created
+ // since this needs to be a top-level
+ // otherwise windowHandle might return 0
+ m_qmenu->winId();
+ m_qmenu->windowHandle()->setTransientParent(tw);
+ }
+
+ setHoveredIndex(m_selectedIndex);
+ m_qmenu->popup(screenPosition.toPoint(), atAction);
+}
+
+void QtMenu::hidePopup()
+{
+ m_qmenu->close();
+}
+
+QAction* QtMenu::action()
+{
+ return m_qmenu->menuAction();
+}
+
+Q_INVOKABLE void QtMenu::clearMenuItems()
+{
+ m_qmenu->clear();
+ foreach (QtMenuBase *item, m_qmenuItems) {
+ delete item;
+ }
+ m_qmenuItems.clear();
+}
+
+void QtMenu::addMenuItem(const QString &text)
+{
+ QtMenuItem *menuItem = new QtMenuItem(this);
+ menuItem->setText(text);
+ m_qmenuItems.append(menuItem);
+ m_qmenu->addAction(menuItem->action());
+
+ connect(menuItem->action(), SIGNAL(triggered()), this, SLOT(emitSelected()));
+ connect(menuItem->action(), SIGNAL(hovered()), this, SLOT(emitHovered()));
+
+ if (m_qmenu->actions().size() == 1)
+ // Inform QML that the selected action (0) now has changed contents:
+ emit selectedIndexChanged();
+}
+
+void QtMenu::emitSelected()
+{
+ QAction *act = qobject_cast<QAction *>(sender());
+ if (!act)
+ return;
+ m_selectedIndex = m_qmenu->actions().indexOf(act);
+ emit selectedIndexChanged();
+}
+
+void QtMenu::emitHovered()
+{
+ QAction *act = qobject_cast<QAction *>(sender());
+ if (!act)
+ return;
+ m_highlightedIndex = m_qmenu->actions().indexOf(act);
+ emit hoveredIndexChanged();
+}
+
+QString QtMenu::itemTextAt(int index) const
+{
+ QList<QAction *> actionList = m_qmenu->actions();
+ if (index >= 0 && index < actionList.size())
+ return actionList[index]->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_qmenuItem(QQmlListProperty<QtMenuBase> *list, QtMenuBase *menuItem)
+{
+ QtMenu *menu = qobject_cast<QtMenu *>(list->object);
+ if (menu) {
+ menuItem->setParent(menu);
+ menu->m_qmenuItems.append(menuItem);
+ menu->qmenu()->addAction(menuItem->action());
+ }
+}
+
+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);
+ }
+}
diff --git a/src/qtdesktop/qtmenu.h b/src/qtdesktop/qtmenu.h
new file mode 100644
index 00000000..d718b55b
--- /dev/null
+++ b/src/qtdesktop/qtmenu.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 QTMLMENU_H
+#define QTMLMENU_H
+#include <QtCore/qglobal.h>
+#include <QtWidgets/qmenu.h>
+#include <QtQuick/QtQuick>
+#include <QtQml/QtQml>
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/QVariant>
+#include "qtmenuitem.h"
+
+class QtMenu : public QtMenuBase
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged)
+ Q_PROPERTY(int hoveredIndex READ hoveredIndex WRITE setHoveredIndex NOTIFY hoveredIndexChanged)
+ Q_PROPERTY(QQmlListProperty<QtMenuBase> menuItems READ menuItems)
+ Q_CLASSINFO("DefaultProperty", "menuItems")
+public:
+ QtMenu(QQuickItem *parent = 0);
+ virtual ~QtMenu();
+
+ void setText(const QString &text);
+ QString text() const;
+
+ int selectedIndex() const { return m_selectedIndex; }
+ void setSelectedIndex(int index);
+ int hoveredIndex() const { return m_highlightedIndex; }
+ void setHoveredIndex(int index);
+
+ QQmlListProperty<QtMenuBase> menuItems();
+
+ QMenu* qmenu() { return m_qmenu; }
+
+ QAction* action();
+
+ Q_INVOKABLE int minimumWidth() const { return m_qmenu->minimumWidth(); }
+ Q_INVOKABLE void setMinimumWidth(int w) { m_qmenu->setMinimumWidth(w); }
+ Q_INVOKABLE void showPopup(qreal x, qreal y, int atActionIndex = -1, QQuickWindow *window = 0);
+ Q_INVOKABLE void hidePopup();
+ Q_INVOKABLE void clearMenuItems();
+ Q_INVOKABLE void addMenuItem(const QString &text);
+ Q_INVOKABLE QString itemTextAt(int index) const;
+ 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; }
+
+public slots:
+ void setModel(const QVariant &newModel);
+
+public:
+Q_SIGNALS:
+ void menuClosed();
+ void selectedIndexChanged();
+ void hoveredIndexChanged();
+ void modelChanged(const QVariant &newModel);
+ void rebuildMenu();
+ void textChanged();
+
+private Q_SLOTS:
+ void emitSelected();
+ void emitHovered();
+
+private:
+ static void append_qmenuItem(QQmlListProperty<QtMenuBase> *list, QtMenuBase *menuItem);
+
+ QWidget *dummy;
+ QMenu *m_qmenu;
+ QList<QtMenuBase *> m_qmenuItems;
+ int m_selectedIndex;
+ int m_highlightedIndex;
+ bool m_hasNativeModel;
+ QVariant m_model;
+};
+
+QML_DECLARE_TYPE(QtMenu)
+
+#endif // QTMLMENU_H
diff --git a/src/qtdesktop/qtmenubar.cpp b/src/qtdesktop/qtmenubar.cpp
new file mode 100644
index 00000000..f63f5562
--- /dev/null
+++ b/src/qtdesktop/qtmenubar.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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.h"
+
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QMenuBar>
+
+QtMenuBar::QtMenuBar(QQuickItem *parent)
+ : QQuickItem(parent)
+{
+ connect(this, SIGNAL(parentChanged(QQuickItem *)), this, SLOT(updateParent(QQuickItem *)));
+ setFlag(QQuickItem::ItemHasContents, false);
+#ifdef Q_OS_MAC
+ _menuBar = new QMenuBar(0);
+#endif
+}
+
+QtMenuBar::~QtMenuBar()
+{
+}
+
+QQmlListProperty<QtMenu> QtMenuBar::menus()
+{
+ return QQmlListProperty<QtMenu>(this, 0, &QtMenuBar::append_menu, 0, 0, 0);
+}
+
+QList<QObject*> QtMenuBar::menuList()
+{
+ return m_menus;
+}
+
+void QtMenuBar::updateParent(QQuickItem *newParent)
+{
+#ifdef Q_OS_MAC
+ _menuBar->clear();
+ foreach (QObject *obj, m_menus) {
+ QtMenu *menu = qobject_cast<QtMenu*>(obj);
+ _menuBar->addMenu(menu->qmenu());
+ }
+#endif
+}
+
+void QtMenuBar::append_menu(QQmlListProperty<QtMenu> *list, QtMenu *menu)
+{
+ QtMenuBar *menuBar = qobject_cast<QtMenuBar *>(list->object);
+ if (menuBar) {
+ menu->setParent(menuBar);
+ menuBar->m_menus.append(menu);
+#ifdef Q_OS_MAC
+ if (menuBar->_menuBar)
+ menuBar->_menuBar->addMenu(menu->qmenu());
+#endif
+ menuBar->menuChanged();
+ }
+}
diff --git a/src/qtdesktop/qtmenubar.h b/src/qtdesktop/qtmenubar.h
new file mode 100644
index 00000000..6f762bb7
--- /dev/null
+++ b/src/qtdesktop/qtmenubar.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 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_H
+#define QTMENUBAR_H
+
+#include <QtCore/qglobal.h>
+
+#include <QtQuick/QQuickItem>
+#include <QtWidgets>
+
+#include "qtmenu.h"
+
+class QtMenuBar: public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QQmlListProperty<QtMenu> menus READ menus NOTIFY menuChanged)
+ Q_PROPERTY(QList<QObject*> menuList READ menuList NOTIFY menuChanged)
+ Q_PROPERTY(bool showMenuBar READ showMenuBar NOTIFY showMenuBarChanged)
+ Q_CLASSINFO("DefaultProperty", "menus")
+public:
+ QtMenuBar(QQuickItem *parent = 0);
+ ~QtMenuBar();
+
+ QQmlListProperty<QtMenu> menus();
+ QList<QObject*> menuList();
+
+ bool showMenuBar() {
+#ifdef Q_OS_MAC
+ return false;
+#endif
+ return true;
+}
+
+signals:
+ void menuChanged();
+ void showMenuBarChanged();
+
+protected Q_SLOTS:
+ void updateParent(QQuickItem *newParent);
+
+private:
+ static void append_menu(QQmlListProperty<QtMenu> *list, QtMenu *menu);
+
+private:
+ QList<QObject *> m_menus;
+ QMenuBar *_menuBar;
+};
+
+#endif //QTMENUBAR_H
diff --git a/src/qtdesktop/qtmenuitem.cpp b/src/qtdesktop/qtmenuitem.cpp
new file mode 100644
index 00000000..9dc58af7
--- /dev/null
+++ b/src/qtdesktop/qtmenuitem.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** 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.h"
+
+void QtMenuBase::setIconSource(const QUrl &icon)
+{
+ _iconSource = icon;
+ if (_iconName.isEmpty())
+ action()->setIcon(QIcon(icon.toLocalFile()));
+ else
+ action()->setIcon(QIcon::fromTheme(_iconName, QIcon(_iconSource.toLocalFile())));
+
+ emit iconSourceChanged();
+}
+
+QUrl QtMenuBase::iconSource() const
+{
+ return _iconSource;
+}
+
+void QtMenuBase::setIconName(const QString &icon)
+{
+ _iconName = icon;
+ action()->setIcon(QIcon::fromTheme(_iconName, QIcon(_iconSource.toLocalFile())));
+
+ emit iconNameChanged();
+}
+
+QString QtMenuBase::iconName() const
+{
+ return _iconName;
+}
+
+QtMenuSeparator::QtMenuSeparator(QQuickItem *parent)
+ : QtMenuBase(parent), _action(new QAction(this))
+{
+ _action->setSeparator(true);
+}
+
+QtMenuSeparator::~QtMenuSeparator()
+{
+}
+
+QAction * QtMenuSeparator::action()
+{
+ return _action;
+}
+
+QtMenuItem::QtMenuItem(QQuickItem *parent)
+ : QtMenuBase(parent), _action(new QAction(this))
+{
+ connect(_action, SIGNAL(triggered()), this, SIGNAL(triggered()));
+ connect(_action, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
+ connect(_action, SIGNAL(changed()), this, SIGNAL(enabledChanged()));
+}
+
+QtMenuItem::~QtMenuItem()
+{
+}
+
+void QtMenuItem::setText(const QString &text)
+{
+ _action->setText(text);
+ emit textChanged();
+}
+
+void QtMenuItem::setShortcut(const QString &shortcut)
+{
+ _action->setShortcut(QKeySequence(shortcut));
+ emit shortcutChanged();
+}
+
+void QtMenuItem::setCheckable(bool checkable)
+{
+ _action->setCheckable(checkable);
+}
+
+void QtMenuItem::setChecked(bool checked)
+{
+ _action->setChecked(checked);
+}
+
+void QtMenuItem::setEnabled(bool enabled)
+{
+ _action->setEnabled(enabled);
+}
+
+QString QtMenuItem::text() const
+{
+ return _action->text();
+}
+
+QString QtMenuItem::shortcut() const
+{
+ return _action->shortcut().toString();
+}
+
+bool QtMenuItem::checkable() const
+{
+ return _action->isCheckable();
+}
+
+bool QtMenuItem::checked() const
+{
+ return _action->isChecked();
+}
+
+bool QtMenuItem::enabled() const
+{
+ return _action->isEnabled();
+}
+
+QAction * QtMenuItem::action()
+{
+ return _action;
+}
diff --git a/src/qtdesktop/qtmenuitem.h b/src/qtdesktop/qtmenuitem.h
new file mode 100644
index 00000000..5ee11671
--- /dev/null
+++ b/src/qtdesktop/qtmenuitem.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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_H
+#define QTMENUITEM_H
+
+#include <QtCore/QObject>
+#include <QtWidgets/QAction>
+#include <QtCore/QUrl>
+
+#include <QtQuick/QQuickItem>
+
+class QtMenuBase: public QQuickItem
+{
+Q_OBJECT
+ Q_PROPERTY(QUrl iconSource READ iconSource WRITE setIconSource NOTIFY iconSourceChanged)
+ Q_PROPERTY(QString iconName READ iconName WRITE setIconName NOTIFY iconNameChanged)
+
+public:
+ QtMenuBase(QQuickItem *parent = 0) : QQuickItem(parent) {}
+
+ virtual QAction* action() = 0;
+
+ void setIconSource(const QUrl &icon);
+ QUrl iconSource() const;
+
+ void setIconName(const QString &icon);
+ QString iconName() const;
+
+Q_SIGNALS:
+ void iconSourceChanged();
+ void iconNameChanged();
+
+private:
+ QUrl _iconSource;
+ QString _iconName;
+};
+
+class QtMenuSeparator : public QtMenuBase
+{
+ Q_OBJECT
+public:
+ QtMenuSeparator(QQuickItem *parent = 0);
+ ~QtMenuSeparator();
+ QAction* action();
+
+private:
+ QAction *_action;
+};
+
+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)
+ Q_PROPERTY(bool checked READ checked WRITE setChecked NOTIFY toggled)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+
+public:
+ QtMenuItem(QQuickItem *parent = 0);
+ ~QtMenuItem();
+
+ void setText(const QString &text);
+ void setShortcut(const QString &shortcut);
+ void setCheckable(bool checkable);
+ void setChecked(bool checked);
+ void setEnabled(bool enabled);
+
+ QString text() const;
+ QString shortcut() const;
+ bool checkable() const;
+ bool checked() const;
+ bool enabled() const;
+
+ QAction* action();
+
+Q_SIGNALS:
+ void triggered();
+ void textChanged();
+ void shortcutChanged();
+ void toggled(bool);
+ void enabledChanged();
+
+private:
+ QAction *_action;
+};
+
+#endif //QTMENUITEM_H
diff --git a/src/qtdesktop/qtsplitterbase.cpp b/src/qtdesktop/qtsplitterbase.cpp
new file mode 100644
index 00000000..c2a26fbf
--- /dev/null
+++ b/src/qtdesktop/qtsplitterbase.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 "qtsplitterbase.h"
+
+QtSplitterBase::QtSplitterBase(QQuickItem *parent)
+ : QQuickItem(parent)
+{
+}
+
+QtSplitterAttached *QtSplitterBase::qmlAttachedProperties(QObject *object)
+{
+ return new QtSplitterAttached(object);
+}
+
+void QtSplitterAttached::setExpanding(bool expanding)
+{
+ m_expanding = expanding;
+ emit expandingChanged(expanding);
+}
+
+void QtSplitterAttached::setMaximumWidth(qreal width)
+{
+ m_maximumWidth = width;
+ emit maximumWidthChanged(width);
+}
+
+void QtSplitterAttached::setMinimumWidth(qreal width)
+{
+ m_minimumWidth = width;
+ emit minimumWidthChanged(width);
+}
+
+void QtSplitterAttached::setMaximumHeight(qreal height)
+{
+ m_maximumHeight = height;
+ emit maximumHeightChanged(height);
+}
+
+void QtSplitterAttached::setMinimumHeight(qreal height)
+{
+ m_minimumHeight = height;
+ emit minimumHeightChanged(height);
+}
+
+QtSplitterAttached::QtSplitterAttached(QObject *object)
+ : QObject(object),
+ m_minimumWidth(-1),
+ m_maximumWidth(-1),
+ m_minimumHeight(-1),
+ m_maximumHeight(-1),
+ m_percentageSize(-1),
+ m_itemIndex(-1),
+ m_expanding(false)
+{
+}
diff --git a/src/qtdesktop/qtsplitterbase.h b/src/qtdesktop/qtsplitterbase.h
new file mode 100644
index 00000000..8bf4ee4d
--- /dev/null
+++ b/src/qtdesktop/qtsplitterbase.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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 QTSPLITTERBASE_H
+#define QTSPLITTERBASE_H
+
+#include <QtQml>
+#include <QtQuick>
+
+
+class QtSplitterAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal minimumWidth READ minimumWidth WRITE setMinimumWidth NOTIFY minimumWidthChanged)
+ Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth NOTIFY maximumWidthChanged)
+ Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight NOTIFY minimumHeightChanged)
+ Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight NOTIFY maximumHeightChanged)
+ Q_PROPERTY(qreal percentageSize READ percentageSize WRITE setPercentageSize NOTIFY percentageWidthSize)
+ Q_PROPERTY(bool expanding READ expanding WRITE setExpanding NOTIFY expandingChanged)
+ Q_PROPERTY(int itemIndex READ itemIndex WRITE setItemIndex NOTIFY itemIndexChanged)
+
+public:
+ explicit QtSplitterAttached(QObject *object);
+
+ qreal minimumWidth() const { return m_minimumWidth; }
+ void setMinimumWidth(qreal width);
+
+ qreal maximumWidth() const { return m_maximumWidth; }
+ void setMaximumWidth(qreal width);
+
+ qreal minimumHeight() const { return m_minimumHeight; }
+ void setMinimumHeight(qreal width);
+
+ qreal maximumHeight() const { return m_maximumHeight; }
+ void setMaximumHeight(qreal width);
+
+ bool expanding() const { return m_expanding; }
+ void setExpanding(bool expanding);
+
+ qreal percentageSize() const { return m_percentageSize; }
+
+ int itemIndex() const { return m_itemIndex; }
+
+ void setPercentageSize(qreal arg) { m_percentageSize = arg; }
+ void setItemIndex(int arg) {
+ if (m_itemIndex != arg) {
+ m_itemIndex = arg;
+ emit itemIndexChanged(arg);
+ }
+ }
+
+signals:
+ void minimumWidthChanged(qreal arg);
+ void maximumWidthChanged(qreal arg);
+ void minimumHeightChanged(qreal arg);
+ void maximumHeightChanged(qreal arg);
+ void expandingChanged(bool arg);
+ void percentageWidthSize(qreal arg);
+ void itemIndexChanged(int arg);
+
+private:
+ qreal m_minimumWidth;
+ qreal m_maximumWidth;
+ qreal m_minimumHeight;
+ qreal m_maximumHeight;
+ qreal m_percentageSize;
+ int m_itemIndex;
+ bool m_expanding;
+
+ friend class QtSplitterBase;
+};
+
+
+class QtSplitterBase : public QQuickItem
+{
+ Q_OBJECT
+public:
+ explicit QtSplitterBase(QQuickItem *parent = 0);
+ ~QtSplitterBase() {}
+
+ static QtSplitterAttached *qmlAttachedProperties(QObject *object);
+};
+
+QML_DECLARE_TYPEINFO(QtSplitterBase, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QTSPLITTERBASE_H
diff --git a/src/qtdesktop/qwheelarea.cpp b/src/qtdesktop/qwheelarea.cpp
new file mode 100644
index 00000000..97aac522
--- /dev/null
+++ b/src/qtdesktop/qwheelarea.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** 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 "qwheelarea.h"
+
+
+QWheelArea::QWheelArea(QQuickItem *parent)
+ : QQuickItem(parent),
+ m_horizontalMinimumValue(0),
+ m_horizontalMaximumValue(0),
+ m_verticalMinimumValue(0),
+ m_verticalMaximumValue(0),
+ m_horizontalValue(0),
+ m_verticalValue(0),
+ m_verticalDelta(0),
+ m_horizontalDelta(0),
+ m_scrollSpeed(1.0)
+{
+
+}
+
+QWheelArea::~QWheelArea()
+{
+
+}
+
+void QWheelArea::wheelEvent(QWheelEvent *we)
+{
+ if (we->orientation() == Qt::Vertical) {
+ setVerticalDelta(we->delta());
+ } else {
+ setHorizontalDelta(we->delta());
+ }
+ we->accept();
+}
+
+void QWheelArea::setHorizontalMinimumValue(qreal value)
+{
+ m_horizontalMinimumValue = value;
+}
+
+qreal QWheelArea::horizontalMinimumValue() const
+{
+ return m_horizontalMinimumValue;
+}
+
+void QWheelArea::setHorizontalMaximumValue(qreal value)
+{
+ m_horizontalMaximumValue = value;
+}
+
+qreal QWheelArea::horizontalMaximumValue() const
+{
+ return m_horizontalMaximumValue;
+}
+
+void QWheelArea::setVerticalMinimumValue(qreal value)
+{
+ m_verticalMinimumValue = value;
+}
+
+qreal QWheelArea::verticalMinimumValue() const
+{
+ return m_verticalMinimumValue;
+}
+
+void QWheelArea::setVerticalMaximumValue(qreal value)
+{
+ m_verticalMaximumValue = value;
+}
+
+qreal QWheelArea::verticalMaximumValue() const
+{
+ return m_verticalMaximumValue;
+}
+
+void QWheelArea::setHorizontalValue(qreal value)
+{
+ value = qBound<qreal>(m_horizontalMinimumValue, value, m_horizontalMaximumValue);
+
+ if (value != m_horizontalValue) {
+ m_horizontalValue = value;
+ emit horizontalValueChanged();
+ }
+}
+
+qreal QWheelArea::horizontalValue() const
+{
+ return m_horizontalValue;
+}
+
+void QWheelArea::setVerticalValue(qreal value)
+{
+ value = qBound<qreal>(m_verticalMinimumValue, value, m_verticalMaximumValue);
+
+ if (value != m_verticalValue) {
+ m_verticalValue = value;
+ emit verticalValueChanged();
+ }
+}
+
+qreal QWheelArea::verticalValue() const
+{
+ return m_verticalValue;
+}
+
+void QWheelArea::setVerticalDelta(qreal value)
+{
+ m_verticalDelta = m_scrollSpeed * value / 15;
+ setVerticalValue(m_verticalValue - m_verticalDelta);
+
+ emit verticalWheelMoved();
+}
+
+qreal QWheelArea::verticalDelta() const
+{
+ return m_verticalDelta;
+}
+
+void QWheelArea::setHorizontalDelta(qreal value)
+{
+ m_horizontalDelta = value / 15;
+ setHorizontalValue(m_horizontalValue - m_horizontalDelta);
+
+ emit horizontalWheelMoved();
+}
+
+qreal QWheelArea::horizontalDelta() const
+{
+ return m_horizontalDelta;
+}
+
+void QWheelArea::setScrollSpeed(qreal value)
+{
+ if (value != m_scrollSpeed) {
+ m_scrollSpeed = value;
+ emit scrollSpeedChanged();
+ }
+}
+
+qreal QWheelArea::scrollSpeed() const
+{
+ return m_scrollSpeed;
+}
diff --git a/src/qtdesktop/qwheelarea.h b/src/qtdesktop/qwheelarea.h
new file mode 100644
index 00000000..a112607c
--- /dev/null
+++ b/src/qtdesktop/qwheelarea.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 QWHEELAREA_H
+#define QWHEELAREA_H
+
+#include <QtGui/qevent.h>
+#include <QtWidgets/qgraphicssceneevent.h>
+#include <QtQuick/qquickitem.h>
+
+
+class QWheelArea : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal verticalDelta READ verticalDelta WRITE setVerticalDelta NOTIFY verticalWheelMoved)
+ Q_PROPERTY(qreal horizontalDelta READ horizontalDelta WRITE setHorizontalDelta NOTIFY horizontalWheelMoved)
+ Q_PROPERTY(qreal horizontalMinimumValue READ horizontalMinimumValue WRITE setHorizontalMinimumValue)
+ Q_PROPERTY(qreal horizontalMaximumValue READ horizontalMaximumValue WRITE setHorizontalMaximumValue)
+ Q_PROPERTY(qreal verticalMinimumValue READ verticalMinimumValue WRITE setVerticalMinimumValue)
+ Q_PROPERTY(qreal verticalMaximumValue READ verticalMaximumValue WRITE setVerticalMaximumValue)
+ Q_PROPERTY(qreal horizontalValue READ horizontalValue WRITE setHorizontalValue)
+ Q_PROPERTY(qreal verticalValue READ verticalValue WRITE setVerticalValue)
+ Q_PROPERTY(qreal scrollSpeed READ scrollSpeed WRITE setScrollSpeed NOTIFY scrollSpeedChanged)
+
+public:
+ QWheelArea(QQuickItem *parent = 0);
+ virtual ~QWheelArea();
+
+ void setHorizontalMinimumValue(qreal value);
+ qreal horizontalMinimumValue() const;
+
+ void setHorizontalMaximumValue(qreal value);
+ qreal horizontalMaximumValue() const;
+
+ void setVerticalMinimumValue(qreal value);
+ qreal verticalMinimumValue() const;
+
+ void setVerticalMaximumValue(qreal value);
+ qreal verticalMaximumValue() const;
+
+ void setHorizontalValue(qreal value);
+ qreal horizontalValue() const;
+
+ void setVerticalValue(qreal value);
+ qreal verticalValue() const;
+
+ void setVerticalDelta(qreal value);
+ qreal verticalDelta() const;
+
+ void setHorizontalDelta(qreal value);
+ qreal horizontalDelta() const;
+
+ void setScrollSpeed(qreal value);
+ qreal scrollSpeed() const;
+
+ void wheelEvent(QWheelEvent *event);
+
+Q_SIGNALS:
+ void verticalValueChanged();
+ void horizontalValueChanged();
+ void verticalWheelMoved();
+ void horizontalWheelMoved();
+ void scrollSpeedChanged();
+
+private:
+ qreal m_horizontalMinimumValue;
+ qreal m_horizontalMaximumValue;
+ qreal m_verticalMinimumValue;
+ qreal m_verticalMaximumValue;
+ qreal m_horizontalValue;
+ qreal m_verticalValue;
+ qreal m_verticalDelta;
+ qreal m_horizontalDelta;
+ qreal m_scrollSpeed;
+
+ Q_DISABLE_COPY(QWheelArea)
+};
+
+QML_DECLARE_TYPE(QWheelArea)
+
+
+#endif // QWHEELAREA_H
diff --git a/src/qtdesktop/styleplugin.json b/src/qtdesktop/styleplugin.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/src/qtdesktop/styleplugin.json
@@ -0,0 +1 @@
+{}
diff --git a/src/qtdesktop/styleplugin.pri b/src/qtdesktop/styleplugin.pri
new file mode 100644
index 00000000..5083a873
--- /dev/null
+++ b/src/qtdesktop/styleplugin.pri
@@ -0,0 +1,35 @@
+HEADERS += \
+ qdesktopitem.h \
+ qfiledialogitem.h \
+ qquickcomponentsprivate.h \
+ qquicklayout.h \
+ qquicklayoutengine_p.h \
+ qquicklinearlayout.h \
+ qrangemodel.h \
+ qrangemodel_p.h \
+ qstyleitem.h \
+ qstyleplugin.h \
+ qtmenu.h \
+ qtmenubar.h \
+ qtmenuitem.h \
+ qtsplitterbase.h \
+ qwheelarea.h
+
+SOURCES += \
+ qdesktopitem.cpp \
+ qfiledialogitem.cpp \
+ qquickcomponentsprivate.cpp \
+ qquicklayout.cpp \
+ qquicklayoutengine.cpp \
+ qquicklinearlayout.cpp \
+ qrangemodel.cpp \
+ qstyleitem.cpp \
+ qstyleplugin.cpp \
+ qtmenu.cpp \
+ qtmenubar.cpp \
+ qtmenuitem.cpp \
+ qtsplitterbase.cpp \
+ qwheelarea.cpp
+
+OTHER_FILES += \
+ styleplugin.json