Merge remote-tracking branch 'origin/master' into refactor
[profile/ivi/qtbase.git] / src / widgets / graphicsview / qgraphicsproxywidget.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qglobal.h"
43
44 #ifndef QT_NO_GRAPHICSVIEW
45
46 #include "qgraphicslayout.h"
47 #include "qgraphicsproxywidget.h"
48 #include "private/qgraphicsproxywidget_p.h"
49 #include "private/qwidget_p.h"
50 #include "private/qapplication_p.h"
51
52 #include <QtCore/qdebug.h>
53 #include <QtGui/qevent.h>
54 #include <QtWidgets/qgraphicsscene.h>
55 #include <QtWidgets/qgraphicssceneevent.h>
56 #include <QtWidgets/qlayout.h>
57 #include <QtGui/qpainter.h>
58 #include <QtWidgets/qstyleoption.h>
59 #include <QtWidgets/qgraphicsview.h>
60 #include <QtWidgets/qlistview.h>
61 #include <QtWidgets/qlineedit.h>
62 #include <QtWidgets/qtextedit.h>
63
64 QT_BEGIN_NAMESPACE
65
66 //#define GRAPHICSPROXYWIDGET_DEBUG
67
68 /*!
69     \class QGraphicsProxyWidget
70     \brief The QGraphicsProxyWidget class provides a proxy layer for embedding
71     a QWidget in a QGraphicsScene.
72     \since 4.4
73     \ingroup graphicsview-api
74
75     QGraphicsProxyWidget embeds QWidget-based widgets, for example, a
76     QPushButton, QFontComboBox, or even QFileDialog, into
77     QGraphicsScene. It forwards events between the two objects and
78     translates between QWidget's integer-based geometry and
79     QGraphicsWidget's qreal-based geometry. QGraphicsProxyWidget
80     supports all core features of QWidget, including tab focus,
81     keyboard input, Drag & Drop, and popups.  You can also embed
82     complex widgets, e.g., widgets with subwidgets.
83
84     Example:
85
86     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 0
87
88     QGraphicsProxyWidget takes care of automatically embedding popup children
89     of embedded widgets through creating a child proxy for each popup. This
90     means that when an embedded QComboBox shows its popup list, a new
91     QGraphicsProxyWidget is created automatically, embedding the popup, and
92     positioning it correctly. This only works if the popup is child of the
93     embedded widget (for example QToolButton::setMenu() requires the QMenu instance
94     to be child of the QToolButton).
95
96     \section1 Embedding a Widget with QGraphicsProxyWidget
97
98     There are two ways to embed a widget using QGraphicsProxyWidget. The most
99     common way is to pass a widget pointer to QGraphicsScene::addWidget()
100     together with any relevant \l Qt::WindowFlags. This function returns a
101     pointer to a QGraphicsProxyWidget. You can then choose to reparent or
102     position either the proxy, or the embedded widget itself.
103
104     For example, in the code snippet below, we embed a group box into the proxy:
105
106     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 1
107
108     The image below is the output obtained with its contents margin and
109     contents rect labeled.
110
111     \image qgraphicsproxywidget-embed.png
112
113     Alternatively, you can start by creating a new QGraphicsProxyWidget item,
114     and then call setWidget() to embed a QWidget later. The widget() function
115     returns a pointer to the embedded widget. QGraphicsProxyWidget shares
116     ownership with QWidget, so if either of the two widgets are destroyed, the
117     other widget will be automatically destroyed as well.
118
119     \section1 Synchronizing Widget States
120
121     QGraphicsProxyWidget keeps its state in sync with the embedded widget. For
122     example, if the proxy is hidden or disabled, the embedded widget will be
123     hidden or disabled as well, and vice versa. When the widget is embedded by
124     calling addWidget(), QGraphicsProxyWidget copies the state from the widget
125     into the proxy, and after that, the two will stay synchronized where
126     possible. By default, when you embed a widget into a proxy, both the widget
127     and the proxy will be visible because a QGraphicsWidget is visible when
128     created (you do not have to call show()). If you explicitly hide the
129     embedded widget, the proxy will also become invisible.
130
131     Example:
132
133     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 2
134
135     QGraphicsProxyWidget maintains symmetry for the following states:
136
137     \table
138     \header \o QWidget state       \o QGraphicsProxyWidget state      \o Notes
139     \row     \o QWidget::enabled
140                     \o QGraphicsProxyWidget::enabled
141                         \o
142     \row    \o QWidget::visible
143                     \o QGraphicsProxyWidget::visible
144                         \o The explicit state is also symmetric.
145     \row    \o QWidget::geometry
146                     \o QGraphicsProxyWidget::geometry
147                         \o Geometry is only guaranteed to be symmetric while
148                             the embedded widget is visible.
149     \row    \o QWidget::layoutDirection
150                     \o QGraphicsProxyWidget::layoutDirection
151                         \o
152     \row    \o QWidget::style
153                     \o QGraphicsProxyWidget::style
154                         \o
155     \row    \o QWidget::palette
156                     \o QGraphicsProxyWidget::palette
157                         \o
158     \row    \o QWidget::font
159                     \o QGraphicsProxyWidget::font
160                         \o
161     \row    \o QWidget::cursor
162                     \o QGraphicsProxyWidget::cursor
163                         \o The embedded widget overrides the proxy widget
164                             cursor. The proxy cursor changes depending on
165                             which embedded subwidget is currently under the
166                             mouse.
167     \row    \o QWidget::sizeHint()
168                     \o QGraphicsProxyWidget::sizeHint()
169                         \o All size hint functionality from the embedded
170                             widget is forwarded by the proxy.
171     \row    \o QWidget::getContentsMargins()
172                     \o QGraphicsProxyWidget::getContentsMargins()
173                         \o Updated once by setWidget().
174     \row    \o QWidget::windowTitle
175                     \o QGraphicsProxyWidget::windowTitle
176                         \o Updated once by setWidget().
177     \endtable
178
179     \note QGraphicsScene keeps the embedded widget in a special state that
180     prevents it from disturbing other widgets (both embedded and not embedded)
181     while the widget is embedded. In this state, the widget may differ slightly
182     in behavior from when it is not embedded.
183
184     \warning This class is provided for convenience when bridging
185     QWidgets and QGraphicsItems, it should not be used for
186     high-performance scenarios.
187
188     \sa QGraphicsScene::addWidget(), QGraphicsWidget
189 */
190
191 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
192 Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets;
193
194 /*!
195     \internal
196 */
197 void QGraphicsProxyWidgetPrivate::init()
198 {
199     Q_Q(QGraphicsProxyWidget);
200     q->setFocusPolicy(Qt::WheelFocus);
201     q->setAcceptDrops(true);
202 }
203
204 /*!
205     \internal
206 */
207 void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneHoverEvent *event)
208 {
209     QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
210     mouseEvent.setPos(event->pos());
211     mouseEvent.setScreenPos(event->screenPos());
212     mouseEvent.setButton(Qt::NoButton);
213     mouseEvent.setButtons(0);
214     mouseEvent.setModifiers(event->modifiers());
215     sendWidgetMouseEvent(&mouseEvent);
216     event->setAccepted(mouseEvent.isAccepted());
217 }
218
219 /*!
220     \internal
221 */
222 void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent *event)
223 {
224     if (!event || !widget || !widget->isVisible())
225         return;
226     Q_Q(QGraphicsProxyWidget);
227
228     // Find widget position and receiver.
229     QPointF pos = event->pos();
230     QPointer<QWidget> alienWidget = widget->childAt(pos.toPoint());
231     QPointer<QWidget> receiver =  alienWidget ? alienWidget : widget;
232
233     if (QWidgetPrivate::nearestGraphicsProxyWidget(receiver) != q)
234         return; //another proxywidget will handle the events
235
236     // Translate QGraphicsSceneMouse events to QMouseEvents.
237     QEvent::Type type = QEvent::None;
238     switch (event->type()) {
239     case QEvent::GraphicsSceneMousePress:
240         type = QEvent::MouseButtonPress;
241         if (!embeddedMouseGrabber)
242             embeddedMouseGrabber = receiver;
243         else
244             receiver = embeddedMouseGrabber;
245         break;
246     case QEvent::GraphicsSceneMouseRelease:
247         type = QEvent::MouseButtonRelease;
248         if (embeddedMouseGrabber)
249             receiver = embeddedMouseGrabber;
250         break;
251     case QEvent::GraphicsSceneMouseDoubleClick:
252         type = QEvent::MouseButtonDblClick;
253         if (!embeddedMouseGrabber)
254             embeddedMouseGrabber = receiver;
255         else
256             receiver = embeddedMouseGrabber;
257         break;
258     case QEvent::GraphicsSceneMouseMove:
259         type = QEvent::MouseMove;
260         if (embeddedMouseGrabber)
261             receiver = embeddedMouseGrabber;
262         break;
263     default:
264         Q_ASSERT_X(false, "QGraphicsProxyWidget", "internal error");
265         break;
266     }
267
268     if (!lastWidgetUnderMouse) {
269         QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : receiver, 0);
270         lastWidgetUnderMouse = receiver;
271     }
272
273     // Map event position from us to the receiver
274     pos = mapToReceiver(pos, receiver);
275
276     // Send mouse event.
277     QMouseEvent mouseEvent(type, pos,
278                            receiver->mapToGlobal(pos.toPoint()), event->button(),
279                            event->buttons(), event->modifiers());
280
281     QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
282     QApplicationPrivate::sendMouseEvent(receiver, &mouseEvent, alienWidget, widget,
283                                         &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous());
284     embeddedMouseGrabber = embeddedMouseGrabberPtr;
285
286     // Handle enter/leave events when last button is released from mouse
287     // grabber child widget.
288     if (embeddedMouseGrabber && type == QEvent::MouseButtonRelease && !event->buttons()) {
289         Q_Q(QGraphicsProxyWidget);
290         if (q->rect().contains(event->pos()) && q->acceptsHoverEvents())
291             lastWidgetUnderMouse = alienWidget ? alienWidget : widget;
292         else // released on the frame our outside the item, or doesn't accept hover events.
293             lastWidgetUnderMouse = 0;
294
295         QApplicationPrivate::dispatchEnterLeave(lastWidgetUnderMouse, embeddedMouseGrabber);
296         embeddedMouseGrabber = 0;
297
298 #ifndef QT_NO_CURSOR
299         // ### Restore the cursor, don't override it.
300         if (!lastWidgetUnderMouse)
301             q->unsetCursor();
302 #endif
303     }
304
305     event->setAccepted(mouseEvent.isAccepted());
306 }
307
308 void QGraphicsProxyWidgetPrivate::sendWidgetKeyEvent(QKeyEvent *event)
309 {
310     Q_Q(QGraphicsProxyWidget);
311     if (!event || !widget || !widget->isVisible())
312         return;
313
314     QPointer<QWidget> receiver = widget->focusWidget();
315     if (!receiver)
316         receiver = widget;
317     Q_ASSERT(receiver);
318
319     do {
320         bool res = QApplication::sendEvent(receiver, event);
321         if ((res && event->isAccepted()) || (q->isWindow() && receiver == widget))
322             break;
323         receiver = receiver->parentWidget();
324     } while (receiver);
325 }
326
327 /*!
328     \internal
329 */
330 void QGraphicsProxyWidgetPrivate::removeSubFocusHelper(QWidget *widget, Qt::FocusReason reason)
331 {
332     QFocusEvent event(QEvent::FocusOut, reason);
333     QPointer<QWidget> widgetGuard = widget;
334     QApplication::sendEvent(widget, &event);
335     if (widgetGuard && event.isAccepted())
336         QApplication::sendEvent(widget->style(), &event);
337 }
338
339 /*!
340     \internal
341
342     Reimplemented from QGraphicsItemPrivate. ### Qt 5: Move impl to
343     reimplementation QGraphicsProxyWidget::inputMethodQuery().
344 */
345 QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const
346 {
347     Q_Q(const QGraphicsProxyWidget);
348     if (!widget || !q->hasFocus())
349         return QVariant();
350
351     QWidget *focusWidget = widget->focusWidget();
352     if (!focusWidget)
353         focusWidget = widget;
354     QVariant v = focusWidget->inputMethodQuery(query);
355     QPointF focusWidgetPos = q->subWidgetRect(focusWidget).topLeft();
356     switch (v.type()) {
357     case QVariant::RectF:
358         v = v.toRectF().translated(focusWidgetPos);
359         break;
360     case QVariant::PointF:
361         v = v.toPointF() + focusWidgetPos;
362         break;
363     case QVariant::Rect:
364         v = v.toRect().translated(focusWidgetPos.toPoint());
365         break;
366     case QVariant::Point:
367         v = v.toPoint() + focusWidgetPos.toPoint();
368         break;
369     default:
370         break;
371     }
372     return v;
373 }
374
375 /*!
376     \internal
377     Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
378 */
379 QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
380 {
381     if (!widget)
382         return 0;
383
384     // Run around the focus chain until we find a widget that can take tab focus.
385     if (!child) {
386         child = next ? (QWidget *)widget : widget->d_func()->focus_prev;
387     } else {
388         child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
389         if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) {
390              return 0;
391         }
392     }
393
394     QWidget *oldChild = child;
395     uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
396     do {
397         if (child->isEnabled()
398             && child->isVisibleTo(widget)
399             && ((child->focusPolicy() & focus_flag) == focus_flag)
400             && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
401             return child;
402         }
403         child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
404     } while (child != oldChild && !(next && child == widget) && !(!next && child == widget->d_func()->focus_prev));
405     return 0;
406 }
407
408 /*!
409     \internal
410 */
411 void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot()
412 {
413     Q_Q(QGraphicsProxyWidget);
414     widget = 0;
415     delete q;
416 }
417
418 /*!
419     \internal
420 */
421 void QGraphicsProxyWidgetPrivate::updateWidgetGeometryFromProxy()
422 {
423 }
424
425 /*!
426     \internal
427 */
428 void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
429 {
430     Q_Q(QGraphicsProxyWidget);
431     if (!widget)
432         return;
433
434     QRectF widgetGeometry = widget->geometry();
435     QWidget *parentWidget = widget->parentWidget();
436     if (widget->isWindow()) {
437         QGraphicsProxyWidget *proxyParent = 0;
438         if (parentWidget && (proxyParent = qobject_cast<QGraphicsProxyWidget *>(q->parentWidget()))) {
439             // Nested window proxy (e.g., combobox popup), map widget to the
440             // parent widget's global coordinates, and map that to the parent
441             // proxy's child coordinates.
442             widgetGeometry.moveTo(proxyParent->subWidgetRect(parentWidget).topLeft()
443                                   + parentWidget->mapFromGlobal(widget->pos()));
444         }
445     }
446
447     // Adjust to size hint if the widget has never been resized.
448     if (!widget->size().isValid())
449         widgetGeometry.setSize(widget->sizeHint());
450
451     // Assign new geometry.
452     posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
453     sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
454     q->setGeometry(widgetGeometry);
455     posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
456     sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
457 }
458
459 /*!
460     \internal
461 */
462 void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
463 {
464     Q_Q(QGraphicsProxyWidget);
465     if (!widget)
466         return;
467
468     QWidget *focusWidget = widget->focusWidget();
469     if (!focusWidget)
470         focusWidget = widget;
471     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
472                focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
473 }
474
475 /*!
476     \internal
477
478     Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
479     widget and a descendant of the widget managed by this proxy. A separate subproxy
480     will be created as a child of this proxy widget to manage \a subWin.
481 */
482 void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
483 {
484     QWExtra *extra;
485     if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
486         QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
487         subProxy->d_func()->setWidget_helper(subWin, false);
488     }
489 }
490
491 /*!
492     \internal
493
494     Removes ("unembeds") \a subWin and deletes the proxy holder item. This can
495     happen when QWidget::setParent() reparents the embedded window out of
496     "embedded space".
497 */
498 void QGraphicsProxyWidgetPrivate::unembedSubWindow(QWidget *subWin)
499 {
500     foreach (QGraphicsItem *child, children) {
501         if (child->isWidget()) {
502             if (QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))) {
503                 if (proxy->widget() == subWin) {
504                     proxy->setWidget(0);
505                     scene->removeItem(proxy);
506                     delete proxy;
507                     return;
508                 }
509             }
510         }
511     }
512 }
513
514 bool QGraphicsProxyWidgetPrivate::isProxyWidget() const
515 {
516     return true;
517 }
518
519 /*!
520      \internal
521 */
522 QPointF QGraphicsProxyWidgetPrivate::mapToReceiver(const QPointF &pos, const QWidget *receiver) const
523 {
524     QPointF p = pos;
525     // Map event position from us to the receiver, preserving its
526     // precision (don't use QWidget::mapFrom here).
527     while (receiver && receiver != widget) {
528         p -= QPointF(receiver->pos());
529         receiver = receiver->parentWidget();
530     }
531     return p;
532 }
533
534 /*!
535     Constructs a new QGraphicsProxy widget. \a parent and \a wFlags are passed
536     to QGraphicsItem's constructor.
537 */
538 QGraphicsProxyWidget::QGraphicsProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
539     : QGraphicsWidget(*new QGraphicsProxyWidgetPrivate, parent, 0, wFlags)
540 {
541     Q_D(QGraphicsProxyWidget);
542     d->init();
543 }
544
545 /*!
546     Destroys the proxy widget and any embedded widget.
547 */
548 QGraphicsProxyWidget::~QGraphicsProxyWidget()
549 {
550     Q_D(QGraphicsProxyWidget);
551     if (d->widget) {
552         QObject::disconnect(d->widget, SIGNAL(destroyed()), this, SLOT(_q_removeWidgetSlot()));
553         delete d->widget;
554     }
555 }
556
557 /*!
558     Embeds \a widget into this proxy widget. The embedded widget must reside
559     exclusively either inside or outside of Graphics View. You cannot embed a
560     widget as long as it is is visible elsewhere in the UI, at the same time.
561
562     \a widget must be a top-level widget whose parent is 0.
563
564     When the widget is embedded, its state (e.g., visible, enabled, geometry,
565     size hints) is copied into the proxy widget. If the embedded widget is
566     explicitly hidden or disabled, the proxy widget will become explicitly
567     hidden or disabled after embedding is complete. The class documentation
568     has a full overview over the shared state.
569
570     QGraphicsProxyWidget's window flags determine whether the widget, after
571     embedding, will be given window decorations or not.
572
573     After this function returns, QGraphicsProxyWidget will keep its state
574     synchronized with that of \a widget whenever possible.
575
576     If a widget is already embedded by this proxy when this function is
577     called, that widget will first be automatically unembedded. Passing 0 for
578     the \a widget argument will only unembed the widget, and the ownership of
579     the currently embedded widget will be passed on to the caller.
580     Every child widget that are embedded will also be embedded and their proxy
581     widget destroyed.
582
583     Note that widgets with the Qt::WA_PaintOnScreen widget attribute
584     set and widgets that wrap an external application or controller
585     cannot be embedded. Examples are QGLWidget and QAxWidget.
586
587     \sa widget()
588 */
589 void QGraphicsProxyWidget::setWidget(QWidget *widget)
590 {
591     Q_D(QGraphicsProxyWidget);
592     d->setWidget_helper(widget, true);
593 }
594
595 void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow)
596 {
597     Q_Q(QGraphicsProxyWidget);
598     if (newWidget == widget)
599         return;
600     if (widget) {
601         QObject::disconnect(widget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
602         widget->removeEventFilter(q);
603         widget->setAttribute(Qt::WA_DontShowOnScreen, false);
604         widget->d_func()->extra->proxyWidget = 0;
605         resolveFont(inheritedFontResolveMask);
606         resolvePalette(inheritedPaletteResolveMask);
607         widget->update();
608
609         foreach (QGraphicsItem *child, q->childItems()) {
610             if (child->d_ptr->isProxyWidget()) {
611                 QGraphicsProxyWidget *childProxy = static_cast<QGraphicsProxyWidget *>(child);
612                 QWidget * parent = childProxy->widget();
613                 while (parent->parentWidget() != 0) {
614                     if (parent == widget)
615                         break;
616                     parent = parent->parentWidget();
617                 }
618                 if (!childProxy->widget() || parent != widget)
619                     continue;
620                 childProxy->setWidget(0);
621                 delete childProxy;
622             }
623         }
624
625         widget = 0;
626 #ifndef QT_NO_CURSOR
627         q->unsetCursor();
628 #endif
629         q->setAcceptHoverEvents(false);
630         if (!newWidget)
631             q->update();
632     }
633     if (!newWidget)
634         return;
635     if (!newWidget->isWindow()) {
636         QWExtra *extra = newWidget->parentWidget()->d_func()->extra;
637         if (!extra || !extra->proxyWidget)  {
638             qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p "
639                      "which is not a toplevel widget, and is not a child of an embedded widget", newWidget);
640             return;
641         }
642     }
643
644     // Register this proxy within the widget's private.
645     // ### This is a bit backdoorish
646     QWExtra *extra = newWidget->d_func()->extra;
647     if (!extra) {
648         newWidget->d_func()->createExtra();
649         extra = newWidget->d_func()->extra;
650     }
651     QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;
652     if (*proxyWidget) {
653         if (*proxyWidget != q) {
654             qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"
655                         "; already embedded", newWidget);
656         }
657         return;
658     }
659     *proxyWidget = q;
660
661     newWidget->setAttribute(Qt::WA_DontShowOnScreen);
662     newWidget->ensurePolished();
663     // Do not wait for this widget to close before the app closes ###
664     // shouldn't this widget inherit the attribute?
665     newWidget->setAttribute(Qt::WA_QuitOnClose, false);
666     q->setAcceptHoverEvents(true);
667
668     if (newWidget->testAttribute(Qt::WA_NoSystemBackground))
669         q->setAttribute(Qt::WA_NoSystemBackground);
670     if (newWidget->testAttribute(Qt::WA_OpaquePaintEvent))
671         q->setAttribute(Qt::WA_OpaquePaintEvent);
672
673     widget = newWidget;
674
675     // Changes only go from the widget to the proxy.
676     enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
677     visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
678     posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
679     sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
680
681     if ((autoShow && !newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide)) || !newWidget->testAttribute(Qt::WA_WState_Hidden)) {
682         newWidget->show();
683     }
684
685     // Copy the state from the widget onto the proxy.
686 #ifndef QT_NO_CURSOR
687     if (newWidget->testAttribute(Qt::WA_SetCursor))
688         q->setCursor(widget->cursor());
689 #endif
690     q->setEnabled(newWidget->isEnabled());
691     q->setVisible(newWidget->isVisible());
692     q->setLayoutDirection(newWidget->layoutDirection());
693     if (newWidget->testAttribute(Qt::WA_SetStyle))
694         q->setStyle(widget->style());
695
696     resolveFont(inheritedFontResolveMask);
697     resolvePalette(inheritedPaletteResolveMask);
698
699     if (!newWidget->testAttribute(Qt::WA_Resized))
700         newWidget->adjustSize();
701
702     int left, top, right, bottom;
703     newWidget->getContentsMargins(&left, &top, &right, &bottom);
704     q->setContentsMargins(left, top, right, bottom);
705     q->setWindowTitle(newWidget->windowTitle());
706
707     // size policies and constraints..
708     q->setSizePolicy(newWidget->sizePolicy());
709     QSize sz = newWidget->minimumSize();
710     q->setMinimumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
711     sz = newWidget->maximumSize();
712     q->setMaximumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
713
714     updateProxyGeometryFromWidget();
715
716     updateProxyInputMethodAcceptanceFromWidget();
717
718     // Hook up the event filter to keep the state up to date.
719     newWidget->installEventFilter(q);
720     QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
721
722     // Changes no longer go only from the widget to the proxy.
723     enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
724     visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
725     posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
726     sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
727 }
728
729 /*!
730     Returns a pointer to the embedded widget.
731
732     \sa setWidget()
733 */
734 QWidget *QGraphicsProxyWidget::widget() const
735 {
736     Q_D(const QGraphicsProxyWidget);
737     return d->widget;
738 }
739
740 /*!
741     Returns the rectangle for \a widget, which must be a descendant of
742     widget(), or widget() itself, in this proxy item's local coordinates.
743
744     If no widget is embedded, \a widget is 0, or \a widget is not a
745     descendant of the embedded widget, this function returns an empty QRectF.
746
747     \sa widget()
748 */
749 QRectF QGraphicsProxyWidget::subWidgetRect(const QWidget *widget) const
750 {
751     Q_D(const QGraphicsProxyWidget);
752     if (!widget || !d->widget)
753         return QRectF();
754     if (d->widget == widget || d->widget->isAncestorOf(widget))
755         return QRectF(widget->mapTo(d->widget, QPoint(0, 0)), widget->size());
756     return QRectF();
757 }
758
759 /*!
760     \reimp
761 */
762 void QGraphicsProxyWidget::setGeometry(const QRectF &rect)
763 {
764     Q_D(QGraphicsProxyWidget);
765     bool proxyResizesWidget = !d->posChangeMode && !d->sizeChangeMode;
766     if (proxyResizesWidget) {
767         d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
768         d->sizeChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
769     }
770     QGraphicsWidget::setGeometry(rect);
771     if (proxyResizesWidget) {
772         d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
773         d->sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
774     }
775 }
776
777 /*!
778     \reimp
779 */
780 QVariant QGraphicsProxyWidget::itemChange(GraphicsItemChange change,
781                                           const QVariant &value)
782 {
783     Q_D(QGraphicsProxyWidget);
784
785     switch (change) {
786     case ItemPositionChange:
787         // The item's position is either changed directly on the proxy, in
788         // which case the position change should propagate to the widget,
789         // otherwise it happens as a side effect when filtering QEvent::Move.
790         if (!d->posChangeMode)
791             d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
792         break;
793     case ItemPositionHasChanged:
794         // Move the internal widget if we're in widget-to-proxy
795         // mode. Otherwise the widget has already moved.
796         if (d->widget && d->posChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
797             d->widget->move(value.toPoint());
798         if (d->posChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
799             d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
800         break;
801     case ItemVisibleChange:
802         if (!d->visibleChangeMode)
803             d->visibleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
804         break;
805     case ItemVisibleHasChanged:
806         if (d->widget && d->visibleChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
807             d->widget->setVisible(isVisible());
808         if (d->visibleChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
809             d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
810         break;
811     case ItemEnabledChange:
812         if (!d->enabledChangeMode)
813             d->enabledChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
814         break;
815     case ItemEnabledHasChanged:
816         if (d->widget && d->enabledChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
817             d->widget->setEnabled(isEnabled());
818         if (d->enabledChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
819             d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
820         break;
821     default:
822         break;
823     }
824     return QGraphicsWidget::itemChange(change, value);
825 }
826
827 /*!
828     \reimp
829 */
830 bool QGraphicsProxyWidget::event(QEvent *event)
831 {
832     Q_D(QGraphicsProxyWidget);
833     if (!d->widget)
834         return QGraphicsWidget::event(event);
835
836     switch (event->type()) {
837     case QEvent::StyleChange:
838         // Propagate style changes to the embedded widget.
839         if (!d->styleChangeMode) {
840             d->styleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
841             d->widget->setStyle(style());
842             d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
843         }
844         break;
845     case QEvent::FontChange: {
846         // Propagate to widget.
847         QWidgetPrivate *wd = d->widget->d_func();
848         int mask = d->font.resolve() | d->inheritedFontResolveMask;
849         wd->inheritedFontResolveMask = mask;
850         wd->resolveFont();
851         break;
852     }
853     case QEvent::PaletteChange: {
854         // Propagate to widget.
855         QWidgetPrivate *wd = d->widget->d_func();
856         int mask = d->palette.resolve() | d->inheritedPaletteResolveMask;
857         wd->inheritedPaletteResolveMask = mask;
858         wd->resolvePalette();
859         break;
860     }
861     case QEvent::InputMethod: {
862         // Forward input method events if the focus widget enables
863         // input methods.
864         // ### Qt 4.5: this code must also go into a reimplementation
865         // of inputMethodEvent().
866         QWidget *focusWidget = d->widget->focusWidget();
867         if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
868             QApplication::sendEvent(focusWidget, event);
869         break;
870     }
871     case QEvent::ShortcutOverride: {
872         QWidget *focusWidget = d->widget->focusWidget();
873         while (focusWidget) {
874             QApplication::sendEvent(focusWidget, event);
875             if (event->isAccepted())
876                 return true;
877             focusWidget = focusWidget->parentWidget();
878         }
879         return false;
880     }
881     case QEvent::KeyPress: {
882         QKeyEvent *k = static_cast<QKeyEvent *>(event);
883         if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
884             if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
885                 QWidget *focusWidget = d->widget->focusWidget();
886                 while (focusWidget) {
887                     bool res = QApplication::sendEvent(focusWidget, event);
888                     if ((res && event->isAccepted()) || (isWindow() && focusWidget == d->widget)) {
889                         event->accept();
890                         break;
891                     }
892                     focusWidget = focusWidget->parentWidget();
893                 }
894                 return true;
895             }
896         }
897         break;
898     }
899 #ifndef QT_NO_TOOLTIP
900     case QEvent::GraphicsSceneHelp: {
901         // Propagate the help event (for tooltip) to the widget under mouse
902         if (d->lastWidgetUnderMouse) {
903             QGraphicsSceneHelpEvent *he = static_cast<QGraphicsSceneHelpEvent *>(event);
904             QPoint pos = d->mapToReceiver(mapFromScene(he->scenePos()), d->lastWidgetUnderMouse).toPoint();
905             QHelpEvent e(QEvent::ToolTip, pos, he->screenPos());
906             QApplication::sendEvent(d->lastWidgetUnderMouse, &e);
907             event->setAccepted(e.isAccepted());
908             return e.isAccepted();
909         }
910         break;
911     }
912     case QEvent::ToolTipChange: {
913         // Propagate tooltip change to the widget
914         if (!d->tooltipChangeMode) {
915             d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
916             d->widget->setToolTip(toolTip());
917             d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
918         }
919         break;
920     }
921 #endif
922     default:
923         break;
924     }
925     return QGraphicsWidget::event(event);
926 }
927
928 /*!
929     \reimp
930 */
931 bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
932 {
933     Q_D(QGraphicsProxyWidget);
934
935     if (object == d->widget) {
936         switch (event->type()) {
937         case QEvent::LayoutRequest:
938             updateGeometry();
939             break;
940          case QEvent::Resize:
941              // If the widget resizes itself, we resize the proxy too.
942              // Prevent feed-back by checking the geometry change mode.
943              if (!d->sizeChangeMode)
944                  d->updateProxyGeometryFromWidget();
945             break;
946          case QEvent::Move:
947              // If the widget moves itself, we move the proxy too.  Prevent
948              // feed-back by checking the geometry change mode.
949              if (!d->posChangeMode)
950                  d->updateProxyGeometryFromWidget();
951             break;
952         case QEvent::Hide:
953         case QEvent::Show:
954             // If the widget toggles its visible state, the proxy will follow.
955             if (!d->visibleChangeMode) {
956                 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
957                 setVisible(event->type() == QEvent::Show);
958                 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
959             }
960             break;
961         case QEvent::EnabledChange:
962             // If the widget toggles its enabled state, the proxy will follow.
963             if (!d->enabledChangeMode) {
964                 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
965                 setEnabled(d->widget->isEnabled());
966                 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
967             }
968             break;
969         case QEvent::StyleChange:
970             // Propagate style changes to the proxy.
971             if (!d->styleChangeMode) {
972                 d->styleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
973                 setStyle(d->widget->style());
974                 d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
975             }
976             break;
977 #ifndef QT_NO_TOOLTIP
978         case QEvent::ToolTipChange:
979             // Propagate tooltip change to the proxy.
980             if (!d->tooltipChangeMode) {
981                 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
982                 setToolTip(d->widget->toolTip());
983                 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
984             }
985             break;
986 #endif
987         default:
988             break;
989         }
990     }
991     return QGraphicsWidget::eventFilter(object, event);
992 }
993
994 /*!
995     \reimp
996 */
997 void QGraphicsProxyWidget::showEvent(QShowEvent *event)
998 {
999     Q_UNUSED(event);
1000 }
1001
1002 /*!
1003     \reimp
1004 */
1005 void QGraphicsProxyWidget::hideEvent(QHideEvent *event)
1006 {
1007     Q_UNUSED(event);
1008 }
1009
1010 #ifndef QT_NO_CONTEXTMENU
1011 /*!
1012     \reimp
1013 */
1014 void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
1015 {
1016     Q_D(QGraphicsProxyWidget);
1017     if (!event || !d->widget || !d->widget->isVisible() || !hasFocus())
1018         return;
1019
1020     // Find widget position and receiver.
1021     QPointF pos = event->pos();
1022     QPointer<QWidget> alienWidget = d->widget->childAt(pos.toPoint());
1023     QPointer<QWidget> receiver =  alienWidget ? alienWidget : d->widget;
1024
1025     // Map event position from us to the receiver
1026     pos = d->mapToReceiver(pos, receiver);
1027
1028     QPoint globalPos = receiver->mapToGlobal(pos.toPoint());
1029     //If the receiver by-pass the proxy its popups
1030     //will be top level QWidgets therefore they need
1031     //the screen position. mapToGlobal expect the widget to
1032     //have proper coordinates in regards of the windowing system
1033     //but it's not true because the widget is embedded.
1034     if (bypassGraphicsProxyWidget(receiver))
1035         globalPos = event->screenPos();
1036
1037     // Send mouse event. ### Doesn't propagate the event.
1038     QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()),
1039                                        pos.toPoint(), globalPos, event->modifiers());
1040     QApplication::sendEvent(receiver, &contextMenuEvent);
1041
1042     event->setAccepted(contextMenuEvent.isAccepted());
1043 }
1044 #endif // QT_NO_CONTEXTMENU
1045
1046 #ifndef QT_NO_DRAGANDDROP
1047 /*!
1048     \reimp
1049 */
1050 void QGraphicsProxyWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
1051 {
1052 #ifdef QT_NO_DRAGANDDROP
1053     Q_UNUSED(event);
1054 #else
1055     Q_D(QGraphicsProxyWidget);
1056     if (!d->widget)
1057         return;
1058
1059     QDragEnterEvent proxyDragEnter(event->pos().toPoint(), event->dropAction(), event->mimeData(), event->buttons(), event->modifiers());
1060     proxyDragEnter.setAccepted(event->isAccepted());
1061     QApplication::sendEvent(d->widget, &proxyDragEnter);
1062     event->setAccepted(proxyDragEnter.isAccepted());
1063     if (proxyDragEnter.isAccepted())    // we discard answerRect
1064         event->setDropAction(proxyDragEnter.dropAction());
1065 #endif
1066 }
1067 /*!
1068     \reimp
1069 */
1070 void QGraphicsProxyWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
1071 {
1072     Q_UNUSED(event);
1073 #ifndef QT_NO_DRAGANDDROP
1074     Q_D(QGraphicsProxyWidget);
1075     if (!d->widget || !d->dragDropWidget)
1076         return;
1077     QDragLeaveEvent proxyDragLeave;
1078     QApplication::sendEvent(d->dragDropWidget, &proxyDragLeave);
1079     d->dragDropWidget = 0;
1080 #endif
1081 }
1082
1083 /*!
1084     \reimp
1085 */
1086 void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
1087 {
1088 #ifdef QT_NO_DRAGANDDROP
1089     Q_UNUSED(event);
1090 #else
1091     Q_D(QGraphicsProxyWidget);
1092     if (!d->widget)
1093         return;
1094     QPointF p = event->pos();
1095     event->ignore();
1096     QPointer<QWidget> subWidget = d->widget->childAt(p.toPoint());
1097     QPointer<QWidget> receiver =  subWidget ? subWidget : d->widget;
1098     bool eventDelivered = false;
1099     for (; receiver; receiver = receiver->parentWidget()) {
1100         if (!receiver->isEnabled() || !receiver->acceptDrops())
1101             continue;
1102         // Map event position from us to the receiver
1103         QPoint receiverPos = d->mapToReceiver(p, receiver).toPoint();
1104         if (receiver != d->dragDropWidget) {
1105             // Try to enter before we leave
1106             QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1107             dragEnter.setDropAction(event->proposedAction());
1108             QApplication::sendEvent(receiver, &dragEnter);
1109             event->setAccepted(dragEnter.isAccepted());
1110             event->setDropAction(dragEnter.dropAction());
1111             if (!event->isAccepted()) {
1112                 // propagate to the parent widget
1113                 continue;
1114             }
1115
1116             d->lastDropAction = event->dropAction();
1117
1118             if (d->dragDropWidget) {
1119                 QDragLeaveEvent dragLeave;
1120                 QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1121             }
1122             d->dragDropWidget = receiver;
1123         }
1124
1125         QDragMoveEvent dragMove(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1126         event->setDropAction(d->lastDropAction);
1127         QApplication::sendEvent(receiver, &dragMove);
1128         event->setAccepted(dragMove.isAccepted());
1129         event->setDropAction(dragMove.dropAction());
1130         if (event->isAccepted())
1131             d->lastDropAction = event->dropAction();
1132         eventDelivered = true;
1133         break;
1134     }
1135
1136     if (!eventDelivered) {
1137         if (d->dragDropWidget) {
1138             // Leave the last drag drop item
1139             QDragLeaveEvent dragLeave;
1140             QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1141             d->dragDropWidget = 0;
1142         }
1143         // Propagate
1144         event->setDropAction(Qt::IgnoreAction);
1145     }
1146 #endif
1147 }
1148
1149 /*!
1150     \reimp
1151 */
1152 void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
1153 {
1154 #ifdef QT_NO_DRAGANDDROP
1155     Q_UNUSED(event);
1156 #else
1157     Q_D(QGraphicsProxyWidget);
1158     if (d->widget && d->dragDropWidget) {
1159         QPoint widgetPos = d->mapToReceiver(event->pos(), d->dragDropWidget).toPoint();
1160         QDropEvent dropEvent(widgetPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1161         QApplication::sendEvent(d->dragDropWidget, &dropEvent);
1162         event->setAccepted(dropEvent.isAccepted());
1163         d->dragDropWidget = 0;
1164     }
1165 #endif
1166 }
1167 #endif
1168
1169 /*!
1170     \reimp
1171 */
1172 void QGraphicsProxyWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1173 {
1174     Q_UNUSED(event);
1175 }
1176
1177 /*!
1178     \reimp
1179 */
1180 void QGraphicsProxyWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1181 {
1182     Q_UNUSED(event);
1183     Q_D(QGraphicsProxyWidget);
1184     // If hoverMove was compressed away, make sure we update properly here.
1185     if (d->lastWidgetUnderMouse) {
1186         QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
1187         d->lastWidgetUnderMouse = 0;
1188     }
1189 }
1190
1191 /*!
1192     \reimp
1193 */
1194 void QGraphicsProxyWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1195 {
1196     Q_D(QGraphicsProxyWidget);
1197 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1198     qDebug() << "QGraphicsProxyWidget::hoverMoveEvent";
1199 #endif
1200     // Ignore events on the window frame.
1201     if (!d->widget || !rect().contains(event->pos())) {
1202         if (d->lastWidgetUnderMouse) {
1203             QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
1204             d->lastWidgetUnderMouse = 0;
1205         }
1206         return;
1207     }
1208
1209     d->embeddedMouseGrabber = 0;
1210     d->sendWidgetMouseEvent(event);
1211 }
1212
1213 /*!
1214     \reimp
1215 */
1216 void QGraphicsProxyWidget::grabMouseEvent(QEvent *event)
1217 {
1218     Q_UNUSED(event);
1219 }
1220
1221 /*!
1222     \reimp
1223 */
1224 void QGraphicsProxyWidget::ungrabMouseEvent(QEvent *event)
1225 {
1226     Q_D(QGraphicsProxyWidget);
1227     Q_UNUSED(event);
1228     d->embeddedMouseGrabber = 0;
1229 }
1230
1231 /*!
1232     \reimp
1233 */
1234 void QGraphicsProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1235 {
1236     Q_D(QGraphicsProxyWidget);
1237 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1238     qDebug() << "QGraphicsProxyWidget::mouseMoveEvent";
1239 #endif
1240     d->sendWidgetMouseEvent(event);
1241 }
1242
1243 /*!
1244     \reimp
1245 */
1246 void QGraphicsProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
1247 {
1248     Q_D(QGraphicsProxyWidget);
1249 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1250     qDebug() << "QGraphicsProxyWidget::mousePressEvent";
1251 #endif
1252     d->sendWidgetMouseEvent(event);
1253 }
1254
1255 /*!
1256     \reimp
1257 */
1258 void QGraphicsProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1259 {
1260     Q_D(QGraphicsProxyWidget);
1261 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1262     qDebug() << "QGraphicsProxyWidget::mouseDoubleClickEvent";
1263 #endif
1264     d->sendWidgetMouseEvent(event);
1265 }
1266
1267 /*!
1268     \reimp
1269 */
1270 #ifndef QT_NO_WHEELEVENT
1271 void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event)
1272 {
1273     Q_D(QGraphicsProxyWidget);
1274 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1275     qDebug() << "QGraphicsProxyWidget::wheelEvent";
1276 #endif
1277     if (!d->widget)
1278         return;
1279
1280     QPointF pos = event->pos();
1281     QPointer<QWidget> receiver = d->widget->childAt(pos.toPoint());
1282     if (!receiver)
1283         receiver = d->widget;
1284
1285     // Map event position from us to the receiver
1286     pos = d->mapToReceiver(pos, receiver);
1287
1288     // Send mouse event.
1289     QWheelEvent wheelEvent(pos.toPoint(), event->screenPos(), event->delta(),
1290                            event->buttons(), event->modifiers(), event->orientation());
1291     QPointer<QWidget> focusWidget = d->widget->focusWidget();
1292     extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
1293     qt_sendSpontaneousEvent(receiver, &wheelEvent);
1294     event->setAccepted(wheelEvent.isAccepted());
1295
1296     // ### Remove, this should be done by proper focusIn/focusOut events.
1297     if (focusWidget && !focusWidget->hasFocus()) {
1298         focusWidget->update();
1299         focusWidget = d->widget->focusWidget();
1300         if (focusWidget && focusWidget->hasFocus())
1301             focusWidget->update();
1302     }
1303 }
1304 #endif
1305
1306 /*!
1307     \reimp
1308 */
1309 void QGraphicsProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1310 {
1311     Q_D(QGraphicsProxyWidget);
1312 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1313     qDebug() << "QGraphicsProxyWidget::mouseReleaseEvent";
1314 #endif
1315     d->sendWidgetMouseEvent(event);
1316 }
1317
1318 /*!
1319     \reimp
1320 */
1321 void QGraphicsProxyWidget::keyPressEvent(QKeyEvent *event)
1322 {
1323     Q_D(QGraphicsProxyWidget);
1324 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1325     qDebug() << "QGraphicsProxyWidget::keyPressEvent";
1326 #endif
1327     d->sendWidgetKeyEvent(event);
1328 }
1329
1330 /*!
1331     \reimp
1332 */
1333 void QGraphicsProxyWidget::keyReleaseEvent(QKeyEvent *event)
1334 {
1335     Q_D(QGraphicsProxyWidget);
1336 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1337     qDebug() << "QGraphicsProxyWidget::keyReleaseEvent";
1338 #endif
1339     d->sendWidgetKeyEvent(event);
1340 }
1341
1342 /*!
1343     \reimp
1344 */
1345 void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
1346 {
1347 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1348     qDebug() << "QGraphicsProxyWidget::focusInEvent";
1349 #endif
1350     Q_D(QGraphicsProxyWidget);
1351
1352     if (d->focusFromWidgetToProxy) {
1353         // Prevent recursion when the proxy autogains focus through the
1354         // embedded widget calling setFocus(). ### Could be done with event
1355         // filter on FocusIn instead?
1356         return;
1357     }
1358
1359     d->proxyIsGivingFocus = true;
1360
1361     switch (event->reason()) {
1362     case Qt::TabFocusReason: {
1363         if (QWidget *focusChild = d->findFocusChild(0, true))
1364             focusChild->setFocus(event->reason());
1365         break;
1366     }
1367     case Qt::BacktabFocusReason:
1368         if (QWidget *focusChild = d->findFocusChild(0, false))
1369             focusChild->setFocus(event->reason());
1370         break;
1371     default:
1372         if (d->widget && d->widget->focusWidget()) {
1373             d->widget->focusWidget()->setFocus(event->reason());
1374         }
1375         break;
1376     }
1377
1378     d->proxyIsGivingFocus = false;
1379 }
1380
1381 /*!
1382     \reimp
1383 */
1384 void QGraphicsProxyWidget::focusOutEvent(QFocusEvent *event)
1385 {
1386 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1387     qDebug() << "QGraphicsProxyWidget::focusOutEvent";
1388 #endif
1389     Q_D(QGraphicsProxyWidget);
1390     if (d->widget) {
1391         // We need to explicitly remove subfocus from the embedded widget's
1392         // focus widget.
1393         if (QWidget *focusWidget = d->widget->focusWidget())
1394             d->removeSubFocusHelper(focusWidget, event->reason());
1395     }
1396 }
1397
1398 /*!
1399     \reimp
1400 */
1401 bool QGraphicsProxyWidget::focusNextPrevChild(bool next)
1402 {
1403     Q_D(QGraphicsProxyWidget);
1404     if (!d->widget || !d->scene)
1405         return QGraphicsWidget::focusNextPrevChild(next);
1406
1407     Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
1408     QWidget *lastFocusChild = d->widget->focusWidget();
1409     if (QWidget *newFocusChild = d->findFocusChild(lastFocusChild, next)) {
1410         newFocusChild->setFocus(reason);
1411         return true;
1412     }
1413
1414     return QGraphicsWidget::focusNextPrevChild(next);
1415 }
1416
1417 /*!
1418     \reimp
1419 */
1420 QSizeF QGraphicsProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
1421 {
1422     Q_D(const QGraphicsProxyWidget);
1423     if (!d->widget)
1424         return QGraphicsWidget::sizeHint(which, constraint);
1425
1426     QSizeF sh;
1427     switch (which) {
1428     case Qt::PreferredSize:
1429         if (QLayout *l = d->widget->layout())
1430             sh = l->sizeHint();
1431         else
1432             sh = d->widget->sizeHint();
1433         break;
1434     case Qt::MinimumSize:
1435         if (QLayout *l = d->widget->layout())
1436             sh = l->minimumSize();
1437         else
1438             sh = d->widget->minimumSizeHint();
1439         break;
1440     case Qt::MaximumSize:
1441         if (QLayout *l = d->widget->layout())
1442             sh = l->maximumSize();
1443         else
1444             sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
1445         break;
1446     case Qt::MinimumDescent:
1447         sh = constraint;
1448         break;
1449     default:
1450         break;
1451     }
1452     return sh;
1453 }
1454
1455 /*!
1456     \reimp
1457 */
1458 void QGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
1459 {
1460     Q_D(QGraphicsProxyWidget);
1461     if (d->widget) {
1462         if (d->sizeChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
1463             d->widget->resize(event->newSize().toSize());
1464     }
1465     QGraphicsWidget::resizeEvent(event);
1466 }
1467
1468 /*!
1469     \reimp
1470 */
1471 void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
1472 {
1473     Q_D(QGraphicsProxyWidget);
1474     Q_UNUSED(widget);
1475     if (!d->widget || !d->widget->isVisible())
1476         return;
1477
1478     // Filter out repaints on the window frame.
1479     const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect();
1480     if (exposedWidgetRect.isEmpty())
1481         return;
1482
1483     // Disable QPainter's default pen being cosmetic. This allows widgets and
1484     // styles to follow Qt's existing defaults without getting ugly cosmetic
1485     // lines when scaled.
1486     bool restore = !(painter->renderHints() & QPainter::NonCosmeticDefaultPen);
1487     painter->setRenderHints(QPainter::NonCosmeticDefaultPen, true);
1488
1489     d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect);
1490
1491     // Restore the render hints if necessary.
1492     if (restore)
1493         painter->setRenderHints(QPainter::NonCosmeticDefaultPen, false);
1494 }
1495
1496 /*!
1497     \reimp
1498 */
1499 int QGraphicsProxyWidget::type() const
1500 {
1501     return Type;
1502 }
1503
1504 /*!
1505   \since 4.5
1506
1507   Creates a proxy widget for the given \a child of the widget
1508   contained in this proxy.
1509
1510   This function makes it possible to acquire proxies for
1511   non top-level widgets. For instance, you can embed a dialog,
1512   and then transform only one of its widgets.
1513
1514   If the widget is already embedded, return the existing proxy widget.
1515
1516   \sa newProxyWidget(), QGraphicsScene::addWidget()
1517 */
1518 QGraphicsProxyWidget *QGraphicsProxyWidget::createProxyForChildWidget(QWidget *child)
1519 {
1520     QGraphicsProxyWidget *proxy = child->graphicsProxyWidget();
1521     if (proxy)
1522         return proxy;
1523     if (!child->parentWidget()) {
1524         qWarning("QGraphicsProxyWidget::createProxyForChildWidget: top-level widget not in a QGraphicsScene");
1525         return 0;
1526     }
1527
1528     QGraphicsProxyWidget *parentProxy = createProxyForChildWidget(child->parentWidget());
1529     if (!parentProxy)
1530         return 0;
1531
1532     if (!QMetaObject::invokeMethod(parentProxy, "newProxyWidget",  Qt::DirectConnection,
1533          Q_RETURN_ARG(QGraphicsProxyWidget*, proxy), Q_ARG(const QWidget*, child)))
1534         return 0;
1535     proxy->setParent(parentProxy);
1536     proxy->setWidget(child);
1537     return proxy;
1538 }
1539
1540 /*!
1541   \fn QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *child)
1542   \since 4.5
1543
1544   Creates a proxy widget for the given \a child of the widget contained in this
1545   proxy.
1546
1547   You should not call this function directly; use
1548   QGraphicsProxyWidget::createProxyForChildWidget() instead.
1549
1550   This function is a fake virtual slot that you can reimplement in
1551   your subclass in order to control how new proxy widgets are
1552   created. The default implementation returns a proxy created with
1553   the QGraphicsProxyWidget() constructor with this proxy widget as
1554   the parent.
1555
1556   \sa createProxyForChildWidget()
1557 */
1558 QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *)
1559 {
1560     return new QGraphicsProxyWidget(this);
1561 }
1562
1563
1564
1565 QT_END_NAMESPACE
1566
1567 #include "moc_qgraphicsproxywidget.cpp"
1568
1569 #endif //QT_NO_GRAPHICSVIEW