Revision control

Copy as Markdown

// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qquickcontainer_p.h"
#include "qquickcontainer_p_p.h"
#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuick/private/qquickitemview_p.h>
QT_BEGIN_NAMESPACE
/*!
\qmltype Container
\inherits Control
//! \nativetype QQuickContainer
\inqmlmodule QtQuick.Controls
\since 5.7
\ingroup qtquickcontrols-containers
\brief Abstract base type providing functionality common to containers.
Container is the base type of container-like user interface controls that
allow dynamic insertion and removal of items.
\section2 Using Containers
Typically, items are statically declared as children of Container, but it
is also possible to \l {addItem}{add}, \l {insertItem}{insert},
\l {moveItem}{move} and \l {removeItem}{remove} items dynamically. The
items in a container can be accessed using \l itemAt() or
\l contentChildren.
Most containers have the concept of a "current" item. The current item is
specified via the \l currentIndex property, and can be accessed using the
read-only \l currentItem property.
The following example illustrates dynamic insertion of items to a \l TabBar,
which is one of the concrete implementations of Container.
\code
Row {
TabBar {
id: tabBar
currentIndex: 0
width: parent.width - addButton.width
TabButton { text: "TabButton" }
}
Component {
id: tabButton
TabButton { text: "TabButton" }
}
Button {
id: addButton
text: "+"
flat: true
onClicked: {
tabBar.addItem(tabButton.createObject(tabBar))
console.log("added:", tabBar.itemAt(tabBar.count - 1))
}
}
}
\endcode
\section2 Managing the Current Index
When using multiple containers, such as \l TabBar and \l SwipeView, together,
their \l currentIndex properties can be bound to each other to keep them in
sync. When the user interacts with either container, its current index changes
automatically propagate to the other container.
Notice, however, that assigning a \c currentIndex value in JavaScript removes
the respective binding. In order to retain the bindings, use the following
methods to alter the current index:
\list
\li \l incrementCurrentIndex()
\li \l decrementCurrentIndex()
\li \l setCurrentIndex()
\endlist
\code
TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
}
SwipeView {
id: swipeView
currentIndex: tabBar.currentIndex
}
Button {
text: qsTr("Home")
onClicked: swipeView.setCurrentIndex(0)
enabled: swipeView.currentIndex != 0
}
Button {
text: qsTr("Previous")
onClicked: swipeView.decrementCurrentIndex()
enabled: swipeView.currentIndex > 0
}
Button {
text: qsTr("Next")
onClicked: swipeView.incrementCurrentIndex()
enabled: swipeView.currentIndex < swipeView.count - 1
}
\endcode
\section2 Implementing Containers
Container does not provide any default visualization. It is used to implement
such containers as \l SwipeView and \l TabBar. When implementing a custom
container, the most important part of the API is \l contentModel, which provides
the contained items in a way that it can be used as an object model for item
views and repeaters.
\code
Container {
id: container
contentItem: ListView {
model: container.contentModel
snapMode: ListView.SnapOneItem
orientation: ListView.Horizontal
}
Text {
text: "Page 1"
width: container.width
height: container.height
}
Text {
text: "Page 2"
width: container.width
height: container.height
}
}
\endcode
Notice how the sizes of the page items are set by hand. This is because the
example uses a plain Container, which does not make any assumptions on the
visual layout. It is typically not necessary to specify sizes for items in
concrete Container implementations, such as \l SwipeView and \l TabBar.
\sa {Container Controls}
*/
static QQuickItem *effectiveContentItem(QQuickItem *item)
{
QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(item);
if (flickable)
return flickable->contentItem();
return item;
}
void QQuickContainerPrivate::init()
{
Q_Q(QQuickContainer);
contentModel = new QQmlObjectModel(q);
QObject::connect(contentModel, &QQmlObjectModel::countChanged, q, &QQuickContainer::countChanged);
QObject::connect(contentModel, &QQmlObjectModel::childrenChanged, q, &QQuickContainer::contentChildrenChanged);
connect(q, &QQuickControl::implicitContentWidthChanged, this, &QQuickContainerPrivate::updateContentWidth);
connect(q, &QQuickControl::implicitContentHeightChanged, this, &QQuickContainerPrivate::updateContentHeight);
setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Preferred);
}
void QQuickContainerPrivate::cleanup()
{
Q_Q(QQuickContainer);
// ensure correct destruction order (QTBUG-46798)
const int count = contentModel->count();
for (int i = 0; i < count; ++i) {
QQuickItem *item = itemAt(i);
if (item)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes);
}
if (contentItem) {
QQuickItem *focusItem = QQuickItemPrivate::get(contentItem)->subFocusItem;
if (focusItem && window)
deliveryAgentPrivate()->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason);
q->contentItemChange(nullptr, contentItem);
QQuickControlPrivate::hideOldItem(contentItem);
}
QObject::disconnect(contentModel, &QQmlObjectModel::countChanged, q, &QQuickContainer::countChanged);
QObject::disconnect(contentModel, &QQmlObjectModel::childrenChanged, q, &QQuickContainer::contentChildrenChanged);
delete contentModel;
contentModel = nullptr;
}
QQuickItem *QQuickContainerPrivate::itemAt(int index) const
{
return qobject_cast<QQuickItem *>(contentModel->get(index));
}
void QQuickContainerPrivate::insertItem(int index, QQuickItem *item)
{
Q_Q(QQuickContainer);
if (!q->isContent(item))
return;
contentData.append(item);
updatingCurrent = true;
item->setParentItem(effectiveContentItem(q->contentItem()));
maybeCullItem(item);
QQuickItemPrivate::get(item)->addItemChangeListener(this, changeTypes);
contentModel->insert(index, item);
q->itemAdded(index, item);
int count = contentModel->count();
for (int i = index + 1; i < count; ++i)
q->itemMoved(i, itemAt(i));
if (count == 1 && currentIndex == -1)
q->setCurrentIndex(index);
updatingCurrent = false;
}
void QQuickContainerPrivate::moveItem(int from, int to, QQuickItem *item)
{
Q_Q(QQuickContainer);
int oldCurrent = currentIndex;
contentModel->move(from, to);
updatingCurrent = true;
q->itemMoved(to, item);
if (from < to) {
for (int i = from; i < to; ++i)
q->itemMoved(i, itemAt(i));
} else {
for (int i = from; i > to; --i)
q->itemMoved(i, itemAt(i));
}
if (from == oldCurrent)
q->setCurrentIndex(to);
else if (from < oldCurrent && to >= oldCurrent)
q->setCurrentIndex(oldCurrent - 1);
else if (from > oldCurrent && to <= oldCurrent)
q->setCurrentIndex(oldCurrent + 1);
updatingCurrent = false;
}
void QQuickContainerPrivate::removeItem(int index, QQuickItem *item)
{
Q_Q(QQuickContainer);
const bool item_inDestructor = QQuickItemPrivate::get(item)->inDestructor;
if (!item_inDestructor && !q->isContent(item))
return;
contentData.removeOne(item);
updatingCurrent = true;
int count = contentModel->count();
bool currentChanged = false;
if (index == currentIndex && (index != 0 || count == 1)) {
q->setCurrentIndex(currentIndex - 1);
} else if (index < currentIndex) {
--currentIndex;
currentChanged = true;
}
if (!item_inDestructor) {
// already handled by ~QQuickItem
QQuickItemPrivate::get(item)->removeItemChangeListener(this, changeTypes);
item->setParentItem(nullptr);
}
contentModel->remove(index);
--count;
q->itemRemoved(index, item);
for (int i = index; i < count; ++i)
q->itemMoved(i, itemAt(i));
if (currentChanged)
emit q->currentIndexChanged();
updatingCurrent = false;
}
void QQuickContainerPrivate::reorderItems()
{
Q_Q(QQuickContainer);
if (!contentItem)
return;
// The item view eventually reparents all the items of the content model
// from the container. At this stage (during component complete), however, due
// to optimisation strategies in the item views, this doesn't happen when the
// visible area of the item view is less than the total content width of the items
// within the content model. This can cause issues while reordering. Thus, it's
// better to skip reordering the item within the content model once it's known
// that it will be reparented to the item views.
bool allowReorder = true;
if (!qobject_cast<QQuickFlickable *>(contentItem)) {
for (int index = 0; index < contentModel->count(); index++) {
if (const auto *item = qobject_cast<QQuickItem *>(contentModel->get(index))) {
const auto *parentItem = item->parentItem();
if (parentItem && !qobject_cast<QQuickItemView *>(parentItem->parentItem())) {
allowReorder = false;
break;
}
}
}
}
if (allowReorder) {
QList<QQuickItem *> siblings = effectiveContentItem(contentItem)->childItems();
int to = 0;
for (int i = 0; i < siblings.size(); ++i) {
QQuickItem* sibling = siblings.at(i);
if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner())
continue;
const int index = contentModel->indexOf(sibling, nullptr);
if (index >= 0)
q->moveItem(index, to++);
}
}
}
void QQuickContainerPrivate::maybeCullItem(QQuickItem *item)
{
if (QQuickItemPrivate::get(item)->isTransparentForPositioner())
return;
// Items like Repeater don't control the visibility of the items they create,
// so we can't expected them to uncull items added dynamically. As mentioned
// below, Repeater _does_ uncull items added to it, but unlike e.g. ListView,
// it shouldn't care if its size becomes zero and so it shouldn't manage
// the culled state of items in the same way.
if (!qobject_cast<QQuickItemView *>(contentItem))
return;
// Only cull items if the contentItem has a zero size; otherwise let the
// contentItem manage it.
const bool hasZeroSize = qFuzzyIsNull(width) && qFuzzyIsNull(height);
if (!hasZeroSize)
return;
QQuickItemPrivate::get(item)->setCulled(true);
}
void QQuickContainerPrivate::maybeCullItems()
{
if (!contentItem)
return;
const QList<QQuickItem *> childItems = effectiveContentItem(contentItem)->childItems();
for (auto &childItem : childItems)
maybeCullItem(childItem);
}
void QQuickContainerPrivate::_q_currentIndexChanged()
{
Q_Q(QQuickContainer);
if (!updatingCurrent)
q->setCurrentIndex(contentItem ? contentItem->property("currentIndex").toInt() : -1);
}
void QQuickContainerPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
{
// add dynamically reparented items (eg. by a Repeater)
if (!QQuickItemPrivate::get(child)->isTransparentForPositioner() && !contentData.contains(child))
insertItem(contentModel->count(), child);
}
void QQuickContainerPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
{
// remove dynamically unparented items (eg. by a Repeater)
if (!parent)
removeItem(contentModel->indexOf(item, nullptr), item);
}
void QQuickContainerPrivate::itemSiblingOrderChanged(QQuickItem *)
{
if (!componentComplete)
return;
// reorder the restacked items (eg. by a Repeater)
reorderItems();
}
void QQuickContainerPrivate::itemDestroyed(QQuickItem *item)
{
int index = contentModel->indexOf(item, nullptr);
if (index != -1)
removeItem(index, item);
else
QQuickControlPrivate::itemDestroyed(item);
}
void QQuickContainerPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
QQuickContainerPrivate *p = QQuickContainerPrivate::get(q);
QQuickItem *item = qobject_cast<QQuickItem *>(obj);
if (item) {
if (QQuickItemPrivate::get(item)->isTransparentForPositioner())
item->setParentItem(effectiveContentItem(q->contentItem()));
else if (p->contentModel->indexOf(item, nullptr) == -1)
q->addItem(item);
} else {
p->contentData.append(obj);
}
}
qsizetype QQuickContainerPrivate::contentData_count(QQmlListProperty<QObject> *prop)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
return QQuickContainerPrivate::get(q)->contentData.size();
}
QObject *QQuickContainerPrivate::contentData_at(QQmlListProperty<QObject> *prop, qsizetype index)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
return QQuickContainerPrivate::get(q)->contentData.value(index);
}
void QQuickContainerPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
return QQuickContainerPrivate::get(q)->contentData.clear();
}
void QQuickContainerPrivate::contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
q->addItem(item);
}
qsizetype QQuickContainerPrivate::contentChildren_count(QQmlListProperty<QQuickItem> *prop)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
return QQuickContainerPrivate::get(q)->contentModel->count();
}
QQuickItem *QQuickContainerPrivate::contentChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
return q->itemAt(index);
}
void QQuickContainerPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> *prop)
{
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
return QQuickContainerPrivate::get(q)->contentModel->clear();
}
void QQuickContainerPrivate::updateContentWidth()
{
Q_Q(QQuickContainer);
if (hasContentWidth || qFuzzyCompare(contentWidth, implicitContentWidth) || !contentModel)
return;
contentWidth = implicitContentWidth;
emit q->contentWidthChanged();
}
void QQuickContainerPrivate::updateContentHeight()
{
Q_Q(QQuickContainer);
if (hasContentHeight || qFuzzyCompare(contentHeight, implicitContentHeight) || !contentModel)
return;
contentHeight = implicitContentHeight;
emit q->contentHeightChanged();
}
QQuickContainer::QQuickContainer(QQuickItem *parent)
: QQuickControl(*(new QQuickContainerPrivate), parent)
{
Q_D(QQuickContainer);
d->init();
}
QQuickContainer::QQuickContainer(QQuickContainerPrivate &dd, QQuickItem *parent)
: QQuickControl(dd, parent)
{
Q_D(QQuickContainer);
d->init();
}
QQuickContainer::~QQuickContainer()
{
Q_D(QQuickContainer);
d->cleanup();
}
/*!
\qmlproperty int QtQuick.Controls::Container::count
\readonly
This property holds the number of items.
*/
int QQuickContainer::count() const
{
Q_D(const QQuickContainer);
return d->contentModel->count();
}
/*!
\qmlmethod Item QtQuick.Controls::Container::itemAt(int index)
Returns the item at \a index, or \c null if it does not exist.
*/
QQuickItem *QQuickContainer::itemAt(int index) const
{
Q_D(const QQuickContainer);
return d->itemAt(index);
}
/*!
\qmlmethod void QtQuick.Controls::Container::addItem(Item item)
Adds an \a item.
*/
void QQuickContainer::addItem(QQuickItem *item)
{
Q_D(QQuickContainer);
insertItem(d->contentModel->count(), item);
}
/*!
\qmlmethod void QtQuick.Controls::Container::insertItem(int index, Item item)
Inserts an \a item at \a index.
*/
void QQuickContainer::insertItem(int index, QQuickItem *item)
{
Q_D(QQuickContainer);
if (!item)
return;
const int count = d->contentModel->count();
if (index < 0 || index > count)
index = count;
int oldIndex = d->contentModel->indexOf(item, nullptr);
if (oldIndex != -1) {
if (oldIndex < index)
--index;
if (oldIndex != index)
d->moveItem(oldIndex, index, item);
} else {
d->insertItem(index, item);
}
}
/*!
\qmlmethod void QtQuick.Controls::Container::moveItem(int from, int to)
Moves an item \a from one index \a to another.
*/
void QQuickContainer::moveItem(int from, int to)
{
Q_D(QQuickContainer);
const int count = d->contentModel->count();
if (from < 0 || from > count - 1)
return;
if (to < 0 || to > count - 1)
to = count - 1;
if (from != to)
d->moveItem(from, to, d->itemAt(from));
}
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\qmlmethod void QtQuick.Controls::Container::removeItem(Item item)
Removes and destroys the specified \a item.
*/
void QQuickContainer::removeItem(QQuickItem *item)
{
Q_D(QQuickContainer);
if (!item)
return;
const int index = d->contentModel->indexOf(item, nullptr);
if (index == -1)
return;
d->removeItem(index, item);
item->deleteLater();
}
/*!
\since QtQuick.Controls 2.3 (Qt 5.10)
\qmlmethod Item QtQuick.Controls::Container::takeItem(int index)
Removes and returns the item at \a index.
\note The ownership of the item is transferred to the caller.
*/
QQuickItem *QQuickContainer::takeItem(int index)
{
Q_D(QQuickContainer);
const int count = d->contentModel->count();
if (index < 0 || index >= count)
return nullptr;
QQuickItem *item = itemAt(index);
if (item)
d->removeItem(index, item);
return item;
}
/*!
\qmlproperty model QtQuick.Controls::Container::contentModel
\readonly
This property holds the content model of items.
The content model is provided for visualization purposes. It can be assigned
as a model to a content item that presents the contents of the container.
\code
Container {
id: container
contentItem: ListView {
model: container.contentModel
}
}
\endcode
\sa contentData, contentChildren
*/
QVariant QQuickContainer::contentModel() const
{
Q_D(const QQuickContainer);
return QVariant::fromValue(d->contentModel);
}
/*!
\qmlproperty list<QtObject> QtQuick.Controls::Container::contentData
\qmldefault
This property holds the list of content data.
The list contains all objects that have been declared in QML as children
of the container, and also items that have been dynamically added or
inserted using the \l addItem() and \l insertItem() methods, respectively.
\note Unlike \c contentChildren, \c contentData does include non-visual QML
objects. It is not re-ordered when items are inserted or moved.
\sa Item::data, contentChildren
*/
QQmlListProperty<QObject> QQuickContainer::contentData()
{
Q_D(QQuickContainer);
if (!d->contentItem)
d->executeContentItem();
return QQmlListProperty<QObject>(this, nullptr,
QQuickContainerPrivate::contentData_append,
QQuickContainerPrivate::contentData_count,
QQuickContainerPrivate::contentData_at,
QQuickContainerPrivate::contentData_clear);
}
/*!
\qmlproperty list<Item> QtQuick.Controls::Container::contentChildren
This property holds the list of content children.
The list contains all items that have been declared in QML as children
of the container, and also items that have been dynamically added or
inserted using the \l addItem() and \l insertItem() methods, respectively.
\note Unlike \c contentData, \c contentChildren does not include non-visual
QML objects. It is re-ordered when items are inserted or moved.
\sa Item::children, contentData
*/
QQmlListProperty<QQuickItem> QQuickContainer::contentChildren()
{
return QQmlListProperty<QQuickItem>(this, nullptr,
QQuickContainerPrivate::contentChildren_append,
QQuickContainerPrivate::contentChildren_count,
QQuickContainerPrivate::contentChildren_at,
QQuickContainerPrivate::contentChildren_clear);
}
/*!
\qmlproperty int QtQuick.Controls::Container::currentIndex
This property holds the index of the current item.
\sa currentItem, {Managing the Current Index}
*/
int QQuickContainer::currentIndex() const
{
Q_D(const QQuickContainer);
return d->currentIndex;
}
/*!
\qmlmethod void QtQuick.Controls::Container::setCurrentIndex(int index)
Sets the current \a index of the container.
This method can be called to set a specific current index without breaking
existing \c currentIndex bindings.
\sa currentIndex, {Managing the Current Index}
*/
void QQuickContainer::setCurrentIndex(int index)
{
Q_D(QQuickContainer);
if (d->currentIndex == index)
return;
d->currentIndex = index;
emit currentIndexChanged();
emit currentItemChanged();
}
/*!
\qmlmethod void QtQuick.Controls::Container::incrementCurrentIndex()
\since QtQuick.Controls 2.1 (Qt 5.8)
Increments the current index of the container.
This method can be called to alter the current index without breaking
existing \c currentIndex bindings.
\sa currentIndex, {Managing the Current Index}
*/
void QQuickContainer::incrementCurrentIndex()
{
Q_D(QQuickContainer);
if (d->currentIndex < count() - 1)
setCurrentIndex(d->currentIndex + 1);
}
/*!
\qmlmethod void QtQuick.Controls::Container::decrementCurrentIndex()
\since QtQuick.Controls 2.1 (Qt 5.8)
Decrements the current index of the container.
This method can be called to alter the current index without breaking
existing \c currentIndex bindings.
\sa currentIndex, {Managing the Current Index}
*/
void QQuickContainer::decrementCurrentIndex()
{
Q_D(QQuickContainer);
if (d->currentIndex > 0)
setCurrentIndex(d->currentIndex - 1);
}
/*!
\qmlproperty Item QtQuick.Controls::Container::currentItem
\readonly
This property holds the current item.
\sa currentIndex
*/
QQuickItem *QQuickContainer::currentItem() const
{
Q_D(const QQuickContainer);
return itemAt(d->currentIndex);
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Container::contentWidth
This property holds the content width. It is used for calculating the total
implicit width of the container.
Unless explicitly overridden, the content width is automatically calculated
based on the implicit width of the items in the container.
\sa contentHeight
*/
qreal QQuickContainer::contentWidth() const
{
Q_D(const QQuickContainer);
return d->contentWidth;
}
void QQuickContainer::setContentWidth(qreal width)
{
Q_D(QQuickContainer);
d->hasContentWidth = true;
if (qFuzzyCompare(d->contentWidth, width))
return;
d->contentWidth = width;
d->resizeContent();
d->updateImplicitContentWidth();
emit contentWidthChanged();
}
void QQuickContainer::resetContentWidth()
{
Q_D(QQuickContainer);
if (!d->hasContentWidth)
return;
d->hasContentWidth = false;
d->updateImplicitContentWidth();
}
/*!
\since QtQuick.Controls 2.5 (Qt 5.12)
\qmlproperty real QtQuick.Controls::Container::contentHeight
This property holds the content height. It is used for calculating the total
implicit height of the container.
Unless explicitly overridden, the content height is automatically calculated
based on the implicit height of the items in the container.
\sa contentWidth
*/
qreal QQuickContainer::contentHeight() const
{
Q_D(const QQuickContainer);
return d->contentHeight;
}
void QQuickContainer::setContentHeight(qreal height)
{
Q_D(QQuickContainer);
d->hasContentHeight = true;
if (qFuzzyCompare(d->contentHeight, height))
return;
d->contentHeight = height;
d->resizeContent();
d->updateImplicitContentHeight();
emit contentHeightChanged();
}
void QQuickContainer::resetContentHeight()
{
Q_D(QQuickContainer);
if (!d->hasContentHeight)
return;
d->hasContentHeight = false;
d->updateImplicitContentHeight();
}
qreal QQuickContainerPrivate::getContentWidth() const
{
if (hasContentWidth)
return contentWidth;
return QQuickControlPrivate::getContentWidth();
}
qreal QQuickContainerPrivate::getContentHeight() const
{
if (hasContentHeight)
return contentHeight;
return QQuickControlPrivate::getContentHeight();
}
void QQuickContainer::componentComplete()
{
Q_D(QQuickContainer);
QQuickControl::componentComplete();
d->reorderItems();
d->maybeCullItems();
}
void QQuickContainer::itemChange(ItemChange change, const ItemChangeData &data)
{
Q_D(QQuickContainer);
QQuickControl::itemChange(change, data);
if (change == QQuickItem::ItemChildAddedChange && isComponentComplete() && data.item != d->background && data.item != d->contentItem) {
if (!QQuickItemPrivate::get(data.item)->isTransparentForPositioner() && d->contentModel->indexOf(data.item, nullptr) == -1)
addItem(data.item);
}
}
void QQuickContainer::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
Q_D(QQuickContainer);
QQuickControl::contentItemChange(newItem, oldItem);
static const int slotIndex = metaObject()->indexOfSlot("_q_currentIndexChanged()");
if (oldItem) {
QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
QQuickItem *oldContentItem = effectiveContentItem(oldItem);
if (oldContentItem != oldItem)
QQuickItemPrivate::get(oldContentItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
int signalIndex = oldItem->metaObject()->indexOfSignal("currentIndexChanged()");
if (signalIndex != -1)
QMetaObject::disconnect(oldItem, signalIndex, this, slotIndex);
}
if (newItem) {
QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
QQuickItem *newContentItem = effectiveContentItem(newItem);
if (newContentItem != newItem)
QQuickItemPrivate::get(newContentItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
int signalIndex = newItem->metaObject()->indexOfSignal("currentIndexChanged()");
if (signalIndex != -1)
QMetaObject::connect(newItem, signalIndex, this, slotIndex);
}
}
bool QQuickContainer::isContent(QQuickItem *item) const
{
// If the item has a QML context associated to it (it was created in QML),
// we add it to the content model. Otherwise, it's probably the default
// highlight item that is always created by the item views, which we need
// to exclude.
//
// TODO: Find a better way to identify/exclude the highlight item...
return qmlContext(item);
}
void QQuickContainer::itemAdded(int index, QQuickItem *item)
{
Q_UNUSED(index);
Q_UNUSED(item);
}
void QQuickContainer::itemMoved(int index, QQuickItem *item)
{
Q_UNUSED(index);
Q_UNUSED(item);
}
void QQuickContainer::itemRemoved(int index, QQuickItem *item)
{
Q_UNUSED(index);
Q_UNUSED(item);
}
QT_END_NAMESPACE
#include "moc_qquickcontainer_p.cpp"