summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-08-18 13:28:09 (GMT)
committerBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-08-20 16:59:01 (GMT)
commit1ffed52434741aa31b1549a931f6b446b2aaabd0 (patch)
tree3b30ddb20e3d8b851f08c93028fcb1386ac28b9e /src/gui/kernel
parent181c9774791b6f581598389337f9af0fa4658e6a (diff)
downloadQt-1ffed52434741aa31b1549a931f6b446b2aaabd0.zip
Qt-1ffed52434741aa31b1549a931f6b446b2aaabd0.tar.gz
Qt-1ffed52434741aa31b1549a931f6b446b2aaabd0.tar.bz2
Add support for graphics effects on QWidget.
Diffstat (limited to 'src/gui/kernel')
-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
3 files changed, 176 insertions, 3 deletions
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 515eed9..a314cf19 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 6f30883..4f14a53 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 a3f4f6f..acfb6c3 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;