aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2017-05-17 12:15:09 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2017-05-18 11:08:15 +0000
commit6bd301a56a4f7d010383ebcb04f7ef398b3be3ae (patch)
treea379c814fa0c03fa93b11659ccf4896b89d45a2a
parent1a99d5af4d53aef72b1dca9720e27d2f50658e05 (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.cpp123
-rw-r--r--src/quicktemplates2/qquicktabbar_p.h30
-rw-r--r--tests/auto/controls/data/tst_tabbar.qml117
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)
+ }
}