Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Resetting a model can cause a crash in views with header/footer.
Geometry listeners were called for deleted header/footer.

Change-Id: I47854178232f8a4ab5e19a931901b49741fec388
Reviewed-by: Bea Lam <bea.lam@nokia.com>
  • Loading branch information
Martin Jones authored and Qt by Nokia committed Mar 19, 2012
1 parent f079f78 commit 6deb3ce
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 25 deletions.
25 changes: 17 additions & 8 deletions src/quick/items/qquickgridview.cpp
Expand Up @@ -66,13 +66,22 @@ QT_BEGIN_NAMESPACE
class FxGridItemSG : public FxViewItem
{
public:
FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own) : FxViewItem(i, own), view(v) {
FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) {
attached = static_cast<QQuickGridViewAttached*>(qmlAttachedPropertiesObject<QQuickGridView>(item));
if (attached)
static_cast<QQuickGridViewAttached*>(attached)->setView(view);
if (trackGeometry) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
}
}

~FxGridItemSG() {}
~FxGridItemSG() {
if (trackGeom) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
}
}

qreal position() const {
return rowPos();
Expand Down Expand Up @@ -423,7 +432,7 @@ FxViewItem *QQuickGridViewPrivate::newViewItem(int modelIndex, QQuickItem *item)
{
Q_Q(QQuickGridView);
Q_UNUSED(modelIndex);
return new FxGridItemSG(item, q, false);
return new FxGridItemSG(item, q, false, false);
}

void QQuickGridViewPrivate::initializeViewItem(FxViewItem *item)
Expand Down Expand Up @@ -685,7 +694,7 @@ void QQuickGridViewPrivate::createHighlight()
if (currentItem) {
QQuickItem *item = createHighlightItem();
if (item) {
FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true);
FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true, true);
if (autoHighlight)
resetHighlightPosition();
highlightXAnimator = new QSmoothedAnimation;
Expand Down Expand Up @@ -760,11 +769,11 @@ void QQuickGridViewPrivate::updateFooter()
Q_Q(QQuickGridView);
bool created = false;
if (!footer) {
QQuickItem *item = createComponentItem(footerComponent, true);
QQuickItem *item = createComponentItem(footerComponent);
if (!item)
return;
item->setZ(1);
footer = new FxGridItemSG(item, q, true);
footer = new FxGridItemSG(item, q, true, true);
created = true;
}

Expand Down Expand Up @@ -799,11 +808,11 @@ void QQuickGridViewPrivate::updateHeader()
Q_Q(QQuickGridView);
bool created = false;
if (!header) {
QQuickItem *item = createComponentItem(headerComponent, true);
QQuickItem *item = createComponentItem(headerComponent);
if (!item)
return;
item->setZ(1);
header = new FxGridItemSG(item, q, true);
header = new FxGridItemSG(item, q, true, true);
created = true;
}

Expand Down
11 changes: 4 additions & 7 deletions src/quick/items/qquickitemview.cpp
Expand Up @@ -45,11 +45,12 @@
QT_BEGIN_NAMESPACE


FxViewItem::FxViewItem(QQuickItem *i, bool own)
FxViewItem::FxViewItem(QQuickItem *i, bool own, bool trackGeometry)
: item(i)
, transitionableItem(0)
, ownItem(own)
, releaseAfterTransition(false)
, trackGeom(trackGeometry)
{
}

Expand Down Expand Up @@ -2195,10 +2196,10 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item)

QQuickItem *QQuickItemViewPrivate::createHighlightItem()
{
return createComponentItem(highlightComponent, true, true);
return createComponentItem(highlightComponent, true);
}

QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, bool receiveItemGeometryChanges, bool createDefault)
QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, bool createDefault)
{
Q_Q(QQuickItemView);

Expand All @@ -2222,10 +2223,6 @@ QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component,
if (item) {
QQml_setParent_noEvent(item, q->contentItem());
item->setParentItem(q->contentItem());
if (receiveItemGeometryChanges) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
}
}
return item;
}
Expand Down
7 changes: 5 additions & 2 deletions src/quick/items/qquickitemview_p_p.h
Expand Up @@ -60,7 +60,7 @@ QT_MODULE(Quick)
class FxViewItem
{
public:
FxViewItem(QQuickItem *, bool own);
FxViewItem(QQuickItem *, bool own, bool trackGeometry);
virtual ~FxViewItem();

qreal itemX() const;
Expand Down Expand Up @@ -92,6 +92,7 @@ class FxViewItem
int index;
bool ownItem;
bool releaseAfterTransition;
bool trackGeom;
};


