Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgraphicswidget.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qglobal.h"
6
11#include "qgraphicsscene.h"
13
14#ifndef QT_NO_ACTION
15#include <private/qaction_p.h>
16#endif
17#include <private/qapplication_p.h>
18#include <private/qgraphicsscene_p.h>
19#ifndef QT_NO_SHORTCUT
20#include <private/qshortcutmap_p.h>
21#endif
22#include <QtCore/qmutex.h>
23#include <QtCore/QScopeGuard>
24#include <QtWidgets/qapplication.h>
25#include <QtWidgets/qgraphicsview.h>
26#include <QtWidgets/qgraphicsproxywidget.h>
27#include <QtGui/qpalette.h>
28#include <QtGui/qpainterpath.h>
29#include <QtWidgets/qstyleoption.h>
30
31#include <qdebug.h>
32
34
35using namespace Qt::StringLiterals;
36
37/*!
38 \class QGraphicsWidget
39 \brief The QGraphicsWidget class is the base class for all widget
40 items in a QGraphicsScene.
41 \since 4.4
42 \ingroup graphicsview-api
43 \inmodule QtWidgets
44
45 QGraphicsWidget is an extended base item that provides extra functionality
46 over QGraphicsItem. It is similar to QWidget in many ways:
47
48 \list
49 \li Provides a \l palette, a \l font and a \l style().
50 \li Has a defined geometry().
51 \li Supports layouts with setLayout() and layout().
52 \li Supports shortcuts and actions with grabShortcut() and insertAction()
53 \endlist
54
55 Unlike QGraphicsItem, QGraphicsWidget is not an abstract class; you can
56 create instances of a QGraphicsWidget without having to subclass it.
57 This approach is useful for widgets that only serve the purpose of
58 organizing child widgets into a layout.
59
60 QGraphicsWidget can be used as a base item for your own custom item if
61 you require advanced input focus handling, e.g., tab focus and activation, or
62 layouts.
63
64 Since QGraphicsWidget resembles QWidget and has similar API, it is
65 easier to port a widget from QWidget to QGraphicsWidget, instead of
66 QGraphicsItem.
67
68 \note QWidget-based widgets can be directly embedded into a
69 QGraphicsScene using QGraphicsProxyWidget.
70
71 Noticeable differences between QGraphicsWidget and QWidget are:
72
73 \table
74 \header \li QGraphicsWidget
75 \li QWidget
76 \row \li Coordinates and geometry are defined with qreals (doubles or
77 floats, depending on the platform).
78 \li QWidget uses integer geometry (QPoint, QRect).
79 \row \li The widget is already visible by default; you do not have to
80 call show() to display the widget.
81 \li QWidget is hidden by default until you call show().
82 \row \li A subset of widget attributes are supported.
83 \li All widget attributes are supported.
84 \row \li A top-level item's style defaults to QGraphicsScene::style
85 \li A top-level widget's style defaults to QApplication::style
86 \row \li Graphics View provides a custom drag and drop framework, different
87 from QWidget.
88 \li Standard drag and drop framework.
89 \row \li Widget items do not support modality.
90 \li Full modality support.
91 \endtable
92
93 QGraphicsWidget supports a subset of Qt's widget attributes,
94 (Qt::WidgetAttribute), as shown in the table below. Any attributes not
95 listed in this table are unsupported, or otherwise unused.
96
97 \table
98 \header \li Widget Attribute \li Usage
99 \row \li Qt::WA_SetLayoutDirection
100 \li Set by setLayoutDirection(), cleared by
101 unsetLayoutDirection(). You can test this attribute to
102 check if the widget has been explicitly assigned a
103 \l{QGraphicsWidget::layoutDirection()}
104 {layoutDirection}. If the attribute is not set, the
105 \l{QGraphicsWidget::layoutDirection()}
106 {layoutDirection()} is inherited.
107 \row \li Qt::WA_RightToLeft
108 \li Toggled by setLayoutDirection(). Inherited from the
109 parent/scene. If set, the widget's layout will order
110 horizontally arranged widgets from right to left.
111 \row \li Qt::WA_SetStyle
112 \li Set and cleared by setStyle(). If this attribute is
113 set, the widget has been explicitly assigned a style.
114 If it is unset, the widget will use the scene's or the
115 application's style.
116 \row \li Qt::WA_Resized
117 \li Set by setGeometry() and resize().
118 \row \li Qt::WA_SetPalette
119 \li Set by setPalette().
120 \row \li Qt::WA_SetFont
121 \li Set by setFont().
122 \row \li Qt::WA_WindowPropagation
123 \li Enables propagation to window widgets.
124 \endtable
125
126 Although QGraphicsWidget inherits from both QObject and QGraphicsItem,
127 you should use the functions provided by QGraphicsItem, \e not QObject, to
128 manage the relationships between parent and child items. These functions
129 control the stacking order of items as well as their ownership.
130
131 \note The QObject::parent() should always return \nullptr for QGraphicsWidgets,
132 but this policy is not strictly defined.
133
134 \sa QGraphicsProxyWidget, QGraphicsItem, {Widgets and Layouts}
135*/
136
137/*!
138 Constructs a QGraphicsWidget instance. The optional \a parent argument is
139 passed to QGraphicsItem's constructor. The optional \a wFlags argument
140 specifies the widget's window flags (e.g., whether the widget should be a
141 window, a tool, a popup, etc).
142*/
143QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
144 : QGraphicsObject(*new QGraphicsWidgetPrivate, nullptr), QGraphicsLayoutItem(nullptr, false)
145{
146 Q_D(QGraphicsWidget);
147 d->init(parent, wFlags);
148}
149
150/*!
151 \internal
152
153 Constructs a new QGraphicsWidget, using \a dd as parent.
154*/
155QGraphicsWidget::QGraphicsWidget(QGraphicsWidgetPrivate &dd, QGraphicsItem *parent, Qt::WindowFlags wFlags)
156 : QGraphicsObject(dd, nullptr), QGraphicsLayoutItem(nullptr, false)
157{
158 Q_D(QGraphicsWidget);
159 d->init(parent, wFlags);
160}
161
162/*
163 \internal
164 \class QGraphicsWidgetStyles
165
166 We use this thread-safe class to maintain a hash of styles for widgets
167 styles. Note that QApplication::style() itself isn't thread-safe, QStyle
168 isn't thread-safe, and we don't have a thread-safe factory for creating
169 the default style, nor cloning a style.
170*/
172{
173public:
174 QStyle *styleForWidget(const QGraphicsWidget *widget) const
175 {
176 QMutexLocker locker(&mutex);
177 return styles.value(widget, 0);
178 }
179
180 void setStyleForWidget(QGraphicsWidget *widget, QStyle *style)
181 {
182 QMutexLocker locker(&mutex);
183 if (style)
184 styles[widget] = style;
185 else
186 styles.remove(widget);
187 }
188
189private:
190 QHash<const QGraphicsWidget *, QStyle *> styles;
191 mutable QMutex mutex;
192};
193Q_GLOBAL_STATIC(QGraphicsWidgetStyles, widgetStyles)
194
195/*!
196 Destroys the QGraphicsWidget instance.
197*/
198QGraphicsWidget::~QGraphicsWidget()
199{
200 Q_D(QGraphicsWidget);
201#ifndef QT_NO_ACTION
202 // Remove all actions from this widget
203 for (auto action : std::as_const(d->actions)) {
204 QActionPrivate *apriv = action->d_func();
205 apriv->associatedObjects.removeAll(this);
206 }
207 d->actions.clear();
208#endif
209
210 if (QGraphicsScene *scn = scene()) {
211 QGraphicsScenePrivate *sceneD = scn->d_func();
212 if (sceneD->tabFocusFirst == this)
213 sceneD->tabFocusFirst = (d->focusNext == this ? nullptr : d->focusNext);
214 }
215 d->focusPrev->d_func()->focusNext = d->focusNext;
216 d->focusNext->d_func()->focusPrev = d->focusPrev;
217
218 // Play it really safe
219 d->focusNext = this;
220 d->focusPrev = this;
221
222 clearFocus();
223
224 //we check if we have a layout previously
225 if (d->layout) {
226 QGraphicsLayout *temp = d->layout;
227 const auto items = childItems();
228 for (QGraphicsItem *item : items) {
229 // In case of a custom layout which doesn't remove and delete items, we ensure that
230 // the parent layout item does not point to the deleted layout. This code is here to
231 // avoid regression from 4.4 to 4.5, because according to 4.5 docs it is not really needed.
232 if (item->isWidget()) {
233 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
234 if (widget->parentLayoutItem() == d->layout)
235 widget->setParentLayoutItem(nullptr);
236 }
237 }
238 d->layout = nullptr;
239 delete temp;
240 }
241
242 // Remove this graphics widget from widgetStyles
243 widgetStyles()->setStyleForWidget(this, nullptr);
244
245 // Unset the parent here, when we're still a QGraphicsWidget.
246 // It is otherwise done in ~QGraphicsItem() where we'd be
247 // calling QGraphicsWidget members on an ex-QGraphicsWidget object
248 setParentItem(nullptr);
249}
250
251/*!
252 \property QGraphicsWidget::size
253 \brief the size of the widget
254
255 Calling resize() resizes the widget to a \a size bounded by minimumSize()
256 and maximumSize(). This property only affects the widget's width and
257 height (e.g., its right and bottom edges); the widget's position and
258 top-left corner remains unaffected.
259
260 Resizing a widget triggers the widget to immediately receive a
261 \l{QEvent::GraphicsSceneResize}{GraphicsSceneResize} event with the
262 widget's old and new size. If the widget has a layout assigned when this
263 event arrives, the layout will be activated and it will automatically
264 update any child widgets's geometry.
265
266 This property does not affect any layout of the parent widget. If the
267 widget itself is managed by a parent layout; e.g., it has a parent widget
268 with a layout assigned, that layout will not activate.
269
270 By default, this property contains a size with zero width and height.
271
272 \sa setGeometry(), QGraphicsSceneResizeEvent, QGraphicsLayout
273*/
274QSizeF QGraphicsWidget::size() const
275{
276 return QGraphicsLayoutItem::geometry().size();
277}
278
279void QGraphicsWidget::resize(const QSizeF &size)
280{
281 setGeometry(QRectF(pos(), size));
282}
283
284/*!
285 \fn void QGraphicsWidget::resize(qreal w, qreal h)
286 \overload
287
288 Constructs a resize with the given \c width (\a w) and \c height (\a h).
289 This convenience function is equivalent to calling resize(QSizeF(w, h)).
290
291 \sa setGeometry(), setTransform()
292*/
293
294/*!
295 \property QGraphicsWidget::sizePolicy
296 \brief the size policy for the widget
297 \sa sizePolicy(), setSizePolicy(), QWidget::sizePolicy()
298*/
299
300/*!
301 \fn QGraphicsWidget::geometryChanged()
302
303 This signal gets emitted whenever the geometry is changed in setGeometry().
304*/
305
306/*!
307 \property QGraphicsWidget::geometry
308 \brief the geometry of the widget
309
310 Sets the item's geometry to \a rect. The item's position and size are
311 modified as a result of calling this function. The item is first moved,
312 then resized.
313
314 A side effect of calling this function is that the widget will receive
315 a move event and a resize event. Also, if the widget has a layout
316 assigned, the layout will activate.
317
318 \sa geometry(), resize()
319*/
320void QGraphicsWidget::setGeometry(const QRectF &rect)
321{
322 QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func();
323 // Package relayout of children in a scope guard so we can just return early
324 // when this widget's geometry is sorted out.
325 const auto relayoutChildren = qScopeGuard([this, wd]() {
326 if (QGraphicsLayout::instantInvalidatePropagation()) {
327 if (QGraphicsLayout *lay = wd->layout) {
328 if (!lay->isActivated()) {
329 QEvent layoutRequest(QEvent::LayoutRequest);
330 QCoreApplication::sendEvent(this, &layoutRequest);
331 }
332 }
333 }
334 });
335
336 QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data();
337 QRectF newGeom;
338 QPointF oldPos = d->geom.topLeft();
339 if (!wd->inSetPos) {
340 setAttribute(Qt::WA_Resized);
341 newGeom = rect;
342 newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize))
343 .boundedTo(effectiveSizeHint(Qt::MaximumSize)));
344
345 if (newGeom == d->geom)
346 return;
347
348 // setPos triggers ItemPositionChange, which can adjust position
349 wd->inSetGeometry = 1;
350 setPos(newGeom.topLeft());
351 wd->inSetGeometry = 0;
352 newGeom.moveTopLeft(pos());
353
354 if (newGeom == d->geom)
355 return;
356
357 // Update and prepare to change the geometry (remove from index) if
358 // the size has changed.
359 if (wd->scene && rect.topLeft() == d->geom.topLeft())
360 prepareGeometryChange();
361 }
362
363 // Update the layout item geometry
364 if (oldPos != pos()) {
365 // Send move event.
366 QGraphicsSceneMoveEvent event;
367 event.setOldPos(oldPos);
368 event.setNewPos(pos());
369 QCoreApplication::sendEvent(this, &event);
370 if (wd->inSetPos) {
371 // Set the new position:
372 d->geom.moveTopLeft(pos());
373 emit geometryChanged();
374 return;
375 }
376 }
377
378 QSizeF oldSize = size();
379 QGraphicsLayoutItem::setGeometry(newGeom);
380 // Send resize event, if appropriate:
381 if (newGeom.size() != oldSize) {
382 if (oldSize.width() != newGeom.size().width())
383 emit widthChanged();
384 if (oldSize.height() != newGeom.size().height())
385 emit heightChanged();
386 QGraphicsLayout *lay = wd->layout;
387 if (!QGraphicsLayout::instantInvalidatePropagation() || !lay || lay->isActivated()) {
388 QGraphicsSceneResizeEvent re;
389 re.setOldSize(oldSize);
390 re.setNewSize(newGeom.size());
391 QCoreApplication::sendEvent(this, &re);
392 }
393 }
394
395 emit geometryChanged();
396}
397
398/*!
399 \fn QRectF QGraphicsWidget::rect() const
400
401 Returns the item's local rect as a QRectF. This function is equivalent
402 to QRectF(QPointF(), size()).
403
404 \sa setGeometry(), resize()
405*/
406
407/*!
408 \fn void QGraphicsWidget::setGeometry(qreal x, qreal y, qreal w, qreal h)
409
410 This convenience function is equivalent to calling setGeometry(QRectF(
411 \a x, \a y, \a w, \a h)).
412
413 \sa geometry(), resize()
414*/
415
416/*!
417 \property QGraphicsWidget::minimumSize
418 \brief the minimum size of the widget
419
420 \sa setMinimumSize(), minimumSize(), preferredSize, maximumSize
421*/
422
423/*!
424 \property QGraphicsWidget::preferredSize
425 \brief the preferred size of the widget
426
427 \sa setPreferredSize(), preferredSize(), minimumSize, maximumSize
428*/
429
430/*!
431 \property QGraphicsWidget::maximumSize
432 \brief the maximum size of the widget
433
434 \sa setMaximumSize(), maximumSize(), minimumSize, preferredSize
435*/
436
437/*!
438 \since 5.14
439
440 Sets the widget's contents margins to \a margins.
441
442 Contents margins are used by the assigned layout to define the placement
443 of subwidgets and layouts. Margins are particularly useful for widgets
444 that constrain subwidgets to only a section of its own geometry. For
445 example, a group box with a layout will place subwidgets inside its frame,
446 but below the title.
447
448 Changing a widget's contents margins will always trigger an update(), and
449 any assigned layout will be activated automatically. The widget will then
450 receive a \l{QEvent::ContentsRectChange}{ContentsRectChange} event.
451
452 \sa getContentsMargins(), setGeometry()
453*/
454void QGraphicsWidget::setContentsMargins(QMarginsF margins)
455{
456 Q_D(QGraphicsWidget);
457
458 if (!d->margins && margins.isNull())
459 return;
460 d->ensureMargins();
461 if (*d->margins == margins)
462 return;
463
464 *d->margins = margins;
465
466 if (QGraphicsLayout *l = d->layout)
467 l->invalidate();
468 else
469 updateGeometry();
470
471 QEvent e(QEvent::ContentsRectChange);
472 QCoreApplication::sendEvent(this, &e);
473}
474
475/*!
476 \overload
477
478 Sets the widget's contents margins to \a left, \a top, \a right and \a
479 bottom.
480*/
481void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
482{
483 setContentsMargins({left, top, right, bottom});
484}
485
486/*!
487 Gets the widget's contents margins. The margins are stored in \a left, \a
488 top, \a right and \a bottom, as pointers to qreals. Each argument can
489 be \e {omitted} by passing \nullptr.
490
491 \sa setContentsMargins()
492*/
493void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
494{
495 Q_D(const QGraphicsWidget);
496 if (left || top || right || bottom)
497 d->ensureMargins();
498 if (left)
499 *left = d->margins->left();
500 if (top)
501 *top = d->margins->top();
502 if (right)
503 *right = d->margins->right();
504 if (bottom)
505 *bottom = d->margins->bottom();
506}
507
508/*!
509 \since 5.14
510 Sets the widget's window frame margins to \a margins.
511 The default frame margins are provided by the style, and they
512 depend on the current window flags.
513
514 If you would like to draw your own window decoration, you can set your
515 own frame margins to override the default margins.
516
517 \sa unsetWindowFrameMargins(), getWindowFrameMargins(), windowFrameRect()
518*/
519void QGraphicsWidget::setWindowFrameMargins(QMarginsF margins)
520{
521 Q_D(QGraphicsWidget);
522
523 if (!d->windowFrameMargins && margins.isNull())
524 return;
525 d->ensureWindowFrameMargins();
526 const bool unchanged = *d->windowFrameMargins == margins;
527 if (d->setWindowFrameMargins && unchanged)
528 return;
529 if (!unchanged)
530 prepareGeometryChange();
531 *d->windowFrameMargins = margins;
532 d->setWindowFrameMargins = true;
533}
534
535/*!
536 \overload
537 Sets the widget's window frame margins to \a left, \a top, \a right and
538 \a bottom.
539*/
540void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
541{
542 setWindowFrameMargins({left, top, right, bottom});
543}
544
545/*!
546 Gets the widget's window frame margins. The margins are stored in \a left,
547 \a top, \a right and \a bottom as pointers to qreals. Each argument can
548 be \e {omitted} by passing \nullptr.
549
550 \sa setWindowFrameMargins(), windowFrameRect()
551*/
552void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
553{
554 Q_D(const QGraphicsWidget);
555 if (left || top || right || bottom)
556 d->ensureWindowFrameMargins();
557 if (left)
558 *left = d->windowFrameMargins->left();
559 if (top)
560 *top = d->windowFrameMargins->top();
561 if (right)
562 *right = d->windowFrameMargins->right();
563 if (bottom)
564 *bottom = d->windowFrameMargins->bottom();
565}
566
567/*!
568 Resets the window frame margins to the default value, provided by the style.
569
570 \sa setWindowFrameMargins(), getWindowFrameMargins(), windowFrameRect()
571*/
572void QGraphicsWidget::unsetWindowFrameMargins()
573{
574 Q_D(QGraphicsWidget);
575 if ((d->windowFlags & Qt::Window) && (d->windowFlags & Qt::WindowType_Mask) != Qt::Popup &&
576 (d->windowFlags & Qt::WindowType_Mask) != Qt::ToolTip && !(d->windowFlags & Qt::FramelessWindowHint)) {
577 QStyleOptionTitleBar bar;
578 d->initStyleOptionTitleBar(&bar);
579 QStyle *style = this->style();
580 const qreal margin = style->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, &bar);
581 qreal titleBarHeight = d->titleBarHeight(bar);
582 setWindowFrameMargins(margin, titleBarHeight, margin, margin);
583 } else {
584 setWindowFrameMargins(0, 0, 0, 0);
585 }
586 d->setWindowFrameMargins = false;
587}
588
589/*!
590 Returns the widget's geometry in parent coordinates including any window
591 frame.
592
593 \sa windowFrameRect(), getWindowFrameMargins(), setWindowFrameMargins()
594*/
595QRectF QGraphicsWidget::windowFrameGeometry() const
596{
597 Q_D(const QGraphicsWidget);
598 return d->windowFrameMargins
599 ? geometry().adjusted(-d->windowFrameMargins->left(), -d->windowFrameMargins->top(),
600 d->windowFrameMargins->right(), d->windowFrameMargins->bottom())
601 : geometry();
602}
603
604/*!
605 Returns the widget's local rect including any window frame.
606
607 \sa windowFrameGeometry(), getWindowFrameMargins(), setWindowFrameMargins()
608*/
609QRectF QGraphicsWidget::windowFrameRect() const
610{
611 Q_D(const QGraphicsWidget);
612 return d->windowFrameMargins
613 ? rect().adjusted(-d->windowFrameMargins->left(), -d->windowFrameMargins->top(),
614 d->windowFrameMargins->right(), d->windowFrameMargins->bottom())
615 : rect();
616}
617
618/*!
619 Populates a style option object for this widget based on its current
620 state, and stores the output in \a option. The default implementation
621 populates \a option with the following properties.
622
623 \table
624 \header
625 \li Style Option Property
626 \li Value
627 \row
628 \li state & QStyle::State_Enabled
629 \li Corresponds to QGraphicsItem::isEnabled().
630 \row
631 \li state & QStyle::State_HasFocus
632 \li Corresponds to QGraphicsItem::hasFocus().
633 \row
634 \li state & QStyle::State_MouseOver
635 \li Corresponds to QGraphicsItem::isUnderMouse().
636 \row
637 \li direction
638 \li Corresponds to QGraphicsWidget::layoutDirection().
639 \row
640 \li rect
641 \li Corresponds to QGraphicsWidget::rect().toRect().
642 \row
643 \li palette
644 \li Corresponds to QGraphicsWidget::palette().
645 \row
646 \li fontMetrics
647 \li Corresponds to QFontMetrics(QGraphicsWidget::font()).
648 \endtable
649
650 Subclasses of QGraphicsWidget should call the base implementation, and
651 then test the type of \a option using qstyleoption_cast<>() or test
652 QStyleOption::Type before storing widget-specific options.
653
654 For example:
655
656 \snippet code/src_gui_graphicsview_qgraphicswidget.cpp 0
657
658 \sa QStyleOption::initFrom()
659*/
660void QGraphicsWidget::initStyleOption(QStyleOption *option) const
661{
662 Q_ASSERT(option);
663
664 option->state = QStyle::State_None;
665 if (isEnabled())
666 option->state |= QStyle::State_Enabled;
667 if (hasFocus())
668 option->state |= QStyle::State_HasFocus;
669 // if (window->testAttribute(Qt::WA_KeyboardFocusChange)) // ### Window
670 // option->state |= QStyle::State_KeyboardFocusChange;
671 if (isUnderMouse())
672 option->state |= QStyle::State_MouseOver;
673 if (QGraphicsWidget *w = window()) {
674 if (w->isActiveWindow())
675 option->state |= QStyle::State_Active;
676 }
677 if (isWindow())
678 option->state |= QStyle::State_Window;
679 /*
680 ###
681#ifdef QT_KEYPAD_NAVIGATION
682 if (widget->hasEditFocus())
683 state |= QStyle::State_HasEditFocus;
684#endif
685 */
686 option->direction = layoutDirection();
687 option->rect = rect().toRect(); // ### truncation!
688 option->palette = palette();
689 if (!isEnabled()) {
690 option->palette.setCurrentColorGroup(QPalette::Disabled);
691 } else if (isActiveWindow()) {
692 option->palette.setCurrentColorGroup(QPalette::Active);
693 } else {
694 option->palette.setCurrentColorGroup(QPalette::Inactive);
695 }
696 option->fontMetrics = QFontMetrics(font());
697 option->styleObject = const_cast<QGraphicsWidget *>(this);
698}
699
700/*!
701 \reimp
702*/
703QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
704{
705 Q_D(const QGraphicsWidget);
706 QSizeF sh;
707 if (d->layout) {
708 QSizeF marginSize(0,0);
709 if (d->margins) {
710 marginSize = QSizeF(d->margins->left() + d->margins->right(),
711 d->margins->top() + d->margins->bottom());
712 }
713 sh = d->layout->effectiveSizeHint(which, constraint - marginSize);
714 sh += marginSize;
715 } else {
716 switch (which) {
717 case Qt::MinimumSize:
718 sh = QSizeF(0, 0);
719 break;
720 case Qt::PreferredSize:
721 sh = QSizeF(50, 50); //rather arbitrary
722 break;
723 case Qt::MaximumSize:
724 sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
725 break;
726 default:
727 qWarning("QGraphicsWidget::sizeHint(): Don't know how to handle the value of 'which'");
728 break;
729 }
730 }
731 return sh;
732}
733
734/*!
735 \property QGraphicsWidget::layout
736 \brief The layout of the widget
737
738 Any existing layout manager is deleted before the new layout is assigned. If
739 \a layout is \nullptr, the widget is left without a layout. Existing subwidgets'
740 geometries will remain unaffected.
741
742 QGraphicsWidget takes ownership of \a layout.
743
744 All widgets that are currently managed by \a layout or all of its
745 sublayouts, are automatically reparented to this item. The layout is then
746 invalidated, and the child widget geometries are adjusted according to
747 this item's geometry() and contentsMargins(). Children who are not
748 explicitly managed by \a layout remain unaffected by the layout after
749 it has been assigned to this widget.
750
751 If no layout is currently managing this widget, layout() will return \nullptr.
752
753*/
754
755/*!
756 \fn void QGraphicsWidget::layoutChanged()
757 This signal gets emitted whenever the layout of the item changes
758 \internal
759*/
760
761/*!
762 Returns this widget's layout, or \nullptr if no layout is currently
763 managing this widget.
764
765 \sa setLayout()
766*/
767QGraphicsLayout *QGraphicsWidget::layout() const
768{
769 Q_D(const QGraphicsWidget);
770 return d->layout;
771}
772
773/*!
774 \fn void QGraphicsWidget::setLayout(QGraphicsLayout *layout)
775
776 Sets the layout for this widget to \a layout. Any existing layout manager
777 is deleted before the new layout is assigned. If \a layout is \nullptr, the
778 widget is left without a layout. Existing subwidgets' geometries will
779 remain unaffected.
780
781 All widgets that are currently managed by \a layout or all of its
782 sublayouts, are automatically reparented to this item. The layout is then
783 invalidated, and the child widget geometries are adjusted according to
784 this item's geometry() and contentsMargins(). Children who are not
785 explicitly managed by \a layout remain unaffected by the layout after
786 it has been assigned to this widget.
787
788 QGraphicsWidget takes ownership of \a layout.
789
790 \sa layout(), QGraphicsLinearLayout::addItem(), QGraphicsLayout::invalidate()
791*/
792void QGraphicsWidget::setLayout(QGraphicsLayout *l)
793{
794 Q_D(QGraphicsWidget);
795 if (d->layout == l)
796 return;
797 d->setLayout_helper(l);
798 if (!l)
799 return;
800
801 // Prevent assigning a layout that is already assigned to another widget.
802 QGraphicsLayoutItem *oldParent = l->parentLayoutItem();
803 if (oldParent && oldParent != this) {
804 qWarning("QGraphicsWidget::setLayout: Attempting to set a layout on %s"
805 " \"%s\", when the layout already has a parent",
806 metaObject()->className(), qPrintable(objectName()));
807 return;
808 }
809
810 // Install and activate the layout.
811 l->setParentLayoutItem(this);
812 l->d_func()->reparentChildItems(this);
813 l->invalidate();
814 emit layoutChanged();
815}
816
817/*!
818 Adjusts the size of the widget to its effective preferred size hint.
819
820 This function is called implicitly when the item is shown for the first
821 time.
822
823 \sa effectiveSizeHint(), Qt::MinimumSize
824*/
825void QGraphicsWidget::adjustSize()
826{
827 QSizeF sz = effectiveSizeHint(Qt::PreferredSize);
828 // What if sz is not valid?!
829 if (sz.isValid())
830 resize(sz);
831}
832
833/*!
834 \property QGraphicsWidget::layoutDirection
835 \brief the layout direction for this widget.
836
837 This property modifies this widget's and all of its descendants'
838 Qt::WA_RightToLeft attribute. It also sets this widget's
839 Qt::WA_SetLayoutDirection attribute.
840
841 The widget's layout direction determines the order in which the layout
842 manager horizontally arranges subwidgets of this widget. The default
843 value depends on the language and locale of the application, and is
844 typically in the same direction as words are read and written. With
845 Qt::LeftToRight, the layout starts placing subwidgets from the left
846 side of this widget towards the right. Qt::RightToLeft does the opposite -
847 the layout will place widgets starting from the right edge moving towards
848 the left.
849
850 Subwidgets inherit their layout direction from the parent. Top-level
851 widget items inherit their layout direction from
852 QGraphicsScene::layoutDirection. If you change a widget's layout direction
853 by calling setLayoutDirection(), the widget will send itself a
854 \l{QEvent::LayoutDirectionChange}{LayoutDirectionChange} event, and then
855 propagate the new layout direction to all its descendants.
856
857 \sa QWidget::layoutDirection, QApplication::layoutDirection
858*/
859Qt::LayoutDirection QGraphicsWidget::layoutDirection() const
860{
861 return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight;
862}
863void QGraphicsWidget::setLayoutDirection(Qt::LayoutDirection direction)
864{
865 Q_D(QGraphicsWidget);
866 setAttribute(Qt::WA_SetLayoutDirection, true);
867 d->setLayoutDirection_helper(direction);
868}
869void QGraphicsWidget::unsetLayoutDirection()
870{
871 Q_D(QGraphicsWidget);
872 setAttribute(Qt::WA_SetLayoutDirection, false);
873 d->resolveLayoutDirection();
874}
875
876/*!
877 Returns a pointer to the widget's style. If this widget does not have any
878 explicitly assigned style, the scene's style is returned instead. In turn,
879 if the scene does not have any assigned style, this function returns
880 QApplication::style().
881
882 \sa setStyle()
883*/
884QStyle *QGraphicsWidget::style() const
885{
886 if (QStyle *style = widgetStyles()->styleForWidget(this))
887 return style;
888 // ### This is not thread-safe. QApplication::style() is not thread-safe.
889 return scene() ? scene()->style() : QApplication::style();
890}
891
892/*!
893 Sets the widget's style to \a style. QGraphicsWidget does \e not take
894 ownership of \a style.
895
896 If no style is assigned, or \a style is \nullptr, the widget will use
897 QGraphicsScene::style() (if this has been set). Otherwise the widget will
898 use QApplication::style().
899
900 This function sets the Qt::WA_SetStyle attribute if \a style is not \nullptr;
901 otherwise it clears the attribute.
902
903 \sa style()
904*/
905void QGraphicsWidget::setStyle(QStyle *style)
906{
907 setAttribute(Qt::WA_SetStyle, style != nullptr);
908 widgetStyles()->setStyleForWidget(this, style);
909
910 // Deliver StyleChange to the widget itself (doesn't propagate).
911 QEvent event(QEvent::StyleChange);
912 QCoreApplication::sendEvent(this, &event);
913}
914
915/*!
916 \property QGraphicsWidget::font
917 \brief the widgets' font
918
919 This property provides the widget's font.
920
921 QFont consists of font properties that have been explicitly defined and
922 properties implicitly inherited from the widget's parent. Hence, font()
923 can return a different font compared to the one set with setFont().
924 This scheme allows you to define single entries in a font without
925 affecting the font's inherited entries.
926
927 When a widget's font changes, it resolves its entries against its
928 parent widget. If the widget does not have a parent widget, it resolves
929 its entries against the scene. The widget then sends itself a
930 \l{QEvent::FontChange}{FontChange} event and notifies all its
931 descendants so that they can resolve their fonts as well.
932
933 By default, this property contains the application's default font.
934
935 \sa QApplication::font(), QGraphicsScene::font, QFont::resolve()
936*/
937QFont QGraphicsWidget::font() const
938{
939 Q_D(const QGraphicsWidget);
940 QFont fnt = d->font;
941 fnt.setResolveMask(fnt.resolveMask() | d->inheritedFontResolveMask);
942 return fnt;
943}
944void QGraphicsWidget::setFont(const QFont &font)
945{
946 Q_D(QGraphicsWidget);
947 setAttribute(Qt::WA_SetFont, font.resolveMask() != 0);
948
949 QFont naturalFont = d->naturalWidgetFont();
950 QFont resolvedFont = font.resolve(naturalFont);
951 d->setFont_helper(resolvedFont);
952}
953
954/*!
955 \property QGraphicsWidget::palette
956 \brief the widget's palette
957
958 This property provides the widget's palette. The palette provides colors
959 and brushes for color groups (e.g., QPalette::Button) and states (e.g.,
960 QPalette::Inactive), loosely defining the general look of the widget and
961 its children.
962
963 QPalette consists of color groups that have been explicitly defined, and
964 groups that are implicitly inherited from the widget's parent. Because of
965 this, palette() can return a different palette than what has been set with
966 setPalette(). This scheme allows you to define single entries in a palette
967 without affecting the palette's inherited entries.
968
969 When a widget's palette changes, it resolves its entries against its
970 parent widget, or if it doesn't have a parent widget, it resolves against
971 the scene. It then sends itself a \l{QEvent::PaletteChange}{PaletteChange}
972 event, and notifies all its descendants so they can resolve their palettes
973 as well.
974
975 By default, this property contains the application's default palette.
976
977 \sa QGuiApplication::palette(), QGraphicsScene::palette, QPalette::resolve()
978*/
979QPalette QGraphicsWidget::palette() const
980{
981 Q_D(const QGraphicsWidget);
982 return d->palette;
983}
984void QGraphicsWidget::setPalette(const QPalette &palette)
985{
986 Q_D(QGraphicsWidget);
987 setAttribute(Qt::WA_SetPalette, palette.resolveMask() != 0);
988
989 QPalette naturalPalette = d->naturalWidgetPalette();
990 QPalette resolvedPalette = palette.resolve(naturalPalette);
991 d->setPalette_helper(resolvedPalette);
992}
993
994/*!
995 \property QGraphicsWidget::autoFillBackground
996 \brief whether the widget background is filled automatically
997 \since 4.7
998
999 If enabled, this property will cause Qt to fill the background of the
1000 widget before invoking the paint() method. The color used is defined by the
1001 QPalette::Window color role from the widget's \l{QPalette}{palette}.
1002
1003 In addition, Windows are always filled with QPalette::Window, unless the
1004 WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
1005
1006 By default, this property is \c false.
1007
1008 \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
1009*/
1010bool QGraphicsWidget::autoFillBackground() const
1011{
1012 Q_D(const QGraphicsWidget);
1013 return d->autoFillBackground;
1014}
1015void QGraphicsWidget::setAutoFillBackground(bool enabled)
1016{
1017 Q_D(QGraphicsWidget);
1018 if (d->autoFillBackground != enabled) {
1019 d->autoFillBackground = enabled;
1020 update();
1021 }
1022}
1023
1024/*!
1025 If this widget is currently managed by a layout, this function notifies
1026 the layout that the widget's size hints have changed and the layout
1027 may need to resize and reposition the widget accordingly.
1028
1029 Call this function if the widget's sizeHint() has changed.
1030
1031 \sa QGraphicsLayout::invalidate()
1032*/
1033void QGraphicsWidget::updateGeometry()
1034{
1035 QGraphicsLayoutItem::updateGeometry();
1036 QGraphicsLayoutItem *parentItem = parentLayoutItem();
1037
1038 if (parentItem && parentItem->isLayout()) {
1039 if (QGraphicsLayout::instantInvalidatePropagation()) {
1040 static_cast<QGraphicsLayout *>(parentItem)->invalidate();
1041 } else {
1042 parentItem->updateGeometry();
1043 }
1044 } else {
1045 if (parentItem) {
1046 // This is for custom layouting
1047 QGraphicsWidget *parentWid = parentWidget(); //###
1048 if (parentWid->isVisible())
1049 QCoreApplication::postEvent(parentWid, new QEvent(QEvent::LayoutRequest));
1050 } else {
1051 /**
1052 * If this is the topmost widget, post a LayoutRequest event to the widget.
1053 * When the event is received, it will start flowing all the way down to the leaf
1054 * widgets in one go. This will make a relayout flicker-free.
1055 */
1056 if (QGraphicsLayout::instantInvalidatePropagation())
1057 QCoreApplication::postEvent(static_cast<QGraphicsWidget *>(this), new QEvent(QEvent::LayoutRequest));
1058 }
1059 if (!QGraphicsLayout::instantInvalidatePropagation()) {
1060 bool wasResized = testAttribute(Qt::WA_Resized);
1061 resize(size()); // this will restrict the size
1062 setAttribute(Qt::WA_Resized, wasResized);
1063 }
1064 }
1065}
1066
1067/*!
1068 \reimp
1069
1070 QGraphicsWidget uses the base implementation of this function to catch and
1071 deliver events related to state changes in the item. Because of this, it is
1072 very important that subclasses call the base implementation.
1073
1074 \a change specifies the type of change, and \a value is the new value.
1075
1076 For example, QGraphicsWidget uses ItemVisibleChange to deliver
1077 \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events,
1078 ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events,
1079 and ItemParentChange both to deliver \l{QEvent::ParentChange}
1080 {ParentChange} events, and for managing the focus chain.
1081
1082 QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in
1083 order to track position changes.
1084
1085 \sa QGraphicsItem::itemChange()
1086*/
1087QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
1088{
1089 Q_D(QGraphicsWidget);
1090 switch (change) {
1091 case ItemEnabledHasChanged: {
1092 // Send EnabledChange after the enabled state has changed.
1093 QEvent event(QEvent::EnabledChange);
1094 QCoreApplication::sendEvent(this, &event);
1095 break;
1096 }
1097 case ItemVisibleChange:
1098 if (value.toBool()) {
1099 // Send Show event before the item has been shown.
1100 QShowEvent event;
1101 QCoreApplication::sendEvent(this, &event);
1102 bool resized = testAttribute(Qt::WA_Resized);
1103 if (!resized) {
1104 adjustSize();
1105 setAttribute(Qt::WA_Resized, false);
1106 }
1107 }
1108
1109 // layout size hint only changes if an item changes from/to explicitly hidden state
1110 if (value.toBool() || d->explicitlyHidden)
1111 updateGeometry();
1112 break;
1113 case ItemVisibleHasChanged:
1114 if (!value.toBool()) {
1115 // Send Hide event after the item has been hidden.
1116 QHideEvent event;
1117 QCoreApplication::sendEvent(this, &event);
1118 }
1119 break;
1120 case ItemPositionHasChanged:
1121 d->setGeometryFromSetPos();
1122 break;
1123 case ItemParentChange: {
1124 // Deliver ParentAboutToChange.
1125 QEvent event(QEvent::ParentAboutToChange);
1126 QCoreApplication::sendEvent(this, &event);
1127 break;
1128 }
1129 case ItemParentHasChanged: {
1130 // Deliver ParentChange.
1131 QEvent event(QEvent::ParentChange);
1132 QCoreApplication::sendEvent(this, &event);
1133 break;
1134 }
1135 case ItemCursorHasChanged: {
1136 // Deliver CursorChange.
1137 QEvent event(QEvent::CursorChange);
1138 QCoreApplication::sendEvent(this, &event);
1139 break;
1140 }
1141 case ItemToolTipHasChanged: {
1142 // Deliver ToolTipChange.
1143 QEvent event(QEvent::ToolTipChange);
1144 QCoreApplication::sendEvent(this, &event);
1145 break;
1146 }
1147 default:
1148 break;
1149 }
1150 return QGraphicsItem::itemChange(change, value);
1151}
1152
1153/*!
1154 \internal
1155
1156 This virtual function is used to notify changes to any property (both
1157 dynamic properties, and registered with Q_PROPERTY) in the
1158 widget. Depending on the property itself, the notification can be
1159 delivered before or after the value has changed.
1160
1161 \a propertyName is the name of the property (e.g., "size" or "font"), and
1162 \a value is the (proposed) new value of the property. The function returns
1163 the new value, which may be different from \a value if the notification
1164 supports adjusting the property value. The base implementation simply
1165 returns \a value for any \a propertyName.
1166
1167 QGraphicsWidget delivers notifications for the following properties:
1168
1169 \table
1170 \header \li propertyName \li Property
1171 \row \li layoutDirection \li QGraphicsWidget::layoutDirection
1172 \row \li size \li QGraphicsWidget::size
1173 \row \li font \li QGraphicsWidget::font
1174 \row \li palette \li QGraphicsWidget::palette
1175 \endtable
1176
1177 \sa itemChange()
1178*/
1179QVariant QGraphicsWidget::propertyChange(const QString &propertyName, const QVariant &value)
1180{
1181 Q_UNUSED(propertyName);
1182 return value;
1183}
1184
1185/*!
1186 QGraphicsWidget's implementation of sceneEvent() simply passes \a event to
1187 QGraphicsWidget::event(). You can handle all events for your widget in
1188 event() or in any of the convenience functions; you should not have to
1189 reimplement this function in a subclass of QGraphicsWidget.
1190
1191 Returns \c true if \a event has been recognized and processed; otherwise,
1192 returns \c false.
1193
1194 \sa QGraphicsItem::sceneEvent()
1195*/
1196bool QGraphicsWidget::sceneEvent(QEvent *event)
1197{
1198 return QGraphicsItem::sceneEvent(event);
1199}
1200
1201/*!
1202 This event handler, for \a event, receives events for the window frame if
1203 this widget is a window. Its base implementation provides support for
1204 default window frame interaction such as moving, resizing, etc.
1205
1206 You can reimplement this handler in a subclass of QGraphicsWidget to
1207 provide your own custom window frame interaction support.
1208
1209 Returns \c true if \a event has been recognized and processed; otherwise,
1210 returns \c false.
1211
1212 \sa event()
1213*/
1214bool QGraphicsWidget::windowFrameEvent(QEvent *event)
1215{
1216 Q_D(QGraphicsWidget);
1217 switch (event->type()) {
1218 case QEvent::GraphicsSceneMousePress:
1219 d->windowFrameMousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
1220 break;
1221 case QEvent::GraphicsSceneMouseMove:
1222 d->ensureWindowData();
1223 if (d->windowData->grabbedSection != Qt::NoSection) {
1224 d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
1225 event->accept();
1226 }
1227 break;
1228 case QEvent::GraphicsSceneMouseRelease:
1229 d->windowFrameMouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
1230 break;
1231 case QEvent::GraphicsSceneHoverMove:
1232 d->windowFrameHoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
1233 break;
1234 case QEvent::GraphicsSceneHoverLeave:
1235 d->windowFrameHoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
1236 break;
1237 default:
1238 break;
1239 }
1240 return event->isAccepted();
1241}
1242
1243/*!
1244 \since 4.4
1245
1246 Returns the window frame section at position \a pos, or
1247 Qt::NoSection if there is no window frame section at this
1248 position.
1249
1250 This function is used in QGraphicsWidget's base implementation for window
1251 frame interaction.
1252
1253 You can reimplement this function if you want to customize how a window
1254 can be interactively moved or resized. For instance, if you only want to
1255 allow a window to be resized by the bottom right corner, you can
1256 reimplement this function to return Qt::NoSection for all sections except
1257 Qt::BottomRightSection.
1258
1259 \sa windowFrameEvent(), paintWindowFrame(), windowFrameGeometry()
1260*/
1261Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) const
1262{
1263 Q_D(const QGraphicsWidget);
1264
1265 const QRectF r = windowFrameRect();
1266 if (!r.contains(pos))
1267 return Qt::NoSection;
1268
1269 const qreal left = r.left();
1270 const qreal top = r.top();
1271 const qreal right = r.right();
1272 const qreal bottom = r.bottom();
1273 const qreal x = pos.x();
1274 const qreal y = pos.y();
1275
1276 const qreal cornerMargin = 20;
1277 //### Not sure of this one, it should be the same value for all edges.
1278 const qreal windowFrameWidth = d->windowFrameMargins
1279 ? d->windowFrameMargins->left() : 0;
1280
1281 Qt::WindowFrameSection s = Qt::NoSection;
1282 if (x <= left + cornerMargin) {
1283 if (y <= top + windowFrameWidth || (x <= left + windowFrameWidth && y <= top + cornerMargin)) {
1284 s = Qt::TopLeftSection;
1285 } else if (y >= bottom - windowFrameWidth || (x <= left + windowFrameWidth && y >= bottom - cornerMargin)) {
1286 s = Qt::BottomLeftSection;
1287 } else if (x <= left + windowFrameWidth) {
1288 s = Qt::LeftSection;
1289 }
1290 } else if (x >= right - cornerMargin) {
1291 if (y <= top + windowFrameWidth || (x >= right - windowFrameWidth && y <= top + cornerMargin)) {
1292 s = Qt::TopRightSection;
1293 } else if (y >= bottom - windowFrameWidth || (x >= right - windowFrameWidth && y >= bottom - cornerMargin)) {
1294 s = Qt::BottomRightSection;
1295 } else if (x >= right - windowFrameWidth) {
1296 s = Qt::RightSection;
1297 }
1298 } else if (y <= top + windowFrameWidth) {
1299 s = Qt::TopSection;
1300 } else if (y >= bottom - windowFrameWidth) {
1301 s = Qt::BottomSection;
1302 }
1303 if (s == Qt::NoSection) {
1304 QRectF r1 = r;
1305 r1.setHeight(d->windowFrameMargins
1306 ? d->windowFrameMargins->top() : 0);
1307 if (r1.contains(pos))
1308 s = Qt::TitleBarArea;
1309 }
1310 return s;
1311}
1312
1313/*!
1314 \reimp
1315
1316 Handles the \a event. QGraphicsWidget handles the following
1317 events:
1318
1319 \table
1320 \header \li Event \li Usage
1321 \row \li Polish
1322 \li Delivered to the widget some time after it has been
1323 shown.
1324 \row \li GraphicsSceneMove
1325 \li Delivered to the widget after its local position has
1326 changed.
1327 \row \li GraphicsSceneResize
1328 \li Delivered to the widget after its size has changed.
1329 \row \li Show
1330 \li Delivered to the widget before it has been shown.
1331 \row \li Hide
1332 \li Delivered to the widget after it has been hidden.
1333 \row \li PaletteChange
1334 \li Delivered to the widget after its palette has changed.
1335 \row \li FontChange
1336 \li Delivered to the widget after its font has changed.
1337 \row \li EnabledChange
1338 \li Delivered to the widget after its enabled state has
1339 changed.
1340 \row \li StyleChange
1341 \li Delivered to the widget after its style has changed.
1342 \row \li LayoutDirectionChange
1343 \li Delivered to the widget after its layout direction has
1344 changed.
1345 \row \li ContentsRectChange
1346 \li Delivered to the widget after its contents margins/
1347 contents rect has changed.
1348 \endtable
1349*/
1350bool QGraphicsWidget::event(QEvent *event)
1351{
1352 Q_D(QGraphicsWidget);
1353 // Forward the event to the layout first.
1354 if (d->layout)
1355 d->layout->widgetEvent(event);
1356
1357 // Handle the event itself.
1358 switch (event->type()) {
1359 case QEvent::GraphicsSceneMove:
1360 moveEvent(static_cast<QGraphicsSceneMoveEvent *>(event));
1361 break;
1362 case QEvent::GraphicsSceneResize:
1363 resizeEvent(static_cast<QGraphicsSceneResizeEvent *>(event));
1364 break;
1365 case QEvent::Show:
1366 showEvent(static_cast<QShowEvent *>(event));
1367 break;
1368 case QEvent::Hide:
1369 hideEvent(static_cast<QHideEvent *>(event));
1370 break;
1371 case QEvent::Polish:
1372 polishEvent();
1373 d->polished = true;
1374 if (!d->font.isCopyOf(QApplication::font()))
1375 d->updateFont(d->font);
1376 break;
1377 case QEvent::WindowActivate:
1378 case QEvent::WindowDeactivate:
1379 update();
1380 break;
1381 case QEvent::StyleAnimationUpdate:
1382 if (isVisible()) {
1383 event->accept();
1384 update();
1385 }
1386 break;
1387 // Taken from QWidget::event
1388 case QEvent::ActivationChange:
1389 case QEvent::EnabledChange:
1390 case QEvent::FontChange:
1391 case QEvent::StyleChange:
1392 case QEvent::PaletteChange:
1393 case QEvent::ParentChange:
1394 case QEvent::ContentsRectChange:
1395 case QEvent::LayoutDirectionChange:
1396 changeEvent(event);
1397 break;
1398 case QEvent::Close:
1399 closeEvent((QCloseEvent *)event);
1400 break;
1401 case QEvent::GrabMouse:
1402 grabMouseEvent(event);
1403 break;
1404 case QEvent::UngrabMouse:
1405 ungrabMouseEvent(event);
1406 break;
1407 case QEvent::GrabKeyboard:
1408 grabKeyboardEvent(event);
1409 break;
1410 case QEvent::UngrabKeyboard:
1411 ungrabKeyboardEvent(event);
1412 break;
1413 case QEvent::GraphicsSceneMousePress:
1414 if (d->hasDecoration() && windowFrameEvent(event))
1415 return true;
1416 break;
1417 case QEvent::GraphicsSceneMouseMove:
1418 case QEvent::GraphicsSceneMouseRelease:
1419 case QEvent::GraphicsSceneMouseDoubleClick:
1420 d->ensureWindowData();
1421 if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection)
1422 return windowFrameEvent(event);
1423 break;
1424 case QEvent::GraphicsSceneHoverEnter:
1425 case QEvent::GraphicsSceneHoverMove:
1426 case QEvent::GraphicsSceneHoverLeave:
1427 if (d->hasDecoration()) {
1428 windowFrameEvent(event);
1429 // Filter out hover events if they were sent to us only because of the
1430 // decoration (special case in QGraphicsScenePrivate::dispatchHoverEvent).
1431 if (!acceptHoverEvents())
1432 return true;
1433 }
1434 break;
1435 default:
1436 break;
1437 }
1438 return QObject::event(event);
1439}
1440
1441/*!
1442 This event handler can be reimplemented to handle state changes.
1443
1444 The state being changed in this event can be retrieved through \a event.
1445
1446 Change events include: QEvent::ActivationChange, QEvent::EnabledChange,
1447 QEvent::FontChange, QEvent::StyleChange, QEvent::PaletteChange,
1448 QEvent::ParentChange, QEvent::LayoutDirectionChange, and
1449 QEvent::ContentsRectChange.
1450*/
1451void QGraphicsWidget::changeEvent(QEvent *event)
1452{
1453 Q_D(QGraphicsWidget);
1454 switch (event->type()) {
1455 case QEvent::StyleChange:
1456 // ### Don't unset if the margins are explicitly set.
1457 unsetWindowFrameMargins();
1458 if (d->layout)
1459 d->layout->invalidate();
1460 Q_FALLTHROUGH();
1461 case QEvent::FontChange:
1462 update();
1463 updateGeometry();
1464 break;
1465 case QEvent::PaletteChange:
1466 update();
1467 break;
1468 case QEvent::ParentChange:
1469 d->resolveFont(d->inheritedFontResolveMask);
1470 d->resolvePalette(d->inheritedPaletteResolveMask);
1471 break;
1472 default:
1473 break;
1474 }
1475}
1476
1477/*!
1478 This event handler, for \a event, can be reimplemented in a subclass to
1479 receive widget close events. The default implementation accepts the
1480 event.
1481
1482 \sa close(), QCloseEvent
1483*/
1484void QGraphicsWidget::closeEvent(QCloseEvent *event)
1485{
1486 event->accept();
1487}
1488
1489/*!
1490 \reimp
1491*/
1492void QGraphicsWidget::focusInEvent(QFocusEvent *event)
1493{
1494 Q_UNUSED(event);
1495 if (focusPolicy() != Qt::NoFocus)
1496 update();
1497}
1498
1499/*!
1500 Finds a new widget to give the keyboard focus to, as appropriate for Tab
1501 and Shift+Tab, and returns \c true if it can find a new widget; returns \c false
1502 otherwise. If \a next is true, this function searches forward; if \a next
1503 is false, it searches backward.
1504
1505 Sometimes, you will want to reimplement this function to provide special
1506 focus handling for your widget and its subwidgets. For example, a web
1507 browser might reimplement it to move its current active link forward or
1508 backward, and call the base implementation only when it reaches the last
1509 or first link on the page.
1510
1511 Child widgets call focusNextPrevChild() on their parent widgets, but only
1512 the window that contains the child widgets decides where to redirect
1513 focus. By reimplementing this function for an object, you gain control of
1514 focus traversal for all child widgets.
1515
1516 \sa focusPolicy()
1517*/
1518bool QGraphicsWidget::focusNextPrevChild(bool next)
1519{
1520 Q_D(QGraphicsWidget);
1521 // Let the parent's focusNextPrevChild implementation decide what to do.
1522 QGraphicsWidget *parent = nullptr;
1523 if (!isWindow() && (parent = parentWidget()))
1524 return parent->focusNextPrevChild(next);
1525 if (!d->scene)
1526 return false;
1527 if (d->scene->focusNextPrevChild(next))
1528 return true;
1529 if (isWindow()) {
1530 setFocus(next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
1531 if (hasFocus())
1532 return true;
1533 }
1534 return false;
1535}
1536
1537/*!
1538 \reimp
1539*/
1540void QGraphicsWidget::focusOutEvent(QFocusEvent *event)
1541{
1542 Q_UNUSED(event);
1543 if (focusPolicy() != Qt::NoFocus)
1544 update();
1545}
1546
1547/*!
1548 This event handler, for \l{QEvent::Hide}{Hide} events, is delivered after
1549 the widget has been hidden, for example, setVisible(false) has been called
1550 for the widget or one of its ancestors when the widget was previously
1551 shown.
1552
1553 You can reimplement this event handler to detect when your widget is
1554 hidden. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1555 effect.
1556
1557 \sa showEvent(), QWidget::hideEvent(), ItemVisibleChange
1558*/
1559void QGraphicsWidget::hideEvent(QHideEvent *event)
1560{
1561 ///### focusNextPrevChild(true), don't lose focus when the focus widget
1562 // is hidden.
1563 Q_UNUSED(event);
1564}
1565
1566/*!
1567 This event handler, for \l{QEvent::GraphicsSceneMove}{GraphicsSceneMove}
1568 events, is delivered after the widget has moved (e.g., its local position
1569 has changed).
1570
1571 This event is only delivered when the item is moved locally. Calling
1572 setTransform() or moving any of the item's ancestors does not affect the
1573 item's local position.
1574
1575 You can reimplement this event handler to detect when your widget has
1576 moved. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1577 effect.
1578
1579 \sa ItemPositionChange, ItemPositionHasChanged
1580*/
1581void QGraphicsWidget::moveEvent(QGraphicsSceneMoveEvent *event)
1582{
1583 // ### Last position is always == current position
1584 Q_UNUSED(event);
1585}
1586
1587/*!
1588 This event is delivered to the item by the scene at some point after it
1589 has been constructed, but before it is shown or otherwise accessed through
1590 the scene. You can use this event handler to do last-minute initializations
1591 of the widget which require the item to be fully constructed.
1592
1593 The base implementation does nothing.
1594*/
1595void QGraphicsWidget::polishEvent()
1596{
1597}
1598
1599/*!
1600 This event handler, for
1601 \l{QEvent::GraphicsSceneResize}{GraphicsSceneResize} events, is
1602 delivered after the widget has been resized (i.e., its local size has
1603 changed). \a event contains both the old and the new size.
1604
1605 This event is only delivered when the widget is resized locally; calling
1606 setTransform() on the widget or any of its ancestors or view, does not
1607 affect the widget's local size.
1608
1609 You can reimplement this event handler to detect when your widget has been
1610 resized. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1611 effect.
1612
1613 \sa geometry(), setGeometry()
1614*/
1615void QGraphicsWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
1616{
1617 Q_UNUSED(event);
1618}
1619
1620/*!
1621 This event handler, for \l{QEvent::Show}{Show} events, is delivered before
1622 the widget has been shown, for example, setVisible(true) has been called
1623 for the widget or one of its ancestors when the widget was previously
1624 hidden.
1625
1626 You can reimplement this event handler to detect when your widget is
1627 shown. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1628 effect.
1629
1630 \sa hideEvent(), QWidget::showEvent(), ItemVisibleChange
1631*/
1632void QGraphicsWidget::showEvent(QShowEvent *event)
1633{
1634 Q_UNUSED(event);
1635}
1636
1637/*!
1638 \reimp
1639*/
1640void QGraphicsWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1641{
1642 Q_UNUSED(event);
1643}
1644
1645/*!
1646 \reimp
1647*/
1648void QGraphicsWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1649{
1650 QGraphicsObject::hoverLeaveEvent(event);
1651}
1652
1653/*!
1654 This event handler, for \a event, can be reimplemented in a subclass to
1655 receive notifications for QEvent::GrabMouse events.
1656
1657 \sa grabMouse(), grabKeyboard()
1658*/
1659void QGraphicsWidget::grabMouseEvent(QEvent *event)
1660{
1661 Q_UNUSED(event);
1662}
1663
1664/*!
1665 This event handler, for \a event, can be reimplemented in a subclass to
1666 receive notifications for QEvent::UngrabMouse events.
1667
1668 \sa ungrabMouse(), ungrabKeyboard()
1669*/
1670void QGraphicsWidget::ungrabMouseEvent(QEvent *event)
1671{
1672 Q_UNUSED(event);
1673}
1674
1675/*!
1676 This event handler, for \a event, can be reimplemented in a subclass to
1677 receive notifications for QEvent::GrabKeyboard events.
1678
1679 \sa grabKeyboard(), grabMouse()
1680*/
1681void QGraphicsWidget::grabKeyboardEvent(QEvent *event)
1682{
1683 Q_UNUSED(event);
1684}
1685
1686/*!
1687 This event handler, for \a event, can be reimplemented in a subclass to
1688 receive notifications for QEvent::UngrabKeyboard events.
1689
1690 \sa ungrabKeyboard(), ungrabMouse()
1691*/
1692void QGraphicsWidget::ungrabKeyboardEvent(QEvent *event)
1693{
1694 Q_UNUSED(event);
1695}
1696
1697/*!
1698 Returns the widgets window type.
1699
1700 \sa windowFlags(), isWindow(), isPanel()
1701*/
1702Qt::WindowType QGraphicsWidget::windowType() const
1703{
1704 return Qt::WindowType(int(windowFlags()) & Qt::WindowType_Mask);
1705}
1706
1707/*!
1708 \property QGraphicsWidget::windowFlags
1709 \brief the widget's window flags
1710
1711 Window flags are a combination of a window type (e.g., Qt::Dialog) and
1712 several flags giving hints on the behavior of the window. The behavior
1713 is platform-dependent.
1714
1715 By default, this property contains no window flags.
1716
1717 Windows are panels. If you set the Qt::Window flag, the ItemIsPanel flag
1718 will be set automatically. If you clear the Qt::Window flag, the
1719 ItemIsPanel flag is also cleared. Note that the ItemIsPanel flag can be
1720 set independently of Qt::Window.
1721
1722 \sa isWindow(), isPanel()
1723*/
1724Qt::WindowFlags QGraphicsWidget::windowFlags() const
1725{
1726 Q_D(const QGraphicsWidget);
1727 return d->windowFlags;
1728}
1729void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
1730{
1731 Q_D(QGraphicsWidget);
1732 if (d->windowFlags == wFlags)
1733 return;
1734 bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
1735
1736 d->adjustWindowFlags(&wFlags);
1737 d->windowFlags = wFlags;
1738 if (!d->setWindowFrameMargins)
1739 unsetWindowFrameMargins();
1740
1741 setFlag(ItemIsPanel, d->windowFlags & Qt::Window);
1742
1743 bool isPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
1744 if (d->scene && isVisible() && wasPopup != isPopup) {
1745 // Popup state changed; update implicit mouse grab.
1746 if (!isPopup)
1747 d->scene->d_func()->removePopup(this);
1748 else
1749 d->scene->d_func()->addPopup(this);
1750 }
1751
1752 if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) {
1753 d->scene->d_func()->allItemsIgnoreHoverEvents = false;
1754 d->scene->d_func()->enableMouseTrackingOnViews();
1755 }
1756}
1757
1758/*!
1759 Returns \c true if this widget's window is in the active window, or if the
1760 widget does not have a window but is in an active scene (i.e., a scene
1761 that currently has focus).
1762
1763 The active window is the window that either contains a child widget that
1764 currently has input focus, or that itself has input focus.
1765
1766 \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow(), isActive()
1767*/
1768bool QGraphicsWidget::isActiveWindow() const
1769{
1770 return isActive();
1771}
1772
1773/*!
1774 \property QGraphicsWidget::windowTitle
1775 \brief This property holds the window title (caption).
1776
1777 This property is only used for windows.
1778
1779 By default, if no title has been set, this property contains an
1780 empty string.
1781*/
1782void QGraphicsWidget::setWindowTitle(const QString &title)
1783{
1784 Q_D(QGraphicsWidget);
1785 d->ensureWindowData();
1786 d->windowData->windowTitle = title;
1787}
1788QString QGraphicsWidget::windowTitle() const
1789{
1790 Q_D(const QGraphicsWidget);
1791 return d->windowData ? d->windowData->windowTitle : QString();
1792}
1793
1794/*!
1795 \property QGraphicsWidget::focusPolicy
1796 \brief the way the widget accepts keyboard focus
1797
1798 The focus policy is Qt::TabFocus if the widget accepts keyboard focus by
1799 tabbing, Qt::ClickFocus if the widget accepts focus by clicking,
1800 Qt::StrongFocus if it accepts both, and Qt::NoFocus (the default) if it
1801 does not accept focus at all.
1802
1803 You must enable keyboard focus for a widget if it processes keyboard
1804 events. This is normally done from the widget's constructor. For instance,
1805 the QLineEdit constructor calls setFocusPolicy(Qt::StrongFocus).
1806
1807 If you enable a focus policy (i.e., not Qt::NoFocus), QGraphicsWidget will
1808 automatically enable the ItemIsFocusable flag. Setting Qt::NoFocus on a
1809 widget will clear the ItemIsFocusable flag. If the widget currently has
1810 keyboard focus, the widget will automatically lose focus.
1811
1812 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
1813*/
1814Qt::FocusPolicy QGraphicsWidget::focusPolicy() const
1815{
1816 Q_D(const QGraphicsWidget);
1817 return d->focusPolicy;
1818}
1819void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy)
1820{
1821 Q_D(QGraphicsWidget);
1822 if (d->focusPolicy == policy)
1823 return;
1824 d->focusPolicy = policy;
1825 if (hasFocus() && policy == Qt::NoFocus)
1826 clearFocus();
1827 setFlag(ItemIsFocusable, policy != Qt::NoFocus);
1828}
1829
1830/*!
1831 If this widget, a child or descendant of this widget currently has input
1832 focus, this function will return a pointer to that widget. If
1833 no descendant widget has input focus, \nullptr is returned.
1834
1835 \sa QGraphicsItem::focusItem(), QWidget::focusWidget()
1836*/
1837QGraphicsWidget *QGraphicsWidget::focusWidget() const
1838{
1839 Q_D(const QGraphicsWidget);
1840 if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget)
1841 return static_cast<QGraphicsWidget *>(d->subFocusItem);
1842 return nullptr;
1843}
1844
1845#ifndef QT_NO_SHORTCUT
1846/*!
1847 \since 4.5
1848
1849 Adds a shortcut to Qt's shortcut system that watches for the given key \a
1850 sequence in the given \a context. If the \a context is
1851 Qt::ApplicationShortcut, the shortcut applies to the application as a
1852 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
1853 or to the window itself, Qt::WindowShortcut. For widgets that are not part
1854 of a window (i.e., top-level widgets and their children),
1855 Qt::WindowShortcut shortcuts apply to the scene.
1856
1857 If the same key \a sequence has been grabbed by several widgets,
1858 when the key \a sequence occurs a QEvent::Shortcut event is sent
1859 to all the widgets to which it applies in a non-deterministic
1860 order, but with the ``ambiguous'' flag set to true.
1861
1862 \warning You should not normally need to use this function;
1863 instead create \l{QAction}s with the shortcut key sequences you
1864 require (if you also want equivalent menu options and toolbar
1865 buttons), or create \l{QShortcut}s if you just need key sequences.
1866 Both QAction and QShortcut handle all the event filtering for you,
1867 and provide signals which are triggered when the user triggers the
1868 key sequence, so are much easier to use than this low-level
1869 function.
1870
1871 \sa releaseShortcut(), setShortcutEnabled(), QWidget::grabShortcut()
1872*/
1873int QGraphicsWidget::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context)
1874{
1875 Q_ASSERT(qApp);
1876 if (sequence.isEmpty())
1877 return 0;
1878 // ### setAttribute(Qt::WA_GrabbedShortcut);
1879 return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, sequence, context, qWidgetShortcutContextMatcher);
1880}
1881
1882/*!
1883 \since 4.5
1884
1885 Removes the shortcut with the given \a id from Qt's shortcut
1886 system. The widget will no longer receive QEvent::Shortcut events
1887 for the shortcut's key sequence (unless it has other shortcuts
1888 with the same key sequence).
1889
1890 \warning You should not normally need to use this function since
1891 Qt's shortcut system removes shortcuts automatically when their
1892 parent widget is destroyed. It is best to use QAction or
1893 QShortcut to handle shortcuts, since they are easier to use than
1894 this low-level function. Note also that this is an expensive
1895 operation.
1896
1897 \sa grabShortcut(), setShortcutEnabled(), QWidget::releaseShortcut()
1898*/
1899void QGraphicsWidget::releaseShortcut(int id)
1900{
1901 Q_ASSERT(qApp);
1902 if (id)
1903 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0);
1904}
1905
1906/*!
1907 \since 4.5
1908
1909 If \a enabled is true, the shortcut with the given \a id is
1910 enabled; otherwise the shortcut is disabled.
1911
1912 \warning You should not normally need to use this function since
1913 Qt's shortcut system enables/disables shortcuts automatically as
1914 widgets become hidden/visible and gain or lose focus. It is best
1915 to use QAction or QShortcut to handle shortcuts, since they are
1916 easier to use than this low-level function.
1917
1918 \sa grabShortcut(), releaseShortcut(), QWidget::setShortcutEnabled()
1919*/
1920void QGraphicsWidget::setShortcutEnabled(int id, bool enabled)
1921{
1922 Q_ASSERT(qApp);
1923 if (id)
1924 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, id, this, 0);
1925}
1926
1927/*!
1928 \since 4.5
1929
1930 If \a enabled is true, auto repeat of the shortcut with the
1931 given \a id is enabled; otherwise it is disabled.
1932
1933 \sa grabShortcut(), releaseShortcut(), QWidget::setShortcutAutoRepeat()
1934*/
1935void QGraphicsWidget::setShortcutAutoRepeat(int id, bool enabled)
1936{
1937 Q_ASSERT(qApp);
1938 if (id)
1939 QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enabled, id, this, 0);
1940}
1941#endif
1942
1943#ifndef QT_NO_ACTION
1944/*!
1945 \since 4.5
1946
1947 Appends the action \a action to this widget's list of actions.
1948
1949 All QGraphicsWidgets have a list of \l{QAction}s, however they can be
1950 represented graphically in many different ways. The default use of the
1951 QAction list (as returned by actions()) is to create a context QMenu.
1952
1953 A QGraphicsWidget should only have one of each action and adding an action
1954 it already has will not cause the same action to be in the widget twice.
1955
1956 \sa removeAction(), insertAction(), actions(), QWidget::addAction()
1957*/
1958void QGraphicsWidget::addAction(QAction *action)
1959{
1960 insertAction(nullptr, action);
1961}
1962
1963/*!
1964 \since 4.5
1965
1966 Appends the actions \a actions to this widget's list of actions.
1967
1968 \sa removeAction(), QMenu, addAction(), QWidget::addActions()
1969*/
1970void QGraphicsWidget::addActions(const QList<QAction *> &actions)
1971{
1972 for (int i = 0; i < actions.size(); ++i)
1973 insertAction(nullptr, actions.at(i));
1974}
1975
1976/*!
1977 \since 4.5
1978
1979 Inserts the action \a action to this widget's list of actions,
1980 before the action \a before. It appends the action if \a before is \nullptr or
1981 \a before is not a valid action for this widget.
1982
1983 A QGraphicsWidget should only have one of each action.
1984
1985 \sa removeAction(), addAction(), QMenu, actions(),
1986 QWidget::insertActions()
1987*/
1988void QGraphicsWidget::insertAction(QAction *before, QAction *action)
1989{
1990 if (!action) {
1991 qWarning("QWidget::insertAction: Attempt to insert null action");
1992 return;
1993 }
1994
1995 Q_D(QGraphicsWidget);
1996 int index = d->actions.indexOf(action);
1997 if (index != -1)
1998 d->actions.removeAt(index);
1999
2000 int pos = d->actions.indexOf(before);
2001 if (pos < 0) {
2002 before = nullptr;
2003 pos = d->actions.size();
2004 }
2005 d->actions.insert(pos, action);
2006
2007 if (index == -1) {
2008 QActionPrivate *apriv = action->d_func();
2009 apriv->associatedObjects.append(this);
2010 }
2011
2012 QActionEvent e(QEvent::ActionAdded, action, before);
2013 QCoreApplication::sendEvent(this, &e);
2014}
2015
2016/*!
2017 \since 4.5
2018
2019 Inserts the actions \a actions to this widget's list of actions,
2020 before the action \a before. It appends the action if \a before is \nullptr or
2021 \a before is not a valid action for this widget.
2022
2023 A QGraphicsWidget can have at most one of each action.
2024
2025 \sa removeAction(), QMenu, insertAction(), QWidget::insertActions()
2026*/
2027void QGraphicsWidget::insertActions(QAction *before, const QList<QAction *> &actions)
2028{
2029 for (int i = 0; i < actions.size(); ++i)
2030 insertAction(before, actions.at(i));
2031}
2032
2033/*!
2034 \since 4.5
2035
2036 Removes the action \a action from this widget's list of actions.
2037
2038 \sa insertAction(), actions(), insertAction(), QWidget::removeAction()
2039*/
2040void QGraphicsWidget::removeAction(QAction *action)
2041{
2042 if (!action)
2043 return;
2044
2045 Q_D(QGraphicsWidget);
2046
2047 QActionPrivate *apriv = action->d_func();
2048 apriv->associatedObjects.removeAll(this);
2049
2050 if (d->actions.removeAll(action)) {
2051 QActionEvent e(QEvent::ActionRemoved, action);
2052 QCoreApplication::sendEvent(this, &e);
2053 }
2054}
2055
2056/*!
2057 \since 4.5
2058
2059 Returns the (possibly empty) list of this widget's actions.
2060
2061 \sa insertAction(), removeAction(), QWidget::actions(),
2062 QAction::associatedWidgets(), QAction::associatedGraphicsWidgets()
2063*/
2064QList<QAction *> QGraphicsWidget::actions() const
2065{
2066 Q_D(const QGraphicsWidget);
2067 return d->actions;
2068}
2069#endif
2070
2071/*!
2072 Moves the \a second widget around the ring of focus widgets so that
2073 keyboard focus moves from the \a first widget to the \a second widget when
2074 the Tab key is pressed.
2075
2076 Note that since the tab order of the \a second widget is changed, you
2077 should order a chain like this:
2078
2079 \snippet code/src_gui_graphicsview_qgraphicswidget.cpp 1
2080
2081 \e not like this:
2082
2083 \snippet code/src_gui_graphicsview_qgraphicswidget.cpp 2
2084
2085 If \a first is \nullptr, this indicates that \a second should be the first widget
2086 to receive input focus should the scene gain Tab focus (i.e., the user
2087 hits Tab so that focus passes into the scene). If \a second is \nullptr, this
2088 indicates that \a first should be the first widget to gain focus if the
2089 scene gained BackTab focus.
2090
2091 By default, tab order is defined implicitly using widget creation order.
2092
2093 \sa focusPolicy, {Keyboard Focus in Widgets}
2094*/
2095void QGraphicsWidget::setTabOrder(QGraphicsWidget *first, QGraphicsWidget *second)
2096{
2097 if (!first && !second) {
2098 qWarning("QGraphicsWidget::setTabOrder(0, 0) is undefined");
2099 return;
2100 }
2101 if ((first && second) && first->scene() != second->scene()) {
2102 qWarning("QGraphicsWidget::setTabOrder: scenes %p and %p are different",
2103 first->scene(), second->scene());
2104 return;
2105 }
2106 QGraphicsScene *scene = first ? first->scene() : second->scene();
2107 if (!scene) {
2108 qWarning("QGraphicsWidget::setTabOrder: assigning tab order from/to the"
2109 " scene requires the item to be in a scene.");
2110 return;
2111 }
2112
2113 // If either first or second are 0, the scene's tabFocusFirst is updated
2114 // to point to the first item in the scene's focus chain. Then first or
2115 // second are set to point to tabFocusFirst.
2116 QGraphicsScenePrivate *sceneD = scene->d_func();
2117 if (!first) {
2118 sceneD->tabFocusFirst = second;
2119 return;
2120 }
2121 if (!second) {
2122 sceneD->tabFocusFirst = first->d_func()->focusNext;
2123 return;
2124 }
2125
2126 // Both first and second are != 0.
2127 QGraphicsWidget *firstFocusNext = first->d_func()->focusNext;
2128 if (firstFocusNext == second) {
2129 // Nothing to do.
2130 return;
2131 }
2132
2133 // Update the focus chain.
2134 QGraphicsWidget *secondFocusPrev = second->d_func()->focusPrev;
2135 QGraphicsWidget *secondFocusNext = second->d_func()->focusNext;
2136 firstFocusNext->d_func()->focusPrev = second;
2137 first->d_func()->focusNext = second;
2138 second->d_func()->focusNext = firstFocusNext;
2139 second->d_func()->focusPrev = first;
2140 secondFocusPrev->d_func()->focusNext = secondFocusNext;
2141 secondFocusNext->d_func()->focusPrev = secondFocusPrev;
2142
2143 Q_ASSERT(first->d_func()->focusNext->d_func()->focusPrev == first);
2144 Q_ASSERT(first->d_func()->focusPrev->d_func()->focusNext == first);
2145
2146 Q_ASSERT(second->d_func()->focusNext->d_func()->focusPrev == second);
2147 Q_ASSERT(second->d_func()->focusPrev->d_func()->focusNext == second);
2148
2149}
2150
2151/*!
2152 If \a on is true, this function enables \a attribute; otherwise
2153 \a attribute is disabled.
2154
2155 See the class documentation for QGraphicsWidget for a complete list of
2156 which attributes are supported, and what they are for.
2157
2158 \sa testAttribute(), QWidget::setAttribute()
2159*/
2160void QGraphicsWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
2161{
2162 Q_D(QGraphicsWidget);
2163 // ### most flags require some immediate action
2164 // ### we might want to qWarn use of unsupported attributes
2165 // ### we might want to not use Qt::WidgetAttribute, but roll our own instead
2166 d->setAttribute(attribute, on);
2167}
2168
2169/*!
2170 Returns \c true if \a attribute is enabled for this widget; otherwise,
2171 returns \c false.
2172
2173 \sa setAttribute()
2174*/
2175bool QGraphicsWidget::testAttribute(Qt::WidgetAttribute attribute) const
2176{
2177 Q_D(const QGraphicsWidget);
2178 return d->testAttribute(attribute);
2179}
2180
2181/*!
2182 \enum QGraphicsWidget::anonymous
2183
2184 The value returned by the virtual type() function.
2185
2186 \value Type A graphics widget item
2187*/
2188
2189/*!
2190 \reimp
2191*/
2192int QGraphicsWidget::type() const
2193{
2194 return Type;
2195}
2196
2197/*!
2198 \reimp
2199*/
2200void QGraphicsWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2201{
2202 Q_UNUSED(painter);
2203 Q_UNUSED(option);
2204 Q_UNUSED(widget);
2205}
2206
2207/*!
2208 This virtual function is called by QGraphicsScene to draw the window frame
2209 for windows using \a painter, \a option, and \a widget, in local
2210 coordinates. The base implementation uses the current style to render the
2211 frame and title bar.
2212
2213 You can reimplement this function in a subclass of QGraphicsWidget to
2214 provide custom rendering of the widget's window frame.
2215
2216 \sa QGraphicsItem::paint()
2217*/
2218void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
2219 QWidget *widget)
2220{
2221 const bool fillBackground = !testAttribute(Qt::WA_OpaquePaintEvent)
2222 && !testAttribute(Qt::WA_NoSystemBackground);
2223 QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(this);
2224 const bool embeddedWidgetFillsOwnBackground = proxy && proxy->widget();
2225
2226 if (rect().contains(option->exposedRect)) {
2227 if (fillBackground && !embeddedWidgetFillsOwnBackground)
2228 painter->fillRect(option->exposedRect, palette().window());
2229 return;
2230 }
2231
2232 Q_D(QGraphicsWidget);
2233
2234 QRect windowFrameRect = QRect(QPoint(), windowFrameGeometry().size().toSize());
2235 QStyleOptionTitleBar bar;
2236 bar.QStyleOption::operator=(*option);
2237 d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state
2238 d->ensureWindowData();
2239 bar.state.setFlag(QStyle::State_MouseOver, d->windowData->buttonMouseOver);
2240 bar.state.setFlag(QStyle::State_Sunken, d->windowData->buttonSunken);
2241 bar.rect = windowFrameRect;
2242
2243 // translate painter to make the style happy
2244 const QPointF styleOrigin = this->windowFrameRect().topLeft();
2245 painter->translate(styleOrigin);
2246
2247#ifdef Q_OS_MAC
2248 const QSize pixmapSize = windowFrameRect.size();
2249 if (pixmapSize.width() <= 0 || pixmapSize.height() <= 0)
2250 return;
2251 QPainter *realPainter = painter;
2252 QPixmap pm(pixmapSize);
2253 painter = new QPainter(&pm);
2254#endif
2255
2256 // Fill background
2257 QStyleHintReturnMask mask;
2258 bool setMask = style()->styleHint(QStyle::SH_WindowFrame_Mask, &bar, widget, &mask) && !mask.region.isEmpty();
2259 bool hasBorder = !style()->styleHint(QStyle::SH_TitleBar_NoBorder, &bar, widget);
2260 int frameWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, &bar, widget);
2261 if (setMask) {
2262 painter->save();
2263 painter->setClipRegion(mask.region, Qt::IntersectClip);
2264 }
2265 if (fillBackground) {
2266 if (embeddedWidgetFillsOwnBackground) {
2267 // Don't fill the background twice.
2268 QPainterPath windowFrameBackground;
2269 windowFrameBackground.addRect(windowFrameRect);
2270 // Adjust with 0.5 to avoid border artifacts between
2271 // widget background and frame background.
2272 windowFrameBackground.addRect(rect().translated(-styleOrigin).adjusted(0.5, 0.5, -0.5, -0.5));
2273 painter->fillPath(windowFrameBackground, palette().window());
2274 } else {
2275 painter->fillRect(windowFrameRect, palette().window());
2276 }
2277 }
2278
2279 // Draw title
2280 int height = (int)d->titleBarHeight(bar);
2281 bar.rect.setHeight(height);
2282 if (hasBorder) // Frame is painted by PE_FrameWindow
2283 bar.rect.adjust(frameWidth, frameWidth, -frameWidth, 0);
2284
2285 painter->save();
2286 painter->setFont(QApplication::font("QMdiSubWindowTitleBar"));
2287 style()->drawComplexControl(QStyle::CC_TitleBar, &bar, painter, widget);
2288 painter->restore();
2289 if (setMask)
2290 painter->restore();
2291 // Draw window frame
2292 QStyleOptionFrame frameOptions;
2293 frameOptions.QStyleOption::operator=(*option);
2294 initStyleOption(&frameOptions);
2295 if (!hasBorder)
2296 painter->setClipRect(windowFrameRect.adjusted(0, +height, 0, 0), Qt::IntersectClip);
2297 frameOptions.state.setFlag(QStyle::State_HasFocus, hasFocus());
2298 bool isActive = isActiveWindow();
2299 frameOptions.state.setFlag(QStyle::State_Active, isActive);
2300
2301 frameOptions.palette.setCurrentColorGroup(isActive ? QPalette::Active : QPalette::Normal);
2302 frameOptions.rect = windowFrameRect;
2303 frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, nullptr, widget);
2304 frameOptions.midLineWidth = 1;
2305 style()->drawPrimitive(QStyle::PE_FrameWindow, &frameOptions, painter, widget);
2306
2307#ifdef Q_OS_MAC
2308 realPainter->drawPixmap(QPoint(), pm);
2309 delete painter;
2310#endif
2311}
2312
2313/*!
2314 \reimp
2315*/
2316QRectF QGraphicsWidget::boundingRect() const
2317{
2318 return windowFrameRect();
2319}
2320
2321/*!
2322 \reimp
2323*/
2324QPainterPath QGraphicsWidget::shape() const
2325{
2326 QPainterPath path;
2327 path.addRect(rect());
2328 return path;
2329}
2330
2331/*!
2332 Call this function to close the widget.
2333
2334 Returns \c true if the widget was closed; otherwise returns \c false.
2335 This slot will first send a QCloseEvent to the widget, which may or may
2336 not accept the event. If the event was ignored, nothing happens. If the
2337 event was accepted, it will hide() the widget.
2338
2339 If the widget has the Qt::WA_DeleteOnClose attribute set it will be
2340 deleted.
2341*/
2342bool QGraphicsWidget::close()
2343{
2344 QCloseEvent closeEvent;
2345 QCoreApplication::sendEvent(this, &closeEvent);
2346 if (!closeEvent.isAccepted()) {
2347 return false;
2348 }
2349 // hide
2350 if (isVisible()) {
2351 hide();
2352 }
2353 if (testAttribute(Qt::WA_DeleteOnClose)) {
2354 deleteLater();
2355 }
2356 return true;
2357}
2358
2359#if 0
2360void QGraphicsWidget::dumpFocusChain()
2361{
2362 qDebug("=========== Dumping focus chain ==============");
2363 int i = 0;
2364 QGraphicsWidget *next = this;
2365 QSet<QGraphicsWidget*> visited;
2366 do {
2367 if (!next) {
2368 qWarning("Found a focus chain that is not circular, (next == 0)");
2369 break;
2370 }
2371 qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromLatin1("focusItem:%1").arg(next->hasFocus() ? '1' : '0') << "next:"_L1 << next->d_func()->focusNext->data(0) << "prev:"_L1 << next->d_func()->focusPrev->data(0);
2372 if (visited.contains(next)) {
2373 qWarning("Already visited this node. However, I expected to dump until I found myself.");
2374 break;
2375 }
2376 visited << next;
2377 next = next->d_func()->focusNext;
2378 } while (next != this);
2379}
2380#endif
2381
2382QT_END_NAMESPACE
2383
2384#include "moc_qgraphicswidget.cpp"
QStyle * styleForWidget(const QGraphicsWidget *widget) const
void setStyleForWidget(QGraphicsWidget *widget, QStyle *style)