src/gui/graphicsview/qgraphicsproxywidget.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,1525 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+#ifndef QT_NO_GRAPHICSVIEW
+
+#include "qgraphicslayout.h"
+#include "qgraphicsproxywidget.h"
+#include "private/qgraphicsproxywidget_p.h"
+#include "private/qwidget_p.h"
+#include "private/qapplication_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicssceneevent.h>
+#include <QtGui/qlayout.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qstyleoption.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qlistview.h>
+#include <QtGui/qlineedit.h>
+#include <QtGui/qtextedit.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define GRAPHICSPROXYWIDGET_DEBUG
+
+/*!
+    \class QGraphicsProxyWidget
+    \brief The QGraphicsProxyWidget class provides a proxy layer for embedding
+    a QWidget in a QGraphicsScene.
+    \since 4.4
+    \ingroup graphicsview-api
+
+    QGraphicsProxyWidget embeds QWidget-based widgets, for example, a
+    QPushButton, QFontComboBox, or even QFileDialog, into
+    QGraphicsScene. It forwards events between the two objects and
+    translates between QWidget's integer-based geometry and
+    QGraphicsWidget's qreal-based geometry. QGraphicsProxyWidget
+    supports all core features of QWidget, including tab focus,
+    keyboard input, Drag & Drop, and popups.  You can also embed
+    complex widgets, e.g., widgets with subwidgets.
+
+    Example:
+
+    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 0
+
+    QGraphicsProxyWidget takes care of automatically embedding popup children
+    of embedded widgets through creating a child proxy for each popup. This
+    means that when an embedded QComboBox shows its popup list, a new
+    QGraphicsProxyWidget is created automatically, embedding the popup, and
+    positioning it correctly. This only works if the popup is child of the
+    embedded widget (for example QToolButton::setMenu() requires the QMenu instance
+    to be child of the QToolButton).
+
+    \section1 Embedding a Widget with QGraphicsProxyWidget
+
+    There are two ways to embed a widget using QGraphicsProxyWidget. The most
+    common way is to pass a widget pointer to QGraphicsScene::addWidget()
+    together with any relevant \l Qt::WindowFlags. This function returns a
+    pointer to a QGraphicsProxyWidget. You can then choose to reparent or
+    position either the proxy, or the embedded widget itself.
+
+    For example, in the code snippet below, we embed a group box into the proxy:
+
+    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 1
+
+    The image below is the output obtained with its contents margin and
+    contents rect labeled.
+
+    \image qgraphicsproxywidget-embed.png
+
+    Alternatively, you can start by creating a new QGraphicsProxyWidget item,
+    and then call setWidget() to embed a QWidget later. The widget() function
+    returns a pointer to the embedded widget. QGraphicsProxyWidget shares
+    ownership with QWidget, so if either of the two widgets are destroyed, the
+    other widget will be automatically destroyed as well.
+
+    \section1 Synchronizing Widget States
+
+    QGraphicsProxyWidget keeps its state in sync with the embedded widget. For
+    example, if the proxy is hidden or disabled, the embedded widget will be
+    hidden or disabled as well, and vice versa. When the widget is embedded by
+    calling addWidget(), QGraphicsProxyWidget copies the state from the widget
+    into the proxy, and after that, the two will stay synchronized where
+    possible. By default, when you embed a widget into a proxy, both the widget
+    and the proxy will be visible because a QGraphicsWidget is visible when
+    created (you do not have to call show()). If you explicitly hide the
+    embedded widget, the proxy will also become invisible.
+
+    Example:
+
+    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 2
+
+    QGraphicsProxyWidget maintains symmetry for the following states:
+
+    \table
+    \header \o QWidget state       \o QGraphicsProxyWidget state      \o Notes
+    \row     \o QWidget::enabled
+                    \o QGraphicsProxyWidget::enabled
+                        \o
+    \row    \o QWidget::visible
+                    \o QGraphicsProxyWidget::visible
+                        \o The explicit state is also symmetric.
+    \row    \o QWidget::geometry
+                    \o QGraphicsProxyWidget::geometry
+                        \o Geometry is only guaranteed to be symmetric while
+                            the embedded widget is visible.
+    \row    \o QWidget::layoutDirection
+                    \o QGraphicsProxyWidget::layoutDirection
+                        \o
+    \row    \o QWidget::style
+                    \o QGraphicsProxyWidget::style
+                        \o
+    \row    \o QWidget::palette
+                    \o QGraphicsProxyWidget::palette
+                        \o
+    \row    \o QWidget::font
+                    \o QGraphicsProxyWidget::font
+                        \o
+    \row    \o QWidget::cursor
+                    \o QGraphicsProxyWidget::cursor
+                        \o The embedded widget overrides the proxy widget
+                            cursor. The proxy cursor changes depending on
+                            which embedded subwidget is currently under the
+                            mouse.
+    \row    \o QWidget::sizeHint()
+                    \o QGraphicsProxyWidget::sizeHint()
+                        \o All size hint functionality from the embedded
+                            widget is forwarded by the proxy.
+    \row    \o QWidget::getContentsMargins()
+                    \o QGraphicsProxyWidget::getContentsMargins()
+                        \o Updated once by setWidget().
+    \row    \o QWidget::windowTitle
+                    \o QGraphicsProxyWidget::windowTitle
+                        \o Updated once by setWidget().
+    \endtable
+
+    \note QGraphicsScene keeps the embedded widget in a special state that
+    prevents it from disturbing other widgets (both embedded and not embedded)
+    while the widget is embedded. In this state, the widget may differ slightly
+    in behavior from when it is not embedded.
+
+    \warning This class is provided for convenience when bridging
+    QWidgets and QGraphicsItems, it should not be used for
+    high-performance scenarios.
+
+    \sa QGraphicsScene::addWidget(), QGraphicsWidget
+*/
+
+extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
+extern bool qt_tab_all_widgets;
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::init()
+{
+    Q_Q(QGraphicsProxyWidget);
+    q->setFocusPolicy(Qt::WheelFocus);
+    q->setAcceptDrops(true);
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneHoverEvent *event)
+{
+    QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+    mouseEvent.setPos(event->pos());
+    mouseEvent.setScreenPos(event->screenPos());
+    mouseEvent.setButton(Qt::NoButton);
+    mouseEvent.setButtons(0);
+    mouseEvent.setModifiers(event->modifiers());
+    sendWidgetMouseEvent(&mouseEvent);
+    event->setAccepted(mouseEvent.isAccepted());
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent *event)
+{
+    if (!event || !widget || !widget->isVisible())
+        return;
+    Q_Q(QGraphicsProxyWidget);
+
+    // Find widget position and receiver.
+    QPointF pos = event->pos();
+    QPointer<QWidget> alienWidget = widget->childAt(pos.toPoint());
+    QPointer<QWidget> receiver =  alienWidget ? alienWidget : widget;
+
+    if (QWidgetPrivate::nearestGraphicsProxyWidget(receiver) != q)
+        return; //another proxywidget will handle the events
+
+    // Translate QGraphicsSceneMouse events to QMouseEvents.
+    QEvent::Type type = QEvent::None;
+    switch (event->type()) {
+    case QEvent::GraphicsSceneMousePress:
+        type = QEvent::MouseButtonPress;
+        if (!embeddedMouseGrabber)
+            embeddedMouseGrabber = receiver;
+        else
+            receiver = embeddedMouseGrabber;
+        break;
+    case QEvent::GraphicsSceneMouseRelease:
+        type = QEvent::MouseButtonRelease;
+        if (embeddedMouseGrabber)
+            receiver = embeddedMouseGrabber;
+        break;
+    case QEvent::GraphicsSceneMouseDoubleClick:
+        type = QEvent::MouseButtonDblClick;
+        if (!embeddedMouseGrabber)
+            embeddedMouseGrabber = receiver;
+        else
+            receiver = embeddedMouseGrabber;
+        break;
+    case QEvent::GraphicsSceneMouseMove:
+        type = QEvent::MouseMove;
+        if (embeddedMouseGrabber)
+            receiver = embeddedMouseGrabber;
+        break;
+    default:
+        Q_ASSERT_X(false, "QGraphicsProxyWidget", "internal error");
+        break;
+    }
+
+    if (!lastWidgetUnderMouse) {
+        QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : widget, 0);
+        lastWidgetUnderMouse = widget;
+    }
+
+    // Map event position from us to the receiver
+    pos = mapToReceiver(pos, receiver);
+
+    // Send mouse event.
+    QMouseEvent *mouseEvent = QMouseEvent::createExtendedMouseEvent(type, pos,
+                                                                    receiver->mapToGlobal(pos.toPoint()), event->button(),
+                                                                    event->buttons(), event->modifiers());
+
+    QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
+    QApplicationPrivate::sendMouseEvent(receiver, mouseEvent, alienWidget, widget,
+                                        &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous());
+    embeddedMouseGrabber = embeddedMouseGrabberPtr;
+
+    // Handle enter/leave events when last button is released from mouse
+    // grabber child widget.
+    if (embeddedMouseGrabber && type == QEvent::MouseButtonRelease && !event->buttons()) {
+        Q_Q(QGraphicsProxyWidget);
+        if (q->rect().contains(event->pos()) && q->acceptsHoverEvents())
+            lastWidgetUnderMouse = alienWidget ? alienWidget : widget;
+        else // released on the frame our outside the item, or doesn't accept hover events.
+            lastWidgetUnderMouse = 0;
+
+        QApplicationPrivate::dispatchEnterLeave(lastWidgetUnderMouse, embeddedMouseGrabber);
+        embeddedMouseGrabber = 0;
+
+#ifndef QT_NO_CURSOR
+        // ### Restore the cursor, don't override it.
+        if (!lastWidgetUnderMouse)
+            q->unsetCursor();
+#endif
+    }
+
+    event->setAccepted(mouseEvent->isAccepted());
+    delete mouseEvent;
+}
+
+void QGraphicsProxyWidgetPrivate::sendWidgetKeyEvent(QKeyEvent *event)
+{
+    Q_Q(QGraphicsProxyWidget);
+    if (!event || !widget || !widget->isVisible())
+        return;
+
+    QPointer<QWidget> receiver = widget->focusWidget();
+    if (!receiver)
+        receiver = widget;
+    Q_ASSERT(receiver);
+
+    do {
+        bool res = QApplication::sendEvent(receiver, event);
+        if ((res && event->isAccepted()) || (q->isWindow() && receiver == widget))
+            break;
+        receiver = receiver->parentWidget();
+    } while (receiver);
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::removeSubFocusHelper(QWidget *widget, Qt::FocusReason reason)
+{
+    QFocusEvent event(QEvent::FocusOut, reason);
+    QPointer<QWidget> widgetGuard = widget;
+    QApplication::sendEvent(widget, &event);
+    if (widgetGuard && event.isAccepted())
+        QApplication::sendEvent(widget->style(), &event);
+}
+
+/*!
+    \internal
+
+    Reimplemented from QGraphicsItemPrivate. ### Qt 5: Move impl to
+    reimplementation QGraphicsProxyWidget::inputMethodQuery().
+*/
+QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const
+{
+    Q_Q(const QGraphicsProxyWidget);
+    if (!widget || !q->hasFocus())
+        return QVariant();
+
+    QWidget *focusWidget = widget->focusWidget();
+    if (!focusWidget)
+        focusWidget = widget;
+    QVariant v = focusWidget->inputMethodQuery(query);
+    QPointF focusWidgetPos = q->subWidgetRect(focusWidget).topLeft();
+    switch (v.type()) {
+    case QVariant::RectF:
+        v = v.toRectF().translated(focusWidgetPos);
+        break;
+    case QVariant::PointF:
+        v = v.toPointF() + focusWidgetPos;
+        break;
+    case QVariant::Rect:
+        v = v.toRect().translated(focusWidgetPos.toPoint());
+        break;
+    case QVariant::Point:
+        v = v.toPoint() + focusWidgetPos.toPoint();
+        break;
+    default:
+        break;
+    }
+    return v;
+}
+
+/*!
+    \internal
+    Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
+*/
+QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
+{
+    if (!widget)
+        return 0;
+
+    // Run around the focus chain until we find a widget that can take tab focus.
+    if (!child) {
+	child = next ? (QWidget *)widget : widget->d_func()->focus_prev;
+    } else {
+        child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
+        if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) {
+             return 0;
+        }
+    }
+
+    QWidget *oldChild = child;
+    uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
+    do {
+        if (child->isEnabled()
+	    && child->isVisibleTo(widget)
+            && (child->focusPolicy() & focus_flag == focus_flag)
+            && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
+            return child;
+        }
+        child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
+    } while (child != oldChild && !(next && child == widget) && !(!next && child == widget->d_func()->focus_prev));
+    return 0;
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot()
+{
+    Q_Q(QGraphicsProxyWidget);
+    widget = 0;
+    delete q;
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::updateWidgetGeometryFromProxy()
+{
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
+{
+    Q_Q(QGraphicsProxyWidget);
+    if (!widget)
+        return;
+
+    QRectF widgetGeometry = widget->geometry();
+    QWidget *parentWidget = widget->parentWidget();
+    if (widget->isWindow()) {
+        QGraphicsProxyWidget *proxyParent = 0;
+        if (parentWidget && (proxyParent = qobject_cast<QGraphicsProxyWidget *>(q->parentWidget()))) {
+            // Nested window proxy (e.g., combobox popup), map widget to the
+            // parent widget's global coordinates, and map that to the parent
+            // proxy's child coordinates.
+            widgetGeometry.moveTo(proxyParent->subWidgetRect(parentWidget).topLeft()
+                                  + parentWidget->mapFromGlobal(widget->pos()));
+        }
+    }
+
+    // Adjust to size hint if the widget has never been resized.
+    if (!widget->size().isValid())
+        widgetGeometry.setSize(widget->sizeHint());
+
+    // Assign new geometry.
+    posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+    sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+    q->setGeometry(widgetGeometry);
+    posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+    sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+}
+
+/*!
+    \internal
+*/
+void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
+{
+    Q_Q(QGraphicsProxyWidget);
+    if (!widget)
+        return;
+
+    QWidget *focusWidget = widget->focusWidget();
+    if (!focusWidget)
+        focusWidget = widget;
+    q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
+               focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
+}
+
+/*!
+    \internal
+
+    Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
+    widget and a descendant of the widget managed by this proxy. A separate subproxy
+    will be created as a child of this proxy widget to manage \a subWin.
+*/
+void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
+{
+    QWExtra *extra;
+    if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
+        QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
+        subProxy->d_func()->setWidget_helper(subWin, false);
+    }
+}
+
+/*!
+    \internal
+
+    Removes ("unembeds") \a subWin and deletes the proxy holder item. This can
+    happen when QWidget::setParent() reparents the embedded window out of
+    "embedded space".
+*/
+void QGraphicsProxyWidgetPrivate::unembedSubWindow(QWidget *subWin)
+{
+    foreach (QGraphicsItem *child, children) {
+        if (child->isWidget()) {
+            if (QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))) {
+                if (proxy->widget() == subWin) {
+                    proxy->setWidget(0);
+                    scene->removeItem(proxy);
+                    delete proxy;
+                    return;
+                }
+            }
+        }
+    }
+}
+
+bool QGraphicsProxyWidgetPrivate::isProxyWidget() const
+{
+    return true;
+}
+
+/*!
+     \internal
+*/
+QPointF QGraphicsProxyWidgetPrivate::mapToReceiver(const QPointF &pos, const QWidget *receiver) const
+{
+    QPointF p = pos;
+    // Map event position from us to the receiver, preserving its
+    // precision (don't use QWidget::mapFrom here).
+    while (receiver && receiver != widget) {
+        p -= QPointF(receiver->pos());
+        receiver = receiver->parentWidget();
+    }
+    return p;
+}
+
+/*!
+    Constructs a new QGraphicsProxy widget. \a parent and \a wFlags are passed
+    to QGraphicsItem's constructor.
+*/
+QGraphicsProxyWidget::QGraphicsProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
+    : QGraphicsWidget(*new QGraphicsProxyWidgetPrivate, parent, 0, wFlags)
+{
+    Q_D(QGraphicsProxyWidget);
+    d->init();
+}
+
+/*!
+    Destroys the proxy widget and any embedded widget.
+*/
+QGraphicsProxyWidget::~QGraphicsProxyWidget()
+{
+    Q_D(QGraphicsProxyWidget);
+    if (d->widget) {
+        QObject::disconnect(d->widget, SIGNAL(destroyed()), this, SLOT(_q_removeWidgetSlot()));
+        delete d->widget;
+    }
+}
+
+/*!
+    Embeds \a widget into this proxy widget. The embedded widget must reside
+    exclusively either inside or outside of Graphics View. You cannot embed a
+    widget as long as it is is visible elsewhere in the UI, at the same time.
+
+    \a widget must be a top-level widget whose parent is 0.
+
+    When the widget is embedded, its state (e.g., visible, enabled, geometry,
+    size hints) is copied into the proxy widget. If the embedded widget is
+    explicitly hidden or disabled, the proxy widget will become explicitly
+    hidden or disabled after embedding is complete. The class documentation
+    has a full overview over the shared state.
+
+    QGraphicsProxyWidget's window flags determine whether the widget, after
+    embedding, will be given window decorations or not.
+
+    After this function returns, QGraphicsProxyWidget will keep its state
+    synchronized with that of \a widget whenever possible.
+
+    If a widget is already embedded by this proxy when this function is
+    called, that widget will first be automatically unembedded. Passing 0 for
+    the \a widget argument will only unembed the widget, and the ownership of
+    the currently embedded widget will be passed on to the caller.
+    Every child widget that are embedded will also be embedded and their proxy
+    widget destroyed.
+
+    Note that widgets with the Qt::WA_PaintOnScreen widget attribute
+    set and widgets that wrap an external application or controller
+    cannot be embedded. Examples are QGLWidget and QAxWidget.
+
+    \sa widget()
+*/
+void QGraphicsProxyWidget::setWidget(QWidget *widget)
+{
+    Q_D(QGraphicsProxyWidget);
+    d->setWidget_helper(widget, true);
+}
+
+void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow)
+{
+    Q_Q(QGraphicsProxyWidget);
+    if (newWidget == widget)
+        return;
+    if (widget) {
+        QObject::disconnect(widget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
+        widget->removeEventFilter(q);
+        widget->setAttribute(Qt::WA_DontShowOnScreen, false);
+        widget->d_func()->extra->proxyWidget = 0;
+        resolveFont(inheritedFontResolveMask);
+        resolvePalette(inheritedPaletteResolveMask);
+        widget->update();
+
+        foreach (QGraphicsItem *child, q->childItems()) {
+            if (child->d_ptr->isProxyWidget()) {
+                QGraphicsProxyWidget *childProxy = static_cast<QGraphicsProxyWidget *>(child);
+                QWidget * parent = childProxy->widget();
+                while (parent->parentWidget() != 0) {
+                    if (parent == widget)
+                        break;
+                    parent = parent->parentWidget();
+                }
+                if (!childProxy->widget() || parent != widget)
+                    continue;
+                childProxy->setWidget(0);
+                delete childProxy;
+            }
+        }
+
+        widget = 0;
+#ifndef QT_NO_CURSOR
+        q->unsetCursor();
+#endif
+        q->setAcceptHoverEvents(false);
+        if (!newWidget)
+            q->update();
+    }
+    if (!newWidget)
+        return;
+    if (!newWidget->isWindow()) {
+        QWExtra *extra = newWidget->parentWidget()->d_func()->extra;
+        if (!extra || !extra->proxyWidget)  {
+            qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p "
+                     "which is not a toplevel widget, and is not a child of an embedded widget", newWidget);
+            return;
+        }
+    }
+
+    // Register this proxy within the widget's private.
+    // ### This is a bit backdoorish
+    QWExtra *extra = newWidget->d_func()->extra;
+    if (!extra) {
+        newWidget->d_func()->createExtra();
+        extra = newWidget->d_func()->extra;
+    }
+    QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;
+    if (*proxyWidget) {
+        if (*proxyWidget != q) {
+            qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"
+                        "; already embedded", newWidget);
+        }
+        return;
+    }
+    *proxyWidget = q;
+
+    newWidget->setAttribute(Qt::WA_DontShowOnScreen);
+    newWidget->ensurePolished();
+    // Do not wait for this widget to close before the app closes ###
+    // shouldn't this widget inherit the attribute?
+    newWidget->setAttribute(Qt::WA_QuitOnClose, false);
+    q->setAcceptHoverEvents(true);
+
+    if (newWidget->testAttribute(Qt::WA_NoSystemBackground))
+        q->setAttribute(Qt::WA_NoSystemBackground);
+    if (newWidget->testAttribute(Qt::WA_OpaquePaintEvent))
+        q->setAttribute(Qt::WA_OpaquePaintEvent);
+
+    widget = newWidget;
+
+    // Changes only go from the widget to the proxy.
+    enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+    visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+    posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+    sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+
+    if ((autoShow && !newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide)) || !newWidget->testAttribute(Qt::WA_WState_Hidden)) {
+        newWidget->show();
+    }
+
+    // Copy the state from the widget onto the proxy.
+#ifndef QT_NO_CURSOR
+    if (newWidget->testAttribute(Qt::WA_SetCursor))
+        q->setCursor(widget->cursor());
+#endif
+    q->setEnabled(newWidget->isEnabled());
+    q->setVisible(newWidget->isVisible());
+    q->setLayoutDirection(newWidget->layoutDirection());
+    if (newWidget->testAttribute(Qt::WA_SetStyle))
+        q->setStyle(widget->style());
+
+    resolveFont(inheritedFontResolveMask);
+    resolvePalette(inheritedPaletteResolveMask);
+
+    if (!newWidget->testAttribute(Qt::WA_Resized))
+        newWidget->adjustSize();
+
+    int left, top, right, bottom;
+    newWidget->getContentsMargins(&left, &top, &right, &bottom);
+    q->setContentsMargins(left, top, right, bottom);
+    q->setWindowTitle(newWidget->windowTitle());
+
+    // size policies and constraints..
+    q->setSizePolicy(newWidget->sizePolicy());
+    QSize sz = newWidget->minimumSize();
+    q->setMinimumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
+    sz = newWidget->maximumSize();
+    q->setMaximumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
+
+    updateProxyGeometryFromWidget();
+
+    updateProxyInputMethodAcceptanceFromWidget();
+
+    // Hook up the event filter to keep the state up to date.
+    newWidget->installEventFilter(q);
+    QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
+
+    // Changes no longer go only from the widget to the proxy.
+    enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+    visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+    posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+    sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+}
+
+/*!
+    Returns a pointer to the embedded widget.
+
+    \sa setWidget()
+*/
+QWidget *QGraphicsProxyWidget::widget() const
+{
+    Q_D(const QGraphicsProxyWidget);
+    return d->widget;
+}
+
+/*!
+    Returns the rectangle for \a widget, which must be a descendant of
+    widget(), or widget() itself, in this proxy item's local coordinates.
+
+    If no widget is embedded, \a widget is 0, or \a widget is not a
+    descendant of the embedded widget, this function returns an empty QRectF.
+
+    \sa widget()
+*/
+QRectF QGraphicsProxyWidget::subWidgetRect(const QWidget *widget) const
+{
+    Q_D(const QGraphicsProxyWidget);
+    if (!widget || !d->widget)
+        return QRectF();
+    if (d->widget == widget || d->widget->isAncestorOf(widget))
+        return QRectF(widget->mapTo(d->widget, QPoint(0, 0)), widget->size());
+    return QRectF();
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::setGeometry(const QRectF &rect)
+{
+    Q_D(QGraphicsProxyWidget);
+    bool proxyResizesWidget = !d->posChangeMode && !d->sizeChangeMode;
+    if (proxyResizesWidget) {
+        d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+        d->sizeChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+    }
+    QGraphicsWidget::setGeometry(rect);
+    if (proxyResizesWidget) {
+        d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+        d->sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+    }
+}
+
+/*!
+    \reimp
+*/
+QVariant QGraphicsProxyWidget::itemChange(GraphicsItemChange change,
+                                          const QVariant &value)
+{
+    Q_D(QGraphicsProxyWidget);
+
+    switch (change) {
+    case ItemPositionChange:
+        // The item's position is either changed directly on the proxy, in
+        // which case the position change should propagate to the widget,
+        // otherwise it happens as a side effect when filtering QEvent::Move.
+        if (!d->posChangeMode)
+            d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+        break;
+    case ItemPositionHasChanged:
+        // Move the internal widget if we're in widget-to-proxy
+        // mode. Otherwise the widget has already moved.
+        if (d->widget && d->posChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
+            d->widget->move(value.toPoint());
+        if (d->posChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
+            d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+        break;
+    case ItemVisibleChange:
+        if (!d->visibleChangeMode)
+            d->visibleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+        break;
+    case ItemVisibleHasChanged:
+        if (d->widget && d->visibleChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
+            d->widget->setVisible(isVisible());
+        if (d->visibleChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
+            d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+        break;
+    case ItemEnabledChange:
+        if (!d->enabledChangeMode)
+            d->enabledChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+        break;
+    case ItemEnabledHasChanged:
+        if (d->widget && d->enabledChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
+            d->widget->setEnabled(isEnabled());
+        if (d->enabledChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
+            d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+        break;
+    default:
+        break;
+    }
+    return QGraphicsWidget::itemChange(change, value);
+}
+
+/*!
+    \reimp
+*/
+bool QGraphicsProxyWidget::event(QEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+    if (!d->widget)
+        return QGraphicsWidget::event(event);
+
+    switch (event->type()) {
+    case QEvent::StyleChange:
+        // Propagate style changes to the embedded widget.
+        if (!d->styleChangeMode) {
+            d->styleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
+            d->widget->setStyle(style());
+            d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+        }
+        break;
+    case QEvent::FontChange: {
+        // Propagate to widget.
+        QWidgetPrivate *wd = d->widget->d_func();
+        int mask = d->font.resolve() | d->inheritedFontResolveMask;
+        wd->inheritedFontResolveMask = mask;
+        wd->resolveFont();
+        break;
+    }
+    case QEvent::PaletteChange: {
+        // Propagate to widget.
+        QWidgetPrivate *wd = d->widget->d_func();
+        int mask = d->palette.resolve() | d->inheritedPaletteResolveMask;
+        wd->inheritedPaletteResolveMask = mask;
+        wd->resolvePalette();
+        break;
+    }
+    case QEvent::InputMethod: {
+        // Forward input method events if the focus widget enables
+        // input methods.
+        // ### Qt 4.5: this code must also go into a reimplementation
+        // of inputMethodEvent().
+        QWidget *focusWidget = d->widget->focusWidget();
+        if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
+            QApplication::sendEvent(focusWidget, event);
+        break;
+    }
+    case QEvent::ShortcutOverride: {
+        QWidget *focusWidget = d->widget->focusWidget();
+        while (focusWidget) {
+            QApplication::sendEvent(focusWidget, event);
+            if (event->isAccepted())
+                return true;
+            focusWidget = focusWidget->parentWidget();
+        }
+        return false;
+    }
+    case QEvent::KeyPress: {
+        QKeyEvent *k = static_cast<QKeyEvent *>(event);
+        if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
+            if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
+                QWidget *focusWidget = d->widget->focusWidget();
+                while (focusWidget) {
+                    bool res = QApplication::sendEvent(focusWidget, event);
+                    if ((res && event->isAccepted()) || (isWindow() && focusWidget == d->widget)) {
+                        event->accept();
+                        break;
+                    }
+                    focusWidget = focusWidget->parentWidget();
+                }
+                return true;
+            }
+        }
+        break;
+    }
+    default:
+        break;
+    }
+    return QGraphicsWidget::event(event);
+}
+
+/*!
+    \reimp
+*/
+bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+
+    if (object == d->widget) {
+        switch (event->type()) {
+        case QEvent::LayoutRequest:
+            updateGeometry();
+            break;
+         case QEvent::Resize:
+             // If the widget resizes itself, we resize the proxy too.
+             // Prevent feed-back by checking the geometry change mode.
+             if (!d->sizeChangeMode)
+                 d->updateProxyGeometryFromWidget();
+            break;
+         case QEvent::Move:
+             // If the widget moves itself, we move the proxy too.  Prevent
+             // feed-back by checking the geometry change mode.
+             if (!d->posChangeMode)
+                 d->updateProxyGeometryFromWidget();
+            break;
+        case QEvent::Hide:
+        case QEvent::Show:
+            // If the widget toggles its visible state, the proxy will follow.
+            if (!d->visibleChangeMode) {
+                d->visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+                setVisible(event->type() == QEvent::Show);
+                d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+            }
+            break;
+        case QEvent::EnabledChange:
+            // If the widget toggles its enabled state, the proxy will follow.
+            if (!d->enabledChangeMode) {
+                d->enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+                setEnabled(d->widget->isEnabled());
+                d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+            }
+            break;
+        case QEvent::StyleChange:
+            // Propagate style changes to the proxy.
+            if (!d->styleChangeMode) {
+                d->styleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
+                setStyle(d->widget->style());
+                d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    return QGraphicsWidget::eventFilter(object, event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::showEvent(QShowEvent *event)
+{
+    Q_UNUSED(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::hideEvent(QHideEvent *event)
+{
+    Q_UNUSED(event);
+}
+
+#ifndef QT_NO_CONTEXTMENU
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+    if (!event || !d->widget || !d->widget->isVisible() || !hasFocus())
+        return;
+
+    // Find widget position and receiver.
+    QPointF pos = event->pos();
+    QPointer<QWidget> alienWidget = d->widget->childAt(pos.toPoint());
+    QPointer<QWidget> receiver =  alienWidget ? alienWidget : d->widget;
+
+    // Map event position from us to the receiver
+    pos = d->mapToReceiver(pos, receiver);
+
+    // Send mouse event. ### Doesn't propagate the event.
+    QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()),
+                                       pos.toPoint(), receiver->mapToGlobal(pos.toPoint()), event->modifiers());
+    QApplication::sendEvent(receiver, &contextMenuEvent);
+
+    event->setAccepted(contextMenuEvent.isAccepted());
+}
+#endif // QT_NO_CONTEXTMENU
+
+#ifndef QT_NO_DRAGANDDROP
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
+{
+#ifdef QT_NO_DRAGANDDROP
+    Q_UNUSED(event);
+#else
+    Q_D(QGraphicsProxyWidget);
+    if (!d->widget)
+        return;
+
+    QDragEnterEvent proxyDragEnter(event->pos().toPoint(), event->dropAction(), event->mimeData(), event->buttons(), event->modifiers());
+    proxyDragEnter.setAccepted(event->isAccepted());
+    QApplication::sendEvent(d->widget, &proxyDragEnter);
+    event->setAccepted(proxyDragEnter.isAccepted());
+    if (proxyDragEnter.isAccepted())    // we discard answerRect
+        event->setDropAction(proxyDragEnter.dropAction());
+#endif
+}
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
+{
+    Q_UNUSED(event);
+#ifndef QT_NO_DRAGANDDROP
+    Q_D(QGraphicsProxyWidget);
+    if (!d->widget || !d->dragDropWidget)
+        return;
+    QDragLeaveEvent proxyDragLeave;
+    QApplication::sendEvent(d->dragDropWidget, &proxyDragLeave);
+    d->dragDropWidget = 0;
+#endif
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
+{
+#ifdef QT_NO_DRAGANDDROP
+    Q_UNUSED(event);
+#else
+    Q_D(QGraphicsProxyWidget);
+    if (!d->widget)
+        return;
+    QPointF p = event->pos();
+    event->ignore();
+    QPointer<QWidget> subWidget = d->widget->childAt(p.toPoint());
+    QPointer<QWidget> receiver =  subWidget ? subWidget : d->widget;
+    bool eventDelivered = false;
+    for (; receiver; receiver = receiver->parentWidget()) {
+        if (!receiver->isEnabled() || !receiver->acceptDrops())
+            continue;
+        // Map event position from us to the receiver
+        QPoint receiverPos = d->mapToReceiver(p, receiver).toPoint();
+        if (receiver != d->dragDropWidget) {
+            // Try to enter before we leave
+            QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
+            dragEnter.setDropAction(event->proposedAction());
+            QApplication::sendEvent(receiver, &dragEnter);
+            event->setAccepted(dragEnter.isAccepted());
+            event->setDropAction(dragEnter.dropAction());
+            if (!event->isAccepted()) {
+                // propagate to the parent widget
+                continue;
+            }
+
+            d->lastDropAction = event->dropAction();
+
+            if (d->dragDropWidget) {
+                QDragLeaveEvent dragLeave;
+                QApplication::sendEvent(d->dragDropWidget, &dragLeave);
+            }
+            d->dragDropWidget = receiver;
+        }
+
+        QDragMoveEvent dragMove(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
+        event->setDropAction(d->lastDropAction);
+        QApplication::sendEvent(receiver, &dragMove);
+        event->setAccepted(dragMove.isAccepted());
+        event->setDropAction(dragMove.dropAction());
+        if (event->isAccepted())
+            d->lastDropAction = event->dropAction();
+        eventDelivered = true;
+        break;
+    }
+
+    if (!eventDelivered) {
+        if (d->dragDropWidget) {
+            // Leave the last drag drop item
+            QDragLeaveEvent dragLeave;
+            QApplication::sendEvent(d->dragDropWidget, &dragLeave);
+            d->dragDropWidget = 0;
+        }
+        // Propagate
+        event->setDropAction(Qt::IgnoreAction);
+    }
+#endif
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
+{
+#ifdef QT_NO_DRAGANDDROP
+    Q_UNUSED(event);
+#else
+    Q_D(QGraphicsProxyWidget);
+    if (d->widget && d->dragDropWidget) {
+        QPoint widgetPos = d->mapToReceiver(event->pos(), d->dragDropWidget).toPoint();
+        QDropEvent dropEvent(widgetPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
+        QApplication::sendEvent(d->dragDropWidget, &dropEvent);
+        event->setAccepted(dropEvent.isAccepted());
+        d->dragDropWidget = 0;
+    }
+#endif
+}
+#endif
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_UNUSED(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_UNUSED(event);
+    Q_D(QGraphicsProxyWidget);
+    // If hoverMove was compressed away, make sure we update properly here.
+    if (d->lastWidgetUnderMouse) {
+        QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
+        d->lastWidgetUnderMouse = 0;
+    }
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::hoverMoveEvent";
+#endif
+    // Ignore events on the window frame.
+    if (!d->widget || !rect().contains(event->pos())) {
+        if (d->lastWidgetUnderMouse) {
+            QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
+            d->lastWidgetUnderMouse = 0;
+        }
+        return;
+    }
+
+    d->embeddedMouseGrabber = 0;
+    d->sendWidgetMouseEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::grabMouseEvent(QEvent *event)
+{
+    Q_UNUSED(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::ungrabMouseEvent(QEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+    Q_UNUSED(event);
+    d->embeddedMouseGrabber = 0;
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::mouseMoveEvent";
+#endif
+    d->sendWidgetMouseEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::mousePressEvent";
+#endif
+    d->sendWidgetMouseEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::mouseDoubleClickEvent";
+#endif
+    d->sendWidgetMouseEvent(event);
+}
+
+/*!
+    \reimp
+*/
+#ifndef QT_NO_WHEELEVENT
+void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::wheelEvent";
+#endif
+    if (!d->widget)
+        return;
+
+    QPointF pos = event->pos();
+    QPointer<QWidget> receiver = d->widget->childAt(pos.toPoint());
+    if (!receiver)
+        receiver = d->widget;
+
+    // Map event position from us to the receiver
+    pos = d->mapToReceiver(pos, receiver);
+
+    // Send mouse event.
+    QWheelEvent wheelEvent(pos.toPoint(), event->screenPos(), event->delta(),
+                           event->buttons(), event->modifiers(), event->orientation());
+    QPointer<QWidget> focusWidget = d->widget->focusWidget();
+    extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
+    qt_sendSpontaneousEvent(receiver, &wheelEvent);
+    event->setAccepted(wheelEvent.isAccepted());
+
+    // ### Remove, this should be done by proper focusIn/focusOut events.
+    if (focusWidget && !focusWidget->hasFocus()) {
+        focusWidget->update();
+        focusWidget = d->widget->focusWidget();
+        if (focusWidget && focusWidget->hasFocus())
+            focusWidget->update();
+    }
+}
+#endif
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::mouseReleaseEvent";
+#endif
+    d->sendWidgetMouseEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::keyPressEvent(QKeyEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::keyPressEvent";
+#endif
+    d->sendWidgetKeyEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::keyReleaseEvent(QKeyEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::keyReleaseEvent";
+#endif
+    d->sendWidgetKeyEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
+{
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::focusInEvent";
+#endif
+    Q_D(QGraphicsProxyWidget);
+
+    if (d->focusFromWidgetToProxy) {
+        // Prevent recursion when the proxy autogains focus through the
+        // embedded widget calling setFocus(). ### Could be done with event
+        // filter on FocusIn instead?
+        return;
+    }
+
+    switch (event->reason()) {
+    case Qt::TabFocusReason: {
+	if (QWidget *focusChild = d->findFocusChild(0, true))
+            focusChild->setFocus(event->reason());
+        break;
+    }
+    case Qt::BacktabFocusReason:
+	if (QWidget *focusChild = d->findFocusChild(0, false))
+            focusChild->setFocus(event->reason());
+        break;
+    default:
+	if (d->widget && d->widget->focusWidget()) {
+	    d->widget->focusWidget()->setFocus(event->reason());
+	    return;
+        }
+        break;
+    }
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::focusOutEvent(QFocusEvent *event)
+{
+#ifdef GRAPHICSPROXYWIDGET_DEBUG
+    qDebug() << "QGraphicsProxyWidget::focusOutEvent";
+#endif
+    Q_D(QGraphicsProxyWidget);
+    if (d->widget) {
+        // We need to explicitly remove subfocus from the embedded widget's
+        // focus widget.
+        if (QWidget *focusWidget = d->widget->focusWidget())
+            d->removeSubFocusHelper(focusWidget, event->reason());
+    }
+}
+
+/*!
+    \reimp
+*/
+bool QGraphicsProxyWidget::focusNextPrevChild(bool next)
+{
+    Q_D(QGraphicsProxyWidget);
+    if (!d->widget || !d->scene)
+        return QGraphicsWidget::focusNextPrevChild(next);
+
+    Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
+    QWidget *lastFocusChild = d->widget->focusWidget();
+    if (QWidget *newFocusChild = d->findFocusChild(lastFocusChild, next)) {
+	newFocusChild->setFocus(reason);
+	return true;
+    }
+
+    return QGraphicsWidget::focusNextPrevChild(next);
+}
+
+/*!
+    \reimp
+*/
+QSizeF QGraphicsProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+    Q_D(const QGraphicsProxyWidget);
+    if (!d->widget)
+        return QGraphicsWidget::sizeHint(which, constraint);
+
+    QSizeF sh;
+    switch (which) {
+    case Qt::PreferredSize:
+        if (QLayout *l = d->widget->layout())
+            sh = l->sizeHint();
+        else
+            sh = d->widget->sizeHint();
+        break;
+    case Qt::MinimumSize:
+        if (QLayout *l = d->widget->layout())
+            sh = l->minimumSize();
+        else
+            sh = d->widget->minimumSizeHint();
+        break;
+    case Qt::MaximumSize:
+        if (QLayout *l = d->widget->layout())
+            sh = l->maximumSize();
+        else
+            sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+        break;
+    case Qt::MinimumDescent:
+        sh = constraint;
+        break;
+    default:
+        break;
+    }
+    return sh;
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
+{
+    Q_D(QGraphicsProxyWidget);
+    if (d->widget) {
+        if (d->sizeChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
+            d->widget->resize(event->newSize().toSize());
+    }
+    QGraphicsWidget::resizeEvent(event);
+}
+
+/*!
+    \reimp
+*/
+void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    Q_D(QGraphicsProxyWidget);
+    Q_UNUSED(widget);
+    if (!d->widget || !d->widget->isVisible())
+        return;
+
+    // Filter out repaints on the window frame.
+    const QRect exposedWidgetRect = (option->exposedRect & rect()).toRect();
+    if (exposedWidgetRect.isEmpty())
+        return;
+
+    // Disable QPainter's default pen being cosmetic. This allows widgets and
+    // styles to follow Qt's existing defaults without getting ugly cosmetic
+    // lines when scaled.
+    bool restore = !(painter->renderHints() & QPainter::NonCosmeticDefaultPen);
+    painter->setRenderHints(QPainter::NonCosmeticDefaultPen, true);
+
+    d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect);
+
+    // Restore the render hints if necessary.
+    if (restore)
+        painter->setRenderHints(QPainter::NonCosmeticDefaultPen, false);
+}
+
+/*!
+    \reimp
+*/
+int QGraphicsProxyWidget::type() const
+{
+    return Type;
+}
+
+/*!
+  \since 4.5
+
+  Creates a proxy widget for the given \a child of the widget
+  contained in this proxy.
+
+  This function makes it possible to aquire proxies for
+  non top-level widgets. For instance, you can embed a dialog,
+  and then transform only one of its widgets.
+
+  If the widget is already embedded, return the existing proxy widget.
+
+  \sa newProxyWidget(), QGraphicsScene::addWidget()
+*/
+QGraphicsProxyWidget *QGraphicsProxyWidget::createProxyForChildWidget(QWidget *child)
+{
+    QGraphicsProxyWidget *proxy = child->graphicsProxyWidget();
+    if (proxy)
+        return proxy;
+    if (!child->parentWidget()) {
+        qWarning("QGraphicsProxyWidget::createProxyForChildWidget: top-level widget not in a QGraphicsScene");
+        return 0;
+    }
+
+    QGraphicsProxyWidget *parentProxy = createProxyForChildWidget(child->parentWidget());
+    if (!parentProxy)
+        return 0;
+
+    if (!QMetaObject::invokeMethod(parentProxy, "newProxyWidget",  Qt::DirectConnection,
+         Q_RETURN_ARG(QGraphicsProxyWidget*, proxy), Q_ARG(const QWidget*, child)))
+        return 0;
+    proxy->setParent(parentProxy);
+    proxy->setWidget(child);
+    return proxy;
+}
+
+/*!
+  \fn QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *child)
+  \since 4.5
+
+  Creates a proxy widget for the given \a child of the widget contained in this
+  proxy.
+
+  You should not call this function directly; use
+  QGraphicsProxyWidget::createProxyForChildWidget() instead.
+
+  This function is a fake virtual slot that you can reimplement in
+  your subclass in order to control how new proxy widgets are
+  created. The default implementation returns a proxy created with
+  the QGraphicsProxyWidget() constructor with this proxy widget as
+  the parent.
+
+  \sa createProxyForChildWidget()
+*/
+QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *)
+{
+    return new QGraphicsProxyWidget(this);
+}
+
+
+
+QT_END_NAMESPACE
+
+#include "moc_qgraphicsproxywidget.cpp"
+
+#endif //QT_NO_GRAPHICSVIEW