diff options
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 114 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.h | 7 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 67 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget.cpp | 14 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget_p.cpp | 51 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget_p.h | 9 | ||||
-rw-r--r-- | tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 44 | ||||
-rw-r--r-- | tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 34 | ||||
-rw-r--r-- | tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 28 |
9 files changed, 365 insertions, 3 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index f3c90ca..f110a5c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1130,6 +1130,9 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q } } + // Resolve depth. + invalidateDepthRecursively(); + if ((parent = newParent)) { if (parent->d_func()->scene && parent->d_func()->scene != scene) { // Move this item to its new parent's scene @@ -1180,8 +1183,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q } } - // Resolve depth. - invalidateDepthRecursively(); dirtySceneTransform = 1; // Restore the sub focus chain. @@ -2176,8 +2177,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); if (c) c->purge(); - if (scene) + if (scene) { +#ifndef QT_NO_GRAPHICSEFFECT + invalidateParentGraphicsEffectsRecursively(); +#endif //QT_NO_GRAPHICSEFFECT scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true); + } } // Certain properties are dropped as an item becomes invisible. @@ -5219,6 +5224,8 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) needSortChildren = 1; // ### maybe 0 child->d_ptr->siblingIndex = children.size(); children.append(child); + if (isObject) + emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged(); } /*! @@ -5241,6 +5248,8 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) // the child is not guaranteed to be at the index after the list is sorted. // (see ensureSortedChildren()). child->d_ptr->siblingIndex = -1; + if (isObject) + emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged(); } /*! @@ -7448,6 +7457,88 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture) } } +void QGraphicsItemPrivate::append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item) +{ + QGraphicsItemPrivate::get(item)->setParentItemHelper(static_cast<QGraphicsObject *>(list->object), /*newParentVariant=*/0, /*thisPointerVariant=*/0); +} + +/*! + Returns a list of this item's children. + + The items are sorted by stacking order. This takes into account both the + items' insertion order and their Z-values. + +*/ +QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList() +{ + Q_Q(QGraphicsItem); + if (isObject) { + QGraphicsObject *that = static_cast<QGraphicsObject *>(q); + return QDeclarativeListProperty<QGraphicsObject>(that, &children, QGraphicsItemPrivate::append); + } else { + //QGraphicsItem is not supported for this property + return QDeclarativeListProperty<QGraphicsObject>(); + } +} + +/*! + \internal + Returns the width of the item + Reimplemented by QGraphicsWidget +*/ +qreal QGraphicsItemPrivate::width() const +{ + return 0; +} + +/*! + \internal + Set the width of the item + Reimplemented by QGraphicsWidget +*/ +void QGraphicsItemPrivate::setWidth(qreal w) +{ + Q_UNUSED(w); +} + +/*! + \internal + Reset the width of the item + Reimplemented by QGraphicsWidget +*/ +void QGraphicsItemPrivate::resetWidth() +{ +} + +/*! + \internal + Returns the height of the item + Reimplemented by QGraphicsWidget +*/ +qreal QGraphicsItemPrivate::height() const +{ + return 0; +} + +/*! + \internal + Set the height of the item + Reimplemented by QGraphicsWidget +*/ +void QGraphicsItemPrivate::setHeight(qreal h) +{ + Q_UNUSED(h); +} + +/*! + \internal + Reset the height of the item + Reimplemented by QGraphicsWidget +*/ +void QGraphicsItemPrivate::resetHeight() +{ +} + /*! \property QGraphicsObject::parent \brief the parent of the item @@ -7634,6 +7725,23 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture) \sa scale, rotation, QGraphicsItem::transformOriginPoint() */ +/*! + \fn void QGraphicsObject::widthChanged() + \internal +*/ + +/*! + \fn void QGraphicsObject::heightChanged() + \internal +*/ + +/*! + + \fn QGraphicsObject::childrenChanged() + + This signal gets emitted whenever the children list changes + \internal +*/ /*! \class QAbstractGraphicsShapeItem diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index d72833b..5023f60 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -547,6 +547,10 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint) + Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged) + Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL) + Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL) + Q_CLASSINFO("DefaultProperty", "children") Q_INTERFACES(QGraphicsItem) public: QGraphicsObject(QGraphicsItem *parent = 0); @@ -571,6 +575,9 @@ Q_SIGNALS: void zChanged(); void rotationChanged(); void scaleChanged(); + void childrenChanged(); + void widthChanged(); + void heightChanged(); protected: QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index ea04e0b..669ae1b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -71,6 +71,62 @@ QT_BEGIN_NAMESPACE class QGraphicsItemPrivate; +#ifndef QDECLARATIVELISTPROPERTY +#define QDECLARATIVELISTPROPERTY +template<typename T> +struct QDeclarativeListProperty { + typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*); + typedef int (*CountFunction)(QDeclarativeListProperty<T> *); + typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int); + typedef void (*ClearFunction)(QDeclarativeListProperty<T> *); + + QDeclarativeListProperty() + : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {} + QDeclarativeListProperty(QObject *o, QList<T *> &list) + : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), + clear(qlist_clear), dummy1(0), dummy2(0) {} + QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0, + ClearFunction r = 0) + : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {} + + bool operator==(const QDeclarativeListProperty &o) const { + return object == o.object && + data == o.data && + append == o.append && + count == o.count && + at == o.at && + clear == o.clear; + } + + QObject *object; + void *data; + + AppendFunction append; + + CountFunction count; + AtFunction at; + + ClearFunction clear; + + void *dummy1; + void *dummy2; + +private: + static void qlist_append(QDeclarativeListProperty *p, T *v) { + ((QList<T *> *)p->data)->append(v); + } + static int qlist_count(QDeclarativeListProperty *p) { + return ((QList<T *> *)p->data)->count(); + } + static T *qlist_at(QDeclarativeListProperty *p, int idx) { + return ((QList<T *> *)p->data)->at(idx); + } + static void qlist_clear(QDeclarativeListProperty *p) { + return ((QList<T *> *)p->data)->clear(); + } +}; +#endif + class QGraphicsItemCache { public: @@ -237,6 +293,7 @@ public: void resolveDepth(); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); + QDeclarativeListProperty<QGraphicsObject> childrenList(); void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant, const QVariant *thisPointerVariant); void childrenBoundingRectHelper(QTransform *x, QRectF *rect); @@ -423,11 +480,21 @@ public: inline QTransform transformToParent() const; inline void ensureSortedChildren(); + static void append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item); static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b); void ensureSequentialSiblingIndex(); inline void sendScenePosChange(); virtual void siblingOrderChange(); + // Private Properties + virtual qreal width() const; + virtual void setWidth(qreal); + virtual void resetWidth(); + + virtual qreal height() const; + virtual void setHeight(qreal); + virtual void resetHeight(); + QRectF childrenBoundingRect; QRectF needsRepaint; QMap<QWidget *, QRect> paintedViewBoundingRects; diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index f42fe4f..a091347 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -324,6 +324,14 @@ void QGraphicsWidget::resize(const QSizeF &size) */ /*! + + \fn QGraphicsWidget::geometryChanged() + + This signal gets emitted whenever the geometry of the item changes + \internal +*/ + +/*! \property QGraphicsWidget::geometry \brief the geometry of the widget @@ -391,6 +399,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) QGraphicsSceneResizeEvent re; re.setOldSize(oldSize); re.setNewSize(newGeom.size()); + if (oldSize.width() != newGeom.size().width()) + emit widthChanged(); + if (oldSize.height() != newGeom.size().height()) + emit heightChanged(); QApplication::sendEvent(this, &re); } } @@ -2322,5 +2334,7 @@ void QGraphicsWidget::dumpFocusChain() #endif QT_END_NAMESPACE + +#include "moc_qgraphicswidget.cpp" #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 1835c74..6e397b6 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -44,6 +44,7 @@ #ifndef QT_NO_GRAPHICSVIEW #include <QtCore/qdebug.h> +#include <QtCore/qnumeric.h> #include "qgraphicswidget_p.h" #include "qgraphicslayout.h" #include "qgraphicsscene_p.h" @@ -825,6 +826,56 @@ void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l) } } +qreal QGraphicsWidgetPrivate::width() const +{ + Q_Q(const QGraphicsWidget); + return q->geometry().width(); +} + +void QGraphicsWidgetPrivate::setWidth(qreal w) +{ + if (qIsNaN(w)) + return; + Q_Q(QGraphicsWidget); + if (q->geometry().width() == w) + return; + + QRectF oldGeom = q->geometry(); + + q->setGeometry(QRectF(q->x(), q->y(), w, height())); +} + +void QGraphicsWidgetPrivate::resetWidth() +{ + Q_Q(QGraphicsWidget); + q->setGeometry(QRectF(q->x(), q->y(), 0, height())); +} + +qreal QGraphicsWidgetPrivate::height() const +{ + Q_Q(const QGraphicsWidget); + return q->geometry().height(); +} + +void QGraphicsWidgetPrivate::setHeight(qreal h) +{ + if (qIsNaN(h)) + return; + Q_Q(QGraphicsWidget); + if (q->geometry().height() == h) + return; + + QRectF oldGeom = q->geometry(); + + q->setGeometry(QRectF(q->x(), q->y(), width(), h)); +} + +void QGraphicsWidgetPrivate::resetHeight() +{ + Q_Q(QGraphicsWidget); + q->setGeometry(QRectF(q->x(), q->y(), width(), 0)); +} + QT_END_NAMESPACE #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h index 2c5b3bf..f34a755 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.h +++ b/src/gui/graphicsview/qgraphicswidget_p.h @@ -130,6 +130,15 @@ public: void windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event); bool hasDecoration() const; + // Private Properties + qreal width() const; + void setWidth(qreal); + void resetWidth(); + + qreal height() const; + void setHeight(qreal); + void resetHeight(); + // State inline int attributeToBitIndex(Qt::WidgetAttribute att) const { diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index 1007d61..49b840f 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -46,6 +46,7 @@ #include <QtGui/qgraphicsview.h> #include <QtGui/qgraphicsscene.h> #include <QtGui/qgraphicsitem.h> +#include <QtGui/qgraphicswidget.h> #include <QtGui/qstyleoption.h> #include "../../shared/util.h" @@ -73,6 +74,7 @@ private slots: void deviceCoordinateTranslateCaching(); void inheritOpacity(); void dropShadowClipping(); + void childrenVisibilityShouldInvalidateCache(); }; void tst_QGraphicsEffect::initTestCase() @@ -510,6 +512,7 @@ void tst_QGraphicsEffect::drawPixmapItem() QGraphicsView view(&scene); view.show(); QTest::qWaitForWindowShown(&view); + QTRY_VERIFY(effect->repaints >= 1); item->rotate(180); QTest::qWait(50); @@ -613,6 +616,47 @@ void tst_QGraphicsEffect::dropShadowClipping() QCOMPARE(img.pixel(x, y), img.pixel(x, y-1)); } +class MyGraphicsItem : public QGraphicsWidget +{ +public: + MyGraphicsItem(QGraphicsItem *parent = 0) : + QGraphicsWidget(parent), nbPaint(0) + {} + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + nbPaint++; + QGraphicsWidget::paint(painter, option, widget); + } + int nbPaint; +}; + +void tst_QGraphicsEffect::childrenVisibilityShouldInvalidateCache() +{ + QGraphicsScene scene; + MyGraphicsItem parent; + parent.resize(200, 200); + QGraphicsWidget child(&parent); + child.resize(200, 200); + child.setVisible(false); + scene.addItem(&parent); + QGraphicsView view(&scene); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(parent.nbPaint, 1); + //we set an effect on the parent + parent.setGraphicsEffect(new QGraphicsDropShadowEffect(&parent)); + //flush the events + QApplication::processEvents(); + //new effect applied->repaint + QCOMPARE(parent.nbPaint, 2); + child.setVisible(true); + //flush the events + QApplication::processEvents(); + //a new child appears we need to redraw the effect. + QCOMPARE(parent.nbPaint, 3); +} + QTEST_MAIN(tst_QGraphicsEffect) #include "tst_qgraphicseffect.moc" diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 4d9f23f..75fb337 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -439,6 +439,7 @@ private slots: void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2(); void QT_2653_fullUpdateDiscardingOpacityUpdate(); void QT_2649_focusScope(); + void sortItemsWhileAdding(); private: QList<QGraphicsItem *> paintedItems; @@ -10070,5 +10071,38 @@ void tst_QGraphicsItem::QT_2649_focusScope() delete scene; } +class MyGraphicsItemWithItemChange : public QGraphicsWidget +{ +public: + MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent) + {} + + QVariant itemChange(GraphicsItemChange change, const QVariant &value) + { + if (change == QGraphicsItem::ItemSceneHasChanged) { + foreach (QGraphicsView *view, scene()->views()) { + //We trigger a sort of unindexed items in the BSP + view->sceneRect(); + } + } + return QGraphicsWidget::itemChange(change, value); + } +}; + +void tst_QGraphicsItem::sortItemsWhileAdding() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + QGraphicsWidget grandGrandParent; + grandGrandParent.resize(200, 200); + scene.addItem(&grandGrandParent); + QGraphicsWidget grandParent; + grandParent.resize(200, 200); + QGraphicsWidget parent(&grandParent); + parent.resize(200, 200); + MyGraphicsItemWithItemChange item(&parent); + grandParent.setParentItem(&grandGrandParent); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 0d1ad9e..5a3a54c 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -111,6 +111,8 @@ private slots: void fontPropagationSceneChange(); void geometry_data(); void geometry(); + void width(); + void height(); void getContentsMargins_data(); void getContentsMargins(); void initStyleOption_data(); @@ -775,6 +777,32 @@ void tst_QGraphicsWidget::geometry() QCOMPARE(widget.geometry(), QRectF(pos, size)); } +void tst_QGraphicsWidget::width() +{ + QGraphicsWidget w; + QCOMPARE(w.property("width").toReal(), qreal(0)); + QSignalSpy spy(&w, SIGNAL(widthChanged())); + w.setProperty("width", qreal(50)); + QCOMPARE(w.property("width").toReal(), qreal(50)); + QCOMPARE(spy.count(), 1); + //calling old school setGeometry should work too + w.setGeometry(0, 0, 200, 200); + QCOMPARE(spy.count(), 2); +} + +void tst_QGraphicsWidget::height() +{ + QGraphicsWidget w; + QCOMPARE(w.property("height").toReal(), qreal(0)); + QSignalSpy spy(&w, SIGNAL(heightChanged())); + w.setProperty("height", qreal(50)); + QCOMPARE(w.property("height").toReal(), qreal(50)); + QCOMPARE(spy.count(), 1); + //calling old school setGeometry should work too + w.setGeometry(0, 0, 200, 200); + QCOMPARE(spy.count(), 2); +} + void tst_QGraphicsWidget::getContentsMargins_data() { QTest::addColumn<qreal>("left"); |