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