Implement TabBar without ExclusiveGroup
Make use of auto-exclusivity introduced in a108298
. Fixes also
the issue that the TabButton that corresponded currentIndex was
not checked at startup.
Change-Id: I44152e62c2dff30e8e0255c9403dcf46c4ea2f3a
Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
This commit is contained in:
parent
99012cbe81
commit
1bbbfa1af4
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "qquickcontainer_p.h"
|
||||
#include "qquickcontainer_p_p.h"
|
||||
#include "qquickexclusivegroup_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -53,7 +52,7 @@ QT_BEGIN_NAMESPACE
|
|||
\sa {Container Controls}
|
||||
*/
|
||||
|
||||
QQuickContainerPrivate::QQuickContainerPrivate() : contentModel(Q_NULLPTR), currentIndex(-1), updatingCurrent(false), exclusiveGroup(Q_NULLPTR)
|
||||
QQuickContainerPrivate::QQuickContainerPrivate() : contentModel(Q_NULLPTR), currentIndex(-1), updatingCurrent(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -89,13 +88,11 @@ void QQuickContainerPrivate::insertItem(int index, QQuickItem *item)
|
|||
{
|
||||
Q_Q(QQuickContainer);
|
||||
contentData.append(item);
|
||||
if (exclusiveGroup && !exclusiveGroup->isCheckable(item))
|
||||
if (!q->isContent(item))
|
||||
return;
|
||||
|
||||
QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
|
||||
contentModel->insert(index, item);
|
||||
if (exclusiveGroup)
|
||||
exclusiveGroup->addCheckable(item);
|
||||
|
||||
q->itemAdded(index, item);
|
||||
|
||||
|
@ -110,16 +107,12 @@ void QQuickContainerPrivate::moveItem(int from, int to)
|
|||
Q_Q(QQuickContainer);
|
||||
contentModel->move(from, to);
|
||||
updatingCurrent = true;
|
||||
if (exclusiveGroup) {
|
||||
q->setCurrentIndex(contentModel->indexOf(exclusiveGroup->current(), Q_NULLPTR));
|
||||
} else {
|
||||
if (from == currentIndex)
|
||||
q->setCurrentIndex(to);
|
||||
else if (from < currentIndex && to >= currentIndex)
|
||||
q->setCurrentIndex(currentIndex - 1);
|
||||
else if (from > currentIndex && to <= currentIndex)
|
||||
q->setCurrentIndex(currentIndex + 1);
|
||||
}
|
||||
if (from == currentIndex)
|
||||
q->setCurrentIndex(to);
|
||||
else if (from < currentIndex && to >= currentIndex)
|
||||
q->setCurrentIndex(currentIndex - 1);
|
||||
else if (from > currentIndex && to <= currentIndex)
|
||||
q->setCurrentIndex(currentIndex + 1);
|
||||
updatingCurrent = false;
|
||||
}
|
||||
|
||||
|
@ -127,7 +120,7 @@ void QQuickContainerPrivate::removeItem(int index, QQuickItem *item)
|
|||
{
|
||||
Q_Q(QQuickContainer);
|
||||
contentData.removeOne(item);
|
||||
if (exclusiveGroup && !exclusiveGroup->isCheckable(item))
|
||||
if (!q->isContent(item))
|
||||
return;
|
||||
|
||||
bool currentChanged = false;
|
||||
|
@ -141,8 +134,6 @@ void QQuickContainerPrivate::removeItem(int index, QQuickItem *item)
|
|||
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
|
||||
item->setParentItem(Q_NULLPTR);
|
||||
contentModel->remove(index);
|
||||
if (exclusiveGroup)
|
||||
exclusiveGroup->removeCheckable(item);
|
||||
|
||||
q->itemRemoved(index, item);
|
||||
|
||||
|
@ -150,13 +141,6 @@ void QQuickContainerPrivate::removeItem(int index, QQuickItem *item)
|
|||
emit q->currentIndexChanged();
|
||||
}
|
||||
|
||||
void QQuickContainerPrivate::_q_currentItemChanged()
|
||||
{
|
||||
Q_Q(QQuickContainer);
|
||||
if (!updatingCurrent)
|
||||
q->setCurrentIndex(contentModel->indexOf(exclusiveGroup->current(), Q_NULLPTR));
|
||||
}
|
||||
|
||||
void QQuickContainerPrivate::_q_currentIndexChanged()
|
||||
{
|
||||
Q_Q(QQuickContainer);
|
||||
|
@ -437,8 +421,6 @@ void QQuickContainer::setCurrentIndex(int index)
|
|||
d->currentIndex = index;
|
||||
emit currentIndexChanged();
|
||||
emit currentItemChanged();
|
||||
if (d->exclusiveGroup && isComponentComplete())
|
||||
d->exclusiveGroup->setCurrent(d->contentModel->get(index));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,48 +435,6 @@ QQuickItem *QQuickContainer::currentItem() const
|
|||
return itemAt(d->currentIndex);
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty bool Qt.labs.controls::Container::exclusive
|
||||
|
||||
This property holds whether the container is considered exclusive.
|
||||
An exclusive container manages the the content children with an
|
||||
ExclusiveGroup.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa ExclusiveGroup
|
||||
*/
|
||||
bool QQuickContainer::isExclusive() const
|
||||
{
|
||||
Q_D(const QQuickContainer);
|
||||
return d->exclusiveGroup;
|
||||
}
|
||||
|
||||
void QQuickContainer::setExclusive(bool exclusive)
|
||||
{
|
||||
Q_D(QQuickContainer);
|
||||
if (exclusive == isExclusive())
|
||||
return;
|
||||
|
||||
if (exclusive) {
|
||||
if (!d->exclusiveGroup) {
|
||||
d->exclusiveGroup = new QQuickExclusiveGroup(this);
|
||||
connect(d->exclusiveGroup, &QQuickExclusiveGroup::currentChanged, this, &QQuickContainer::currentItemChanged);
|
||||
QObjectPrivate::connect(d->exclusiveGroup, &QQuickExclusiveGroup::currentChanged, d, &QQuickContainerPrivate::_q_currentItemChanged);
|
||||
|
||||
const int count = d->contentModel->count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
QObject *object = d->contentModel->get(i);
|
||||
if (d->exclusiveGroup->isCheckable(object))
|
||||
d->exclusiveGroup->addCheckable(object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
delete d->exclusiveGroup;
|
||||
d->exclusiveGroup = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
void QQuickContainer::itemChange(ItemChange change, const ItemChangeData &data)
|
||||
{
|
||||
Q_D(QQuickContainer);
|
||||
|
@ -515,24 +455,26 @@ void QQuickContainer::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem
|
|||
if (oldItem) {
|
||||
QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
|
||||
|
||||
if (!d->exclusiveGroup) {
|
||||
int signalIndex = oldItem->metaObject()->indexOfSignal("currentIndexChanged()");
|
||||
if (signalIndex != -1)
|
||||
QMetaObject::disconnect(oldItem, signalIndex, this, slotIndex);
|
||||
}
|
||||
int signalIndex = oldItem->metaObject()->indexOfSignal("currentIndexChanged()");
|
||||
if (signalIndex != -1)
|
||||
QMetaObject::disconnect(oldItem, signalIndex, this, slotIndex);
|
||||
}
|
||||
|
||||
if (newItem) {
|
||||
QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
|
||||
|
||||
if (!d->exclusiveGroup) {
|
||||
int signalIndex = newItem->metaObject()->indexOfSignal("currentIndexChanged()");
|
||||
if (signalIndex != -1)
|
||||
QMetaObject::connect(newItem, signalIndex, this, slotIndex);
|
||||
}
|
||||
int signalIndex = newItem->metaObject()->indexOfSignal("currentIndexChanged()");
|
||||
if (signalIndex != -1)
|
||||
QMetaObject::connect(newItem, signalIndex, this, slotIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool QQuickContainer::isContent(QQuickItem *item) const
|
||||
{
|
||||
Q_UNUSED(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QQuickContainer::itemAdded(int index, QQuickItem *item)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
|
|
|
@ -64,7 +64,6 @@ class Q_LABSTEMPLATES_EXPORT QQuickContainer : public QQuickControl
|
|||
Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL)
|
||||
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL)
|
||||
Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged FINAL)
|
||||
Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive NOTIFY exclusiveChanged FINAL)
|
||||
Q_CLASSINFO("DefaultProperty", "contentData")
|
||||
|
||||
public:
|
||||
|
@ -85,9 +84,6 @@ public:
|
|||
int currentIndex() const;
|
||||
QQuickItem *currentItem() const;
|
||||
|
||||
bool isExclusive() const;
|
||||
void setExclusive(bool exclusive);
|
||||
|
||||
public Q_SLOTS:
|
||||
void setCurrentIndex(int index);
|
||||
|
||||
|
@ -96,7 +92,6 @@ Q_SIGNALS:
|
|||
void contentChildrenChanged();
|
||||
void currentIndexChanged();
|
||||
void currentItemChanged();
|
||||
void exclusiveChanged();
|
||||
|
||||
protected:
|
||||
QQuickContainer(QQuickContainerPrivate &dd, QQuickItem *parent);
|
||||
|
@ -104,13 +99,13 @@ protected:
|
|||
void itemChange(ItemChange change, const ItemChangeData &data) Q_DECL_OVERRIDE;
|
||||
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) Q_DECL_OVERRIDE;
|
||||
|
||||
virtual bool isContent(QQuickItem *item) const;
|
||||
virtual void itemAdded(int index, QQuickItem *item);
|
||||
virtual void itemRemoved(int index, QQuickItem *item);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QQuickContainer)
|
||||
Q_DECLARE_PRIVATE(QQuickContainer)
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_currentItemChanged())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_currentIndexChanged())
|
||||
};
|
||||
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QQuickExclusiveGroup;
|
||||
|
||||
class Q_LABSTEMPLATES_EXPORT QQuickContainerPrivate : public QQuickControlPrivate, public QQuickItemChangeListener
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QQuickContainer)
|
||||
|
@ -71,7 +69,6 @@ public:
|
|||
void moveItem(int from, int to);
|
||||
void removeItem(int index, QQuickItem *item);
|
||||
|
||||
void _q_currentItemChanged();
|
||||
void _q_currentIndexChanged();
|
||||
|
||||
void itemChildAdded(QQuickItem *item, QQuickItem *child) Q_DECL_OVERRIDE;
|
||||
|
@ -93,7 +90,6 @@ public:
|
|||
QQmlObjectModel *contentModel;
|
||||
int currentIndex;
|
||||
bool updatingCurrent;
|
||||
QQuickExclusiveGroup *exclusiveGroup;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QQuickContainerPrivate, Q_COMPLEX_TYPE);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include "qquicktabbar_p.h"
|
||||
#include "qquicktabbutton_p.h"
|
||||
#include "qquickcontainer_p_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -66,13 +67,26 @@ class QQuickTabBarPrivate : public QQuickContainerPrivate
|
|||
Q_DECLARE_PUBLIC(QQuickTabBar)
|
||||
|
||||
public:
|
||||
QQuickTabBarPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
void updateCurrentItem();
|
||||
void updateCurrentIndex();
|
||||
void updateLayout();
|
||||
};
|
||||
|
||||
void QQuickTabBarPrivate::updateCurrentItem()
|
||||
{
|
||||
QQuickTabButton *button = qobject_cast<QQuickTabButton *>(contentModel->get(currentIndex));
|
||||
if (button)
|
||||
button->setChecked(true);
|
||||
}
|
||||
|
||||
void QQuickTabBarPrivate::updateCurrentIndex()
|
||||
{
|
||||
Q_Q(QQuickTabBar);
|
||||
QQuickTabButton *button = qobject_cast<QQuickTabButton *>(q->sender());
|
||||
if (button && button->isChecked())
|
||||
q->setCurrentIndex(contentModel->indexOf(button, Q_NULLPTR));
|
||||
}
|
||||
|
||||
void QQuickTabBarPrivate::updateLayout()
|
||||
{
|
||||
Q_Q(QQuickTabBar);
|
||||
|
@ -96,8 +110,9 @@ void QQuickTabBarPrivate::updateLayout()
|
|||
QQuickTabBar::QQuickTabBar(QQuickItem *parent) :
|
||||
QQuickContainer(*(new QQuickTabBarPrivate), parent)
|
||||
{
|
||||
setExclusive(true);
|
||||
Q_D(QQuickTabBar);
|
||||
setFlag(ItemIsFocusScope);
|
||||
QObjectPrivate::connect(this, &QQuickTabBar::currentIndexChanged, d, &QQuickTabBarPrivate::updateCurrentItem);
|
||||
}
|
||||
|
||||
void QQuickTabBar::updatePolish()
|
||||
|
@ -111,6 +126,7 @@ void QQuickTabBar::componentComplete()
|
|||
{
|
||||
Q_D(QQuickTabBar);
|
||||
QQuickContainer::componentComplete();
|
||||
d->updateCurrentItem();
|
||||
d->updateLayout();
|
||||
}
|
||||
|
||||
|
@ -121,18 +137,27 @@ void QQuickTabBar::geometryChanged(const QRectF &newGeometry, const QRectF &oldG
|
|||
d->updateLayout();
|
||||
}
|
||||
|
||||
bool QQuickTabBar::isContent(QQuickItem *item) const
|
||||
{
|
||||
return qobject_cast<QQuickTabButton *>(item);
|
||||
}
|
||||
|
||||
void QQuickTabBar::itemAdded(int index, QQuickItem *item)
|
||||
{
|
||||
Q_D(QQuickTabBar);
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(item);
|
||||
if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item))
|
||||
QObjectPrivate::connect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex);
|
||||
if (isComponentComplete())
|
||||
polish();
|
||||
}
|
||||
|
||||
void QQuickTabBar::itemRemoved(int index, QQuickItem *item)
|
||||
{
|
||||
Q_D(QQuickTabBar);
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(item);
|
||||
if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item))
|
||||
QObjectPrivate::disconnect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex);
|
||||
if (isComponentComplete())
|
||||
polish();
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ protected:
|
|||
void updatePolish() Q_DECL_OVERRIDE;
|
||||
void componentComplete() Q_DECL_OVERRIDE;
|
||||
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
|
||||
bool isContent(QQuickItem *item) const Q_DECL_OVERRIDE;
|
||||
void itemAdded(int index, QQuickItem *item) Q_DECL_OVERRIDE;
|
||||
void itemRemoved(int index, QQuickItem *item) Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
|
@ -120,24 +120,29 @@ TestCase {
|
|||
compare(control.count, 1)
|
||||
compare(control.currentIndex, 0)
|
||||
compare(control.currentItem.text, "0")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.addItem(tabButton.createObject(control, {text: "1"}))
|
||||
compare(control.count, 2)
|
||||
compare(control.currentIndex, 0)
|
||||
compare(control.currentItem.text, "0")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.addItem(tabButton.createObject(control, {text: "2"}))
|
||||
compare(control.count, 3)
|
||||
compare(control.currentIndex, 0)
|
||||
compare(control.currentItem.text, "0")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.currentIndex = 1
|
||||
compare(control.currentIndex, 1)
|
||||
compare(control.currentItem.text, "1")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.currentIndex = 2
|
||||
compare(control.currentIndex, 2)
|
||||
compare(control.currentItem.text, "2")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.destroy()
|
||||
}
|
||||
|
@ -148,6 +153,7 @@ TestCase {
|
|||
compare(control.count, 2)
|
||||
compare(control.currentIndex, 0)
|
||||
compare(control.currentItem.text, "0")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.destroy()
|
||||
|
||||
|
@ -156,6 +162,7 @@ TestCase {
|
|||
compare(control.count, 2)
|
||||
compare(control.currentIndex, 1)
|
||||
compare(control.currentItem.text, "1")
|
||||
compare(control.currentItem.checked, true)
|
||||
|
||||
control.destroy()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue