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 = QMouseEvent::createExtendedMouseEvent(type, pos,
278 receiver->mapToGlobal(pos.toPoint()), event->button(),
279 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());
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);
343 Reimplemented from QGraphicsItemPrivate. ### Qt 5: Move impl to
344 reimplementation QGraphicsProxyWidget::inputMethodQuery().
346 QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const
348 Q_Q(const QGraphicsProxyWidget);
349 if (!widget || !q->hasFocus())
352 QWidget *focusWidget = widget->focusWidget();
354 focusWidget = widget;
355 QVariant v = focusWidget->inputMethodQuery(query);
356 QPointF focusWidgetPos = q->subWidgetRect(focusWidget).topLeft();
358 case QVariant::RectF:
359 v = v.toRectF().translated(focusWidgetPos);
361 case QVariant::PointF:
362 v = v.toPointF() + focusWidgetPos;
365 v = v.toRect().translated(focusWidgetPos.toPoint());
367 case QVariant::Point:
368 v = v.toPoint() + focusWidgetPos.toPoint();
378 Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
380 QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
385 // Run around the focus chain until we find a widget that can take tab focus.
387 child = next ? (QWidget *)widget : widget->d_func()->focus_prev;
389 child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
390 if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) {
395 QWidget *oldChild = child;
396 uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
398 if (child->isEnabled()
399 && child->isVisibleTo(widget)
400 && ((child->focusPolicy() & focus_flag) == focus_flag)
401 && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
404 child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
405 } while (child != oldChild && !(next && child == widget) && !(!next && child == widget->d_func()->focus_prev));
412 void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot()
414 Q_Q(QGraphicsProxyWidget);
422 void QGraphicsProxyWidgetPrivate::updateWidgetGeometryFromProxy()
429 void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
431 Q_Q(QGraphicsProxyWidget);
435 QRectF widgetGeometry = widget->geometry();
436 QWidget *parentWidget = widget->parentWidget();
437 if (widget->isWindow()) {
438 QGraphicsProxyWidget *proxyParent = 0;
439 if (parentWidget && (proxyParent = qobject_cast<QGraphicsProxyWidget *>(q->parentWidget()))) {
440 // Nested window proxy (e.g., combobox popup), map widget to the
441 // parent widget's global coordinates, and map that to the parent
442 // proxy's child coordinates.
443 widgetGeometry.moveTo(proxyParent->subWidgetRect(parentWidget).topLeft()
444 + parentWidget->mapFromGlobal(widget->pos()));
448 // Adjust to size hint if the widget has never been resized.
449 if (!widget->size().isValid())
450 widgetGeometry.setSize(widget->sizeHint());
452 // Assign new geometry.
453 posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
454 sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
455 q->setGeometry(widgetGeometry);
456 posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
457 sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
463 void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
465 Q_Q(QGraphicsProxyWidget);
469 QWidget *focusWidget = widget->focusWidget();
471 focusWidget = widget;
472 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
473 focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
479 Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
480 widget and a descendant of the widget managed by this proxy. A separate subproxy
481 will be created as a child of this proxy widget to manage \a subWin.
483 void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
486 if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
487 QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
488 subProxy->d_func()->setWidget_helper(subWin, false);
495 Removes ("unembeds") \a subWin and deletes the proxy holder item. This can
496 happen when QWidget::setParent() reparents the embedded window out of
499 void QGraphicsProxyWidgetPrivate::unembedSubWindow(QWidget *subWin)
501 foreach (QGraphicsItem *child, children) {
502 if (child->isWidget()) {
503 if (QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))) {
504 if (proxy->widget() == subWin) {
506 scene->removeItem(proxy);
515 bool QGraphicsProxyWidgetPrivate::isProxyWidget() const
523 QPointF QGraphicsProxyWidgetPrivate::mapToReceiver(const QPointF &pos, const QWidget *receiver) const
526 // Map event position from us to the receiver, preserving its
527 // precision (don't use QWidget::mapFrom here).
528 while (receiver && receiver != widget) {
529 p -= QPointF(receiver->pos());
530 receiver = receiver->parentWidget();
536 Constructs a new QGraphicsProxy widget. \a parent and \a wFlags are passed
537 to QGraphicsItem's constructor.
539 QGraphicsProxyWidget::QGraphicsProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
540 : QGraphicsWidget(*new QGraphicsProxyWidgetPrivate, parent, 0, wFlags)
542 Q_D(QGraphicsProxyWidget);
547 Destroys the proxy widget and any embedded widget.
549 QGraphicsProxyWidget::~QGraphicsProxyWidget()
551 Q_D(QGraphicsProxyWidget);
553 QObject::disconnect(d->widget, SIGNAL(destroyed()), this, SLOT(_q_removeWidgetSlot()));
559 Embeds \a widget into this proxy widget. The embedded widget must reside
560 exclusively either inside or outside of Graphics View. You cannot embed a
561 widget as long as it is is visible elsewhere in the UI, at the same time.
563 \a widget must be a top-level widget whose parent is 0.
565 When the widget is embedded, its state (e.g., visible, enabled, geometry,
566 size hints) is copied into the proxy widget. If the embedded widget is
567 explicitly hidden or disabled, the proxy widget will become explicitly
568 hidden or disabled after embedding is complete. The class documentation
569 has a full overview over the shared state.
571 QGraphicsProxyWidget's window flags determine whether the widget, after
572 embedding, will be given window decorations or not.
574 After this function returns, QGraphicsProxyWidget will keep its state
575 synchronized with that of \a widget whenever possible.
577 If a widget is already embedded by this proxy when this function is
578 called, that widget will first be automatically unembedded. Passing 0 for
579 the \a widget argument will only unembed the widget, and the ownership of
580 the currently embedded widget will be passed on to the caller.
581 Every child widget that are embedded will also be embedded and their proxy
584 Note that widgets with the Qt::WA_PaintOnScreen widget attribute
585 set and widgets that wrap an external application or controller
586 cannot be embedded. Examples are QGLWidget and QAxWidget.
590 void QGraphicsProxyWidget::setWidget(QWidget *widget)
592 Q_D(QGraphicsProxyWidget);
593 d->setWidget_helper(widget, true);
596 void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow)
598 Q_Q(QGraphicsProxyWidget);
599 if (newWidget == widget)
602 QObject::disconnect(widget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
603 widget->removeEventFilter(q);
604 widget->setAttribute(Qt::WA_DontShowOnScreen, false);
605 widget->d_func()->extra->proxyWidget = 0;
606 resolveFont(inheritedFontResolveMask);
607 resolvePalette(inheritedPaletteResolveMask);
610 foreach (QGraphicsItem *child, q->childItems()) {
611 if (child->d_ptr->isProxyWidget()) {
612 QGraphicsProxyWidget *childProxy = static_cast<QGraphicsProxyWidget *>(child);
613 QWidget * parent = childProxy->widget();
614 while (parent->parentWidget() != 0) {
615 if (parent == widget)
617 parent = parent->parentWidget();
619 if (!childProxy->widget() || parent != widget)
621 childProxy->setWidget(0);
630 q->setAcceptHoverEvents(false);
636 if (!newWidget->isWindow()) {
637 QWExtra *extra = newWidget->parentWidget()->d_func()->extra;
638 if (!extra || !extra->proxyWidget) {
639 qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p "
640 "which is not a toplevel widget, and is not a child of an embedded widget", newWidget);
645 // Register this proxy within the widget's private.
646 // ### This is a bit backdoorish
647 QWExtra *extra = newWidget->d_func()->extra;
649 newWidget->d_func()->createExtra();
650 extra = newWidget->d_func()->extra;
652 QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget;
654 if (*proxyWidget != q) {
655 qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p"
656 "; already embedded", newWidget);
662 newWidget->setAttribute(Qt::WA_DontShowOnScreen);
663 newWidget->ensurePolished();
664 // Do not wait for this widget to close before the app closes ###
665 // shouldn't this widget inherit the attribute?
666 newWidget->setAttribute(Qt::WA_QuitOnClose, false);
667 q->setAcceptHoverEvents(true);
669 if (newWidget->testAttribute(Qt::WA_NoSystemBackground))
670 q->setAttribute(Qt::WA_NoSystemBackground);
671 if (newWidget->testAttribute(Qt::WA_OpaquePaintEvent))
672 q->setAttribute(Qt::WA_OpaquePaintEvent);
676 // Changes only go from the widget to the proxy.
677 enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
678 visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
679 posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
680 sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
682 if ((autoShow && !newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide)) || !newWidget->testAttribute(Qt::WA_WState_Hidden)) {
686 // Copy the state from the widget onto the proxy.
688 if (newWidget->testAttribute(Qt::WA_SetCursor))
689 q->setCursor(widget->cursor());
691 q->setEnabled(newWidget->isEnabled());
692 q->setVisible(newWidget->isVisible());
693 q->setLayoutDirection(newWidget->layoutDirection());
694 if (newWidget->testAttribute(Qt::WA_SetStyle))
695 q->setStyle(widget->style());
697 resolveFont(inheritedFontResolveMask);
698 resolvePalette(inheritedPaletteResolveMask);
700 if (!newWidget->testAttribute(Qt::WA_Resized))
701 newWidget->adjustSize();
703 int left, top, right, bottom;
704 newWidget->getContentsMargins(&left, &top, &right, &bottom);
705 q->setContentsMargins(left, top, right, bottom);
706 q->setWindowTitle(newWidget->windowTitle());
708 // size policies and constraints..
709 q->setSizePolicy(newWidget->sizePolicy());
710 QSize sz = newWidget->minimumSize();
711 q->setMinimumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
712 sz = newWidget->maximumSize();
713 q->setMaximumSize(sz.isNull() ? QSizeF() : QSizeF(sz));
715 updateProxyGeometryFromWidget();
717 updateProxyInputMethodAcceptanceFromWidget();
719 // Hook up the event filter to keep the state up to date.
720 newWidget->installEventFilter(q);
721 QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
723 // Changes no longer go only from the widget to the proxy.
724 enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
725 visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
726 posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
727 sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
731 Returns a pointer to the embedded widget.
735 QWidget *QGraphicsProxyWidget::widget() const
737 Q_D(const QGraphicsProxyWidget);
742 Returns the rectangle for \a widget, which must be a descendant of
743 widget(), or widget() itself, in this proxy item's local coordinates.
745 If no widget is embedded, \a widget is 0, or \a widget is not a
746 descendant of the embedded widget, this function returns an empty QRectF.
750 QRectF QGraphicsProxyWidget::subWidgetRect(const QWidget *widget) const
752 Q_D(const QGraphicsProxyWidget);
753 if (!widget || !d->widget)
755 if (d->widget == widget || d->widget->isAncestorOf(widget))
756 return QRectF(widget->mapTo(d->widget, QPoint(0, 0)), widget->size());
763 void QGraphicsProxyWidget::setGeometry(const QRectF &rect)
765 Q_D(QGraphicsProxyWidget);
766 bool proxyResizesWidget = !d->posChangeMode && !d->sizeChangeMode;
767 if (proxyResizesWidget) {
768 d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
769 d->sizeChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
771 QGraphicsWidget::setGeometry(rect);
772 if (proxyResizesWidget) {
773 d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
774 d->sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
781 QVariant QGraphicsProxyWidget::itemChange(GraphicsItemChange change,
782 const QVariant &value)
784 Q_D(QGraphicsProxyWidget);
787 case ItemPositionChange:
788 // The item's position is either changed directly on the proxy, in
789 // which case the position change should propagate to the widget,
790 // otherwise it happens as a side effect when filtering QEvent::Move.
791 if (!d->posChangeMode)
792 d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
794 case ItemPositionHasChanged:
795 // Move the internal widget if we're in widget-to-proxy
796 // mode. Otherwise the widget has already moved.
797 if (d->widget && d->posChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
798 d->widget->move(value.toPoint());
799 if (d->posChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
800 d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
802 case ItemVisibleChange:
803 if (!d->visibleChangeMode)
804 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
806 case ItemVisibleHasChanged:
807 if (d->widget && d->visibleChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
808 d->widget->setVisible(isVisible());
809 if (d->visibleChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
810 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
812 case ItemEnabledChange:
813 if (!d->enabledChangeMode)
814 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
816 case ItemEnabledHasChanged:
817 if (d->widget && d->enabledChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
818 d->widget->setEnabled(isEnabled());
819 if (d->enabledChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode)
820 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
825 return QGraphicsWidget::itemChange(change, value);
831 bool QGraphicsProxyWidget::event(QEvent *event)
833 Q_D(QGraphicsProxyWidget);
835 return QGraphicsWidget::event(event);
837 switch (event->type()) {
838 case QEvent::StyleChange:
839 // Propagate style changes to the embedded widget.
840 if (!d->styleChangeMode) {
841 d->styleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
842 d->widget->setStyle(style());
843 d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
846 case QEvent::FontChange: {
847 // Propagate to widget.
848 QWidgetPrivate *wd = d->widget->d_func();
849 int mask = d->font.resolve() | d->inheritedFontResolveMask;
850 wd->inheritedFontResolveMask = mask;
854 case QEvent::PaletteChange: {
855 // Propagate to widget.
856 QWidgetPrivate *wd = d->widget->d_func();
857 int mask = d->palette.resolve() | d->inheritedPaletteResolveMask;
858 wd->inheritedPaletteResolveMask = mask;
859 wd->resolvePalette();
862 case QEvent::InputMethod: {
863 // Forward input method events if the focus widget enables
865 // ### Qt 4.5: this code must also go into a reimplementation
866 // of inputMethodEvent().
867 QWidget *focusWidget = d->widget->focusWidget();
868 if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
869 QApplication::sendEvent(focusWidget, event);
872 case QEvent::ShortcutOverride: {
873 QWidget *focusWidget = d->widget->focusWidget();
874 while (focusWidget) {
875 QApplication::sendEvent(focusWidget, event);
876 if (event->isAccepted())
878 focusWidget = focusWidget->parentWidget();
882 case QEvent::KeyPress: {
883 QKeyEvent *k = static_cast<QKeyEvent *>(event);
884 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
885 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
886 QWidget *focusWidget = d->widget->focusWidget();
887 while (focusWidget) {
888 bool res = QApplication::sendEvent(focusWidget, event);
889 if ((res && event->isAccepted()) || (isWindow() && focusWidget == d->widget)) {
893 focusWidget = focusWidget->parentWidget();
900 #ifndef QT_NO_TOOLTIP
901 case QEvent::GraphicsSceneHelp: {
902 // Propagate the help event (for tooltip) to the widget under mouse
903 if (d->lastWidgetUnderMouse) {
904 QGraphicsSceneHelpEvent *he = static_cast<QGraphicsSceneHelpEvent *>(event);
905 QPoint pos = d->mapToReceiver(mapFromScene(he->scenePos()), d->lastWidgetUnderMouse).toPoint();
906 QHelpEvent e(QEvent::ToolTip, pos, he->screenPos());
907 QApplication::sendEvent(d->lastWidgetUnderMouse, &e);
908 event->setAccepted(e.isAccepted());
909 return e.isAccepted();
913 case QEvent::ToolTipChange: {
914 // Propagate tooltip change to the widget
915 if (!d->tooltipChangeMode) {
916 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode;
917 d->widget->setToolTip(toolTip());
918 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
926 return QGraphicsWidget::event(event);
932 bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event)
934 Q_D(QGraphicsProxyWidget);
936 if (object == d->widget) {
937 switch (event->type()) {
938 case QEvent::LayoutRequest:
942 // If the widget resizes itself, we resize the proxy too.
943 // Prevent feed-back by checking the geometry change mode.
944 if (!d->sizeChangeMode)
945 d->updateProxyGeometryFromWidget();
948 // If the widget moves itself, we move the proxy too. Prevent
949 // feed-back by checking the geometry change mode.
950 if (!d->posChangeMode)
951 d->updateProxyGeometryFromWidget();
955 // If the widget toggles its visible state, the proxy will follow.
956 if (!d->visibleChangeMode) {
957 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
958 setVisible(event->type() == QEvent::Show);
959 d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
962 case QEvent::EnabledChange:
963 // If the widget toggles its enabled state, the proxy will follow.
964 if (!d->enabledChangeMode) {
965 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
966 setEnabled(d->widget->isEnabled());
967 d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
970 case QEvent::StyleChange:
971 // Propagate style changes to the proxy.
972 if (!d->styleChangeMode) {
973 d->styleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
974 setStyle(d->widget->style());
975 d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
978 #ifndef QT_NO_TOOLTIP
979 case QEvent::ToolTipChange:
980 // Propagate tooltip change to the proxy.
981 if (!d->tooltipChangeMode) {
982 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
983 setToolTip(d->widget->toolTip());
984 d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode;
992 return QGraphicsWidget::eventFilter(object, event);
998 void QGraphicsProxyWidget::showEvent(QShowEvent *event)
1006 void QGraphicsProxyWidget::hideEvent(QHideEvent *event)
1011 #ifndef QT_NO_CONTEXTMENU
1015 void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
1017 Q_D(QGraphicsProxyWidget);
1018 if (!event || !d->widget || !d->widget->isVisible() || !hasFocus())
1021 // Find widget position and receiver.
1022 QPointF pos = event->pos();
1023 QPointer<QWidget> alienWidget = d->widget->childAt(pos.toPoint());
1024 QPointer<QWidget> receiver = alienWidget ? alienWidget : d->widget;
1026 // Map event position from us to the receiver
1027 pos = d->mapToReceiver(pos, receiver);
1029 QPoint globalPos = receiver->mapToGlobal(pos.toPoint());
1030 //If the receiver by-pass the proxy its popups
1031 //will be top level QWidgets therefore they need
1032 //the screen position. mapToGlobal expect the widget to
1033 //have proper coordinates in regards of the windowing system
1034 //but it's not true because the widget is embedded.
1035 if (bypassGraphicsProxyWidget(receiver))
1036 globalPos = event->screenPos();
1038 // Send mouse event. ### Doesn't propagate the event.
1039 QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()),
1040 pos.toPoint(), globalPos, event->modifiers());
1041 QApplication::sendEvent(receiver, &contextMenuEvent);
1043 event->setAccepted(contextMenuEvent.isAccepted());
1045 #endif // QT_NO_CONTEXTMENU
1047 #ifndef QT_NO_DRAGANDDROP
1051 void QGraphicsProxyWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
1053 #ifdef QT_NO_DRAGANDDROP
1056 Q_D(QGraphicsProxyWidget);
1060 QDragEnterEvent proxyDragEnter(event->pos().toPoint(), event->dropAction(), event->mimeData(), event->buttons(), event->modifiers());
1061 proxyDragEnter.setAccepted(event->isAccepted());
1062 QApplication::sendEvent(d->widget, &proxyDragEnter);
1063 event->setAccepted(proxyDragEnter.isAccepted());
1064 if (proxyDragEnter.isAccepted()) // we discard answerRect
1065 event->setDropAction(proxyDragEnter.dropAction());
1071 void QGraphicsProxyWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
1074 #ifndef QT_NO_DRAGANDDROP
1075 Q_D(QGraphicsProxyWidget);
1076 if (!d->widget || !d->dragDropWidget)
1078 QDragLeaveEvent proxyDragLeave;
1079 QApplication::sendEvent(d->dragDropWidget, &proxyDragLeave);
1080 d->dragDropWidget = 0;
1087 void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
1089 #ifdef QT_NO_DRAGANDDROP
1092 Q_D(QGraphicsProxyWidget);
1095 QPointF p = event->pos();
1097 QPointer<QWidget> subWidget = d->widget->childAt(p.toPoint());
1098 QPointer<QWidget> receiver = subWidget ? subWidget : d->widget;
1099 bool eventDelivered = false;
1100 for (; receiver; receiver = receiver->parentWidget()) {
1101 if (!receiver->isEnabled() || !receiver->acceptDrops())
1103 // Map event position from us to the receiver
1104 QPoint receiverPos = d->mapToReceiver(p, receiver).toPoint();
1105 if (receiver != d->dragDropWidget) {
1106 // Try to enter before we leave
1107 QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1108 dragEnter.setDropAction(event->proposedAction());
1109 QApplication::sendEvent(receiver, &dragEnter);
1110 event->setAccepted(dragEnter.isAccepted());
1111 event->setDropAction(dragEnter.dropAction());
1112 if (!event->isAccepted()) {
1113 // propagate to the parent widget
1117 d->lastDropAction = event->dropAction();
1119 if (d->dragDropWidget) {
1120 QDragLeaveEvent dragLeave;
1121 QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1123 d->dragDropWidget = receiver;
1126 QDragMoveEvent dragMove(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1127 event->setDropAction(d->lastDropAction);
1128 QApplication::sendEvent(receiver, &dragMove);
1129 event->setAccepted(dragMove.isAccepted());
1130 event->setDropAction(dragMove.dropAction());
1131 if (event->isAccepted())
1132 d->lastDropAction = event->dropAction();
1133 eventDelivered = true;
1137 if (!eventDelivered) {
1138 if (d->dragDropWidget) {
1139 // Leave the last drag drop item
1140 QDragLeaveEvent dragLeave;
1141 QApplication::sendEvent(d->dragDropWidget, &dragLeave);
1142 d->dragDropWidget = 0;
1145 event->setDropAction(Qt::IgnoreAction);
1153 void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
1155 #ifdef QT_NO_DRAGANDDROP
1158 Q_D(QGraphicsProxyWidget);
1159 if (d->widget && d->dragDropWidget) {
1160 QPoint widgetPos = d->mapToReceiver(event->pos(), d->dragDropWidget).toPoint();
1161 QDropEvent dropEvent(widgetPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1162 QApplication::sendEvent(d->dragDropWidget, &dropEvent);
1163 event->setAccepted(dropEvent.isAccepted());
1164 d->dragDropWidget = 0;
1173 void QGraphicsProxyWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1181 void QGraphicsProxyWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1184 Q_D(QGraphicsProxyWidget);
1185 // If hoverMove was compressed away, make sure we update properly here.
1186 if (d->lastWidgetUnderMouse) {
1187 QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
1188 d->lastWidgetUnderMouse = 0;
1195 void QGraphicsProxyWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1197 Q_D(QGraphicsProxyWidget);
1198 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1199 qDebug() << "QGraphicsProxyWidget::hoverMoveEvent";
1201 // Ignore events on the window frame.
1202 if (!d->widget || !rect().contains(event->pos())) {
1203 if (d->lastWidgetUnderMouse) {
1204 QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse);
1205 d->lastWidgetUnderMouse = 0;
1210 d->embeddedMouseGrabber = 0;
1211 d->sendWidgetMouseEvent(event);
1217 void QGraphicsProxyWidget::grabMouseEvent(QEvent *event)
1225 void QGraphicsProxyWidget::ungrabMouseEvent(QEvent *event)
1227 Q_D(QGraphicsProxyWidget);
1229 d->embeddedMouseGrabber = 0;
1235 void QGraphicsProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1237 Q_D(QGraphicsProxyWidget);
1238 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1239 qDebug() << "QGraphicsProxyWidget::mouseMoveEvent";
1241 d->sendWidgetMouseEvent(event);
1247 void QGraphicsProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event)
1249 Q_D(QGraphicsProxyWidget);
1250 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1251 qDebug() << "QGraphicsProxyWidget::mousePressEvent";
1253 d->sendWidgetMouseEvent(event);
1259 void QGraphicsProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1261 Q_D(QGraphicsProxyWidget);
1262 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1263 qDebug() << "QGraphicsProxyWidget::mouseDoubleClickEvent";
1265 d->sendWidgetMouseEvent(event);
1271 #ifndef QT_NO_WHEELEVENT
1272 void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event)
1274 Q_D(QGraphicsProxyWidget);
1275 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1276 qDebug() << "QGraphicsProxyWidget::wheelEvent";
1281 QPointF pos = event->pos();
1282 QPointer<QWidget> receiver = d->widget->childAt(pos.toPoint());
1284 receiver = d->widget;
1286 // Map event position from us to the receiver
1287 pos = d->mapToReceiver(pos, receiver);
1289 // Send mouse event.
1290 QWheelEvent wheelEvent(pos.toPoint(), event->screenPos(), event->delta(),
1291 event->buttons(), event->modifiers(), event->orientation());
1292 QPointer<QWidget> focusWidget = d->widget->focusWidget();
1293 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
1294 qt_sendSpontaneousEvent(receiver, &wheelEvent);
1295 event->setAccepted(wheelEvent.isAccepted());
1297 // ### Remove, this should be done by proper focusIn/focusOut events.
1298 if (focusWidget && !focusWidget->hasFocus()) {
1299 focusWidget->update();
1300 focusWidget = d->widget->focusWidget();
1301 if (focusWidget && focusWidget->hasFocus())
1302 focusWidget->update();
1310 void QGraphicsProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1312 Q_D(QGraphicsProxyWidget);
1313 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1314 qDebug() << "QGraphicsProxyWidget::mouseReleaseEvent";
1316 d->sendWidgetMouseEvent(event);
1322 void QGraphicsProxyWidget::keyPressEvent(QKeyEvent *event)
1324 Q_D(QGraphicsProxyWidget);
1325 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1326 qDebug() << "QGraphicsProxyWidget::keyPressEvent";
1328 d->sendWidgetKeyEvent(event);
1334 void QGraphicsProxyWidget::keyReleaseEvent(QKeyEvent *event)
1336 Q_D(QGraphicsProxyWidget);
1337 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1338 qDebug() << "QGraphicsProxyWidget::keyReleaseEvent";
1340 d->sendWidgetKeyEvent(event);
1346 void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
1348 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1349 qDebug() << "QGraphicsProxyWidget::focusInEvent";
1351 Q_D(QGraphicsProxyWidget);
1353 if (d->focusFromWidgetToProxy) {
1354 // Prevent recursion when the proxy autogains focus through the
1355 // embedded widget calling setFocus(). ### Could be done with event
1356 // filter on FocusIn instead?
1360 d->proxyIsGivingFocus = true;
1362 switch (event->reason()) {
1363 case Qt::TabFocusReason: {
1364 if (QWidget *focusChild = d->findFocusChild(0, true))
1365 focusChild->setFocus(event->reason());
1368 case Qt::BacktabFocusReason:
1369 if (QWidget *focusChild = d->findFocusChild(0, false))
1370 focusChild->setFocus(event->reason());
1373 if (d->widget && d->widget->focusWidget()) {
1374 d->widget->focusWidget()->setFocus(event->reason());
1379 d->proxyIsGivingFocus = false;
1385 void QGraphicsProxyWidget::focusOutEvent(QFocusEvent *event)
1387 #ifdef GRAPHICSPROXYWIDGET_DEBUG
1388 qDebug() << "QGraphicsProxyWidget::focusOutEvent";
1390 Q_D(QGraphicsProxyWidget);
1392 // We need to explicitly remove subfocus from the embedded widget's
1394 if (QWidget *focusWidget = d->widget->focusWidget())
1395 d->removeSubFocusHelper(focusWidget, event->reason());
1402 bool QGraphicsProxyWidget::focusNextPrevChild(bool next)
1404 Q_D(QGraphicsProxyWidget);
1405 if (!d->widget || !d->scene)
1406 return QGraphicsWidget::focusNextPrevChild(next);
1408 Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason;
1409 QWidget *lastFocusChild = d->widget->focusWidget();
1410 if (QWidget *newFocusChild = d->findFocusChild(lastFocusChild, next)) {
1411 newFocusChild->setFocus(reason);
1415 return QGraphicsWidget::focusNextPrevChild(next);
1421 QSizeF QGraphicsProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
1423 Q_D(const QGraphicsProxyWidget);
1425 return QGraphicsWidget::sizeHint(which, constraint);
1429 case Qt::PreferredSize:
1430 if (QLayout *l = d->widget->layout())
1433 sh = d->widget->sizeHint();
1435 case Qt::MinimumSize:
1436 if (QLayout *l = d->widget->layout())
1437 sh = l->minimumSize();
1439 sh = d->widget->minimumSizeHint();
1441 case Qt::MaximumSize:
1442 if (QLayout *l = d->widget->layout())
1443 sh = l->maximumSize();
1445 sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
1447 case Qt::MinimumDescent:
1459 void QGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
1461 Q_D(QGraphicsProxyWidget);
1463 if (d->sizeChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode)
1464 d->widget->resize(event->newSize().toSize());
1466 QGraphicsWidget::resizeEvent(event);
1472 void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
1474 Q_D(QGraphicsProxyWidget);
1476 if (!d->widget || !d->widget->isVisible())
1479 // Filter out repaints on the window frame.
1480 const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect();
1481 if (exposedWidgetRect.isEmpty())
1484 // Disable QPainter's default pen being cosmetic. This allows widgets and
1485 // styles to follow Qt's existing defaults without getting ugly cosmetic
1486 // lines when scaled.
1487 bool restore = !(painter->renderHints() & QPainter::NonCosmeticDefaultPen);
1488 painter->setRenderHints(QPainter::NonCosmeticDefaultPen, true);
1490 d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect);
1492 // Restore the render hints if necessary.
1494 painter->setRenderHints(QPainter::NonCosmeticDefaultPen, false);
1500 int QGraphicsProxyWidget::type() const
1508 Creates a proxy widget for the given \a child of the widget
1509 contained in this proxy.
1511 This function makes it possible to acquire proxies for
1512 non top-level widgets. For instance, you can embed a dialog,
1513 and then transform only one of its widgets.
1515 If the widget is already embedded, return the existing proxy widget.
1517 \sa newProxyWidget(), QGraphicsScene::addWidget()
1519 QGraphicsProxyWidget *QGraphicsProxyWidget::createProxyForChildWidget(QWidget *child)
1521 QGraphicsProxyWidget *proxy = child->graphicsProxyWidget();
1524 if (!child->parentWidget()) {
1525 qWarning("QGraphicsProxyWidget::createProxyForChildWidget: top-level widget not in a QGraphicsScene");
1529 QGraphicsProxyWidget *parentProxy = createProxyForChildWidget(child->parentWidget());
1533 if (!QMetaObject::invokeMethod(parentProxy, "newProxyWidget", Qt::DirectConnection,
1534 Q_RETURN_ARG(QGraphicsProxyWidget*, proxy), Q_ARG(const QWidget*, child)))
1536 proxy->setParent(parentProxy);
1537 proxy->setWidget(child);
1542 \fn QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *child)
1545 Creates a proxy widget for the given \a child of the widget contained in this
1548 You should not call this function directly; use
1549 QGraphicsProxyWidget::createProxyForChildWidget() instead.
1551 This function is a fake virtual slot that you can reimplement in
1552 your subclass in order to control how new proxy widgets are
1553 created. The default implementation returns a proxy created with
1554 the QGraphicsProxyWidget() constructor with this proxy widget as
1557 \sa createProxyForChildWidget()
1559 QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *)
1561 return new QGraphicsProxyWidget(this);
1568 #include "moc_qgraphicsproxywidget.cpp"
1570 #endif //QT_NO_GRAPHICSVIEW