1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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
75 QGraphicsProxyWidget embeds QWidget-based widgets, for example, a
76 QPushButton, QFontComboBox, or even QFileDialog, into
77 QGraphicsScene. It forwards events between the two objects and
78 translates between QWidget's integer-based geometry and
79 QGraphicsWidget's qreal-based geometry. QGraphicsProxyWidget
80 supports all core features of QWidget, including tab focus,
81 keyboard input, Drag & Drop, and popups. You can also embed
82 complex widgets, e.g., widgets with subwidgets.
86 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 0
88 QGraphicsProxyWidget takes care of automatically embedding popup children
89 of embedded widgets through creating a child proxy for each popup. This
90 means that when an embedded QComboBox shows its popup list, a new
91 QGraphicsProxyWidget is created automatically, embedding the popup, and
92 positioning it correctly. This only works if the popup is child of the
93 embedded widget (for example QToolButton::setMenu() requires the QMenu instance
94 to be child of the QToolButton).
96 \section1 Embedding a Widget with QGraphicsProxyWidget
98 There are two ways to embed a widget using QGraphicsProxyWidget. The most
99 common way is to pass a widget pointer to QGraphicsScene::addWidget()
100 together with any relevant \l Qt::WindowFlags. This function returns a
101 pointer to a QGraphicsProxyWidget. You can then choose to reparent or
102 position either the proxy, or the embedded widget itself.
104 For example, in the code snippet below, we embed a group box into the proxy:
106 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 1
108 The image below is the output obtained with its contents margin and
109 contents rect labeled.
111 \image qgraphicsproxywidget-embed.png
113 Alternatively, you can start by creating a new QGraphicsProxyWidget item,
114 and then call setWidget() to embed a QWidget later. The widget() function
115 returns a pointer to the embedded widget. QGraphicsProxyWidget shares
116 ownership with QWidget, so if either of the two widgets are destroyed, the
117 other widget will be automatically destroyed as well.
119 \section1 Synchronizing Widget States
121 QGraphicsProxyWidget keeps its state in sync with the embedded widget. For
122 example, if the proxy is hidden or disabled, the embedded widget will be
123 hidden or disabled as well, and vice versa. When the widget is embedded by
124 calling addWidget(), QGraphicsProxyWidget copies the state from the widget
125 into the proxy, and after that, the two will stay synchronized where
126 possible. By default, when you embed a widget into a proxy, both the widget
127 and the proxy will be visible because a QGraphicsWidget is visible when
128 created (you do not have to call show()). If you explicitly hide the
129 embedded widget, the proxy will also become invisible.
133 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 2
135 QGraphicsProxyWidget maintains symmetry for the following states:
138 \header \o QWidget state \o QGraphicsProxyWidget state \o Notes
139 \row \o QWidget::enabled
140 \o QGraphicsProxyWidget::enabled
142 \row \o QWidget::visible
143 \o QGraphicsProxyWidget::visible
144 \o The explicit state is also symmetric.
145 \row \o QWidget::geometry
146 \o QGraphicsProxyWidget::geometry
147 \o Geometry is only guaranteed to be symmetric while
148 the embedded widget is visible.
149 \row \o QWidget::layoutDirection
150 \o QGraphicsProxyWidget::layoutDirection
152 \row \o QWidget::style
153 \o QGraphicsProxyWidget::style
155 \row \o QWidget::palette
156 \o QGraphicsProxyWidget::palette
158 \row \o QWidget::font
159 \o QGraphicsProxyWidget::font
161 \row \o QWidget::cursor
162 \o QGraphicsProxyWidget::cursor
163 \o The embedded widget overrides the proxy widget
164 cursor. The proxy cursor changes depending on
165 which embedded subwidget is currently under the
167 \row \o QWidget::sizeHint()
168 \o QGraphicsProxyWidget::sizeHint()
169 \o All size hint functionality from the embedded
170 widget is forwarded by the proxy.
171 \row \o QWidget::getContentsMargins()
172 \o QGraphicsProxyWidget::getContentsMargins()
173 \o Updated once by setWidget().
174 \row \o QWidget::windowTitle
175 \o QGraphicsProxyWidget::windowTitle
176 \o Updated once by setWidget().
179 \note QGraphicsScene keeps the embedded widget in a special state that
180 prevents it from disturbing other widgets (both embedded and not embedded)
181 while the widget is embedded. In this state, the widget may differ slightly
182 in behavior from when it is not embedded.
184 \warning This class is provided for convenience when bridging
185 QWidgets and QGraphicsItems, it should not be used for
186 high-performance scenarios.
188 \sa QGraphicsScene::addWidget(), QGraphicsWidget
191 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
192 Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets;
197 void QGraphicsProxyWidgetPrivate::init()
199 Q_Q(QGraphicsProxyWidget);
200 q->setFocusPolicy(Qt::WheelFocus);
201 q->setAcceptDrops(true);
207 void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneHoverEvent *event)
209 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
210 mouseEvent.setPos(event->pos());
211 mouseEvent.setScreenPos(event->screenPos());
212 mouseEvent.setButton(Qt::NoButton);
213 mouseEvent.setButtons(0);
214 mouseEvent.setModifiers(event->modifiers());
215 sendWidgetMouseEvent(&mouseEvent);
216 event->setAccepted(mouseEvent.isAccepted());
222 void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent *event)
224 if (!event || !widget || !widget->isVisible())
226 Q_Q(QGraphicsProxyWidget);
228 // Find widget position and receiver.
229 QPointF pos = event->pos();
230 QPointer<QWidget> alienWidget = widget->childAt(pos.toPoint());
231 QPointer<QWidget> receiver = alienWidget ? alienWidget : widget;
233 if (QWidgetPrivate::nearestGraphicsProxyWidget(receiver) != q)
234 return; //another proxywidget will handle the events
236 // Translate QGraphicsSceneMouse events to QMouseEvents.
237 QEvent::Type type = QEvent::None;
238 switch (event->type()) {
239 case QEvent::GraphicsSceneMousePress:
240 type = QEvent::MouseButtonPress;
241 if (!embeddedMouseGrabber)
242 embeddedMouseGrabber = receiver;
244 receiver = embeddedMouseGrabber;
246 case QEvent::GraphicsSceneMouseRelease:
247 type = QEvent::MouseButtonRelease;
248 if (embeddedMouseGrabber)
249 receiver = embeddedMouseGrabber;
251 case QEvent::GraphicsSceneMouseDoubleClick:
252 type = QEvent::MouseButtonDblClick;
253 if (!embeddedMouseGrabber)
254 embeddedMouseGrabber = receiver;
256 receiver = embeddedMouseGrabber;
258 case QEvent::GraphicsSceneMouseMove:
259 type = QEvent::MouseMove;
260 if (embeddedMouseGrabber)
261 receiver = embeddedMouseGrabber;
264 Q_ASSERT_X(false, "QGraphicsProxyWidget", "internal error");
268 if (!lastWidgetUnderMouse) {
269 QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : receiver, 0);
270 lastWidgetUnderMouse = receiver;
273 // Map event position from us to the receiver
274 pos = mapToReceiver(pos, receiver);
277 QMouseEvent mouseEvent(type, pos, receiver->mapTo(receiver->topLevelWidget(), pos.toPoint()),
278 receiver->mapToGlobal(pos.toPoint()),
279 event->button(), event->buttons(), event->modifiers());
281 QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
282 QApplicationPrivate::sendMouseEvent(receiver, &mouseEvent, alienWidget, widget,
283 &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous());
284 embeddedMouseGrabber = embeddedMouseGrabberPtr;
286 // Handle enter/leave events when last button is released from mouse
287 // grabber child widget.
288 if (embeddedMouseGrabber && type == QEvent::MouseButtonRelease && !event->buttons()) {
289 Q_Q(QGraphicsProxyWidget);
290 if (q->rect().contains(event->pos()) && q->acceptsHoverEvents())
291 lastWidgetUnderMouse = alienWidget ? alienWidget : widget;
292 else // released on the frame our outside the item, or doesn't accept hover events.
293 lastWidgetUnderMouse = 0;
295 QApplicationPrivate::dispatchEnterLeave(lastWidgetUnderMouse, embeddedMouseGrabber);
296 embeddedMouseGrabber = 0;
299 // ### Restore the cursor, don't override it.
300 if (!lastWidgetUnderMouse)
305 event->setAccepted(mouseEvent.isAccepted());
308 void QGraphicsProxyWidgetPrivate::sendWidgetKeyEvent(QKeyEvent *event)
310 Q_Q(QGraphicsProxyWidget);
311 if (!event || !widget || !widget->isVisible())
314 QPointer<QWidget> receiver = widget->focusWidget();
320 bool res = QApplication::sendEvent(receiver, event);
321 if ((res && event->isAccepted()) || (q->isWindow() && receiver == widget))
323 receiver = receiver->parentWidget();
330 void QGraphicsProxyWidgetPrivate::removeSubFocusHelper(QWidget *widget, Qt::FocusReason reason)
332 QFocusEvent event(QEvent::FocusOut, reason);
333 QPointer<QWidget> widgetGuard = widget;
334 QApplication::sendEvent(widget, &event);
335 if (widgetGuard && event.isAccepted())
336 QApplication::sendEvent(widget->style(), &event);
342 Reimplemented from QGraphicsItemPrivate. ### Qt 5: Move impl to
343 reimplementation QGraphicsProxyWidget::inputMethodQuery().
345 QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const
347 Q_Q(const QGraphicsProxyWidget);
348 if (!widget || !q->hasFocus())
351 QWidget *focusWidget = widget->focusWidget();
353 focusWidget = widget;
354 QVariant v = focusWidget->inputMethodQuery(query);
355 QPointF focusWidgetPos = q->subWidgetRect(focusWidget).topLeft();
357 case QVariant::RectF:
358 v = v.toRectF().translated(focusWidgetPos);
360 case QVariant::PointF:
361 v = v.toPointF() + focusWidgetPos;
364 v = v.toRect().translated(focusWidgetPos.toPoint());
366 case QVariant::Point:
367 v = v.toPoint() + focusWidgetPos.toPoint();
377 Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
379 QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
384 // Run around the focus chain until we find a widget that can take tab focus.
386 child = next ? (QWidget *)widget : widget->d_func()->focus_prev;
388 child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
389 if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) {
394 QWidget *oldChild = child;
395 uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
397 if (child->isEnabled()
398 && child->isVisibleTo(widget)
399 && ((child->focusPolicy() & focus_flag) == focus_flag)
400 && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
403 child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
404 } while (child != oldChild && !(next && child == widget) && !(!next && child == widget->d_func()->focus_prev));
411 void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot()
413 Q_Q(QGraphicsProxyWidget);
421 void QGraphicsProxyWidgetPrivate::updateWidgetGeometryFromProxy()
428 void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
430 Q_Q(QGraphicsProxyWidget);
434 QRectF widgetGeometry = widget->geometry();
435 QWidget *parentWidget = widget->parentWidget();
436 if (widget->isWindow()) {
437 QGraphicsProxyWidget *proxyParent = 0;
438 if (parentWidget && (proxyParent = qobject_cast<QGraphicsProxyWidget *>(q->parentWidget()))) {
439 // Nested window proxy (e.g., combobox popup), map widget to the
440 // parent widget's global coordinates, and map that to the parent
441 // proxy's child coordinates.
442 widgetGeometry.moveTo(proxyParent->subWidgetRect(parentWidget).topLeft()
443 + parentWidget->mapFromGlobal(widget->pos()));
447 // Adjust to size hint if the widget has never been resized.
448 if (!widget->size().isValid())
449 widgetGeometry.setSize(widget->sizeHint());
451 // Assign new geometry.
452 posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
453 sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
454 q->setGeometry(widgetGeometry);
455 posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
456 sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
462 void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
464 Q_Q(QGraphicsProxyWidget);
468 QWidget *focusWidget = widget->focusWidget();
470 focusWidget = widget;
471 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
472 focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
478 Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
479 widget and a descendant of the widget managed by this proxy. A separate subproxy
480 will be created as a child of this proxy widget to manage \a subWin.
482 void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
485 if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
486 QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
487 subProxy->d_func()->setWidget_helper(subWin, false);
494 Removes ("unembeds") \a subWin and deletes the proxy holder item. This can
495 happen when QWidget::setParent() reparents the embedded window out of
498 void QGraphicsProxyWidgetPrivate::unembedSubWindow(QWidget *subWin)
500 foreach (QGraphicsItem *child, children) {
501 if (child->isWidget()) {
502 if (QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))) {
503 if (proxy->widget() == subWin) {
505 scene->removeItem(proxy);
514 bool QGraphicsProxyWidgetPrivate::isProxyWidget() const
522 QPointF QGraphicsProxyWidgetPrivate::mapToReceiver(const QPointF &pos, const QWidget *receiver) const
525 // Map event position from us to the receiver, preserving its
526 // precision (don't use QWidget::mapFrom here).
527 while (receiver && receiver != widget) {
528 p -= QPointF(receiver->pos());
529 receiver = receiver->parentWidget();
535 Constructs a new QGraphicsProxy widget. \a parent and \a wFlags are passed
536 to QGraphicsItem's constructor.
538 QGraphicsProxyWidget::QGraphicsProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
539 : QGraphicsWidget(*new QGraphicsProxyWidgetPrivate, parent, 0, wFlags)
541 Q_D(QGraphicsProxyWidget);
546 Destroys the proxy widget and any embedded widget.
548 QGraphicsProxyWidget::~QGraphicsProxyWidget()
550 Q_D(QGraphicsProxyWidget);
552 QObject::disconnect(d->widget, SIGNAL(destroyed()), this, SLOT(_q_removeWidgetSlot()));
558 Embeds \a widget into this proxy widget. The embedded widget must reside
559 exclusively either inside or outside of Graphics View. You cannot embed a
560 widget as long as it is is visible elsewhere in the UI, at the same time.
562 \a widget must be a top-level widget whose parent is 0.
564 When the widget is embedded, its state (e.g., visible, enabled, geometry,
565 size hints) is copied into the proxy widget. If the embedded widget is
566 explicitly hidden or disabled, the proxy widget will become explicitly
567 hidden or disabled after embedding is complete. The class documentation
568 has a full overview over the shared state.
570 QGraphicsProxyWidget's window flags determine whether the widget, after
571 embedding, will be given window decorations or not.
573 After this function returns, QGraphicsProxyWidget will keep its state
574 synchronized with that of \a widget whenever possible.
576 If a widget is already embedded by this proxy when this function is
577 called, that widget will first be automatically unembedded. Passing 0 for
578 the \a widget argument will only unembed the widget, and the ownership of
579 the currently embedded widget will be passed on to the caller.
580 Every child widget that are embedded will also be embedded and their proxy
583 Note that widgets with the Qt::WA_PaintOnScreen widget attribute
584 set and widgets that wrap an external application or controller
585 cannot be embedded. Examples are QGLWidget and QAxWidget.
589 void QGraphicsProxyWidget::setWidget(QWidget *widget)
591 Q_D(QGraphicsProxyWidget);
592 d->setWidget_helper(widget, true);
595 void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow)
597 Q_Q(QGraphicsProxyWidget);
598 if (newWidget == widget)
601 QObject::disconnect(widget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
602 widget->removeEventFilter(q);
603 widget->setAttribute(Qt::WA_DontShowOnScreen, false);
604 widget->d_func()->extra->proxyWidget = 0;
605 resolveFont(inheritedFontResolveMask);
606 resolvePalette(inheritedPaletteResolveMask);
609 foreach (QGraphicsItem *child, q->childItems()) {
610 if (child->d_ptr->isProxyWidget()) {
611 QGraphicsProxyWidget *childProxy = static_cast<QGraphicsProxyWidget *>(child);
612 QWidget * parent = childProxy->widget();
613 while (parent->parentWidget() != 0) {
614 if (parent == widget)
616 parent = parent->parentWidget();
618 if (!childProxy->widget() || parent != widget)
620 childProxy->setWidget(0);
629 q->setAcceptHoverEvents(false);
635 if (!newWidget->isWindow()) {
636 QWExtra *extra = newWidget->parentWidget()->d_func()->extra;
637 if (!extra || !extra->proxyWidget) {
638 qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p "
639 "which is not a toplevel widget, and is not a child of an embedded widget", newWidget);
644 // Register this proxy within the widget's private.
645 // ### This is a bit backdoorish
646 QWExtra *extra = newWidget->d_func()->extra;
648 newWidget->d_func()->createExtra();
649 extra = newWidget->d_func()->extra;
651 QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;
653 if (*proxyWidget != q) {
654 qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"
655 "; already embedded", newWidget);
661 newWidget->setAttribute(Qt::WA_DontShowOnScreen);
662 newWidget->ensurePolished();
663 // Do not wait for this widget to close before the app closes ###
664 // shouldn't this widget inherit the attribute?
665 newWidget->setAttribute(Qt::WA_QuitOnClose, false);
666 q->setAcceptHoverEvents(true);
668 if (newWidget->testAttribute(Qt::WA_NoSystemBackground))
669 q->setAttribute(Qt::WA_NoSystemBackground);
670 if (newWidget->testAttribute(Qt::WA_OpaquePaintEvent))
671 q->setAttribute(Qt::WA_OpaquePaintEvent);
675 // Changes only go from the widget to the proxy.
676 enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
677 visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
678 posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
679 sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
681 if ((autoShow && !newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide)) || !newWidget->testAttribute(Qt::WA_WState_Hidden)) {
685 // Copy the state from the widget onto the proxy.
687 if (newWidget->testAttribute(Qt::WA_SetCursor))
688 q->setCursor(widget->cursor());
690 q->setEnabled(newWidget->isEnabled());
691 q->setVisible(newWidget->isVisible());
692 q->setLayoutDirection(newWidget->layoutDirection());
693 if (newWidget->testAttribute(Qt::WA_SetStyle))
694 q->setStyle(widget->style());
696 resolveFont(inheritedFontResolveMask);
697 resolvePalette(inheritedPaletteResolveMask);
699 if (!newWidget->testAttribute(Qt::WA_Resized))
700 newWidget->adjustSize();
702 int left, top, right, bottom;
703 newWidget->getContentsMargins(&left, &top, &right, &bottom);
704 q->setContentsMargins(left, top, right, bottom);
705 q->setWindowTitle(newWidget->windowTitle());
707 // size policies and constraints..
708 q->setSizePolicy(newWidget->sizePolicy());
709 QSize sz = newWidget->minimumSize();
710 q->setMinimumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
711 sz = newWidget->maximumSize();
712 q->setMaximumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
714 updateProxyGeometryFromWidget();
716 updateProxyInputMethodAcceptanceFromWidget();
718 // Hook up the event filter to keep the state up to date.
719 newWidget->installEventFilter(q);
720 QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
722 // Changes no longer go only from the widget to the proxy.
723 enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
724 visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
725 posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
726 sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
730 Returns a pointer to the embedded widget.
734 QWidget *QGraphicsProxyWidget::widget() const
736 Q_D(const QGraphicsProxyWidget);
741 Returns the rectangle for \a widget, which must be a descendant of
742 widget(), or widget() itself, in this proxy item's local coordinates.
744 If no widget is embedded, \a widget is 0, or \a widget is not a
745 descendant of the embedded widget, this function returns an empty QRectF.
749 QRectF QGraphicsProxyWidget::subWidgetRect(const QWidget *widget) const
751 Q_D(const QGraphicsProxyWidget);
752 if (!widget || !d->widget)
754 if (d->widget == widget || d->widget->isAncestorOf(widget))
755 return QRectF(widget->mapTo(d->widget, QPoint(0, 0)), widget->size());
762 void QGraphicsProxyWidget::setGeometry(const QRectF &rect)
764 Q_D(QGraphicsProxyWidget);
765 bool proxyResizesWidget = !d->posChangeMode && !d->sizeChangeMode;
766 if (proxyResizesWidget) {
767 d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
768 d->sizeChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
770 QGraphicsWidget::setGeometry(rect);
771 if (proxyResizesWidget) {
772 d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
773 d->sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
780 QVariant QGraphicsProxyWidget::itemChange(GraphicsItemChange change,
781 const QVariant &value)
783 Q_D(QGraphicsProxyWidget);
786 case ItemPositionChange:
787 // The item's position is either changed directly on the proxy, in
788 // which case the position change should propagate to the widget,
789 // otherwise it happens as a side effect when filtering QEvent::Move.
790 if (!d->posChangeMode)
791 d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
793 case ItemPositionHasChanged:
794 // Move the internal widget if we're in widget-to-proxy
795 // mode. Otherwise the widget has already moved.
796 if (d->widget && d->posChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
797 d->widget->move(value.toPoint());
798 if (d->posChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
799 d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
801 case ItemVisibleChange:
802 if (!d->visibleChangeMode)
803 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
805 case ItemVisibleHasChanged:
806 if (d->widget && d->visibleChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
807 d->widget->setVisible(isVisible());
808 if (d->visibleChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
809 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
811 case ItemEnabledChange:
812 if (!d->enabledChangeMode)
813 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
815 case ItemEnabledHasChanged:
816 if (d->widget && d->enabledChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
817 d->widget->setEnabled(isEnabled());
818 if (d->enabledChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
819 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
824 return QGraphicsWidget::itemChange(change, value);
830 bool QGraphicsProxyWidget::event(QEvent *event)
832 Q_D(QGraphicsProxyWidget);
834 return QGraphicsWidget::event(event);
836 switch (event->type()) {
837 case QEvent::StyleChange:
838 // Propagate style changes to the embedded widget.
839 if (!d->styleChangeMode) {
840 d->styleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
841 d->widget->setStyle(style());
842 d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
845 case QEvent::FontChange: {
846 // Propagate to widget.
847 QWidgetPrivate *wd = d->widget->d_func();
848 int mask = d->font.resolve() | d->inheritedFontResolveMask;
849 wd->inheritedFontResolveMask = mask;
853 case QEvent::PaletteChange: {
854 // Propagate to widget.
855 QWidgetPrivate *wd = d->widget->d_func();
856 int mask = d->palette.resolve() | d->inheritedPaletteResolveMask;
857 wd->inheritedPaletteResolveMask = mask;
858 wd->resolvePalette();
861 case QEvent::InputMethod: {
862 // Forward input method events if the focus widget enables
864 // ### Qt 4.5: this code must also go into a reimplementation
865 // of inputMethodEvent().
866 QWidget *focusWidget = d->widget->focusWidget();
867 if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
868 QApplication::sendEvent(focusWidget, event);
871 case QEvent::ShortcutOverride: {
872 QWidget *focusWidget = d->widget->focusWidget();
873 while (focusWidget) {
874 QApplication::sendEvent(focusWidget, event);
875 if (event->isAccepted())
877 focusWidget = focusWidget->parentWidget();
881 case QEvent::KeyPress: {
882 QKeyEvent *k = static_cast<QKeyEvent *>(event);
883 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
884 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
885 QWidget *focusWidget = d->widget->focusWidget();
886 while (focusWidget) {
887 bool res = QApplication::sendEvent(focusWidget, event);
888 if ((res && event->isAccepted()) || (isWindow() && focusWidget == d->widget)) {
892 focusWidget = focusWidget->parentWidget();
899 #ifndef QT_NO_TOOLTIP
900 case QEvent::GraphicsSceneHelp: {
901 // Propagate the help event (for tooltip) to the widget under mouse
902 if (d->lastWidgetUnderMouse) {
903 QGraphicsSceneHelpEvent *he = static_cast<QGraphicsSceneHelpEvent *>(event);
904 QPoint pos = d->mapToReceiver(mapFromScene(he->scenePos()), d->lastWidgetUnderMouse).toPoint();
905 QHelpEvent e(QEvent::ToolTip, pos, he->screenPos());
906 QApplication::sendEvent(d->lastWidgetUnderMouse, &e);
907 event->setAccepted(e.isAccepted());
908 return e.isAccepted();
912 case QEvent::ToolTipChange: {
913 // Propagate tooltip change to the widget
914 if (!d->tooltipChangeMode) {
915 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
916 d->widget->setToolTip(toolTip());
917 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
925 return QGraphicsWidget::event(event);
931 bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
933 Q_D(QGraphicsProxyWidget);
935 if (object == d->widget) {
936 switch (event->type()) {
937 case QEvent::LayoutRequest:
941 // If the widget resizes itself, we resize the proxy too.
942 // Prevent feed-back by checking the geometry change mode.
943 if (!d->sizeChangeMode)
944 d->updateProxyGeometryFromWidget();
947 // If the widget moves itself, we move the proxy too. Prevent
948 // feed-back by checking the geometry change mode.
949 if (!d->posChangeMode)
950 d->updateProxyGeometryFromWidget();
954 // If the widget toggles its visible state, the proxy will follow.
955 if (!d->visibleChangeMode) {
956 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
957 setVisible(event->type() == QEvent::Show);
958 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
961 case QEvent::EnabledChange:
962 // If the widget toggles its enabled state, the proxy will follow.
963 if (!d->enabledChangeMode) {
964 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
965 setEnabled(d->widget->isEnabled());
966 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
969 case QEvent::StyleChange:
970 // Propagate style changes to the proxy.
971 if (!d->styleChangeMode) {
972 d->styleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
973 setStyle(d->widget->style());
974 d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
977 #ifndef QT_NO_TOOLTIP
978 case QEvent::ToolTipChange:
979 // Propagate tooltip change to the proxy.
980 if (!d->tooltipChangeMode) {
981 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
982 setToolTip(d->widget->toolTip());
983 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
991 return QGraphicsWidget::eventFilter(object, event);
997 void QGraphicsProxyWidget::showEvent(QShowEvent *event)
1005 void QGraphicsProxyWidget::hideEvent(QHideEvent *event)
1010 #ifndef QT_NO_CONTEXTMENU
1014 void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
1016 Q_D(QGraphicsProxyWidget);
1017 if (!event || !d->widget || !d->widget->isVisible() || !hasFocus())
1020 // Find widget position and receiver.
1021 QPointF pos = event->pos();
1022 QPointer<QWidget> alienWidget = d->widget->childAt(pos.toPoint());
1023 QPointer<QWidget> receiver = alienWidget ? alienWidget : d->widget;
1025 // Map event position from us to the receiver
1026 pos = d->mapToReceiver(pos, receiver);
1028 QPoint globalPos = receiver->mapToGlobal(pos.toPoint());
1029 //If the receiver by-pass the proxy its popups
1030 //will be top level QWidgets therefore they need
1031 //the screen position. mapToGlobal expect the widget to
1032 //have proper coordinates in regards of the windowing system
1033 //but it's not true because the widget is embedded.
1034 if (bypassGraphicsProxyWidget(receiver))
1035 globalPos = event->screenPos();
1037 // Send mouse event. ### Doesn't propagate the event.
1038 QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()),
1039 pos.toPoint(), globalPos, event->modifiers());
1040 QApplication::sendEvent(receiver, &contextMenuEvent);
1042 event->setAccepted(contextMenuEvent.isAccepted());
1044 #endif // QT_NO_CONTEXTMENU
1046 #ifndef QT_NO_DRAGANDDROP
1050 void QGraphicsProxyWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
1052 #ifdef QT_NO_DRAGANDDROP
1055 Q_D(QGraphicsProxyWidget);
1059 QDragEnterEvent proxyDragEnter(event->pos().toPoint(), event->dropAction(), event->mimeData(), event->buttons(), event->modifiers());
1060 proxyDragEnter.setAccepted(event->isAccepted());
1061 QApplication::sendEvent(d->widget, &proxyDragEnter);
1062 event->setAccepted(proxyDragEnter.isAccepted());
1063 if (proxyDragEnter.isAccepted()) // we discard answerRect
1064 event->setDropAction(proxyDragEnter.dropAction());
1070 void QGraphicsProxyWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
1073 #ifndef QT_NO_DRAGANDDROP
1074 Q_D(QGraphicsProxyWidget);
1075 if (!d->widget || !d->dragDropWidget)
1077 QDragLeaveEvent proxyDragLeave;
1078 QApplication::sendEvent(d->dragDropWidget, &proxyDragLeave);
1079 d->dragDropWidget = 0;
1086 void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
1088 #ifdef QT_NO_DRAGANDDROP
1091 Q_D(QGraphicsProxyWidget);
1094 QPointF p = event->pos();
1096 QPointer<QWidget> subWidget = d->widget->childAt(p.toPoint());
1097 QPointer<QWidget> receiver = subWidget ? subWidget : d->widget;
1098 bool eventDelivered = false;
1099 for (; receiver; receiver = receiver->parentWidget()) {
1100 if (!receiver->isEnabled() || !receiver->acceptDrops())
1102 // Map event position from us to the receiver
1103 QPoint receiverPos = d->mapToReceiver(p, receiver).toPoint();
1104 if (receiver != d->dragDropWidget) {
1105 // Try to enter before we leave
1106 QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1107 dragEnter.setDropAction(event->proposedAction());
1108 QApplication::sendEvent(receiver, &dragEnter);
1109 event->setAccepted(dragEnter.isAccepted());
1110 event->setDropAction(dragEnter.dropAction());
1111 if (!event->isAccepted()) {
1112 // propagate to the parent widget
1116 d->lastDropAction = event->dropAction();
1118 if (d->dragDropWidget) {
1119 QDragLeaveEvent dragLeave;
1120 QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1122 d->dragDropWidget = receiver;
1125 QDragMoveEvent dragMove(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1126 event->setDropAction(d->lastDropAction);
1127 QApplication::sendEvent(receiver, &dragMove);
1128 event->setAccepted(dragMove.isAccepted());
1129 event->setDropAction(dragMove.dropAction());
1130 if (event->isAccepted())
1131 d->lastDropAction = event->dropAction();
1132 eventDelivered = true;
1136 if (!eventDelivered) {
1137 if (d->dragDropWidget) {
1138 // Leave the last drag drop item
1139 QDragLeaveEvent dragLeave;
1140 QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1141 d->dragDropWidget = 0;
1144 event->setDropAction(Qt::IgnoreAction);
1152 void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
1154 #ifdef QT_NO_DRAGANDDROP
1157 Q_D(QGraphicsProxyWidget);
1158 if (d->widget && d->dragDropWidget) {
1159 QPoint widgetPos = d->mapToReceiver(event->pos(), d->dragDropWidget).toPoint();
1160 QDropEvent dropEvent(widgetPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1161 QApplication::sendEvent(d->dragDropWidget, &dropEvent);
1162 event->setAccepted(dropEvent.isAccepted());
1163 d->dragDropWidget = 0;
1172 void QGraphicsProxyWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1180 void QGraphicsProxyWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1183 Q_D(QGraphicsProxyWidget);
1184 // If hoverMove was compressed away, make sure we update properly here.
1185 if (d->lastWidgetUnderMouse) {
1186 QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
1187 d->lastWidgetUnderMouse = 0;
1194 void QGraphicsProxyWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1196 Q_D(QGraphicsProxyWidget);
1197 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1198 qDebug() << "QGraphicsProxyWidget::hoverMoveEvent";
1200 // Ignore events on the window frame.
1201 if (!d->widget || !rect().contains(event->pos())) {
1202 if (d->lastWidgetUnderMouse) {
1203 QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
1204 d->lastWidgetUnderMouse = 0;
1209 d->embeddedMouseGrabber = 0;
1210 d->sendWidgetMouseEvent(event);
1216 void QGraphicsProxyWidget::grabMouseEvent(QEvent *event)
1224 void QGraphicsProxyWidget::ungrabMouseEvent(QEvent *event)
1226 Q_D(QGraphicsProxyWidget);
1228 d->embeddedMouseGrabber = 0;
1234 void QGraphicsProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1236 Q_D(QGraphicsProxyWidget);
1237 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1238 qDebug() << "QGraphicsProxyWidget::mouseMoveEvent";
1240 d->sendWidgetMouseEvent(event);
1246 void QGraphicsProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
1248 Q_D(QGraphicsProxyWidget);
1249 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1250 qDebug() << "QGraphicsProxyWidget::mousePressEvent";
1252 d->sendWidgetMouseEvent(event);
1258 void QGraphicsProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1260 Q_D(QGraphicsProxyWidget);
1261 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1262 qDebug() << "QGraphicsProxyWidget::mouseDoubleClickEvent";
1264 d->sendWidgetMouseEvent(event);
1270 #ifndef QT_NO_WHEELEVENT
1271 void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event)
1273 Q_D(QGraphicsProxyWidget);
1274 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1275 qDebug() << "QGraphicsProxyWidget::wheelEvent";
1280 QPointF pos = event->pos();
1281 QPointer<QWidget> receiver = d->widget->childAt(pos.toPoint());
1283 receiver = d->widget;
1285 // Map event position from us to the receiver
1286 pos = d->mapToReceiver(pos, receiver);
1288 // Send mouse event.
1289 QWheelEvent wheelEvent(pos.toPoint(), event->screenPos(), event->delta(),
1290 event->buttons(), event->modifiers(), event->orientation());
1291 QPointer<QWidget> focusWidget = d->widget->focusWidget();
1292 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
1293 qt_sendSpontaneousEvent(receiver, &wheelEvent);
1294 event->setAccepted(wheelEvent.isAccepted());
1296 // ### Remove, this should be done by proper focusIn/focusOut events.
1297 if (focusWidget && !focusWidget->hasFocus()) {
1298 focusWidget->update();
1299 focusWidget = d->widget->focusWidget();
1300 if (focusWidget && focusWidget->hasFocus())
1301 focusWidget->update();
1309 void QGraphicsProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1311 Q_D(QGraphicsProxyWidget);
1312 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1313 qDebug() << "QGraphicsProxyWidget::mouseReleaseEvent";
1315 d->sendWidgetMouseEvent(event);
1321 void QGraphicsProxyWidget::keyPressEvent(QKeyEvent *event)
1323 Q_D(QGraphicsProxyWidget);
1324 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1325 qDebug() << "QGraphicsProxyWidget::keyPressEvent";
1327 d->sendWidgetKeyEvent(event);
1333 void QGraphicsProxyWidget::keyReleaseEvent(QKeyEvent *event)
1335 Q_D(QGraphicsProxyWidget);
1336 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1337 qDebug() << "QGraphicsProxyWidget::keyReleaseEvent";
1339 d->sendWidgetKeyEvent(event);
1345 void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
1347 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1348 qDebug() << "QGraphicsProxyWidget::focusInEvent";
1350 Q_D(QGraphicsProxyWidget);
1352 if (d->focusFromWidgetToProxy) {
1353 // Prevent recursion when the proxy autogains focus through the
1354 // embedded widget calling setFocus(). ### Could be done with event
1355 // filter on FocusIn instead?
1359 d->proxyIsGivingFocus = true;
1361 switch (event->reason()) {
1362 case Qt::TabFocusReason: {
1363 if (QWidget *focusChild = d->findFocusChild(0, true))
1364 focusChild->setFocus(event->reason());
1367 case Qt::BacktabFocusReason:
1368 if (QWidget *focusChild = d->findFocusChild(0, false))
1369 focusChild->setFocus(event->reason());
1372 if (d->widget && d->widget->focusWidget()) {
1373 d->widget->focusWidget()->setFocus(event->reason());
1378 d->proxyIsGivingFocus = false;
1384 void QGraphicsProxyWidget::focusOutEvent(QFocusEvent *event)
1386 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1387 qDebug() << "QGraphicsProxyWidget::focusOutEvent";
1389 Q_D(QGraphicsProxyWidget);
1391 // We need to explicitly remove subfocus from the embedded widget's
1393 if (QWidget *focusWidget = d->widget->focusWidget())
1394 d->removeSubFocusHelper(focusWidget, event->reason());
1401 bool QGraphicsProxyWidget::focusNextPrevChild(bool next)
1403 Q_D(QGraphicsProxyWidget);
1404 if (!d->widget || !d->scene)
1405 return QGraphicsWidget::focusNextPrevChild(next);
1407 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
1408 QWidget *lastFocusChild = d->widget->focusWidget();
1409 if (QWidget *newFocusChild = d->findFocusChild(lastFocusChild, next)) {
1410 newFocusChild->setFocus(reason);
1414 return QGraphicsWidget::focusNextPrevChild(next);
1420 QSizeF QGraphicsProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
1422 Q_D(const QGraphicsProxyWidget);
1424 return QGraphicsWidget::sizeHint(which, constraint);
1428 case Qt::PreferredSize:
1429 if (QLayout *l = d->widget->layout())
1432 sh = d->widget->sizeHint();
1434 case Qt::MinimumSize:
1435 if (QLayout *l = d->widget->layout())
1436 sh = l->minimumSize();
1438 sh = d->widget->minimumSizeHint();
1440 case Qt::MaximumSize:
1441 if (QLayout *l = d->widget->layout())
1442 sh = l->maximumSize();
1444 sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
1446 case Qt::MinimumDescent:
1458 void QGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
1460 Q_D(QGraphicsProxyWidget);
1462 if (d->sizeChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
1463 d->widget->resize(event->newSize().toSize());
1465 QGraphicsWidget::resizeEvent(event);
1471 void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
1473 Q_D(QGraphicsProxyWidget);
1475 if (!d->widget || !d->widget->isVisible())
1478 // Filter out repaints on the window frame.
1479 const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect();
1480 if (exposedWidgetRect.isEmpty())
1483 // Disable QPainter's default pen being cosmetic. This allows widgets and
1484 // styles to follow Qt's existing defaults without getting ugly cosmetic
1485 // lines when scaled.
1486 bool restore = !(painter->renderHints() & QPainter::NonCosmeticDefaultPen);
1487 painter->setRenderHints(QPainter::NonCosmeticDefaultPen, true);
1489 d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect);
1491 // Restore the render hints if necessary.
1493 painter->setRenderHints(QPainter::NonCosmeticDefaultPen, false);
1499 int QGraphicsProxyWidget::type() const
1507 Creates a proxy widget for the given \a child of the widget
1508 contained in this proxy.
1510 This function makes it possible to acquire proxies for
1511 non top-level widgets. For instance, you can embed a dialog,
1512 and then transform only one of its widgets.
1514 If the widget is already embedded, return the existing proxy widget.
1516 \sa newProxyWidget(), QGraphicsScene::addWidget()
1518 QGraphicsProxyWidget *QGraphicsProxyWidget::createProxyForChildWidget(QWidget *child)
1520 QGraphicsProxyWidget *proxy = child->graphicsProxyWidget();
1523 if (!child->parentWidget()) {
1524 qWarning("QGraphicsProxyWidget::createProxyForChildWidget: top-level widget not in a QGraphicsScene");
1528 QGraphicsProxyWidget *parentProxy = createProxyForChildWidget(child->parentWidget());
1532 if (!QMetaObject::invokeMethod(parentProxy, "newProxyWidget", Qt::DirectConnection,
1533 Q_RETURN_ARG(QGraphicsProxyWidget*, proxy), Q_ARG(const QWidget*, child)))
1535 proxy->setParent(parentProxy);
1536 proxy->setWidget(child);
1541 \fn QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *child)
1544 Creates a proxy widget for the given \a child of the widget contained in this
1547 You should not call this function directly; use
1548 QGraphicsProxyWidget::createProxyForChildWidget() instead.
1550 This function is a fake virtual slot that you can reimplement in
1551 your subclass in order to control how new proxy widgets are
1552 created. The default implementation returns a proxy created with
1553 the QGraphicsProxyWidget() constructor with this proxy widget as
1556 \sa createProxyForChildWidget()
1558 QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *)
1560 return new QGraphicsProxyWidget(this);
1567 #include "moc_qgraphicsproxywidget.cpp"
1569 #endif //QT_NO_GRAPHICSVIEW