1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
44 #ifndef QT_NO_GRAPHICSVIEW
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"
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>
66 //#define GRAPHICSPROXYWIDGET_DEBUG
69 \class QGraphicsProxyWidget
70 \brief The QGraphicsProxyWidget class provides a proxy layer for embedding
71 a QWidget in a QGraphicsScene.
73 \ingroup graphicsview-api
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.
87 \snippet code/src_gui_graphicsview_qgraphicsproxywidget.cpp 0
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).
97 \section1 Embedding a Widget with QGraphicsProxyWidget
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.
105 For example, in the code snippet below, we embed a group box into the proxy:
107 \snippet code/src_gui_graphicsview_qgraphicsproxywidget.cpp 1
109 The image below is the output obtained with its contents margin and
110 contents rect labeled.
112 \image qgraphicsproxywidget-embed.png
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.
120 \section1 Synchronizing Widget States
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.
134 \snippet code/src_gui_graphicsview_qgraphicsproxywidget.cpp 2
136 QGraphicsProxyWidget maintains symmetry for the following states:
139 \header \li QWidget state \li QGraphicsProxyWidget state \li Notes
140 \row \li QWidget::enabled
141 \li QGraphicsProxyWidget::enabled
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
153 \row \li QWidget::style
154 \li QGraphicsProxyWidget::style
156 \row \li QWidget::palette
157 \li QGraphicsProxyWidget::palette
159 \row \li QWidget::font
160 \li QGraphicsProxyWidget::font
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
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().
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.
185 \warning This class is provided for convenience when bridging
186 QWidgets and QGraphicsItems, it should not be used for
187 high-performance scenarios.
189 \sa QGraphicsScene::addWidget(), QGraphicsWidget
192 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
193 Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
198 void QGraphicsProxyWidgetPrivate::init()
200 Q_Q(QGraphicsProxyWidget);
201 q->setFocusPolicy(Qt::WheelFocus);
202 q->setAcceptDrops(true);
208 void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneHoverEvent *event)
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());
223 void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent *event)
225 if (!event || !widget || !widget->isVisible())
227 Q_Q(QGraphicsProxyWidget);
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;
234 if (QWidgetPrivate::nearestGraphicsProxyWidget(receiver) != q)
235 return; //another proxywidget will handle the events
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;
245 receiver = embeddedMouseGrabber;
247 case QEvent::GraphicsSceneMouseRelease:
248 type = QEvent::MouseButtonRelease;
249 if (embeddedMouseGrabber)
250 receiver = embeddedMouseGrabber;
252 case QEvent::GraphicsSceneMouseDoubleClick:
253 type = QEvent::MouseButtonDblClick;
254 if (!embeddedMouseGrabber)
255 embeddedMouseGrabber = receiver;
257 receiver = embeddedMouseGrabber;
259 case QEvent::GraphicsSceneMouseMove:
260 type = QEvent::MouseMove;
261 if (embeddedMouseGrabber)
262 receiver = embeddedMouseGrabber;
265 Q_ASSERT_X(false, "QGraphicsProxyWidget", "internal error");
269 if (!lastWidgetUnderMouse) {
270 QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : receiver, 0);
271 lastWidgetUnderMouse = receiver;
274 // Map event position from us to the receiver
275 pos = mapToReceiver(pos, receiver);
278 QMouseEvent mouseEvent(type, pos, receiver->mapTo(receiver->topLevelWidget(), pos.toPoint()),
279 receiver->mapToGlobal(pos.toPoint()),
280 event->button(), event->buttons(), event->modifiers());
282 QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
283 QApplicationPrivate::sendMouseEvent(receiver, &mouseEvent, alienWidget, widget,
284 &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous());
285 embeddedMouseGrabber = embeddedMouseGrabberPtr;
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;
296 QApplicationPrivate::dispatchEnterLeave(lastWidgetUnderMouse, embeddedMouseGrabber);
297 embeddedMouseGrabber = 0;
300 // ### Restore the cursor, don't override it.
301 if (!lastWidgetUnderMouse)
306 event->setAccepted(mouseEvent.isAccepted());
309 void QGraphicsProxyWidgetPrivate::sendWidgetKeyEvent(QKeyEvent *event)
311 Q_Q(QGraphicsProxyWidget);
312 if (!event || !widget || !widget->isVisible())
315 QPointer<QWidget> receiver = widget->focusWidget();
321 bool res = QApplication::sendEvent(receiver, event);
322 if ((res && event->isAccepted()) || (q->isWindow() && receiver == widget))
324 receiver = receiver->parentWidget();
331 void QGraphicsProxyWidgetPrivate::removeSubFocusHelper(QWidget *widget, Qt::FocusReason reason)
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);
342 Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
344 QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
349 // Run around the focus chain until we find a widget that can take tab focus.
351 child = next ? (QWidget *)widget : widget->d_func()->focus_prev;
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)) {
359 QWidget *oldChild = child;
360 uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;
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)) {
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));
376 void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot()
378 Q_Q(QGraphicsProxyWidget);
386 void QGraphicsProxyWidgetPrivate::updateWidgetGeometryFromProxy()
393 void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
395 Q_Q(QGraphicsProxyWidget);
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()));
412 // Adjust to size hint if the widget has never been resized.
413 if (!widget->size().isValid())
414 widgetGeometry.setSize(widget->sizeHint());
416 // Assign new geometry.
417 posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
418 sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
419 q->setGeometry(widgetGeometry);
420 posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
421 sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
427 void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
429 Q_Q(QGraphicsProxyWidget);
433 QWidget *focusWidget = widget->focusWidget();
435 focusWidget = widget;
436 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
437 focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
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.
447 void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
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);
459 Removes ("unembeds") \a subWin and deletes the proxy holder item. This can
460 happen when QWidget::setParent() reparents the embedded window out of
463 void QGraphicsProxyWidgetPrivate::unembedSubWindow(QWidget *subWin)
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) {
470 scene->removeItem(proxy);
479 bool QGraphicsProxyWidgetPrivate::isProxyWidget() const
487 QPointF QGraphicsProxyWidgetPrivate::mapToReceiver(const QPointF &pos, const QWidget *receiver) const
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();
500 Constructs a new QGraphicsProxy widget. \a parent and \a wFlags are passed
501 to QGraphicsItem's constructor.
503 QGraphicsProxyWidget::QGraphicsProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
504 : QGraphicsWidget(*new QGraphicsProxyWidgetPrivate, parent, wFlags)
506 Q_D(QGraphicsProxyWidget);
511 Destroys the proxy widget and any embedded widget.
513 QGraphicsProxyWidget::~QGraphicsProxyWidget()
515 Q_D(QGraphicsProxyWidget);
517 QObject::disconnect(d->widget, SIGNAL(destroyed()), this, SLOT(_q_removeWidgetSlot()));
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.
527 \a widget must be a top-level widget whose parent is 0.
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.
535 QGraphicsProxyWidget's window flags determine whether the widget, after
536 embedding, will be given window decorations or not.
538 After this function returns, QGraphicsProxyWidget will keep its state
539 synchronized with that of \a widget whenever possible.
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
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.
554 void QGraphicsProxyWidget::setWidget(QWidget *widget)
556 Q_D(QGraphicsProxyWidget);
557 d->setWidget_helper(widget, true);
560 void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow)
562 Q_Q(QGraphicsProxyWidget);
563 if (newWidget == 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);
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)
581 parent = parent->parentWidget();
583 if (!childProxy->widget() || parent != widget)
585 childProxy->setWidget(0);
594 q->setAcceptHoverEvents(false);
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);
609 // Register this proxy within the widget's private.
610 // ### This is a bit backdoorish
611 QWExtra *extra = newWidget->d_func()->extra;
613 newWidget->d_func()->createExtra();
614 extra = newWidget->d_func()->extra;
616 QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;
618 if (*proxyWidget != q) {
619 qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"
620 "; already embedded", newWidget);
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);
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);
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;
646 if ((autoShow && !newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide)) || !newWidget->testAttribute(Qt::WA_WState_Hidden)) {
650 // Copy the state from the widget onto the proxy.
652 if (newWidget->testAttribute(Qt::WA_SetCursor))
653 q->setCursor(widget->cursor());
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());
661 resolveFont(inheritedFontResolveMask);
662 resolvePalette(inheritedPaletteResolveMask);
664 if (!newWidget->testAttribute(Qt::WA_Resized))
665 newWidget->adjustSize();
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());
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));
679 updateProxyGeometryFromWidget();
681 updateProxyInputMethodAcceptanceFromWidget();
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()));
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;
695 Returns a pointer to the embedded widget.
699 QWidget *QGraphicsProxyWidget::widget() const
701 Q_D(const QGraphicsProxyWidget);
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.
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.
714 QRectF QGraphicsProxyWidget::subWidgetRect(const QWidget *widget) const
716 Q_D(const QGraphicsProxyWidget);
717 if (!widget || !d->widget)
719 if (d->widget == widget || d->widget->isAncestorOf(widget))
720 return QRectF(widget->mapTo(d->widget, QPoint(0, 0)), widget->size());
727 void QGraphicsProxyWidget::setGeometry(const QRectF &rect)
729 Q_D(QGraphicsProxyWidget);
730 bool proxyResizesWidget = !d->posChangeMode && !d->sizeChangeMode;
731 if (proxyResizesWidget) {
732 d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
733 d->sizeChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
735 QGraphicsWidget::setGeometry(rect);
736 if (proxyResizesWidget) {
737 d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
738 d->sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
745 QVariant QGraphicsProxyWidget::itemChange(GraphicsItemChange change,
746 const QVariant &value)
748 Q_D(QGraphicsProxyWidget);
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;
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;
766 case ItemVisibleChange:
767 if (!d->visibleChangeMode)
768 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
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;
776 case ItemEnabledChange:
777 if (!d->enabledChangeMode)
778 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
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;
789 return QGraphicsWidget::itemChange(change, value);
795 bool QGraphicsProxyWidget::event(QEvent *event)
797 Q_D(QGraphicsProxyWidget);
799 return QGraphicsWidget::event(event);
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;
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;
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();
826 case QEvent::InputMethod: {
827 inputMethodEvent(static_cast<QInputMethodEvent *>(event));
830 case QEvent::ShortcutOverride: {
831 QWidget *focusWidget = d->widget->focusWidget();
832 while (focusWidget) {
833 QApplication::sendEvent(focusWidget, event);
834 if (event->isAccepted())
836 focusWidget = focusWidget->parentWidget();
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)) {
851 focusWidget = focusWidget->parentWidget();
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();
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;
884 return QGraphicsWidget::event(event);
890 bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
892 Q_D(QGraphicsProxyWidget);
894 if (object == d->widget) {
895 switch (event->type()) {
896 case QEvent::LayoutRequest:
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();
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();
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;
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;
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;
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;
950 return QGraphicsWidget::eventFilter(object, event);
956 void QGraphicsProxyWidget::showEvent(QShowEvent *event)
964 void QGraphicsProxyWidget::hideEvent(QHideEvent *event)
969 #ifndef QT_NO_CONTEXTMENU
973 void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
975 Q_D(QGraphicsProxyWidget);
976 if (!event || !d->widget || !d->widget->isVisible() || !hasFocus())
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;
984 // Map event position from us to the receiver
985 pos = d->mapToReceiver(pos, receiver);
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();
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);
1001 event->setAccepted(contextMenuEvent.isAccepted());
1003 #endif // QT_NO_CONTEXTMENU
1005 #ifndef QT_NO_DRAGANDDROP
1009 void QGraphicsProxyWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
1011 #ifdef QT_NO_DRAGANDDROP
1014 Q_D(QGraphicsProxyWidget);
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());
1029 void QGraphicsProxyWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
1032 #ifndef QT_NO_DRAGANDDROP
1033 Q_D(QGraphicsProxyWidget);
1034 if (!d->widget || !d->dragDropWidget)
1036 QDragLeaveEvent proxyDragLeave;
1037 QApplication::sendEvent(d->dragDropWidget, &proxyDragLeave);
1038 d->dragDropWidget = 0;
1045 void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
1047 #ifdef QT_NO_DRAGANDDROP
1050 Q_D(QGraphicsProxyWidget);
1053 QPointF p = event->pos();
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())
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
1075 d->lastDropAction = event->dropAction();
1077 if (d->dragDropWidget) {
1078 QDragLeaveEvent dragLeave;
1079 QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1081 d->dragDropWidget = receiver;
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;
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;
1103 event->setDropAction(Qt::IgnoreAction);
1111 void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
1113 #ifdef QT_NO_DRAGANDDROP
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;
1131 void QGraphicsProxyWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1139 void QGraphicsProxyWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *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;
1153 void QGraphicsProxyWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1155 Q_D(QGraphicsProxyWidget);
1156 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1157 qDebug() << "QGraphicsProxyWidget::hoverMoveEvent";
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;
1168 d->embeddedMouseGrabber = 0;
1169 d->sendWidgetMouseEvent(event);
1175 void QGraphicsProxyWidget::grabMouseEvent(QEvent *event)
1183 void QGraphicsProxyWidget::ungrabMouseEvent(QEvent *event)
1185 Q_D(QGraphicsProxyWidget);
1187 d->embeddedMouseGrabber = 0;
1193 void QGraphicsProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1195 Q_D(QGraphicsProxyWidget);
1196 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1197 qDebug() << "QGraphicsProxyWidget::mouseMoveEvent";
1199 d->sendWidgetMouseEvent(event);
1205 void QGraphicsProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
1207 Q_D(QGraphicsProxyWidget);
1208 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1209 qDebug() << "QGraphicsProxyWidget::mousePressEvent";
1211 d->sendWidgetMouseEvent(event);
1217 void QGraphicsProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1219 Q_D(QGraphicsProxyWidget);
1220 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1221 qDebug() << "QGraphicsProxyWidget::mouseDoubleClickEvent";
1223 d->sendWidgetMouseEvent(event);
1229 #ifndef QT_NO_WHEELEVENT
1230 void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event)
1232 Q_D(QGraphicsProxyWidget);
1233 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1234 qDebug() << "QGraphicsProxyWidget::wheelEvent";
1239 QPointF pos = event->pos();
1240 QPointer<QWidget> receiver = d->widget->childAt(pos.toPoint());
1242 receiver = d->widget;
1244 // Map event position from us to the receiver
1245 pos = d->mapToReceiver(pos, receiver);
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());
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();
1268 void QGraphicsProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1270 Q_D(QGraphicsProxyWidget);
1271 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1272 qDebug() << "QGraphicsProxyWidget::mouseReleaseEvent";
1274 d->sendWidgetMouseEvent(event);
1280 void QGraphicsProxyWidget::keyPressEvent(QKeyEvent *event)
1282 Q_D(QGraphicsProxyWidget);
1283 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1284 qDebug() << "QGraphicsProxyWidget::keyPressEvent";
1286 d->sendWidgetKeyEvent(event);
1292 void QGraphicsProxyWidget::keyReleaseEvent(QKeyEvent *event)
1294 Q_D(QGraphicsProxyWidget);
1295 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1296 qDebug() << "QGraphicsProxyWidget::keyReleaseEvent";
1298 d->sendWidgetKeyEvent(event);
1304 void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
1306 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1307 qDebug() << "QGraphicsProxyWidget::focusInEvent";
1309 Q_D(QGraphicsProxyWidget);
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?
1318 d->proxyIsGivingFocus = true;
1320 switch (event->reason()) {
1321 case Qt::TabFocusReason: {
1322 if (QWidget *focusChild = d->findFocusChild(0, true))
1323 focusChild->setFocus(event->reason());
1326 case Qt::BacktabFocusReason:
1327 if (QWidget *focusChild = d->findFocusChild(0, false))
1328 focusChild->setFocus(event->reason());
1331 if (d->widget && d->widget->focusWidget()) {
1332 d->widget->focusWidget()->setFocus(event->reason());
1337 d->proxyIsGivingFocus = false;
1343 void QGraphicsProxyWidget::focusOutEvent(QFocusEvent *event)
1345 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1346 qDebug() << "QGraphicsProxyWidget::focusOutEvent";
1348 Q_D(QGraphicsProxyWidget);
1350 // We need to explicitly remove subfocus from the embedded widget's
1352 if (QWidget *focusWidget = d->widget->focusWidget())
1353 d->removeSubFocusHelper(focusWidget, event->reason());
1360 bool QGraphicsProxyWidget::focusNextPrevChild(bool next)
1362 Q_D(QGraphicsProxyWidget);
1363 if (!d->widget || !d->scene)
1364 return QGraphicsWidget::focusNextPrevChild(next);
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);
1373 return QGraphicsWidget::focusNextPrevChild(next);
1379 QVariant QGraphicsProxyWidget::inputMethodQuery(Qt::InputMethodQuery query) const
1381 Q_D(const QGraphicsProxyWidget);
1383 if (!d->widget || !hasFocus())
1386 QWidget *focusWidget = widget()->focusWidget();
1388 focusWidget = d->widget;
1389 QVariant v = focusWidget->inputMethodQuery(query);
1390 QPointF focusWidgetPos = subWidgetRect(focusWidget).topLeft();
1392 case QVariant::RectF:
1393 v = v.toRectF().translated(focusWidgetPos);
1395 case QVariant::PointF:
1396 v = v.toPointF() + focusWidgetPos;
1398 case QVariant::Rect:
1399 v = v.toRect().translated(focusWidgetPos.toPoint());
1401 case QVariant::Point:
1402 v = v.toPoint() + focusWidgetPos.toPoint();
1413 void QGraphicsProxyWidget::inputMethodEvent(QInputMethodEvent *event)
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);
1425 QSizeF QGraphicsProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
1427 Q_D(const QGraphicsProxyWidget);
1429 return QGraphicsWidget::sizeHint(which, constraint);
1433 case Qt::PreferredSize:
1434 if (QLayout *l = d->widget->layout())
1437 sh = d->widget->sizeHint();
1439 case Qt::MinimumSize:
1440 if (QLayout *l = d->widget->layout())
1441 sh = l->minimumSize();
1443 sh = d->widget->minimumSizeHint();
1445 case Qt::MaximumSize:
1446 if (QLayout *l = d->widget->layout())
1447 sh = l->maximumSize();
1449 sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
1451 case Qt::MinimumDescent:
1463 void QGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
1465 Q_D(QGraphicsProxyWidget);
1467 if (d->sizeChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
1468 d->widget->resize(event->newSize().toSize());
1470 QGraphicsWidget::resizeEvent(event);
1476 void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
1478 Q_D(QGraphicsProxyWidget);
1480 if (!d->widget || !d->widget->isVisible())
1483 // Filter out repaints on the window frame.
1484 const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect();
1485 if (exposedWidgetRect.isEmpty())
1488 d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect);
1494 int QGraphicsProxyWidget::type() const
1502 Creates a proxy widget for the given \a child of the widget
1503 contained in this proxy.
1505 This function makes it possible to acquire proxies for
1506 non top-level widgets. For instance, you can embed a dialog,
1507 and then transform only one of its widgets.
1509 If the widget is already embedded, return the existing proxy widget.
1511 \sa newProxyWidget(), QGraphicsScene::addWidget()
1513 QGraphicsProxyWidget *QGraphicsProxyWidget::createProxyForChildWidget(QWidget *child)
1515 QGraphicsProxyWidget *proxy = child->graphicsProxyWidget();
1518 if (!child->parentWidget()) {
1519 qWarning("QGraphicsProxyWidget::createProxyForChildWidget: top-level widget not in a QGraphicsScene");
1523 QGraphicsProxyWidget *parentProxy = createProxyForChildWidget(child->parentWidget());
1527 if (!QMetaObject::invokeMethod(parentProxy, "newProxyWidget", Qt::DirectConnection,
1528 Q_RETURN_ARG(QGraphicsProxyWidget*, proxy), Q_ARG(const QWidget*, child)))
1530 proxy->setParent(parentProxy);
1531 proxy->setWidget(child);
1536 \fn QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *child)
1539 Creates a proxy widget for the given \a child of the widget contained in this
1542 You should not call this function directly; use
1543 QGraphicsProxyWidget::createProxyForChildWidget() instead.
1545 This function is a fake virtual slot that you can reimplement in
1546 your subclass in order to control how new proxy widgets are
1547 created. The default implementation returns a proxy created with
1548 the QGraphicsProxyWidget() constructor with this proxy widget as
1551 \sa createProxyForChildWidget()
1553 QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *)
1555 return new QGraphicsProxyWidget(this);
1562 #include "moc_qgraphicsproxywidget.cpp"
1564 #endif //QT_NO_GRAPHICSVIEW