diff options
author | Caroline Chao <caroline.chao@digia.com> | 2013-07-31 13:38:35 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-08-16 17:32:06 +0200 |
commit | 5483ccd3547dcb3edbe4c50d70e6921ee5c5cb7a (patch) | |
tree | 634db3b0a47cf54e68fe232d5664cbde2dd8579a /src/controls/Private | |
parent | 2b308e33bec09c8a792b37282f6172a59dc3d543 (diff) | |
download | qtquickcontrols-5483ccd3547dcb3edbe4c50d70e6921ee5c5cb7a.tar.gz |
Move Styles and Private under controls
Register the C++ private API from the controls plugin. The
private plugin is not needed anymore.
The Controls "submodules" Styles and Private are moved to
the controls subfolder in the sources tree.
Change-Id: I98358227c945b6cd1a8dbff9d07e6cad4f044277
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Diffstat (limited to 'src/controls/Private')
31 files changed, 5713 insertions, 0 deletions
diff --git a/src/controls/Private/AbstractCheckable.qml b/src/controls/Private/AbstractCheckable.qml new file mode 100644 index 00000000..02348b71 --- /dev/null +++ b/src/controls/Private/AbstractCheckable.qml @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 + +/*! + \qmltype AbstractCheckable + \inqmlmodule QtQuick.Controls 1.0 + \ingroup controls + \brief An abstract representation of a checkable control with a label + \qmlabstract + \internal + + A checkable control is one that has two states: checked (on) and + unchecked (off). AbstractCheckable encapsulates the basic behavior and + states that are required by checkable controls. + + Examples of checkable controls are RadioButton and + CheckBox. CheckBox extends AbstractCheckable's behavior by adding a third + state: partially checked. +*/ + +Control { + id: abstractCheckable + + /*! + Emitted whenever the control is clicked. + */ + signal clicked + + /*! + \qmlproperty bool AbstractCheckable::pressed + + This property is \c true if the control is being pressed. + Set this property to manually invoke a mouse click. + */ + property alias pressed: mouseArea.effectivePressed + + /*! \qmlproperty bool AbstractCheckcable::hovered + + This property indicates whether the control is being hovered. + */ + readonly property alias hovered: mouseArea.containsMouse + + /*! + This property is \c true if the control is checked. + */ + property bool checked: false + + /*! + This property is \c true if the control takes the focus when it is + pressed; \l{QQuickItem::forceActiveFocus()}{forceActiveFocus()} will be + called on the control. + */ + property bool activeFocusOnPress: false + + /*! + This property stores the ExclusiveGroup that the control belongs to. + */ + property ExclusiveGroup exclusiveGroup: null + + /*! + This property holds the text that the label should display. + */ + property string text + + /*! \internal */ + property var __cycleStatesHandler: cycleRadioButtonStates + + activeFocusOnTab: true + + MouseArea { + id: mouseArea + focus: true + anchors.fill: parent + hoverEnabled: true + enabled: !keyPressed + + property bool keyPressed: false + property bool effectivePressed: pressed && containsMouse || keyPressed + + onClicked: abstractCheckable.clicked(); + + onPressed: if (activeFocusOnPress) forceActiveFocus(); + + onReleased: { + if (containsMouse && (!exclusiveGroup || !checked)) + __cycleStatesHandler(); + } + } + + /*! \internal */ + onExclusiveGroupChanged: { + if (exclusiveGroup) + exclusiveGroup.bindCheckable(abstractCheckable) + } + + Keys.onPressed: { + if (event.key === Qt.Key_Space && !event.isAutoRepeat && !mouseArea.pressed) + mouseArea.keyPressed = true; + } + + Keys.onReleased: { + if (event.key === Qt.Key_Space && !event.isAutoRepeat && mouseArea.keyPressed) { + mouseArea.keyPressed = false; + if (!exclusiveGroup || !checked) + __cycleStatesHandler(); + clicked(); + } + } +} diff --git a/src/controls/Private/BasicButton.qml b/src/controls/Private/BasicButton.qml new file mode 100644 index 00000000..f07aea86 --- /dev/null +++ b/src/controls/Private/BasicButton.qml @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Private 1.0 +import QtQuick.Controls.Styles 1.0 + +/*! + \qmltype BasicButton + \internal + \qmlabstract + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ + +Control { + id: button + + /*! This signal is emitted when the button is clicked. */ + signal clicked + + /*! \qmlproperty bool BasicButton::pressed + + This property holds whether the button is being pressed. */ + readonly property alias pressed: behavior.effectivePressed + + /*! \qmlproperty bool BasicButton::hovered + + This property indicates whether the control is being hovered. + */ + readonly property alias hovered: behavior.containsMouse + + /*! This property holds whether the button is checkable. + + The default value is \c false. */ + property bool checkable: false + + /*! This property holds whether the button is checked. + + Only checkable buttons can be checked. + + The default value is \c false. */ + property bool checked: false + + /*! This property holds the ExclusiveGroup that the button belongs to. + + The default value is \c null. */ + property ExclusiveGroup exclusiveGroup: null + + /*! This property holds the associated button action. + + If a button has an action associated, the action defines the + button's properties like checked, text, tooltip etc. + + When an action is set, it's still possible to override the \l text, + \l tooltip, \l iconSource, and \l iconName properties. + + The default value is \c null. */ + property Action action: null + + /*! This property specifies whether the button should gain active focus when pressed. + + The default value is \c false. */ + property bool activeFocusOnPress: false + + /*! This property holds the text shown on the button. If the button has no + text, the \l text property will be an empty string. + + The default value is the empty string. + */ + property string text: action ? action.text : "" + + /*! This property holds the button tooltip. */ + property string tooltip: action ? (action.tooltip || StyleHelpers.removeMnemonics(action.text)) : "" + + /*! This property holds the icon shown on the button. If the button has no + icon, the iconSource property will be an empty string. + + The default value is the empty string. + */ + property url iconSource: action ? action.iconSource : "" + + /*! The image label source as theme name. + When an icon from the platform icon theme is found, this takes + precedence over iconSource. + */ + property string iconName: action ? action.iconName : "" + + /*! \internal */ + property color __textColor: syspal.text + /*! \internal */ + property string __position: "only" + /*! \internal */ + readonly property bool __iconOverriden: button.action && (button.action.iconSource !== button.iconSource || button.action.iconName !== button.iconName) + /*! \internal */ + property Action __action: action || ownAction + /*! \internal */ + readonly property Action __iconAction: __iconOverriden ? ownAction : __action + + /*! \internal */ + onExclusiveGroupChanged: { + if (exclusiveGroup) + exclusiveGroup.bindCheckable(button) + } + + Accessible.role: Accessible.Button + Accessible.description: tooltip + + /*! \internal */ + function accessiblePressAction() { + __action.trigger() + } + + Action { + id: ownAction + iconSource: !button.action || __iconOverriden ? button.iconSource : "" + iconName: !button.action || __iconOverriden ? button.iconName : "" + } + + Connections { + target: __action + onTriggered: button.clicked() + } + + activeFocusOnTab: true + + 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; + __action.trigger() + } + } + + MouseArea { + id: behavior + property bool keyPressed: false + property bool effectivePressed: pressed && containsMouse || keyPressed + + anchors.fill: parent + hoverEnabled: true + enabled: !keyPressed + + onReleased: if (containsMouse) __action.trigger() + onExited: Tooltip.hideText() + onCanceled: Tooltip.hideText() + onPressed: { + if (activeFocusOnPress) + button.forceActiveFocus() + if (button.checkable && !button.action && !(button.checked && button.exclusiveGroup)) + button.checked = !button.checked + } + + Timer { + interval: 1000 + running: behavior.containsMouse && !pressed && tooltip.length + onTriggered: Tooltip.showText(behavior, Qt.point(behavior.mouseX, behavior.mouseY), tooltip) + } + } + + /*! \internal */ + property var __behavior: behavior + + SystemPalette { id: syspal } + + states: [ + State { + name: "boundAction" + when: action !== null + PropertyChanges { + target: button + enabled: action.enabled + checkable: action.checkable + checked: action.checked + } + } + ] +} diff --git a/src/controls/Private/Control.qml b/src/controls/Private/Control.qml new file mode 100644 index 00000000..05916c0a --- /dev/null +++ b/src/controls/Private/Control.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ +import QtQuick 2.1 +import QtQuick.Controls.Styles 1.0 + +/*! + \qmltype Control + \internal + \qmlabstract + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +FocusScope { + id: root + + /*! \qmlproperty Component Control::style + + The style Component for this control. + \sa {Qt Quick Controls Styles QML Types} + + */ + property Component style + + /*! \internal */ + property QtObject __style: styleLoader.item + + /*! \internal */ + property Item __panel: panelLoader.item + + /*! \internal */ + property var styleHints + + implicitWidth: __panel ? __panel.implicitWidth: 0 + implicitHeight: __panel ? __panel.implicitHeight: 0 + activeFocusOnTab: false + + /*! \internal */ + property alias __styleData: styleLoader.styleData + + Loader { + id: panelLoader + anchors.fill: parent + sourceComponent: __style ? __style.panel : null + onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", root) + Loader { + id: styleLoader + sourceComponent: style + property Item __control: root + property QtObject styleData: null + onStatusChanged: { + if (status === Loader.Error) + console.error("Failed to load Style for", root) + } + } + } +} diff --git a/src/controls/Private/FocusFrame.qml b/src/controls/Private/FocusFrame.qml new file mode 100644 index 00000000..0bf9174a --- /dev/null +++ b/src/controls/Private/FocusFrame.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Private 1.0 + +/*! + \qmltype FocusFrame + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +Item { + id: root + activeFocusOnTab: false + Accessible.role: Accessible.StatusBar + + anchors.topMargin: focusMargin + anchors.leftMargin: focusMargin + anchors.rightMargin: focusMargin + anchors.bottomMargin: focusMargin + + property int focusMargin: loader.item ? loader.item.margin : -3 + + Loader { + id: loader + z: 2 + anchors.fill: parent + sourceComponent: Qt.createComponent(Settings.style + "/FocusFrameStyle.qml", root) + } +} diff --git a/src/controls/Private/ModalPopupBehavior.qml b/src/controls/Private/ModalPopupBehavior.qml new file mode 100644 index 00000000..1c6db2ff --- /dev/null +++ b/src/controls/Private/ModalPopupBehavior.qml @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 + +// KNOWN ISSUES +// none + +/*! + \qmltype ModalPopupBehavior + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +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/controls/Private/ScrollBar.qml b/src/controls/Private/ScrollBar.qml new file mode 100644 index 00000000..c21d6562 --- /dev/null +++ b/src/controls/Private/ScrollBar.qml @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Private 1.0 + +/*! + \qmltype ScrollBar + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +Item { + id: scrollbar + + property bool isTransient: false + property bool active: false + property int orientation: Qt.Horizontal + property alias minimumValue: slider.minimumValue + property alias maximumValue: slider.maximumValue + property alias value: slider.value + + activeFocusOnTab: false + + Accessible.role: Accessible.ScrollBar + implicitWidth: panelLoader.implicitWidth + implicitHeight: panelLoader.implicitHeight + + property bool upPressed + property bool downPressed + property bool pageUpPressed + property bool pageDownPressed + property bool handlePressed + + + property Item __panel: panelLoader.item + Loader { + id: panelLoader + anchors.fill: parent + sourceComponent: __style ? __style.__scrollbar : null + onStatusChanged: if (status === Loader.Error) console.error("Failed to load Style for", root) + property alias __control: scrollbar + property QtObject __styleData: QtObject { + readonly property alias horizontal: internal.horizontal + readonly property alias upPressed: scrollbar.upPressed + readonly property alias downPressed: scrollbar.downPressed + readonly property alias handlePressed: scrollbar.handlePressed + } + } + + MouseArea { + id: internal + property bool horizontal: orientation === Qt.Horizontal + property int pageStep: internal.horizontal ? width : height + property int singleStep: 20 + property bool scrollToClickposition: internal.scrollToClickPosition + anchors.fill: parent + cursorShape: __panel.visible ? Qt.ArrowCursor : Qt.IBeamCursor // forces a cursor change + + property bool autoincrement: false + property bool scrollToClickPosition: __style ? __style.scrollToClickedPosition : 0 + + // Update hover item + onEntered: if (!pressed) __panel.activeControl = __panel.hitTest(mouseX, mouseY) + onExited: if (!pressed) __panel.activeControl = "none" + onMouseXChanged: if (!pressed) __panel.activeControl = __panel.hitTest(mouseX, mouseY) + hoverEnabled: true + + property var pressedX + property var 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: { + if (upPressed && internal.containsMouse) + internal.decrement(); + else if (downPressed && internal.containsMouse) + internal.increment(); + else if (pageUpPressed) + internal.decrementPage(); + else if (pageDownPressed) + internal.incrementPage(); + } + } + + onPositionChanged: { + if (handlePressed) { + if (!horizontal) + slider.position = oldPosition + (mouseY - pressedY) + else + slider.position = oldPosition + (mouseX - pressedX) + } + } + + onPressed: { + __panel.activeControl = __panel.hitTest(mouseX, mouseY) + scrollToClickposition = scrollToClickPosition + var handleRect = __panel.subControlRect("handle") + grooveSize = horizontal ? __panel.subControlRect("groove").width - + handleRect.width: + __panel.subControlRect("groove").height - + handleRect.height; + if (__panel.activeControl === "handle") { + pressedX = mouseX; + pressedY = mouseY; + handlePressed = true; + oldPosition = slider.position; + } else if (__panel.activeControl === "up") { + decrement(); + upPressed = Qt.binding(function() {return containsMouse}); + } else if (__panel.activeControl === "down") { + increment(); + downPressed = Qt.binding(function() {return containsMouse}); + } else if (!scrollToClickposition){ + if (__panel.activeControl === "upPage") { + decrementPage(); + pageUpPressed = true; + } else if (__panel.activeControl === "downPage") { + incrementPage(); + pageDownPressed = true; + } + } else { + slider.position = horizontal ? mouseX - handleRect.width/2 + : mouseY - handleRect.height/2 + } + } + + onReleased: { + __panel.activeControl = __panel.hitTest(mouseX, mouseY); + autoincrement = false; + upPressed = false; + downPressed = false; + handlePressed = false; + pageUpPressed = false; + pageDownPressed = false; + } + + onWheel: { + var stepCount = -(wheel.angleDelta.x ? wheel.angleDelta.x : wheel.angleDelta.y) / 120 + if (stepCount != 0) { + if (wheel.modifiers & Qt.ControlModifier || wheel.modifiers & Qt.ShiftModifier) + incrementPage(stepCount) + else + increment(stepCount) + } + } + + function incrementPage(stepCount) { + value = boundValue(value + getSteps(pageStep, stepCount)) + } + + function decrementPage(stepCount) { + value = boundValue(value - getSteps(pageStep, stepCount)) + } + + function increment(stepCount) { + value = boundValue(value + getSteps(singleStep, stepCount)) + } + + function decrement(stepCount) { + value = boundValue(value - getSteps(singleStep, stepCount)) + } + + function boundValue(val) { + return Math.min(Math.max(val, minimumValue), maximumValue) + } + + function getSteps(step, count) { + if (count) + step *= count + return step + } + + RangeModel { + id: slider + minimumValue: 0.0 + maximumValue: 1.0 + value: 0 + stepSize: 0.0 + inverted: false + positionAtMaximum: internal.grooveSize + } + } +} diff --git a/src/controls/Private/ScrollViewHelper.qml b/src/controls/Private/ScrollViewHelper.qml new file mode 100644 index 00000000..791c5e02 --- /dev/null +++ b/src/controls/Private/ScrollViewHelper.qml @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Private 1.0 + +/*! + \qmltype ScrollViewHeader + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +Item { + id: wheelarea + + property alias horizontalScrollBar: hscrollbar + property alias verticalScrollBar: vscrollbar + property bool blockUpdates: false + property int availableHeight + property int availableWidth + property int contentHeight + property int contentWidth + property real originX + property real originY + + property int leftMargin: outerFrame ? root.__style.padding.left : 0 + property int rightMargin: outerFrame ? root.__style.padding.right : 0 + property int topMargin: outerFrame ? root.__style.padding.top : 0 + property int bottomMargin: outerFrame ? root.__style.padding.bottom : 0 + + anchors.fill: parent + + property bool recursionGuard: false + + function doLayout() { + if (!recursionGuard) { + recursionGuard = true + wheelarea.availableWidth = viewport.width + wheelarea.availableHeight = viewport.height + wheelarea.contentWidth = flickableItem !== null ? flickableItem.contentWidth : 0 + wheelarea.contentHeight = flickableItem !== null ? flickableItem.contentHeight : 0 + wheelarea.originX = flickableItem !== null ? flickableItem.originX : 0 + wheelarea.originY = flickableItem !== null ? flickableItem.originY : 0 + recursionGuard = false + } + } + + Connections { + target: viewport + onWidthChanged: doLayout() + onHeightChanged: doLayout() + } + + Connections { + target: flickableItem + onContentWidthChanged: doLayout() + onContentHeightChanged: doLayout() + } + + Connections { + target: flickableItem + onContentXChanged: { + hscrollbar.flash() + vscrollbar.flash() + } + onContentYChanged: { + hscrollbar.flash() + vscrollbar.flash() + } + } + + Loader { + id: cornerFill + z: 1 + sourceComponent: __style.corner + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.bottomMargin: bottomMargin + anchors.rightMargin: rightMargin + width: visible ? vscrollbar.width : 0 + height: visible ? hscrollbar.height : 0 + visible: hscrollbar.visible && !hscrollbar.isTransient && vscrollbar.visible && !vscrollbar.isTransient + } + + ScrollBar { + id: hscrollbar + isTransient: !!__panel && !!__panel.transient + active: !!__panel && (__panel.sunken || __panel.activeControl !== "none") + enabled: !isTransient || __panel.visible + orientation: Qt.Horizontal + visible: contentWidth > availableWidth + height: visible ? implicitHeight : 0 + z: 1 + maximumValue: contentWidth > availableWidth ? originX + contentWidth - availableWidth : 0 + minimumValue: originX + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: cornerFill.left + anchors.leftMargin: leftMargin + anchors.bottomMargin: bottomMargin + onValueChanged: { + if (!blockUpdates) { + flickableItem.contentX = value + } + } + Binding { + target: hscrollbar.__panel + property: "raised" + value: vscrollbar.active + when: hscrollbar.isTransient + } + Binding { + target: hscrollbar.__panel + property: "visible" + value: true + when: !hscrollbar.isTransient + } + function flash() { + if (hscrollbar.isTransient) { + hscrollbar.__panel.on = true + hscrollbar.__panel.visible = true + } + } + } + + ScrollBar { + id: vscrollbar + isTransient: !!__panel && !!__panel.transient + active: !!__panel && (__panel.sunken || __panel.activeControl !== "none") + enabled: !isTransient || __panel.visible + orientation: Qt.Vertical + visible: contentHeight > availableHeight + width: visible ? implicitWidth : 0 + z: 1 + anchors.bottom: cornerFill.top + maximumValue: contentHeight > availableHeight ? originY + contentHeight - availableHeight + __viewTopMargin : 0 + minimumValue: originY + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: __scrollBarTopMargin + topMargin + anchors.rightMargin: rightMargin + onValueChanged: { + if (flickableItem && !blockUpdates && enabled) { + flickableItem.contentY = value + } + } + Binding { + target: vscrollbar.__panel + property: "raised" + value: hscrollbar.active + when: vscrollbar.isTransient + } + Binding { + target: vscrollbar.__panel + property: "visible" + value: true + when: !vscrollbar.isTransient + } + function flash() { + if (vscrollbar.isTransient) { + vscrollbar.__panel.on = true + vscrollbar.__panel.visible = true + } + } + } +} diff --git a/src/controls/Private/StackView.js b/src/controls/Private/StackView.js new file mode 100644 index 00000000..fa9bb08e --- /dev/null +++ b/src/controls/Private/StackView.js @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +var stackView = []; + +function push(p) +{ + if (!p) + return + stackView.push(p) + __depth++ + return p +} + +function pop() +{ + if (stackView.length === 0) + return null + var p = stackView.pop() + __depth-- + return p +} + +function current() +{ + if (stackView.length === 0) + return null + return stackView[stackView.length-1] +} + diff --git a/src/controls/Private/StackViewSlideDelegate.qml b/src/controls/Private/StackViewSlideDelegate.qml new file mode 100644 index 00000000..6cc1c683 --- /dev/null +++ b/src/controls/Private/StackViewSlideDelegate.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 + +/*! + \qmltype StackViewSlideTransition + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +StackViewDelegate { + id: root + + property bool horizontal: true + + function getTransition(properties) + { + return root[horizontal ? "horizontalSlide" : "verticalSlide"][properties.name] + } + + function transitionFinished(properties) + { + properties.exitItem.x = 0 + properties.exitItem.y = 0 + } + + property QtObject horizontalSlide: QtObject { + property Component pushTransition: StackViewTransition { + PropertyAnimation { + target: enterItem + property: "x" + from: target.width + to: 0 + duration: 300 + } + PropertyAnimation { + target: exitItem + property: "x" + from: 0 + to: -target.width + duration: 300 + } + } + + property Component popTransition: StackViewTransition { + PropertyAnimation { + target: enterItem + property: "x" + from: -target.width + to: 0 + duration: 300 + } + PropertyAnimation { + target: exitItem + property: "x" + from: 0 + to: target.width + duration: 300 + } + } + property Component replaceTransition: pushTransition + } + + property QtObject verticalSlide: QtObject { + property Component pushTransition: StackViewTransition { + PropertyAnimation { + target: enterItem + property: "y" + from: target.height + to: 0 + duration: 300 + } + PropertyAnimation { + target: exitItem + property: "y" + from: 0 + to: -target.height + duration: 300 + } + } + + property Component popTransition: StackViewTransition { + PropertyAnimation { + target: enterItem + property: "y" + from: -target.height + to: 0 + duration: 300 + } + PropertyAnimation { + target: exitItem + property: "y" + from: 0 + to: target.height + duration: 300 + } + property Component replaceTransition: pushTransition + } + } +} diff --git a/src/controls/Private/Style.qml b/src/controls/Private/Style.qml new file mode 100644 index 00000000..6b4c08ef --- /dev/null +++ b/src/controls/Private/Style.qml @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Private 1.0 + +/*! + \qmltype Style + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ + +AbstractStyle { + /*! The control attached to this style */ + readonly property Item control: __control + + /*! \internal */ + property var __syspal: SystemPalette { + colorGroup: control.enabled ? + SystemPalette.Active : SystemPalette.Disabled + } +} diff --git a/src/controls/Private/TabBar.qml b/src/controls/Private/TabBar.qml new file mode 100644 index 00000000..8341c922 --- /dev/null +++ b/src/controls/Private/TabBar.qml @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 + +/*! + \qmltype TabBar + \internal + \inqmlmodule QtQuick.Controls.Private 1.0 +*/ +FocusScope { + id: tabbar + height: Math.max(tabrow.height, Math.max(leftCorner.height, rightCorner.height)) + width: tabView.width + + activeFocusOnTab: true + + Keys.onRightPressed: { + if (tabView && tabView.currentIndex < tabView.count - 1) + tabView.currentIndex = tabView.currentIndex + 1 + } + Keys.onLeftPressed: { + if (tabView && tabView.currentIndex > 0) + tabView.currentIndex = tabView.currentIndex - 1 + } + + onTabViewChanged: parent = tabView + visible: tabView ? tabView.tabsVisible : true + + property var tabView + property var style + property var styleItem: tabView.__styleItem ? tabView.__styleItem : null + + property bool tabsMovable: styleItem ? styleItem.tabsMovable : false + + property int tabsAlignment: styleItem ? styleItem.tabsAlignment : Qt.AlignLeft + + property int tabOverlap: styleItem ? styleItem.tabOverlap : 0 + + property int elide: Text.ElideRight + + property real availableWidth: tabbar.width - leftCorner.width - rightCorner.width + + property var __selectedTabRect + + function tab(index) { + for (var i = 0; i < tabrow.children.length; ++i) { + if (tabrow.children[i].tabindex == index) { + return tabrow.children[i] + } + } + return null; + } + + /*! \internal */ + function __isAncestorOf(item, child) { + //TODO: maybe removed from 5.2 if the function was merged in qtdeclarative + if (child === item) + return false; + + while (child) { + child = child.parent; + if (child === item) + return true; + } + return false; + } + Loader { + id: background + anchors.fill: parent + sourceComponent: styleItem ? styleItem.tabBar : undefined + } + + ListView { + id: tabrow + objectName: "tabrow" + Accessible.role: Accessible.PageTabList + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + spacing: -tabOverlap + orientation: Qt.Horizontal + interactive: false + focus: true + + width: Math.min(availableWidth, count ? contentWidth : availableWidth) + height: currentItem ? currentItem.height : 0 + + highlightMoveDuration: 0 + currentIndex: tabView.currentIndex + onCurrentIndexChanged: tabrow.positionViewAtIndex(currentIndex, ListView.Contain) + + moveDisplaced: Transition { + NumberAnimation { + property: "x" + duration: 125 + easing.type: Easing.OutQuad + } + } + + states: [ + State { + name: "left" + when: tabsAlignment === Qt.AlignLeft + AnchorChanges { target:tabrow ; anchors.left: parent.left } + PropertyChanges { target:tabrow ; anchors.leftMargin: leftCorner.width } + }, + State { + name: "center" + when: tabsAlignment === Qt.AlignHCenter + AnchorChanges { target:tabrow ; anchors.horizontalCenter: tabbar.horizontalCenter } + }, + State { + name: "right" + when: tabsAlignment === Qt.AlignRight + AnchorChanges { target:tabrow ; anchors.right: parent.right } + PropertyChanges { target:tabrow ; anchors.rightMargin: rightCorner.width } + } + ] + + model: tabView.__tabs + + delegate: MouseArea { + id: tabitem + objectName: "mousearea" + hoverEnabled: true + focus: true + + Binding { + target: tabbar + when: selected + property: "__selectedTabRect" + value: Qt.rect(x, y, width, height) + } + + drag.target: tabsMovable ? tabloader : null + drag.axis: Drag.XAxis + drag.minimumX: drag.active ? 0 : -Number.MAX_VALUE + drag.maximumX: tabrow.width - tabitem.width + + property int tabindex: index + property bool selected : tabView.currentIndex === index + property string title: modelData.title + property bool nextSelected: tabView.currentIndex === index + 1 + property bool previousSelected: tabView.currentIndex === index - 1 + + z: selected ? 1 : -index + implicitWidth: tabloader.implicitWidth + implicitHeight: tabloader.implicitHeight + + function changeTab() { + tabView.currentIndex = index; + var next = tabbar.nextItemInFocusChain(true); + if (__isAncestorOf(tabView.getTab(currentIndex), next)) + next.forceActiveFocus(); + } + + onClicked: { + if (tabrow.interactive) { + changeTab() + } + } + onPressed: { + if (!tabrow.interactive) { + changeTab() + } + } + + Loader { + id: tabloader + + property Item control: tabView + property int index: tabindex + + property QtObject styleData: QtObject { + readonly property alias index: tabitem.tabindex + readonly property alias selected: tabitem.selected + readonly property alias title: tabitem.title + readonly property alias nextSelected: tabitem.nextSelected + readonly property alias previsousSelected: tabitem.previousSelected + readonly property alias hovered: tabitem.containsMouse + readonly property bool activeFocus: tabbar.activeFocus + readonly property real availableWidth: tabbar.availableWidth + } + + sourceComponent: loader.item ? loader.item.tab : null + + Drag.keys: "application/x-tabbartab" + Drag.active: tabitem.drag.active + Drag.source: tabitem + + property real __prevX: 0 + property real __dragX: 0 + onXChanged: { + if (Drag.active) { + // keep track for the snap back animation + __dragX = tabitem.mapFromItem(tabrow, tabloader.x, 0).x + + // when moving to the left, the hot spot is the left edge and vice versa + Drag.hotSpot.x = x < __prevX ? 0 : width + __prevX = x + } + } + + width: tabitem.width + state: Drag.active ? "drag" : "" + + transitions: [ + Transition { + to: "drag" + PropertyAction { target: tabloader; property: "parent"; value: tabrow } + }, + Transition { + from: "drag" + SequentialAnimation { + PropertyAction { target: tabloader; property: "parent"; value: tabitem } + NumberAnimation { + target: tabloader + duration: 50 + easing.type: Easing.OutQuad + property: "x" + from: tabloader.__dragX + to: 0 + } + } + } + ] + } + + Accessible.role: Accessible.PageTab + Accessible.name: modelData.title + } + } + + Loader { + id: leftCorner + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + sourceComponent: styleItem ? styleItem.leftCorner : undefined + width: item ? item.implicitWidth : 0 + height: item ? item.implicitHeight : 0 + } + + Loader { + id: rightCorner + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + sourceComponent: styleItem ? styleItem.rightCorner : undefined + width: item ? item.implicitWidth : 0 + height: item ? item.implicitHeight : 0 + } + + DropArea { + anchors.fill: tabrow + keys: "application/x-tabbartab" + onPositionChanged: { + var source = drag.source + var target = tabrow.itemAt(drag.x, drag.y) + if (source && target && source !== target) { + source = source.drag.target + target = target.drag.target + var center = target.parent.x + target.width / 2 + if ((source.index > target.index && source.x < center) + || (source.index < target.index && source.x + source.width > center)) + tabView.moveTab(source.index, target.index) + } + } + } +} diff --git a/src/controls/Private/private.pri b/src/controls/Private/private.pri new file mode 100644 index 00000000..bd001c0a --- /dev/null +++ b/src/controls/Private/private.pri @@ -0,0 +1,42 @@ +HEADERS += \ + $$PWD/qquicktooltip_p.h \ + $$PWD/qquickspinboxvalidator_p.h \ + $$PWD/qquickrangemodel_p.h \ + $$PWD/qquickrangemodel_p_p.h \ + $$PWD/qquickcontrolsettings_p.h \ + $$PWD/qquickwheelarea_p.h \ + $$PWD/qquickabstractstyle_p.h \ + $$PWD/qquickpadding_p.h \ + $$PWD/qquickcontrolsprivate_p.h + +SOURCES += \ + $$PWD/qquicktooltip.cpp \ + $$PWD/qquickspinboxvalidator.cpp \ + $$PWD/qquickrangemodel.cpp \ + $$PWD/qquickcontrolsettings.cpp \ + $$PWD/qquickwheelarea.cpp \ + $$PWD/qquickabstractstyle.cpp + +qtHaveModule(widgets) { + QT += widgets + HEADERS += $$PWD/qquickstyleitem_p.h + SOURCES += $$PWD/qquickstyleitem.cpp +} + +# private qml files +PRIVATE_QML_FILES += \ + $$PWD/AbstractCheckable.qml \ + $$PWD/TabBar.qml \ + $$PWD/BasicButton.qml \ + $$PWD/Control.qml \ + $$PWD/Style.qml \ + $$PWD/style.js \ + $$PWD/ModalPopupBehavior.qml \ + $$PWD/StackViewSlideDelegate.qml \ + $$PWD/StackView.js \ + $$PWD/ScrollViewHelper.qml \ + $$PWD/ScrollBar.qml \ + $$PWD/FocusFrame.qml \ + $$PWD/qmldir + +QML_FILES += $$PRIVATE_QML_FILES diff --git a/src/controls/Private/qmldir b/src/controls/Private/qmldir new file mode 100644 index 00000000..1ee66461 --- /dev/null +++ b/src/controls/Private/qmldir @@ -0,0 +1,18 @@ +module QtQuick.Controls.Private +AbstractCheckable 1.0 AbstractCheckable.qml +Control 1.0 Control.qml +FocusFrame 1.0 FocusFrame.qml +Margins 1.0 Margins.qml +BasicButton 1.0 BasicButton.qml +ScrollBar 1.0 ScrollBar.qml +ScrollViewHelper 1.0 ScrollViewHelper.qml +Style 1.0 Style.qml +TabBar 1.0 TabBar.qml +StackViewSlideDelegate 1.0 StackViewSlideDelegate.qml +StyleHelpers 1.0 style.js +JSArray 1.0 StackView.js +GroupBoxStyle 1.0 ../Styles/Base/GroupBoxStyle.qml +SpinBoxStyle 1.0 ../Styles/Base/SpinBoxStyle.qml +ToolBarStyle 1.0 ../Styles/Base/ToolBarStyle.qml +StatusBarStyle 1.0 ../Styles/Base/StatusBarStyle.qml +ToolButtonStyle 1.0 ../Styles/Base/ToolButtonStyle.qml diff --git a/src/controls/Private/qquickabstractstyle.cpp b/src/controls/Private/qquickabstractstyle.cpp new file mode 100644 index 00000000..eba57b03 --- /dev/null +++ b/src/controls/Private/qquickabstractstyle.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickabstractstyle_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype AbstractStyle + \instantiates QQuickAbstractStyle + \qmlabstract + \internal +*/ + +/*! + \qmlproperty int AbstractStyle::padding.top + \qmlproperty int AbstractStyle::padding.left + \qmlproperty int AbstractStyle::padding.right + \qmlproperty int AbstractStyle::padding.bottom + + This grouped property holds the \c top, \c left, \c right and \c bottom padding. +*/ + +QQuickAbstractStyle::QQuickAbstractStyle(QObject *parent) : QObject(parent) +{ +} + +QQmlListProperty<QObject> QQuickAbstractStyle::data() +{ + return QQmlListProperty<QObject>(this, 0, &QQuickAbstractStyle::data_append, &QQuickAbstractStyle::data_count, + &QQuickAbstractStyle::data_at, &QQuickAbstractStyle::data_clear); +} + +void QQuickAbstractStyle::data_append(QQmlListProperty<QObject> *list, QObject *object) +{ + if (QQuickAbstractStyle *style = qobject_cast<QQuickAbstractStyle *>(list->object)) + style->m_data.append(object); +} + +int QQuickAbstractStyle::data_count(QQmlListProperty<QObject> *list) +{ + if (QQuickAbstractStyle *style = qobject_cast<QQuickAbstractStyle *>(list->object)) + return style->m_data.count(); + return 0; +} + +QObject *QQuickAbstractStyle::data_at(QQmlListProperty<QObject> *list, int index) +{ + if (QQuickAbstractStyle *style = qobject_cast<QQuickAbstractStyle *>(list->object)) + return style->m_data.at(index); + return 0; +} + +void QQuickAbstractStyle::data_clear(QQmlListProperty<QObject> *list) +{ + if (QQuickAbstractStyle *style = qobject_cast<QQuickAbstractStyle *>(list->object)) + style->m_data.clear(); +} + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquickabstractstyle_p.h b/src/controls/Private/qquickabstractstyle_p.h new file mode 100644 index 00000000..13764053 --- /dev/null +++ b/src/controls/Private/qquickabstractstyle_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKABSTRACTSTYLE_H +#define QQUICKABSTRACTSTYLE_H + +#include <QtCore/qobject.h> +#include <QtQml/qqmllist.h> +#include "qquickpadding_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickAbstractStyle : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QQuickPadding* padding READ padding CONSTANT) + Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false) + Q_CLASSINFO("DefaultProperty", "data") + +public: + QQuickAbstractStyle(QObject *parent = 0); + + QQuickPadding* padding() { return &m_padding; } + + QQmlListProperty<QObject> data(); + +private: + static void data_append(QQmlListProperty<QObject> *list, QObject *object); + static int data_count(QQmlListProperty<QObject> *list); + static QObject *data_at(QQmlListProperty<QObject> *list, int index); + static void data_clear(QQmlListProperty<QObject> *list); + + QQuickPadding m_padding; + QList<QObject *> m_data; +}; + +QT_END_NAMESPACE + +#endif // QQUICKABSTRACTSTYLE_H diff --git a/src/controls/Private/qquickcontrolsettings.cpp b/src/controls/Private/qquickcontrolsettings.cpp new file mode 100644 index 00000000..e2daa17f --- /dev/null +++ b/src/controls/Private/qquickcontrolsettings.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickcontrolsettings_p.h" +#include <qquickitem.h> +#include <qcoreapplication.h> +#include <qqmlengine.h> +#include <qdir.h> + +QT_BEGIN_NAMESPACE + +static QString defaultStyleName() +{ + //Only enable QStyle support when we are using QApplication + if (QCoreApplication::instance()->inherits("QApplication")) + return QLatin1String("Desktop"); + return QLatin1String("Base"); +} + +static QString styleImportName() +{ + QString name = qgetenv("QT_QUICK_CONTROLS_STYLE"); + if (name.isEmpty()) + name = defaultStyleName(); + return QFileInfo(name).fileName(); +} + +static QString styleImportPath(QQmlEngine *engine, const QString &styleName) +{ + QString path = qgetenv("QT_QUICK_CONTROLS_STYLE"); + QFileInfo info(path); + if (info.isRelative()) { + foreach (const QString &import, engine->importPathList()) { + QDir dir(import + QLatin1String("/QtQuick/Controls/Styles")); + if (dir.exists(styleName)) { + path = dir.absolutePath(); + break; + } + } + } else { + path = info.absolutePath(); + } + return path; +} + +QQuickControlSettings::QQuickControlSettings(QQmlEngine *engine) +{ + m_name = styleImportName(); + m_path = styleImportPath(engine, m_name); + + if (!QFile::exists(styleFilePath())) { + QString unknownStyle = m_name; + m_name = defaultStyleName(); + m_path = styleImportPath(engine, m_name); + qWarning() << "WARNING: Cannot find style" << unknownStyle << "- fallback:" << styleFilePath(); + } + + connect(this, SIGNAL(styleNameChanged()), SIGNAL(styleChanged())); + connect(this, SIGNAL(stylePathChanged()), SIGNAL(styleChanged())); +} + +QUrl QQuickControlSettings::style() const +{ + return QUrl::fromLocalFile(styleFilePath()); +} + +QString QQuickControlSettings::styleName() const +{ + return m_name; +} + +void QQuickControlSettings::setStyleName(const QString &name) +{ + if (m_name != name) { + m_name = name; + emit styleNameChanged(); + } +} + +QString QQuickControlSettings::stylePath() const +{ + return m_path; +} + +void QQuickControlSettings::setStylePath(const QString &path) +{ + if (m_path != path) { + m_path = path; + emit stylePathChanged(); + } +} + +QString QQuickControlSettings::styleFilePath() const +{ + return m_path + QLatin1Char('/') + m_name; +} + +extern Q_GUI_EXPORT int qt_defaultDpiX(); + +qreal QQuickControlSettings::dpiScaleFactor() const +{ +#ifndef Q_OS_MAC + return (qreal(qt_defaultDpiX()) / 96.0); +#endif + return 1.0; +} + + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquickcontrolsettings_p.h b/src/controls/Private/qquickcontrolsettings_p.h new file mode 100644 index 00000000..8ff0ecbf --- /dev/null +++ b/src/controls/Private/qquickcontrolsettings_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKCONTROLSETTINGS_P_H +#define QQUICKCONTROLSETTINGS_P_H + +#include <QtCore/qurl.h> +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class QQmlEngine; + +class QQuickControlSettings : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl style READ style NOTIFY styleChanged) + Q_PROPERTY(QString styleName READ styleName WRITE setStyleName NOTIFY styleNameChanged) + Q_PROPERTY(QString stylePath READ stylePath WRITE setStylePath NOTIFY stylePathChanged) + Q_PROPERTY(qreal dpiScaleFactor READ dpiScaleFactor CONSTANT) + +public: + QQuickControlSettings(QQmlEngine *engine); + + QUrl style() const; + + QString styleName() const; + void setStyleName(const QString &name); + + QString stylePath() const; + void setStylePath(const QString &path); + + qreal dpiScaleFactor() const; + +signals: + void styleChanged(); + void styleNameChanged(); + void stylePathChanged(); + +private: + QString styleFilePath() const; + + QString m_name; + QString m_path; +}; + +QT_END_NAMESPACE + +#endif // QQUICKCONTROLSETTINGS_P_H diff --git a/src/controls/Private/qquickcontrolsprivate_p.h b/src/controls/Private/qquickcontrolsprivate_p.h new file mode 100644 index 00000000..068b2a21 --- /dev/null +++ b/src/controls/Private/qquickcontrolsprivate_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKCONTROLSPRIVATE_P_H +#define QQUICKCONTROLSPRIVATE_P_H + +#include "qqml.h" + +QT_BEGIN_NAMESPACE + +class QQuickControlsPrivate { + +public: + + inline static QObject *registerTooltipModule(QQmlEngine *engine, QJSEngine *jsEngine) + { + Q_UNUSED(engine); + Q_UNUSED(jsEngine); + return new QQuickTooltip(); + } + + inline static QObject *registerSettingsModule(QQmlEngine *engine, QJSEngine *jsEngine) + { + Q_UNUSED(engine); + Q_UNUSED(jsEngine); + return new QQuickControlSettings(engine); + } + +}; + +QT_END_NAMESPACE + +#endif // QQUICKCONTROLSPRIVATE_P_H diff --git a/src/controls/Private/qquickpadding_p.h b/src/controls/Private/qquickpadding_p.h new file mode 100644 index 00000000..1830df4c --- /dev/null +++ b/src/controls/Private/qquickpadding_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPADDING_H +#define QQUICKPADDING_H + +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class QQuickPadding : public QObject +{ + Q_OBJECT + + Q_PROPERTY(int left READ left WRITE setLeft NOTIFY leftChanged) + Q_PROPERTY(int top READ top WRITE setTop NOTIFY topChanged) + Q_PROPERTY(int right READ right WRITE setRight NOTIFY rightChanged) + Q_PROPERTY(int bottom READ bottom WRITE setBottom NOTIFY bottomChanged) + + int m_left; + int m_top; + int m_right; + int m_bottom; + +public: + QQuickPadding(QObject *parent = 0) : + QObject(parent), + m_left(0), + m_top(0), + m_right(0), + m_bottom(0) {} + + int left() const { return m_left; } + int top() const { return m_top; } + int right() const { return m_right; } + int bottom() const { return m_bottom; } + +public slots: + void setLeft(int arg) { if (m_left != arg) {m_left = arg; emit leftChanged();}} + void setTop(int arg) { if (m_top != arg) {m_top = arg; emit topChanged();}} + void setRight(int arg) { if (m_right != arg) {m_right = arg; emit rightChanged();}} + void setBottom(int arg) {if (m_bottom != arg) {m_bottom = arg; emit bottomChanged();}} + +signals: + void leftChanged(); + void topChanged(); + void rightChanged(); + void bottomChanged(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKPADDING_H diff --git a/src/controls/Private/qquickrangemodel.cpp b/src/controls/Private/qquickrangemodel.cpp new file mode 100644 index 00000000..ee1ade32 --- /dev/null +++ b/src/controls/Private/qquickrangemodel.cpp @@ -0,0 +1,524 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + 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 QQuickRangeModel. 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. +*/ + +#include "qquickrangemodel_p.h" +#include "qquickrangemodel_p_p.h" + +QT_BEGIN_NAMESPACE + +QQuickRangeModelPrivate::QQuickRangeModelPrivate(QQuickRangeModel *qq) + : q_ptr(qq) +{ +} + +QQuickRangeModelPrivate::~QQuickRangeModelPrivate() +{ +} + +void QQuickRangeModelPrivate::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 QQuickRangeModel. It takes into account the \l stepSize, + \l positionAtMinimum, \l positionAtMaximum properties + and \a position that is passed as parameter. +*/ + +qreal QQuickRangeModelPrivate::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 QQuickRangeModel. It takes into account the \l stepSize, + \l minimumValue, \l maximumValue properties + and \a value that is passed as parameter. +*/ + +qreal QQuickRangeModelPrivate::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 QQuickRangeModelPrivate::emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition) +{ + Q_Q(QQuickRangeModel); + + // 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 QQuickRangeModel with \a parent +*/ + +QQuickRangeModel::QQuickRangeModel(QObject *parent) + : QObject(parent), d_ptr(new QQuickRangeModelPrivate(this)) +{ + Q_D(QQuickRangeModel); + d->init(); +} + +/*! + \internal + Constructs a QQuickRangeModel with private class pointer \a dd and \a parent +*/ + +QQuickRangeModel::QQuickRangeModel(QQuickRangeModelPrivate &dd, QObject *parent) + : QObject(parent), d_ptr(&dd) +{ + Q_D(QQuickRangeModel); + d->init(); +} + +/*! + Destroys the QQuickRangeModel +*/ + +QQuickRangeModel::~QQuickRangeModel() +{ + 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 QQuickRangeModel::setPositionRange(qreal min, qreal max) +{ + Q_D(QQuickRangeModel); + + 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 QQuickRangeModel::setRange(qreal min, qreal max) +{ + Q_D(QQuickRangeModel); + + 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 QQuickRangeModel::minimumValue + \brief the minimum value that \l value can assume + + This property's default value is 0 +*/ + +void QQuickRangeModel::setMinimum(qreal min) +{ + Q_D(const QQuickRangeModel); + setRange(min, d->maximum); +} + +qreal QQuickRangeModel::minimum() const +{ + Q_D(const QQuickRangeModel); + return d->minimum; +} + +/*! + \property QQuickRangeModel::maximumValue + \brief the maximum value that \l value can assume + + This property's default value is 99 +*/ + +void QQuickRangeModel::setMaximum(qreal max) +{ + Q_D(const QQuickRangeModel); + // if the new maximum value is smaller than + // minimum, update minimum too + setRange(qMin(d->minimum, max), max); +} + +qreal QQuickRangeModel::maximum() const +{ + Q_D(const QQuickRangeModel); + return d->maximum; +} + +/*! + \property QQuickRangeModel::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 QQuickRangeModel::setStepSize(qreal stepSize) +{ + Q_D(QQuickRangeModel); + + 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 QQuickRangeModel::stepSize() const +{ + Q_D(const QQuickRangeModel); + 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 QQuickRangeModel::positionForValue(qreal value) const +{ + Q_D(const QQuickRangeModel); + + const qreal unconstrainedPosition = d->equivalentPosition(value); + return d->publicPosition(unconstrainedPosition); +} + +/*! + \property QQuickRangeModel::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 QQuickRangeModel::position() const +{ + Q_D(const QQuickRangeModel); + + // Return the internal position but observe boundaries and + // stepSize restrictions. + return d->publicPosition(d->pos); +} + +void QQuickRangeModel::setPosition(qreal newPosition) +{ + Q_D(QQuickRangeModel); + + 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 QQuickRangeModel::positionAtMinimum + \brief the minimum value that \l position can assume + + This property's default value is 0 +*/ + +void QQuickRangeModel::setPositionAtMinimum(qreal min) +{ + Q_D(QQuickRangeModel); + setPositionRange(min, d->posatmax); +} + +qreal QQuickRangeModel::positionAtMinimum() const +{ + Q_D(const QQuickRangeModel); + return d->posatmin; +} + +/*! + \property QQuickRangeModel::positionAtMaximum + \brief the maximum value that \l position can assume + + This property's default value is 0 +*/ + +void QQuickRangeModel::setPositionAtMaximum(qreal max) +{ + Q_D(QQuickRangeModel); + setPositionRange(d->posatmin, max); +} + +qreal QQuickRangeModel::positionAtMaximum() const +{ + Q_D(const QQuickRangeModel); + 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 QQuickRangeModel::valueForPosition(qreal position) const +{ + Q_D(const QQuickRangeModel); + + const qreal unconstrainedValue = d->equivalentValue(position); + return d->publicValue(unconstrainedValue); +} + +/*! + \property QQuickRangeModel::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 QQuickRangeModel::value() const +{ + Q_D(const QQuickRangeModel); + + // Return internal value but observe boundaries and + // stepSize restrictions + return d->publicValue(d->value); +} + +void QQuickRangeModel::setValue(qreal newValue) +{ + Q_D(QQuickRangeModel); + + 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 QQuickRangeModel::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 QQuickRangeModel::setInverted(bool inverted) +{ + Q_D(QQuickRangeModel); + 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 QQuickRangeModel::inverted() const +{ + Q_D(const QQuickRangeModel); + return d->inverted; +} + +/*! + Sets the \l value to \l minimumValue. +*/ + +void QQuickRangeModel::toMinimum() +{ + Q_D(const QQuickRangeModel); + setValue(d->minimum); +} + +/*! + Sets the \l value to \l maximumValue. +*/ + +void QQuickRangeModel::toMaximum() +{ + Q_D(const QQuickRangeModel); + setValue(d->maximum); +} + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquickrangemodel_p.h b/src/controls/Private/qquickrangemodel_p.h new file mode 100644 index 00000000..a15843d7 --- /dev/null +++ b/src/controls/Private/qquickrangemodel_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKRANGEMODEL_P_H +#define QQUICKRANGEMODEL_P_H + +#include <QtCore/qobject.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class QQuickRangeModelPrivate; + +class QQuickRangeModel : 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: + QQuickRangeModel(QObject *parent = 0); + virtual ~QQuickRangeModel(); + + 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: + QQuickRangeModel(QQuickRangeModelPrivate &dd, QObject *parent); + QQuickRangeModelPrivate* d_ptr; + +private: + Q_DISABLE_COPY(QQuickRangeModel) + Q_DECLARE_PRIVATE(QQuickRangeModel) + +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickRangeModel) + +#endif // QQUICKRANGEMODEL_P_H diff --git a/src/controls/Private/qquickrangemodel_p_p.h b/src/controls/Private/qquickrangemodel_p_p.h new file mode 100644 index 00000000..9ddf16c2 --- /dev/null +++ b/src/controls/Private/qquickrangemodel_p_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKRANGEMODEL_P_P_H +#define QQUICKRANGEMODEL_P_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 "qquickrangemodel_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickRangeModelPrivate +{ + Q_DECLARE_PUBLIC(QQuickRangeModel) +public: + QQuickRangeModelPrivate(QQuickRangeModel *qq); + virtual ~QQuickRangeModelPrivate(); + + void init(); + + qreal posatmin, posatmax; + qreal minimum, maximum, stepSize, pos, value; + + uint inverted : 1; + + QQuickRangeModel *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); +}; + +QT_END_NAMESPACE + +#endif // QQUICKRANGEMODEL_P_P_H diff --git a/src/controls/Private/qquickspinboxvalidator.cpp b/src/controls/Private/qquickspinboxvalidator.cpp new file mode 100644 index 00000000..a39a8deb --- /dev/null +++ b/src/controls/Private/qquickspinboxvalidator.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickspinboxvalidator_p.h" + +QT_BEGIN_NAMESPACE + +QQuickSpinBoxValidator::QQuickSpinBoxValidator(QObject *parent) + : QValidator(parent), m_value(0), m_step(1), m_initialized(false) +{ + m_validator.setTop(99); + m_validator.setBottom(0); + m_validator.setDecimals(0); + m_validator.setNotation(QDoubleValidator::StandardNotation); + + QLocale locale; + locale.setNumberOptions(QLocale::OmitGroupSeparator); + setLocale(locale); + + connect(this, SIGNAL(valueChanged()), this, SIGNAL(textChanged())); + connect(this, SIGNAL(minimumValueChanged()), this, SIGNAL(textChanged())); + connect(this, SIGNAL(maximumValueChanged()), this, SIGNAL(textChanged())); + connect(this, SIGNAL(decimalsChanged()), this, SIGNAL(textChanged())); + connect(this, SIGNAL(prefixChanged()), this, SIGNAL(textChanged())); + connect(this, SIGNAL(suffixChanged()), this, SIGNAL(textChanged())); +} + +QQuickSpinBoxValidator::~QQuickSpinBoxValidator() +{ +} + +QString QQuickSpinBoxValidator::text() const +{ + return m_prefix + locale().toString(m_value, 'f', m_validator.decimals()) + m_suffix; +} + +qreal QQuickSpinBoxValidator::value() const +{ + return m_value; +} + +void QQuickSpinBoxValidator::setValue(qreal value) +{ + if (m_initialized) { + value = qBound(minimumValue(), value, maximumValue()); + value = QString::number(value, 'f', m_validator.decimals()).toDouble(); + } + + if (m_value != value) { + m_value = value; + emit valueChanged(); + } +} + +qreal QQuickSpinBoxValidator::minimumValue() const +{ + return m_validator.bottom(); +} + +void QQuickSpinBoxValidator::setMinimumValue(qreal min) +{ + if (min != m_validator.bottom()) { + m_validator.setBottom(min); + emit minimumValueChanged(); + if (m_initialized) + setValue(m_value); + } +} + +qreal QQuickSpinBoxValidator::maximumValue() const +{ + return m_validator.top(); +} + +void QQuickSpinBoxValidator::setMaximumValue(qreal max) +{ + if (max != m_validator.top()) { + m_validator.setTop(max); + emit maximumValueChanged(); + if (m_initialized) + setValue(m_value); + } +} + +int QQuickSpinBoxValidator::decimals() const +{ + return m_validator.decimals(); +} + +void QQuickSpinBoxValidator::setDecimals(int decimals) +{ + if (decimals != m_validator.decimals()) { + m_validator.setDecimals(decimals); + emit decimalsChanged(); + if (m_initialized) + setValue(m_value); + } +} + +qreal QQuickSpinBoxValidator::stepSize() const +{ + return m_step; +} + +void QQuickSpinBoxValidator::setStepSize(qreal step) +{ + if (m_step != step) { + m_step = step; + emit stepSizeChanged(); + } +} + +QString QQuickSpinBoxValidator::prefix() const +{ + return m_prefix; +} + +void QQuickSpinBoxValidator::setPrefix(const QString &prefix) +{ + if (m_prefix != prefix) { + m_prefix = prefix; + emit prefixChanged(); + } +} + +QString QQuickSpinBoxValidator::suffix() const +{ + return m_suffix; +} + +void QQuickSpinBoxValidator::setSuffix(const QString &suffix) +{ + if (m_suffix != suffix) { + m_suffix = suffix; + emit suffixChanged(); + } +} + +void QQuickSpinBoxValidator::fixup(QString &input) const +{ + input.remove(locale().groupSeparator()); +} + +QValidator::State QQuickSpinBoxValidator::validate(QString &input, int &pos) const +{ + if (pos > 0 && pos < input.length()) { + if (input.at(pos - 1) == locale().groupSeparator()) + return QValidator::Invalid; + if (input.at(pos - 1) == locale().decimalPoint() && m_validator.decimals() == 0) + return QValidator::Invalid; + } + + if (!m_prefix.isEmpty() && !input.startsWith(m_prefix)) { + input.prepend(m_prefix); + pos += m_prefix.length(); + } + + if (!m_suffix.isEmpty() && !input.endsWith(m_suffix)) + input.append(m_suffix); + + QString value = input.mid(m_prefix.length(), input.length() - m_prefix.length() - m_suffix.length()); + int valuePos = pos - m_prefix.length(); + QValidator::State state = m_validator.validate(value, valuePos); + input = m_prefix + value + m_suffix; + pos = m_prefix.length() + valuePos; + + if (state == QValidator::Acceptable) { + bool ok = false; + qreal val = locale().toDouble(value, &ok); + if (ok) + const_cast<QQuickSpinBoxValidator *>(this)->setValue(val); + } + return state; +} + +void QQuickSpinBoxValidator::componentComplete() +{ + m_initialized = true; + setValue(m_value); +} + +void QQuickSpinBoxValidator::increment() +{ + setValue(m_value + m_step); +} + +void QQuickSpinBoxValidator::decrement() +{ + setValue(m_value - m_step); +} + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquickspinboxvalidator_p.h b/src/controls/Private/qquickspinboxvalidator_p.h new file mode 100644 index 00000000..09468fce --- /dev/null +++ b/src/controls/Private/qquickspinboxvalidator_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSPINBOXVALIDATOR_P_H +#define QQUICKSPINBOXVALIDATOR_P_H + +#include <QtGui/qvalidator.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +class QQuickSpinBoxValidator : public QValidator, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QString text READ text NOTIFY textChanged) + Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged) + Q_PROPERTY(qreal minimumValue READ minimumValue WRITE setMinimumValue NOTIFY minimumValueChanged) + Q_PROPERTY(qreal maximumValue READ maximumValue WRITE setMaximumValue NOTIFY maximumValueChanged) + Q_PROPERTY(int decimals READ decimals WRITE setDecimals NOTIFY decimalsChanged) + Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged) + Q_PROPERTY(QString prefix READ prefix WRITE setPrefix NOTIFY prefixChanged) + Q_PROPERTY(QString suffix READ suffix WRITE setSuffix NOTIFY suffixChanged) + +public: + explicit QQuickSpinBoxValidator(QObject *parent = 0); + virtual ~QQuickSpinBoxValidator(); + + QString text() const; + + qreal value() const; + void setValue(qreal value); + + qreal minimumValue() const; + void setMinimumValue(qreal min); + + qreal maximumValue() const; + void setMaximumValue(qreal max); + + int decimals() const; + void setDecimals(int decimals); + + qreal stepSize() const; + void setStepSize(qreal step); + + QString prefix() const; + void setPrefix(const QString &prefix); + + QString suffix() const; + void setSuffix(const QString &suffix); + + void fixup(QString &input) const; + State validate(QString &input, int &pos) const; + + void classBegin() { } + void componentComplete(); + +public Q_SLOTS: + void increment(); + void decrement(); + +Q_SIGNALS: + void valueChanged(); + void minimumValueChanged(); + void maximumValueChanged(); + void decimalsChanged(); + void stepSizeChanged(); + void prefixChanged(); + void suffixChanged(); + void textChanged(); + +private: + qreal m_value; + qreal m_step; + QString m_prefix; + QString m_suffix; + bool m_initialized; + QDoubleValidator m_validator; + + Q_DISABLE_COPY(QQuickSpinBoxValidator) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickSpinBoxValidator) + +#endif // QQUICKSPINBOXVALIDATOR_P_H diff --git a/src/controls/Private/qquickstyleitem.cpp b/src/controls/Private/qquickstyleitem.cpp new file mode 100644 index 00000000..e1c9ee18 --- /dev/null +++ b/src/controls/Private/qquickstyleitem.cpp @@ -0,0 +1,1495 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickstyleitem_p.h" + +#include <qstringbuilder.h> +#include <qpainter.h> +#include <qpixmapcache.h> +#include <qstyle.h> +#include <qstyleoption.h> +#include <qapplication.h> +#include <qsgsimpletexturenode.h> +#include <qquickwindow.h> +#include "private/qguiapplication_p.h" +#include <QtGui/qpa/qplatformtheme.h> + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_OSX +#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 + +class QQuickStyleNode : public QSGSimpleTextureNode +{ +public: + ~QQuickStyleNode() + { + delete texture(); + } + + void setTexture(QSGTexture *texture) + { + delete QSGSimpleTextureNode::texture(); + QSGSimpleTextureNode::setTexture(texture); + } +}; + +QQuickStyleItem::QQuickStyleItem(QQuickItem *parent) + : QQuickItem(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_transient(false), + 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(widthChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(heightChanged()), this, SLOT(updateItem())); + 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(updateSizeHint())); + 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(transientChanged()), 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(hintChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(propertiesChanged()), this, SLOT(updateSizeHint())); + connect(this, SIGNAL(propertiesChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(elementTypeChanged()), this, SLOT(updateItem())); + connect(this, SIGNAL(contentWidthChanged(int)), this, SLOT(updateSizeHint())); + connect(this, SIGNAL(contentHeightChanged(int)), this, SLOT(updateSizeHint())); + connect(this, SIGNAL(widthChanged()), this, SLOT(updateRect())); +} + +QQuickStyleItem::~QQuickStyleItem() +{ + delete m_styleoption; + m_styleoption = 0; +} + +void QQuickStyleItem::initStyleOption() +{ + QString type = elementType(); + if (m_styleoption) + m_styleoption->state = 0; + + QString sizeHint = m_hints.value("size").toString(); + QPlatformTheme::Font platformFont = (sizeHint == "mini") ? QPlatformTheme::MiniFont : + (sizeHint == "small") ? QPlatformTheme::SmallFont : + QPlatformTheme::SystemFont; + + switch (m_itemType) { + case Button: { + if (!m_styleoption) + m_styleoption = new QStyleOptionButton(); + + QStyleOptionButton *opt = qstyleoption_cast<QStyleOptionButton*>(m_styleoption); + opt->text = text(); + opt->icon = m_properties["icon"].value<QIcon>(); + int e = qApp->style()->pixelMetric(QStyle::PM_ButtonIconSize, m_styleoption, 0); + opt->iconSize = QSize(e, e); + opt->features = (activeControl() == "default") ? + QStyleOptionButton::DefaultButton : + QStyleOptionButton::None; + if (platformFont == QPlatformTheme::SystemFont) + platformFont = QPlatformTheme::PushButtonFont; + const QFont *font = QGuiApplicationPrivate::platformTheme()->font(platformFont); + if (font) + opt->fontMetrics = QFontMetrics(*font); + QObject * menu = m_properties["menu"].value<QObject *>(); + if (menu) { + opt->features |= QStyleOptionButton::HasMenu; +#ifdef Q_OS_OSX + if (style() == "mac") { + if (platformFont == QPlatformTheme::PushButtonFont) + menu->setProperty("__xOffset", 12); + else + menu->setProperty("__xOffset", 11); + if (platformFont == QPlatformTheme::MiniFont) + menu->setProperty("__yOffset", 5); + else if (platformFont == QPlatformTheme::SmallFont) + menu->setProperty("__yOffset", 6); + else + menu->setProperty("__yOffset", 3); + if (font) + menu->setProperty("__font", *font); + } +#endif + } + } + 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; + if (const QFont *font = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::ItemViewFont)) { + opt->fontMetrics = QFontMetrics(*font); + opt->font = *font; + } + } + 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; + QString headerpos = m_properties.value("headerpos").toString(); + if (headerpos == "beginning") + opt->position = QStyleOptionHeader::Beginning; + else if (headerpos == "end") + opt->position = QStyleOptionHeader::End; + else if (headerpos == "only") + opt->position = QStyleOptionHeader::OnlyOneSection; + else + opt->position = QStyleOptionHeader::Middle; + if (const QFont *font = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::HeaderViewFont)) + opt->fontMetrics = QFontMetrics(*font); + } + 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; + opt->text = text(); + opt->icon = m_properties["icon"].value<QIcon>(); + + // For now icon only is displayed by default. + opt->toolButtonStyle = Qt::ToolButtonIconOnly; + if (opt->icon.isNull() && !opt->text.isEmpty()) + opt->toolButtonStyle = Qt::ToolButtonTextOnly; + + int e = qApp->style()->pixelMetric(QStyle::PM_ToolBarIconSize, m_styleoption, 0); + opt->iconSize = QSize(e, e); + + if (const QFont *font = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::ToolButtonFont)) { + opt->fontMetrics = QFontMetrics(*font); + opt->font = *font; + } + + } + 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(); + + if (m_properties.value("hasFrame").toBool()) + opt->features |= QStyleOptionTab::HasFrame; + + QString orientation = m_properties.value("orientation").toString(); + QString position = m_properties.value("tabpos").toString(); + QString selectedPosition = m_properties.value("selectedpos").toString(); + + opt->shape = (orientation == "Bottom") ? QTabBar::RoundedSouth : QTabBar::RoundedNorth; + if (position == QLatin1String("beginning")) + opt->position = QStyleOptionTab::Beginning; + else if (position == QLatin1String("end")) + opt->position = QStyleOptionTab::End; + else if (position == QLatin1String("only")) + opt->position = QStyleOptionTab::OnlyOneTab; + else + opt->position = QStyleOptionTab::Middle; + + if (selectedPosition == QLatin1String("next")) + opt->selectedPosition = QStyleOptionTab::NextIsSelected; + else if (selectedPosition == QLatin1String("previous")) + opt->selectedPosition = QStyleOptionTab::PreviousIsSelected; + else + opt->selectedPosition = QStyleOptionTab::NotAdjacent; + + + } 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 FocusRect: { + if (!m_styleoption) + m_styleoption = new QStyleOptionFocusRect(); + // Needed on windows + m_styleoption->state |= QStyle::State_KeyboardFocusChange; + } + break; + case TabFrame: { + if (!m_styleoption) + m_styleoption = new QStyleOptionTabWidgetFrame(); + QStyleOptionTabWidgetFrame *opt = qstyleoption_cast<QStyleOptionTabWidgetFrame*>(m_styleoption); + + opt->selectedTabRect = m_properties["selectedTabRect"].toRect(); + opt->shape = m_properties["orientation"] == Qt::BottomEdge ? 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 MenuBar: + if (!m_styleoption) { + QStyleOptionMenuItem *menuOpt = new QStyleOptionMenuItem(); + menuOpt->menuItemType = QStyleOptionMenuItem::EmptyArea; + m_styleoption = menuOpt; + } + + break; + case MenuBarItem: + { + if (!m_styleoption) + m_styleoption = new QStyleOptionMenuItem(); + + QStyleOptionMenuItem *opt = qstyleoption_cast<QStyleOptionMenuItem*>(m_styleoption); + opt->text = text(); + opt->menuItemType = QStyleOptionMenuItem::Normal; + + if (const QFont *font = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::MenuBarFont)) { + opt->font = *font; + opt->fontMetrics = QFontMetrics(opt->font); + m_font = opt->font; + } + } + break; + case Menu: { + if (!m_styleoption) + m_styleoption = new QStyleOptionMenuItem(); + } + break; + case MenuItem: + case ComboBoxItem: + { + if (!m_styleoption) + m_styleoption = new QStyleOptionMenuItem(); + + QStyleOptionMenuItem *opt = qstyleoption_cast<QStyleOptionMenuItem*>(m_styleoption); + // For GTK style. See below, in setElementType() + setProperty("_q_isComboBoxPopupItem", m_itemType == ComboBoxItem); + if (text().isEmpty()) { + opt->menuItemType = QStyleOptionMenuItem::Separator; + } else { + opt->text = text(); + + if (m_properties["isSubmenu"].toBool()) { + opt->menuItemType = QStyleOptionMenuItem::SubMenu; + } else { + QString shortcut = m_properties["shortcut"].toString(); + if (!shortcut.isEmpty()) { + opt->text += QLatin1Char('\t') + shortcut; + opt->tabWidth = qMax(opt->tabWidth, qRound(textWidth(shortcut))); + } + + if (m_properties["checkable"].toBool()) { + opt->checked = on(); + QVariant exclusive = m_properties["exclusive"]; + opt->checkType = exclusive.toBool() ? QStyleOptionMenuItem::Exclusive : + QStyleOptionMenuItem::NonExclusive; + } else { + opt->menuItemType = QStyleOptionMenuItem::Normal; + } + } + if (m_properties["icon"].canConvert<QIcon>()) + opt->icon = m_properties["icon"].value<QIcon>(); + + if (const QFont *font = QGuiApplicationPrivate::platformTheme()->font(m_itemType == ComboBoxItem ? QPlatformTheme::ComboMenuItemFont : QPlatformTheme::MenuFont)) { + opt->font = *font; + opt->fontMetrics = QFontMetrics(opt->font); + m_font = opt->font; + } + } + } + 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; + if (m_properties.value("partiallyChecked").toBool()) + opt->state |= QStyle::State_NoChange; + 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); + + if (platformFont == QPlatformTheme::SystemFont) + platformFont = QPlatformTheme::PushButtonFont; + const QFont *font = QGuiApplicationPrivate::platformTheme()->font(platformFont); + if (font) + opt->fontMetrics = QFontMetrics(*font); + opt->currentText = text(); + opt->editable = false; +#ifdef Q_OS_OSX + if (m_properties["popup"].canConvert<QObject *>() && style() == "mac") { + QObject *popup = m_properties["popup"].value<QObject *>(); + if (platformFont == QPlatformTheme::MiniFont) { + popup->setProperty("__xOffset", -2); + popup->setProperty("__yOffset", 5); + } else { + if (platformFont == QPlatformTheme::SmallFont) + popup->setProperty("__xOffset", -1); + popup->setProperty("__yOffset", 6); + } + if (font) + popup->setProperty("__font", *font); + } +#endif + } + 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->orientation = horizontal() ? Qt::Horizontal : Qt::Vertical; + opt->upsideDown = !horizontal(); + 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() == "ticks" ? + QSlider::TicksBelow : QSlider::NoTicks); + if (opt->tickPosition != QSlider::NoTicks) + opt->subControls |= QStyle::SC_SliderTickmarks; + + opt->activeSubControls = QStyle::SC_SliderHandle; + } + 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 (m_properties["sunken"].toBool()) { // Qt draws an ugly line here so I ignore it + opt->subControls |= QStyle::SC_GroupBoxFrame; + } else { + opt->features |= QStyleOptionFrame::Flat; + } + if (m_properties["checkable"].toBool()) + 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 : + (activeControl() == QLatin1String("handle")) ? + QStyle::SC_ScrollBarSlider : hover() ? QStyle::SC_ScrollBarGroove : QStyle::SC_None; + if (raised()) + opt->state |= QStyle::State_On; + + opt->sliderValue = value(); + opt->subControls = QStyle::SC_All; + + setTransient(qApp->style()->styleHint(QStyle::SH_ScrollBar_Transient, m_styleoption)); + break; + } + default: + break; + } + + if (!m_styleoption) + m_styleoption = new QStyleOption(); + + m_styleoption->styleObject = this; + m_styleoption->direction = qApp->layoutDirection(); + m_styleoption->rect = QRect(m_paintMargins, 0, width() - 2* m_paintMargins, height()); + + if (isEnabled()) { + m_styleoption->state |= QStyle::State_Enabled; + m_styleoption->palette.setCurrentColorGroup(QPalette::Active); + } else { + m_styleoption->palette.setCurrentColorGroup(QPalette::Disabled); + } + if (m_active) + m_styleoption->state |= QStyle::State_Active; + else + m_styleoption->palette.setCurrentColorGroup(QPalette::Inactive); + 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 (sizeHint == "mini") { + m_styleoption->state |= QStyle::State_Mini; + } else if (sizeHint == "small") { + m_styleoption->state |= QStyle::State_Small; + } + +} + +/* + * Property style + * + * Returns a simplified style name. + * + * QMacStyle = "mac" + * QWindowsXPStyle = "windowsxp" + * QFusionStyle = "fusion" + */ + +QString QQuickStyleItem::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; +} + +QString QQuickStyleItem::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 QQuickStyleItem::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, style().contains("windows") ? 30 : 42); + break; + case ToolButton: { + QStyleOptionToolButton *btn = qstyleoption_cast<QStyleOptionToolButton*>(m_styleoption); + int w = 0; + int h = 0; + if (btn->toolButtonStyle != Qt::ToolButtonTextOnly) { + QSize icon = btn->iconSize; + w = icon.width(); + h = icon.height(); + } + if (btn->toolButtonStyle != Qt::ToolButtonIconOnly) { + QSize textSize = btn->fontMetrics.size(Qt::TextShowMnemonic, btn->text); + textSize.setWidth(textSize.width() + btn->fontMetrics.width(QLatin1Char(' '))*2); + if (btn->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { + h += 4 + textSize.height(); + if (textSize.width() > w) + w = textSize.width(); + } else if (btn->toolButtonStyle == Qt::ToolButtonTextBesideIcon) { + w += 4 + textSize.width(); + if (textSize.height() > h) + h = textSize.height(); + } else { // TextOnly + w = textSize.width(); + h = textSize.height(); + } + } + btn->rect.setSize(QSize(w, h)); + size = qApp->style()->sizeFromContents(QStyle::CT_ToolButton, m_styleoption, QSize(w, h)); } + 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)); } +#ifdef Q_OS_OSX + if (style() == "mac") { + // Cancel out QMacStylePrivate::PushButton*Offset, or part of it + size -= QSize(7, 6); + } +#endif + 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 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 SpinBox: +#ifdef Q_OS_OSX + if (style() == "mac") { + size = qApp->style()->sizeFromContents(QStyle::CT_SpinBox, m_styleoption, QSize(width, height + 5)); + break; + } +#endif // fall trough if not mac + case Edit: +#ifdef Q_OS_OSX + if (style() =="mac") { + QString sizeHint = m_hints.value("size").toString(); + if ((sizeHint == "small") || (sizeHint == "mini")) + size = QSize(width, 19); + else + size = QSize(width, 22); + if (style() == "mac" && hints().value("rounded").toBool()) + size += QSize(4, 4); + + } else +#endif + { + // We have to create a new style option since we might be calling with a QStyleOptionSpinBox + QStyleOptionFrame frame; + frame.state = m_styleoption->state; + frame.lineWidth = qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, m_styleoption, 0); + frame.rect = m_styleoption->rect; + size = qApp->style()->sizeFromContents(QStyle::CT_LineEdit, &frame, QSize(width, height)); + } + break; + case GroupBox: { + QStyleOptionGroupBox *box = qstyleoption_cast<QStyleOptionGroupBox*>(m_styleoption); + QFontMetrics metrics(box->fontMetrics); + int baseWidth = metrics.width(box->text) + metrics.width(QLatin1Char(' ')); + int baseHeight = metrics.height() + m_contentHeight; + if (box->subControls & QStyle::SC_GroupBoxCheckBox) { + baseWidth += qApp->style()->pixelMetric(QStyle::PM_IndicatorWidth); + baseWidth += qApp->style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing); + baseHeight = qMax(baseHeight, qApp->style()->pixelMetric(QStyle::PM_IndicatorHeight)); + } + size = qApp->style()->sizeFromContents(QStyle::CT_GroupBox, m_styleoption, QSize(qMax(baseWidth, m_contentWidth), baseHeight)); + } + break; + case Header: + size = qApp->style()->sizeFromContents(QStyle::CT_HeaderSection, m_styleoption, QSize(width,height)); +#ifdef Q_OS_OSX + 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: + size = qApp->style()->sizeFromContents(QStyle::CT_MenuBarItem, m_styleoption, QSize(width,height)); + break; + case MenuBar: + size = qApp->style()->sizeFromContents(QStyle::CT_MenuBar, m_styleoption, QSize(width,height)); + break; + case Menu: + size = qApp->style()->sizeFromContents(QStyle::CT_Menu, m_styleoption, QSize(width,height)); + break; + case MenuItem: + case ComboBoxItem: + size = qApp->style()->sizeFromContents(QStyle::CT_MenuItem, m_styleoption, QSize(width,height)); + break; + default: + break; + } return size; +} + +void QQuickStyleItem::setContentWidth(int arg) +{ + if (m_contentWidth != arg) { + m_contentWidth = arg; + emit contentWidthChanged(arg); + } +} + +void QQuickStyleItem::setContentHeight(int arg) +{ + if (m_contentHeight != arg) { + m_contentHeight = arg; + emit contentHeightChanged(arg); + } +} + +void QQuickStyleItem::updateSizeHint() +{ + QSize implicitSize = sizeFromContents(m_contentWidth, m_contentHeight); + setImplicitSize(implicitSize.width(), implicitSize.height()); +} + +void QQuickStyleItem::updateRect() +{ + initStyleOption(); + m_styleoption->rect.setWidth(width()); +} + +int QQuickStyleItem::pixelMetric(const QString &metric) +{ + + if (metric == "scrollbarExtent") + return qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0 ); + 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, m_styleoption ); + 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 == "menubarhmargin") + return qApp->style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0 ); + else if (metric == "menubarvmargin") + return qApp->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0 ); + else if (metric == "menubarpanelwidth") + return qApp->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0 ); + else if (metric == "menubaritemspacing") + return qApp->style()->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0 ); + else if (metric == "spacebelowmenubar") + return qApp->style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, m_styleoption); + 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 == "submenuoverlap") + return qApp->style()->pixelMetric(QStyle::PM_SubMenuOverlap, 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 QQuickStyleItem::styleHint(const QString &metric) +{ + initStyleOption(); + if (metric == "comboboxpopup") { + return qApp->style()->styleHint(QStyle::SH_ComboBox_Popup, m_styleoption); + } else if (metric == "highlightedTextColor") { + QPalette pal = QApplication::palette("QAbstractItemView"); + pal.setCurrentColorGroup(m_styleoption->palette.currentColorGroup()); + return pal.highlightedText().color().name(); + } else if (metric == "textColor") { + QPalette pal = qApp->palette(); + pal.setCurrentColorGroup(active()? QPalette::Active : QPalette::Inactive); + return pal.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 == "externalScrollBars") { + return qApp->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents); + } else if (metric == "scrollToClickPosition") + return qApp->style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition); + else if (metric == "activateItemOnSingleClick") + return qApp->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); + return 0; + + // Add SH_Menu_SpaceActivatesItem, SH_Menu_SubMenuPopupDelay +} + +void QQuickStyleItem::setHints(const QVariantMap &str) +{ + if (m_hints != str) { + m_hints = 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(); + } else { + emit hintChanged(); + } + } +} + +void QQuickStyleItem::resetHints() +{ + m_hints.clear(); +} + + +void QQuickStyleItem::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") { + m_itemType = Menu; + } else if (str == "menuitem") { + m_itemType = MenuItem; + } else if (str == "item" || str == "itemrow" || str == "header") { +#ifdef Q_OS_OSX + 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 == "focusrect") { + m_itemType = FocusRect; + } 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 QQuickStyleItem::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(); +} + +namespace { +class QHighDpiPixmapsEnabler { +public: + QHighDpiPixmapsEnabler() + :wasEnabled(false) + { + if (!qApp->testAttribute(Qt::AA_UseHighDpiPixmaps)) { + qApp->setAttribute(Qt::AA_UseHighDpiPixmaps); + wasEnabled = true; + } + } + + ~QHighDpiPixmapsEnabler() + { + if (wasEnabled) + qApp->setAttribute(Qt::AA_UseHighDpiPixmaps, false); + } +private: + bool wasEnabled; +}; +} + +void QQuickStyleItem::paint(QPainter *painter) +{ + initStyleOption(); + if (QStyleOptionMenuItem *opt = qstyleoption_cast<QStyleOptionMenuItem*>(m_styleoption)) + painter->setFont(opt->font); + else { + QPlatformTheme::Font platformFont = (m_styleoption->state & QStyle::State_Mini) ? QPlatformTheme::MiniFont : + (m_styleoption->state & QStyle::State_Small) ? QPlatformTheme::SmallFont : + QPlatformTheme::NFonts; + if (platformFont != QPlatformTheme::NFonts) + if (const QFont *font = QGuiApplicationPrivate::platformTheme()->font(platformFont)) + painter->setFont(*font); + } + + // Set AA_UseHighDpiPixmaps when calling style code to make QIcon return + // "retina" pixmaps. The flag is controlled by the application so we can't + // set it unconditinally. + QHighDpiPixmapsEnabler enabler; + + switch (m_itemType) { + case Button: +#ifdef Q_OS_OSX + if (style() == "mac") { + // Add back what was substracted in sizeFromContents() + m_styleoption->rect.adjust(-4, -2, 3, 4); + } +#endif + 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 ((style() == "mac" || !qApp->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected)) && selected()) { + QPalette pal = QApplication::palette("QAbstractItemView"); + pal.setCurrentColorGroup(m_styleoption->palette.currentColorGroup()); + pixpainter.fillRect(m_styleoption->rect, pal.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_OSX + if (style() == "mac" && hints().value("segmented").toBool()) { + 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); + QString buttonPos = m_properties.value("position").toString(); + sgi.position = buttonPos == "leftmost" ? kHIThemeSegmentPositionFirst : + buttonPos == "rightmost" ? kHIThemeSegmentPositionLast : + buttonPos == "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: +#ifdef Q_OS_OSX + if (style() == "mac") { + m_styleoption->rect.translate(0, 1); // Unhack QMacStyle's hack + qApp->style()->drawControl(QStyle::CE_TabBarTabShape, m_styleoption, painter); + m_styleoption->rect.translate(0, -1); + qApp->style()->drawControl(QStyle::CE_TabBarTabLabel, m_styleoption, painter); + } else +#endif + { + qApp->style()->drawControl(QStyle::CE_TabBarTab, m_styleoption, painter); + } + break; + case Frame: + qApp->style()->drawControl(QStyle::CE_ShapedFrame, m_styleoption, painter); + break; + case FocusFrame: + qApp->style()->drawControl(QStyle::CE_FocusFrame, m_styleoption, painter); + break; + case FocusRect: + qApp->style()->drawPrimitive(QStyle::PE_FrameFocusRect, 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_OSX + if (style() == "mac" && hints().value("rounded").toBool()) { + 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.adjusted(2, 2, -2, 2), QRect(0, 0, 0, 0)); + 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_OSX + { + 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: + painter->fillRect(m_styleoption->rect, m_styleoption->palette.window().color()); + qApp->style()->drawControl(QStyle::CE_ToolBar, m_styleoption, painter); + painter->save(); + painter->setPen(style() != "fusion" ? m_styleoption->palette.dark().color().darker(120) : + m_styleoption->palette.window().color().lighter(107)); + painter->drawLine(m_styleoption->rect.bottomLeft(), m_styleoption->rect.bottomRight()); + painter->restore(); + break; + case StatusBar: +#ifdef Q_OS_OSX + if (style() == "mac") { + qApp->style()->drawControl(QStyle::CE_ToolBar, m_styleoption, painter); + painter->setPen(m_styleoption->palette.dark().color().darker(120)); + painter->drawLine(m_styleoption->rect.topLeft(), m_styleoption->rect.topRight()); + } else +#endif + { + painter->fillRect(m_styleoption->rect, m_styleoption->palette.window().color()); + painter->setPen(m_styleoption->palette.dark().color().darker(120)); + painter->drawLine(m_styleoption->rect.topLeft(), m_styleoption->rect.topRight()); + qApp->style()->drawPrimitive(QStyle::PE_PanelStatusBar, 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); + setOn(false); + 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); + + if (int fw = qApp->style()->pixelMetric(QStyle::PM_MenuPanelWidth)) { + QStyleOptionFrame frame; + frame.state = QStyle::State_None; + frame.lineWidth = fw; + frame.midLineWidth = 0; + frame.rect = m_styleoption->rect; + qApp->style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, painter); + } + } + break; + default: + break; + } +} + +qreal QQuickStyleItem::textWidth(const QString &text) +{ + QFontMetricsF fm = QFontMetricsF(m_styleoption->fontMetrics); + return fm.boundingRect(text).width(); +} + +qreal QQuickStyleItem::textHeight(const QString &text) +{ + QFontMetricsF fm = QFontMetricsF(m_styleoption->fontMetrics); + return text.isEmpty() ? fm.height() : + fm.boundingRect(text).height(); +} + +QString QQuickStyleItem::elidedText(const QString &text, int elideMode, int width) +{ + return m_styleoption->fontMetrics.elidedText(text, Qt::TextElideMode(elideMode), width); +} + +bool QQuickStyleItem::hasThemeIcon(const QString &icon) const +{ + return QIcon::hasThemeIcon(icon); +} + +bool QQuickStyleItem::event(QEvent *ev) +{ + if (ev->type() == QEvent::StyleAnimationUpdate) { + polish(); + return true; + } else if (ev->type() == QEvent::StyleChange) { + if (m_itemType == ScrollBar) + initStyleOption(); + } + return QQuickItem::event(ev); +} + +QSGNode *QQuickStyleItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) +{ + if (m_image.isNull()) { + delete node; + return 0; + } + + QQuickStyleNode *styleNode = static_cast<QQuickStyleNode *>(node); + if (!styleNode) + styleNode = new QQuickStyleNode; + + styleNode->setTexture(window()->createTextureFromImage(m_image, QQuickWindow::TextureCanUseAtlas)); + styleNode->setRect(boundingRect()); + return styleNode; +} + +void QQuickStyleItem::updatePolish() +{ + if (width() >= 1 && height() >= 1) { // Note these are reals so 1 pixel is minimum + float devicePixelRatio = window() ? window()->devicePixelRatio() : qApp->devicePixelRatio(); + m_image = QImage(width() * devicePixelRatio, height() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied); + m_image.setDevicePixelRatio(devicePixelRatio); + m_image.fill(Qt::transparent); + QPainter painter(&m_image); + painter.setLayoutDirection(qApp->layoutDirection()); + paint(&painter); + QQuickItem::update(); + } else if (!m_image.isNull()) { + m_image = QImage(); + QQuickItem::update(); + } +} + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquickstyleitem_p.h b/src/controls/Private/qquickstyleitem_p.h new file mode 100644 index 00000000..cfe9866e --- /dev/null +++ b/src/controls/Private/qquickstyleitem_p.h @@ -0,0 +1,265 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKSTYLEITEM_P_H +#define QQUICKSTYLEITEM_P_H + +#include <QtGui/qimage.h> +#include <QtQuick/qquickitem.h> + +QT_BEGIN_NAMESPACE + +class QWidget; +class QStyleOption; + +class QQuickStyleItem: public QQuickItem +{ + 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( bool transient READ transient WRITE setTransient NOTIFY transientChanged) + + 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 style READ style NOTIFY styleChanged) + Q_PROPERTY( QVariantMap hints READ hints WRITE setHints NOTIFY hintChanged RESET resetHints) + Q_PROPERTY( QVariantMap properties READ properties WRITE setProperties NOTIFY propertiesChanged) + 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: + QQuickStyleItem(QQuickItem *parent = 0); + ~QQuickStyleItem(); + + enum Type { + Undefined, + Button, + RadioButton, + CheckBox, + ComboBox, + ComboBoxItem, + Dial, + ToolBar, + ToolButton, + Tab, + TabFrame, + Frame, + FocusFrame, + FocusRect, + 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; } + bool transient() const { return m_transient; } + + 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; } + QVariantMap hints() const { return m_hints; } + QVariantMap properties() const { return m_properties; } + 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 setTransient(bool transient) { if (m_transient != transient) {m_transient = transient; emit transientChanged();}} + 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 setHints(const QVariantMap &str); + void setProperties(const QVariantMap &props) { if (m_properties != props) { m_properties = props; emit propertiesChanged(); } } + void resetHints(); + + int contentWidth() const { return m_contentWidth; } + void setContentWidth(int arg); + + int contentHeight() const { return m_contentHeight; } + void setContentHeight(int arg); + + virtual void initStyleOption (); + + Q_INVOKABLE qreal textWidth(const QString &); + Q_INVOKABLE qreal textHeight(const QString &); + +public Q_SLOTS: + int pixelMetric(const QString&); + QVariant styleHint(const QString&); + void updateSizeHint(); + void updateRect(); + void updateItem(){polish();} + QString hitTest(int x, int y); + QRectF subControlRect(const QString &subcontrolString); + QString elidedText(const QString &text, int elideMode, int width); + bool hasThemeIcon(const QString &) const; + +Q_SIGNALS: + void elementTypeChanged(); + void textChanged(); + void sunkenChanged(); + void raisedChanged(); + void activeChanged(); + void selectedChanged(); + void hasFocusChanged(); + void onChanged(); + void hoverChanged(); + void horizontalChanged(); + void transientChanged(); + void minimumChanged(); + void maximumChanged(); + void stepChanged(); + void valueChanged(); + void activeControlChanged(); + void infoChanged(); + void styleChanged(); + void paintMarginsChanged(); + void hintChanged(); + void propertiesChanged(); + void fontChanged(); + + void contentWidthChanged(int arg); + void contentHeightChanged(int arg); + +protected: + virtual bool event(QEvent *); + virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + virtual void updatePolish(); + +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; + QVariantMap m_hints; + QVariantMap m_properties; + 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_transient; + bool m_sharedWidget; + + int m_minimum; + int m_maximum; + int m_value; + int m_step; + int m_paintMargins; + + int m_contentWidth; + int m_contentHeight; + + QImage m_image; +}; + +QT_END_NAMESPACE + +#endif // QQUICKSTYLEITEM_P_H diff --git a/src/controls/Private/qquicktooltip.cpp b/src/controls/Private/qquicktooltip.cpp new file mode 100644 index 00000000..ae4366d9 --- /dev/null +++ b/src/controls/Private/qquicktooltip.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquicktooltip_p.h" +#include <qquickwindow.h> +#include <qquickitem.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> + +#ifndef QT_NO_WIDGETS +#include <qtooltip.h> +#endif + +QT_BEGIN_NAMESPACE + +QQuickTooltip::QQuickTooltip(QObject *parent) + : QObject(parent) +{ + +} + +void QQuickTooltip::showText(QQuickItem *item, const QPointF &pos, const QString &str) +{ + if (!item || !item->window()) + return; +#ifndef QT_NO_WIDGETS + if (QGuiApplicationPrivate::platformIntegration()-> + hasCapability(QPlatformIntegration::MultipleWindows) && + QCoreApplication::instance()->inherits("QApplication")) + QToolTip::showText(item->window()->mapToGlobal(item->mapToScene(pos).toPoint()), str); +#else + Q_UNUSED(item); + Q_UNUSED(pos); + Q_UNUSED(str); +#endif +} + +void QQuickTooltip::hideText() +{ +#ifndef QT_NO_WIDGETS + QToolTip::hideText(); +#endif +} + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquicktooltip_p.h b/src/controls/Private/qquicktooltip_p.h new file mode 100644 index 00000000..20f91830 --- /dev/null +++ b/src/controls/Private/qquicktooltip_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKTOOLTIP_P_H +#define QQUICKTOOLTIP_P_H + +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class QPointF; +class QQuickItem; + +class QQuickTooltip : public QObject +{ + Q_OBJECT + +public: + QQuickTooltip(QObject *parent = 0); + + Q_INVOKABLE void showText(QQuickItem *item, const QPointF &pos, const QString &text); + Q_INVOKABLE void hideText(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKTOOLTIP_P_H diff --git a/src/controls/Private/qquickwheelarea.cpp b/src/controls/Private/qquickwheelarea.cpp new file mode 100644 index 00000000..101e22bf --- /dev/null +++ b/src/controls/Private/qquickwheelarea.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickwheelarea_p.h" + +QT_BEGIN_NAMESPACE + +// On Mac OS X, the scrolling speed in Safari is roughly 2.5 times faster +// than in TextEdit (the native app). The former is using high-resolution +// pixel-based delta values as they are, which is fine for a typical web +// content, whereas the latter evidently makes scrolling slower to make it +// feel natural and more precise for typical document type of content. +// => we'll compromise between the two for now, and pick an arbitrary value +// to make the pixel-based scrolling speed something between the two +static const qreal pixelDeltaAdjustment = 0.5; + +// The default scroll speed for typical angle-based mouse wheels. The value +// comes originally from QTextEdit, which sets 20px steps by default. +static const qreal defaultScrollSpeed = 20.0; + +QQuickWheelArea::QQuickWheelArea(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(defaultScrollSpeed) +{ + +} + +QQuickWheelArea::~QQuickWheelArea() +{ + +} + +void QQuickWheelArea::wheelEvent(QWheelEvent *we) +{ + QPoint numPixels = we->pixelDelta(); + QPoint numDegrees = we->angleDelta() / 8; + + if (!numPixels.isNull()) { + setHorizontalDelta(numPixels.x() * pixelDeltaAdjustment); + setVerticalDelta(numPixels.y() * pixelDeltaAdjustment); + } else if (!numDegrees.isNull()) { + setHorizontalDelta(numDegrees.x() / 15.0 * m_scrollSpeed); + setVerticalDelta(numDegrees.y() / 15.0 * m_scrollSpeed); + } + + we->accept(); +} + +void QQuickWheelArea::setHorizontalMinimumValue(qreal value) +{ + m_horizontalMinimumValue = value; +} + +qreal QQuickWheelArea::horizontalMinimumValue() const +{ + return m_horizontalMinimumValue; +} + +void QQuickWheelArea::setHorizontalMaximumValue(qreal value) +{ + m_horizontalMaximumValue = value; +} + +qreal QQuickWheelArea::horizontalMaximumValue() const +{ + return m_horizontalMaximumValue; +} + +void QQuickWheelArea::setVerticalMinimumValue(qreal value) +{ + m_verticalMinimumValue = value; +} + +qreal QQuickWheelArea::verticalMinimumValue() const +{ + return m_verticalMinimumValue; +} + +void QQuickWheelArea::setVerticalMaximumValue(qreal value) +{ + m_verticalMaximumValue = value; +} + +qreal QQuickWheelArea::verticalMaximumValue() const +{ + return m_verticalMaximumValue; +} + +void QQuickWheelArea::setHorizontalValue(qreal value) +{ + value = qBound<qreal>(m_horizontalMinimumValue, value, m_horizontalMaximumValue); + + if (value != m_horizontalValue) { + m_horizontalValue = value; + emit horizontalValueChanged(); + } +} + +qreal QQuickWheelArea::horizontalValue() const +{ + return m_horizontalValue; +} + +void QQuickWheelArea::setVerticalValue(qreal value) +{ + value = qBound<qreal>(m_verticalMinimumValue, value, m_verticalMaximumValue); + + if (value != m_verticalValue) { + m_verticalValue = value; + emit verticalValueChanged(); + } +} + +qreal QQuickWheelArea::verticalValue() const +{ + return m_verticalValue; +} + +void QQuickWheelArea::setVerticalDelta(qreal value) +{ + m_verticalDelta = value; + setVerticalValue(m_verticalValue - m_verticalDelta); + + emit verticalWheelMoved(); +} + +qreal QQuickWheelArea::verticalDelta() const +{ + return m_verticalDelta; +} + +void QQuickWheelArea::setHorizontalDelta(qreal value) +{ + m_horizontalDelta = value; + setHorizontalValue(m_horizontalValue - m_horizontalDelta); + + emit horizontalWheelMoved(); +} + +qreal QQuickWheelArea::horizontalDelta() const +{ + return m_horizontalDelta; +} + +void QQuickWheelArea::setScrollSpeed(qreal value) +{ + if (value != m_scrollSpeed) { + m_scrollSpeed = value; + emit scrollSpeedChanged(); + } +} + +qreal QQuickWheelArea::scrollSpeed() const +{ + return m_scrollSpeed; +} + +QT_END_NAMESPACE diff --git a/src/controls/Private/qquickwheelarea_p.h b/src/controls/Private/qquickwheelarea_p.h new file mode 100644 index 00000000..057ad56d --- /dev/null +++ b/src/controls/Private/qquickwheelarea_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWHEELAREA_P_H +#define QQUICKWHEELAREA_P_H + +#include <QtGui/qevent.h> +#include <QtQuick/qquickitem.h> + +QT_BEGIN_NAMESPACE + +class QQuickWheelArea : 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: + QQuickWheelArea(QQuickItem *parent = 0); + virtual ~QQuickWheelArea(); + + 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(QQuickWheelArea) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickWheelArea) + +#endif // QQUICKWHEELAREA_P_H diff --git a/src/controls/Private/style.js b/src/controls/Private/style.js new file mode 100644 index 00000000..2c47ff0e --- /dev/null +++ b/src/controls/Private/style.js @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls module 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$ +** +****************************************************************************/ + +.pragma library + +function underlineAmpersands(match, p1, p2, p3) { + if (p2 === "&") + return p1.concat(p2, p3) + return p1.concat("<u>", p2, "</u>", p3) +} + +function removeAmpersands(match, p1, p2, p3) { + return p1.concat(p2, p3) +} + +function replaceAmpersands(text, replaceFunction) { + return text.replace(/([^&]*)&(.)([^&]*)/g, replaceFunction) +} + +function stylizeMnemonics(text) { + return replaceAmpersands(text, underlineAmpersands) +} + +function removeMnemonics(text) { + return replaceAmpersands(text, removeAmpersands) +} |