Expand Down Expand Up @@ -124,6 +125,8 @@ class QQuickItemViewPrivate : public QQuickFlickablePrivate, public QQuickItemVi
QQuickItemViewPrivate();
~QQuickItemViewPrivate();

static inline QQuickItemViewPrivate *get(QQuickItemView *o) { return o->d_func(); }

struct ChangeResult {
QQmlNullableValue<qreal> visiblePos;
bool changedFirstItem;
Expand Down Expand Up @@ -191,7 +194,7 @@ class QQuickItemViewPrivate : public QQuickFlickablePrivate, public QQuickItemVi
virtual bool releaseItem(FxViewItem *item);

QQuickItem *createHighlightItem();
QQuickItem *createComponentItem(QQmlComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
QQuickItem *createComponentItem(QQmlComponent *component, bool createDefault = false);

void updateCurrent(int modelIndex);
void updateTrackedItem();
Expand Down
25 changes: 17 additions & 8 deletions src/quick/items/qquicklistview.cpp
Expand Up @@ -236,13 +236,22 @@ void QQuickViewSection::setLabelPositioning(int l)
class FxListItemSG : public FxViewItem
{
public:
FxListItemSG(QQuickItem *i, QQuickListView *v, bool own) : FxViewItem(i, own), view(v) {
FxListItemSG(QQuickItem *i, QQuickListView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) {
attached = static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(item));
if (attached)
static_cast<QQuickListViewAttached*>(attached)->setView(view);
if (trackGeometry) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
}
}

~FxListItemSG() {}
~FxListItemSG() {
if (trackGeom) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
}
}

inline QQuickItem *section() const {
return attached ? static_cast<QQuickListViewAttached*>(attached)->m_sectionItem : 0;
Expand Down Expand Up @@ -536,7 +545,7 @@ FxViewItem *QQuickListViewPrivate::newViewItem(int modelIndex, QQuickItem *item)
{
Q_Q(QQuickListView);

FxListItemSG *listItem = new FxListItemSG(item, q, false);
FxListItemSG *listItem = new FxListItemSG(item, q, false, false);
listItem->index = modelIndex;

// initialise attached properties
Expand Down Expand Up @@ -835,7 +844,7 @@ void QQuickListViewPrivate::createHighlight()
if (currentItem) {
QQuickItem *item = createHighlightItem();
if (item) {
FxListItemSG *newHighlight = new FxListItemSG(item, q, true);
FxListItemSG *newHighlight = new FxListItemSG(item, q, true, true);

if (autoHighlight) {
newHighlight->setSize(static_cast<FxListItemSG*>(currentItem)->itemSize());
Expand Down Expand Up @@ -1238,11 +1247,11 @@ void QQuickListViewPrivate::updateFooter()
Q_Q(QQuickListView);
bool created = false;
if (!footer) {
QQuickItem *item = createComponentItem(footerComponent, true);
QQuickItem *item = createComponentItem(footerComponent);
if (!item)
return;
item->setZ(1);
footer = new FxListItemSG(item, q, true);
footer = new FxListItemSG(item, q, true, true);
created = true;
}

Expand All @@ -1269,11 +1278,11 @@ void QQuickListViewPrivate::updateHeader()
Q_Q(QQuickListView);
bool created = false;
if (!header) {
QQuickItem *item = createComponentItem(headerComponent, true);
QQuickItem *item = createComponentItem(headerComponent);
if (!item)
return;
item->setZ(1);
header = new FxListItemSG(item, q, true);
header = new FxListItemSG(item, q, true, true);
created = true;
}

Expand Down
31 changes: 31 additions & 0 deletions tests/auto/quick/qquickgridview/data/headerfooter.qml
@@ -0,0 +1,31 @@
import QtQuick 2.0

GridView {
id: view
property bool horizontal: false
property bool rtl: false
width: 240
height: 320

model: testModel

flow: horizontal ? GridView.TopToBottom : GridView.LeftToRight
header: Rectangle {
objectName: "header"
width: horizontal ? 20 : view.width
height: horizontal ? view.height : 20
color: "red"
}
footer: Rectangle {
objectName: "footer"
width: horizontal ? 30 : view.width
height: horizontal ? view.height : 30
color: "blue"
}

cellWidth: 80;
cellHeight: 80;

delegate: Text { width: 80; height: 80; text: index + "(" + x + ")" }
layoutDirection: rtl ? Qt.RightToLeft : Qt.LeftToRight
}

0 comments on commit 6deb3ce

Please sign in to comment.