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:
J-P Nurmi 2015-11-03 19:57:57 +01:00
parent 99012cbe81
commit 1bbbfa1af4
6 changed files with 62 additions and 96 deletions

View File

@ -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);

View File

@ -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())
};

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -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()
}