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