1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QGRAPHICSSCENE_P_H
41#define QGRAPHICSSCENE_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists for the convenience
48// of other Qt classes. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtWidgets/private/qtwidgetsglobal_p.h>
55#include "qgraphicsscene.h"
56
57#include "qgraphicssceneevent.h"
58#include "qgraphicsview.h"
59#include "qgraphicsview_p.h"
60#include "qgraphicsitem_p.h"
61
62#include <private/qobject_p.h>
63#include <QtCore/qbitarray.h>
64#include <QtCore/qlist.h>
65#include <QtCore/qmap.h>
66#include <QtCore/qset.h>
67#include <QtGui/qfont.h>
68#include <QtGui/qpalette.h>
69#include <QtWidgets/qstyle.h>
70#include <QtWidgets/qstyleoption.h>
71
72QT_REQUIRE_CONFIG(graphicsview);
73
74QT_BEGIN_NAMESPACE
75
76class QGraphicsSceneIndex;
77class QGraphicsView;
78class QGraphicsWidget;
79
80class Q_AUTOTEST_EXPORT QGraphicsScenePrivate : public QObjectPrivate
81{
82 Q_DECLARE_PUBLIC(QGraphicsScene)
83public:
84 QGraphicsScenePrivate();
85 void init();
86
87 static QGraphicsScenePrivate *get(QGraphicsScene *q);
88
89 int changedSignalIndex;
90 int processDirtyItemsIndex;
91 int polishItemsIndex;
92
93 QGraphicsScene::ItemIndexMethod indexMethod;
94 QGraphicsSceneIndex *index;
95
96 int lastItemCount;
97
98 QRectF sceneRect;
99
100 quint32 hasSceneRect : 1;
101 quint32 dirtyGrowingItemsBoundingRect : 1;
102 quint32 updateAll : 1;
103 quint32 calledEmitUpdated : 1;
104 quint32 processDirtyItemsEmitted : 1;
105 quint32 needSortTopLevelItems : 1;
106 quint32 holesInTopLevelSiblingIndex : 1;
107 quint32 topLevelSequentialOrdering : 1;
108 quint32 scenePosDescendantsUpdatePending : 1;
109 quint32 stickyFocus : 1;
110 quint32 hasFocus : 1;
111 quint32 lastMouseGrabberItemHasImplicitMouseGrab : 1;
112 quint32 allItemsIgnoreHoverEvents : 1;
113 quint32 allItemsUseDefaultCursor : 1;
114 quint32 painterStateProtection : 1;
115 quint32 sortCacheEnabled : 1; // for compatibility
116 quint32 allItemsIgnoreTouchEvents : 1;
117 quint32 focusOnTouch : 1;
118 quint32 padding : 14;
119
120 qreal minimumRenderSize;
121
122 QRectF growingItemsBoundingRect;
123
124 void _q_emitUpdated();
125 QList<QRectF> updatedRects;
126
127 QPainterPath selectionArea;
128 int selectionChanging;
129 QSet<QGraphicsItem *> selectedItems;
130 QVector<QGraphicsItem *> unpolishedItems;
131 QList<QGraphicsItem *> topLevelItems;
132
133 QHash<QGraphicsItem *, QPointF> movingItemsInitialPositions;
134 void registerTopLevelItem(QGraphicsItem *item);
135 void unregisterTopLevelItem(QGraphicsItem *item);
136 void _q_updateLater();
137 void _q_polishItems();
138
139 void _q_processDirtyItems();
140
141 QSet<QGraphicsItem *> scenePosItems;
142 void setScenePosItemEnabled(QGraphicsItem *item, bool enabled);
143 void registerScenePosItem(QGraphicsItem *item);
144 void unregisterScenePosItem(QGraphicsItem *item);
145 void _q_updateScenePosDescendants();
146
147 void removeItemHelper(QGraphicsItem *item);
148
149 QBrush backgroundBrush;
150 QBrush foregroundBrush;
151
152 quint32 rectAdjust;
153 QGraphicsItem *focusItem;
154 QGraphicsItem *lastFocusItem;
155 QGraphicsItem *passiveFocusItem;
156 QGraphicsWidget *tabFocusFirst;
157 QGraphicsItem *activePanel;
158 QGraphicsItem *lastActivePanel;
159 int activationRefCount;
160 int childExplicitActivation;
161 void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent);
162 void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason,
163 bool emitFocusChanged = true);
164
165 QList<QGraphicsWidget *> popupWidgets;
166 void addPopup(QGraphicsWidget *widget);
167 void removePopup(QGraphicsWidget *widget, bool itemIsDying = false);
168
169 QGraphicsItem *lastMouseGrabberItem;
170 QList<QGraphicsItem *> mouseGrabberItems;
171 void grabMouse(QGraphicsItem *item, bool implicit = false);
172 void ungrabMouse(QGraphicsItem *item, bool itemIsDying = false);
173 void clearMouseGrabber();
174
175 QList<QGraphicsItem *> keyboardGrabberItems;
176 void grabKeyboard(QGraphicsItem *item);
177 void ungrabKeyboard(QGraphicsItem *item, bool itemIsDying = false);
178 void clearKeyboardGrabber();
179
180 QGraphicsItem *dragDropItem;
181 QGraphicsWidget *enterWidget;
182 Qt::DropAction lastDropAction;
183 QList<QGraphicsItem *> cachedItemsUnderMouse;
184 QList<QGraphicsItem *> hoverItems;
185 QPointF lastSceneMousePos;
186 void enableMouseTrackingOnViews();
187 QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos;
188 QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos;
189 QMap<Qt::MouseButton, QPoint> mouseGrabberButtonDownScreenPos;
190 QList<QGraphicsItem *> itemsAtPosition(const QPoint &screenPos,
191 const QPointF &scenePos,
192 QWidget *widget) const;
193 void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event);
194
195 QList<QGraphicsView *> views;
196 void addView(QGraphicsView *view);
197 void removeView(QGraphicsView *view);
198
199 QMultiMap<QGraphicsItem *, QGraphicsItem *> sceneEventFilters;
200 void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
201 void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
202 bool filterDescendantEvent(QGraphicsItem *item, QEvent *event);
203 bool filterEvent(QGraphicsItem *item, QEvent *event);
204 bool sendEvent(QGraphicsItem *item, QEvent *event);
205
206 bool dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent);
207 bool itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const;
208 void leaveScene(QWidget *viewport);
209
210 void cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
211 QGraphicsSceneDragDropEvent *source);
212 void sendDragDropEvent(QGraphicsItem *item,
213 QGraphicsSceneDragDropEvent *dragDropEvent);
214 void sendHoverEvent(QEvent::Type type, QGraphicsItem *item,
215 QGraphicsSceneHoverEvent *hoverEvent);
216 void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent);
217 void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
218 QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
219
220 void drawItemHelper(QGraphicsItem *item, QPainter *painter,
221 const QStyleOptionGraphicsItem *option, QWidget *widget,
222 bool painterStateProtection);
223
224 void drawItems(QPainter *painter, const QTransform *const viewTransform,
225 QRegion *exposedRegion, QWidget *widget);
226
227 void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const,
228 QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0),
229 const QTransform *const effectTransform = nullptr);
230 void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const,
231 QRegion *, QWidget *, qreal, const QTransform *const, bool, bool);
232
233 void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
234 bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false,
235 bool updateBoundingRect = false);
236 void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false,
237 qreal parentOpacity = qreal(1.0));
238
239 inline void resetDirtyItem(QGraphicsItem *item, bool recursive = false)
240 {
241 Q_ASSERT(item);
242 item->d_ptr->dirty = 0;
243 item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
244 item->d_ptr->geometryChanged = 0;
245 if (!item->d_ptr->dirtyChildren)
246 recursive = false;
247 item->d_ptr->dirtyChildren = 0;
248 item->d_ptr->needsRepaint = QRectF();
249 item->d_ptr->allChildrenDirty = 0;
250 item->d_ptr->fullUpdatePending = 0;
251 item->d_ptr->ignoreVisible = 0;
252 item->d_ptr->ignoreOpacity = 0;
253#if QT_CONFIG(graphicseffect)
254 QGraphicsEffect::ChangeFlags flags;
255 if (item->d_ptr->notifyBoundingRectChanged) {
256 flags |= QGraphicsEffect::SourceBoundingRectChanged;
257 item->d_ptr->notifyBoundingRectChanged = 0;
258 }
259 if (item->d_ptr->notifyInvalidated) {
260 flags |= QGraphicsEffect::SourceInvalidated;
261 item->d_ptr->notifyInvalidated = 0;
262 }
263#endif // QT_CONFIG(graphicseffect)
264 if (recursive) {
265 for (int i = 0; i < item->d_ptr->children.size(); ++i)
266 resetDirtyItem(item->d_ptr->children.at(i), recursive);
267 }
268#if QT_CONFIG(graphicseffect)
269 if (flags && item->d_ptr->graphicsEffect)
270 item->d_ptr->graphicsEffect->sourceChanged(flags);
271#endif // QT_CONFIG(graphicseffect)
272 }
273
274 inline void ensureSortedTopLevelItems()
275 {
276 if (needSortTopLevelItems) {
277 std::sort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
278 topLevelSequentialOrdering = false;
279 needSortTopLevelItems = false;
280 }
281 }
282
283 void ensureSequentialTopLevelSiblingIndexes();
284
285 QStyle *style;
286 QFont font;
287 void setFont_helper(const QFont &font);
288 void resolveFont();
289 void updateFont(const QFont &font);
290 QPalette palette;
291 void setPalette_helper(const QPalette &palette);
292 void resolvePalette();
293 void updatePalette(const QPalette &palette);
294
295 QStyleOptionGraphicsItem styleOptionTmp;
296
297 QMap<int, QTouchEvent::TouchPoint> sceneCurrentTouchPoints;
298 QMap<int, QGraphicsItem *> itemForTouchPointId;
299 static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent);
300 int findClosestTouchPointId(const QPointF &scenePos);
301 void touchEventHandler(QTouchEvent *touchEvent);
302 bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent);
303 void enableTouchEventsOnViews();
304
305 QList<QGraphicsObject *> cachedTargetItems;
306#ifndef QT_NO_GESTURES
307 QHash<QGraphicsObject *, QSet<QGesture *> > cachedItemGestures;
308 QHash<QGraphicsObject *, QSet<QGesture *> > cachedAlreadyDeliveredGestures;
309 QHash<QGesture *, QGraphicsObject *> gestureTargets;
310 QHash<Qt::GestureType, int> grabbedGestures;
311 void gestureEventHandler(QGestureEvent *event);
312 void gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
313 Qt::GestureFlag flag,
314 QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
315 QSet<QGraphicsObject *> *itemsSet = nullptr,
316 QSet<QGesture *> *normal = nullptr,
317 QSet<QGesture *> *conflicts = nullptr);
318 void cancelGesturesForChildren(QGesture *original);
319 void grabGesture(QGraphicsItem *, Qt::GestureType gesture);
320 void ungrabGesture(QGraphicsItem *, Qt::GestureType gesture);
321#endif // QT_NO_GESTURES
322
323 void updateInputMethodSensitivityInViews();
324
325 QList<QGraphicsItem *> modalPanels;
326 void enterModal(QGraphicsItem *item,
327 QGraphicsItem::PanelModality panelModality = QGraphicsItem::NonModal);
328 void leaveModal(QGraphicsItem *item);
329};
330
331// QRectF::intersects() returns false always if either the source or target
332// rectangle's width or height are 0. This works around that problem.
333static inline void _q_adjustRect(QRectF *rect)
334{
335 Q_ASSERT(rect);
336 if (!rect->width())
337 rect->adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
338 if (!rect->height())
339 rect->adjust(0, qreal(-0.00001), 0, qreal(0.00001));
340}
341
342static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
343{
344 Q_ASSERT(item);
345 QRectF boundingRect(item->boundingRect());
346 _q_adjustRect(&boundingRect);
347 return boundingRect;
348}
349
350static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item)
351{
352 Q_ASSERT(item);
353 QRectF boundingRect(QGraphicsItemPrivate::get(item)->effectiveBoundingRect());
354 _q_adjustRect(&boundingRect);
355 return boundingRect;
356}
357
358QT_END_NAMESPACE
359
360#endif
361