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

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

trunk: Merged in qt 4.6.2 sources.

File size: 76.1 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 if (!d->inSetGeometry) {
1048 d->inSetPos = 1;
1049 // Ensure setGeometry is called (avoid recursion when setPos is
1050 // called from within setGeometry).
1051 setGeometry(QRectF(pos(), size()));
1052 d->inSetPos = 0 ;
1053 }
1054 break;
1055 case ItemParentChange: {
1056 QGraphicsItem *parent = qVariantValue<QGraphicsItem *>(value);
1057 d->fixFocusChainBeforeReparenting((parent && parent->isWidget()) ? static_cast<QGraphicsWidget *>(parent) : 0, scene());
1058
1059 // Deliver ParentAboutToChange.
1060 QEvent event(QEvent::ParentAboutToChange);
1061 QApplication::sendEvent(this, &event);
1062 break;
1063 }
1064 case ItemParentHasChanged: {
1065 // Deliver ParentChange.
1066 QEvent event(QEvent::ParentChange);
1067 QApplication::sendEvent(this, &event);
1068 break;
1069 }
1070 case ItemCursorChange: {
1071 // Deliver CursorChange.
1072 QEvent event(QEvent::CursorChange);
1073 QApplication::sendEvent(this, &event);
1074 break;
1075 }
1076 case ItemToolTipChange: {
1077 // Deliver ToolTipChange.
1078 QEvent event(QEvent::ToolTipChange);
1079 QApplication::sendEvent(this, &event);
1080 break;
1081 }
1082 default:
1083 break;
1084 }
1085 return QGraphicsItem::itemChange(change, value);
1086}
1087
1088/*!
1089 \internal
1090
1091 This virtual function is used to notify changes to any property (both
1092 dynamic properties, and registered with Q_PROPERTY) in the
1093 widget. Depending on the property itself, the notification can be
1094 delivered before or after the value has changed.
1095
1096 \a propertyName is the name of the property (e.g., "size" or "font"), and
1097 \a value is the (proposed) new value of the property. The function returns
1098 the new value, which may be different from \a value if the notification
1099 supports adjusting the property value. The base implementation simply
1100 returns \a value for any \a propertyName.
1101
1102 QGraphicsWidget delivers notifications for the following properties:
1103
1104 \table \o propertyName \o Property
1105 \row \o layoutDirection \o QGraphicsWidget::layoutDirection
1106 \row \o size \o QGraphicsWidget::size
1107 \row \o font \o QGraphicsWidget::font
1108 \row \o palette \o QGraphicsWidget::palette
1109 \endtable
1110
1111 \sa itemChange()
1112*/
1113QVariant QGraphicsWidget::propertyChange(const QString &propertyName, const QVariant &value)
1114{
1115 Q_UNUSED(propertyName);
1116 return value;
1117}
1118
1119/*!
1120 QGraphicsWidget's implementation of sceneEvent() simply passes \a event to
1121 QGraphicsWidget::event(). You can handle all events for your widget in
1122 event() or in any of the convenience functions; you should not have to
1123 reimplement this function in a subclass of QGraphicsWidget.
1124
1125 \sa QGraphicsItem::sceneEvent()
1126*/
1127bool QGraphicsWidget::sceneEvent(QEvent *event)
1128{
1129 return QGraphicsItem::sceneEvent(event);
1130}
1131
1132/*!
1133 This event handler, for \a event, receives events for the window frame if
1134 this widget is a window. Its base implementation provides support for
1135 default window frame interaction such as moving, resizing, etc.
1136
1137 You can reimplement this handler in a subclass of QGraphicsWidget to
1138 provide your own custom window frame interaction support.
1139
1140 Returns true if \a event has been recognized and processed; otherwise,
1141 returns false.
1142
1143 \sa event()
1144*/
1145bool QGraphicsWidget::windowFrameEvent(QEvent *event)
1146{
1147 Q_D(QGraphicsWidget);
1148 switch (event->type()) {
1149 case QEvent::GraphicsSceneMousePress:
1150 d->windowFrameMousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
1151 break;
1152 case QEvent::GraphicsSceneMouseMove:
1153 d->ensureWindowData();
1154 if (d->windowData->grabbedSection != Qt::NoSection) {
1155 d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
1156 event->accept();
1157 }
1158 break;
1159 case QEvent::GraphicsSceneMouseRelease:
1160 d->windowFrameMouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
1161 break;
1162 case QEvent::GraphicsSceneHoverMove:
1163 d->windowFrameHoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
1164 break;
1165 case QEvent::GraphicsSceneHoverLeave:
1166 d->windowFrameHoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
1167 break;
1168 default:
1169 break;
1170 }
1171 return event->isAccepted();
1172}
1173
1174/*!
1175 \since 4.4
1176
1177 Returns the window frame section at position \a pos, or
1178 Qt::NoSection if there is no window frame section at this
1179 position.
1180
1181 This function is used in QGraphicsWidget's base implementation for window
1182 frame interaction.
1183
1184 You can reimplement this function if you want to customize how a window
1185 can be interactively moved or resized. For instance, if you only want to
1186 allow a window to be resized by the bottom right corner, you can
1187 reimplement this function to return Qt::NoSection for all sections except
1188 Qt::BottomRightSection.
1189
1190 \sa windowFrameEvent(), paintWindowFrame(), windowFrameGeometry()
1191*/
1192Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) const
1193{
1194 Q_D(const QGraphicsWidget);
1195
1196 const QRectF r = windowFrameRect();
1197 if (!r.contains(pos))
1198 return Qt::NoSection;
1199
1200 const qreal left = r.left();
1201 const qreal top = r.top();
1202 const qreal right = r.right();
1203 const qreal bottom = r.bottom();
1204 const qreal x = pos.x();
1205 const qreal y = pos.y();
1206
1207 const qreal cornerMargin = 20;
1208 //### Not sure of this one, it should be the same value for all edges.
1209 const qreal windowFrameWidth = d->windowFrameMargins
1210 ? d->windowFrameMargins[d->Left] : 0;
1211
1212 Qt::WindowFrameSection s = Qt::NoSection;
1213 if (x <= left + cornerMargin) {
1214 if (y <= top + windowFrameWidth || (x <= left + windowFrameWidth && y <= top + cornerMargin)) {
1215 s = Qt::TopLeftSection;
1216 } else if (y >= bottom - windowFrameWidth || (x <= left + windowFrameWidth && y >= bottom - windowFrameWidth)) {
1217 s = Qt::BottomLeftSection;
1218 } else if (x <= left + windowFrameWidth) {
1219 s = Qt::LeftSection;
1220 }
1221 } else if (x >= right - cornerMargin) {
1222 if (y <= top + windowFrameWidth || (x >= right - windowFrameWidth && y <= top + cornerMargin)) {
1223 s = Qt::TopRightSection;
1224 } else if (y >= bottom - windowFrameWidth || (x >= right - windowFrameWidth && y >= bottom - windowFrameWidth)) {
1225 s = Qt::BottomRightSection;
1226 } else if (x >= right - windowFrameWidth) {
1227 s = Qt::RightSection;
1228 }
1229 } else if (y <= top + windowFrameWidth) {
1230 s = Qt::TopSection;
1231 } else if (y >= bottom - windowFrameWidth) {
1232 s = Qt::BottomSection;
1233 }
1234 if (s == Qt::NoSection) {
1235 QRectF r1 = r;
1236 r1.setHeight(d->windowFrameMargins
1237 ? d->windowFrameMargins[d->Top] : 0);
1238 if (r1.contains(pos))
1239 s = Qt::TitleBarArea;
1240 }
1241 return s;
1242}
1243
1244/*!
1245 \reimp
1246
1247 Handles the \a event. QGraphicsWidget handles the following
1248 events:
1249
1250 \table \o Event \o Usage
1251 \row \o Polish
1252 \o Delivered to the widget some time after it has been
1253 shown.
1254 \row \o GraphicsSceneMove
1255 \o Delivered to the widget after its local position has
1256 changed.
1257 \row \o GraphicsSceneResize
1258 \o Delivered to the widget after its size has changed.
1259 \row \o Show
1260 \o Delivered to the widget before it has been shown.
1261 \row \o Hide
1262 \o Delivered to the widget after it has been hidden.
1263 \row \o PaletteChange
1264 \o Delivered to the widget after its palette has changed.
1265 \row \o FontChange
1266 \o Delivered to the widget after its font has changed.
1267 \row \o EnabledChange
1268 \o Delivered to the widget after its enabled state has
1269 changed.
1270 \row \o StyleChange
1271 \o Delivered to the widget after its style has changed.
1272 \row \o LayoutDirectionChange
1273 \o Delivered to the widget after its layout direction has
1274 changed.
1275 \row \o ContentsRectChange
1276 \o Delivered to the widget after its contents margins/
1277 contents rect has changed.
1278 \endtable
1279*/
1280bool QGraphicsWidget::event(QEvent *event)
1281{
1282 Q_D(QGraphicsWidget);
1283 // Forward the event to the layout first.
1284 if (d->layout)
1285 d->layout->widgetEvent(event);
1286
1287 // Handle the event itself.
1288 switch (event->type()) {
1289 case QEvent::GraphicsSceneMove:
1290 moveEvent(static_cast<QGraphicsSceneMoveEvent *>(event));
1291 break;
1292 case QEvent::GraphicsSceneResize:
1293 resizeEvent(static_cast<QGraphicsSceneResizeEvent *>(event));
1294 break;
1295 case QEvent::Show:
1296 showEvent(static_cast<QShowEvent *>(event));
1297 break;
1298 case QEvent::Hide:
1299 hideEvent(static_cast<QHideEvent *>(event));
1300 break;
1301 case QEvent::Polish:
1302 polishEvent();
1303 d->polished = true;
1304 if (!d->font.isCopyOf(QApplication::font()))
1305 d->updateFont(d->font);
1306 break;
1307 case QEvent::WindowActivate:
1308 case QEvent::WindowDeactivate:
1309 update();
1310 break;
1311 // Taken from QWidget::event
1312 case QEvent::ActivationChange:
1313 case QEvent::EnabledChange:
1314 case QEvent::FontChange:
1315 case QEvent::StyleChange:
1316 case QEvent::PaletteChange:
1317 case QEvent::ParentChange:
1318 case QEvent::ContentsRectChange:
1319 case QEvent::LayoutDirectionChange:
1320 changeEvent(event);
1321 break;
1322 case QEvent::Close:
1323 closeEvent((QCloseEvent *)event);
1324 break;
1325 case QEvent::GrabMouse:
1326 grabMouseEvent(event);
1327 break;
1328 case QEvent::UngrabMouse:
1329 ungrabMouseEvent(event);
1330 break;
1331 case QEvent::GrabKeyboard:
1332 grabKeyboardEvent(event);
1333 break;
1334 case QEvent::UngrabKeyboard:
1335 ungrabKeyboardEvent(event);
1336 break;
1337 case QEvent::GraphicsSceneMousePress:
1338 if (d->hasDecoration() && windowFrameEvent(event))
1339 return true;
1340 case QEvent::GraphicsSceneMouseMove:
1341 case QEvent::GraphicsSceneMouseRelease:
1342 case QEvent::GraphicsSceneMouseDoubleClick:
1343 d->ensureWindowData();
1344 if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection)
1345 return windowFrameEvent(event);
1346 break;
1347 case QEvent::GraphicsSceneHoverEnter:
1348 case QEvent::GraphicsSceneHoverMove:
1349 case QEvent::GraphicsSceneHoverLeave:
1350 if (d->hasDecoration()) {
1351 windowFrameEvent(event);
1352 // Filter out hover events if they were sent to us only because of the
1353 // decoration (special case in QGraphicsScenePrivate::dispatchHoverEvent).
1354 if (!acceptsHoverEvents())
1355 return true;
1356 }
1357 break;
1358 default:
1359 break;
1360 }
1361 return QObject::event(event);
1362}
1363
1364/*!
1365 This event handler can be reimplemented to handle state changes.
1366
1367 The state being changed in this event can be retrieved through \a event.
1368
1369 Change events include: QEvent::ActivationChange, QEvent::EnabledChange,
1370 QEvent::FontChange, QEvent::StyleChange, QEvent::PaletteChange,
1371 QEvent::ParentChange, QEvent::LayoutDirectionChange, and
1372 QEvent::ContentsRectChange.
1373*/
1374void QGraphicsWidget::changeEvent(QEvent *event)
1375{
1376 Q_D(QGraphicsWidget);
1377 switch (event->type()) {
1378 case QEvent::StyleChange:
1379 // ### Don't unset if the margins are explicitly set.
1380 unsetWindowFrameMargins();
1381 if (d->layout)
1382 d->layout->invalidate();
1383 case QEvent::FontChange:
1384 update();
1385 updateGeometry();
1386 break;
1387 case QEvent::PaletteChange:
1388 update();
1389 break;
1390 case QEvent::ParentChange:
1391 d->resolveFont(d->inheritedFontResolveMask);
1392 d->resolvePalette(d->inheritedPaletteResolveMask);
1393 break;
1394 default:
1395 break;
1396 }
1397}
1398
1399/*!
1400 This event handler, for \a event, can be reimplemented in a subclass to
1401 receive widget close events. The default implementation accepts the
1402 event.
1403
1404 \sa close(), QCloseEvent
1405*/
1406void QGraphicsWidget::closeEvent(QCloseEvent *event)
1407{
1408 event->accept();
1409}
1410
1411/*!
1412 \reimp
1413*/
1414void QGraphicsWidget::focusInEvent(QFocusEvent *event)
1415{
1416 Q_UNUSED(event);
1417 if (focusPolicy() != Qt::NoFocus)
1418 update();
1419}
1420
1421/*!
1422 Finds a new widget to give the keyboard focus to, as appropriate for Tab
1423 and Shift+Tab, and returns true if it can find a new widget; returns false
1424 otherwise. If \a next is true, this function searches forward; if \a next
1425 is false, it searches backward.
1426
1427 Sometimes, you will want to reimplement this function to provide special
1428 focus handling for your widget and its subwidgets. For example, a web
1429 browser might reimplement it to move its current active link forward or
1430 backward, and call the base implementation only when it reaches the last
1431 or first link on the page.
1432
1433 Child widgets call focusNextPrevChild() on their parent widgets, but only
1434 the window that contains the child widgets decides where to redirect
1435 focus. By reimplementing this function for an object, you gain control of
1436 focus traversal for all child widgets.
1437
1438 \sa focusPolicy()
1439*/
1440bool QGraphicsWidget::focusNextPrevChild(bool next)
1441{
1442 Q_D(QGraphicsWidget);
1443 // Let the parent's focusNextPrevChild implementation decide what to do.
1444 QGraphicsWidget *parent = 0;
1445 if (!isWindow() && (parent = parentWidget()))
1446 return parent->focusNextPrevChild(next);
1447 if (!d->scene)
1448 return false;
1449 if (d->scene->focusNextPrevChild(next))
1450 return true;
1451 if (isWindow()) {
1452 setFocus(next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
1453 if (hasFocus())
1454 return true;
1455 }
1456 return false;
1457}
1458
1459/*!
1460 \reimp
1461*/
1462void QGraphicsWidget::focusOutEvent(QFocusEvent *event)
1463{
1464 Q_UNUSED(event);
1465 if (focusPolicy() != Qt::NoFocus)
1466 update();
1467}
1468
1469/*!
1470 This event handler, for \l{QEvent::Hide}{Hide} events, is delivered after
1471 the widget has been hidden, for example, setVisible(false) has been called
1472 for the widget or one of its ancestors when the widget was previously
1473 shown.
1474
1475 You can reimplement this event handler to detect when your widget is
1476 hidden. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1477 effect.
1478
1479 \sa showEvent(), QWidget::hideEvent(), ItemVisibleChange
1480*/
1481void QGraphicsWidget::hideEvent(QHideEvent *event)
1482{
1483 ///### focusNextPrevChild(true), don't lose focus when the focus widget
1484 // is hidden.
1485 Q_UNUSED(event);
1486}
1487
1488/*!
1489 This event handler, for \l{QEvent::GraphicsSceneMove}{GraphicsSceneMove}
1490 events, is delivered after the widget has moved (e.g., its local position
1491 has changed).
1492
1493 This event is only delivered when the item is moved locally. Calling
1494 setTransform() or moving any of the item's ancestors does not affect the
1495 item's local position.
1496
1497 You can reimplement this event handler to detect when your widget has
1498 moved. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1499 effect.
1500
1501 \sa ItemPositionChange, ItemPositionHasChanged
1502*/
1503void QGraphicsWidget::moveEvent(QGraphicsSceneMoveEvent *event)
1504{
1505 // ### Last position is always == current position
1506 Q_UNUSED(event);
1507}
1508
1509/*!
1510 This event is delivered to the item by the scene at some point after it
1511 has been constructed, but before it is shown or otherwise accessed through
1512 the scene. You can use this event handler to do last-minute initializations
1513 of the widget which require the item to be fully constructed.
1514
1515 The base implementation does nothing.
1516*/
1517void QGraphicsWidget::polishEvent()
1518{
1519}
1520
1521/*!
1522 This event handler, for
1523 \l{QEvent::GraphicsSceneResize}{GraphicsSceneResize} events, is
1524 delivered after the widget has been resized (i.e., its local size has
1525 changed). \a event contains both the old and the new size.
1526
1527 This event is only delivered when the widget is resized locally; calling
1528 setTransform() on the widget or any of its ancestors or view, does not
1529 affect the widget's local size.
1530
1531 You can reimplement this event handler to detect when your widget has been
1532 resized. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1533 effect.
1534
1535 \sa geometry(), setGeometry()
1536*/
1537void QGraphicsWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
1538{
1539 Q_UNUSED(event);
1540}
1541
1542/*!
1543 This event handler, for \l{QEvent::Show}{Show} events, is delivered before
1544 the widget has been shown, for example, setVisible(true) has been called
1545 for the widget or one of its ancestors when the widget was previously
1546 hidden.
1547
1548 You can reimplement this event handler to detect when your widget is
1549 shown. Calling QEvent::accept() or QEvent::ignore() on \a event has no
1550 effect.
1551
1552 \sa hideEvent(), QWidget::showEvent(), ItemVisibleChange
1553*/
1554void QGraphicsWidget::showEvent(QShowEvent *event)
1555{
1556 Q_UNUSED(event);
1557}
1558
1559/*!
1560 \reimp
1561*/
1562void QGraphicsWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1563{
1564 Q_UNUSED(event);
1565}
1566
1567/*!
1568 \reimp
1569*/
1570void QGraphicsWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1571{
1572 Q_UNUSED(event);
1573}
1574
1575/*!
1576 This event handler, for \a event, can be reimplemented in a subclass to
1577 receive notifications for Qt::GrabMouse events.
1578
1579 \sa grabMouse(), grabKeyboard()
1580*/
1581void QGraphicsWidget::grabMouseEvent(QEvent *event)
1582{
1583 Q_UNUSED(event);
1584}
1585
1586/*!
1587 This event handler, for \a event, can be reimplemented in a subclass to
1588 receive notifications for Qt::UngrabMouse events.
1589
1590 \sa ungrabMouse(), ungrabKeyboard()
1591*/
1592void QGraphicsWidget::ungrabMouseEvent(QEvent *event)
1593{
1594 Q_UNUSED(event);
1595}
1596
1597/*!
1598 This event handler, for \a event, can be reimplemented in a subclass to
1599 receive notifications for Qt::GrabKeyboard events.
1600
1601 \sa grabKeyboard(), grabMouse()
1602*/
1603void QGraphicsWidget::grabKeyboardEvent(QEvent *event)
1604{
1605 Q_UNUSED(event);
1606}
1607
1608/*!
1609 This event handler, for \a event, can be reimplemented in a subclass to
1610 receive notifications for Qt::UngrabKeyboard events.
1611
1612 \sa ungrabKeyboard(), ungrabMouse()
1613*/
1614void QGraphicsWidget::ungrabKeyboardEvent(QEvent *event)
1615{
1616 Q_UNUSED(event);
1617}
1618
1619/*!
1620 Returns the widgets window type.
1621
1622 \sa windowFlags(), isWindow(), isPanel()
1623*/
1624Qt::WindowType QGraphicsWidget::windowType() const
1625{
1626 return Qt::WindowType(int(windowFlags()) & Qt::WindowType_Mask);
1627}
1628
1629/*!
1630 \property QGraphicsWidget::windowFlags
1631 \brief the widget's window flags
1632
1633 Window flags are a combination of a window type (e.g., Qt::Dialog) and
1634 several flags giving hints on the behavior of the window. The behavior
1635 is platform-dependent.
1636
1637 By default, this property contains no window flags.
1638
1639 Windows are panels. If you set the Qt::Window flag, the ItemIsPanel flag
1640 will be set automatically. If you clear the Qt::Window flag, the
1641 ItemIsPanel flag is also cleared. Note that the ItemIsPanel flag can be
1642 set independently of Qt::Window.
1643
1644 \sa isWindow(), isPanel()
1645*/
1646Qt::WindowFlags QGraphicsWidget::windowFlags() const
1647{
1648 Q_D(const QGraphicsWidget);
1649 return d->windowFlags;
1650}
1651void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
1652{
1653 Q_D(QGraphicsWidget);
1654 if (d->windowFlags == wFlags)
1655 return;
1656 bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
1657
1658 d->adjustWindowFlags(&wFlags);
1659 d->windowFlags = wFlags;
1660 if (!d->setWindowFrameMargins)
1661 unsetWindowFrameMargins();
1662
1663 setFlag(ItemIsPanel, d->windowFlags & Qt::Window);
1664
1665 bool isPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
1666 if (d->scene && isVisible() && wasPopup != isPopup) {
1667 // Popup state changed; update implicit mouse grab.
1668 if (!isPopup)
1669 d->scene->d_func()->removePopup(this);
1670 else
1671 d->scene->d_func()->addPopup(this);
1672 }
1673
1674 if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) {
1675 d->scene->d_func()->allItemsIgnoreHoverEvents = false;
1676 d->scene->d_func()->enableMouseTrackingOnViews();
1677 }
1678}
1679
1680/*!
1681 Returns true if this widget's window is in the active window, or if the
1682 widget does not have a window but is in an active scene (i.e., a scene
1683 that currently has focus).
1684
1685 The active window is the window that either contains a child widget that
1686 currently has input focus, or that itself has input focus.
1687
1688 \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow(), isActive()
1689*/
1690bool QGraphicsWidget::isActiveWindow() const
1691{
1692 return isActive();
1693}
1694
1695/*!
1696 \property QGraphicsWidget::windowTitle
1697 \brief This property holds the window title (caption).
1698
1699 This property is only used for windows.
1700
1701 By default, if no title has been set, this property contains an
1702 empty string.
1703*/
1704void QGraphicsWidget::setWindowTitle(const QString &title)
1705{
1706 Q_D(QGraphicsWidget);
1707 d->ensureWindowData();
1708 d->windowData->windowTitle = title;
1709}
1710QString QGraphicsWidget::windowTitle() const
1711{
1712 Q_D(const QGraphicsWidget);
1713 return d->windowData ? d->windowData->windowTitle : QString();
1714}
1715
1716/*!
1717 \property QGraphicsWidget::focusPolicy
1718 \brief the way the widget accepts keyboard focus
1719
1720 The focus policy is Qt::TabFocus if the widget accepts keyboard focus by
1721 tabbing, Qt::ClickFocus if the widget accepts focus by clicking,
1722 Qt::StrongFocus if it accepts both, and Qt::NoFocus (the default) if it
1723 does not accept focus at all.
1724
1725 You must enable keyboard focus for a widget if it processes keyboard
1726 events. This is normally done from the widget's constructor. For instance,
1727 the QLineEdit constructor calls setFocusPolicy(Qt::StrongFocus).
1728
1729 If you enable a focus policy (i.e., not Qt::NoFocus), QGraphicsWidget will
1730 automatically enable the ItemIsFocusable flag. Setting Qt::NoFocus on a
1731 widget will clear the ItemIsFocusable flag. If the widget currently has
1732 keyboard focus, the widget will automatically lose focus.
1733
1734 \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled
1735*/
1736Qt::FocusPolicy QGraphicsWidget::focusPolicy() const
1737{
1738 Q_D(const QGraphicsWidget);
1739 return d->focusPolicy;
1740}
1741void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy)
1742{
1743 Q_D(QGraphicsWidget);
1744 if (d->focusPolicy == policy)
1745 return;
1746 d->focusPolicy = policy;
1747 if (hasFocus() && policy == Qt::NoFocus)
1748 clearFocus();
1749 setFlag(ItemIsFocusable, policy != Qt::NoFocus);
1750}
1751
1752/*!
1753 If this widget, a child or descendant of this widget currently has input
1754 focus, this function will return a pointer to that widget. If
1755 no descendant widget has input focus, 0 is returned.
1756
1757 \sa QGraphicsItem::focusItem(), QWidget::focusWidget()
1758*/
1759QGraphicsWidget *QGraphicsWidget::focusWidget() const
1760{
1761 Q_D(const QGraphicsWidget);
1762 if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget)
1763 return static_cast<QGraphicsWidget *>(d->subFocusItem);
1764 return 0;
1765}
1766
1767#ifndef QT_NO_SHORTCUT
1768/*!
1769 \since 4.5
1770
1771 Adds a shortcut to Qt's shortcut system that watches for the given key \a
1772 sequence in the given \a context. If the \a context is
1773 Qt::ApplicationShortcut, the shortcut applies to the application as a
1774 whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut,
1775 or to the window itself, Qt::WindowShortcut. For widgets that are not part
1776 of a window (i.e., top-level widgets and their children),
1777 Qt::WindowShortcut shortcuts apply to the scene.
1778
1779 If the same key \a sequence has been grabbed by several widgets,
1780 when the key \a sequence occurs a QEvent::Shortcut event is sent
1781 to all the widgets to which it applies in a non-deterministic
1782 order, but with the ``ambiguous'' flag set to true.
1783
1784 \warning You should not normally need to use this function;
1785 instead create \l{QAction}s with the shortcut key sequences you
1786 require (if you also want equivalent menu options and toolbar
1787 buttons), or create \l{QShortcut}s if you just need key sequences.
1788 Both QAction and QShortcut handle all the event filtering for you,
1789 and provide signals which are triggered when the user triggers the
1790 key sequence, so are much easier to use than this low-level
1791 function.
1792
1793 \sa releaseShortcut() setShortcutEnabled() QWidget::grabShortcut()
1794*/
1795int QGraphicsWidget::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context)
1796{
1797 Q_ASSERT(qApp);
1798 if (sequence.isEmpty())
1799 return 0;
1800 // ### setAttribute(Qt::WA_GrabbedShortcut);
1801 return qApp->d_func()->shortcutMap.addShortcut(this, sequence, context);
1802}
1803
1804/*!
1805 \since 4.5
1806
1807 Removes the shortcut with the given \a id from Qt's shortcut
1808 system. The widget will no longer receive QEvent::Shortcut events
1809 for the shortcut's key sequence (unless it has other shortcuts
1810 with the same key sequence).
1811
1812 \warning You should not normally need to use this function since
1813 Qt's shortcut system removes shortcuts automatically when their
1814 parent widget is destroyed. It is best to use QAction or
1815 QShortcut to handle shortcuts, since they are easier to use than
1816 this low-level function. Note also that this is an expensive
1817 operation.
1818
1819 \sa grabShortcut() setShortcutEnabled() , QWidget::releaseShortcut()
1820*/
1821void QGraphicsWidget::releaseShortcut(int id)
1822{
1823 Q_ASSERT(qApp);
1824 if (id)
1825 qApp->d_func()->shortcutMap.removeShortcut(id, this, 0);
1826}
1827
1828/*!
1829 \since 4.5
1830
1831 If \a enabled is true, the shortcut with the given \a id is
1832 enabled; otherwise the shortcut is disabled.
1833
1834 \warning You should not normally need to use this function since
1835 Qt's shortcut system enables/disables shortcuts automatically as
1836 widgets become hidden/visible and gain or lose focus. It is best
1837 to use QAction or QShortcut to handle shortcuts, since they are
1838 easier to use than this low-level function.
1839
1840 \sa grabShortcut() releaseShortcut(), QWidget::setShortcutEnabled()
1841*/
1842void QGraphicsWidget::setShortcutEnabled(int id, bool enabled)
1843{
1844 Q_ASSERT(qApp);
1845 if (id)
1846 qApp->d_func()->shortcutMap.setShortcutEnabled(enabled, id, this, 0);
1847}
1848
1849/*!
1850 \since 4.5
1851
1852 If \a enabled is true, auto repeat of the shortcut with the
1853 given \a id is enabled; otherwise it is disabled.
1854
1855 \sa grabShortcut() releaseShortcut() QWidget::setShortcutAutoRepeat()
1856*/
1857void QGraphicsWidget::setShortcutAutoRepeat(int id, bool enabled)
1858{
1859 Q_ASSERT(qApp);
1860 if (id)
1861 qApp->d_func()->shortcutMap.setShortcutAutoRepeat(enabled, id, this, 0);
1862}
1863#endif
1864
1865#ifndef QT_NO_ACTION
1866/*!
1867 \since 4.5
1868
1869 Appends the action \a action to this widget's list of actions.
1870
1871 All QGraphicsWidgets have a list of \l{QAction}s, however they can be
1872 represented graphically in many different ways. The default use of the
1873 QAction list (as returned by actions()) is to create a context QMenu.
1874
1875 A QGraphicsWidget should only have one of each action and adding an action
1876 it already has will not cause the same action to be in the widget twice.
1877
1878 \sa removeAction(), insertAction(), actions(), QWidget::addAction()
1879*/
1880void QGraphicsWidget::addAction(QAction *action)
1881{
1882 insertAction(0, action);
1883}
1884
1885/*!
1886 \since 4.5
1887
1888 Appends the actions \a actions to this widget's list of actions.
1889
1890 \sa removeAction(), QMenu, addAction(), QWidget::addActions()
1891*/
1892void QGraphicsWidget::addActions(QList<QAction *> actions)
1893{
1894 for (int i = 0; i < actions.count(); ++i)
1895 insertAction(0, actions.at(i));
1896}
1897
1898/*!
1899 \since 4.5
1900
1901 Inserts the action \a action to this widget's list of actions,
1902 before the action \a before. It appends the action if \a before is 0 or
1903 \a before is not a valid action for this widget.
1904
1905 A QGraphicsWidget should only have one of each action.
1906
1907 \sa removeAction(), addAction(), QMenu, actions(),
1908 QWidget::insertActions()
1909*/
1910void QGraphicsWidget::insertAction(QAction *before, QAction *action)
1911{
1912 if (!action) {
1913 qWarning("QWidget::insertAction: Attempt to insert null action");
1914 return;
1915 }
1916
1917 Q_D(QGraphicsWidget);
1918 int index = d->actions.indexOf(action);
1919 if (index != -1)
1920 d->actions.removeAt(index);
1921
1922 int pos = d->actions.indexOf(before);
1923 if (pos < 0) {
1924 before = 0;
1925 pos = d->actions.size();
1926 }
1927 d->actions.insert(pos, action);
1928
1929 if (index == -1) {
1930 QActionPrivate *apriv = action->d_func();
1931 apriv->graphicsWidgets.append(this);
1932 }
1933
1934 QActionEvent e(QEvent::ActionAdded, action, before);
1935 QApplication::sendEvent(this, &e);
1936}
1937
1938/*!
1939 \since 4.5
1940
1941 Inserts the actions \a actions to this widget's list of actions,
1942 before the action \a before. It appends the action if \a before is 0 or
1943 \a before is not a valid action for this widget.
1944
1945 A QGraphicsWidget can have at most one of each action.
1946
1947 \sa removeAction(), QMenu, insertAction(), QWidget::insertActions()
1948*/
1949void QGraphicsWidget::insertActions(QAction *before, QList<QAction *> actions)
1950{
1951 for (int i = 0; i < actions.count(); ++i)
1952 insertAction(before, actions.at(i));
1953}
1954
1955/*!
1956 \since 4.5
1957
1958 Removes the action \a action from this widget's list of actions.
1959
1960 \sa insertAction(), actions(), insertAction(), QWidget::removeAction()
1961*/
1962void QGraphicsWidget::removeAction(QAction *action)
1963{
1964 if (!action)
1965 return;
1966
1967 Q_D(QGraphicsWidget);
1968
1969 QActionPrivate *apriv = action->d_func();
1970 apriv->graphicsWidgets.removeAll(this);
1971
1972 if (d->actions.removeAll(action)) {
1973 QActionEvent e(QEvent::ActionRemoved, action);
1974 QApplication::sendEvent(this, &e);
1975 }
1976}
1977
1978/*!
1979 \since 4.5
1980
1981 Returns the (possibly empty) list of this widget's actions.
1982
1983 \sa insertAction(), removeAction(), QWidget::actions(),
1984 QAction::associatedWidgets(), QAction::associatedGraphicsWidgets()
1985*/
1986QList<QAction *> QGraphicsWidget::actions() const
1987{
1988 Q_D(const QGraphicsWidget);
1989 return d->actions;
1990}
1991#endif
1992
1993/*!
1994 Moves the \a second widget around the ring of focus widgets so that
1995 keyboard focus moves from the \a first widget to the \a second widget when
1996 the Tab key is pressed.
1997
1998 Note that since the tab order of the \a second widget is changed, you
1999 should order a chain like this:
2000
2001 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicswidget.cpp 1
2002
2003 \e not like this:
2004
2005 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicswidget.cpp 2
2006
2007 If \a first is 0, this indicates that \a second should be the first widget
2008 to receive input focus should the scene gain Tab focus (i.e., the user
2009 hits Tab so that focus passes into the scene). If \a second is 0, this
2010 indicates that \a first should be the first widget to gain focus if the
2011 scene gained BackTab focus.
2012
2013 By default, tab order is defined implicitly using widget creation order.
2014
2015 \sa focusPolicy, {Keyboard Focus}
2016*/
2017void QGraphicsWidget::setTabOrder(QGraphicsWidget *first, QGraphicsWidget *second)
2018{
2019 if (!first && !second) {
2020 qWarning("QGraphicsWidget::setTabOrder(0, 0) is undefined");
2021 return;
2022 }
2023 if ((first && second) && first->scene() != second->scene()) {
2024 qWarning("QGraphicsWidget::setTabOrder: scenes %p and %p are different",
2025 first->scene(), second->scene());
2026 return;
2027 }
2028 QGraphicsScene *scene = first ? first->scene() : second->scene();
2029 if (!scene && (!first || !second)) {
2030 qWarning("QGraphicsWidget::setTabOrder: assigning tab order from/to the"
2031 " scene requires the item to be in a scene.");
2032 return;
2033 }
2034
2035 // If either first or second are 0, the scene's tabFocusFirst is updated
2036 // to point to the first item in the scene's focus chain. Then first or
2037 // second are set to point to tabFocusFirst.
2038 QGraphicsScenePrivate *sceneD = scene->d_func();
2039 if (!first) {
2040 sceneD->tabFocusFirst = second;
2041 return;
2042 }
2043 if (!second) {
2044 sceneD->tabFocusFirst = first->d_func()->focusNext;
2045 return;
2046 }
2047
2048 // Both first and second are != 0.
2049 QGraphicsWidget *firstFocusNext = first->d_func()->focusNext;
2050 if (firstFocusNext == second) {
2051 // Nothing to do.
2052 return;
2053 }
2054
2055 // Update the focus chain.
2056 QGraphicsWidget *secondFocusPrev = second->d_func()->focusPrev;
2057 QGraphicsWidget *secondFocusNext = second->d_func()->focusNext;
2058 firstFocusNext->d_func()->focusPrev = second;
2059 first->d_func()->focusNext = second;
2060 second->d_func()->focusNext = firstFocusNext;
2061 second->d_func()->focusPrev = first;
2062 secondFocusPrev->d_func()->focusNext = secondFocusNext;
2063 secondFocusNext->d_func()->focusPrev = secondFocusPrev;
2064
2065 Q_ASSERT(first->d_func()->focusNext->d_func()->focusPrev == first);
2066 Q_ASSERT(first->d_func()->focusPrev->d_func()->focusNext == first);
2067
2068 Q_ASSERT(second->d_func()->focusNext->d_func()->focusPrev == second);
2069 Q_ASSERT(second->d_func()->focusPrev->d_func()->focusNext == second);
2070
2071}
2072
2073/*!
2074 If \a on is true, this function enables \a attribute; otherwise
2075 \a attribute is disabled.
2076
2077 See the class documentation for QGraphicsWidget for a complete list of
2078 which attributes are supported, and what they are for.
2079
2080 \sa testAttribute(), QWidget::setAttribute()
2081*/
2082void QGraphicsWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
2083{
2084 Q_D(QGraphicsWidget);
2085 // ### most flags require some immediate action
2086 // ### we might want to qWarn use of unsupported attributes
2087 // ### we might want to not use Qt::WidgetAttribute, but roll our own instead
2088 d->setAttribute(attribute, on);
2089}
2090
2091/*!
2092 Returns true if \a attribute is enabled for this widget; otherwise,
2093 returns false.
2094
2095 \sa setAttribute()
2096*/
2097bool QGraphicsWidget::testAttribute(Qt::WidgetAttribute attribute) const
2098{
2099 Q_D(const QGraphicsWidget);
2100 return d->testAttribute(attribute);
2101}
2102
2103/*!
2104 \reimp
2105*/
2106int QGraphicsWidget::type() const
2107{
2108 return Type;
2109}
2110
2111/*!
2112 \reimp
2113*/
2114void QGraphicsWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2115{
2116 Q_UNUSED(painter);
2117 Q_UNUSED(option);
2118 Q_UNUSED(widget);
2119}
2120
2121/*!
2122 This virtual function is called by QGraphicsScene to draw the window frame
2123 for windows using \a painter, \a option, and \a widget, in local
2124 coordinates. The base implementation uses the current style to render the
2125 frame and title bar.
2126
2127 You can reimplement this function in a subclass of QGraphicsWidget to
2128 provide custom rendering of the widget's window frame.
2129
2130 \sa QGraphicsItem::paint()
2131*/
2132void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
2133 QWidget *widget)
2134{
2135 const bool fillBackground = !testAttribute(Qt::WA_OpaquePaintEvent)
2136 && !testAttribute(Qt::WA_NoSystemBackground);
2137 QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(this);
2138 const bool embeddedWidgetFillsOwnBackground = proxy && proxy->widget();
2139
2140 if (rect().contains(option->exposedRect)) {
2141 if (fillBackground && !embeddedWidgetFillsOwnBackground)
2142 painter->fillRect(option->exposedRect, palette().window());
2143 return;
2144 }
2145
2146 Q_D(QGraphicsWidget);
2147
2148 QRect windowFrameRect = QRect(QPoint(), windowFrameGeometry().size().toSize());
2149 QStyleOptionTitleBar bar;
2150 bar.QStyleOption::operator=(*option);
2151 d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state
2152 d->ensureWindowData();
2153 if (d->windowData->buttonMouseOver)
2154 bar.state |= QStyle::State_MouseOver;
2155 else
2156 bar.state &= ~QStyle::State_MouseOver;
2157 if (d->windowData->buttonSunken)
2158 bar.state |= QStyle::State_Sunken;
2159 else
2160 bar.state &= ~QStyle::State_Sunken;
2161
2162 bar.rect = windowFrameRect;
2163
2164 // translate painter to make the style happy
2165 const QPointF styleOrigin = this->windowFrameRect().topLeft();
2166 painter->translate(styleOrigin);
2167
2168#ifdef Q_WS_MAC
2169 const QSize pixmapSize = windowFrameRect.size();
2170 if (pixmapSize.width() <= 0 || pixmapSize.height() <= 0)
2171 return;
2172 QPainter *realPainter = painter;
2173 QPixmap pm(pixmapSize);
2174 painter = new QPainter(&pm);
2175#endif
2176
2177 // Fill background
2178 QStyleHintReturnMask mask;
2179 bool setMask = style()->styleHint(QStyle::SH_WindowFrame_Mask, &bar, widget, &mask) && !mask.region.isEmpty();
2180 bool hasBorder = !style()->styleHint(QStyle::SH_TitleBar_NoBorder, &bar, widget);
2181 int frameWidth = style()->pixelMetric(QStyle::PM_MDIFrameWidth, &bar, widget);
2182 if (setMask) {
2183 painter->save();
2184 painter->setClipRegion(mask.region, Qt::IntersectClip);
2185 }
2186 if (fillBackground) {
2187 if (embeddedWidgetFillsOwnBackground) {
2188 // Don't fill the background twice.
2189 QPainterPath windowFrameBackground;
2190 windowFrameBackground.addRect(windowFrameRect);
2191 // Adjust with 0.5 to avoid border artifacts between
2192 // widget background and frame background.
2193 windowFrameBackground.addRect(rect().translated(-styleOrigin).adjusted(0.5, 0.5, -0.5, -0.5));
2194 painter->fillPath(windowFrameBackground, palette().window());
2195 } else {
2196 painter->fillRect(windowFrameRect, palette().window());
2197 }
2198 }
2199 painter->setRenderHint(QPainter::NonCosmeticDefaultPen);
2200
2201 // Draw title
2202 int height = (int)d->titleBarHeight(bar);
2203 bar.rect.setHeight(height);
2204 if (hasBorder) // Frame is painted by PE_FrameWindow
2205 bar.rect.adjust(frameWidth, frameWidth, -frameWidth, 0);
2206
2207 painter->save();
2208 painter->setFont(QApplication::font("QWorkspaceTitleBar"));
2209 style()->drawComplexControl(QStyle::CC_TitleBar, &bar, painter, widget);
2210 painter->restore();
2211 if (setMask)
2212 painter->restore();
2213 // Draw window frame
2214 QStyleOptionFrame frameOptions;
2215 frameOptions.QStyleOption::operator=(*option);
2216 initStyleOption(&frameOptions);
2217 if (!hasBorder)
2218 painter->setClipRect(windowFrameRect.adjusted(0, +height, 0, 0), Qt::IntersectClip);
2219 if (hasFocus()) {
2220 frameOptions.state |= QStyle::State_HasFocus;
2221 } else {
2222 frameOptions.state &= ~QStyle::State_HasFocus;
2223 }
2224 bool isActive = isActiveWindow();
2225 if (isActive) {
2226 frameOptions.state |= QStyle::State_Active;
2227 } else {
2228 frameOptions.state &= ~QStyle::State_Active;
2229 }
2230
2231 frameOptions.palette.setCurrentColorGroup(isActive ? QPalette::Active : QPalette::Normal);
2232 frameOptions.rect = windowFrameRect;
2233 frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, widget);
2234 frameOptions.midLineWidth = 1;
2235 style()->drawPrimitive(QStyle::PE_FrameWindow, &frameOptions, painter, widget);
2236
2237#ifdef Q_WS_MAC
2238 realPainter->drawPixmap(QPoint(), pm);
2239 delete painter;
2240#endif
2241}
2242
2243/*!
2244 \reimp
2245*/
2246QRectF QGraphicsWidget::boundingRect() const
2247{
2248 return windowFrameRect();
2249}
2250
2251/*!
2252 \reimp
2253*/
2254QPainterPath QGraphicsWidget::shape() const
2255{
2256 QPainterPath path;
2257 path.addRect(rect());
2258 return path;
2259}
2260
2261/*!
2262 Call this function to close the widget.
2263
2264 Returns true if the widget was closed; otherwise returns false.
2265 This slot will first send a QCloseEvent to the widget, which may or may
2266 not accept the event. If the event was ignored, nothing happens. If the
2267 event was accepted, it will hide() the widget.
2268
2269 If the widget has the Qt::WA_DeleteOnClose attribute set it will be
2270 deleted.
2271*/
2272bool QGraphicsWidget::close()
2273{
2274 QCloseEvent closeEvent;
2275 QApplication::sendEvent(this, &closeEvent);
2276 if (!closeEvent.isAccepted()) {
2277 return false;
2278 }
2279 // hide
2280 if (isVisible()) {
2281 hide();
2282 }
2283 if (testAttribute(Qt::WA_DeleteOnClose)) {
2284 deleteLater();
2285 }
2286 return true;
2287}
2288
2289#ifdef Q_NO_USING_KEYWORD
2290/*!
2291 \fn const QObjectList &QGraphicsWidget::children() const
2292 \internal
2293
2294 This function returns the same value as QObject::children(). It's
2295 provided to differentiate between the obsolete member
2296 QGraphicsItem::children() and QObject::children(). QGraphicsItem now
2297 provides childItems() instead.
2298*/
2299#endif
2300
2301#if 0
2302void QGraphicsWidget::dumpFocusChain()
2303{
2304 qDebug() << "=========== Dumping focus chain ==============";
2305 int i = 0;
2306 QGraphicsWidget *next = this;
2307 QSet<QGraphicsWidget*> visited;
2308 do {
2309 if (!next) {
2310 qWarning("Found a focus chain that is not circular, (next == 0)");
2311 break;
2312 }
2313 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);
2314 if (visited.contains(next)) {
2315 qWarning("Already visited this node. However, I expected to dump until I found myself.");
2316 break;
2317 }
2318 visited << next;
2319 next = next->d_func()->focusNext;
2320 } while (next != this);
2321}
2322#endif
2323
2324QT_END_NAMESPACE
2325
2326#endif //QT_NO_GRAPHICSVIEW
Note: See TracBrowser for help on using the repository browser.