summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/effects/qgraphicseffect.cpp6
-rw-r--r--src/gui/effects/qgraphicseffect.h5
-rw-r--r--src/gui/effects/qgraphicseffect_p.h1
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h3
-rw-r--r--src/gui/kernel/qwidget.cpp109
-rw-r--r--src/gui/kernel/qwidget.h4
-rw-r--r--src/gui/kernel/qwidget_p.h66
-rw-r--r--src/gui/painting/qpaintengine_p.h4
8 files changed, 192 insertions, 6 deletions
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
index c6f2871bc7..3d363f1310 100644
--- a/src/gui/effects/qgraphicseffect.cpp
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -97,6 +97,7 @@
#include <QtGui/qimage.h>
#include <QtGui/qpainter.h>
#include <QtCore/qrect.h>
+#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
@@ -122,6 +123,11 @@ const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const
return d_func()->graphicsItem();
}
+const QWidget *QGraphicsEffectSource::widget() const
+{
+ return d_func()->widget();
+}
+
const QStyleOption *QGraphicsEffectSource::styleOption() const
{
return d_func()->styleOption();
diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h
index 4344e2de3f..f6c47d71d0 100644
--- a/src/gui/effects/qgraphicseffect.h
+++ b/src/gui/effects/qgraphicseffect.h
@@ -65,6 +65,7 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject
public:
~QGraphicsEffectSource();
const QGraphicsItem *graphicsItem() const;
+ const QWidget *widget() const;
const QStyleOption *styleOption() const;
bool isPixmap() const;
@@ -85,6 +86,8 @@ private:
friend class QGraphicsEffectPrivate;
friend class QGraphicsScenePrivate;
friend class QGraphicsItem;
+ friend class QWidget;
+ friend class QWidgetPrivate;
};
class QGraphicsEffectPrivate;
@@ -131,6 +134,8 @@ private:
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
friend class QGraphicsScenePrivate;
+ friend class QWidget;
+ friend class QWidgetPrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags);
diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h
index 309b382618..25397c303c 100644
--- a/src/gui/effects/qgraphicseffect_p.h
+++ b/src/gui/effects/qgraphicseffect_p.h
@@ -70,6 +70,7 @@ public:
virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0;
virtual QRect deviceRect() const = 0;
virtual const QGraphicsItem *graphicsItem() const = 0;
+ virtual const QWidget *widget() const = 0;
virtual const QStyleOption *styleOption() const = 0;
virtual void draw(QPainter *p) = 0;
virtual void update() = 0;
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index a798a3b232..cd5c595625 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -559,6 +559,9 @@ public:
inline const QGraphicsItem *graphicsItem() const
{ return item; }
+ inline const QWidget *widget() const
+ { return 0; }
+
inline void update()
{ item->update(); }
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 515eed96ff..a314cf1958 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -182,6 +182,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
, widgetItem(0)
, extraPaintEngine(0)
, polished(0)
+ , graphicsEffect(0)
, inheritedFontResolveMask(0)
, inheritedPaletteResolveMask(0)
, leftmargin(0)
@@ -237,6 +238,8 @@ QWidgetPrivate::~QWidgetPrivate()
if (extra)
deleteExtra();
+
+ delete graphicsEffect;
}
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface()
@@ -1649,7 +1652,7 @@ QRect QWidgetPrivate::clipRect() const
const QWidget * w = q;
if (!w->isVisible())
return QRect();
- QRect r = q->rect();
+ QRect r = effectiveRectFor(q->rect());
int ox = 0;
int oy = 0;
while (w
@@ -1891,6 +1894,12 @@ void QWidgetPrivate::updateIsOpaque()
// hw: todo: only needed if opacity actually changed
setDirtyOpaqueRegion();
+ if (graphicsEffect) {
+ // ### We should probably add QGraphicsEffect::isOpaque at some point.
+ setOpaque(false);
+ return;
+ }
+
Q_Q(QWidget);
#ifdef Q_WS_X11
if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
@@ -4847,6 +4856,43 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
d->extra->inRenderWithPainter = false;
}
+QGraphicsEffect *QWidget::graphicsEffect() const
+{
+ Q_D(const QWidget);
+ return d->graphicsEffect;
+}
+
+void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
+{
+ Q_D(QWidget);
+ if (d->graphicsEffect == effect)
+ return;
+
+ if (d->graphicsEffect && effect) {
+ // ### This seems wrong - the effect should automatically be deleted.
+ qWarning("already set");
+ return;
+ }
+
+ if (!effect) {
+ // Unset current effect.
+ QGraphicsEffectPrivate *oldEffectPrivate = d->graphicsEffect->d_func();
+ d->graphicsEffect = 0;
+ if (oldEffectPrivate) {
+ oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
+ }
+ } else {
+ // Set new effect.
+ QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
+ QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
+ d->graphicsEffect = effect;
+ effect->d_func()->setGraphicsEffectSource(source);
+ }
+
+ d->updateIsOpaque();
+ update();
+}
+
bool QWidgetPrivate::isAboutToShow() const
{
if (data.in_show)
@@ -4991,6 +5037,30 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
return;
Q_Q(QWidget);
+ if (graphicsEffect && graphicsEffect->isEnabled()) {
+ QGraphicsEffectSource *source = graphicsEffect->d_func()->source;
+ QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
+ (source->d_func());
+ if (!sourced->context) {
+ QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
+ sourced->context = &context;
+ if (!sharedPainter) {
+ QPaintEngine *paintEngine = pdev->paintEngine();
+ paintEngine->d_func()->systemClip = clipRect().translated(offset);
+ QPainter p(pdev);
+ p.translate(offset);
+ context.painter = &p;
+ graphicsEffect->draw(&p, source);
+ paintEngine->d_func()->systemClip = QRegion();
+ } else {
+ context.painter = sharedPainter;
+ graphicsEffect->draw(sharedPainter, source);
+ }
+ sourced->context = 0;
+ return;
+ }
+ }
+
const bool asRoot = flags & DrawAsRoot;
const bool alsoOnScreen = flags & DrawPaintOnScreen;
const bool recursive = flags & DrawRecursive;
@@ -5023,7 +5093,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (sharedPainter)
paintEngine->d_func()->systemClip = toBePainted;
else
- paintEngine->setSystemRect(q->data->crect);
+ paintEngine->d_func()->systemRect = q->data->crect;
//paint the background
if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
@@ -5062,7 +5132,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (paintEngine) {
restoreRedirected();
if (!sharedPainter)
- paintEngine->setSystemRect(QRect());
+ paintEngine->d_func()->systemRect = QRect();
else
paintEngine->d_func()->currentClipWidget = 0;
paintEngine->d_func()->systemClip = QRegion();
@@ -5166,6 +5236,39 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis
}
}
+void QWidgetEffectSourcePrivate::draw(QPainter *painter)
+{
+ if (!context || context->painter != painter) {
+ m_widget->render(painter);
+ return;
+ }
+
+ qt_widget_private(m_widget)->drawWidget(context->pdev, context->rgn, context->offset, context->flags,
+ context->sharedPainter, context->backingStore);
+}
+
+QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+{
+ const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
+ QPoint pixmapOffset;
+
+ QRect sourceRect(m_widget->rect());
+ if (deviceCoordinates) {
+ pixmapOffset = m_widget->mapTo(m_widget->window(), QPoint());
+ sourceRect.translate(pixmapOffset);
+ }
+
+ QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+ if (offset)
+ *offset = effectRect.topLeft();
+ pixmapOffset -= effectRect.topLeft();
+
+ QPixmap pixmap(effectRect.size());
+ pixmap.fill(Qt::transparent);
+ m_widget->render(&pixmap, pixmapOffset);
+ return pixmap;
+}
+
/*!
\internal
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 6f30883229..4f14a53d92 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -96,6 +96,7 @@ class QWindowSurface;
class QLocale;
class QGraphicsProxyWidget;
class QGestureManager;
+class QGraphicsEffect;
#if defined(Q_WS_X11)
class QX11Info;
#endif
@@ -352,6 +353,9 @@ public:
const QRegion &sourceRegion = QRegion(),
RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
+ QGraphicsEffect *graphicsEffect() const;
+ void setGraphicsEffect(QGraphicsEffect *effect);
+
public Q_SLOTS:
void setWindowTitle(const QString &);
#ifndef QT_NO_STYLE_STYLESHEET
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index a3f4f6fe30..acfb6c355f 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -61,6 +61,7 @@
#include "QtGui/qregion.h"
#include "QtGui/qsizepolicy.h"
#include "QtGui/qstyle.h"
+#include <private/qgraphicseffect_p.h>
#ifdef Q_WS_WIN
#include "QtCore/qt_windows.h"
@@ -443,6 +444,13 @@ public:
return extra ? extra->nativeChildrenForced : false;
}
+ inline QRect effectiveRectFor(const QRect &rect) const
+ {
+ if (graphicsEffect && graphicsEffect->isEnabled())
+ return graphicsEffect->boundingRectFor(rect).toAlignedRect();
+ return rect;
+ }
+
QSize adjustedSize() const;
#ifndef Q_WS_QWS // Almost cross-platform :-)
@@ -473,6 +481,7 @@ public:
QWidgetItemV2 *widgetItem;
QPaintEngine *extraPaintEngine;
mutable const QMetaObject *polished;
+ QGraphicsEffect *graphicsEffect;
// All widgets are initially added into the uncreatedWidgets set. Once
// they receive a window id they are removed and added to the mapper
static QWidgetMapper *mapper;
@@ -642,6 +651,63 @@ public:
#endif
};
+struct QWidgetPaintContext
+{
+ inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f,
+ QPainter *p, QWidgetBackingStore *b)
+ : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {}
+
+ QPaintDevice *pdev;
+ QRegion rgn;
+ QPoint offset;
+ int flags;
+ QPainter *sharedPainter;
+ QWidgetBackingStore *backingStore;
+ QPainter *painter;
+};
+
+class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate
+{
+public:
+ QWidgetEffectSourcePrivate(QWidget *widget)
+ : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0)
+ {}
+
+ inline void detach()
+ { m_widget->setGraphicsEffect(0); }
+
+ inline const QGraphicsItem *graphicsItem() const
+ { return 0; }
+
+ inline const QWidget *widget() const
+ { return m_widget; }
+
+ inline void update()
+ { m_widget->update(); }
+
+ inline bool isPixmap() const
+ { return false; }
+
+ inline const QStyleOption *styleOption() const
+ { return 0; }
+
+ inline QRect deviceRect() const
+ { return m_widget->window()->rect(); }
+
+ inline QRectF boundingRect(Qt::CoordinateSystem system) const
+ {
+ if (system == Qt::LogicalCoordinates)
+ return m_widget->rect();
+ return m_widget->rect().translated(m_widget->mapTo(m_widget->window(), QPoint()));
+ }
+
+ void draw(QPainter *p);
+ QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const;
+
+ QWidget *m_widget;
+ QWidgetPaintContext *context;
+};
+
inline QWExtra *QWidgetPrivate::extraData() const
{
return extra;
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index 7ea68d24e3..d3cd6f9415 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -72,6 +72,7 @@ public:
QPaintDevice *pdev;
QPaintEngine *q_ptr;
QRegion systemClip;
+ QRect systemRect;
QRegion systemViewport;
QTransform systemTransform;
QWidget *currentClipWidget;
@@ -117,9 +118,6 @@ public:
virtual void systemStateChanged() { }
void drawBoxTextItem(const QPointF &p, const QTextItemInt &ti);
-
-private:
- QRect systemRect;
};
QT_END_NAMESPACE