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

Last change on this file since 463 was 2, checked in by Dmitry A. Kuminov, 17 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