|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #ifndef QGRAPHICSITEM_P_H |
|
43 #define QGRAPHICSITEM_P_H |
|
44 |
|
45 // |
|
46 // W A R N I N G |
|
47 // ------------- |
|
48 // |
|
49 // This file is not part of the Qt API. It exists for the convenience |
|
50 // of other Qt classes. This header file may change from version to |
|
51 // version without notice, or even be removed. |
|
52 // |
|
53 // We mean it. |
|
54 // |
|
55 |
|
56 #include "qgraphicsitem.h" |
|
57 #include "qset.h" |
|
58 #include "qpixmapcache.h" |
|
59 #include <private/qgraphicsview_p.h> |
|
60 #include "qgraphicstransform.h" |
|
61 #include <private/qgraphicstransform_p.h> |
|
62 |
|
63 #include <private/qgraphicseffect_p.h> |
|
64 |
|
65 #include <QtCore/qpoint.h> |
|
66 |
|
67 #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW |
|
68 |
|
69 QT_BEGIN_NAMESPACE |
|
70 |
|
71 class QGraphicsItemPrivate; |
|
72 |
|
73 class QGraphicsItemCache |
|
74 { |
|
75 public: |
|
76 QGraphicsItemCache() : allExposed(false) { } |
|
77 |
|
78 // ItemCoordinateCache only |
|
79 QRect boundingRect; |
|
80 QSize fixedSize; |
|
81 QPixmapCache::Key key; |
|
82 |
|
83 // DeviceCoordinateCache only |
|
84 struct DeviceData { |
|
85 DeviceData() {} |
|
86 QTransform lastTransform; |
|
87 QPoint cacheIndent; |
|
88 QPixmapCache::Key key; |
|
89 }; |
|
90 QMap<QPaintDevice *, DeviceData> deviceData; |
|
91 |
|
92 // List of logical exposed rects |
|
93 QVector<QRectF> exposed; |
|
94 bool allExposed; |
|
95 |
|
96 // Empty cache |
|
97 void purge(); |
|
98 }; |
|
99 |
|
100 class Q_GUI_EXPORT QGraphicsItemPrivate |
|
101 { |
|
102 Q_DECLARE_PUBLIC(QGraphicsItem) |
|
103 public: |
|
104 enum Extra { |
|
105 ExtraToolTip, |
|
106 ExtraCursor, |
|
107 ExtraCacheData, |
|
108 ExtraMaxDeviceCoordCacheSize, |
|
109 ExtraBoundingRegionGranularity |
|
110 }; |
|
111 |
|
112 enum AncestorFlag { |
|
113 NoFlag = 0, |
|
114 AncestorHandlesChildEvents = 0x1, |
|
115 AncestorClipsChildren = 0x2, |
|
116 AncestorIgnoresTransformations = 0x4, |
|
117 AncestorFiltersChildEvents = 0x8 |
|
118 }; |
|
119 |
|
120 inline QGraphicsItemPrivate() |
|
121 : z(0), |
|
122 opacity(1.), |
|
123 scene(0), |
|
124 parent(0), |
|
125 transformData(0), |
|
126 graphicsEffect(0), |
|
127 index(-1), |
|
128 siblingIndex(-1), |
|
129 itemDepth(-1), |
|
130 focusProxy(0), |
|
131 subFocusItem(0), |
|
132 focusScopeItem(0), |
|
133 imHints(Qt::ImhNone), |
|
134 panelModality(QGraphicsItem::NonModal), |
|
135 acceptedMouseButtons(0x1f), |
|
136 visible(1), |
|
137 explicitlyHidden(0), |
|
138 enabled(1), |
|
139 explicitlyDisabled(0), |
|
140 selected(0), |
|
141 acceptsHover(0), |
|
142 acceptDrops(0), |
|
143 isMemberOfGroup(0), |
|
144 handlesChildEvents(0), |
|
145 itemDiscovered(0), |
|
146 hasCursor(0), |
|
147 ancestorFlags(0), |
|
148 cacheMode(0), |
|
149 hasBoundingRegionGranularity(0), |
|
150 isWidget(0), |
|
151 dirty(0), |
|
152 dirtyChildren(0), |
|
153 localCollisionHack(0), |
|
154 dirtyClipPath(1), |
|
155 emptyClipPath(0), |
|
156 inSetPosHelper(0), |
|
157 needSortChildren(1), // ### can be 0 by default? |
|
158 allChildrenDirty(0), |
|
159 fullUpdatePending(0), |
|
160 flags(0), |
|
161 dirtyChildrenBoundingRect(1), |
|
162 paintedViewBoundingRectsNeedRepaint(0), |
|
163 dirtySceneTransform(1), |
|
164 geometryChanged(1), |
|
165 inDestructor(0), |
|
166 isObject(0), |
|
167 ignoreVisible(0), |
|
168 ignoreOpacity(0), |
|
169 acceptTouchEvents(0), |
|
170 acceptedTouchBeginEvent(0), |
|
171 filtersDescendantEvents(0), |
|
172 sceneTransformTranslateOnly(0), |
|
173 notifyBoundingRectChanged(0), |
|
174 notifyInvalidated(0), |
|
175 mouseSetsFocus(1), |
|
176 explicitActivate(0), |
|
177 wantsActive(0), |
|
178 holesInSiblingIndex(0), |
|
179 sequentialOrdering(1), |
|
180 updateDueToGraphicsEffect(0), |
|
181 globalStackingOrder(-1), |
|
182 q_ptr(0) |
|
183 { |
|
184 } |
|
185 |
|
186 inline virtual ~QGraphicsItemPrivate() |
|
187 { } |
|
188 |
|
189 static const QGraphicsItemPrivate *get(const QGraphicsItem *item) |
|
190 { |
|
191 return item->d_ptr.data(); |
|
192 } |
|
193 static QGraphicsItemPrivate *get(QGraphicsItem *item) |
|
194 { |
|
195 return item->d_ptr.data(); |
|
196 } |
|
197 |
|
198 void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, |
|
199 AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); |
|
200 void setIsMemberOfGroup(bool enabled); |
|
201 void remapItemPos(QEvent *event, QGraphicsItem *item); |
|
202 QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; |
|
203 inline bool itemIsUntransformable() const |
|
204 { |
|
205 return (flags & QGraphicsItem::ItemIgnoresTransformations) |
|
206 || (ancestorFlags & AncestorIgnoresTransformations); |
|
207 } |
|
208 |
|
209 void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; |
|
210 void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; |
|
211 virtual void updateSceneTransformFromParent(); |
|
212 |
|
213 // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. |
|
214 virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; |
|
215 static bool movableAncestorIsSelected(const QGraphicsItem *item); |
|
216 |
|
217 virtual void setPosHelper(const QPointF &pos); |
|
218 void setTransformHelper(const QTransform &transform); |
|
219 void appendGraphicsTransform(QGraphicsTransform *t); |
|
220 void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); |
|
221 void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); |
|
222 bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, |
|
223 bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; |
|
224 int depth() const; |
|
225 void invalidateGraphicsEffectsRecursively(); |
|
226 void invalidateDepthRecursively(); |
|
227 void resolveDepth(); |
|
228 void addChild(QGraphicsItem *child); |
|
229 void removeChild(QGraphicsItem *child); |
|
230 void setParentItemHelper(QGraphicsItem *parent); |
|
231 void childrenBoundingRectHelper(QTransform *x, QRectF *rect); |
|
232 void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, |
|
233 const QRegion &exposedRegion, bool allItems = false) const; |
|
234 QRectF effectiveBoundingRect() const; |
|
235 QRectF sceneEffectiveBoundingRect() const; |
|
236 |
|
237 virtual void resolveFont(uint inheritedMask) |
|
238 { |
|
239 for (int i = 0; i < children.size(); ++i) |
|
240 children.at(i)->d_ptr->resolveFont(inheritedMask); |
|
241 } |
|
242 |
|
243 virtual void resolvePalette(uint inheritedMask) |
|
244 { |
|
245 for (int i = 0; i < children.size(); ++i) |
|
246 children.at(i)->d_ptr->resolveFont(inheritedMask); |
|
247 } |
|
248 |
|
249 virtual bool isProxyWidget() const; |
|
250 |
|
251 inline QVariant extra(Extra type) const |
|
252 { |
|
253 for (int i = 0; i < extras.size(); ++i) { |
|
254 const ExtraStruct &extra = extras.at(i); |
|
255 if (extra.type == type) |
|
256 return extra.value; |
|
257 } |
|
258 return QVariant(); |
|
259 } |
|
260 |
|
261 inline void setExtra(Extra type, const QVariant &value) |
|
262 { |
|
263 int index = -1; |
|
264 for (int i = 0; i < extras.size(); ++i) { |
|
265 if (extras.at(i).type == type) { |
|
266 index = i; |
|
267 break; |
|
268 } |
|
269 } |
|
270 |
|
271 if (index == -1) { |
|
272 extras << ExtraStruct(type, value); |
|
273 } else { |
|
274 extras[index].value = value; |
|
275 } |
|
276 } |
|
277 |
|
278 inline void unsetExtra(Extra type) |
|
279 { |
|
280 for (int i = 0; i < extras.size(); ++i) { |
|
281 if (extras.at(i).type == type) { |
|
282 extras.removeAt(i); |
|
283 return; |
|
284 } |
|
285 } |
|
286 } |
|
287 |
|
288 struct ExtraStruct { |
|
289 ExtraStruct(Extra type, QVariant value) |
|
290 : type(type), value(value) |
|
291 { } |
|
292 |
|
293 Extra type; |
|
294 QVariant value; |
|
295 |
|
296 bool operator<(Extra extra) const |
|
297 { return type < extra; } |
|
298 }; |
|
299 |
|
300 QList<ExtraStruct> extras; |
|
301 |
|
302 QGraphicsItemCache *maybeExtraItemCache() const; |
|
303 QGraphicsItemCache *extraItemCache() const; |
|
304 void removeExtraItemCache(); |
|
305 |
|
306 inline void setCachedClipPath(const QPainterPath &path) |
|
307 { |
|
308 cachedClipPath = path; |
|
309 dirtyClipPath = 0; |
|
310 emptyClipPath = 0; |
|
311 } |
|
312 |
|
313 inline void setEmptyCachedClipPath() |
|
314 { |
|
315 emptyClipPath = 1; |
|
316 dirtyClipPath = 0; |
|
317 } |
|
318 |
|
319 void setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect = QRectF()); |
|
320 |
|
321 inline void invalidateCachedClipPath() |
|
322 { /*static int count = 0 ;qWarning("%i", ++count);*/ dirtyClipPath = 1; emptyClipPath = 0; } |
|
323 |
|
324 void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); |
|
325 void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); |
|
326 void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem); |
|
327 inline void ensureSceneTransform() |
|
328 { |
|
329 QGraphicsItem *that = q_func(); |
|
330 ensureSceneTransformRecursive(&that); |
|
331 } |
|
332 |
|
333 inline bool hasTranslateOnlySceneTransform() |
|
334 { |
|
335 ensureSceneTransform(); |
|
336 return sceneTransformTranslateOnly; |
|
337 } |
|
338 |
|
339 inline void invalidateChildrenSceneTransform() |
|
340 { |
|
341 for (int i = 0; i < children.size(); ++i) |
|
342 children.at(i)->d_ptr->dirtySceneTransform = 1; |
|
343 } |
|
344 |
|
345 inline qreal calcEffectiveOpacity() const |
|
346 { |
|
347 qreal o = opacity; |
|
348 QGraphicsItem *p = parent; |
|
349 int myFlags = flags; |
|
350 while (p) { |
|
351 int parentFlags = p->d_ptr->flags; |
|
352 |
|
353 // If I have a parent, and I don't ignore my parent's opacity, and my |
|
354 // parent propagates to me, then combine my local opacity with my parent's |
|
355 // effective opacity into my effective opacity. |
|
356 if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity) |
|
357 || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { |
|
358 break; |
|
359 } |
|
360 |
|
361 o *= p->d_ptr->opacity; |
|
362 p = p->d_ptr->parent; |
|
363 myFlags = parentFlags; |
|
364 } |
|
365 return o; |
|
366 } |
|
367 |
|
368 inline bool isFullyTransparent() const |
|
369 { |
|
370 if (opacity < 0.001) |
|
371 return true; |
|
372 if (!parent) |
|
373 return false; |
|
374 |
|
375 return calcEffectiveOpacity() < 0.001; |
|
376 } |
|
377 |
|
378 inline qreal effectiveOpacity() const { |
|
379 if (!parent || !opacity) |
|
380 return opacity; |
|
381 |
|
382 return calcEffectiveOpacity(); |
|
383 } |
|
384 |
|
385 inline qreal combineOpacityFromParent(qreal parentOpacity) const |
|
386 { |
|
387 if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) |
|
388 && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { |
|
389 return parentOpacity * opacity; |
|
390 } |
|
391 return opacity; |
|
392 } |
|
393 |
|
394 inline bool childrenCombineOpacity() const |
|
395 { |
|
396 if (!children.size()) |
|
397 return true; |
|
398 if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) |
|
399 return false; |
|
400 |
|
401 for (int i = 0; i < children.size(); ++i) { |
|
402 if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity) |
|
403 return false; |
|
404 } |
|
405 return true; |
|
406 } |
|
407 |
|
408 inline bool isClippedAway() const |
|
409 { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } |
|
410 |
|
411 inline bool childrenClippedToShape() const |
|
412 { return (flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty(); } |
|
413 |
|
414 inline bool isInvisible() const |
|
415 { |
|
416 return !visible |
|
417 || (childrenClippedToShape() && isClippedAway()) |
|
418 || (childrenCombineOpacity() && isFullyTransparent()); |
|
419 } |
|
420 |
|
421 void setFocusHelper(Qt::FocusReason focusReason, bool climb); |
|
422 void setSubFocus(QGraphicsItem *rootItem = 0); |
|
423 void clearSubFocus(QGraphicsItem *rootItem = 0); |
|
424 void resetFocusProxy(); |
|
425 virtual void subFocusItemChange(); |
|
426 |
|
427 inline QTransform transformToParent() const; |
|
428 inline void ensureSortedChildren(); |
|
429 static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b); |
|
430 void ensureSequentialSiblingIndex(); |
|
431 |
|
432 QPainterPath cachedClipPath; |
|
433 QRectF childrenBoundingRect; |
|
434 QRectF needsRepaint; |
|
435 QMap<QWidget *, QRect> paintedViewBoundingRects; |
|
436 QPointF pos; |
|
437 qreal z; |
|
438 qreal opacity; |
|
439 QGraphicsScene *scene; |
|
440 QGraphicsItem *parent; |
|
441 QList<QGraphicsItem *> children; |
|
442 struct TransformData; |
|
443 TransformData *transformData; |
|
444 QGraphicsEffect *graphicsEffect; |
|
445 QTransform sceneTransform; |
|
446 int index; |
|
447 int siblingIndex; |
|
448 int itemDepth; // Lazily calculated when calling depth(). |
|
449 QGraphicsItem *focusProxy; |
|
450 QList<QGraphicsItem **> focusProxyRefs; |
|
451 QGraphicsItem *subFocusItem; |
|
452 QGraphicsItem *focusScopeItem; |
|
453 Qt::InputMethodHints imHints; |
|
454 QGraphicsItem::PanelModality panelModality; |
|
455 QMap<Qt::GestureType, Qt::GestureContext> gestureContext; |
|
456 |
|
457 // Packed 32 bits |
|
458 quint32 acceptedMouseButtons : 5; |
|
459 quint32 visible : 1; |
|
460 quint32 explicitlyHidden : 1; |
|
461 quint32 enabled : 1; |
|
462 quint32 explicitlyDisabled : 1; |
|
463 quint32 selected : 1; |
|
464 quint32 acceptsHover : 1; |
|
465 quint32 acceptDrops : 1; |
|
466 quint32 isMemberOfGroup : 1; |
|
467 quint32 handlesChildEvents : 1; |
|
468 quint32 itemDiscovered : 1; |
|
469 quint32 hasCursor : 1; |
|
470 quint32 ancestorFlags : 4; |
|
471 quint32 cacheMode : 2; |
|
472 quint32 hasBoundingRegionGranularity : 1; |
|
473 quint32 isWidget : 1; |
|
474 quint32 dirty : 1; |
|
475 quint32 dirtyChildren : 1; |
|
476 quint32 localCollisionHack : 1; |
|
477 quint32 dirtyClipPath : 1; |
|
478 quint32 emptyClipPath : 1; |
|
479 quint32 inSetPosHelper : 1; |
|
480 quint32 needSortChildren : 1; |
|
481 quint32 allChildrenDirty : 1; |
|
482 |
|
483 // Packed 32 bits |
|
484 quint32 fullUpdatePending : 1; |
|
485 quint32 flags : 16; |
|
486 quint32 dirtyChildrenBoundingRect : 1; |
|
487 quint32 paintedViewBoundingRectsNeedRepaint : 1; |
|
488 quint32 dirtySceneTransform : 1; |
|
489 quint32 geometryChanged : 1; |
|
490 quint32 inDestructor : 1; |
|
491 quint32 isObject : 1; |
|
492 quint32 ignoreVisible : 1; |
|
493 quint32 ignoreOpacity : 1; |
|
494 quint32 acceptTouchEvents : 1; |
|
495 quint32 acceptedTouchBeginEvent : 1; |
|
496 quint32 filtersDescendantEvents : 1; |
|
497 quint32 sceneTransformTranslateOnly : 1; |
|
498 quint32 notifyBoundingRectChanged : 1; |
|
499 quint32 notifyInvalidated : 1; |
|
500 quint32 mouseSetsFocus : 1; |
|
501 |
|
502 // New 32 bits |
|
503 quint32 explicitActivate : 1; |
|
504 quint32 wantsActive : 1; |
|
505 quint32 holesInSiblingIndex : 1; |
|
506 quint32 sequentialOrdering : 1; |
|
507 quint32 updateDueToGraphicsEffect : 1; |
|
508 |
|
509 // Optional stacking order |
|
510 int globalStackingOrder; |
|
511 QGraphicsItem *q_ptr; |
|
512 }; |
|
513 |
|
514 struct QGraphicsItemPrivate::TransformData |
|
515 { |
|
516 QTransform transform; |
|
517 qreal scale; |
|
518 qreal rotation; |
|
519 qreal xOrigin; |
|
520 qreal yOrigin; |
|
521 QList<QGraphicsTransform *> graphicsTransforms; |
|
522 bool onlyTransform; |
|
523 |
|
524 TransformData() : |
|
525 scale(1.0), rotation(0.0), |
|
526 xOrigin(0.0), yOrigin(0.0), |
|
527 onlyTransform(true) |
|
528 { } |
|
529 |
|
530 QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const |
|
531 { |
|
532 if (onlyTransform) { |
|
533 if (!postmultiplyTransform || postmultiplyTransform->isIdentity()) |
|
534 return transform; |
|
535 if (transform.isIdentity()) |
|
536 return *postmultiplyTransform; |
|
537 return transform * *postmultiplyTransform; |
|
538 } |
|
539 |
|
540 QTransform x(transform); |
|
541 if (!graphicsTransforms.isEmpty()) { |
|
542 QMatrix4x4 m; |
|
543 for (int i = 0; i < graphicsTransforms.size(); ++i) |
|
544 graphicsTransforms.at(i)->applyTo(&m); |
|
545 x *= m.toTransform(0); |
|
546 } |
|
547 x.translate(xOrigin, yOrigin); |
|
548 x.rotate(rotation); |
|
549 x.scale(scale, scale); |
|
550 x.translate(-xOrigin, -yOrigin); |
|
551 if (postmultiplyTransform) |
|
552 x *= *postmultiplyTransform; |
|
553 return x; |
|
554 } |
|
555 }; |
|
556 |
|
557 struct QGraphicsItemPaintInfo |
|
558 { |
|
559 inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2, |
|
560 const QTransform *const xform3, |
|
561 QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, |
|
562 QPainter *p, qreal o, bool b1, bool b2) |
|
563 : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w), |
|
564 option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) |
|
565 {} |
|
566 |
|
567 const QTransform *viewTransform; |
|
568 const QTransform *transformPtr; |
|
569 const QTransform *effectTransform; |
|
570 QRegion *exposedRegion; |
|
571 QWidget *widget; |
|
572 QStyleOptionGraphicsItem *option; |
|
573 QPainter *painter; |
|
574 qreal opacity; |
|
575 quint32 wasDirtySceneTransform : 1; |
|
576 quint32 drawItem : 1; |
|
577 }; |
|
578 |
|
579 class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate |
|
580 { |
|
581 public: |
|
582 QGraphicsItemEffectSourcePrivate(QGraphicsItem *i) |
|
583 : QGraphicsEffectSourcePrivate(), item(i), info(0) |
|
584 {} |
|
585 |
|
586 inline void detach() |
|
587 { item->setGraphicsEffect(0); } |
|
588 |
|
589 inline const QGraphicsItem *graphicsItem() const |
|
590 { return item; } |
|
591 |
|
592 inline const QWidget *widget() const |
|
593 { return 0; } |
|
594 |
|
595 inline void update() { |
|
596 item->d_ptr->updateDueToGraphicsEffect = true; |
|
597 item->update(); |
|
598 item->d_ptr->updateDueToGraphicsEffect = false; |
|
599 } |
|
600 |
|
601 inline void effectBoundingRectChanged() |
|
602 { item->prepareGeometryChange(); } |
|
603 |
|
604 inline bool isPixmap() const |
|
605 { |
|
606 return (item->type() == QGraphicsPixmapItem::Type); |
|
607 //|| (item->d_ptr->isObject && qobject_cast<QFxImage *>(q_func())); |
|
608 } |
|
609 |
|
610 inline const QStyleOption *styleOption() const |
|
611 { return info ? info->option : 0; } |
|
612 |
|
613 inline QRect deviceRect() const |
|
614 { |
|
615 if (!info || !info->widget) { |
|
616 qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context"); |
|
617 return QRect(); |
|
618 } |
|
619 return info->widget->rect(); |
|
620 } |
|
621 |
|
622 QRectF boundingRect(Qt::CoordinateSystem system) const; |
|
623 void draw(QPainter *); |
|
624 QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; |
|
625 |
|
626 QGraphicsItem *item; |
|
627 QGraphicsItemPaintInfo *info; |
|
628 QTransform lastEffectTransform; |
|
629 }; |
|
630 |
|
631 |
|
632 /*! |
|
633 Returns true if \a item1 is on top of \a item2. |
|
634 The items dont need to be siblings. |
|
635 |
|
636 \internal |
|
637 */ |
|
638 inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) |
|
639 { |
|
640 // Siblings? Just check their z-values. |
|
641 const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); |
|
642 const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); |
|
643 if (d1->parent == d2->parent) |
|
644 return qt_closestLeaf(item1, item2); |
|
645 |
|
646 // Find common ancestor, and each item's ancestor closest to the common |
|
647 // ancestor. |
|
648 int item1Depth = d1->depth(); |
|
649 int item2Depth = d2->depth(); |
|
650 const QGraphicsItem *p = item1; |
|
651 const QGraphicsItem *t1 = item1; |
|
652 while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { |
|
653 if (p == item2) { |
|
654 // item2 is one of item1's ancestors; item1 is on top |
|
655 return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); |
|
656 } |
|
657 t1 = p; |
|
658 --item1Depth; |
|
659 } |
|
660 p = item2; |
|
661 const QGraphicsItem *t2 = item2; |
|
662 while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { |
|
663 if (p == item1) { |
|
664 // item1 is one of item2's ancestors; item1 is not on top |
|
665 return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); |
|
666 } |
|
667 t2 = p; |
|
668 --item2Depth; |
|
669 } |
|
670 |
|
671 // item1Ancestor is now at the same level as item2Ancestor, but not the same. |
|
672 const QGraphicsItem *p1 = t1; |
|
673 const QGraphicsItem *p2 = t2; |
|
674 while (t1 && t1 != t2) { |
|
675 p1 = t1; |
|
676 p2 = t2; |
|
677 t1 = t1->d_ptr->parent; |
|
678 t2 = t2->d_ptr->parent; |
|
679 } |
|
680 |
|
681 // in case we have a common ancestor, we compare the immediate children in the ancestor's path. |
|
682 // otherwise we compare the respective items' topLevelItems directly. |
|
683 return qt_closestLeaf(p1, p2); |
|
684 } |
|
685 |
|
686 /*! |
|
687 Returns true if \a item2 is on top of \a item1. |
|
688 The items dont need to be siblings. |
|
689 |
|
690 \internal |
|
691 */ |
|
692 inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2) |
|
693 { |
|
694 return qt_closestItemFirst(item2, item1); |
|
695 } |
|
696 |
|
697 /*! |
|
698 \internal |
|
699 */ |
|
700 inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) |
|
701 { |
|
702 // Return true if sibling item1 is on top of item2. |
|
703 const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); |
|
704 const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); |
|
705 bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; |
|
706 bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; |
|
707 if (f1 != f2) |
|
708 return f2; |
|
709 if (d1->z != d2->z) |
|
710 return d1->z > d2->z; |
|
711 return d1->siblingIndex > d2->siblingIndex; |
|
712 } |
|
713 |
|
714 /*! |
|
715 \internal |
|
716 */ |
|
717 inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) |
|
718 { return qt_closestLeaf(item2, item1); } |
|
719 |
|
720 /* |
|
721 return the full transform of the item to the parent. This include the position and all the transform data |
|
722 */ |
|
723 inline QTransform QGraphicsItemPrivate::transformToParent() const |
|
724 { |
|
725 QTransform matrix; |
|
726 combineTransformToParent(&matrix); |
|
727 return matrix; |
|
728 } |
|
729 |
|
730 /*! |
|
731 \internal |
|
732 */ |
|
733 inline void QGraphicsItemPrivate::ensureSortedChildren() |
|
734 { |
|
735 if (needSortChildren) { |
|
736 qSort(children.begin(), children.end(), qt_notclosestLeaf); |
|
737 needSortChildren = 0; |
|
738 sequentialOrdering = 1; |
|
739 for (int i = 0; i < children.size(); ++i) { |
|
740 if (children[i]->d_ptr->siblingIndex != i) { |
|
741 sequentialOrdering = 0; |
|
742 break; |
|
743 } |
|
744 } |
|
745 } |
|
746 } |
|
747 |
|
748 /*! |
|
749 \internal |
|
750 */ |
|
751 inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b) |
|
752 { |
|
753 return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex; |
|
754 } |
|
755 |
|
756 QT_END_NAMESPACE |
|
757 |
|
758 #endif // QT_NO_GRAPHICSVIEW |
|
759 |
|
760 #endif |