diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-05-17 12:15:09 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-05-18 11:08:15 +0000 |
commit | 6bd301a56a4f7d010383ebcb04f7ef398b3be3ae (patch) | |
tree | a379c814fa0c03fa93b11659ccf4896b89d45a2a | |
parent | 1a99d5af4d53aef72b1dca9720e27d2f50658e05 (diff) |
QQuickTabBar: introduce index/tabBar/position attached properties
The upcoming Fusion style tab buttons are visually different depending
on whether the tab bar is at the top or at the bottom. Let styles access
the tab bar via attached properties to be able to visualize such things.
[ChangeLog][Controls][TabBar] Added index/tabBar/position attached
properties.
Change-Id: I1ff8105ac8600dad3ed5c6aafc6d85cf06283bed
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r-- | src/quicktemplates2/qquicktabbar.cpp | 123 | ||||
-rw-r--r-- | src/quicktemplates2/qquicktabbar_p.h | 30 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_tabbar.qml | 117 |
3 files changed, 270 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp index c255ef1b..2f025dcf 100644 --- a/src/quicktemplates2/qquicktabbar.cpp +++ b/src/quicktemplates2/qquicktabbar.cpp @@ -116,6 +116,28 @@ public: QQuickTabBar::Position position; }; +class QQuickTabBarAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickTabBarAttached) + +public: + QQuickTabBarAttachedPrivate() + : index(-1), + tabBar(nullptr) + { + } + + static QQuickTabBarAttachedPrivate *get(QQuickTabBarAttached *attached) + { + return attached->d_func(); + } + + void update(QQuickTabBar *tabBar, int index); + + int index; + QQuickTabBar *tabBar; +}; + QQuickTabBarPrivate::QQuickTabBarPrivate() : updatingLayout(false), hasContentWidth(false), @@ -351,6 +373,11 @@ void QQuickTabBar::resetContentHeight() d->updateLayout(); } +QQuickTabBarAttached *QQuickTabBar::qmlAttachedProperties(QObject *object) +{ + return new QQuickTabBarAttached(object); +} + void QQuickTabBar::updatePolish() { Q_D(QQuickTabBar); @@ -385,16 +412,29 @@ void QQuickTabBar::itemAdded(int index, QQuickItem *item) QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-55129 if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item)) QObjectPrivate::connect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex); + QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); + if (attached) + QQuickTabBarAttachedPrivate::get(attached)->update(this, index); if (isComponentComplete()) polish(); } +void QQuickTabBar::itemMoved(int index, QQuickItem *item) +{ + QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); + if (attached) + QQuickTabBarAttachedPrivate::get(attached)->update(this, index); +} + void QQuickTabBar::itemRemoved(int index, QQuickItem *item) { Q_D(QQuickTabBar); Q_UNUSED(index); if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item)) QObjectPrivate::disconnect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex); + QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item)); + if (attached) + QQuickTabBarAttachedPrivate::get(attached)->update(nullptr, -1); if (isComponentComplete()) polish(); } @@ -406,4 +446,87 @@ QAccessible::Role QQuickTabBar::accessibleRole() const } #endif +/*! + \qmlattachedproperty int QtQuick.Controls::TabBar::index + \since QtQuick.Controls 2.3 + \readonly + + This attached property holds the index of each tab button in the TabBar. + + It is attached to each tab button of the TabBar. +*/ + +/*! + \qmlattachedproperty TabBar QtQuick.Controls::TabBar::tabBar + \since QtQuick.Controls 2.3 + \readonly + + This attached property holds the tab bar that manages this tab button. + + It is attached to each tab button of the TabBar. +*/ + +/*! + \qmlattachedproperty enumeration QtQuick.Controls::TabBar::position + \since QtQuick.Controls 2.3 + \readonly + + This attached property holds the position of the tab bar. + + It is attached to each tab button of the TabBar. + + Possible values: + \value TabBar.Header The tab bar is at the top, as a window or page header. + \value TabBar.Footer The tab bar is at the bottom, as a window or page footer. +*/ + +void QQuickTabBarAttachedPrivate::update(QQuickTabBar *newTabBar, int newIndex) +{ + Q_Q(QQuickTabBarAttached); + const int oldIndex = index; + const QQuickTabBar *oldTabBar = tabBar; + const QQuickTabBar::Position oldPos = q->position(); + + index = newIndex; + tabBar = newTabBar; + + if (oldTabBar != newTabBar) { + if (oldTabBar) + QObject::disconnect(oldTabBar, &QQuickTabBar::positionChanged, q, &QQuickTabBarAttached::positionChanged); + if (newTabBar) + QObject::connect(newTabBar, &QQuickTabBar::positionChanged, q, &QQuickTabBarAttached::positionChanged); + emit q->tabBarChanged(); + } + + if (oldIndex != newIndex) + emit q->indexChanged(); + if (oldPos != q->position()) + emit q->positionChanged(); +} + +QQuickTabBarAttached::QQuickTabBarAttached(QObject *parent) + : QObject(*(new QQuickTabBarAttachedPrivate), parent) +{ +} + +int QQuickTabBarAttached::index() const +{ + Q_D(const QQuickTabBarAttached); + return d->index; +} + +QQuickTabBar *QQuickTabBarAttached::tabBar() const +{ + Q_D(const QQuickTabBarAttached); + return d->tabBar; +} + +QQuickTabBar::Position QQuickTabBarAttached::position() const +{ + Q_D(const QQuickTabBarAttached); + if (!d->tabBar) + return QQuickTabBar::Header; + return d->tabBar->position(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h index 0ffd53d5..e1016c06 100644 --- a/src/quicktemplates2/qquicktabbar_p.h +++ b/src/quicktemplates2/qquicktabbar_p.h @@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE class QQuickTabBarPrivate; +class QQuickTabBarAttached; +class QQuickTabBarAttachedPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBar : public QQuickContainer { @@ -81,6 +83,8 @@ public: void setContentHeight(qreal height); void resetContentHeight(); + static QQuickTabBarAttached *qmlAttachedProperties(QObject *object); + Q_SIGNALS: void positionChanged(); Q_REVISION(2) void contentWidthChanged(); @@ -92,6 +96,7 @@ protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; bool isContent(QQuickItem *item) const override; void itemAdded(int index, QQuickItem *item) override; + void itemMoved(int index, QQuickItem *item) override; void itemRemoved(int index, QQuickItem *item) override; #if QT_CONFIG(accessibility) @@ -103,8 +108,33 @@ private: Q_DECLARE_PRIVATE(QQuickTabBar) }; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBarAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL) + Q_PROPERTY(QQuickTabBar *tabBar READ tabBar NOTIFY tabBarChanged FINAL) + Q_PROPERTY(QQuickTabBar::Position position READ position NOTIFY positionChanged FINAL) + +public: + explicit QQuickTabBarAttached(QObject *parent = nullptr); + + int index() const; + QQuickTabBar *tabBar() const; + QQuickTabBar::Position position() const; + +Q_SIGNALS: + void indexChanged(); + void tabBarChanged(); + void positionChanged(); + +private: + Q_DISABLE_COPY(QQuickTabBarAttached) + Q_DECLARE_PRIVATE(QQuickTabBarAttached) +}; + QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickTabBar) +QML_DECLARE_TYPEINFO(QQuickTabBar, QML_HAS_ATTACHED_PROPERTIES) #endif // QQUICKTABBAR_P_H diff --git a/tests/auto/controls/data/tst_tabbar.qml b/tests/auto/controls/data/tst_tabbar.qml index 4c67ec82..5c9905d5 100644 --- a/tests/auto/controls/data/tst_tabbar.qml +++ b/tests/auto/controls/data/tst_tabbar.qml @@ -576,4 +576,121 @@ TestCase { compare(tab2.height, control.contentHeight) compare(tab3.height, control.contentHeight) } + + Component { + id: attachedButton + TabButton { + property int index: TabBar.index + property TabBar tabBar: TabBar.tabBar + property int position: TabBar.position + } + } + + function test_attached() { + var control = createTemporaryObject(tabBar, testCase, {position: TabBar.Footer}) + + // append + var tab1 = createTemporaryObject(attachedButton, testCase) + compare(tab1.index, -1) + compare(tab1.tabBar, null) + compare(tab1.position, TabBar.Header) + + control.addItem(tab1) + compare(tab1.index, 0) + compare(tab1.tabBar, control) + compare(tab1.position, TabBar.Footer) + + // insert in the beginning + var tab2 = createTemporaryObject(attachedButton, testCase) + compare(tab2.index, -1) + compare(tab2.tabBar, null) + compare(tab2.position, TabBar.Header) + + control.insertItem(0, tab2) + compare(tab2.index, 0) + compare(tab2.tabBar, control) + compare(tab2.position, TabBar.Footer) + + compare(tab1.index, 1) + + // insert in the middle + var tab3 = createTemporaryObject(attachedButton, testCase) + compare(tab3.index, -1) + compare(tab3.tabBar, null) + compare(tab3.position, TabBar.Header) + + control.insertItem(1, tab3) + compare(tab3.index, 1) + compare(tab3.tabBar, control) + compare(tab3.position, TabBar.Footer) + + compare(tab2.index, 0) + compare(tab1.index, 2) + + // insert in the end + var tab4 = createTemporaryObject(attachedButton, testCase) + compare(tab4.index, -1) + compare(tab4.tabBar, null) + compare(tab4.position, TabBar.Header) + + control.insertItem(-1, tab4) + compare(tab4.index, 3) + compare(tab4.tabBar, control) + compare(tab4.position, TabBar.Footer) + + compare(tab2.index, 0) + compare(tab3.index, 1) + compare(tab1.index, 2) + + // move forwards + control.moveItem(0, 1) + compare(tab3.index, 0) + compare(tab2.index, 1) + compare(tab1.index, 2) + compare(tab4.index, 3) + + control.moveItem(0, 2) + compare(tab2.index, 0) + compare(tab1.index, 1) + compare(tab3.index, 2) + compare(tab4.index, 3) + + control.moveItem(1, 3) + compare(tab2.index, 0) + compare(tab3.index, 1) + compare(tab4.index, 2) + compare(tab1.index, 3) + + // move backwards + control.moveItem(3, 2) + compare(tab2.index, 0) + compare(tab3.index, 1) + compare(tab1.index, 2) + compare(tab4.index, 3) + + control.moveItem(3, 1) + compare(tab2.index, 0) + compare(tab4.index, 1) + compare(tab3.index, 2) + compare(tab1.index, 3) + + // remove from the beginning + control.removeItem(0) + compare(tab2.index, -1) + compare(tab2.tabBar, null) + compare(tab2.position, TabBar.Header) + + compare(tab4.index, 0) + compare(tab3.index, 1) + compare(tab1.index, 2) + + // remove from the middle + control.removeItem(1) + compare(tab3.index, -1) + compare(tab3.tabBar, null) + compare(tab3.position, TabBar.Header) + + compare(tab4.index, 0) + compare(tab1.index, 1) + } } |