aboutsummaryrefslogtreecommitdiffstats
path: root/src/imports/controls
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@theqtcompany.com>2015-09-18 13:40:01 +0200
committerMitch Curtis <mitch.curtis@theqtcompany.com>2015-09-18 14:14:07 +0000
commit0797e0cb2072a0b5cac4d8db2205d932cc64d25c (patch)
tree103fd7a6f67a83bd7b6f44dcc9c2a67547aa2cb2 /src/imports/controls
parent2ef6a789e9cd91a9245c65201a6fe3d3322712ad (diff)
Merge Qt Quick Extras into Qt Quick Controls
The original split existed because the public and enterprise controls were developed separately. Now that all controls are public and developed together, the split no longer makes sense and is difficult for users to understand. Change-Id: I00420f4d09f8c837232231d03fe818b7b3403fab Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com> Reviewed-by: Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
Diffstat (limited to 'src/imports/controls')
-rw-r--r--src/imports/controls/Dial.qml82
-rw-r--r--src/imports/controls/Drawer.qml57
-rw-r--r--src/imports/controls/SwipeView.qml66
-rw-r--r--src/imports/controls/Tumbler.qml79
-rw-r--r--src/imports/controls/controls.pro16
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-dial-background.pngbin0 -> 3286 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-dial-handle.pngbin0 -> 3538 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-tumbler-background.pngbin0 -> 1025 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-tumbler-contentItem.pngbin0 -> 1025 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-tumbler-delegate.pngbin0 -> 1047 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-tumbler-wrap.gifbin0 -> 38931 bytes
-rw-r--r--src/imports/controls/doc/qtquickcontrols2.qdocconf2
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc42
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-index.qdoc4
-rw-r--r--src/imports/controls/qquickdial.cpp527
-rw-r--r--src/imports/controls/qquickdial_p.h142
-rw-r--r--src/imports/controls/qquickdrawer.cpp388
-rw-r--r--src/imports/controls/qquickdrawer_p.h114
-rw-r--r--src/imports/controls/qquickswipeview.cpp346
-rw-r--r--src/imports/controls/qquickswipeview_p.h111
-rw-r--r--src/imports/controls/qquicktumbler.cpp535
-rw-r--r--src/imports/controls/qquicktumbler_p.h146
-rw-r--r--src/imports/controls/qtquickcontrols2plugin.cpp14
23 files changed, 2666 insertions, 5 deletions
diff --git a/src/imports/controls/Dial.qml b/src/imports/controls/Dial.qml
new file mode 100644
index 00000000..fcca2066
--- /dev/null
+++ b/src/imports/controls/Dial.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+AbstractDial {
+ id: control
+
+ implicitWidth: 100
+ implicitHeight: 100
+
+ Accessible.pressed: pressed
+ Accessible.role: Accessible.Dial
+
+ //! [background]
+ background: Rectangle {
+ color: control.Theme.backgroundColor
+ radius: width / 2
+
+ border.color: control.activeFocus ? control.Theme.focusColor : control.Theme.frameColor
+ }
+ //! [background]
+
+ //! [handle]
+ handle: Rectangle {
+ id: handleItem
+
+ x: background.width / 2 - handle.width / 2
+ y: background.height / 2 - handle.height / 2
+ transform: [
+ Translate {
+ y: -background.height * 0.35
+ },
+ Rotation {
+ angle: control.angle
+ origin.x: handle.width / 2
+ origin.y: handle.height / 2
+ }
+ ]
+ implicitWidth: 20
+ implicitHeight: 20
+ radius: width / 2
+ border.width: control.activeFocus ? 2 : 1
+ border.color: control.activeFocus ? control.Theme.focusColor : control.Theme.frameColor
+ color: control.Theme.baseColor
+ }
+ //! [handle]
+}
diff --git a/src/imports/controls/Drawer.qml b/src/imports/controls/Drawer.qml
new file mode 100644
index 00000000..57db687d
--- /dev/null
+++ b/src/imports/controls/Drawer.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+AbstractDrawer {
+ id: control
+
+ width: parent ? parent.width : 0 // TODO: Window.width
+ height: parent ? parent.height : 0 // TODO: Window.height
+
+ //! [background]
+ background: Rectangle {
+ color: control.Theme.shadowColor
+ opacity: position * 0.75
+ }
+ //! [background]
+
+ // TODO: make this a proper transition
+ animation: SmoothedAnimation {
+ velocity: 5
+ }
+}
diff --git a/src/imports/controls/SwipeView.qml b/src/imports/controls/SwipeView.qml
new file mode 100644
index 00000000..63274f20
--- /dev/null
+++ b/src/imports/controls/SwipeView.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+AbstractSwipeView {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+
+ Accessible.role: Accessible.PageTabList
+
+ //! [contentItem]
+ contentItem: ListView {
+ model: control.contentModel
+ currentIndex: control.currentIndex
+
+ spacing: control.spacing
+ orientation: Qt.Horizontal
+ snapMode: ListView.SnapOneItem
+ boundsBehavior: Flickable.StopAtBounds
+
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: 0
+ preferredHighlightEnd: 0
+ highlightMoveDuration: 250
+ }
+ //! [contentItem]
+}
diff --git a/src/imports/controls/Tumbler.qml b/src/imports/controls/Tumbler.qml
new file mode 100644
index 00000000..500d59db
--- /dev/null
+++ b/src/imports/controls/Tumbler.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+AbstractTumbler {
+ id: control
+ implicitWidth: 60
+ implicitHeight: 200
+
+ //! [delegate]
+ delegate: Text {
+ id: label
+ text: modelData
+ color: "#666666"
+ opacity: 0.4 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.6
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ //! [delegate]
+
+ //! [contentItem]
+ contentItem: PathView {
+ id: pathView
+ model: control.model
+ delegate: control.delegate
+ clip: true
+ pathItemCount: control.visibleItemCount + 1
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ dragMargin: width / 2
+
+ path: Path {
+ startX: pathView.width / 2
+ startY: -pathView.delegateHeight / 2
+ PathLine {
+ x: pathView.width / 2
+ y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2
+ }
+ }
+
+ property real delegateHeight: control.availableHeight / control.visibleItemCount
+ }
+ //! [contentItem]
+}
diff --git a/src/imports/controls/controls.pro b/src/imports/controls/controls.pro
index ddf85666..efea03ef 100644
--- a/src/imports/controls/controls.pro
+++ b/src/imports/controls/controls.pro
@@ -15,6 +15,8 @@ QML_FILES = \
BusyIndicator.qml \
Button.qml \
CheckBox.qml \
+ Dial.qml \
+ Drawer.qml \
Frame.qml \
GroupBox.qml \
Label.qml \
@@ -26,21 +28,31 @@ QML_FILES = \
Slider.qml \
StackView.qml \
Switch.qml \
+ SwipeView.qml \
TabBar.qml \
TabButton.qml \
TextArea.qml \
TextField.qml \
ToggleButton.qml \
ToolBar.qml \
- ToolButton.qml
+ ToolButton.qml \
+ Tumbler.qml
HEADERS += \
+ $$PWD/qquickdial_p.h \
+ $$PWD/qquickdrawer_p.h \
+ $$PWD/qquickswipeview_p.h \
$$PWD/qquicktheme_p.h \
- $$PWD/qquickthemedata_p.h
+ $$PWD/qquickthemedata_p.h \
+ $$PWD/qquicktumbler_p.h
SOURCES += \
+ $$PWD/qquickdial.cpp \
+ $$PWD/qquickdrawer.cpp \
+ $$PWD/qquickswipeview.cpp \
$$PWD/qquicktheme.cpp \
$$PWD/qquickthemedata.cpp \
+ $$PWD/qquicktumbler.cpp \
$$PWD/qtquickcontrols2plugin.cpp
RESOURCES += \
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-dial-background.png b/src/imports/controls/doc/images/qtquickcontrols2-dial-background.png
new file mode 100644
index 00000000..38fad583
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-dial-background.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-dial-handle.png b/src/imports/controls/doc/images/qtquickcontrols2-dial-handle.png
new file mode 100644
index 00000000..e6fd8cdc
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-dial-handle.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-tumbler-background.png b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-background.png
new file mode 100644
index 00000000..aa736615
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-background.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-tumbler-contentItem.png b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-contentItem.png
new file mode 100644
index 00000000..aa736615
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-contentItem.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-tumbler-delegate.png b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-delegate.png
new file mode 100644
index 00000000..77c51efd
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-delegate.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-tumbler-wrap.gif b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-wrap.gif
new file mode 100644
index 00000000..2a7e435d
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-tumbler-wrap.gif
Binary files differ
diff --git a/src/imports/controls/doc/qtquickcontrols2.qdocconf b/src/imports/controls/doc/qtquickcontrols2.qdocconf
index 9e613328..b4d17791 100644
--- a/src/imports/controls/doc/qtquickcontrols2.qdocconf
+++ b/src/imports/controls/doc/qtquickcontrols2.qdocconf
@@ -23,7 +23,7 @@ qhp.QtQuickControls2.subprojects.qtquickcontrols2qmltypes.indexTitle = Qt Quick
qhp.QtQuickControls2.subprojects.qtquickcontrols2qmltypes.selectors = qmlclass
qhp.QtQuickControls2.subprojects.qtquickcontrols2qmltypes.sortPages = true
-depends = qtcore qtgui qtdoc qtqml qtquick qtquicklayouts qtquickdialogs qtquickcontrols qtquickextras2
+depends = qtcore qtgui qtdoc qtqml qtquick qtquicklayouts qtquickdialogs qtquickcontrols
# Specify the install path under QT_INSTALL_EXAMPLES
# Examples will be installed under quick/controls - 'controls' subdirectory
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
index b099b482..e554b202 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
@@ -95,6 +95,23 @@
\snippet CheckBox.qml indicator
+ \section1 Customizing Dial
+
+ Dial consists of two visual items: \l {Control::background}{background}
+ and \l {Dial::handle}{handle}.
+
+ \section3 Background
+
+ \image qtquickcontrols2-dial-background.png
+
+ \snippet Dial.qml background
+
+ \section3 Indicator
+
+ \image qtquickcontrols2-dial-handle.png
+
+ \snippet Dial.qml handle
+
\section1 Customizing Frame
@@ -370,4 +387,29 @@
\image qtquickcontrols2-toolbutton-label.png
\snippet ToolButton.qml label
+
+ \section1 Customizing Tumbler
+
+ Tumbler consists of three visual items:
+ \l {Control::background}{background},
+ \l {Control::contentItem}{contentItem}, and
+ \l {Tumbler::delegate}{delegate}.
+
+ \section3 Background
+
+ \image qtquickcontrols2-tumbler-background.png
+
+ Tumbler has no background item by default.
+
+ \section3 Content Item
+
+ \image qtquickcontrols2-tumbler-contentItem.png
+
+ \snippet Tumbler.qml contentItem
+
+ \section3 Delegate
+
+ \image qtquickcontrols2-tumbler-delegate.png
+
+ \snippet Tumbler.qml delegate
*/
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
index eefd6c3a..d6d13cae 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
@@ -229,7 +229,7 @@
\li \l [QtQuickControls2] {Slider}
\row
\li \l [QtQuickControls] {SpinBox}
- \li No equivalent; see \l [QtQuickExtras2] {Tumbler} instead.
+ \li No equivalent; see \l [QtQuickControls2] {Tumbler} instead.
\row
\li \l [QtQuickControls] {Stack},
\l [QtQuickControls] {StackView},
@@ -245,7 +245,7 @@
\li \l [QtQuickControls] {Tab},
\l [QtQuickControls] {TabView}
\li \l [QtQuickControls2] {TabBar} in combination with, for example,
- \l [QtQuickExtras2] {SwipeView}.
+ \l [QtQuickControls2] {SwipeView}.
\row
\li \l [QtQuickControls] {TableView}
\li No equivalent
diff --git a/src/imports/controls/qquickdial.cpp b/src/imports/controls/qquickdial.cpp
new file mode 100644
index 00000000..407899d3
--- /dev/null
+++ b/src/imports/controls/qquickdial.cpp
@@ -0,0 +1,527 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdial_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtQuick/private/qquickflickable_p.h>
+#include <QtQuickTemplates/private/qquickcontrol_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Dial
+ \inherits Control
+ \instantiates QQuickDial
+ \inqmlmodule QtQuick.Controls
+ \ingroup sliders
+ \brief A circular dial that is rotated to set a value.
+
+ The Dial is similar to a traditional dial knob that is found on devices
+ such as stereos or industrial equipment. It allows the user to specify a
+ value within a range.
+
+ The value of the dial is set with the \l value property. The range is
+ set with the \l from and \l to properties.
+
+ The dial can be manipulated with a keyboard. It supports the following
+ actions:
+
+ \table
+ \header \li \b {Action} \li \b {Key}
+ \row \li Decrease \l value by \l stepSize \li \c Qt.Key_Left
+ \row \li Decrease \l value by \l stepSize \li \c Qt.Key_Down
+ \row \li Set \l value to \l from \li \c Qt.Key_Home
+ \row \li Increase \l value by \l stepSize \li \c Qt.Key_Right
+ \row \li Increase \l value by \l stepSize \li \c Qt.Key_Up
+ \row \li Set \l value to \l to \li \c Qt.Key_End
+ \endtable
+
+ \sa {Customizing Dial}
+*/
+
+static const qreal startAngle = -140;
+static const qreal endAngle = 140;
+
+class QQuickDialPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickDial)
+
+public:
+ QQuickDialPrivate() :
+ from(0),
+ to(1),
+ value(0),
+ position(0),
+ angle(startAngle),
+ stepSize(0),
+ pressed(false),
+ snapMode(QQuickDial::NoSnap),
+ handle(Q_NULLPTR)
+ {
+ }
+
+ qreal valueAt(qreal position) const;
+ qreal snapPosition(qreal position) const;
+ qreal positionAt(const QPoint &point) const;
+ void setPosition(qreal position);
+ void updatePosition();
+
+ qreal from;
+ qreal to;
+ qreal value;
+ qreal position;
+ qreal angle;
+ qreal stepSize;
+ bool pressed;
+ QPoint pressPoint;
+ QQuickDial::SnapMode snapMode;
+ QQuickItem *handle;
+};
+
+qreal QQuickDialPrivate::valueAt(qreal position) const
+{
+ return from + (to - from) * position;
+}
+
+qreal QQuickDialPrivate::snapPosition(qreal position) const
+{
+ if (qFuzzyIsNull(stepSize))
+ return position;
+ return qRound(position / stepSize) * stepSize;
+}
+
+qreal QQuickDialPrivate::positionAt(const QPoint &point) const
+{
+ qreal yy = height / 2.0 - point.y();
+ qreal xx = point.x() - width / 2.0;
+ qreal angle = (xx || yy) ? atan2(yy, xx) : 0;
+
+ if (angle < M_PI / -2)
+ angle = angle + M_PI * 2;
+
+ qreal normalizedAngle = (M_PI * 4 / 3 - angle) / (M_PI * 10 / 6);
+ return normalizedAngle;
+}
+
+void QQuickDialPrivate::setPosition(qreal pos)
+{
+ Q_Q(QQuickDial);
+ pos = qBound(0.0, pos, 1.0);
+ if (!qFuzzyCompare(position, pos)) {
+ position = pos;
+
+ angle = startAngle + position * qAbs(endAngle - startAngle);
+
+ emit q->positionChanged();
+ emit q->angleChanged();
+ }
+}
+
+void QQuickDialPrivate::updatePosition()
+{
+ qreal pos = 0;
+ if (!qFuzzyCompare(from, to))
+ pos = (value - from) / (to - from);
+ setPosition(pos);
+}
+
+QQuickDial::QQuickDial(QQuickItem *parent) :
+ QQuickControl(*(new QQuickDialPrivate), parent)
+{
+ setActiveFocusOnTab(true);
+ setAcceptedMouseButtons(Qt::LeftButton);
+}
+
+/*!
+ \qmlproperty real QtQuickControls2::Dial::from
+
+ This property holds the starting value for the range. The default value is \c 0.0.
+
+ \sa to, value
+*/
+qreal QQuickDial::from() const
+{
+ Q_D(const QQuickDial);
+ return d->from;
+}
+
+void QQuickDial::setFrom(qreal from)
+{
+ Q_D(QQuickDial);
+ if (!qFuzzyCompare(d->from, from)) {
+ d->from = from;
+ emit fromChanged();
+ if (isComponentComplete()) {
+ setValue(d->value);
+ d->updatePosition();
+ }
+ }
+}
+
+/*!
+ \qmlproperty real QtQuickControls2::Dial::to
+
+ This property holds the end value for the range. The default value is
+ \c 1.0.
+
+ \sa from, value
+*/
+qreal QQuickDial::to() const
+{
+ Q_D(const QQuickDial);
+ return d->to;
+}
+
+void QQuickDial::setTo(qreal to)
+{
+ Q_D(QQuickDial);
+ if (!qFuzzyCompare(d->to, to)) {
+ d->to = to;
+ emit toChanged();
+ if (isComponentComplete()) {
+ setValue(d->value);
+ d->updatePosition();
+ }
+ }
+}
+
+/*!
+ \qmlproperty real QtQuickControls2::Dial::value
+
+ This property holds the value in the range \c from - \c to. The default
+ value is \c 0.0.
+
+ Unlike the \l position property, the \c value is not updated while the
+ handle is dragged. The value is updated after the value has been chosen
+ and the dial has been released.
+
+ \sa position
+*/
+qreal QQuickDial::value() const
+{
+ Q_D(const QQuickDial);
+ return d->value;
+}
+
+void QQuickDial::setValue(qreal value)
+{
+ Q_D(QQuickDial);
+ if (isComponentComplete())
+ value = d->from > d->to ? qBound(d->to, value, d->from) : qBound(d->from, value, d->to);
+
+ if (!qFuzzyCompare(d->value, value)) {
+ d->value = value;
+ d->updatePosition();
+ emit valueChanged();
+ }
+}
+
+/*!
+ \qmlproperty real QtQuickControls2::Dial::position
+
+ This property holds the logical position of the handle.
+
+ The position is defined as a percentage of the control's angle range (the
+ range within which the handle can be moved) scaled to \c {0.0 - 1.0}.
+ Unlike the \l value property, the \c position is continuously updated while
+ the handle is dragged.
+
+ \sa value, angle
+*/
+qreal QQuickDial::position() const
+{
+ Q_D(const QQuickDial);
+ return d->position;
+}
+
+/*!
+ \qmlproperty real QtQuickControls2::Dial::angle \readonly
+
+ This property holds the angle of the handle.
+
+ Like the \l position property, angle is continuously updated while the
+ handle is dragged.
+
+ \sa position
+*/
+qreal QQuickDial::angle() const
+{
+ Q_D(const QQuickDial);
+ return d->angle;
+}
+
+/*!
+ \qmlproperty real QtQuickControls2::Dial::stepSize
+
+ This property holds the step size. The default value is \c 0.0.
+
+ \sa snapMode, increase(), decrease()
+*/
+qreal QQuickDial::stepSize() const
+{
+ Q_D(const QQuickDial);
+ return d->stepSize;
+}
+
+void QQuickDial::setStepSize(qreal step)
+{
+ Q_D(QQuickDial);
+ if (!qFuzzyCompare(d->stepSize, step)) {
+ d->stepSize = step;
+ emit stepSizeChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration QtQuickControls2::Dial::snapMode
+
+ This property holds the snap mode.
+
+ The snap mode works with the \l stepSize to allow the handle to snap to
+ certain points along the dial.
+
+ Possible values:
+ \list
+ \li \c Dial.NoSnap (default) - The dial does not snap.
+ \li \c Dial.SnapAlways - The dial snaps while the handle is dragged.
+ \li \c Dial.SnapOnRelease - The dial does not snap while being dragged, but only after the handle is released.
+ \endlist
+
+ \sa stepSize
+*/
+QQuickDial::SnapMode QQuickDial::snapMode() const
+{
+ Q_D(const QQuickDial);
+ return d->snapMode;
+}
+
+void QQuickDial::setSnapMode(SnapMode mode)
+{
+ Q_D(QQuickDial);
+ if (d->snapMode != mode) {
+ d->snapMode = mode;
+ emit snapModeChanged();
+ }
+}
+
+/*!
+ \qmlproperty bool QtQuickControls2::Dial::pressed
+
+ This property holds whether the dial is pressed.
+
+ The dial will be pressed when either the mouse is pressed over it, or a key
+ such as \c Qt.Key_Left is held down. If you'd prefer not to have the dial
+ be pressed upon key presses (due to styling reasons, for example), you can
+ use the \l {Keys}{Keys attached property}:
+
+ \code
+ Dial {
+ Keys.onLeftPressed: {}
+ }
+ \endcode
+
+ This will result in pressed only being \c true upon mouse presses.
+*/
+bool QQuickDial::isPressed() const
+{
+ Q_D(const QQuickDial);
+ return d->pressed;
+}
+
+void QQuickDial::setPressed(bool pressed)
+{
+ Q_D(QQuickDial);
+ if (d->pressed != pressed) {
+ d->pressed = pressed;
+ emit pressedChanged();
+ }
+}
+
+/*!
+ \qmlmethod void QtQuickControls2::Dial::increase()
+
+ Increases the value by \l stepSize, or \c 0.1 if stepSize is not defined.
+
+ \sa stepSize
+*/
+void QQuickDial::increase()
+{
+ Q_D(QQuickDial);
+ qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
+ setValue(d->value + step);
+}
+
+/*!
+ \qmlmethod void QtQuickControls2::Dial::decrease()
+
+ Decreases the value by \l stepSize, or \c 0.1 if stepSize is not defined.
+
+ \sa stepSize
+*/
+void QQuickDial::decrease()
+{
+ Q_D(QQuickDial);
+ qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
+ setValue(d->value - step);
+}
+
+/*!
+ \qmlproperty component QtQuickControls2::Dial::handle
+
+ This property holds the handle of the dial.
+
+ The handle acts as a visual indicator of the position of the dial.
+
+ \sa {Customizing Dial}
+*/
+QQuickItem *QQuickDial::handle() const
+{
+ Q_D(const QQuickDial);
+ return d->handle;
+}
+
+void QQuickDial::setHandle(QQuickItem *handle)
+{
+ Q_D(QQuickDial);
+ if (handle != d->handle) {
+ d->handle = handle;
+ if (d->handle && !d->handle->parentItem())
+ d->handle->setParentItem(this);
+ emit handleChanged();
+ }
+}
+
+void QQuickDial::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickDial);
+ if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Down) {
+ setPressed(true);
+ if (isMirrored())
+ increase();
+ else
+ decrease();
+ } else if (event->key() == Qt::Key_Right || event->key() == Qt::Key_Up) {
+ setPressed(true);
+ if (isMirrored())
+ decrease();
+ else
+ increase();
+ } else if (event->key() == Qt::Key_Home) {
+ setPressed(true);
+ setValue(isMirrored() ? d->to : d->from);
+ } else if (event->key() == Qt::Key_End) {
+ setPressed(true);
+ setValue(isMirrored() ? d->from : d->to);
+ } else {
+ event->ignore();
+ QQuickControl::keyPressEvent(event);
+ }
+}
+
+void QQuickDial::keyReleaseEvent(QKeyEvent *event)
+{
+ QQuickControl::keyReleaseEvent(event);
+ setPressed(false);
+}
+
+void QQuickDial::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickDial);
+ QQuickControl::mousePressEvent(event);
+ d->pressPoint = event->pos();
+ setPressed(true);
+}
+
+void QQuickDial::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickDial);
+ QQuickControl::mouseMoveEvent(event);
+ if (!keepMouseGrab()) {
+ bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event);
+ setKeepMouseGrab(overXDragThreshold);
+
+ if (!overXDragThreshold) {
+ bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event);
+ setKeepMouseGrab(overYDragThreshold);
+ }
+ }
+ if (keepMouseGrab()) {
+ qreal pos = d->positionAt(event->pos());
+ if (d->snapMode == SnapAlways)
+ pos = d->snapPosition(pos);
+ d->setPosition(pos);
+ }
+}
+
+void QQuickDial::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickDial);
+ QQuickControl::mouseReleaseEvent(event);
+ d->pressPoint = QPoint();
+ if (keepMouseGrab()) {
+ qreal pos = d->positionAt(event->pos());
+ if (d->snapMode != NoSnap)
+ pos = d->snapPosition(pos);
+ setValue(d->valueAt(pos));
+ setKeepMouseGrab(false);
+ }
+ setPressed(false);
+}
+
+void QQuickDial::mouseUngrabEvent()
+{
+ Q_D(QQuickDial);
+ QQuickControl::mouseUngrabEvent();
+ d->pressPoint = QPoint();
+ setPressed(false);
+}
+
+void QQuickDial::mirrorChange()
+{
+ QQuickControl::mirrorChange();
+ emit angleChanged();
+}
+
+void QQuickDial::componentComplete()
+{
+ Q_D(QQuickDial);
+ QQuickControl::componentComplete();
+ setValue(d->value);
+ d->updatePosition();
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/controls/qquickdial_p.h b/src/imports/controls/qquickdial_p.h
new file mode 100644
index 00000000..a31ad09f
--- /dev/null
+++ b/src/imports/controls/qquickdial_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKDIAL_H
+#define QQUICKDIAL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt 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 <QtCore/qvariant.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQuickTemplates/private/qquickcontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickDialAttached;
+class QQuickDialPrivate;
+
+class QQuickDial : public QQuickControl
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged FINAL)
+ Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged FINAL)
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged FINAL)
+ Q_PROPERTY(qreal position READ position NOTIFY positionChanged FINAL)
+ Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged FINAL)
+ Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
+ Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL)
+ Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
+
+public:
+ explicit QQuickDial(QQuickItem *parent = Q_NULLPTR);
+
+ qreal from() const;
+ void setFrom(qreal from);
+
+ qreal to() const;
+ void setTo(qreal to);
+
+ qreal value() const;
+ void setValue(qreal value);
+
+ qreal position() const;
+
+ qreal angle() const;
+
+ qreal stepSize() const;
+ void setStepSize(qreal step);
+
+ enum SnapMode {
+ NoSnap,
+ SnapAlways,
+ SnapOnRelease
+ };
+ Q_ENUM(SnapMode)
+
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ bool isPressed() const;
+ void setPressed(bool pressed);
+
+ QQuickItem *handle() const;
+ void setHandle(QQuickItem *handle);
+
+public Q_SLOTS:
+ void increase();
+ void decrease();
+
+Q_SIGNALS:
+ void fromChanged();
+ void toChanged();
+ void valueChanged();
+ void positionChanged();
+ void angleChanged();
+ void stepSizeChanged();
+ void snapModeChanged();
+ void pressedChanged();
+ void handleChanged();
+
+protected:
+ void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+ void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ void mirrorChange() Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(QQuickDial)
+ Q_DECLARE_PRIVATE(QQuickDial)
+};
+
+Q_DECLARE_TYPEINFO(QQuickDial, Q_COMPLEX_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QQUICKDIAL_H
diff --git a/src/imports/controls/qquickdrawer.cpp b/src/imports/controls/qquickdrawer.cpp
new file mode 100644
index 00000000..23988432
--- /dev/null
+++ b/src/imports/controls/qquickdrawer.cpp
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdrawer_p.h"
+
+#include <QtGui/qstylehints.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuickTemplates/private/qquickcontrol_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickDrawerPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickDrawer)
+
+public:
+ QQuickDrawerPrivate() : edge(Qt::LeftEdge), offset(0), position(0),
+ content(Q_NULLPTR), animation(Q_NULLPTR) { }
+
+ void updateContent();
+ bool handleMousePressEvent(QQuickItem *item, QMouseEvent *event);
+ bool handleMouseMoveEvent(QQuickItem *item, QMouseEvent *event);
+ bool handleMouseReleaseEvent(QQuickItem *item, QMouseEvent *event);
+
+ Qt::Edge edge;
+ qreal offset;
+ qreal position;
+ QPointF pressPoint;
+ QQuickItem *content;
+ QQuickPropertyAnimation *animation;
+};
+
+void QQuickDrawerPrivate::updateContent()
+{
+ Q_Q(QQuickDrawer);
+ if (!content)
+ return;
+
+ switch (edge) {
+ case Qt::LeftEdge:
+ content->setX((position - 1.0) * content->width());
+ break;
+ case Qt::RightEdge:
+ content->setX(q->width() + - position * content->width());
+ break;
+ case Qt::TopEdge:
+ content->setY((position - 1.0) * content->height());
+ break;
+ case Qt::BottomEdge:
+ content->setY(q->height() + - position * content->height());
+ break;
+ }
+}
+
+bool QQuickDrawerPrivate::handleMousePressEvent(QQuickItem *item, QMouseEvent *event)
+{
+ Q_Q(QQuickDrawer);
+ pressPoint = q->mapFromItem(item, event->pos());
+
+ if (qFuzzyIsNull(position)) {
+ // only accept pressing at drag margins when fully closed
+ switch (edge) {
+ case Qt::LeftEdge:
+ event->setAccepted(!QQuickWindowPrivate::dragOverThreshold(event->x(), Qt::XAxis, event));
+ break;
+ case Qt::RightEdge:
+ event->setAccepted(!QQuickWindowPrivate::dragOverThreshold(q->width() - event->x(), Qt::XAxis, event));
+ break;
+ case Qt::TopEdge:
+ event->setAccepted(!QQuickWindowPrivate::dragOverThreshold(event->y(), Qt::YAxis, event));
+ break;
+ case Qt::BottomEdge:
+ event->setAccepted(!QQuickWindowPrivate::dragOverThreshold(q->height() - event->y(), Qt::YAxis, event));
+ break;
+ }
+ offset = 0;
+ } else {
+ event->accept();
+ offset = q->positionAt(pressPoint) - position;
+ }
+
+ return item == q;
+}
+
+bool QQuickDrawerPrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEvent *event)
+{
+ Q_Q(QQuickDrawer);
+ QPointF movePoint = q->mapFromItem(item, event->pos());
+
+ if (!q->keepMouseGrab()) {
+ bool overThreshold = false;
+ if (edge == Qt::LeftEdge || edge == Qt::RightEdge)
+ overThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.x() - pressPoint.x(), Qt::XAxis, event);
+ else
+ overThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.y() - pressPoint.y(), Qt::YAxis, event);
+
+ if (window && overThreshold) {
+ QQuickItem *grabber = q->window()->mouseGrabberItem();
+ if (!grabber || !grabber->keepMouseGrab()) {
+ q->grabMouse();
+ q->setKeepMouseGrab(overThreshold);
+ }
+ }
+ }
+
+ if (q->keepMouseGrab())
+ q->setPosition(q->positionAt(event->pos()) - offset);
+ event->accept();
+
+ return q->keepMouseGrab();
+}
+
+bool QQuickDrawerPrivate::handleMouseReleaseEvent(QQuickItem *item, QMouseEvent *event)
+{
+ Q_Q(QQuickDrawer);
+ bool wasGrabbed = q->keepMouseGrab();
+ if (wasGrabbed) {
+// int startDragVelocity = QGuiApplication::styleHints()->startDragVelocity();
+// if (startDragVelocity && QGuiApplicationPrivate::mouseEventCaps(event) & QTouchDevice::Velocity) {
+// QVector2D velocity = QGuiApplicationPrivate::mouseEventVelocity(event);
+// qreal vel = (edge == Qt::LeftEdge || edge == Qt::RightEdge) ? velocity.x() : velocity.y();
+// qDebug() << vel << "vs." << startDragVelocity;
+// }
+ if (position < 0.3) {
+ q->close();
+ } else if (position > 0.7) {
+ q->open();
+ } else {
+ switch (edge) {
+ case Qt::LeftEdge:
+ if (event->x() - pressPoint.x() > 0)
+ q->open();
+ else
+ q->close();
+ break;
+ case Qt::RightEdge:
+ if (event->x() - pressPoint.x() < 0)
+ q->open();
+ else
+ q->close();
+ break;
+ case Qt::TopEdge:
+ if (event->y() - pressPoint.y() > 0)
+ q->open();
+ else
+ q->close();
+ break;
+ case Qt::BottomEdge:
+ if (event->y() - pressPoint.y() < 0)
+ q->open();
+ else
+ q->close();
+ break;
+ }
+ }
+ q->setKeepMouseGrab(false);
+ } else {
+ if (item == q)
+ emit q->clicked();
+ }
+ pressPoint = QPoint();
+ event->accept();
+ return wasGrabbed;
+}
+
+QQuickDrawer::QQuickDrawer(QQuickItem *parent) :
+ QQuickControl(*(new QQuickDrawerPrivate), parent)
+{
+ setZ(1);
+ setFiltersChildMouseEvents(true);
+ setAcceptedMouseButtons(Qt::LeftButton);
+}
+
+Qt::Edge QQuickDrawer::edge() const
+{
+ Q_D(const QQuickDrawer);
+ return d->edge;
+}
+
+void QQuickDrawer::setEdge(Qt::Edge edge)
+{
+ Q_D(QQuickDrawer);
+ if (d->edge != edge) {
+ d->edge = edge;
+ if (isComponentComplete())
+ d->updateContent();
+ emit edgeChanged();
+ }
+}
+
+qreal QQuickDrawer::position() const
+{
+ Q_D(const QQuickDrawer);
+ return d->position;
+}
+
+void QQuickDrawer::setPosition(qreal position)
+{
+ Q_D(QQuickDrawer);
+ position = qBound(0.0, position, 1.0);
+ if (!qFuzzyCompare(d->position, position)) {
+ d->position = position;
+ if (isComponentComplete())
+ d->updateContent();
+ emit positionChanged();
+ }
+}
+
+QQuickItem *QQuickDrawer::contentItem() const
+{
+ Q_D(const QQuickDrawer);
+ return d->content;
+}
+
+void QQuickDrawer::setContentItem(QQuickItem *item)
+{
+ Q_D(QQuickDrawer);
+ if (d->content != item) {
+ delete d->content;
+ d->content = item;
+ if (item)
+ item->setParentItem(this);
+ if (isComponentComplete())
+ d->updateContent();
+ emit contentItemChanged();
+ }
+}
+
+QQuickPropertyAnimation *QQuickDrawer::animation() const
+{
+ Q_D(const QQuickDrawer);
+ return d->animation;
+}
+
+void QQuickDrawer::setAnimation(QQuickPropertyAnimation *animation)
+{
+ Q_D(QQuickDrawer);
+ if (d->animation != animation) {
+ delete d->animation;
+ d->animation = animation;
+ if (animation) {
+ animation->setTargetObject(this);
+ animation->setProperty(QStringLiteral("position"));
+ }
+ emit animationChanged();
+ }
+}
+
+void QQuickDrawer::open()
+{
+ Q_D(QQuickDrawer);
+ if (d->animation) {
+ d->animation->stop();
+ d->animation->setFrom(d->position);
+ d->animation->setTo(1.0);
+ d->animation->start();
+ } else {
+ setPosition(1.0);
+ }
+}
+
+void QQuickDrawer::close()
+{
+ Q_D(QQuickDrawer);
+ if (d->animation) {
+ d->animation->stop();
+ d->animation->setFrom(d->position);
+ d->animation->setTo(0.0);
+ d->animation->start();
+ } else {
+ setPosition(0.0);
+ }
+}
+
+bool QQuickDrawer::childMouseEventFilter(QQuickItem *child, QEvent *event)
+{
+ Q_D(QQuickDrawer);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ return d->handleMousePressEvent(child, static_cast<QMouseEvent *>(event));
+ case QEvent::MouseMove:
+ return d->handleMouseMoveEvent(child, static_cast<QMouseEvent *>(event));
+ case QEvent::MouseButtonRelease:
+ return d->handleMouseReleaseEvent(child, static_cast<QMouseEvent *>(event));
+ default:
+ return false;
+ }
+}
+
+void QQuickDrawer::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickDrawer);
+ QQuickControl::mousePressEvent(event);
+ d->handleMousePressEvent(this, event);
+}
+
+void QQuickDrawer::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickDrawer);
+ QQuickControl::mouseMoveEvent(event);
+ d->handleMouseMoveEvent(this, event);
+}
+
+void QQuickDrawer::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickDrawer);
+ QQuickControl::mouseReleaseEvent(event);
+ d->handleMouseReleaseEvent(this, event);
+}
+
+void QQuickDrawer::mouseUngrabEvent()
+{
+ Q_D(QQuickDrawer);
+ QQuickControl::mouseUngrabEvent();
+ d->pressPoint = QPoint();
+}
+
+void QQuickDrawer::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickDrawer);
+ QQuickControl::geometryChanged(newGeometry, oldGeometry);
+ if (isComponentComplete())
+ d->updateContent();
+}
+
+void QQuickDrawer::componentComplete()
+{
+ Q_D(QQuickDrawer);
+ QQuickControl::componentComplete();
+ d->updateContent();
+}
+
+qreal QQuickDrawer::positionAt(const QPointF &point) const
+{
+ Q_D(const QQuickDrawer);
+ if (!d->content)
+ return 0.0;
+
+ switch (d->edge) {
+ case Qt::TopEdge:
+ return point.y() / d->content->height();
+ case Qt::LeftEdge:
+ return point.x() / d->content->width();
+ case Qt::RightEdge:
+ return (width() - point.x()) / d->content->width();
+ case Qt::BottomEdge:
+ return (height() - point.y()) / d->content->height();
+ default:
+ return 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/controls/qquickdrawer_p.h b/src/imports/controls/qquickdrawer_p.h
new file mode 100644
index 00000000..1fd8b21a
--- /dev/null
+++ b/src/imports/controls/qquickdrawer_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKDRAWER_P_H
+#define QQUICKDRAWER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt 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 <QtQuickTemplates/private/qquickcontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPropertyAnimation;
+class QQuickDrawerPrivate;
+
+class QQuickDrawer : public QQuickControl
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged FINAL)
+ Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
+ Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL)
+ // TODO: make this a proper transition
+ Q_PROPERTY(QQuickPropertyAnimation *animation READ animation WRITE setAnimation NOTIFY animationChanged FINAL)
+ Q_CLASSINFO("DefaultProperty", "contentItem")
+
+public:
+ explicit QQuickDrawer(QQuickItem *parent = Q_NULLPTR);
+
+ Qt::Edge edge() const;
+ void setEdge(Qt::Edge edge);
+
+ qreal position() const;
+ void setPosition(qreal position);
+
+ QQuickItem *contentItem() const;
+ void setContentItem(QQuickItem *item);
+
+ QQuickPropertyAnimation *animation() const;
+ void setAnimation(QQuickPropertyAnimation *animation);
+
+public Q_SLOTS:
+ void open();
+ void close();
+
+Q_SIGNALS:
+ void clicked();
+ void edgeChanged();
+ void positionChanged();
+ void contentItemChanged();
+ void animationChanged();
+
+protected:
+ bool childMouseEventFilter(QQuickItem *child, QEvent *event) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
+
+ virtual qreal positionAt(const QPointF &point) const;
+
+private:
+ Q_DISABLE_COPY(QQuickDrawer)
+ Q_DECLARE_PRIVATE(QQuickDrawer)
+};
+
+Q_DECLARE_TYPEINFO(QQuickDrawer, Q_COMPLEX_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QQUICKDRAWER_P_H
diff --git a/src/imports/controls/qquickswipeview.cpp b/src/imports/controls/qquickswipeview.cpp
new file mode 100644
index 00000000..f86e8c8c
--- /dev/null
+++ b/src/imports/controls/qquickswipeview.cpp
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickswipeview_p.h"
+
+#include <QtQuickTemplates/private/qquickcontainer_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype SwipeView
+ \inherits Container
+ \instantiates QQuickSwipeView
+ \inqmlmodule QtQuick.Controls
+ \ingroup navigation
+ \brief A swipe view control.
+
+ TODO
+*/
+
+class QQuickSwipeViewPrivate : public QQuickContainerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickSwipeView)
+
+public:
+ QQuickSwipeViewPrivate() : updatingCurrent(false) { }
+
+ void resizeItem(QQuickItem *item);
+ void resizeItems();
+ void _q_updateCurrent();
+
+ void itemInserted(int index, QQuickItem *item) Q_DECL_OVERRIDE;
+ void itemMoved(int from, int to) Q_DECL_OVERRIDE;
+
+ static QQuickSwipeViewPrivate *get(QQuickSwipeView *view);
+
+ bool updatingCurrent;
+};
+
+void QQuickSwipeViewPrivate::resizeItems()
+{
+ Q_Q(QQuickSwipeView);
+ const int count = q->count();
+ for (int i = 0; i < count; ++i) {
+ QQuickItem *item = itemAt(i);
+ if (item)
+ item->setSize(QSizeF(contentItem->width(), contentItem->height()));
+ }
+}
+
+void QQuickSwipeViewPrivate::_q_updateCurrent()
+{
+ Q_Q(QQuickSwipeView);
+ if (!updatingCurrent)
+ q->setCurrentIndex(contentItem ? contentItem->property("currentIndex").toInt() : -1);
+}
+
+void QQuickSwipeViewPrivate::itemInserted(int, QQuickItem *item)
+{
+ Q_Q(QQuickSwipeView);
+ if (q->isComponentComplete())
+ item->setSize(QSizeF(contentItem->width(), contentItem->height()));
+}
+
+void QQuickSwipeViewPrivate::itemMoved(int from, int to)
+{
+ Q_Q(QQuickSwipeView);
+ updatingCurrent = true;
+ if (from == currentIndex)
+ q->setCurrentIndex(to);
+ else if (from < currentIndex && to >= currentIndex)
+ q->setCurrentIndex(currentIndex - 1);
+ else if (from > currentIndex && to <= currentIndex)
+ q->setCurrentIndex(currentIndex + 1);
+ updatingCurrent = false;
+}
+
+
+QQuickSwipeViewPrivate *QQuickSwipeViewPrivate::get(QQuickSwipeView *view)
+{
+ return view->d_func();
+}
+
+QQuickSwipeView::QQuickSwipeView(QQuickItem *parent) :
+ QQuickContainer(*(new QQuickSwipeViewPrivate), parent)
+{
+ setFlag(ItemIsFocusScope);
+ setActiveFocusOnTab(true);
+}
+
+QQuickSwipeViewAttached *QQuickSwipeView::qmlAttachedProperties(QObject *object)
+{
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
+ if (!item) {
+ qWarning() << "SwipeView: attached properties must be accessed from within a child item";
+ return Q_NULLPTR;
+ }
+
+ return new QQuickSwipeViewAttached(item);
+}
+
+void QQuickSwipeView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickSwipeView);
+ QQuickContainer::geometryChanged(newGeometry, oldGeometry);
+ d->resizeItems();
+}
+
+void QQuickSwipeView::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ QQuickContainer::contentItemChange(newItem, oldItem);
+ if (oldItem)
+ disconnect(oldItem, SIGNAL(currentIndexChanged()), this, SLOT(_q_updateCurrent()));
+ if (newItem)
+ connect(newItem, SIGNAL(currentIndexChanged()), this, SLOT(_q_updateCurrent()));
+}
+
+/*!
+ \qmlattachedproperty int QtQuickControls2::SwipeView::index
+
+ This attached property holds the index of each child item in the SwipeView.
+
+ It is attached to each child item of the SwipeView.
+*/
+
+/*!
+ \qmlattachedproperty bool QtQuickControls2::SwipeView::isCurrentItem
+
+ This attached property is \c true if this child is the current item.
+
+ It is attached to each child item of the SwipeView.
+*/
+
+/*!
+ \qmlattachedproperty SwipeView QtQuickControls2::SwipeView::view
+
+ This attached property holds the view that manages this child item.
+
+ It is attached to each child item of the SwipeView.
+*/
+
+class QQuickSwipeViewAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickSwipeViewAttached)
+public:
+ QQuickSwipeViewAttachedPrivate(QQuickItem *item) :
+ item(item),
+ swipeView(Q_NULLPTR),
+ index(-1),
+ isCurrent(false)
+ {
+ }
+
+ ~QQuickSwipeViewAttachedPrivate() {
+ }
+
+ void updateView(QQuickItem *parent);
+
+ void itemChildAdded(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+ void itemChildRemoved(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+ void itemParentChanged(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+
+ void updateIndex();
+ void updateIsCurrent();
+
+ void setView(QQuickSwipeView *view);
+ void setIndex(int i);
+ void setIsCurrent(bool current);
+
+ QQuickItem *item;
+ QQuickSwipeView *swipeView;
+ int index;
+ // Better to store this so that we don't need to lump its calculation
+ // together with index's calculation, as it would otherwise need to know
+ // the old index to know if it should emit the change signal.
+ bool isCurrent;
+};
+
+void QQuickSwipeViewAttachedPrivate::updateIndex()
+{
+ setIndex(swipeView ? QQuickSwipeViewPrivate::get(swipeView)->contentModel->indexOf(item, Q_NULLPTR) : -1);
+}
+
+void QQuickSwipeViewAttachedPrivate::updateIsCurrent()
+{
+ setIsCurrent(swipeView ? swipeView->currentIndex() == index : false);
+}
+
+void QQuickSwipeViewAttachedPrivate::setView(QQuickSwipeView *view)
+{
+ if (view == swipeView)
+ return;
+
+ if (swipeView) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(swipeView);
+ p->removeItemChangeListener(this, QQuickItemPrivate::Children);
+
+ disconnect(swipeView, &QQuickSwipeView::currentIndexChanged,
+ this, &QQuickSwipeViewAttachedPrivate::updateIsCurrent);
+ disconnect(swipeView, &QQuickSwipeView::contentChildrenChanged,
+ this, &QQuickSwipeViewAttachedPrivate::updateIndex);
+ }
+
+ swipeView = view;
+
+ if (swipeView) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(swipeView);
+ p->addItemChangeListener(this, QQuickItemPrivate::Children);
+
+ connect(swipeView, &QQuickSwipeView::currentIndexChanged,
+ this, &QQuickSwipeViewAttachedPrivate::updateIsCurrent);
+ connect(swipeView, &QQuickSwipeView::contentChildrenChanged,
+ this, &QQuickSwipeViewAttachedPrivate::updateIndex);
+ }
+
+ Q_Q(QQuickSwipeViewAttached);
+ emit q->viewChanged();
+
+ updateIndex();
+ updateIsCurrent();
+}
+
+void QQuickSwipeViewAttachedPrivate::setIsCurrent(bool current)
+{
+ if (current != isCurrent) {
+ isCurrent = current;
+ Q_Q(QQuickSwipeViewAttached);
+ emit q->isCurrentItemChanged();
+ }
+}
+
+void QQuickSwipeViewAttachedPrivate::setIndex(int i)
+{
+ if (i != index) {
+ index = i;
+ Q_Q(QQuickSwipeViewAttached);
+ emit q->indexChanged();
+ }
+}
+
+void QQuickSwipeViewAttachedPrivate::updateView(QQuickItem *parent)
+{
+ // parent can be, e.g.:
+ // - The contentItem of a ListView (typically the case)
+ // - A non-visual or weird type like TestCase, when child items are created from components
+ // wherein the attached properties are used
+ // - null, when the item was removed with removeItem()
+ QQuickSwipeView *view = Q_NULLPTR;
+ if (parent) {
+ view = qobject_cast<QQuickSwipeView*>(parent);
+ if (!view) {
+ if (parent->parentItem() && parent->parentItem()->property("contentItem").isValid()) {
+ // The parent is the contentItem of some kind of view.
+ view = qobject_cast<QQuickSwipeView*>(parent->parentItem()->parentItem());
+ }
+ }
+ }
+
+ setView(view);
+}
+
+void QQuickSwipeViewAttachedPrivate::itemChildAdded(QQuickItem *, QQuickItem *)
+{
+ updateIndex();
+}
+
+void QQuickSwipeViewAttachedPrivate::itemChildRemoved(QQuickItem *, QQuickItem *)
+{
+ updateIndex();
+}
+
+void QQuickSwipeViewAttachedPrivate::itemParentChanged(QQuickItem *, QQuickItem *parent)
+{
+ updateView(parent);
+}
+
+QQuickSwipeViewAttached::QQuickSwipeViewAttached(QQuickItem *item) :
+ QObject(*(new QQuickSwipeViewAttachedPrivate(item)), item)
+{
+ Q_D(QQuickSwipeViewAttached);
+ if (item->parentItem()) {
+ d->updateView(item->parentItem());
+ } else {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ p->addItemChangeListener(d, QQuickItemPrivate::Parent);
+ }
+}
+
+QQuickSwipeViewAttached::~QQuickSwipeViewAttached()
+{
+}
+
+QQuickSwipeView *QQuickSwipeViewAttached::view() const
+{
+ Q_D(const QQuickSwipeViewAttached);
+ return d->swipeView;
+}
+
+int QQuickSwipeViewAttached::index() const
+{
+ Q_D(const QQuickSwipeViewAttached);
+ return d->index;
+}
+
+bool QQuickSwipeViewAttached::isCurrentItem() const
+{
+ Q_D(const QQuickSwipeViewAttached);
+ return d->swipeView ? d->swipeView->currentIndex() == d->index : false;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickswipeview_p.cpp"
diff --git a/src/imports/controls/qquickswipeview_p.h b/src/imports/controls/qquickswipeview_p.h
new file mode 100644
index 00000000..e7e1600c
--- /dev/null
+++ b/src/imports/controls/qquickswipeview_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSWIPEVIEW_P_H
+#define QQUICKSWIPEVIEW_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt 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 <QtQuickTemplates/private/qquickcontainer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickSwipeViewAttached;
+class QQuickSwipeViewPrivate;
+
+class QQuickSwipeView : public QQuickContainer
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickSwipeView(QQuickItem *parent = Q_NULLPTR);
+
+ static QQuickSwipeViewAttached *qmlAttachedProperties(QObject *object);
+
+protected:
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(QQuickSwipeView)
+ Q_DECLARE_PRIVATE(QQuickSwipeView)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_updateCurrent())
+};
+
+class QQuickSwipeViewAttachedPrivate;
+
+class QQuickSwipeViewAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL)
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY isCurrentItemChanged FINAL)
+ Q_PROPERTY(QQuickSwipeView *view READ view NOTIFY viewChanged FINAL)
+
+public:
+ explicit QQuickSwipeViewAttached(QQuickItem *delegateItem);
+ ~QQuickSwipeViewAttached();
+
+ int index() const;
+ bool isCurrentItem() const;
+ QQuickSwipeView *view() const;
+
+Q_SIGNALS:
+ void indexChanged();
+ void isCurrentItemChanged();
+ void viewChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickSwipeViewAttached)
+ Q_DECLARE_PRIVATE(QQuickSwipeViewAttached)
+};
+
+Q_DECLARE_TYPEINFO(QQuickSwipeView, Q_COMPLEX_TYPE);
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPEINFO(QQuickSwipeView, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKSWIPEVIEW_P_H
diff --git a/src/imports/controls/qquicktumbler.cpp b/src/imports/controls/qquicktumbler.cpp
new file mode 100644
index 00000000..9f53f92e
--- /dev/null
+++ b/src/imports/controls/qquicktumbler.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquicktumbler_p.h"
+
+#include <QtQuick/private/qquickflickable_p.h>
+#include <QtQuickTemplates/private/qquickcontrol_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Tumbler
+ \inherits Control
+ \instantiates QQuickTumbler
+ \inqmlmodule QtQuick.Controls
+ \ingroup containers
+ \brief A spinnable wheel of items that can be selected.
+
+ \code
+ Tumbler {
+ model: 5
+ }
+ \endcode
+
+ \section1 Non-wrapping Tumbler
+
+ The default contentItem of Tumbler is a \l PathView, which wraps when it
+ reaches the top and bottom. To achieve a non-wrapping Tumbler, use ListView
+ as the contentItem:
+
+ \snippet tst_tumbler.qml contentItem
+
+ \image qtquickcontrols2-tumbler-wrap.gif
+*/
+
+class QQuickTumblerPrivate : public QQuickControlPrivate, public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickTumbler)
+
+public:
+ QQuickTumblerPrivate() :
+ delegate(Q_NULLPTR),
+ visibleItemCount(3)
+ {
+ }
+
+ ~QQuickTumblerPrivate()
+ {
+ }
+
+ QVariant model;
+ QQmlComponent *delegate;
+ int visibleItemCount;
+
+ void _q_updateItemHeights();
+ void _q_updateItemWidths();
+
+ void itemChildAdded(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+ void itemChildRemoved(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+};
+
+static QList<QQuickItem *> contentItemChildItems(QQuickItem *contentItem)
+{
+ if (!contentItem)
+ return QList<QQuickItem *>();
+
+ // PathView has no contentItem property, but ListView does.
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(contentItem);
+ return flickable ? flickable->contentItem()->childItems() : contentItem->childItems();
+}
+
+namespace {
+ static inline qreal delegateHeight(const QQuickTumbler *tumbler)
+ {
+ return tumbler->availableHeight() / tumbler->visibleItemCount();
+ }
+
+ enum ContentItemType {
+ UnsupportedContentItemType,
+ PathViewContentItem,
+ ListViewContentItem
+ };
+
+ static inline QQuickItem *actualContentItem(QQuickItem *rootContentItem, ContentItemType contentType)
+ {
+ if (contentType == PathViewContentItem)
+ return rootContentItem;
+ else if (contentType == ListViewContentItem)
+ return qobject_cast<QQuickFlickable*>(rootContentItem)->contentItem();
+
+ return Q_NULLPTR;
+ }
+
+ static inline ContentItemType contentItemType(QQuickItem *rootContentItem)
+ {
+ if (rootContentItem->inherits("QQuickPathView"))
+ return PathViewContentItem;
+ else if (rootContentItem->inherits("QQuickListView"))
+ return ListViewContentItem;
+
+ return UnsupportedContentItemType;
+ }
+
+ static inline ContentItemType contentItemTypeFromDelegate(QQuickItem *delegateItem)
+ {
+ if (delegateItem->parentItem()->inherits("QQuickPathView")) {
+ return PathViewContentItem;
+ } else if (delegateItem->parentItem()->parentItem()
+ && delegateItem->parentItem()->parentItem()->inherits("QQuickListView")) {
+ return ListViewContentItem;
+ }
+
+ return UnsupportedContentItemType;
+ }
+}
+
+void QQuickTumblerPrivate::_q_updateItemHeights()
+{
+ // Can't use our own private padding members here, as the padding property might be set,
+ // which doesn't affect them, only their getters.
+ Q_Q(const QQuickTumbler);
+ const qreal itemHeight = delegateHeight(q);
+ foreach (QQuickItem *childItem, contentItemChildItems(contentItem))
+ childItem->setHeight(itemHeight);
+}
+
+void QQuickTumblerPrivate::_q_updateItemWidths()
+{
+ Q_Q(const QQuickTumbler);
+ const qreal availableWidth = q->availableWidth();
+ foreach (QQuickItem *childItem, contentItemChildItems(contentItem))
+ childItem->setWidth(availableWidth);
+}
+
+void QQuickTumblerPrivate::itemChildAdded(QQuickItem *, QQuickItem *)
+{
+ _q_updateItemWidths();
+ _q_updateItemHeights();
+}
+
+void QQuickTumblerPrivate::itemChildRemoved(QQuickItem *, QQuickItem *)
+{
+ _q_updateItemWidths();
+ _q_updateItemHeights();
+}
+
+QQuickTumbler::QQuickTumbler(QQuickItem *parent) :
+ QQuickControl(*(new QQuickTumblerPrivate), parent)
+{
+ setActiveFocusOnTab(true);
+
+ connect(this, SIGNAL(leftPaddingChanged()), this, SLOT(_q_updateItemWidths()));
+ connect(this, SIGNAL(rightPaddingChanged()), this, SLOT(_q_updateItemWidths()));
+ connect(this, SIGNAL(topPaddingChanged()), this, SLOT(_q_updateItemHeights()));
+ connect(this, SIGNAL(bottomPaddingChanged()), this, SLOT(_q_updateItemHeights()));
+}
+
+QQuickTumbler::~QQuickTumbler()
+{
+}
+
+/*!
+ \qmlproperty variant QtQuickControls2::Tumbler::model
+
+ This property holds the model that provides data for this tumbler.
+*/
+QVariant QQuickTumbler::model() const
+{
+ Q_D(const QQuickTumbler);
+ return d->model;
+}
+
+void QQuickTumbler::setModel(const QVariant &model)
+{
+ Q_D(QQuickTumbler);
+ if (model != d->model) {
+ d->model = model;
+ emit modelChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuickControls2::Tumbler::count
+
+ This property holds the number of items in the model.
+*/
+int QQuickTumbler::count() const
+{
+ Q_D(const QQuickTumbler);
+ return d->contentItem->property("count").toInt();
+}
+
+/*!
+ \qmlproperty int QtQuickControls2::Tumbler::currentIndex
+
+ This property holds the index of the current item.
+*/
+int QQuickTumbler::currentIndex() const
+{
+ Q_D(const QQuickTumbler);
+ return d->contentItem ? d->contentItem->property("currentIndex").toInt() : -1;
+}
+
+void QQuickTumbler::setCurrentIndex(int currentIndex)
+{
+ Q_D(QQuickTumbler);
+ d->contentItem->setProperty("currentIndex", currentIndex);
+}
+
+/*!
+ \qmlproperty Item QtQuickControls2::Tumbler::currentItem
+
+ This property holds the item at the current index.
+*/
+QQuickItem *QQuickTumbler::currentItem() const
+{
+ Q_D(const QQuickTumbler);
+ return d->contentItem ? d->contentItem->property("currentItem").value<QQuickItem*>() : Q_NULLPTR;
+}
+
+/*!
+ \qmlproperty component QtQuickControls2::Tumbler::delegate
+
+ This property holds the delegate used to display each item.
+*/
+QQmlComponent *QQuickTumbler::delegate() const
+{
+ Q_D(const QQuickTumbler);
+ return d->delegate;
+}
+
+void QQuickTumbler::setDelegate(QQmlComponent *delegate)
+{
+ Q_D(QQuickTumbler);
+ if (delegate != d->delegate) {
+ d->delegate = delegate;
+ emit delegateChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuickControls2::Tumbler::visibleItemCount
+
+ This property holds the number of items visible in the tumbler. It must be
+ an odd number, as the current item is always vertically centered.
+*/
+int QQuickTumbler::visibleItemCount() const
+{
+ Q_D(const QQuickTumbler);
+ return d->visibleItemCount;
+}
+
+void QQuickTumbler::setVisibleItemCount(int visibleItemCount)
+{
+ Q_D(QQuickTumbler);
+ if (visibleItemCount != d->visibleItemCount) {
+ d->visibleItemCount = visibleItemCount;
+ d->_q_updateItemHeights();
+ emit visibleItemCountChanged();
+ }
+}
+
+QQuickTumblerAttached *QQuickTumbler::qmlAttachedProperties(QObject *object)
+{
+ QQuickItem *delegateItem = qobject_cast<QQuickItem *>(object);
+ if (!delegateItem) {
+ qWarning() << "Tumbler: attached properties of Tumbler must be accessed from within a delegate item";
+ return Q_NULLPTR;
+ }
+
+ return new QQuickTumblerAttached(delegateItem);
+}
+
+void QQuickTumbler::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickTumbler);
+
+ QQuickControl::geometryChanged(newGeometry, oldGeometry);
+
+ d->_q_updateItemHeights();
+
+ if (newGeometry.width() != oldGeometry.width())
+ d->_q_updateItemWidths();
+}
+
+void QQuickTumbler::componentComplete()
+{
+ Q_D(QQuickTumbler);
+ QQuickControl::componentComplete();
+ d->_q_updateItemHeights();
+ d->_q_updateItemWidths();
+}
+
+void QQuickTumbler::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickTumbler);
+
+ QQuickControl::contentItemChange(newItem, oldItem);
+
+ // Since we use the currentIndex of the contentItem directly, we must
+ // ensure that we keep track of the currentIndex so it doesn't get lost
+ // between contentItem changes.
+ const int previousCurrentIndex = currentIndex();
+
+ if (oldItem) {
+ disconnect(oldItem, SIGNAL(currentIndexChanged()), this, SIGNAL(currentIndexChanged()));
+ disconnect(oldItem, SIGNAL(currentItemChanged()), this, SIGNAL(currentItemChanged()));
+ disconnect(oldItem, SIGNAL(countChanged()), this, SIGNAL(countChanged()));
+
+ ContentItemType oldContentItemType = contentItemType(oldItem);
+ QQuickItem *actualOldContentItem = actualContentItem(oldItem, oldContentItemType);
+ QQuickItemPrivate *actualContentItemPrivate = QQuickItemPrivate::get(actualOldContentItem);
+ actualContentItemPrivate->removeItemChangeListener(d, QQuickItemPrivate::Children);
+ }
+
+ if (newItem) {
+ ContentItemType contentType = contentItemType(newItem);
+ if (contentType == UnsupportedContentItemType) {
+ qWarning() << "Tumbler: contentItems other than PathView and ListView are not supported";
+ return;
+ }
+
+ connect(newItem, SIGNAL(currentIndexChanged()), this, SIGNAL(currentIndexChanged()));
+ connect(newItem, SIGNAL(currentItemChanged()), this, SIGNAL(currentItemChanged()));
+ connect(newItem, SIGNAL(countChanged()), this, SIGNAL(countChanged()));
+
+ QQuickItem *actualNewContentItem = actualContentItem(newItem, contentType);
+ QQuickItemPrivate *actualContentItemPrivate = QQuickItemPrivate::get(actualNewContentItem);
+ actualContentItemPrivate->addItemChangeListener(d, QQuickItemPrivate::Children);
+
+ // If the previous currentIndex is -1, it means we had no contentItem previously.
+ if (previousCurrentIndex != -1) {
+ // Can't call setCurrentIndex here, as contentItemChange() is
+ // called *before* the contentItem is set.
+ newItem->setProperty("currentIndex", previousCurrentIndex);
+ }
+ }
+}
+
+void QQuickTumbler::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickTumbler);
+
+ QQuickControl::keyPressEvent(event);
+
+ if (event->isAutoRepeat())
+ return;
+
+ if (event->key() == Qt::Key_Up) {
+ QMetaObject::invokeMethod(d->contentItem, "decrementCurrentIndex");
+ } else if (event->key() == Qt::Key_Down) {
+ QMetaObject::invokeMethod(d->contentItem, "incrementCurrentIndex");
+ }
+}
+
+class QQuickTumblerAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickTumblerAttached)
+public:
+ QQuickTumblerAttachedPrivate(QQuickItem *delegateItem) :
+ tumbler(Q_NULLPTR),
+ index(-1),
+ displacement(1)
+ {
+ if (!delegateItem->parentItem()) {
+ qWarning() << "Tumbler: attached properties must be accessed from within a delegate item that has a parent";
+ return;
+ }
+
+ QVariant indexContextProperty = qmlContext(delegateItem)->contextProperty(QStringLiteral("index"));
+ if (!indexContextProperty.isValid()) {
+ qWarning() << "Tumbler: attempting to access attached property on item without an \"index\" property";
+ return;
+ }
+
+ index = indexContextProperty.toInt();
+ const ContentItemType contentItemType = contentItemTypeFromDelegate(delegateItem);
+ if (contentItemType == UnsupportedContentItemType)
+ return;
+
+ // ListView has an "additional" content item.
+ tumbler = qobject_cast<QQuickTumbler* >(contentItemType == PathViewContentItem
+ ? delegateItem->parentItem()->parentItem() : delegateItem->parentItem()->parentItem()->parentItem());
+ Q_ASSERT(tumbler);
+ }
+
+ ~QQuickTumblerAttachedPrivate() {
+ }
+
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void itemChildAdded(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+ void itemChildRemoved(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+
+ void _q_calculateDisplacement();
+
+ // The Tumbler that contains the delegate. Required to calculated the displacement.
+ QQuickTumbler *tumbler;
+ // The index of the delegate. Used to calculate the displacement.
+ int index;
+ // The displacement for our delegate.
+ qreal displacement;
+};
+
+void QQuickTumblerAttachedPrivate::itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &)
+{
+ _q_calculateDisplacement();
+}
+
+void QQuickTumblerAttachedPrivate::itemChildAdded(QQuickItem *, QQuickItem *)
+{
+ _q_calculateDisplacement();
+}
+
+void QQuickTumblerAttachedPrivate::itemChildRemoved(QQuickItem *item, QQuickItem *child)
+{
+ _q_calculateDisplacement();
+
+ if (parent == child) {
+ // The child that was removed from the contentItem was the delegate
+ // that our properties are attached to. If we don't remove the change
+ // listener, the contentItem will attempt to notify a destroyed
+ // listener, causing a crash.
+
+ // item is the "actual content item" of Tumbler's contentItem, i.e. a PathView or ListView.contentItem
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ p->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Children);
+ }
+}
+
+void QQuickTumblerAttachedPrivate::_q_calculateDisplacement()
+{
+ const int previousDisplacement = displacement;
+ displacement = 0;
+
+ // This can happen in tests, so it may happen in normal usage too.
+ if (tumbler->count() == 0)
+ return;
+
+ ContentItemType contentType = contentItemType(tumbler->contentItem());
+ if (contentType == UnsupportedContentItemType)
+ return;
+
+ qreal offset = 0;
+
+ if (contentType == PathViewContentItem) {
+ offset = tumbler->contentItem()->property("offset").toReal();
+
+ displacement = tumbler->count() - index - offset;
+ int halfVisibleItems = tumbler->visibleItemCount() / 2 + 1;
+ if (displacement > halfVisibleItems)
+ displacement -= tumbler->count();
+ else if (displacement < -halfVisibleItems)
+ displacement += tumbler->count();
+ } else {
+ const qreal contentY = tumbler->contentItem()->property("contentY").toReal();
+ const qreal delegateH = delegateHeight(tumbler);
+ const qreal preferredHighlightBegin = tumbler->contentItem()->property("preferredHighlightBegin").toReal();
+ // Tumbler's displacement goes from negative at the top to positive towards the bottom, so we must switch this around.
+ const qreal reverseDisplacement = (contentY + preferredHighlightBegin) / delegateH;
+ displacement = reverseDisplacement - index;
+ }
+
+ Q_Q(QQuickTumblerAttached);
+ if (displacement != previousDisplacement)
+ emit q->displacementChanged();
+}
+
+QQuickTumblerAttached::QQuickTumblerAttached(QQuickItem *delegateItem) :
+ QObject(*(new QQuickTumblerAttachedPrivate(delegateItem)), delegateItem)
+{
+ Q_D(QQuickTumblerAttached);
+ if (d->tumbler) {
+ QQuickItem *rootContentItem = d->tumbler->contentItem();
+ const ContentItemType contentType = contentItemType(rootContentItem);
+ QQuickItemPrivate *p = QQuickItemPrivate::get(actualContentItem(rootContentItem, contentType));
+ p->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Children);
+
+ const char *contentItemSignal = contentType == PathViewContentItem
+ ? SIGNAL(offsetChanged()) : SIGNAL(contentYChanged());
+ connect(d->tumbler->contentItem(), contentItemSignal, this, SLOT(_q_calculateDisplacement()));
+ }
+}
+
+QQuickTumblerAttached::~QQuickTumblerAttached()
+{
+}
+
+QQuickTumbler *QQuickTumblerAttached::tumbler() const
+{
+ Q_D(const QQuickTumblerAttached);
+ return d->tumbler;
+}
+
+qreal QQuickTumblerAttached::displacement() const
+{
+ Q_D(const QQuickTumblerAttached);
+ return d->displacement;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquicktumbler_p.cpp"
diff --git a/src/imports/controls/qquicktumbler_p.h b/src/imports/controls/qquicktumbler_p.h
new file mode 100644
index 00000000..46c683e8
--- /dev/null
+++ b/src/imports/controls/qquicktumbler_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKTUMBLER_H
+#define QQUICKTUMBLER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt 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 <QtCore/qvariant.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQuickTemplates/private/qquickcontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTumblerAttached;
+class QQuickTumblerPrivate;
+
+class QQuickTumbler : public QQuickControl
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged FINAL)
+ Q_PROPERTY(int count READ count NOTIFY countChanged FINAL)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL)
+ Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged FINAL)
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
+ Q_PROPERTY(int visibleItemCount READ visibleItemCount WRITE setVisibleItemCount NOTIFY visibleItemCountChanged FINAL)
+
+public:
+ explicit QQuickTumbler(QQuickItem *parent = Q_NULLPTR);
+ ~QQuickTumbler();
+
+ QVariant model() const;
+ void setModel(const QVariant &model);
+
+ int count() const;
+
+ int currentIndex() const;
+ void setCurrentIndex(int currentIndex);
+ QQuickItem *currentItem() const;
+
+ QQmlComponent *delegate() const;
+ void setDelegate(QQmlComponent *delegate);
+
+ int visibleItemCount() const;
+ void setVisibleItemCount(int visibleItemCount);
+
+ static QQuickTumblerAttached *qmlAttachedProperties(QObject *object);
+
+Q_SIGNALS:
+ void modelChanged();
+ void countChanged();
+ void currentIndexChanged();
+ void currentItemChanged();
+ void delegateChanged();
+ void visibleItemCountChanged();
+
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(QQuickTumbler)
+ Q_DECLARE_PRIVATE(QQuickTumbler)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_updateItemWidths())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateItemHeights())
+};
+
+Q_DECLARE_TYPEINFO(QQuickTumbler, Q_COMPLEX_TYPE);
+
+class QQuickTumblerAttachedPrivate;
+
+class QQuickTumblerAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickTumbler *tumbler READ tumbler CONSTANT)
+ Q_PROPERTY(qreal displacement READ displacement NOTIFY displacementChanged FINAL)
+
+public:
+ explicit QQuickTumblerAttached(QQuickItem *delegateItem);
+ ~QQuickTumblerAttached();
+
+ QQuickTumbler *tumbler() const;
+ qreal displacement() const;
+
+Q_SIGNALS:
+ void displacementChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickTumblerAttached)
+ Q_DECLARE_PRIVATE(QQuickTumblerAttached)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_calculateDisplacement())
+};
+
+Q_DECLARE_TYPEINFO(QQuickTumblerAttached, Q_COMPLEX_TYPE);
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPEINFO(QQuickTumbler, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKTUMBLER_H
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp
index fcc263a8..f572590c 100644
--- a/src/imports/controls/qtquickcontrols2plugin.cpp
+++ b/src/imports/controls/qtquickcontrols2plugin.cpp
@@ -60,6 +60,10 @@
#include <QtQuickTemplates/private/qquicktogglebutton_p.h>
#include <QtQuickTemplates/private/qquicktoolbar_p.h>
#include <QtQuickTemplates/private/qquicktoolbutton_p.h>
+#include "qquickdial_p.h"
+#include "qquickdrawer_p.h"
+#include "qquickswipeview_p.h"
+#include "qquicktumbler_p.h"
#include "qquicktheme_p.h"
void initResources()
@@ -83,14 +87,22 @@ void QtQuickControls2Plugin::registerTypes(const char *uri)
{
qmlRegisterUncreatableType<QQuickThemeAttached>(uri, 2, 0, "Theme", "Theme is an attached property");
+ qmlRegisterType<QQuickDial>(uri, 2, 0, "AbstractDial");
+ qmlRegisterType<QQuickDrawer>(uri, 2, 0, "AbstractDrawer");
qmlRegisterType<QQuickExclusiveGroup>(uri, 2, 0, "ExclusiveGroup");
qmlRegisterType<QQuickExclusiveGroupAttached>();
+ qmlRegisterType<QQuickSwipeView>(uri, 2, 0, "AbstractSwipeView");
+ qmlRegisterType<QQuickSwipeViewAttached>();
+ qmlRegisterType<QQuickTumbler>(uri, 2, 0, "AbstractTumbler");
+ qmlRegisterType<QQuickTumblerAttached>();
QDir baseDir(baseUrl().toLocalFile());
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("ApplicationWindow.qml"))), uri, 2, 0, "ApplicationWindow");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("BusyIndicator.qml"))), uri, 2, 0, "BusyIndicator");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Button.qml"))), uri, 2, 0, "Button");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("CheckBox.qml"))), uri, 2, 0, "CheckBox");
+ qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Dial.qml"))), uri, 2, 0, "Dial");
+ qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Drawer.qml"))), uri, 2, 0, "Drawer");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Frame.qml"))), uri, 2, 0, "Frame");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("GroupBox.qml"))), uri, 2, 0, "GroupBox");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Label.qml"))), uri, 2, 0, "Label");
@@ -101,6 +113,7 @@ void QtQuickControls2Plugin::registerTypes(const char *uri)
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("ScrollIndicator.qml"))), uri, 2, 0, "ScrollIndicator");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Slider.qml"))), uri, 2, 0, "Slider");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("StackView.qml"))), uri, 2, 0, "StackView");
+ qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("SwipeView.qml"))), uri, 2, 0, "SwipeView");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Switch.qml"))), uri, 2, 0, "Switch");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("TabBar.qml"))), uri, 2, 0, "TabBar");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("TabButton.qml"))), uri, 2, 0, "TabButton");
@@ -109,6 +122,7 @@ void QtQuickControls2Plugin::registerTypes(const char *uri)
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("ToggleButton.qml"))), uri, 2, 0, "ToggleButton");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("ToolBar.qml"))), uri, 2, 0, "ToolBar");
qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("ToolButton.qml"))), uri, 2, 0, "ToolButton");
+ qmlRegisterType(QUrl::fromLocalFile(baseDir.filePath(QStringLiteral("Tumbler.qml"))), uri, 2, 0, "Tumbler");
}
void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char *uri)