diff options
author | J-P Nurmi <jpnurmi@theqtcompany.com> | 2015-04-29 09:55:05 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@theqtcompany.com> | 2015-06-11 15:12:56 +0000 |
commit | 3dab48bcc532f44acc0370d056329a2e5a6b7b6e (patch) | |
tree | bbd2dffec81d1bf101565ef4d46beefdd19b68dc | |
parent | f944c34757baf145f7018e37bc732d061f0bbf7f (diff) |
Import the new TabBar implementation
Change-Id: I2c646c07f8310c27f3f03f3cdb27f748c5e6198c
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
-rw-r--r-- | src/controls/qquicktabbar.cpp | 182 | ||||
-rw-r--r-- | src/controls/qquicktabbar_p.h | 26 | ||||
-rw-r--r-- | src/imports/controls/TabBar.qml | 27 |
3 files changed, 208 insertions, 27 deletions
diff --git a/src/controls/qquicktabbar.cpp b/src/controls/qquicktabbar.cpp index 340c2701..74766d1b 100644 --- a/src/controls/qquicktabbar.cpp +++ b/src/controls/qquicktabbar.cpp @@ -36,6 +36,10 @@ #include "qquicktabbar_p.h" #include "qquickcontainer_p_p.h" +#include "qquickexclusivegroup_p.h" + +#include <QtQuick/private/qquickitem_p.h> +#include <QtQml/private/qqmlobjectmodel_p.h> QT_BEGIN_NAMESPACE @@ -52,17 +56,84 @@ QT_BEGIN_NAMESPACE class QQuickTabBarPrivate : public QQuickContainerPrivate { + Q_DECLARE_PUBLIC(QQuickTabBar) + public: - QQuickTabBarPrivate() : currentIndex(0) { } + QQuickTabBarPrivate() : currentIndex(0), model(Q_NULLPTR), group(Q_NULLPTR) { } + + void updateLayout(); + void updateCurrent(); + + // TODO: implement the whole list property + static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj); int currentIndex; + QQmlObjectModel *model; + QQuickExclusiveGroup *group; }; +void QQuickTabBarPrivate::updateLayout() +{ + const int count = model->count(); + if (count > 0 && contentItem) { + const qreal spacing = contentItem->property("spacing").toReal(); + const qreal itemWidth = (contentItem->width() - qMax(0, count - 1) * spacing) / count; + + for (int i = 0; i < count; ++i) { + QQuickItem *item = qobject_cast<QQuickItem *>(model->get(i)); + if (item) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + if (!p->widthValid) { + item->setWidth(itemWidth); + p->widthValid = false; + } + } + } + } +} + +void QQuickTabBarPrivate::updateCurrent() +{ + Q_Q(QQuickTabBar); + q->setCurrentIndex(model->indexOf(group->current(), Q_NULLPTR)); +} + +void QQuickTabBarPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj) +{ + QQuickTabBar *bar = static_cast<QQuickTabBar *>(prop->object); + QQuickItem *item = qobject_cast<QQuickItem *>(obj); + if (item) + bar->addItem(item); + else + QQuickItemPrivate::data_append(prop, obj); +} + QQuickTabBar::QQuickTabBar(QQuickItem *parent) : QQuickContainer(*(new QQuickTabBarPrivate), parent) { + Q_D(QQuickTabBar); setFlag(ItemIsFocusScope); setActiveFocusOnTab(true); + + d->model = new QQmlObjectModel(this); + connect(d->model, &QQmlObjectModel::countChanged, this, &QQuickTabBar::countChanged); + QObjectPrivate::connect(d->model, &QQmlObjectModel::countChanged, d, &QQuickTabBarPrivate::updateLayout); + + d->group = new QQuickExclusiveGroup(this); + connect(d->group, &QQuickExclusiveGroup::currentChanged, this, &QQuickTabBar::currentItemChanged); + QObjectPrivate::connect(d->group, &QQuickExclusiveGroup::currentChanged, d, &QQuickTabBarPrivate::updateCurrent); +} + +/*! + \qmlproperty int QtQuickControls2::TabBar::count + \readonly + + TODO +*/ +int QQuickTabBar::count() const +{ + Q_D(const QQuickTabBar); + return d->model->count(); } /*! @@ -81,8 +152,115 @@ void QQuickTabBar::setCurrentIndex(int index) Q_D(QQuickTabBar); if (d->currentIndex != index) { d->currentIndex = index; - emit currentIndexChanged(index); + emit currentIndexChanged(); } } +/*! + \qmlproperty Item QtQuickControls2::TabBar::currentItem + + TODO +*/ +QQuickItem *QQuickTabBar::currentItem() const +{ + Q_D(const QQuickTabBar); + return qobject_cast<QQuickItem *>(d->group->current()); +} + +/*! + \qmlproperty model QtQuickControls2::TabBar::model + \readonly + + TODO +*/ +QVariant QQuickTabBar::model() const +{ + Q_D(const QQuickTabBar); + return QVariant::fromValue(d->model); +} + +QQmlListProperty<QObject> QQuickTabBar::contentData() +{ + Q_D(QQuickTabBar); + // TODO: implement the whole list property + return QQmlListProperty<QObject>(this, d, + QQuickTabBarPrivate::contentData_append, + QQuickItemPrivate::data_count, + QQuickItemPrivate::data_at, + QQuickItemPrivate::data_clear); +} + +/*! + \qmlmethod Item QtQuickControls2::TabBar::itemAt(int index) + + TODO +*/ +QQuickItem *QQuickTabBar::itemAt(int index) const +{ + Q_D(const QQuickTabBar); + return qobject_cast<QQuickItem *>(d->model->get(index)); +} + +/*! + \qmlmethod void QtQuickControls2::TabBar::addItem(Item item) + + TODO +*/ +void QQuickTabBar::addItem(QQuickItem *item) +{ + Q_D(QQuickTabBar); + insertItem(d->model->count(), item); +} + +/*! + \qmlmethod void QtQuickControls2::TabBar::insertItem(int index, Item item) + + TODO +*/ +void QQuickTabBar::insertItem(int index, QQuickItem *item) +{ + Q_D(QQuickTabBar); + d->model->insert(index, item); + d->group->addCheckable(item); + if (d->currentIndex == index) + d->group->setCurrent(item); +} + +/*! + \qmlmethod void QtQuickControls2::TabBar::moveItem(int from, int to) + + TODO +*/ +void QQuickTabBar::moveItem(int from, int to) +{ + Q_D(QQuickTabBar); + d->model->move(from, to); +} + +/*! + \qmlmethod void QtQuickControls2::TabBar::removeItem(int index) + + TODO +*/ +void QQuickTabBar::removeItem(int index) +{ + Q_D(QQuickTabBar); + d->group->removeCheckable(d->model->get(index)); + d->model->remove(index); +} + +void QQuickTabBar::componentComplete() +{ + Q_D(QQuickTabBar); + QQuickContainer::componentComplete(); + d->updateCurrent(); +} + +void QQuickTabBar::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickTabBar); + QQuickContainer::geometryChanged(newGeometry, oldGeometry); + d->updateLayout(); +} + QT_END_NAMESPACE diff --git a/src/controls/qquicktabbar_p.h b/src/controls/qquicktabbar_p.h index aee165a9..7d43e24e 100644 --- a/src/controls/qquicktabbar_p.h +++ b/src/controls/qquicktabbar_p.h @@ -49,6 +49,7 @@ // #include <QtQuickControls/private/qquickcontainer_p.h> +#include <QtQml/qqmllist.h> QT_BEGIN_NAMESPACE @@ -57,23 +58,44 @@ class QQuickTabBarPrivate; class Q_QUICKCONTROLS_EXPORT QQuickTabBar : 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(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged FINAL) + Q_PROPERTY(QVariant model READ model CONSTANT FINAL) + Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData) + Q_CLASSINFO("DefaultProperty", "contentData") public: explicit QQuickTabBar(QQuickItem *parent = Q_NULLPTR); + int count() const; int currentIndex() const; + QQuickItem *currentItem() const; + + QVariant model() const; + QQmlListProperty<QObject> 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 currentIndexChanged(int index); + void countChanged(); + void currentIndexChanged(); + void currentItemChanged(); + +protected: + void componentComplete() Q_DECL_OVERRIDE; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QQuickTabBar) Q_DECLARE_PRIVATE(QQuickTabBar) - friend class QQuickTabView; }; QT_END_NAMESPACE diff --git a/src/imports/controls/TabBar.qml b/src/imports/controls/TabBar.qml index 845cf3d0..93d30f35 100644 --- a/src/imports/controls/TabBar.qml +++ b/src/imports/controls/TabBar.qml @@ -40,14 +40,7 @@ import QtQuick.Controls 2.0 AbstractTabBar { id: control - property list<Item> items - readonly property int count: items.length property alias highlight: listView.highlight - property alias spacing: listView.spacing - - property Component delegate: TabButton { - width: (listView.width - Math.max(0, count - 1) * spacing) / count - } contentWidth: listView.contentWidth contentHeight: listView.contentHeight @@ -57,10 +50,6 @@ AbstractTabBar { Accessible.role: Accessible.PageTabList - ExclusiveGroup { - id: group - } - contentItem: ListView { id: listView @@ -69,18 +58,9 @@ AbstractTabBar { boundsBehavior: Flickable.StopAtBounds snapMode: ListView.SnapToItem - model: control.items + model: control.model currentIndex: control.currentIndex - delegate: Loader { - sourceComponent: control.delegate - visible: modelData.Tab.visible - Binding { target: item; property: "Exclusive.group"; value: group } - Binding { target: item; property: "text"; value: modelData.Tab.title } - Binding { target: item; property: "checked"; value: control.currentIndex === index } - Connections { target: item; onClicked: control.currentIndex = index } - } - highlightMoveDuration: 250 highlightResizeDuration: 0 highlightFollowsCurrentItem: true @@ -98,10 +78,11 @@ AbstractTabBar { background: Rectangle { implicitWidth: 26 implicitHeight: 26 - width: listView.width + border.color: control.Theme.backgroundColor border.width: 8 - color: listView.count > 1 ? control.Theme.frameColor : control.Theme.backgroundColor + color: control.count > 1 ? control.Theme.frameColor : control.Theme.backgroundColor + Rectangle { y: parent.height - height width: parent.width |