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