source: trunk/src/gui/graphicsview/qgraphicswidget.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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