diff options
author | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-08-18 13:28:09 (GMT) |
---|---|---|
committer | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-08-20 16:59:01 (GMT) |
commit | 1ffed52434741aa31b1549a931f6b446b2aaabd0 (patch) | |
tree | 3b30ddb20e3d8b851f08c93028fcb1386ac28b9e /src/gui | |
parent | 181c9774791b6f581598389337f9af0fa4658e6a (diff) | |
download | Qt-1ffed52434741aa31b1549a931f6b446b2aaabd0.zip Qt-1ffed52434741aa31b1549a931f6b446b2aaabd0.tar.gz Qt-1ffed52434741aa31b1549a931f6b446b2aaabd0.tar.bz2 |
Add support for graphics effects on QWidget.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/effects/qgraphicseffect.cpp | 6 | ||||
-rw-r--r-- | src/gui/effects/qgraphicseffect.h | 5 | ||||
-rw-r--r-- | src/gui/effects/qgraphicseffect_p.h | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 109 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 66 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_p.h | 4 |
8 files changed, 192 insertions, 6 deletions
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index c6f2871..3d363f1 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 4344e2d..f6c47d7 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 309b382..25397c3 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 a798a3b..cd5c595 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 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; diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index 7ea68d2..d3cd6f9 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 |