Fix StackView attached property

The attached properties weren't initialized at all for the initial
item. Furthermore, the properties were initialized lazily, which
made them work for imperative tests, but not correctly in bindings.

Change-Id: I783c406dcf4e1cf27a6b4e6ddd43214cb06a3c7a
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
This commit is contained in:
J-P Nurmi 2015-10-11 00:04:55 +02:00
parent 9d4c627821
commit aa634f8642
5 changed files with 75 additions and 41 deletions

View File

@ -673,6 +673,7 @@ void QQuickStackView::componentComplete()
if (d->pushElement(element)) {
emit depthChanged();
d->setCurrentItem(element->item);
element->setStatus(QQuickStackView::Active);
}
}
@ -702,39 +703,40 @@ bool QQuickStackView::childMouseEventFilter(QQuickItem *, QEvent *)
return true;
}
void QQuickStackAttachedPrivate::init()
{
QQuickItem *item = qobject_cast<QQuickItem *>(parent);
if (item) {
QQuickStackView *view = qobject_cast<QQuickStackView *>(item->parentItem());
if (view) {
element = QQuickStackViewPrivate::get(view)->findElement(item);
if (element)
initialized = true;
}
}
}
void QQuickStackAttachedPrivate::reset()
void QQuickStackAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
{
Q_Q(QQuickStackAttached);
int oldIndex = element ? element->index : -1;
QQuickStackView *oldView = element ? element->view : Q_NULLPTR;
QQuickStackView::Status oldStatus = element ? element->status : QQuickStackView::Inactive;
element = Q_NULLPTR;
QQuickStackView *newView = qobject_cast<QQuickStackView *>(parent);
element = newView ? QQuickStackViewPrivate::get(newView)->findElement(item) : Q_NULLPTR;
if (oldIndex != -1)
int newIndex = element ? element->index : -1;
QQuickStackView::Status newStatus = element ? element->status : QQuickStackView::Inactive;
if (oldIndex != newIndex)
emit q->indexChanged();
if (oldView)
if (oldView != newView)
emit q->viewChanged();
if (oldStatus != QQuickStackView::Inactive)
if (oldStatus != newStatus)
emit q->statusChanged();
}
QQuickStackAttached::QQuickStackAttached(QQuickItem *parent) :
QObject(*(new QQuickStackAttachedPrivate), parent)
{
Q_D(QQuickStackAttached);
QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Parent);
d->itemParentChanged(parent, parent->parentItem());
}
QQuickStackAttached::~QQuickStackAttached()
{
Q_D(QQuickStackAttached);
QQuickItem *parentItem = static_cast<QQuickItem *>(parent());
QQuickItemPrivate::get(parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Parent);
}
/*!
@ -745,8 +747,6 @@ QQuickStackAttached::QQuickStackAttached(QQuickItem *parent) :
int QQuickStackAttached::index() const
{
Q_D(const QQuickStackAttached);
if (!d->initialized)
const_cast<QQuickStackAttachedPrivate *>(d)->init();
return d->element ? d->element->index : -1;
}
@ -758,8 +758,6 @@ int QQuickStackAttached::index() const
QQuickStackView *QQuickStackAttached::view() const
{
Q_D(const QQuickStackAttached);
if (!d->initialized)
const_cast<QQuickStackAttachedPrivate *>(d)->init();
return d->element ? d->element->view : Q_NULLPTR;
}
@ -771,8 +769,6 @@ QQuickStackView *QQuickStackAttached::view() const
QQuickStackView::Status QQuickStackAttached::status() const
{
Q_D(const QQuickStackAttached);
if (!d->initialized)
const_cast<QQuickStackAttachedPrivate *>(d)->init();
return d->element ? d->element->status : QQuickStackView::Inactive;
}

View File

@ -48,9 +48,12 @@
QT_BEGIN_NAMESPACE
static QQuickStackAttached *attachedStackObject(QQuickItem *item)
static QQuickStackAttached *attachedStackObject(QQuickStackElement *element)
{
return qobject_cast<QQuickStackAttached *>(qmlAttachedPropertiesObject<QQuickStackView>(item, false));
QQuickStackAttached *attached = qobject_cast<QQuickStackAttached *>(qmlAttachedPropertiesObject<QQuickStackView>(element->item, false));
if (attached)
QQuickStackAttachedPrivate::get(attached)->element = element;
return attached;
}
class QQuickStackIncubator : public QQmlIncubator
@ -74,14 +77,9 @@ QQuickStackElement::QQuickStackElement() : QQuickItemViewTransitionableItem(Q_NU
QQuickStackElement::~QQuickStackElement()
{
if (item) {
if (item)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
QQuickStackAttached *attached = attachedStackObject(item);
if (attached)
QQuickStackAttachedPrivate::get(attached)->reset();
}
if (ownComponent)
delete component;
@ -91,7 +89,13 @@ QQuickStackElement::~QQuickStackElement()
item = Q_NULLPTR;
} else if (item) {
item->setVisible(false);
item->setParentItem(originalParent);
if (item->parentItem() != originalParent) {
item->setParentItem(originalParent);
} else {
QQuickStackAttached *attached = attachedStackObject(this);
if (attached)
QQuickStackAttachedPrivate::get(attached)->itemParentChanged(item, Q_NULLPTR);
}
}
delete context;
@ -182,7 +186,7 @@ void QQuickStackElement::setIndex(int value)
{
if (index != value) {
index = value;
QQuickStackAttached *attached = attachedStackObject(item);
QQuickStackAttached *attached = attachedStackObject(this);
if (attached)
emit attached->indexChanged();
}
@ -192,7 +196,7 @@ void QQuickStackElement::setView(QQuickStackView *value)
{
if (view != value) {
view = value;
QQuickStackAttached *attached = attachedStackObject(item);
QQuickStackAttached *attached = attachedStackObject(this);
if (attached)
emit attached->viewChanged();
}
@ -202,7 +206,7 @@ void QQuickStackElement::setStatus(QQuickStackView::Status value)
{
if (status != value) {
status = value;
QQuickStackAttached *attached = attachedStackObject(item);
QQuickStackAttached *attached = attachedStackObject(this);
if (attached)
emit attached->statusChanged();
}

View File

@ -157,6 +157,7 @@ class Q_LABSTEMPLATES_EXPORT QQuickStackAttached : public QObject
public:
explicit QQuickStackAttached(QQuickItem *parent = Q_NULLPTR);
~QQuickStackAttached();
int index() const;
QQuickStackView *view() const;

View File

@ -139,22 +139,20 @@ public:
QQuickItemViewTransitioner *transitioner;
};
class QQuickStackAttachedPrivate : public QObjectPrivate
class QQuickStackAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(QQuickStackAttached)
public:
QQuickStackAttachedPrivate() : initialized(false), element(Q_NULLPTR) { }
QQuickStackAttachedPrivate() : element(Q_NULLPTR) { }
static QQuickStackAttachedPrivate *get(QQuickStackAttached *attached)
{
return attached->d_func();
}
void init();
void reset();
void itemParentChanged(QQuickItem *item, QQuickItem *parent);
bool initialized;
QQuickStackElement *element;
};

View File

@ -540,4 +540,39 @@ TestCase {
control.destroy()
}
Component {
id: attachedItem
Item {
property int index: StackView.index
property StackView view: StackView.view
property int status: StackView.status
}
}
function test_attached() {
var control = stackView.createObject(testCase, {initialItem: attachedItem})
compare(control.get(0).index, 0)
compare(control.get(0).view, control)
compare(control.get(0).status, StackView.Active)
control.push(attachedItem, StackView.Immediate)
compare(control.get(0).index, 0)
compare(control.get(0).view, control)
compare(control.get(0).status, StackView.Inactive)
compare(control.get(1).index, 1)
compare(control.get(1).view, control)
compare(control.get(1).status, StackView.Active)
control.pop(StackView.Immediate)
compare(control.get(0).index, 0)
compare(control.get(0).view, control)
compare(control.get(0).status, StackView.Active)
control.destroy()
}
}