From dbf0b858952f57be61dc1b2765c05d25e86db546 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 29 Apr 2015 09:37:15 +0200 Subject: Add SwipeView Based on the old TabView prototype, easy to use together with TabBar. The side-swiping feature will be removed from TabView to keep it simple and light-weight. Change-Id: I214b88688b98897962d335fe00008d222e0656a8 Reviewed-by: J-P Nurmi --- src/extras/extras.pri | 6 +- src/extras/qquickswipeview.cpp | 247 ++++++++++++++++++++++++++++ src/extras/qquickswipeview_p.h | 103 ++++++++++++ src/imports/extras/SwipeView.qml | 73 ++++++++ src/imports/extras/extras.pro | 3 +- src/imports/extras/qmldir | 1 + src/imports/extras/qtquickextras2plugin.cpp | 2 + 7 files changed, 432 insertions(+), 3 deletions(-) create mode 100644 src/extras/qquickswipeview.cpp create mode 100644 src/extras/qquickswipeview_p.h create mode 100644 src/imports/extras/SwipeView.qml (limited to 'src') diff --git a/src/extras/extras.pri b/src/extras/extras.pri index c8cfeba4..63c10268 100644 --- a/src/extras/extras.pri +++ b/src/extras/extras.pri @@ -1,7 +1,9 @@ INCLUDEPATH += $$PWD HEADERS += \ - $$PWD/qquickdrawer_p.h + $$PWD/qquickdrawer_p.h \ + $$PWD/qquickswipeview_p.h SOURCES += \ - $$PWD/qquickdrawer.cpp + $$PWD/qquickdrawer.cpp \ + $$PWD/qquickswipeview.cpp diff --git a/src/extras/qquickswipeview.cpp b/src/extras/qquickswipeview.cpp new file mode 100644 index 00000000..bd9b8464 --- /dev/null +++ b/src/extras/qquickswipeview.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Extras 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 +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype SwipeView + \inherits Container + \instantiates QQuickSwipeView + \inqmlmodule QtQuick.Extras + \ingroup navigation + \brief A swipe view control. + + TODO +*/ + +class QQuickSwipeViewPrivate : public QQuickContainerPrivate +{ + Q_DECLARE_PUBLIC(QQuickSwipeView) + +public: + QQuickSwipeViewPrivate() : currentIndex(0), model(Q_NULLPTR) { } + + void _q_updateCurrent(); + + // TODO: implement the whole list property + static void contentData_append(QQmlListProperty *, QObject *); + + int currentIndex; + QQmlObjectModel *model; +}; + +void QQuickSwipeViewPrivate::_q_updateCurrent() +{ + Q_Q(QQuickSwipeView); + q->setCurrentIndex(contentItem ? contentItem->property("currentIndex").toInt() : -1); +} + +void QQuickSwipeViewPrivate::contentData_append(QQmlListProperty *prop, QObject *obj) +{ + QQuickSwipeView *view = static_cast(prop->object); + if (QQuickItem *item = qobject_cast(obj)) + view->addItem(item); + else + QQuickItemPrivate::data_append(prop, obj); +} + +QQuickSwipeView::QQuickSwipeView(QQuickItem *parent) : + QQuickContainer(*(new QQuickSwipeViewPrivate), parent) +{ + Q_D(QQuickSwipeView); + setFlag(ItemIsFocusScope); + setActiveFocusOnTab(true); + + d->model = new QQmlObjectModel(this); + connect(d->model, &QQmlObjectModel::countChanged, this, &QQuickSwipeView::countChanged); +} + +/*! + \qmlproperty int QtQuickControls2::SwipeView::count + + TODO +*/ +int QQuickSwipeView::count() const +{ + Q_D(const QQuickSwipeView); + return d->model->count(); +} + +/*! + \qmlproperty int QtQuickControls2::SwipeView::currentIndex + + TODO +*/ +int QQuickSwipeView::currentIndex() const +{ + Q_D(const QQuickSwipeView); + return d->currentIndex; +} + +void QQuickSwipeView::setCurrentIndex(int index) +{ + Q_D(QQuickSwipeView); + if (d->currentIndex != index) { + d->currentIndex = index; + emit currentIndexChanged(); + } +} + +/*! + \qmlproperty model QtQuickControls2::SwipeView::model + \readonly + + TODO +*/ +QVariant QQuickSwipeView::model() const +{ + Q_D(const QQuickSwipeView); + return QVariant::fromValue(d->model); +} + +QQmlListProperty QQuickSwipeView::contentData() +{ + Q_D(QQuickSwipeView); + // TODO: implement the whole list property + return QQmlListProperty(this, d, + QQuickSwipeViewPrivate::contentData_append, + QQuickItemPrivate::data_count, + QQuickItemPrivate::data_at, + QQuickItemPrivate::data_clear); +} + +/*! + \qmlmethod Item QtQuickControls2::SwipeView::itemAt(int index) + + TODO +*/ +QQuickItem *QQuickSwipeView::itemAt(int index) const +{ + Q_D(const QQuickSwipeView); + return qobject_cast(d->model->get(index)); +} + +/*! + \qmlmethod void QtQuickControls2::SwipeView::addItem(Item item) + + TODO +*/ +void QQuickSwipeView::addItem(QQuickItem *item) +{ + Q_D(QQuickSwipeView); + d->model->append(item); +} + +/*! + \qmlmethod void QtQuickControls2::SwipeView::insertItem(int index, Item item) + + TODO +*/ +void QQuickSwipeView::insertItem(int index, QQuickItem *item) +{ + Q_D(QQuickSwipeView); + d->model->insert(index, item); +} + +/*! + \qmlmethod void QtQuickControls2::SwipeView::moveItem(int from, int to) + + TODO +*/ +void QQuickSwipeView::moveItem(int from, int to) +{ + Q_D(QQuickSwipeView); + d->model->move(from, to); +} + +/*! + \qmlmethod void QtQuickControls2::SwipeView::removeItem(int index) + + TODO +*/ +void QQuickSwipeView::removeItem(int index) +{ + Q_D(QQuickSwipeView); + d->model->remove(index); +} + +void QQuickSwipeView::componentComplete() +{ + Q_D(QQuickSwipeView); + QQuickContainer::componentComplete(); + d->_q_updateCurrent(); +} + +void QQuickSwipeView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickSwipeView); + QQuickContainer::geometryChanged(newGeometry, oldGeometry); + + const int count = d->model->count(); + for (int i = 0; i < count; ++i) { + QQuickItem *item = qobject_cast(d->model->get(i)); + if (item) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + if (!p->widthValid) { + item->setWidth(newGeometry.width()); + p->widthValid = false; + } + if (!p->heightValid) { + item->setHeight(newGeometry.height()); + p->widthValid = false; + } + } + } +} + +void QQuickSwipeView::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) +{ + if (oldItem) + disconnect(oldItem, SIGNAL(currentIndexChanged()), this, SLOT(_q_updateCurrent())); + if (newItem) + connect(newItem, SIGNAL(currentIndexChanged()), this, SLOT(_q_updateCurrent())); +} + +QT_END_NAMESPACE + +#include "moc_qquickswipeview_p.cpp" diff --git a/src/extras/qquickswipeview_p.h b/src/extras/qquickswipeview_p.h new file mode 100644 index 00000000..53e1032d --- /dev/null +++ b/src/extras/qquickswipeview_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Extras 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 +#include + +QT_BEGIN_NAMESPACE + +class QQuickSwipeViewPrivate; + +class Q_QUICKEXTRAS_EXPORT QQuickSwipeView : public QQuickContainer +{ + Q_OBJECT + Q_PROPERTY(int count READ count NOTIFY countChanged FINAL) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL) + Q_PROPERTY(QVariant model READ model CONSTANT FINAL) + Q_PROPERTY(QQmlListProperty contentData READ contentData) + Q_CLASSINFO("DefaultProperty", "contentData") + +public: + explicit QQuickSwipeView(QQuickItem *parent = Q_NULLPTR); + + int count() const; + int currentIndex() const; + + QVariant model() const; + QQmlListProperty contentData(); + + Q_INVOKABLE QQuickItem *itemAt(int index) const; + Q_INVOKABLE void addItem(QQuickItem *item); + Q_INVOKABLE void insertItem(int index, QQuickItem *item); + Q_INVOKABLE void moveItem(int from, int to); + Q_INVOKABLE void removeItem(int index); + +public Q_SLOTS: + void setCurrentIndex(int index); + +Q_SIGNALS: + void countChanged(); + void currentIndexChanged(); + +protected: + void componentComplete() Q_DECL_OVERRIDE; + 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()) +}; + +QT_END_NAMESPACE + +#endif // QQUICKSWIPEVIEW_P_H diff --git a/src/imports/extras/SwipeView.qml b/src/imports/extras/SwipeView.qml new file mode 100644 index 00000000..85e31874 --- /dev/null +++ b/src/imports/extras/SwipeView.qml @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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.Extras 2.0 + +AbstractSwipeView { + id: control + + property alias spacing: listView.spacing + + contentWidth: listView.implicitWidth + contentHeight: listView.contentHeight + + implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) + + Accessible.role: Accessible.PageTabList + + contentItem: ListView { + id: listView + + currentIndex: control.currentIndex + + x: control.leftPadding + y: control.topPadding + width: parent.width - control.leftPadding - control.rightPadding + height: parent.height - control.topPadding - control.bottomPadding + + orientation: Qt.Horizontal + snapMode: ListView.SnapOneItem + boundsBehavior: Flickable.StopAtBounds + highlightRangeMode: ListView.StrictlyEnforceRange + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 250 + + model: control.model + } +} diff --git a/src/imports/extras/extras.pro b/src/imports/extras/extras.pro index 437fcab4..675a058f 100644 --- a/src/imports/extras/extras.pro +++ b/src/imports/extras/extras.pro @@ -9,7 +9,8 @@ OTHER_FILES += \ qmldir QML_FILES = \ - Drawer.qml + Drawer.qml \ + SwipeView.qml SOURCES += \ $$PWD/qtquickextras2plugin.cpp diff --git a/src/imports/extras/qmldir b/src/imports/extras/qmldir index ec2bc05a..d21f666e 100644 --- a/src/imports/extras/qmldir +++ b/src/imports/extras/qmldir @@ -2,3 +2,4 @@ module QtQuick.Extras plugin qtquickextras2plugin classname QtQuickExtras2Plugin Drawer 2.0 Drawer.qml +SwipeView 2.0 SwipeView.qml diff --git a/src/imports/extras/qtquickextras2plugin.cpp b/src/imports/extras/qtquickextras2plugin.cpp index e2e0d62d..2a099ae2 100644 --- a/src/imports/extras/qtquickextras2plugin.cpp +++ b/src/imports/extras/qtquickextras2plugin.cpp @@ -37,6 +37,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -52,6 +53,7 @@ public: void QtQuickExtras2Plugin::registerTypes(const char *uri) { qmlRegisterType(uri, 2, 0, "AbstractDrawer"); + qmlRegisterType(uri, 2, 0, "AbstractSwipeView"); } QT_END_NAMESPACE -- cgit v1.2.3