aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-02-01 20:44:51 +0100
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-02-01 20:44:51 +0100
commit855633758577750e44482843b0836cc0437ef1b2 (patch)
tree097f298789631d5b1b2562af39aab5d280dd4d04
parent283e95aaf299b6bb320dbacabb099d91f070f116 (diff)
parent9351df782b513a5e4dbdd2780ef376a0a08e9800 (diff)
Merge dev into 5.9
-rw-r--r--src/imports/controls/ScrollView.qml66
-rw-r--r--src/imports/controls/controls.pri1
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-scrollview-custom.pngbin0 -> 5909 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-scrollview-wireframe.pngbin0 -> 1343 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-scrollview.pngbin0 -> 5922 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-textarea-scrollable.png (renamed from src/imports/controls/doc/images/qtquickcontrols2-textarea-flickable.png)bin1942 -> 1942 bytes
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-interactive.qml38
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-listview.qml61
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-policy.qml38
-rw-r--r--src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview-custom.qml81
-rw-r--r--src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview.qml61
-rw-r--r--src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-textarea-scrollable.qml (renamed from src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-textarea-flickable.qml)13
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-containers.qdoc6
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc10
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc11
-rw-r--r--src/imports/controls/plugins.qmltypes19
-rw-r--r--src/imports/controls/qtquickcontrols2plugin.cpp1
-rw-r--r--src/imports/templates/plugins.qmltypes11
-rw-r--r--src/imports/templates/qtquicktemplates2plugin.cpp2
-rw-r--r--src/quicktemplates2/qquickpopup.cpp8
-rw-r--r--src/quicktemplates2/qquickscrollbar.cpp49
-rw-r--r--src/quicktemplates2/qquickscrollbar_p.h3
-rw-r--r--src/quicktemplates2/qquickscrollbar_p_p.h2
-rw-r--r--src/quicktemplates2/qquickscrollindicator.cpp3
-rw-r--r--src/quicktemplates2/qquickscrollview.cpp572
-rw-r--r--src/quicktemplates2/qquickscrollview_p.h105
-rw-r--r--src/quicktemplates2/qquicktextarea.cpp17
-rw-r--r--src/quicktemplates2/quicktemplates2.pri2
-rw-r--r--tests/auto/controls/data/tst_popup.qml10
-rw-r--r--tests/auto/controls/data/tst_scrollbar.qml2
-rw-r--r--tests/auto/controls/data/tst_scrollview.qml332
31 files changed, 1489 insertions, 35 deletions
diff --git a/src/imports/controls/ScrollView.qml b/src/imports/controls/ScrollView.qml
new file mode 100644
index 00000000..e10c5328
--- /dev/null
+++ b/src/imports/controls/ScrollView.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 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.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
+
+T.ScrollView {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding)
+
+ contentWidth: contentItem.implicitWidth || (contentChildren.length === 1 ? contentChildren[0].implicitWidth : -1)
+ contentHeight: contentItem.implicitHeight || (contentChildren.length === 1 ? contentChildren[0].implicitHeight : -1)
+
+ ScrollBar.vertical: ScrollBar {
+ parent: control
+ x: control.mirrored ? 0 : control.width - width
+ y: control.topPadding
+ height: control.availableHeight
+ active: control.ScrollBar.horizontal.active
+ }
+
+ ScrollBar.horizontal: ScrollBar {
+ parent: control
+ x: control.leftPadding
+ y: control.height - height
+ width: control.availableWidth
+ active: control.ScrollBar.vertical.active
+ }
+}
diff --git a/src/imports/controls/controls.pri b/src/imports/controls/controls.pri
index 04e31103..5aa56418 100644
--- a/src/imports/controls/controls.pri
+++ b/src/imports/controls/controls.pri
@@ -45,6 +45,7 @@ QML_CONTROLS = \
RoundButton.qml \
ScrollBar.qml \
ScrollIndicator.qml \
+ ScrollView.qml \
Slider.qml \
SpinBox.qml \
StackView.qml \
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-scrollview-custom.png b/src/imports/controls/doc/images/qtquickcontrols2-scrollview-custom.png
new file mode 100644
index 00000000..9c2790c9
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-scrollview-custom.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-scrollview-wireframe.png b/src/imports/controls/doc/images/qtquickcontrols2-scrollview-wireframe.png
new file mode 100644
index 00000000..afdc681d
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-scrollview-wireframe.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-scrollview.png b/src/imports/controls/doc/images/qtquickcontrols2-scrollview.png
new file mode 100644
index 00000000..2a1807ee
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-scrollview.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-textarea-flickable.png b/src/imports/controls/doc/images/qtquickcontrols2-textarea-scrollable.png
index 39578f71..39578f71 100644
--- a/src/imports/controls/doc/images/qtquickcontrols2-textarea-flickable.png
+++ b/src/imports/controls/doc/images/qtquickcontrols2-textarea-scrollable.png
Binary files differ
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-interactive.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-interactive.qml
new file mode 100644
index 00000000..8bb7be29
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-interactive.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+//! [file]
+ScrollView {
+ // ...
+ ScrollBar.horizontal.interactive: true
+ ScrollBar.vertical.interactive: true
+}
+//! [file]
+
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-listview.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-listview.qml
new file mode 100644
index 00000000..bce00cde
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-listview.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+Item {
+ id: root
+ width: 200
+ height: 200
+
+ Binding {
+ target: root.children[0].ScrollBar.horizontal
+ property: "active"
+ value: true
+ }
+
+ Binding {
+ target: root.children[0].ScrollBar.vertical
+ property: "active"
+ value: true
+ }
+
+//! [file]
+ScrollView {
+ width: 200
+ height: 200
+
+ ListView {
+ model: 20
+ delegate: ItemDelegate {
+ text: "Item " + index
+ }
+ }
+}
+//! [file]
+}
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-policy.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-policy.qml
new file mode 100644
index 00000000..ce41950d
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-scrollview-policy.qml
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+//! [file]
+ScrollView {
+ // ...
+ ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
+ ScrollBar.vertical.policy: ScrollBar.AlwaysOn
+}
+//! [file]
+
diff --git a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview-custom.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview-custom.qml
new file mode 100644
index 00000000..82347a5d
--- /dev/null
+++ b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview-custom.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+Item {
+ width: 200
+ height: 200
+
+ Binding {
+ target: control.ScrollBar.horizontal
+ property: "active"
+ value: true
+ }
+
+ Binding {
+ target: control.ScrollBar.vertical
+ property: "active"
+ value: true
+ }
+
+//! [file]
+ScrollView {
+ id: control
+
+ width: 200
+ height: 200
+ focus: true
+
+ Label {
+ text: "ABC"
+ font.pixelSize: 224
+ }
+
+ ScrollBar.vertical: ScrollBar {
+ parent: control
+ x: control.mirrored ? 0 : control.width - width
+ y: control.topPadding
+ height: control.availableHeight
+ active: control.ScrollBar.horizontal.active
+ }
+
+ ScrollBar.horizontal: ScrollBar {
+ parent: control
+ x: control.leftPadding
+ y: control.height - height
+ width: control.availableWidth
+ active: control.ScrollBar.vertical.active
+ }
+
+ background: Rectangle {
+ border.color: control.activeFocus ? "#21be2b" : "#bdbebf"
+ }
+}
+//! [file]
+}
diff --git a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview.qml
new file mode 100644
index 00000000..8900cf9e
--- /dev/null
+++ b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-scrollview.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+Rectangle {
+ id: root
+ width: 200
+ height: 200
+ border.color: "#ddd"
+
+ Binding {
+ target: root.children[0].ScrollBar.horizontal
+ property: "active"
+ value: true
+ }
+
+ Binding {
+ target: root.children[0].ScrollBar.vertical
+ property: "active"
+ value: true
+ }
+
+//! [file]
+ScrollView {
+ width: 200
+ height: 200
+ clip: true
+
+ Label {
+ text: "ABC"
+ font.pixelSize: 224
+ }
+}
+//! [file]
+}
diff --git a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-textarea-flickable.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-textarea-scrollable.qml
index 6fa64390..aa4d05a8 100644
--- a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-textarea-flickable.qml
+++ b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-textarea-scrollable.qml
@@ -26,25 +26,22 @@
****************************************************************************/
import QtQuick 2.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
Item {
width: 100
height: 100
- Binding { target: flickable.ScrollBar.vertical; property: "active"; value: true }
+ Binding { target: view.ScrollBar.vertical; property: "active"; value: true }
//! [1]
- Flickable {
- id: flickable
+ ScrollView {
+ id: view
anchors.fill: parent
- TextArea.flickable: TextArea {
+ TextArea {
text: "TextArea\n...\n...\n...\n...\n...\n...\n"
- wrapMode: TextArea.Wrap
}
-
- ScrollBar.vertical: ScrollBar { }
}
//! [1]
}
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-containers.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-containers.qdoc
index 139958e0..73cfd989 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-containers.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-containers.qdoc
@@ -78,6 +78,12 @@
you to position its contents, for instance by using a \l RowLayout or
a \l ColumnLayout.
+ \section1 ScrollView Control
+
+ \image qtquickcontrols2-scrollview-wireframe.png
+
+ \l ScrollView provides scrolling for user-defined content.
+
\section1 StackView Control
\image qtquickcontrols2-stackview-wireframe.png
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
index 6ef019f6..487c5d6f 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
@@ -636,6 +636,16 @@
\snippet qtquickcontrols2-scrollindicator-custom.qml file
+ \section2 Customizing ScrollView
+
+ ScrollView consists of a \l {Control::background}{background} item,
+ and horizontal and vertical scroll bars.
+
+ \image qtquickcontrols2-scrollview-custom.png
+
+ \snippet qtquickcontrols2-scrollview-custom.qml file
+
+
\section2 Customizing Slider
Slider consists of two visual items: \l {Control::background}{background},
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc
index 3423e423..dd86d2ed 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc
@@ -328,14 +328,9 @@
\li
\row
\li \l [QML QtQuickControls] {ScrollView}
- \li \mdash
- \li \l [QML QtQuickControls2] {ScrollBar},\br
- \l [QML QtQuickControls2] {ScrollIndicator} \br\sup {(Qt Quick Controls 2)}
- \li \list
- \li \b {Qt Quick Controls 2}: \c ScrollBar and \c ScrollIndicator offer
- similar functionality. They can be attached to any \c Flickable to
- build scrollable views.
- \endlist
+ \li \l [QML QtQuickControls2] {ScrollView}
+ \li
+ \li
\row
\li \l [QML QtQuickControls] {Slider}
\li \l [QML QtQuickControls2] {Slider}
diff --git a/src/imports/controls/plugins.qmltypes b/src/imports/controls/plugins.qmltypes
index c3e01172..affdfb96 100644
--- a/src/imports/controls/plugins.qmltypes
+++ b/src/imports/controls/plugins.qmltypes
@@ -376,6 +376,14 @@ Module {
defaultProperty: "data"
}
Component {
+ prototype: "QQuickScrollView"
+ name: "QtQuick.Controls/ScrollView 2.2"
+ exports: ["QtQuick.Controls/ScrollView 2.2"]
+ exportMetaObjectRevisions: [2]
+ isComposite: true
+ defaultProperty: "contentData"
+ }
+ Component {
prototype: "QQuickSlider"
name: "QtQuick.Controls/Slider 2.0"
exports: ["QtQuick.Controls/Slider 2.0"]
@@ -1258,6 +1266,17 @@ Module {
Property { name: "vertical"; type: "QQuickScrollIndicator"; isPointer: true }
}
Component {
+ name: "QQuickScrollView"
+ defaultProperty: "contentData"
+ prototype: "QQuickControl"
+ exports: ["QtQuick.Templates/ScrollView 2.2"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "contentWidth"; type: "double" }
+ Property { name: "contentHeight"; type: "double" }
+ Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
+ }
+ Component {
name: "QQuickSlider"
defaultProperty: "data"
prototype: "QQuickControl"
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp
index e7bedc73..cd81eb62 100644
--- a/src/imports/controls/qtquickcontrols2plugin.cpp
+++ b/src/imports/controls/qtquickcontrols2plugin.cpp
@@ -143,6 +143,7 @@ void QtQuickControls2Plugin::registerTypes(const char *uri)
// QtQuick.Controls 2.2 (new types in Qt 5.9)
qmlRegisterType(selector.select(QStringLiteral("DelayButton.qml")), uri, 2, 2, "DelayButton");
+ qmlRegisterType(selector.select(QStringLiteral("ScrollView.qml")), uri, 2, 2, "ScrollView");
}
static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
diff --git a/src/imports/templates/plugins.qmltypes b/src/imports/templates/plugins.qmltypes
index d2151685..0ff02f22 100644
--- a/src/imports/templates/plugins.qmltypes
+++ b/src/imports/templates/plugins.qmltypes
@@ -753,6 +753,17 @@ Module {
Property { name: "vertical"; type: "QQuickScrollIndicator"; isPointer: true }
}
Component {
+ name: "QQuickScrollView"
+ defaultProperty: "contentData"
+ prototype: "QQuickControl"
+ exports: ["QtQuick.Templates/ScrollView 2.2"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "contentWidth"; type: "double" }
+ Property { name: "contentHeight"; type: "double" }
+ Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
+ }
+ Component {
name: "QQuickSlider"
defaultProperty: "data"
prototype: "QQuickControl"
diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp
index 52529c3b..b17b916b 100644
--- a/src/imports/templates/qtquicktemplates2plugin.cpp
+++ b/src/imports/templates/qtquicktemplates2plugin.cpp
@@ -70,6 +70,7 @@
#include <QtQuickTemplates2/private/qquickroundbutton_p.h>
#include <QtQuickTemplates2/private/qquickscrollbar_p.h>
#include <QtQuickTemplates2/private/qquickscrollindicator_p.h>
+#include <QtQuickTemplates2/private/qquickscrollview_p.h>
#include <QtQuickTemplates2/private/qquickshortcutcontext_p_p.h>
#include <QtQuickTemplates2/private/qquickslider_p.h>
#include <QtQuickTemplates2/private/qquickspinbox_p.h>
@@ -231,6 +232,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
qmlRegisterType<QQuickDrawer, 2>(uri, 2, 2, "Drawer");
qmlRegisterType<QQuickRangeSlider, 2>(uri, 2, 2, "RangeSlider");
qmlRegisterType<QQuickScrollBar, 2>(uri, 2, 2, "ScrollBar");
+ qmlRegisterType<QQuickScrollView>(uri, 2, 2, "ScrollView");
qmlRegisterType<QQuickSlider, 2>(uri, 2, 2, "Slider");
qmlRegisterType<QQuickSpinBox, 2>(uri, 2, 2, "SpinBox");
qmlRegisterType<QQuickSwipeDelegate, 2>(uri, 2, 2, "SwipeDelegate");
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index 3a09bf84..80c530eb 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -1729,8 +1729,12 @@ void QQuickPopup::componentComplete()
{
Q_D(QQuickPopup);
d->complete = true;
- if (!parentItem())
- setParentItem(qobject_cast<QQuickItem *>(parent()));
+ if (!parentItem()) {
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(parent()))
+ setParentItem(item);
+ else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent()))
+ setParentItem(window->contentItem());
+ }
if (d->visible)
d->transitionManager.transitionEnter();
d->popupItem->componentComplete();
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp
index ac786649..1ad14e9d 100644
--- a/src/quicktemplates2/qquickscrollbar.cpp
+++ b/src/quicktemplates2/qquickscrollbar.cpp
@@ -36,6 +36,7 @@
#include "qquickscrollbar_p.h"
#include "qquickscrollbar_p_p.h"
+#include "qquickscrollview_p.h"
#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickflickable_p.h>
@@ -163,6 +164,7 @@ QQuickScrollBarPrivate::QQuickScrollBarPrivate()
pressed(false),
moving(false),
interactive(true),
+ explicitInteractive(false),
orientation(Qt::Vertical),
snapMode(QQuickScrollBar::NoSnap),
policy(QQuickScrollBar::AsNeeded)
@@ -187,6 +189,19 @@ qreal QQuickScrollBarPrivate::positionAt(const QPointF &point) const
return (point.y() - q->topPadding()) / q->availableHeight();
}
+void QQuickScrollBarPrivate::setInteractive(bool enabled)
+{
+ Q_Q(QQuickScrollBar);
+ if (interactive == enabled)
+ return;
+
+ interactive = enabled;
+ q->setAcceptedMouseButtons(interactive ? Qt::LeftButton : Qt::NoButton);
+ if (!interactive)
+ q->ungrabMouse();
+ emit q->interactiveChanged();
+}
+
void QQuickScrollBarPrivate::updateActive()
{
Q_Q(QQuickScrollBar);
@@ -480,14 +495,15 @@ bool QQuickScrollBar::isInteractive() const
void QQuickScrollBar::setInteractive(bool interactive)
{
Q_D(QQuickScrollBar);
- if (d->interactive == interactive)
- return;
+ d->explicitInteractive = true;
+ d->setInteractive(interactive);
+}
- d->interactive = interactive;
- setAcceptedMouseButtons(interactive ? Qt::LeftButton : Qt::NoButton);
- if (!interactive)
- ungrabMouse();
- emit interactiveChanged();
+void QQuickScrollBar::resetInteractive()
+{
+ Q_D(QQuickScrollBar);
+ d->explicitInteractive = false;
+ d->setInteractive(true);
}
/*!
@@ -615,7 +631,10 @@ QQuickScrollBarAttachedPrivate::QQuickScrollBarAttachedPrivate()
void QQuickScrollBarAttachedPrivate::setFlickable(QQuickFlickable *item)
{
if (flickable) {
- QQuickItemPrivate::get(flickable)->updateOrRemoveGeometryChangeListener(this, QQuickItemPrivate::Size);
+ // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size).
+ // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling
+ // pointer on destruction.
+ QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
if (horizontal)
cleanupHorizontal();
if (vertical)
@@ -644,6 +663,11 @@ void QQuickScrollBarAttachedPrivate::initHorizontal()
QObject::connect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal)));
QObject::connect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal)));
+ // ensure that the ScrollBar is stacked above the Flickable in a ScrollView
+ QQuickItem *parent = horizontal->parentItem();
+ if (parent && parent == flickable->parentItem())
+ horizontal->stackAfter(flickable);
+
layoutHorizontal();
horizontal->setSize(area->property("widthRatio").toReal());
horizontal->setPosition(area->property("xPosition").toReal());
@@ -660,6 +684,11 @@ void QQuickScrollBarAttachedPrivate::initVertical()
QObject::connect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal)));
QObject::connect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal)));
+ // ensure that the ScrollBar is stacked above the Flickable in a ScrollView
+ QQuickItem *parent = vertical->parentItem();
+ if (parent && parent == flickable->parentItem())
+ vertical->stackAfter(flickable);
+
layoutVertical();
vertical->setSize(area->property("heightRatio").toReal());
vertical->setPosition(area->property("yPosition").toReal());
@@ -806,8 +835,8 @@ QQuickScrollBarAttached::QQuickScrollBarAttached(QObject *parent)
Q_D(QQuickScrollBarAttached);
d->setFlickable(qobject_cast<QQuickFlickable *>(parent));
- if (parent && !d->flickable)
- qmlWarning(parent) << "ScrollBar must be attached to a Flickable";
+ if (parent && !d->flickable && !qobject_cast<QQuickScrollView *>(parent))
+ qmlWarning(parent) << "ScrollBar must be attached to a Flickable or ScrollView";
}
QQuickScrollBarAttached::~QQuickScrollBarAttached()
diff --git a/src/quicktemplates2/qquickscrollbar_p.h b/src/quicktemplates2/qquickscrollbar_p.h
index dabc860b..868cb5d8 100644
--- a/src/quicktemplates2/qquickscrollbar_p.h
+++ b/src/quicktemplates2/qquickscrollbar_p.h
@@ -65,7 +65,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollBar : public QQuickControl
Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL REVISION 2)
- Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged FINAL REVISION 2)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive RESET resetInteractive NOTIFY interactiveChanged FINAL REVISION 2)
Q_PROPERTY(Policy policy READ policy WRITE setPolicy NOTIFY policyChanged FINAL REVISION 2)
public:
@@ -100,6 +100,7 @@ public:
bool isInteractive() const;
void setInteractive(bool interactive);
+ void resetInteractive();
enum Policy {
AsNeeded = Qt::ScrollBarAsNeeded,
diff --git a/src/quicktemplates2/qquickscrollbar_p_p.h b/src/quicktemplates2/qquickscrollbar_p_p.h
index fa5bd0b5..cbbef2c8 100644
--- a/src/quicktemplates2/qquickscrollbar_p_p.h
+++ b/src/quicktemplates2/qquickscrollbar_p_p.h
@@ -70,6 +70,7 @@ public:
qreal snapPosition(qreal position) const;
qreal positionAt(const QPointF &point) const;
+ void setInteractive(bool interactive);
void updateActive();
void resizeContent() override;
@@ -86,6 +87,7 @@ public:
bool pressed;
bool moving;
bool interactive;
+ bool explicitInteractive;
Qt::Orientation orientation;
QQuickScrollBar::SnapMode snapMode;
QQuickScrollBar::Policy policy;
diff --git a/src/quicktemplates2/qquickscrollindicator.cpp b/src/quicktemplates2/qquickscrollindicator.cpp
index c98a1956..a57cfbb6 100644
--- a/src/quicktemplates2/qquickscrollindicator.cpp
+++ b/src/quicktemplates2/qquickscrollindicator.cpp
@@ -412,6 +412,9 @@ QQuickScrollIndicatorAttached::~QQuickScrollIndicatorAttached()
QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes);
if (d->vertical)
QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d,verticalChangeTypes);
+ // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size).
+ // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling
+ // pointer on destruction.
QQuickItemPrivate::get(d->flickable)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
}
}
diff --git a/src/quicktemplates2/qquickscrollview.cpp b/src/quicktemplates2/qquickscrollview.cpp
new file mode 100644
index 00000000..cf1fac48
--- /dev/null
+++ b/src/quicktemplates2/qquickscrollview.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 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 "qquickscrollview_p.h"
+#include "qquickcontrol_p_p.h"
+#include "qquickscrollbar_p_p.h"
+
+#include <QtQuick/private/qquickflickable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ScrollView
+ \inherits Control
+ \instantiates QQuickScrollView
+ \inqmlmodule QtQuick.Controls
+ \since 5.9
+ \ingroup qtquickcontrols2-containers
+ \brief Scrollable view.
+
+ ScrollView provides scrolling for user-defined content. It can be used to
+ either replace a \l Flickable, or to decorate an existing one.
+
+ \image qtquickcontrols2-scrollview.png
+
+ The first example demonstrates the simplest usage of ScrollView.
+
+ \snippet qtquickcontrols2-scrollview.qml file
+
+ \note ScrollView does not automatically clip its contents. If it is not used as
+ a full-screen item, you should consider setting the \l {Item::}{clip} property
+ to \c true, as shown above.
+
+ The second example illustrates using an existing \l Flickable, that is,
+ a \l ListView.
+
+ \snippet qtquickcontrols2-scrollview-listview.qml file
+
+ \section2 Scroll Bars
+
+ The horizontal and vertical scroll bars can be accessed and customized using
+ the \l {ScrollBar::horizontal}{ScrollBar.horizontal} and \l {ScrollBar::vertical}
+ {ScrollBar.vertical} attached properties. The following example adjusts the scroll
+ bar policies so that the horizontal scroll bar is always off, and the vertical
+ scroll bar is always on.
+
+ \snippet qtquickcontrols2-scrollview-policy.qml file
+
+ \section2 Touch vs. Mouse Interaction
+
+ On touch, ScrollView enables flicking and makes the scroll bars non-interactive.
+
+ \image qtquickcontrols2-scrollindicator.gif
+
+ When interacted with a mouse device, flicking is disabled and the scroll bars
+ are interactive.
+
+ \image qtquickcontrols2-scrollbar.gif
+
+ Scroll bars can be made interactive on touch, or non-interactive when interacted
+ with a mouse device, by setting the \l {ScrollBar::}{interactive} property explicitly
+ to \c true or \c false, respectively.
+
+ \snippet qtquickcontrols2-scrollview-interactive.qml file
+
+ \sa ScrollBar, ScrollIndicator, {Customizing ScrollView}, {Container Controls},
+*/
+
+class QQuickScrollViewPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickScrollView)
+
+public:
+ QQuickScrollViewPrivate();
+
+ QQuickItem *getContentItem() override;
+
+ QQuickFlickable *ensureFlickable();
+ bool setFlickable(QQuickFlickable *flickable, bool content);
+
+ void updateContentWidth();
+ void updateContentHeight();
+
+ QQuickScrollBar *verticalScrollBar() const;
+ QQuickScrollBar *horizontalScrollBar() const;
+
+ void setScrollBarsInteractive(bool interactive);
+
+ static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj);
+ static int contentData_count(QQmlListProperty<QObject> *prop);
+ static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index);
+ static void contentData_clear(QQmlListProperty<QObject> *prop);
+
+ static void contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *obj);
+ static int contentChildren_count(QQmlListProperty<QQuickItem> *prop);
+ static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index);
+ static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop);
+
+ bool wasTouched;
+ qreal contentWidth;
+ qreal contentHeight;
+ QQuickFlickable *flickable;
+};
+
+QQuickScrollViewPrivate::QQuickScrollViewPrivate()
+ : wasTouched(false),
+ contentWidth(-1),
+ contentHeight(-1),
+ flickable(nullptr)
+{
+ wheelEnabled = true;
+}
+
+QQuickItem *QQuickScrollViewPrivate::getContentItem()
+{
+ return ensureFlickable();
+}
+
+QQuickFlickable *QQuickScrollViewPrivate::ensureFlickable()
+{
+ Q_Q(QQuickScrollView);
+ if (!flickable)
+ setFlickable(new QQuickFlickable(q), true);
+ return flickable;
+}
+
+bool QQuickScrollViewPrivate::setFlickable(QQuickFlickable *item, bool content)
+{
+ Q_Q(QQuickScrollView);
+ if (item == flickable)
+ return false;
+
+ QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
+
+ if (flickable) {
+ flickable->removeEventFilter(q);
+
+ if (attached)
+ QQuickScrollBarAttachedPrivate::get(attached)->setFlickable(nullptr);
+
+ QObject::disconnect(flickable->contentItem(), &QQuickItem::childrenChanged, q, &QQuickScrollView::contentChildrenChanged);
+ QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::updateContentWidth);
+ QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::updateContentHeight);
+ }
+
+ flickable = item;
+ if (content)
+ q->setContentItem(flickable);
+
+ if (flickable) {
+ flickable->installEventFilter(q);
+ if (contentWidth > 0)
+ item->setContentWidth(contentWidth);
+ else
+ updateContentWidth();
+ if (contentHeight > 0)
+ item->setContentHeight(contentHeight);
+ else
+ updateContentHeight();
+
+ if (attached)
+ QQuickScrollBarAttachedPrivate::get(attached)->setFlickable(flickable);
+
+ QObject::connect(flickable->contentItem(), &QQuickItem::childrenChanged, q, &QQuickScrollView::contentChildrenChanged);
+ QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::updateContentWidth);
+ QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::updateContentHeight);
+ }
+
+ return true;
+}
+
+void QQuickScrollViewPrivate::updateContentWidth()
+{
+ Q_Q(QQuickScrollView);
+ if (!flickable)
+ return;
+
+ const qreal cw = flickable->contentWidth();
+ if (qFuzzyCompare(cw, contentWidth))
+ return;
+
+ contentWidth = cw;
+ emit q->contentWidthChanged();
+}
+
+void QQuickScrollViewPrivate::updateContentHeight()
+{
+ Q_Q(QQuickScrollView);
+ if (!flickable)
+ return;
+
+ const qreal ch = flickable->contentHeight();
+ if (qFuzzyCompare(ch, contentHeight))
+ return;
+
+ contentHeight = ch;
+ emit q->contentHeightChanged();
+}
+
+QQuickScrollBar *QQuickScrollViewPrivate::verticalScrollBar() const
+{
+ Q_Q(const QQuickScrollView);
+ QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
+ if (!attached)
+ return nullptr;
+ return attached->vertical();
+}
+
+QQuickScrollBar *QQuickScrollViewPrivate::horizontalScrollBar() const
+{
+ Q_Q(const QQuickScrollView);
+ QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
+ if (!attached)
+ return nullptr;
+ return attached->horizontal();
+}
+
+void QQuickScrollViewPrivate::setScrollBarsInteractive(bool interactive)
+{
+ QQuickScrollBar *hbar = horizontalScrollBar();
+ if (hbar) {
+ QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(hbar);
+ if (!p->explicitInteractive)
+ p->setInteractive(interactive);
+ }
+
+ QQuickScrollBar *vbar = verticalScrollBar();
+ if (vbar) {
+ QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(vbar);
+ if (!p->explicitInteractive)
+ p->setInteractive(interactive);
+ }
+}
+
+void QQuickScrollViewPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable && p->setFlickable(qobject_cast<QQuickFlickable *>(obj), true))
+ return;
+
+ QQuickFlickable *flickable = p->ensureFlickable();
+ Q_ASSERT(flickable);
+ QQmlListProperty<QObject> data = flickable->flickableData();
+ data.append(&data, obj);
+}
+
+int QQuickScrollViewPrivate::contentData_count(QQmlListProperty<QObject> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return 0;
+
+ QQmlListProperty<QObject> data = p->flickable->flickableData();
+ return data.count(&data);
+}
+
+QObject *QQuickScrollViewPrivate::contentData_at(QQmlListProperty<QObject> *prop, int index)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return nullptr;
+
+ QQmlListProperty<QObject> data = p->flickable->flickableData();
+ return data.at(&data, index);
+}
+
+void QQuickScrollViewPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return;
+
+ QQmlListProperty<QObject> data = p->flickable->flickableData();
+ return data.clear(&data);
+}
+
+void QQuickScrollViewPrivate::contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ p->setFlickable(qobject_cast<QQuickFlickable *>(item), true);
+
+ QQuickFlickable *flickable = p->ensureFlickable();
+ Q_ASSERT(flickable);
+ QQmlListProperty<QQuickItem> children = flickable->flickableChildren();
+ children.append(&children, item);
+}
+
+int QQuickScrollViewPrivate::contentChildren_count(QQmlListProperty<QQuickItem> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return 0;
+
+ QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
+ return children.count(&children);
+}
+
+QQuickItem *QQuickScrollViewPrivate::contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return nullptr;
+
+ QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
+ return children.at(&children, index);
+}
+
+void QQuickScrollViewPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return;
+
+ QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
+ children.clear(&children);
+}
+
+QQuickScrollView::QQuickScrollView(QQuickItem *parent)
+ : QQuickControl(*(new QQuickScrollViewPrivate), parent)
+{
+ setFlag(ItemIsFocusScope);
+ setActiveFocusOnTab(true);
+ setFiltersChildMouseEvents(true);
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::ScrollView::contentWidth
+
+ This property holds the width of the scrollable content.
+
+ If only a single item is used within a ScrollView, the content size is
+ automatically calculated based on the implicit size of its contained item.
+
+ \sa contentHeight
+*/
+qreal QQuickScrollView::contentWidth() const
+{
+ Q_D(const QQuickScrollView);
+ return d->contentWidth;
+}
+
+void QQuickScrollView::setContentWidth(qreal width)
+{
+ Q_D(QQuickScrollView);
+ if (qFuzzyCompare(d->contentWidth, width))
+ return;
+
+ if (d->flickable) {
+ d->flickable->setContentWidth(width);
+ } else {
+ d->contentWidth = width;
+ emit contentWidthChanged();
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::ScrollView::contentHeight
+
+ This property holds the height of the scrollable content.
+
+ If only a single item is used within a ScrollView, the content size is
+ automatically calculated based on the implicit size of its contained item.
+
+ \sa contentWidth
+*/
+qreal QQuickScrollView::contentHeight() const
+{
+ Q_D(const QQuickScrollView);
+ return d->contentHeight;
+}
+
+void QQuickScrollView::setContentHeight(qreal height)
+{
+ Q_D(QQuickScrollView);
+ if (qFuzzyCompare(d->contentHeight, height))
+ return;
+
+ if (d->flickable) {
+ d->flickable->setContentHeight(height);
+ } else {
+ d->contentHeight = height;
+ emit contentHeightChanged();
+ }
+}
+
+/*!
+ \qmlproperty list<Object> QtQuick.Controls::ScrollView::contentData
+ \default
+
+ This property holds the list of content data.
+
+ The list contains all objects that have been declared in QML as children of the view.
+
+ \note Unlike \c contentChildren, \c contentData does include non-visual QML objects.
+
+ \sa Item::data, contentChildren
+*/
+QQmlListProperty<QObject> QQuickScrollView::contentData()
+{
+ Q_D(QQuickScrollView);
+ return QQmlListProperty<QObject>(this, d,
+ QQuickScrollViewPrivate::contentData_append,
+ QQuickScrollViewPrivate::contentData_count,
+ QQuickScrollViewPrivate::contentData_at,
+ QQuickScrollViewPrivate::contentData_clear);
+}
+
+/*!
+ \qmlproperty list<Item> QtQuick.Controls::ScrollView::contentChildren
+
+ This property holds the list of content children.
+
+ The list contains all items that have been declared in QML as children of the view.
+
+ \note Unlike \c contentData, \c contentChildren does not include non-visual QML objects.
+
+ \sa Item::children, contentData
+*/
+QQmlListProperty<QQuickItem> QQuickScrollView::contentChildren()
+{
+ Q_D(QQuickScrollView);
+ return QQmlListProperty<QQuickItem>(this, d,
+ QQuickScrollViewPrivate::contentChildren_append,
+ QQuickScrollViewPrivate::contentChildren_count,
+ QQuickScrollViewPrivate::contentChildren_at,
+ QQuickScrollViewPrivate::contentChildren_clear);
+}
+
+bool QQuickScrollView::childMouseEventFilter(QQuickItem *item, QEvent *event)
+{
+ Q_D(QQuickScrollView);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ d->wasTouched = true;
+ d->setScrollBarsInteractive(false);
+ return false;
+
+ case QEvent::TouchEnd:
+ d->wasTouched = false;
+ return false;
+
+ case QEvent::MouseButtonPress:
+ // NOTE: Flickable does not handle touch events, only synthesized mouse events
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized) {
+ d->wasTouched = false;
+ d->setScrollBarsInteractive(true);
+ return false;
+ }
+ return !d->wasTouched && item == d->flickable;
+
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
+ return item == d->flickable;
+ break;
+
+ case QEvent::HoverEnter:
+ case QEvent::HoverMove:
+ if (d->wasTouched && (item == d->verticalScrollBar() || item == d->horizontalScrollBar()))
+ d->setScrollBarsInteractive(true);
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool QQuickScrollView::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QQuickScrollView);
+ if (event->type() == QEvent::Wheel) {
+ d->setScrollBarsInteractive(true);
+ if (!d->wheelEnabled)
+ return true;
+ }
+ return QQuickControl::eventFilter(object, event);
+}
+
+void QQuickScrollView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickScrollView);
+ QQuickControl::keyPressEvent(event);
+ switch (event->key()) {
+ case Qt::Key_Up:
+ if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
+ vbar->decrease();
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
+ vbar->increase();
+ event->accept();
+ }
+ break;
+ case Qt::Key_Left:
+ if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
+ hbar->decrease();
+ event->accept();
+ }
+ break;
+ case Qt::Key_Right:
+ if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
+ hbar->increase();
+ event->accept();
+ }
+ break;
+ default:
+ event->ignore();
+ break;
+ }
+}
+
+void QQuickScrollView::componentComplete()
+{
+ Q_D(QQuickScrollView);
+ QQuickControl::componentComplete();
+ if (!d->contentItem)
+ d->ensureFlickable();
+}
+
+void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickScrollView);
+ QQuickControl::contentItemChange(newItem, oldItem);
+ d->setFlickable(qobject_cast<QQuickFlickable *>(newItem), false);
+}
+
+#ifndef QT_NO_ACCESSIBILITY
+QAccessible::Role QQuickScrollView::accessibleRole() const
+{
+ return QAccessible::Pane;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickscrollview_p.h b/src/quicktemplates2/qquickscrollview_p.h
new file mode 100644
index 00000000..353f2fc9
--- /dev/null
+++ b/src/quicktemplates2/qquickscrollview_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 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 QQUICKSCROLLVIEW_P_H
+#define QQUICKSCROLLVIEW_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 <QtQuickTemplates2/private/qquickcontrol_p.h>
+#include <QtQml/qqmllist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickScrollViewPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollView : public QQuickControl
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged FINAL)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged FINAL)
+ Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
+ Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL)
+ Q_CLASSINFO("DefaultProperty", "contentData")
+
+public:
+ explicit QQuickScrollView(QQuickItem *parent = nullptr);
+
+ qreal contentWidth() const;
+ void setContentWidth(qreal width);
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal height);
+
+ QQmlListProperty<QObject> contentData();
+ QQmlListProperty<QQuickItem> contentChildren();
+
+Q_SIGNALS:
+ void contentWidthChanged();
+ void contentHeightChanged();
+ void contentChildrenChanged();
+
+protected:
+ bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
+ bool eventFilter(QObject *object, QEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+
+ void componentComplete() override;
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::Role accessibleRole() const override;
+#endif
+
+private:
+ Q_DISABLE_COPY(QQuickScrollView)
+ Q_DECLARE_PRIVATE(QQuickScrollView)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickScrollView)
+
+#endif // QQUICKSCROLLVIEW_P_H
diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp
index fb006c1b..573521cf 100644
--- a/src/quicktemplates2/qquicktextarea.cpp
+++ b/src/quicktemplates2/qquicktextarea.cpp
@@ -38,6 +38,7 @@
#include "qquicktextarea_p_p.h"
#include "qquickcontrol_p.h"
#include "qquickcontrol_p_p.h"
+#include "qquickscrollview_p.h"
#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickitem_p.h>
@@ -80,14 +81,13 @@ QT_BEGIN_NAMESPACE
\section2 Scrollable TextArea
If you want to make a TextArea scrollable, for example, when it covers
- an entire application page, attach it to a \l Flickable and combine with a
- \l ScrollBar or \l ScrollIndicator.
+ an entire application page, it can be placed inside a \l ScrollView.
- \image qtquickcontrols2-textarea-flickable.png
+ \image qtquickcontrols2-textarea-scrollable.png
- \snippet qtquickcontrols2-textarea-flickable.qml 1
+ \snippet qtquickcontrols2-textarea-scrollable.qml 1
- A TextArea that is attached to a \l Flickable does the following:
+ A TextArea that is placed inside a \l ScrollView does the following:
\list
\li Sets the content size automatically
@@ -603,6 +603,13 @@ void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem:
d->resolveFont();
if (!d->explicitHoverEnabled)
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
+ if (flickable) {
+ QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
+ if (scrollView)
+ d->attachFlickable(flickable);
+ }
}
}
diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri
index 8ef1ef28..dfeb899d 100644
--- a/src/quicktemplates2/quicktemplates2.pri
+++ b/src/quicktemplates2/quicktemplates2.pri
@@ -54,6 +54,7 @@ HEADERS += \
$$PWD/qquickscrollbar_p.h \
$$PWD/qquickscrollbar_p_p.h \
$$PWD/qquickscrollindicator_p.h \
+ $$PWD/qquickscrollview_p.h \
$$PWD/qquickshortcutcontext_p_p.h \
$$PWD/qquickslider_p.h \
$$PWD/qquickspinbox_p.h \
@@ -120,6 +121,7 @@ SOURCES += \
$$PWD/qquickroundbutton.cpp \
$$PWD/qquickscrollbar.cpp \
$$PWD/qquickscrollindicator.cpp \
+ $$PWD/qquickscrollview.cpp \
$$PWD/qquickshortcutcontext.cpp \
$$PWD/qquickslider.cpp \
$$PWD/qquickspinbox.cpp \
diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml
index 6294250e..3d88e62a 100644
--- a/tests/auto/controls/data/tst_popup.qml
+++ b/tests/auto/controls/data/tst_popup.qml
@@ -1230,4 +1230,14 @@ TestCase {
compare(control.x, (control.parent.width - control.width) / 2)
compare(control.y, (control.parent.height - control.height) / 2)
}
+
+ function test_windowParent() {
+ var control = popupControl.createObject(applicationWindow, {width: 100, height: 100})
+ verify(control)
+
+ control.open()
+ verify(control.visible)
+
+ control.destroy()
+ }
}
diff --git a/tests/auto/controls/data/tst_scrollbar.qml b/tests/auto/controls/data/tst_scrollbar.qml
index cf1a8559..ab2c8cb6 100644
--- a/tests/auto/controls/data/tst_scrollbar.qml
+++ b/tests/auto/controls/data/tst_scrollbar.qml
@@ -307,7 +307,7 @@ TestCase {
}
function test_warning() {
- ignoreWarning(Qt.resolvedUrl("tst_scrollbar.qml") + ":45:1: QML TestCase: ScrollBar must be attached to a Flickable")
+ ignoreWarning(Qt.resolvedUrl("tst_scrollbar.qml") + ":45:1: QML TestCase: ScrollBar must be attached to a Flickable or ScrollView")
testCase.ScrollBar.vertical = null
}
diff --git a/tests/auto/controls/data/tst_scrollview.qml b/tests/auto/controls/data/tst_scrollview.qml
new file mode 100644
index 00000000..fc9507a5
--- /dev/null
+++ b/tests/auto/controls/data/tst_scrollview.qml
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+import QtQuick.Controls 2.2
+
+TestCase {
+ id: testCase
+ width: 400
+ height: 400
+ visible: true
+ when: windowShown
+ name: "ScrollView"
+
+ Component {
+ id: signalSpy
+ SignalSpy { }
+ }
+
+ Component {
+ id: scrollView
+ ScrollView { }
+ }
+
+ Component {
+ id: scrollableLabel
+ ScrollView {
+ Label {
+ text: "ABC"
+ font.pixelSize: 512
+ }
+ }
+ }
+
+ Component {
+ id: scrollableLabels
+ ScrollView {
+ contentHeight: label1.implicitHeight + label2.implicitHeight + label3.implicitHeight
+ Label {
+ id: label1
+ text: "First"
+ font.pixelSize: 96
+ }
+ Label {
+ id: label2
+ text: "Second"
+ font.pixelSize: 96
+ }
+ Label {
+ id: label3
+ text: "Third"
+ font.pixelSize: 96
+ }
+ }
+ }
+
+ Component {
+ id: flickableLabel
+ ScrollView {
+ Flickable {
+ contentWidth: label.implicitWidth
+ contentHeight: label.implicitHeight
+ Label {
+ id: label
+ text: "ABC"
+ font.pixelSize: 512
+ }
+ }
+ }
+ }
+
+ Component {
+ id: scrollableListView
+ ScrollView {
+ ListView {
+ model: 3
+ delegate: Label {
+ text: modelData
+ }
+ }
+ }
+ }
+
+ function test_scrollBars() {
+ var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200})
+ verify(control)
+
+ var vertical = control.ScrollBar.vertical
+ verify(vertical)
+
+ var horizontal = control.ScrollBar.horizontal
+ verify(horizontal)
+
+ control.contentHeight = 400
+ verify(vertical.size > 0)
+ compare(control.contentItem.visibleArea.heightRatio, vertical.size)
+
+ control.contentWidth = 400
+ verify(horizontal.size > 0)
+ compare(control.contentItem.visibleArea.widthRatio, horizontal.size)
+
+ vertical.increase()
+ verify(vertical.position > 0)
+ compare(control.contentItem.visibleArea.yPosition, vertical.position)
+
+ horizontal.increase()
+ verify(horizontal.position > 0)
+ compare(control.contentItem.visibleArea.xPosition, horizontal.position)
+ }
+
+ function test_oneChild_data() {
+ return [
+ { tag: "label", component: scrollableLabel },
+ { tag: "flickable", component: flickableLabel }
+ ]
+ }
+
+ function test_oneChild(data) {
+ var control = createTemporaryObject(data.component, testCase)
+ verify(control)
+
+ var flickable = control.contentItem
+ verify(flickable.hasOwnProperty("contentX"))
+ verify(flickable.hasOwnProperty("contentY"))
+
+ var label = flickable.contentItem.children[0]
+ compare(label.text, "ABC")
+
+ compare(control.implicitWidth, label.implicitWidth)
+ compare(control.implicitHeight, label.implicitHeight)
+
+ compare(control.contentWidth, label.implicitWidth)
+ compare(control.contentHeight, label.implicitHeight)
+
+ compare(flickable.contentWidth, label.implicitWidth)
+ compare(flickable.contentHeight, label.implicitHeight)
+
+ control.contentWidth = 200
+ compare(control.implicitWidth, 200)
+ compare(control.contentWidth, 200)
+ compare(flickable.contentWidth, 200)
+
+ control.contentHeight = 100
+ compare(control.implicitHeight, 100)
+ compare(control.contentHeight, 100)
+ compare(flickable.contentHeight, 100)
+ }
+
+ function test_multipleChildren() {
+ var control = createTemporaryObject(scrollableLabels, testCase)
+ verify(control)
+
+ var flickable = control.contentItem
+ verify(flickable.hasOwnProperty("contentX"))
+ verify(flickable.hasOwnProperty("contentY"))
+
+ compare(control.contentChildren, flickable.contentItem.children)
+
+ var label1 = control.contentChildren[0]
+ compare(label1.text, "First")
+
+ var label2 = control.contentChildren[1]
+ compare(label2.text, "Second")
+
+ var label3 = control.contentChildren[2]
+ compare(label3.text, "Third")
+
+ var expectedContentHeight = label1.implicitHeight + label2.implicitHeight + label3.implicitHeight
+ compare(control.contentHeight, expectedContentHeight)
+ compare(flickable.contentHeight, expectedContentHeight)
+ }
+
+ function test_listView() {
+ var control = createTemporaryObject(scrollableListView, testCase)
+ verify(control)
+
+ var listview = control.contentItem
+ verify(listview.hasOwnProperty("contentX"))
+ verify(listview.hasOwnProperty("contentY"))
+ verify(listview.hasOwnProperty("model"))
+
+ compare(control.contentWidth, listview.contentWidth)
+ compare(control.contentHeight, listview.contentHeight)
+ }
+
+ function test_mouse() {
+ var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ verify(control)
+
+ mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ compare(control.contentItem.contentY, 0)
+
+ for (var y = control.height / 2; y >= 0; --y) {
+ mouseMove(control, control.width / 2, y, 10)
+ compare(control.contentItem.contentY, 0)
+ }
+
+ mouseRelease(control, control.width / 2, 0, Qt.LeftButton)
+ compare(control.contentItem.contentY, 0)
+ }
+
+ function test_hover() {
+ var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ verify(control)
+
+ var vertical = control.ScrollBar.vertical
+ verify(vertical)
+ vertical.hoverEnabled = true
+
+ mouseMove(vertical, vertical.width / 2, vertical.height / 2)
+ compare(vertical.visible, true)
+ compare(vertical.hovered, true)
+ compare(vertical.active, true)
+ compare(vertical.interactive, true)
+ }
+
+ function test_wheel() {
+ var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ verify(control)
+
+ var vertical = control.ScrollBar.vertical
+ verify(vertical)
+
+ mouseWheel(control, control.width / 2, control.height / 2, 0, -120)
+ compare(vertical.visible, true)
+ compare(vertical.active, true)
+ compare(vertical.interactive, true)
+ }
+
+ function test_touch() {
+ var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentHeight: 400})
+ verify(control)
+
+ var vertical = control.ScrollBar.vertical
+ verify(vertical)
+
+ var touch = touchEvent(control)
+ touch.press(0, control, control.width / 2, control.height / 2).commit()
+ compare(control.contentItem.contentY, 0)
+
+ compare(vertical.active, false)
+ compare(vertical.interactive, false)
+
+ var maxContentY = 0
+ for (var y = control.height / 2; y >= 0; --y) {
+ touch.move(0, control, control.width / 2, y).commit()
+ maxContentY = Math.max(maxContentY, control.contentItem.contentY)
+ }
+ verify(maxContentY > 0)
+
+ compare(vertical.active, true)
+ compare(vertical.interactive, false)
+
+ touch.release(0, control, control.width / 2, 0).commit()
+ }
+
+ function test_keys() {
+ var control = createTemporaryObject(scrollView, testCase, {width: 200, height: 200, contentWidth: 400, contentHeight: 400})
+ verify(control)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ var vertical = control.ScrollBar.vertical
+ verify(vertical)
+
+ compare(vertical.position, 0.0)
+ for (var i = 1; i <= 10; ++i) {
+ keyClick(Qt.Key_Down)
+ compare(vertical.position, Math.min(0.5, i * 0.1))
+ }
+ compare(vertical.position, 0.5)
+ for (i = 1; i <= 10; ++i) {
+ keyClick(Qt.Key_Up)
+ compare(vertical.position, Math.max(0.0, 0.5 - i * 0.1))
+ }
+ compare(vertical.position, 0.0)
+
+ var horizontal = control.ScrollBar.horizontal
+ verify(horizontal)
+
+ compare(horizontal.position, 0.0)
+ for (i = 1; i <= 10; ++i) {
+ keyClick(Qt.Key_Right)
+ compare(horizontal.position, Math.min(0.5, i * 0.1))
+ }
+ compare(horizontal.position, 0.5)
+ for (i = 1; i <= 10; ++i) {
+ keyClick(Qt.Key_Left)
+ compare(horizontal.position, Math.max(0.0, 0.5 - i * 0.1))
+ }
+ compare(horizontal.position, 0.0)
+ }
+}