summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-07-23 15:11:54 (GMT)
committerBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-07-24 01:03:19 (GMT)
commite646d08593dc18cad4e59176c2fe8c10fa5b9497 (patch)
treef1babc50eaddbe47327bcb7b7adb938c6a5820e0 /src
parent8e18256d023e6e78081a34b573d548d52137575d (diff)
downloadQt-e646d08593dc18cad4e59176c2fe8c10fa5b9497.zip
Qt-e646d08593dc18cad4e59176c2fe8c10fa5b9497.tar.gz
Qt-e646d08593dc18cad4e59176c2fe8c10fa5b9497.tar.bz2
Make QGraphicsEffect independent of QGraphicsItem.
This makes it possible to basically implement support for graphics effects on pretty much everything, e.g. QWidget. We currently only support effects on QGraphicsItem, but there's more to come :-)
Diffstat (limited to 'src')
-rw-r--r--src/gui/graphicsview/qgraphicseffect.cpp234
-rw-r--r--src/gui/graphicsview/qgraphicseffect.h58
-rw-r--r--src/gui/graphicsview/qgraphicseffect_p.h27
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp91
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h45
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp72
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h5
8 files changed, 266 insertions, 268 deletions
diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp
index c173d1b..8d2c416 100644
--- a/src/gui/graphicsview/qgraphicseffect.cpp
+++ b/src/gui/graphicsview/qgraphicseffect.cpp
@@ -104,83 +104,90 @@
QGraphicsEffect::QGraphicsEffect()
: QObject(*new QGraphicsEffectPrivate, 0)
+{}
+
+/*!
+ \internal
+*/
+QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd)
+ : QObject(dd, 0)
+{}
+
+QGraphicsEffect::~QGraphicsEffect()
{
Q_D(QGraphicsEffect);
- d->parentItem = 0;
+ d->setGraphicsEffectSource(0);
}
-QGraphicsEffect::~QGraphicsEffect()
+QRectF QGraphicsEffect::boundingRect() const
{
+ return sourceBoundingRect();
}
-QRectF QGraphicsEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsEffect::sourceBoundingRect() const
{
- // default is to give the item's bounding rect
- // do NOT call item->effectiveBoundRect() because
- // that function will call this one (infinite loop)
- return item->boundingRect();
+ Q_D(const QGraphicsEffect);
+ if (d->source)
+ return d->source->boundingRect();
+ return QRectF();
}
-/*! \internal
-*/
-QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd)
- : QObject(dd, 0)
+void QGraphicsEffect::drawSource(QPainter *painter)
{
Q_D(QGraphicsEffect);
- d->parentItem = 0;
+ if (d->source)
+ d->source->draw(painter);
}
-// this helper function is only for subclasses of QGraphicsEffect
-// the implementation is trivial, but this allows us to keep
-// QGraphicsScene::drawItem() as a protected function
-// (since QGraphicsEffect is a friend of QGraphicsScene)
-QPixmap* QGraphicsEffect::drawItemOnPixmap(QPainter *painter, QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option, QWidget *widget, int flags)
+bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform)
{
- if (!item->scene())
- return 0;
- return item->scene()->drawItemOnPixmap(painter, item, option, widget, flags);
+ Q_D(QGraphicsEffect);
+ if (d->source)
+ return d->source->drawIntoPixmap(pixmap, itemToPixmapTransform);
+ return false;
}
QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect()
: QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate)
-{
-}
+{}
QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect()
-{
-}
+{}
-void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsGrayscaleEffect::draw(QPainter *painter)
{
Q_D(QGraphicsGrayscaleEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
// Draw the pixmap with the filter using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect());
+ d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
+
}
QGraphicsColorizeEffect::QGraphicsColorizeEffect()
: QGraphicsEffect(*new QGraphicsColorizeEffectPrivate)
-{
-}
+{}
QGraphicsColorizeEffect::~QGraphicsColorizeEffect()
-{
-}
+{}
QColor QGraphicsColorizeEffect::color() const
{
@@ -194,25 +201,30 @@ void QGraphicsColorizeEffect::setColor(const QColor &c)
d->filter->setColor(c);
}
-void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsColorizeEffect::draw(QPainter *painter)
{
Q_D(QGraphicsColorizeEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
// Draw the pixmap with the filter using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect());
+ d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -237,23 +249,28 @@ void QGraphicsPixelizeEffect::setPixelSize(int size)
d->pixelSize = size;
}
-void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsPixelizeEffect::draw(QPainter *painter)
{
Q_D(QGraphicsPixelizeEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap))
return;
// pixelize routine
- QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
if (d->pixelSize > 0) {
int width = img.width();
int height = img.height();
@@ -365,31 +382,42 @@ void QGraphicsBlurEffect::setBlurRadius(int radius)
d->filter->setBlurRadius(radius);
}
-QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsBlurEffect::boundingRect() const
{
Q_D(const QGraphicsBlurEffect);
- return d->filter->boundingRectFor(item->boundingRect());
+ if (d->source)
+ return d->filter->boundingRectFor(d->source->boundingRect());
+ return QRectF();
}
-void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsBlurEffect::draw(QPainter *painter)
{
Q_D(QGraphicsBlurEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ // ### Potentially big rect; must be clipped to the viewport rect.
+ const qreal delta = d->blurRadius * 3;
+ const QRect effectRect = deviceBounds.adjusted(-delta, -delta, delta, delta)
+ .toRect().adjusted(-1, -1, 1, 1);
+ if (effectRect.x() != 0 || effectRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-effectRect.x(), -effectRect.y());
+
+ QPixmap pixmap(effectRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
// Draw the pixmap with the filter using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- d->filter->draw(painter, deviceRect.topLeft(), *pixmap, pixmap->rect());
+ d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -426,13 +454,13 @@ void QGraphicsBloomEffect::setOpacity(qreal alpha)
d->opacity = alpha;
}
-QRectF QGraphicsBloomEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsBloomEffect::boundingRect() const
{
- Q_D(QGraphicsBloomEffect);
+ Q_D(const QGraphicsBloomEffect);
+ if (!d->source)
+ return QRectF();
qreal delta = d->blurRadius * 3;
- QRectF blurRect = item->boundingRect();
- blurRect.adjust(-delta, -delta, delta, delta);
- return blurRect;
+ return d->source->boundingRect().adjusted(-delta, -delta, delta, delta);
}
// Change brightness (positive integer) of each pixel
@@ -466,24 +494,29 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity,
return result;
}
-void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsBloomEffect::draw(QPainter *painter)
{
Q_D(QGraphicsBloomEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
// bloom routine
int radius = d->blurRadius;
- QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
QImage overlay = blurred(img, img.rect(), radius);
overlay = brightened(overlay, 70);
img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay);
@@ -540,31 +573,35 @@ void QGraphicsFrameEffect::setFrameOpacity(qreal opacity)
d->alpha = opacity;
}
-QRectF QGraphicsFrameEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsFrameEffect::boundingRect() const
{
- Q_D(QGraphicsFrameEffect);
- QRectF frameRect = item->boundingRect();
- frameRect.adjust(-d->width, -d->width, d->width, d->width);
- return frameRect;
+ Q_D(const QGraphicsFrameEffect);
+ if (!d->source)
+ return QRectF();
+ return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width);
}
-void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsFrameEffect::draw(QPainter *painter)
{
Q_D(QGraphicsFrameEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
+ if (deviceBounds.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
- return;
+ QRect frameRect = deviceBounds.adjusted(-d->width, -d->width, d->width, d->width)
+ .toRect().adjusted(-1, -1, 1, 1);
+
+ if (frameRect.x() != 0 || frameRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-frameRect.x(), -frameRect.y());
- QRectF frameRect = deviceBounds;
- frameRect.adjust(-d->width, -d->width, d->width, d->width);
+ QPixmap pixmap(frameRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ return;
painter->save();
painter->setWorldTransform(QTransform());
@@ -576,7 +613,7 @@ void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter,
painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize);
painter->restore();
- painter->drawPixmap(frameRect.topLeft(), *pixmap);
+ painter->drawPixmap(frameRect.topLeft(), pixmap);
painter->restore();
}
@@ -626,25 +663,30 @@ void QGraphicsShadowEffect::setOpacity(qreal opacity)
d->alpha = opacity;
}
-QRectF QGraphicsShadowEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsShadowEffect::boundingRect() const
{
- Q_D(QGraphicsShadowEffect);
- QRectF shadowRect = item->boundingRect();
+ Q_D(const QGraphicsShadowEffect);
+ if (!d->source)
+ return QRectF();
+ const QRectF srcBrect = d->source->boundingRect();
+ QRectF shadowRect = srcBrect;
shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y());
QRectF blurRect = shadowRect;
qreal delta = d->radius * 3;
blurRect.adjust(-delta, -delta, delta, delta);
- QRectF totalRect = blurRect.united(item->boundingRect());
+ QRectF totalRect = blurRect.united(srcBrect);
return totalRect;
}
-void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsShadowEffect::draw(QPainter *painter)
{
Q_D(QGraphicsShadowEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
@@ -654,13 +696,16 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
QRectF blurRect = shadowRect;
qreal delta = d->radius * 3;
blurRect.adjust(-delta, -delta, delta, delta);
- QRectF totalRect = blurRect.united(deviceRect);
+ QRect totalRect = blurRect.united(deviceRect).toRect().adjusted(-1, -1, 1, 1);
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (totalRect.x() != 0 || totalRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-totalRect.x(), -totalRect.y());
+
+ QPixmap pixmap(totalRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
- QImage img = pixmap->toImage();
+ QImage img = pixmap.toImage();
QImage shadowImage(img.size(), QImage::Format_ARGB32);
shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255));
shadowImage.setAlphaChannel(img.alphaChannel());
@@ -682,10 +727,9 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
qreal itemx = qMin(blurRect.x(), deviceBounds.x());
qreal itemy = qMin(blurRect.y(), deviceBounds.y());
- painter->drawPixmap(itemx, itemy, *pixmap);
+ painter->drawPixmap(itemx, itemy, pixmap);
painter->setWorldTransform(restoreTransform);
}
-
#endif
diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h
index 9f6e342..74a8430 100644
--- a/src/gui/graphicsview/qgraphicseffect.h
+++ b/src/gui/graphicsview/qgraphicseffect.h
@@ -46,6 +46,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qpoint.h>
#include <QtCore/qvariant.h>
+#include <QtGui/qtransform.h>
#include <QtGui/qcolor.h>
QT_FORWARD_DECLARE_CLASS(QGraphicsItem);
@@ -71,18 +72,17 @@ public:
QGraphicsEffect();
virtual ~QGraphicsEffect();
- virtual QRectF boundingRectFor(const QGraphicsItem *item);
-
- virtual void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0) = 0;
+ virtual QRectF boundingRect() const;
protected:
QGraphicsEffect(QGraphicsEffectPrivate &d);
- QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option, QWidget *widget, int flags);
+ virtual void draw(QPainter *painter) = 0;
+ void drawSource(QPainter *painter);
+ bool drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &xform = QTransform());
+ QRectF sourceBoundingRect() const;
private:
+ friend class QGraphicsScenePrivate;
friend class QGraphicsItem;
Q_DECLARE_PRIVATE(QGraphicsEffect)
Q_DISABLE_COPY(QGraphicsEffect)
@@ -96,9 +96,8 @@ public:
QGraphicsGrayscaleEffect();
~QGraphicsGrayscaleEffect();
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect)
@@ -115,9 +114,8 @@ public:
QColor color() const;
void setColor(const QColor &c);
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsColorizeEffect)
@@ -134,9 +132,8 @@ public:
int pixelSize() const;
void setPixelSize(int pixelSize);
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect)
@@ -153,11 +150,10 @@ public:
int blurRadius() const;
void setBlurRadius(int blurRadius);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsBlurEffect)
@@ -177,11 +173,10 @@ public:
qreal opacity() const;
void setOpacity(qreal opacity);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsBloomEffect)
@@ -204,11 +199,11 @@ public:
qreal frameOpacity() const;
void setFrameOpacity(qreal opacity);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
+
+protected:
+ void draw(QPainter *painter);
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
private:
Q_DECLARE_PRIVATE(QGraphicsFrameEffect)
Q_DISABLE_COPY(QGraphicsFrameEffect)
@@ -232,11 +227,10 @@ public:
qreal opacity() const;
void setOpacity(qreal opacity);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsShadowEffect)
diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h
index 999e013..9204789 100644
--- a/src/gui/graphicsview/qgraphicseffect_p.h
+++ b/src/gui/graphicsview/qgraphicseffect_p.h
@@ -61,12 +61,31 @@
QT_BEGIN_NAMESPACE
+class QGraphicsEffectSource
+{
+public:
+ QGraphicsEffectSource() {}
+ virtual ~QGraphicsEffectSource() {}
+ virtual void detach() = 0;
+ virtual QRectF boundingRect() = 0;
+ virtual void draw(QPainter *p) = 0;
+ virtual bool drawIntoPixmap(QPixmap *, const QTransform & = QTransform()) = 0;
+};
+
class QGraphicsEffectPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QGraphicsEffect)
public:
- QGraphicsEffectPrivate(): parentItem(0) {}
- QGraphicsItem *parentItem;
+ QGraphicsEffectPrivate() : source(0) {}
+ QGraphicsEffectSource *source;
+ inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource)
+ {
+ if (source) {
+ source->detach();
+ delete source;
+ }
+ source = newSource;
+ }
};
class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate
@@ -106,8 +125,10 @@ class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate
{
Q_DECLARE_PUBLIC(QGraphicsBlurEffect)
public:
- QGraphicsBlurEffectPrivate() : blurRadius(4) {}
+ QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter), blurRadius(4) {}
+ ~QGraphicsBlurEffectPrivate() { delete filter; }
+ QPixmapBlurFilter *filter;
int blurRadius;
};
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 3a350e0..1d271c9 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -552,7 +552,6 @@
#ifndef QT_NO_GRAPHICSVIEW
-#include "qgraphicseffect_p.h"
#include "qgraphicsscene.h"
#include "qgraphicsscene_p.h"
#include "qgraphicssceneevent.h"
@@ -1180,8 +1179,7 @@ QGraphicsItem::~QGraphicsItem()
else
d_ptr->setParentItemHelper(0);
- QGraphicsEffect *e = graphicsEffect();
- delete e;
+ delete d_ptr->graphicsEffect;
delete d_ptr->transformData;
delete d_ptr;
@@ -2198,11 +2196,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
*/
QGraphicsEffect *QGraphicsItem::graphicsEffect() const
{
- QGraphicsEffect *fx = 0;
- if (d_ptr->hasEffect)
- fx = d_ptr->extra(QGraphicsItemPrivate::ExtraEffect).value<QGraphicsEffect*>();
-
- return fx;
+ return d_ptr->graphicsEffect;
}
/*!
@@ -2220,30 +2214,29 @@ QGraphicsEffect *QGraphicsItem::graphicsEffect() const
*/
void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
{
- if (effect) {
- if (QGraphicsEffect *currentEffect = this->graphicsEffect()) {
- if (currentEffect != effect) {
- qWarning("QGraphicsItem::setEffect: Attempting to set QGraphicsEffect "
- "%p on %p, which already has an effect", effect, this);
- }
- return;
- }
+ if (d_ptr->graphicsEffect == effect)
+ return;
- if (effect->d_func()->parentItem)
- effect->d_func()->parentItem->setGraphicsEffect(0);
- effect->d_func()->parentItem = this;
- d_ptr->hasEffect = true;
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffect, QVariant::fromValue(effect));
+ if (d_ptr->graphicsEffect && effect) {
+ qWarning("QGraphicsItem::setGraphicsEffect: Attempting to set QGraphicsEffect "
+ "%p on %p, which already has an effect installed", effect, this);
+ return;
+ }
+
+ if (!effect) {
+ // Unset current effect.
+ QGraphicsEffectPrivate *oldEffectPrivate = d_ptr->graphicsEffect->d_func();
+ d_ptr->graphicsEffect = 0;
+ if (oldEffectPrivate)
+ oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
} else {
- d_ptr->hasEffect = false;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffect);
- void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value<void*>();
- QPixmap *pixmap = reinterpret_cast<QPixmap*>(ptr);
- delete pixmap;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffectPixmap);
+ // Set new effect.
+ effect->d_func()->setGraphicsEffectSource(new QGraphicsItemEffectSource(this));
+ d_ptr->graphicsEffect = effect;
}
- update();
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this);
}
/*!
@@ -2257,10 +2250,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
*/
QRectF QGraphicsItem::effectiveBoundingRect() const
{
- QGraphicsEffect *fx = graphicsEffect();
- if (fx)
- return fx->boundingRectFor(this);
-
+ if (d_ptr->graphicsEffect)
+ return d_ptr->graphicsEffect->boundingRect();
return boundingRect();
}
@@ -2294,42 +2285,6 @@ QRectF QGraphicsItem::sceneEffectiveBoundingRect() const
}
/*!
- \internal
-
- Used by QGraphicsScene.
-*/
-QPixmap *QGraphicsItem::effectPixmap()
-{
- if (!d_ptr->hasEffect)
- return 0;
-
- // the exact size of the pixmap is not a big deal
- // as long as it contains the effective bounding rect
- // TODO: use smart resizing etc
- // TODO: store per device and do everything in device coordinate?
- // TODO: use layer
- QRect rect = effectiveBoundingRect().toAlignedRect();
-
- void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value<void*>();
- QPixmap *pixmap = reinterpret_cast<QPixmap*>(ptr);
- bool avail = true;
- if (!pixmap)
- avail = false;
- if (avail && pixmap->size() != rect.size())
- avail = false;
-
- if (!avail) {
- delete pixmap;
- pixmap = new QPixmap(rect.size());
- pixmap->fill(Qt::transparent);
- ptr = reinterpret_cast<void*>(pixmap);
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffectPixmap, QVariant::fromValue(ptr));
- }
-
- return pixmap;
-}
-
-/*!
Returns true if this item can accept drag and drop events; otherwise,
returns false. By default, items do not accept drag and drop events; items
are transparent to drag and drop.
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 0beb07c..0c0b341 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -440,8 +440,6 @@ protected:
void removeFromIndex();
void prepareGeometryChange();
- QPixmap *effectPixmap();
-
private:
Q_DISABLE_COPY(QGraphicsItem)
Q_DECLARE_PRIVATE(QGraphicsItem)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 09f296a..dc875f7 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -57,6 +57,7 @@
#include "qset.h"
#include "qpixmapcache.h"
#include "qgraphicsview_p.h"
+#include "qgraphicseffect_p.h"
#include <QtCore/qpoint.h>
@@ -103,8 +104,6 @@ public:
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
ExtraBoundingRegionGranularity,
- ExtraEffect,
- ExtraEffectPixmap,
ExtraGestures
};
@@ -122,6 +121,7 @@ public:
scene(0),
parent(0),
transformData(0),
+ graphicsEffect(0),
index(-1),
siblingIndex(-1),
depth(0),
@@ -151,7 +151,6 @@ public:
allChildrenDirty(0),
fullUpdatePending(0),
flags(0),
- hasEffect(0),
dirtyChildrenBoundingRect(1),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -409,6 +408,7 @@ public:
QList<QGraphicsItem *> children;
struct TransformData;
TransformData *transformData;
+ QGraphicsEffect *graphicsEffect;
QTransform sceneTransform;
int index;
int siblingIndex;
@@ -443,7 +443,6 @@ public:
// New 32 bits
quint32 fullUpdatePending : 1;
quint32 flags : 12;
- quint32 hasEffect : 1;
quint32 dirtyChildrenBoundingRect : 1;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
@@ -511,6 +510,44 @@ struct QGraphicsItemPrivate::TransformData {
}
};
+class QGraphicsItemEffectSource : public QGraphicsEffectSource
+{
+public:
+ QGraphicsItemEffectSource(QGraphicsItem *i)
+ : QGraphicsEffectSource(), item(i), option(0), widget(0)
+ {}
+
+ inline void detach()
+ { item->setGraphicsEffect(0); }
+
+ inline QRectF boundingRect()
+ { return item->boundingRect(); }
+
+ inline void draw(QPainter *painter)
+ { item->paint(painter, option, widget); }
+
+ inline bool drawIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform)
+ {
+ pixmap->fill(Qt::transparent);
+ QPainter pixmapPainter(pixmap);
+ if (!itemToPixmapTransform.isIdentity())
+ pixmapPainter.setWorldTransform(itemToPixmapTransform);
+ item->paint(&pixmapPainter, option, widget);
+ return true;
+ }
+
+ inline void setPaintInfo(const QStyleOptionGraphicsItem *o, QWidget *w)
+ { option = o; widget = w; }
+
+ void resetPaintInfo()
+ { option = 0; widget = 0; }
+
+private:
+ QGraphicsItem *item;
+ const QStyleOptionGraphicsItem *option;
+ QWidget *widget;
+};
+
/*!
\internal
*/
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index c56f34c..f4fd4ce 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -3928,8 +3928,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
#endif
// Render using effect, works now only for no cache mode
- if (noCache && itemd->hasEffect && item->graphicsEffect()) {
- item->graphicsEffect()->drawItem(item, painter, option, widget);
+ if (noCache && itemd->graphicsEffect) {
+ itemd->graphicsEffect->draw(painter);
return;
}
@@ -4228,62 +4228,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
}
-// FIXME: merge this with drawItems (needs refactoring)
-QPixmap* QGraphicsScene::drawItemOnPixmap(QPainter *painter,
- QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option,
- QWidget *widget,
- int flags)
-{
- // TODO: use for choosing item or device coordinate
- // FIXME: how about source, dest, and exposed rects?
- Q_UNUSED(flags);
-
- // Item's (local) bounding rect, including the effect
- QRectF brect = item->effectiveBoundingRect();
- QRectF adjustedBrect(brect);
- _q_adjustRect(&adjustedBrect);
- if (adjustedBrect.isEmpty())
- return 0;
-
- // Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(brect);
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return 0;
-
- // If widget, check if it intersects or not
- QRect viewRect = widget ? widget->rect() : QRect();
- if (widget && !viewRect.intersects(deviceRect))
- return 0;
-
- // Create offscreen pixmap
- // TODO: use the pixmap from the layer
- QPixmap *targetPixmap = item->effectPixmap();
- if (!targetPixmap)
- targetPixmap = new QPixmap(deviceRect.size());
-
- // FIXME: this is brute force
- QRegion pixmapExposed;
- pixmapExposed += targetPixmap->rect();
-
- // Construct an item-to-pixmap transform.
- QPointF p = deviceRect.topLeft();
- QTransform itemToPixmap = painter->worldTransform();
- if (!p.isNull())
- itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
-
- // Calculate the style option's exposedRect.
- QStyleOptionGraphicsItem fxOption = *option;
- fxOption.exposedRect = brect.adjusted(-1, -1, 1, 1);
-
- // Render
- _q_paintIntoCache(targetPixmap, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &fxOption, false);
-
- return targetPixmap;
-}
-
void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform,
QRegion *exposedRegion, QWidget *widget)
{
@@ -4412,11 +4356,21 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
painter->setClipPath(item->shape(), Qt::IntersectClip);
painter->setOpacity(opacity);
- if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !item->d_ptr->hasEffect)
+ QGraphicsItemEffectSource *source = item->d_ptr->graphicsEffect
+ ? static_cast<QGraphicsItemEffectSource *>
+ (item->d_ptr->graphicsEffect->d_func()->source)
+ : 0;
+ if (source)
+ source->setPaintInfo(&styleOptionTmp, widget);
+
+ if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !source)
item->paint(painter, &styleOptionTmp, widget);
else
drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
+ if (source)
+ source->resetPaintInfo();
+
if (savePainter)
painter->restore();
}
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index 68bd3e1..1606053 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -281,11 +281,6 @@ protected:
const QStyleOptionGraphicsItem options[],
QWidget *widget = 0);
- QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option, QWidget *widget, int flags);
-
-
-
protected Q_SLOTS:
bool focusNextPrevChild(bool next);