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

Last change on this file since 1126 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

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