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

Last change on this file since 135 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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