From a6ea9ce6990003856ecadcca8ce9ddf37949363d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 29 Jul 2009 02:26:43 +0200 Subject: Implement new transformation handling for graphics items. The idea of having separate rotationX/Y/Z, shearX/Y, etc. methods in QGraphicsItem turned out to be not giving us the flexibility we need and wanted. The new code now implements a different scheme, where we keep simple rotate (around z-axis), scale and transformOriginPoint methods, but remove the other ones. Instead we now have an additional list of QGraphicsTransform object. QGraphicsTransform is an abstract class that inherits QObject. Several specializations are provided and can be used to transform (and through property bindings animate) the item. Reviewed-By: Andreas --- demos/sub-attaq/submarine.cpp | 11 +- demos/sub-attaq/submarine.h | 4 + demos/sub-attaq/submarine_p.h | 4 +- src/gui/graphicsview/graphicsview.pri | 4 +- src/gui/graphicsview/qgraphicsitem.cpp | 339 +++++---------- src/gui/graphicsview/qgraphicsitem.h | 42 +- src/gui/graphicsview/qgraphicsitem_p.h | 39 +- src/gui/graphicsview/qgraphicstransform.cpp | 479 +++++++++++++++++++++ src/gui/graphicsview/qgraphicstransform.h | 168 ++++++++ src/gui/graphicsview/qgraphicswidget.cpp | 33 -- src/gui/graphicsview/qgraphicswidget.h | 8 - tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 158 ++----- .../auto/qgraphicstransform/qgraphicstransform.pro | 2 + .../qgraphicstransform/tst_qgraphicstransform.cpp | 162 +++++++ 14 files changed, 998 insertions(+), 455 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicstransform.cpp create mode 100644 src/gui/graphicsview/qgraphicstransform.h create mode 100644 tests/auto/qgraphicstransform/qgraphicstransform.pro create mode 100644 tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp diff --git a/demos/sub-attaq/submarine.cpp b/demos/sub-attaq/submarine.cpp index 78a9539..029e04b 100644 --- a/demos/sub-attaq/submarine.cpp +++ b/demos/sub-attaq/submarine.cpp @@ -109,7 +109,14 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * setZValue(5); setFlags(QGraphicsItem::ItemIsMovable); resize(pixmapItem->boundingRect().width(),pixmapItem->boundingRect().height()); - setTransformOrigin(boundingRect().center()); + setTransformOriginPoint(boundingRect().center()); + + graphicsRotation = new QGraphicsRotation3D(this); + graphicsRotation->setAxis(QVector3D(0, 1, 0)); + graphicsRotation->setOrigin(QPointF(size().width()/2, size().height()/2)); + QList r; + r.append(graphicsRotation); + setTransformations(r); //We setup the state machine of the submarine QStateMachine *machine = new QStateMachine(this); @@ -166,7 +173,7 @@ void SubMarine::setCurrentDirection(SubMarine::Movement direction) if (this->direction == direction) return; if (direction == SubMarine::Right && this->direction == SubMarine::None) { - setYRotation(180); + graphicsRotation->setAngle(180); } this->direction = direction; } diff --git a/demos/sub-attaq/submarine.h b/demos/sub-attaq/submarine.h index 481e816..564e9c6 100644 --- a/demos/sub-attaq/submarine.h +++ b/demos/sub-attaq/submarine.h @@ -45,6 +45,7 @@ //Qt #include #include +#include class PixmapItem; @@ -75,6 +76,8 @@ public: virtual int type() const; + QGraphicsRotation3D *rotation3d() const { return graphicsRotation; } + signals: void subMarineDestroyed(); void subMarineExecutionFinished(); @@ -87,6 +90,7 @@ private: int speed; Movement direction; PixmapItem *pixmapItem; + QGraphicsRotation3D *graphicsRotation; }; #endif //__SUBMARINE__H__ diff --git a/demos/sub-attaq/submarine_p.h b/demos/sub-attaq/submarine_p.h index e8df877..c04b25b 100644 --- a/demos/sub-attaq/submarine_p.h +++ b/demos/sub-attaq/submarine_p.h @@ -109,7 +109,7 @@ class ReturnState : public QAnimationState public: ReturnState(SubMarine *submarine, QState *parent = 0) : QAnimationState(parent) { - returnAnimation = new QPropertyAnimation(submarine, "yRotation"); + returnAnimation = new QPropertyAnimation(submarine->rotation3d(), "angle"); AnimationManager::self()->registerAnimation(returnAnimation); setAnimation(returnAnimation); this->submarine = submarine; @@ -119,7 +119,7 @@ protected: void onEntry(QEvent *e) { returnAnimation->stop(); - returnAnimation->setStartValue(submarine->yRotation()); + returnAnimation->setStartValue(submarine->rotation3d()->angle()); returnAnimation->setEndValue(submarine->currentDirection() == SubMarine::Right ? 360. : 180.); returnAnimation->setDuration(500); QAnimationState::onEntry(e); diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 0c0747e..9d232e4 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -16,12 +16,13 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicssceneindex_p.h \ graphicsview/qgraphicsscenelinearindex_p.h \ + graphicsview/qgraphicstransform.h \ + graphicsview/qgraphicstransform_p.h \ graphicsview/qgraphicsview.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ graphicsview/qgridlayoutengine_p.h - SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsitem.cpp \ graphicsview/qgraphicsitemanimation.cpp \ @@ -36,6 +37,7 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicssceneevent.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicsscenelinearindex.cpp \ + graphicsview/qgraphicstransform.cpp \ graphicsview/qgraphicsview.cpp \ graphicsview/qgraphicswidget.cpp \ graphicsview/qgraphicswidget_p.cpp \ diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 06f26a1..6770206 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1197,6 +1197,13 @@ QGraphicsItem::~QGraphicsItem() else d_ptr->setParentItemHelper(0); + if (d_ptr->transformData) { + for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) { + QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i); + static_cast(t->d_ptr)->item = 0; + delete t; + } + } delete d_ptr->transformData; delete d_ptr; @@ -2980,94 +2987,19 @@ QTransform QGraphicsItem::transform() const /*! \since 4.6 - Returns the rotation around the X axis. - - The default is 0 - - \warning The value doesn't take in account any rotation set with - the setTransform() method. - - \sa setXRotation(), {Transformations} -*/ -qreal QGraphicsItem::xRotation() const -{ - if (!d_ptr->transformData) - return 0; - return d_ptr->transformData->xRotation; -} - -/*! - \since 4.6 - - Sets the rotation around the X axis to \a angle degrees. - - \warning The value doesn't take in account any rotation set with the setTransform() method. - - \sa xRotation(), setTransformOrigin(), {Transformations} -*/ -void QGraphicsItem::setXRotation(qreal angle) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->xRotation = angle; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; -} - -/*! - \since 4.6 - - Returns the rotation around the Y axis. - - The default is 0 - - \warning The value doesn't take in account any rotation set with the setTransform() method. - - \sa setYRotation(), {Transformations} -*/ -qreal QGraphicsItem::yRotation() const -{ - if (!d_ptr->transformData) - return 0; - return d_ptr->transformData->yRotation; -} - -/*! - \since 4.6 - - Sets the rotation around the Y axis to \a angle degrees. - - \warning The value doesn't take in account any rotation set with the setTransform() method. - - \sa yRotation(), setTransformOrigin() {Transformations} -*/ -void QGraphicsItem::setYRotation(qreal angle) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->yRotation = angle; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; -} - -/*! - \since 4.6 - Returns the rotation around the Z axis. The default is 0 \warning The value doesn't take in account any rotation set with the setTransform() method. - \sa setZRotation(), {Transformations} + \sa setRotation(), {Transformations} */ -qreal QGraphicsItem::zRotation() const +qreal QGraphicsItem::rotation() const { if (!d_ptr->transformData) return 0; - return d_ptr->transformData->zRotation; + return d_ptr->transformData->rotation; } /*! @@ -3077,224 +3009,107 @@ qreal QGraphicsItem::zRotation() const \warning The value doesn't take in account any rotation set with the setTransform() method. - \sa zRotation(), setTransformOrigin(), {Transformations} + \sa rotation(), setTransformOriginPoint(), {Transformations} */ -void QGraphicsItem::setZRotation(qreal angle) +void QGraphicsItem::setRotation(qreal angle) { prepareGeometryChange(); if (!d_ptr->transformData) d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->zRotation = angle; + d_ptr->transformData->rotation = angle; d_ptr->transformData->onlyTransform = false; d_ptr->dirtySceneTransform = 1; -} - -/*! - \since 4.6 - This convenience function set the rotation angles around the 3 axes - to \a x, \a y and \a z. - - \sa setXRotation(), setYRotation(), setZRotation(), {Transformations} -*/ -void QGraphicsItem::setRotation(qreal x, qreal y, qreal z) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->xRotation = x; - d_ptr->transformData->yRotation = y; - d_ptr->transformData->zRotation = z; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; + if (d_ptr->isObject) + emit static_cast(this)->rotationChanged(); } /*! \since 4.6 - Returns the scale factor on the X axis. + Returns the scale factor of the item. The default is 1 \warning The value doesn't take in account any scaling set with the setTransform() method. - \sa setXScale(), {Transformations} + \sa setScale(), {Transformations} */ -qreal QGraphicsItem::xScale() const +qreal QGraphicsItem::scale() const { if (!d_ptr->transformData) - return 1; - return d_ptr->transformData->xScale; + return 1.; + return d_ptr->transformData->scale; } /*! \since 4.6 - Sets the scale factor on the X axis to \a factor. + Sets the scale factor of the item to \a factor. \warning The value doesn't take in account any scaling set with the setTransform() method. - \sa xScale(), setTransformOrigin(), {Transformations} + \sa scale(), setTransformOriginPoint(), {Transformations} */ -void QGraphicsItem::setXScale(qreal factor) +void QGraphicsItem::setScale(qreal factor) { prepareGeometryChange(); if (!d_ptr->transformData) d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->xScale = factor; + d_ptr->transformData->scale = factor; d_ptr->transformData->onlyTransform = false; d_ptr->dirtySceneTransform = 1; -} - -/*! - \since 4.6 - - Returns the scale factor on the Y axis. - - The default is 1 - - \warning The value doesn't take in account any scaling set with the setTransform() method. - - \sa setYScale(), {Transformations} -*/ -qreal QGraphicsItem::yScale() const -{ - if (!d_ptr->transformData) - return 1; - return d_ptr->transformData->yScale; -} - -/*! - \since 4.6 - - Sets the scale factor on the Y axis to \a factor. - \warning The value doesn't take in account any scaling set with the setTransform() method. - - \sa yScale(), setTransformOrigin(), {Transformations} -*/ -void QGraphicsItem::setYScale(qreal factor) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->yScale = factor; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; + if (d_ptr->isObject) + emit static_cast(this)->scaleChanged(); } -/*! - \since 4.6 - - This convenience function set the scaling factors on X and Y axis to \a sx and \a sy. - - \warning The value doesn't take in account any scaling set with the setTransform() method. - - \sa setXScale(), setYScale(), {Transformations} -*/ -void QGraphicsItem::setScale(qreal sx, qreal sy) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->xScale = sx; - d_ptr->transformData->yScale = sy; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; -} /*! \since 4.6 - Returns the horizontal shear. - - The default is 0 - - \warning The value doesn't take in account any shearing set with the setTransform() method. + returns list of graphics transformations on the item. - \sa setHorizontalShear(), {Transformations} + \sa scale(), setTransformOriginPoint(), {Transformations} */ -qreal QGraphicsItem::horizontalShear() const +QList QGraphicsItem::transformations() const { if (!d_ptr->transformData) - return 0; - return d_ptr->transformData->horizontalShear; + return QList(); + return d_ptr->transformData->graphicsTransforms; } /*! \since 4.6 - Sets the horizontal shear to \a shear. - - \warning The value doesn't take in account any shearing set with the setTransform() method. + Sets a list of graphics transformations on the item to \a transformations. - \sa horizontalShear(), {Transformations} + \sa scale(), setTransformOriginPoint(), {Transformations} */ -void QGraphicsItem::setHorizontalShear(qreal shear) +void QGraphicsItem::setTransformations(const QList &transformations) { prepareGeometryChange(); if (!d_ptr->transformData) d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->horizontalShear = shear; + d_ptr->transformData->graphicsTransforms = transformations; + for (int i = 0; i < transformations.size(); ++i) + transformations.at(i)->d_func()->setItem(this); d_ptr->transformData->onlyTransform = false; d_ptr->dirtySceneTransform = 1; } -/*! - \since 4.6 - - Returns the vertical shear. - - The default is 0 - - \warning The value doesn't take in account any shearing set with the setTransform() method. - \sa setHorizontalShear(), {Transformations} -*/ -qreal QGraphicsItem::verticalShear() const +void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t) { - if (!d_ptr->transformData) - return 0; - return d_ptr->transformData->verticalShear; -} + if (!transformData) + transformData = new QGraphicsItemPrivate::TransformData; + if (!transformData->graphicsTransforms.contains(t)) + transformData->graphicsTransforms.append(t); -/*! - \since 4.6 - - Sets the vertical shear to \a shear. - - \warning The value doesn't take in account any shearing set with the setTransform() method. - - \sa verticalShear(), {Transformations} -*/ -void QGraphicsItem::setVerticalShear(qreal shear) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->verticalShear = shear; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; -} - -/*! - \since 4.6 - - This convenience function sets the horizontal shear to \a sh and the vertical shear to \a sv. - - \warning The value doesn't take in account any shearing set with the setTransform() method. - - \sa setHorizontalShear(), setVerticalShear() -*/ -void QGraphicsItem::setShear(qreal sh, qreal sv) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->horizontalShear = sh; - d_ptr->transformData->verticalShear = sv; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; + Q_Q(QGraphicsItem); + t->d_func()->setItem(q); + transformData->onlyTransform = false; + dirtySceneTransform = 1; } /*! @@ -3304,9 +3119,9 @@ void QGraphicsItem::setShear(qreal sh, qreal sv) The default is QPointF(0,0). - \sa setTransformOrigin(), {Transformations} + \sa setTransformOriginPoint(), {Transformations} */ -QPointF QGraphicsItem::transformOrigin() const +QPointF QGraphicsItem::transformOriginPoint() const { if (!d_ptr->transformData) return QPointF(0,0); @@ -3318,9 +3133,9 @@ QPointF QGraphicsItem::transformOrigin() const Sets the \a origin point for the transformation in item coordinates. - \sa transformOrigin(), {Transformations} + \sa transformOriginPoint(), {Transformations} */ -void QGraphicsItem::setTransformOrigin(const QPointF &origin) +void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) { prepareGeometryChange(); if (!d_ptr->transformData) @@ -3332,15 +3147,15 @@ void QGraphicsItem::setTransformOrigin(const QPointF &origin) } /*! - \fn void QGraphicsItem::setTransformOrigin(qreal x, qreal y) + \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y) \since 4.6 \overload Sets the origin point for the transformation in item coordinates. - This is equivalent to calling setTransformOrigin(QPointF(\a x, \a y)). + This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)). - \sa setTransformOrigin(), {Transformations} + \sa setTransformOriginPoint(), {Transformations} */ @@ -3619,7 +3434,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) \warning using this function doesnt affect the value of the transformation properties - \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin(), {The Graphics View Coordinate System}, {Transformations} + \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations} */ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) { @@ -3733,7 +3548,7 @@ void QGraphicsItem::shear(qreal sh, qreal sv) /*! \obsolete - Use setPos() or setTransformOrigin() instead. + Use setPos() or setTransformOriginPoint() instead. Translates the current item transformation by (\a dx, \a dy). @@ -6857,6 +6672,41 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent \sa pos() */ +/*! + \property QGraphicsObject::rotation + This property holds the rotation of the item in degrees. + + This specifies how many degrees to rotate the item around its transformOrigin. + The default rotation is 0 degrees (i.e. not rotated at all). +*/ + +/*! + \fn QGraphicsObject::rotationChanged() + + This signal gets emitted whenever the roation of the item changes. +*/ + +/*! + \property QGraphicsObject::scale + This property holds the scale of the item. + + A scale of less than 1 means the item will be displayed smaller than + normal, and a scale of greater than 1 means the item will be + displayed larger than normal. A negative scale means the item will + be mirrored. + + By default, items are displayed at a scale of 1 (i.e. at their + normal size). + + Scaling is from the item's transformOrigin. +*/ + +/*! + \fn void QGraphicsObject::scaleChanged() + + This signal is emitted when the scale of the item changes. +*/ + /*! \property QGraphicsObject::enabled @@ -6896,6 +6746,15 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent \sa visible */ +/*! + \property QGraphicsObject::transformOriginPoint + \brief the transformation origin + + This property sets a specific point in the items coordiante system as the + origin for scale and rotation. + + \sa scale, rotation, QGraphicsItem::transformOriginPoint() +*/ /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 0e21a47..945163f 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -71,6 +71,7 @@ class QGraphicsSceneHoverEvent; class QGraphicsSceneMouseEvent; class QGraphicsSceneWheelEvent; class QGraphicsScene; +class QGraphicsTransform; class QGraphicsWidget; class QInputMethodEvent; class QKeyEvent; @@ -268,34 +269,19 @@ public: void shear(qreal sh, qreal sv); // ### obsolete void translate(qreal dx, qreal dy); // ### obsolete - qreal xRotation() const; - void setXRotation(qreal angle); + void setRotation(qreal angle); + qreal rotation() const; - qreal yRotation() const; - void setYRotation(qreal angle); + void setScale(qreal scale); + qreal scale() const; - qreal zRotation() const; - void setZRotation(qreal angle); - void setRotation(qreal x, qreal y, qreal z); + QList transformations() const; + void setTransformations(const QList &transformations); - qreal xScale() const; - void setXScale(qreal factor); - - qreal yScale() const; - void setYScale(qreal factor); - void setScale(qreal sx, qreal sy); - - qreal horizontalShear() const; - void setHorizontalShear(qreal shear); - - qreal verticalShear() const; - void setVerticalShear(qreal shear); - void setShear(qreal sh, qreal sv); - - QPointF transformOrigin() const; - void setTransformOrigin(const QPointF &origin); - inline void setTransformOrigin(qreal x, qreal y) - { setTransformOrigin(QPointF(x,y)); } + QPointF transformOriginPoint() const; + void setTransformOriginPoint(const QPointF &origin); + inline void setTransformOriginPoint(qreal x, qreal y) + { setTransformOriginPoint(QPointF(x,y)); } virtual void advance(int phase); @@ -456,6 +442,7 @@ private: friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; friend class QGraphicsSceneBspTreeIndexPrivate; + friend class QGraphicsTransformPrivate; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); @@ -521,6 +508,9 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged) Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged) Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged) + 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) public: QGraphicsObject(QGraphicsItem *parent = 0); @@ -532,6 +522,8 @@ Q_SIGNALS: void xChanged(); void yChanged(); void zChanged(); + void rotationChanged(); + void scaleChanged(); 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 c208b99..b8d98c1 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -57,6 +57,8 @@ #include "qset.h" #include "qpixmapcache.h" #include "qgraphicsview_p.h" +#include "qgraphicstransform.h" +#include "qgraphicstransform_p.h" #include @@ -192,7 +194,7 @@ public: void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; - void updateSceneTransformFromParent(); + virtual void updateSceneTransformFromParent(); // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; @@ -200,6 +202,7 @@ public: void setPosHelper(const QPointF &pos); void setTransformHelper(const QTransform &transform); + void appendGraphicsTransform(QGraphicsTransform *t); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, @@ -467,45 +470,35 @@ public: struct QGraphicsItemPrivate::TransformData { QTransform transform; - qreal xScale; - qreal yScale; - qreal xRotation; - qreal yRotation; - qreal zRotation; - qreal horizontalShear; - qreal verticalShear; + qreal scale; + qreal rotation; qreal xOrigin; qreal yOrigin; + QList graphicsTransforms; bool onlyTransform; TransformData() : - xScale(1.0), yScale(1.0), xRotation(0.0), yRotation(0.0), zRotation(0.0), - horizontalShear(0.0), verticalShear(0.0), xOrigin(0.0), yOrigin(0.0), + scale(1.0), rotation(0.0), + xOrigin(0.0), yOrigin(0.0), onlyTransform(true) {} QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const { if (onlyTransform) { - if (!postmultiplyTransform) - return transform; - if (postmultiplyTransform->isIdentity()) + if (!postmultiplyTransform || postmultiplyTransform->isIdentity()) return transform; if (transform.isIdentity()) return *postmultiplyTransform; - QTransform x(transform); - x *= *postmultiplyTransform; - return x; + return transform * *postmultiplyTransform; } QTransform x(transform); - if (xOrigin != 0 || yOrigin != 0) - x *= QTransform::fromTranslate(xOrigin, yOrigin); - x.rotate(xRotation, Qt::XAxis); - x.rotate(yRotation, Qt::YAxis); - x.rotate(zRotation, Qt::ZAxis); - x.shear(horizontalShear, verticalShear); - x.scale(xScale, yScale); + for (int i = 0; i < graphicsTransforms.size(); ++i) + graphicsTransforms.at(i)->applyTo(&x); + x.translate(xOrigin, yOrigin); + x.rotate(rotation, Qt::ZAxis); + x.scale(scale, scale); x.translate(-xOrigin, -yOrigin); if (postmultiplyTransform) x *= *postmultiplyTransform; diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp new file mode 100644 index 0000000..f18752a --- /dev/null +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -0,0 +1,479 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicstransform.h" +#include "qgraphicsitem_p.h" +#include "qgraphicstransform_p.h" +#include + +#include +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +QT_BEGIN_NAMESPACE + + +void QGraphicsTransformPrivate::setItem(QGraphicsItem *i) +{ + if (item == i) + return; + + if (item) { + Q_Q(QGraphicsTransform); + QGraphicsItemPrivate *d_ptr = item->d_ptr; + + item->prepareGeometryChange(); + Q_ASSERT(d_ptr->transformData); + d_ptr->transformData->graphicsTransforms.remove(q); + d_ptr->dirtySceneTransform = 1; + item = 0; + } + + item = i; +} + +void QGraphicsTransformPrivate::updateItem(QGraphicsItem *item) +{ + item->prepareGeometryChange(); + item->d_ptr->dirtySceneTransform = 1; +} + +void QGraphicsTransform::update() +{ + Q_D(QGraphicsTransform); + if (d->item) + d->updateItem(d->item); +} + +/*! + returns this object as a QTransform. +*/ +QTransform QGraphicsTransform::transform() const +{ + QTransform t; + applyTo(&t); + return t; +} + +/*! + \class QGraphicsTransform + \brief The QGraphicsTransform class is an abstract base class for tranformations on QGraphicsItems. + \since 4.6 + + The classes that inherit QGraphicsTransform express different types of transformations + that can be applied to graphics items. + + A list of these transformations can be applied to any graphics item. These + transformations are then easily modifyable and usable from e.g. within animations. + + QGraphicsTransform is an abstract base class that is implemented by QGraphicsScale, + QGraphicsRotation and QGraphicsRotation3D. Subclasses have to implement the applyTo method. + + \sa QGraphicsItem::transform(), QGraphicsScale, QGraphicsRotation, QGraphicsRotation3D +*/ + +/*! + Constructs a new QGraphicsTransform with \a parent. +*/ +QGraphicsTransform::QGraphicsTransform(QObject *parent) : + QObject(*new QGraphicsTransformPrivate, parent) +{ +} + +/*! + Destructs the graphics transform. +*/ +QGraphicsTransform::~QGraphicsTransform() +{ + Q_D(QGraphicsTransform); + d->setItem(0); +} + +/*! + \internal +*/ +QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent) + : QObject(p, parent) +{ +} + +/*! \fn void QGraphicsTransform::applyTo(QTransform *transform) const + + This pure virtual method has to be reimplemented in derived classes. + + It applies this transformation to \a transform. +*/ + + +/*! + \class QGraphicsScale + \brief The QGraphicsScale class provides a way to scale a graphics item in 2 dimensions. + \since 4.6 + + QGraphicsScale contains an \a origin around which the scaling happens, and two + scale factors, xScale and yScale, the x and one for the y axis. +*/ + +class QGraphicsScalePrivate : public QGraphicsTransformPrivate +{ +public: + QGraphicsScalePrivate() + : xScale(1), yScale(1) {} + QPointF origin; + qreal xScale; + qreal yScale; +}; + +/*! + Constructs a new graphics scale object with \a parent. +*/ +QGraphicsScale::QGraphicsScale(QObject *parent) + : QGraphicsTransform(*new QGraphicsScalePrivate, parent) +{ +} + +/*! + Destroys the object +*/ +QGraphicsScale::~QGraphicsScale() +{ +} + +/*! + \property QGraphicsScale::origin + The origin of the scale. All scaling will be done relative to this point. + + The \a origin is in other words the fixed point for the transformation. +*/ +QPointF QGraphicsScale::origin() const +{ + Q_D(const QGraphicsScale); + return d->origin; +} + +void QGraphicsScale::setOrigin(const QPointF &point) +{ + Q_D(QGraphicsScale); + d->origin = point; + update(); + emit originChanged(); +} + +/*! + \fn QGraphicsScale::originChanged() + + This signal is emitted whenever the origin of the object + changes. +*/ + +/*! + \property QGraphicsScale::xScale + + The scale factor in x direction. The x direction is + in the graphics items logical coordinates. + + \sa yScale +*/ +qreal QGraphicsScale::xScale() const +{ + Q_D(const QGraphicsScale); + return d->xScale; +} + +void QGraphicsScale::setXScale(qreal scale) +{ + Q_D(QGraphicsScale); + if (d->xScale == scale) + return; + d->xScale = scale; + update(); + emit scaleChanged(); +} + +/*! + \property QGraphicsScale::yScale + + The scale factor in y direction. The y direction is + in the graphics items logical coordinates. + + \sa xScale +*/ +qreal QGraphicsScale::yScale() const +{ + Q_D(const QGraphicsScale); + return d->yScale; +} + +void QGraphicsScale::setYScale(qreal scale) +{ + Q_D(QGraphicsScale); + if (d->yScale == scale) + return; + d->yScale = scale; + update(); + emit scaleChanged(); +} + +/*! + \fn QGraphicsScale::scaleChanged() + + This signal is emitted whenever the xScale or yScale of the object + changes. +*/ + +/*! + \reimp +*/ +void QGraphicsScale::applyTo(QTransform *transform) const +{ + Q_D(const QGraphicsScale); + transform->translate(d->origin.x(), d->origin.y()); + transform->scale(d->xScale, d->yScale); + transform->translate(-d->origin.x(), -d->origin.y()); +} + +/*! + \class QGraphicsRotation + \brief The QGraphicsRotation class provides a way to rotate a graphics item in 2 dimensions. + \since 4.6 + + QGraphicsRotation contains an \a origin around which the rotation happens, and one + angle in degrees describing the amount of the rotation. +*/ + +class QGraphicsRotationPrivate : public QGraphicsTransformPrivate +{ +public: + QGraphicsRotationPrivate() + : angle(0) {} + QPointF origin; + qreal originY; + qreal angle; +}; + +/*! + Constructs a new graphics rotation with \a parent. +*/ +QGraphicsRotation::QGraphicsRotation(QObject *parent) + : QGraphicsTransform(*new QGraphicsRotationPrivate, parent) +{ +} + +/*! + \internal +*/ +QGraphicsRotation::QGraphicsRotation(QGraphicsRotationPrivate &p, QObject *parent) + : QGraphicsTransform(p, parent) +{ +} + +/*! + Destructs the object +*/ +QGraphicsRotation::~QGraphicsRotation() +{ +} + +/*! + \property QGraphicsRotation::origin + The origin around which this object will rotate the graphics item. + + The \a origin is in other words the fixed point for the transformation. +*/ +QPointF QGraphicsRotation::origin() const +{ + Q_D(const QGraphicsRotation); + return d->origin; +} + +void QGraphicsRotation::setOrigin(const QPointF &point) +{ + Q_D(QGraphicsRotation); + d->origin = point; + update(); + emit originChanged(); +} + +/*! + \fn QGraphicsRotation::originChanged() + + This signal is emitted whenever the origin of the object + changes. +*/ + +/*! + \property QGraphicsRotation::angle + The angle, in degrees, of the rotation. +*/ +qreal QGraphicsRotation::angle() const +{ + Q_D(const QGraphicsRotation); + return d->angle; +} + +void QGraphicsRotation::setAngle(qreal angle) +{ + Q_D(QGraphicsRotation); + if (d->angle == angle) + return; + d->angle = angle; + update(); + emit angleChanged(); +} + +/*! + \fn void QGraphicsRotation::angleChanged() + + This signal is emitted whenever the angle of the object + changes. +*/ + +/*! + \reimp +*/ +void QGraphicsRotation::applyTo(QTransform *t) const +{ + Q_D(const QGraphicsRotation); + if(d->angle) { + t->translate(d->origin.x(), d->origin.y()); + t->rotate(d->angle); + t->translate(-d->origin.x(), -d->origin.y()); + } +} + + +/*! + \class QGraphicsRotation3D + \brief The QGraphicsRotation3D class provides a way to rotate a graphics item in 3 dimensions. + \since 4.6 + + In addition to the origin and angle of a simple QGraphicsRotation, QGraphicsRotation3D contains + also an axis that describes around which axis in space the rotation is supposed to happen. +*/ + +class QGraphicsRotation3DPrivate : public QGraphicsRotationPrivate +{ +public: + QGraphicsRotation3DPrivate() {} + + QVector3D axis; +}; + +/*! + Constructs a new 3D rotation with \a parent. +*/ +QGraphicsRotation3D::QGraphicsRotation3D(QObject *parent) + : QGraphicsRotation(*new QGraphicsRotation3DPrivate, parent) +{ +} + +/*! + Destroys the object +*/ +QGraphicsRotation3D::~QGraphicsRotation3D() +{ +} + +/*! + \property QGraphicsRotation3D::axis + + A rotation axis is specified by a vector in 3D space. +*/ +QVector3D QGraphicsRotation3D::axis() +{ + Q_D(QGraphicsRotation3D); + return d->axis; +} + +void QGraphicsRotation3D::setAxis(const QVector3D &axis) +{ + Q_D(QGraphicsRotation3D); + d->axis = axis; + update(); +} + +/*! + \fn void QGraphicsRotation3D::axisChanged() + + This signal is emitted whenever the axis of the object + changes. +*/ + +const qreal inv_dist_to_plane = 1. / 1024.; + +/*! + \reimp +*/ +void QGraphicsRotation3D::applyTo(QTransform *t) const +{ + Q_D(const QGraphicsRotation3D); + + if (d->angle == 0. || + (d->axis.z() == 0. && d->axis.y() == 0 && d->axis.x() == 0)) + return; + + qreal rad = d->angle * 2. * M_PI / 360.; + qreal c = ::cos(rad); + qreal s = ::sin(rad); + + qreal x = d->axis.x(); + qreal y = d->axis.y(); + qreal z = d->axis.z(); + + qreal len = x * x + y * y + z * z; + if (len != 1.) { + len = 1./::sqrt(len); + x *= len; + y *= len; + z *= len; + } + + t->translate(d->origin.x(), d->origin.y()); + *t = QTransform(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane, + y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane, + 0, 0, 1) * *t; + t->translate(-d->origin.x(), -d->origin.y()); +} + +#include "moc_qgraphicstransform.cpp" + +QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h new file mode 100644 index 0000000..adf9438 --- /dev/null +++ b/src/gui/graphicsview/qgraphicstransform.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSTRANSFORM_H +#define QGRAPHICSTRANSFORM_H + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGraphicsItem; +class QGraphicsTransformPrivate; + +class Q_GUI_EXPORT QGraphicsTransform : public QObject +{ + Q_OBJECT +public: + QGraphicsTransform(QObject *parent = 0); + ~QGraphicsTransform(); + + QTransform transform() const; + virtual void applyTo(QTransform *transform) const = 0; + +protected slots: + void update(); + +protected: + QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent); +private: + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + Q_DECLARE_PRIVATE(QGraphicsTransform) +}; + +class QGraphicsScalePrivate; + +class Q_GUI_EXPORT QGraphicsScale : public QGraphicsTransform +{ + Q_OBJECT + + Q_PROPERTY(QPointF origin READ origin WRITE setOrigin NOTIFY originChanged) + Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY scaleChanged) + Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY scaleChanged) +public: + QGraphicsScale(QObject *parent = 0); + ~QGraphicsScale(); + + QPointF origin() const; + void setOrigin(const QPointF &point); + + qreal xScale() const; + void setXScale(qreal); + + qreal yScale() const; + void setYScale(qreal); + + void applyTo(QTransform *transform) const; + +Q_SIGNALS: + void originChanged(); + void scaleChanged(); + +private: + Q_DECLARE_PRIVATE(QGraphicsScale) +}; + +class QGraphicsRotationPrivate; + +class Q_GUI_EXPORT QGraphicsRotation : public QGraphicsTransform +{ + Q_OBJECT + + Q_PROPERTY(QPointF origin READ origin WRITE setOrigin NOTIFY originChanged) + Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) +public: + QGraphicsRotation(QObject *parent = 0); + ~QGraphicsRotation(); + + QPointF origin() const; + void setOrigin(const QPointF &point); + + qreal angle() const; + void setAngle(qreal); + + void applyTo(QTransform *transform) const; + +Q_SIGNALS: + void originChanged(); + void angleChanged(); + +protected: + QGraphicsRotation(QGraphicsRotationPrivate &p, QObject *parent); +private: + Q_DECLARE_PRIVATE(QGraphicsRotation) +}; + +class QGraphicsRotation3DPrivate; + +class Q_GUI_EXPORT QGraphicsRotation3D : public QGraphicsRotation +{ + Q_OBJECT + + Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged) +public: + QGraphicsRotation3D(QObject *parent = 0); + ~QGraphicsRotation3D(); + + QVector3D axis(); + void setAxis(const QVector3D &axis); + + void applyTo(QTransform *transform) const; + +Q_SIGNALS: + void axisChanged(); + +private: + Q_DECLARE_PRIVATE(QGraphicsRotation3D) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFXTRANSFORM_H diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 6f56b84..3ea80ce 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -1728,39 +1728,6 @@ QGraphicsWidget *QGraphicsWidget::focusWidget() const return 0; } -/*! \property QGraphicsWidget::horizontalShear - \brief This property holds the horizontal shear value for the item. - */ - -/*! \property QGraphicsWidget::transformOrigin - \brief This property holds the origin point used for transformations - in item coordinates. - */ - -/*! \property QGraphicsWidget::verticalShear - \brief This property holds the vertical shear value for the item. - */ - -/*! \property QGraphicsWidget::xRotation - \brief This property holds the value for rotation around the x axis. - */ - -/*! \property QGraphicsWidget::xScale - \brief This property holds the scale factor for the x axis. - */ - -/*! \property QGraphicsWidget::yRotation - \brief This property holds the value for rotation around the y axis. - */ - -/*! \property QGraphicsWidget::yScale - \brief This property holds the scale factor for the y axis. - */ - -/*! \property QGraphicsWidget::zRotation - \brief This property holds the value for rotation around the z axis. - */ - #ifndef QT_NO_SHORTCUT /*! \since 4.5 diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index b72ec9f..d03a637 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -77,14 +77,6 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) - Q_PROPERTY(QPointF transformOrigin READ transformOrigin WRITE setTransformOrigin) - Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation) - Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation) - Q_PROPERTY(qreal zRotation READ zRotation WRITE setZRotation) - Q_PROPERTY(qreal xScale READ xScale WRITE setXScale) - Q_PROPERTY(qreal yScale READ yScale WRITE setYScale) - Q_PROPERTY(qreal horizontalShear READ horizontalShear WRITE setHorizontalShear) - Q_PROPERTY(qreal verticalShear READ verticalShear WRITE setVerticalShear) public: QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); ~QGraphicsWidget(); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 9f1693d..7f6f322 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -6884,44 +6885,21 @@ void tst_QGraphicsItem::update() void tst_QGraphicsItem::setTransformProperties_data() { QTest::addColumn("origin"); - QTest::addColumn("rotationX"); - QTest::addColumn("rotationY"); - QTest::addColumn("rotationZ"); - QTest::addColumn("scaleX"); - QTest::addColumn("scaleY"); - QTest::addColumn("shearX"); - QTest::addColumn("shearY"); + QTest::addColumn("rotation"); + QTest::addColumn("scale"); - QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0); - QTest::newRow("rotationZ") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(42.2) - << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0); - QTest::newRow("rotationXY") << QPointF() << qreal(12.5) << qreal(53.6) << qreal(0.0) - << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2)) + << qreal(-2578.2) + << qreal(1.0); - QTest::newRow("rotationXYZ") << QPointF() << qreal(-25) << qreal(12) << qreal(556) - << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); + QTest::newRow("Scale") << QPointF() << qreal(0.0) + << qreal(6); - QTest::newRow("rotationXYZ dicentred") << QPointF(-53, 25.2) - << qreal(-2578.2) << qreal(4565.2) << qreal(56) - << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0); - - QTest::newRow("Scale") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(6) << qreal(0.5) << qreal(0.0) << qreal(0.0); - - QTest::newRow("Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(1.0) << qreal(1.0) << qreal(2.2) << qreal(0.5); - - QTest::newRow("Scale and Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0) - << qreal(5.2) << qreal(2.1) << qreal(5.2) << qreal(5.5); - - QTest::newRow("Everything") << QPointF() << qreal(41) << qreal(-23) << qreal(0.56) - << qreal(8.2) << qreal(-0.2) << qreal(-12) << qreal(-0.8); - - QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196) << qreal(-1260) - << qreal(4) << qreal(2) << qreal(2.56) << qreal(0.8); + QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196); } /** @@ -6932,92 +6910,61 @@ void tst_QGraphicsItem::setTransformProperties_data() void tst_QGraphicsItem::setTransformProperties() { QFETCH(QPointF,origin); - QFETCH(qreal,rotationX); - QFETCH(qreal,rotationY); - QFETCH(qreal,rotationZ); - QFETCH(qreal,scaleX); - QFETCH(qreal,scaleY); - QFETCH(qreal,shearX); - QFETCH(qreal,shearY); + QFETCH(qreal,rotation); + QFETCH(qreal,scale); QTransform result; result.translate(origin.x(), origin.y()); - result.rotate(rotationX, Qt::XAxis); - result.rotate(rotationY, Qt::YAxis); - result.rotate(rotationZ, Qt::ZAxis); - result.shear(shearX, shearY); - result.scale(scaleX, scaleY); + result.rotate(rotation, Qt::ZAxis); + result.scale(scale, scale); result.translate(-origin.x(), -origin.y()); QGraphicsScene scene; QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100)); scene.addItem(item); - item->setRotation(rotationX, rotationY, rotationZ); - item->setScale(scaleX, scaleY); - item->setShear(shearX, shearY); - item->setTransformOrigin(origin); + item->setRotation(rotation); + item->setScale(scale); + item->setTransformOriginPoint(origin); - QCOMPARE(item->xRotation(), rotationX); - QCOMPARE(item->yRotation(), rotationY); - QCOMPARE(item->zRotation(), rotationZ); - QCOMPARE(item->xScale(), scaleX); - QCOMPARE(item->yScale(), scaleY); - QCOMPARE(item->horizontalShear(), shearX); - QCOMPARE(item->verticalShear(), shearY); - QCOMPARE(item->transformOrigin(), origin); + QCOMPARE(item->rotation(), rotation); + QCOMPARE(item->scale(), scale); + QCOMPARE(item->transformOriginPoint(), origin); QCOMPARE(QTransform(), item->transform()); QCOMPARE(result, item->sceneTransform()); //----------------------------------------------------------------- //Change the rotation Z - item->setZRotation(45); + item->setRotation(45); QTransform result2; result2.translate(origin.x(), origin.y()); - result2.rotate(rotationX, Qt::XAxis); - result2.rotate(rotationY, Qt::YAxis); - result2.rotate(45, Qt::ZAxis); - result2.shear(shearX, shearY); - result2.scale(scaleX, scaleY); + result2.rotate(45); + result2.scale(scale, scale); result2.translate(-origin.x(), -origin.y()); - QCOMPARE(item->xRotation(), rotationX); - QCOMPARE(item->yRotation(), rotationY); - QCOMPARE(item->zRotation(), 45.0); - QCOMPARE(item->xScale(), scaleX); - QCOMPARE(item->yScale(), scaleY); - QCOMPARE(item->horizontalShear(), shearX); - QCOMPARE(item->verticalShear(), shearY); - QCOMPARE(item->transformOrigin(), origin); + QCOMPARE(item->rotation(), 45.); + QCOMPARE(item->scale(), scale); + QCOMPARE(item->transformOriginPoint(), origin); QCOMPARE(QTransform(), item->transform()); QCOMPARE(result2, item->sceneTransform()); //----------------------------------------------------------------- - // calling setTransform() and setPos shoukld change the sceneTransform + // calling setTransform() and setPos should change the sceneTransform item->setTransform(result); item->setPos(100, -150.5); - QCOMPARE(item->xRotation(), rotationX); - QCOMPARE(item->yRotation(), rotationY); - QCOMPARE(item->zRotation(), 45.0); - QCOMPARE(item->xScale(), scaleX); - QCOMPARE(item->yScale(), scaleY); - QCOMPARE(item->horizontalShear(), shearX); - QCOMPARE(item->verticalShear(), shearY); - QCOMPARE(item->transformOrigin(), origin); + QCOMPARE(item->rotation(), 45.); + QCOMPARE(item->scale(), scale); + QCOMPARE(item->transformOriginPoint(), origin); QCOMPARE(result, item->transform()); - QTransform result3; + QTransform result3(result); result3.translate(origin.x(), origin.y()); - result3 = result * result3; - result3.rotate(rotationX, Qt::XAxis); - result3.rotate(rotationY, Qt::YAxis); - result3.rotate(45, Qt::ZAxis); - result3.shear(shearX, shearY); - result3.scale(scaleX, scaleY); + result3.rotate(45); + result3.scale(scale, scale); result3.translate(-origin.x(), -origin.y()); result3 *= QTransform::fromTranslate(100, -150.5); //the pos; @@ -7034,10 +6981,9 @@ void tst_QGraphicsItem::setTransformProperties() item1->setPos(12.3, -5); item2->setPos(12.3, -5); - item1->setRotation(rotationX, rotationY, rotationZ); - item1->setScale(scaleX, scaleY); - item1->setShear(shearX, shearY); - item1->setTransformOrigin(origin); + item1->setRotation(rotation); + item1->setScale(scale); + item1->setTransformOriginPoint(origin); item2->setTransform(result); @@ -7046,36 +6992,6 @@ void tst_QGraphicsItem::setTransformProperties() QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform()); QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform()); } - - {//with center origin on the item - QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); - scene.addItem(item1); - QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119)); - scene.addItem(item2); - - item1->setPos(12.3, -5); - item2->setPos(12.3, -5); - item1->setTransformOrigin(origin); - item2->setTransformOrigin(origin); - - item1->setRotation(rotationX, rotationY, rotationZ); - item1->setScale(scaleX, scaleY); - item1->setShear(shearX, shearY); - - QTransform tr; - tr.rotate(rotationX, Qt::XAxis); - tr.rotate(rotationY, Qt::YAxis); - tr.rotate(rotationZ, Qt::ZAxis); - tr.shear(shearX, shearY); - tr.scale(scaleX, scaleY); - - item2->setTransform(tr); - - QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform()); - - QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform()); - QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform()); - } } class MyStyleOptionTester : public QGraphicsRectItem diff --git a/tests/auto/qgraphicstransform/qgraphicstransform.pro b/tests/auto/qgraphicstransform/qgraphicstransform.pro new file mode 100644 index 0000000..709cff6 --- /dev/null +++ b/tests/auto/qgraphicstransform/qgraphicstransform.pro @@ -0,0 +1,2 @@ +load(qttest_p4) +SOURCES += tst_qgraphicstransform.cpp diff --git a/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp new file mode 100644 index 0000000..672b1f1 --- /dev/null +++ b/tests/auto/qgraphicstransform/tst_qgraphicstransform.cpp @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include "../../shared/util.h" + +class tst_QGraphicsTransform : public QObject { + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void scale(); + void rotation(); + void rotation3d(); +}; + + +// This will be called before the first test function is executed. +// It is only called once. +void tst_QGraphicsTransform::initTestCase() +{ +} + +// This will be called after the last test function is executed. +// It is only called once. +void tst_QGraphicsTransform::cleanupTestCase() +{ +} + +// This will be called before each test function is executed. +void tst_QGraphicsTransform::init() +{ +} + +// This will be called after every test function. +void tst_QGraphicsTransform::cleanup() +{ +} + + +void tst_QGraphicsTransform::scale() +{ + QGraphicsScale scale; + scale.setOrigin(QPointF(10, 10)); + + QTransform t; + scale.applyTo(&t); + + QCOMPARE(t, QTransform()); + QCOMPARE(scale.transform(), QTransform()); + + scale.setXScale(10); + scale.setOrigin(QPointF(0, 0)); + + QTransform res; + res.scale(10, 1); + + QCOMPARE(scale.transform(), res); + QCOMPARE(scale.transform().map(QPointF(10, 10)), QPointF(100, 10)); + + scale.setOrigin(QPointF(10, 10)); + QCOMPARE(scale.transform().map(QPointF(10, 10)), QPointF(10, 10)); + QCOMPARE(scale.transform().map(QPointF(11, 10)), QPointF(20, 10)); +} + +void tst_QGraphicsTransform::rotation() +{ + QGraphicsRotation rotation; + rotation.setOrigin(QPointF(10, 10)); + + QTransform t; + rotation.applyTo(&t); + + QCOMPARE(t, QTransform()); + QCOMPARE(rotation.transform(), QTransform()); + + rotation.setAngle(40); + rotation.setOrigin(QPointF(0, 0)); + + QTransform res; + res.rotate(40); + + QCOMPARE(rotation.transform(), res); + + rotation.setOrigin(QPointF(10, 10)); + rotation.setAngle(90); + QCOMPARE(rotation.transform().map(QPointF(10, 10)), QPointF(10, 10)); + QCOMPARE(rotation.transform().map(QPointF(20, 10)), QPointF(10, 20)); +} + +void tst_QGraphicsTransform::rotation3d() +{ + QGraphicsRotation3D rotation; + rotation.setOrigin(QPointF(10, 10)); + + QTransform t; + rotation.applyTo(&t); + + QCOMPARE(t, QTransform()); + QCOMPARE(rotation.transform(), QTransform()); + + rotation.setAngle(180); + + QCOMPARE(t, QTransform()); + QCOMPARE(rotation.transform(), QTransform()); + + rotation.setOrigin(QPointF(0, 0)); + + QCOMPARE(t, QTransform()); + QCOMPARE(rotation.transform(), QTransform()); +} + + +QTEST_MAIN(tst_QGraphicsTransform) +#include "tst_qgraphicstransform.moc" + -- cgit v0.12