Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qgraphicsscene.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
168#include "qgraphicsscene.h"
169
170#include "qgraphicsitem.h"
171#include "qgraphicsitem_p.h"
172#include "qgraphicslayout.h"
173#include "qgraphicsscene_p.h"
174#include "qgraphicssceneevent.h"
175#include "qgraphicsview.h"
176#include "qgraphicsview_p.h"
177#include "qgraphicswidget.h"
178#include "qgraphicswidget_p.h"
182
183#include <QtCore/qdebug.h>
184#include <QtCore/qlist.h>
185#include <QtCore/qmath.h>
186#include <QtCore/qrect.h>
187#include <QtCore/qset.h>
188#include <QtCore/qstack.h>
189#include <QtCore/qtimer.h>
190#include <QtCore/qvarlengtharray.h>
191#include <QtCore/QMetaMethod>
192#include <QtWidgets/qapplication.h>
193#include <QtGui/qevent.h>
194#include <QtWidgets/qgraphicslayout.h>
195#include <QtWidgets/qgraphicsproxywidget.h>
196#include <QtWidgets/qgraphicswidget.h>
197#include <QtGui/qpaintengine.h>
198#include <QtGui/qpainter.h>
199#include <QtGui/qpainterpath.h>
200#include <QtGui/qpixmapcache.h>
201#include <QtGui/qpolygon.h>
202#include <QtGui/qpointingdevice.h>
203#include <QtWidgets/qstyleoption.h>
204#if QT_CONFIG(tooltip)
205#include <QtWidgets/qtooltip.h>
206#endif
207#include <QtGui/qtransform.h>
208#include <QtGui/qinputmethod.h>
209#include <private/qapplication_p.h>
210#include <private/qevent_p.h>
211#include <QtGui/private/qeventpoint_p.h>
212#include <private/qobject_p.h>
213#if QT_CONFIG(graphicseffect)
214#include <private/qgraphicseffect_p.h>
215#endif
216#include <private/qgesturemanager_p.h>
217#include <private/qpathclipper_p.h>
218
219// #define GESTURE_DEBUG
220#ifndef GESTURE_DEBUG
221# define DEBUG if (0) qDebug
222#else
223# define DEBUG qDebug
224#endif
225
227
229
231{
232 hover->setWidget(mouseEvent->widget());
233 hover->setPos(mouseEvent->pos());
234 hover->setScenePos(mouseEvent->scenePos());
235 hover->setScreenPos(mouseEvent->screenPos());
236 hover->setLastPos(mouseEvent->lastPos());
237 hover->setLastScenePos(mouseEvent->lastScenePos());
238 hover->setLastScreenPos(mouseEvent->lastScreenPos());
239 hover->setModifiers(mouseEvent->modifiers());
240 hover->setAccepted(mouseEvent->isAccepted());
241}
242
247 : indexMethod(QGraphicsScene::BspTreeIndex),
248 index(nullptr),
249 lastItemCount(0),
250 hasSceneRect(false),
251 dirtyGrowingItemsBoundingRect(true),
252 updateAll(false),
253 calledEmitUpdated(false),
254 processDirtyItemsEmitted(false),
255 needSortTopLevelItems(true),
256 holesInTopLevelSiblingIndex(false),
257 topLevelSequentialOrdering(true),
258 scenePosDescendantsUpdatePending(false),
259 stickyFocus(false),
260 hasFocus(false),
261 lastMouseGrabberItemHasImplicitMouseGrab(false),
262 allItemsIgnoreHoverEvents(true),
263 allItemsUseDefaultCursor(true),
264 painterStateProtection(true),
265 sortCacheEnabled(false),
266 allItemsIgnoreTouchEvents(true),
267 focusOnTouch(true),
268 minimumRenderSize(0.0),
269 selectionChanging(0),
270 rectAdjust(2),
271 focusItem(nullptr),
272 lastFocusItem(nullptr),
273 passiveFocusItem(nullptr),
274 tabFocusFirst(nullptr),
275 activePanel(nullptr),
276 lastActivePanel(nullptr),
277 activationRefCount(0),
278 childExplicitActivation(0),
279 lastMouseGrabberItem(nullptr),
280 dragDropItem(nullptr),
281 enterWidget(nullptr),
282 lastDropAction(Qt::IgnoreAction),
283 style(nullptr)
284{
285}
286
291{
292 Q_Q(QGraphicsScene);
293
295
296 // Keep this index so we can check for connected slots later on.
297 changedSignalIndex = signalIndex("changed(QList<QRectF>)");
298 processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()");
299 polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()");
300
301 qApp->d_func()->scene_list.append(q);
302 q->update();
303}
304
309{
310 return q->d_func();
311}
312
314{
315 Q_Q(QGraphicsScene);
316 calledEmitUpdated = false;
317
319 if (!hasSceneRect) {
320 const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
321 growingItemsBoundingRect |= q->itemsBoundingRect();
322 if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
323 emit q->sceneRectChanged(growingItemsBoundingRect);
324 }
326 }
327
328 // Ensure all views are connected if anything is connected. This disables
329 // the optimization that items send updates directly to the views, but it
330 // needs to happen in order to keep compatibility with the behavior from
331 // Qt 4.4 and backward.
333 for (auto view : std::as_const(views)) {
334 if (!view->d_func()->connectedToScene) {
335 view->d_func()->connectedToScene = true;
336 q->connect(q, SIGNAL(changed(QList<QRectF>)),
337 view, SLOT(updateScene(QList<QRectF>)));
338 }
339 }
340 } else {
341 if (views.isEmpty()) {
342 updateAll = false;
343 return;
344 }
345 for (auto view : std::as_const(views))
346 view->d_func()->processPendingUpdates();
347 // It's important that we update all views before we dispatch, hence two for-loops.
348 for (auto view : std::as_const(views))
349 view->d_func()->dispatchPendingUpdateRequests();
350 return;
351 }
352
353 // Notify the changes to anybody interested.
354 QList<QRectF> oldUpdatedRects;
355 if (updateAll) {
356 oldUpdatedRects << q->sceneRect();
357 } else {
358 // Switch to a ranged constructor in Qt 6...
359 oldUpdatedRects.reserve(int(updatedRects.size()));
360 std::copy(updatedRects.cbegin(), updatedRects.cend(),
361 std::back_inserter(oldUpdatedRects));
362 }
363
364 updateAll = false;
365 updatedRects.clear();
366 emit q->changed(oldUpdatedRects);
367}
368
375{
377 needSortTopLevelItems = true; // ### maybe false
380}
381
388{
393 else
395 // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
396 // the item is not guaranteed to be at the index after the list is sorted
397 // (see ensureSortedTopLevelItems()).
398 item->d_ptr->siblingIndex = -1;
401}
402
407{
409 return;
410
411 const QVariant booleanTrueVariant(true);
412 QGraphicsItem *item = nullptr;
413 QGraphicsItemPrivate *itemd = nullptr;
414 const int oldUnpolishedCount = unpolishedItems.size();
415
416 for (int i = 0; i < oldUnpolishedCount; ++i) {
418 if (!item)
419 continue;
420 itemd = item->d_ptr.data();
421 itemd->pendingPolish = false;
422 if (!itemd->explicitlyHidden) {
425 }
426 if (itemd->isWidget) {
429 }
430 }
431
432 if (unpolishedItems.size() == oldUnpolishedCount) {
433 // No new items were added to the vector.
435 } else {
436 // New items were appended; keep them and remove the old ones.
437 unpolishedItems.remove(0, oldUnpolishedCount);
440 }
441}
442
444{
446
447 if (updateAll) {
449 // No need for further processing (except resetting the dirty states).
450 // The growingItemsBoundingRect is updated in _q_emitUpdated.
451 for (auto topLevelItem : std::as_const(topLevelItems))
452 resetDirtyItem(topLevelItem, /*recursive=*/true);
453 return;
454 }
455
456 const bool wasPendingSceneUpdate = calledEmitUpdated;
457 const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
458
459 // Process items recursively.
460 for (auto topLevelItem : std::as_const(topLevelItems))
461 processDirtyItemsRecursive(topLevelItem);
462
464 if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
465 emit q_func()->sceneRectChanged(growingItemsBoundingRect);
466
467 if (wasPendingSceneUpdate)
468 return;
469
470 for (auto view : std::as_const(views))
471 view->d_func()->processPendingUpdates();
472
473 if (calledEmitUpdated) {
474 // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
475 // and we cannot wait for the control to reach the eventloop before the
476 // changed signal is emitted, so we emit it now.
478 }
479
480 // Immediately dispatch all pending update requests on the views.
481 for (auto view : std::as_const(views))
482 view->d_func()->dispatchPendingUpdateRequests();
483}
484
489{
491 while (p) {
493 p = p->d_ptr->parent;
494 }
497 QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection);
498 }
499}
500
505{
508}
509
514{
517}
518
523{
524 for (QGraphicsItem *item : std::as_const(scenePosItems)) {
526 while (p) {
528 p = p->d_ptr->parent;
529 }
530 }
532}
533
547{
548 Q_Q(QGraphicsScene);
549
550 // Clear focus on the item to remove any reference in the focusWidget chain.
551 item->clearFocus();
552
553 markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false,
554 /*ignoreOpacity=*/false, /*removingItemFromScene=*/true);
555
556 if (item->d_ptr->inDestructor) {
557 // The item is actually in its destructor, we call the special method in the index.
558 index->deleteItem(item);
559 } else {
560 // Can potentially call item->boundingRect() (virtual function), that's why
561 // we only can call this function if the item is not in its destructor.
562 index->removeItem(item);
563 }
564
566
569
570 QGraphicsScene *oldScene = item->d_func()->scene;
571 item->d_func()->scene = nullptr;
572
573 //We need to remove all children first because they might use their parent
574 //attributes (e.g. sceneTransform).
575 if (!item->d_ptr->inDestructor) {
576 // Remove all children recursively
577 for (auto child : std::as_const(item->d_ptr->children))
579 }
580
581 if (!item->d_ptr->inDestructor && !item->parentItem() && item->isWidget()) {
582 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
583 widget->d_func()->fixFocusChainBeforeReparenting(nullptr, oldScene, nullptr);
584 }
585
586 // Unregister focus proxy.
588
589 // Remove from parent, or unregister from toplevels.
590 if (QGraphicsItem *parentItem = item->parentItem()) {
591 if (parentItem->scene()) {
592 Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
593 "Parent item's scene is different from this item's scene");
594 item->setParentItem(nullptr);
595 }
596 } else {
598 }
599
600 // Reset the mouse grabber and focus item data.
601 if (item == focusItem)
602 focusItem = nullptr;
603 if (item == lastFocusItem)
604 lastFocusItem = nullptr;
605 if (item == passiveFocusItem)
606 passiveFocusItem = nullptr;
607 if (item == activePanel) {
608 // ### deactivate...
609 activePanel = nullptr;
610 }
611 if (item == lastActivePanel)
612 lastActivePanel = nullptr;
613
614 // Change tabFocusFirst to the next widget in focus chain if removing the current one.
615 if (item == tabFocusFirst) {
617 if (wd->focusNext && wd->focusNext != tabFocusFirst && wd->focusNext->scene() == q)
619 else
620 tabFocusFirst = nullptr;
621 }
622
623 // Cancel active touches
624 {
626 while (it != itemForTouchPointId.end()) {
627 if (it.value() == item) {
630 } else {
631 ++it;
632 }
633 }
634 }
635
636 // Disable selectionChanged() for individual items
638 int oldSelectedItemsSize = selectedItems.size();
639
640 // Update selected & hovered item bookkeeping
644 if (item->d_ptr->pendingPolish) {
645 const int unpolishedIndex = unpolishedItems.indexOf(item);
646 if (unpolishedIndex != -1)
647 unpolishedItems[unpolishedIndex] = 0;
648 item->d_ptr->pendingPolish = false;
649 }
651
652 //We remove all references of item from the sceneEventFilter arrays
654 while (iterator != sceneEventFilters.end()) {
655 if (iterator.value() == item || iterator.key() == item)
656 iterator = sceneEventFilters.erase(iterator);
657 else
658 ++iterator;
659 }
660
663
664 // Reset the mouse grabber and focus item data.
666 ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
667
668 // Reset the keyboard grabber
670 ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
671
672 // Reset the last mouse grabber item
674 lastMouseGrabberItem = nullptr;
675
676 // Reset the current drop item
677 if (item == dragDropItem)
678 dragDropItem = nullptr;
679
680 // Re-enable selectionChanged() for individual items
682 if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
683 emit q->selectionChanged();
684
685#ifndef QT_NO_GESTURES
686 for (auto it = gestureTargets.begin(); it != gestureTargets.end();) {
687 if (it.value() == item)
689 else
690 ++it;
691 }
692
693 if (QGraphicsObject *dummy = item->toGraphicsObject()) {
697 }
698
699 for (auto it = item->d_ptr->gestureContext.constBegin();
701 ungrabGesture(item, it.key());
702#endif // QT_NO_GESTURES
703}
704
709{
710 Q_Q(QGraphicsScene);
711 if (item && item->scene() != q) {
712 qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene",
713 item);
714 return;
715 }
716
717 // Ensure the scene has focus when we change panel activation.
719
720 // Find the item's panel.
721 QGraphicsItem *panel = item ? item->panel() : nullptr;
722 lastActivePanel = panel ? activePanel : nullptr;
723 if (panel == activePanel || (!q->isActive() && !duringActivationEvent))
724 return;
725
726 QGraphicsItem *oldFocusItem = focusItem;
727
728 // Deactivate the last active panel.
729 if (activePanel) {
731 // Remove focus from the current focus item.
732 if (fi == q->focusItem())
733 setFocusItemHelper(nullptr, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
734 }
735
737 q->sendEvent(activePanel, &event);
738 } else if (panel && !duringActivationEvent) {
739 // Deactivate the scene if changing activation to a panel.
740 const auto items = q->items();
742 for (QGraphicsItem *item : items) {
743 if (item->isVisible() && !item->isPanel() && !item->parentItem())
744 q->sendEvent(item, &event);
745 }
746 }
747
748 // Update activate state.
752
753 // Activate
754 if (panel) {
756 q->sendEvent(panel, &event);
757
758 // Set focus on the panel's focus item, or itself if it's
759 // focusable, or on the first focusable item in the panel's
760 // focus chain as a last resort.
761 if (QGraphicsItem *focusItem = panel->focusItem()) {
762 setFocusItemHelper(focusItem, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
763 } else if (panel->flags() & QGraphicsItem::ItemIsFocusable) {
764 setFocusItemHelper(panel, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
765 } else if (panel->isWidget()) {
766 QGraphicsWidget *fw = static_cast<QGraphicsWidget *>(panel)->d_func()->focusNext;
767 do {
768 if (fw->focusPolicy() & Qt::TabFocus) {
769 setFocusItemHelper(fw, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
770 break;
771 }
772 fw = fw->d_func()->focusNext;
773 } while (fw != panel);
774 }
775 } else if (q->isActive()) {
776 const auto items = q->items();
777 // Activate the scene
779 for (QGraphicsItem *item : items) {
780 if (item->isVisible() && !item->isPanel() && !item->parentItem())
781 q->sendEvent(item, &event);
782 }
783 }
784
785 emit q->focusItemChanged(focusItem, oldFocusItem, Qt::ActiveWindowFocusReason);
786}
787
799 Qt::FocusReason focusReason,
800 bool emitFocusChanged)
801{
802 Q_Q(QGraphicsScene);
803 if (item == focusItem)
804 return;
805
806 // Clear focus if asked to set focus on something that can't
807 // accept input focus.
809 || !item->isVisible() || !item->isEnabled())) {
810 item = nullptr;
811 }
812
813 // Set focus on the scene if an item requests focus.
814 if (item) {
815 q->setFocus(focusReason);
816 if (item == focusItem) {
817 if (emitFocusChanged)
818 emit q->focusItemChanged(focusItem, (QGraphicsItem *)nullptr, focusReason);
819 return;
820 }
821 }
822
823 QGraphicsItem *oldFocusItem = focusItem;
824 if (focusItem) {
826
827#ifndef QT_NO_IM
829 // Close any external input method panel. This happens
830 // automatically by removing WA_InputMethodEnabled on
831 // the views, but if we are changing focus, we have to
832 // do it ourselves.
833 if (qApp)
835 }
836#endif //QT_NO_IM
837
838 focusItem = nullptr;
839 QFocusEvent event(QEvent::FocusOut, focusReason);
841 }
842
843 // This handles the case that the item has been removed from the
844 // scene in response to the FocusOut event.
845 if (item && item->scene() != q)
846 item = nullptr;
847
848 if (item)
849 focusItem = item;
851
852 if (item) {
853 QFocusEvent event(QEvent::FocusIn, focusReason);
855 }
856
857 if (emitFocusChanged)
858 emit q->focusItemChanged(focusItem, oldFocusItem, focusReason);
859}
860
865{
869 if (QGraphicsWidget *focusWidget = widget->focusWidget()) {
870 focusWidget->setFocus(Qt::PopupFocusReason);
871 } else {
873 if (focusItem && popupWidgets.size() == 1) {
876 }
877 }
879}
880
891{
894 Q_ASSERT(index != -1);
895
896 for (int i = popupWidgets.size() - 1; i >= index; --i) {
898 ungrabMouse(widget, itemIsDying);
899 if (focusItem && popupWidgets.isEmpty()) {
902 } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) {
903 ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying);
904 }
905 if (!itemIsDying && widget->isVisible()) {
906 widget->QGraphicsItem::d_ptr->setVisibleHelper(false, /* explicit = */ false);
907 }
908 }
909}
910
915{
916 // Append to list of mouse grabber items, and send a mouse grab event.
919 Q_ASSERT(!implicit);
921 qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
922 } else {
923 // Upgrade to an explicit mouse grab
925 }
926 } else {
927 qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
929 }
930 return;
931 }
932
933 // Send ungrab event to the last grabber.
934 if (!mouseGrabberItems.isEmpty()) {
937 // Implicit mouse grab is immediately lost.
938 last->ungrabMouse();
939 } else {
940 // Just send ungrab event to current grabber.
941 QEvent ungrabEvent(QEvent::UngrabMouse);
942 sendEvent(last, &ungrabEvent);
943 }
944 }
945
948
949 // Send grab event to current grabber.
950 QEvent grabEvent(QEvent::GrabMouse);
951 sendEvent(item, &grabEvent);
952}
953
958{
960 if (index == -1) {
961 qWarning("QGraphicsItem::ungrabMouse: not a mouse grabber");
962 return;
963 }
964
966 // Recursively ungrab the next mouse grabber until we reach this item
967 // to ensure state consistency.
968 ungrabMouse(mouseGrabberItems.at(index + 1), itemIsDying);
969 }
971 // If the item is a popup, go via removePopup to ensure state
972 // consistency and that it gets hidden correctly - beware that
973 // removePopup() reenters this function to continue removing the grab.
974 removePopup(popupWidgets.constLast(), itemIsDying);
975 return;
976 }
977
978 // Send notification about mouse ungrab.
979 if (!itemIsDying) {
982 }
983
984 // Remove the item from the list of grabbers. Whenever this happens, we
985 // reset the implicitGrab (there can be only ever be one implicit grabber
986 // in a scene, and it is always the latest grabber; if the implicit grab
987 // is lost, it is not automatically regained.
990
991 // Send notification about mouse regrab. ### It's unfortunate that all the
992 // items get a GrabMouse event, but this is a rare case with a simple
993 // implementation and it does ensure a consistent state.
994 if (!itemIsDying && !mouseGrabberItems.isEmpty()) {
997 sendEvent(last, &event);
998 }
999}
1000
1005{
1008 lastMouseGrabberItem = nullptr;
1009}
1010
1015{
1018 qWarning("QGraphicsItem::grabKeyboard: already a keyboard grabber");
1019 else
1020 qWarning("QGraphicsItem::grabKeyboard: already blocked by keyboard grabber: %p",
1022 return;
1023 }
1024
1025 // Send ungrab event to the last grabber.
1027 // Just send ungrab event to current grabber.
1028 QEvent ungrabEvent(QEvent::UngrabKeyboard);
1029 sendEvent(keyboardGrabberItems.constLast(), &ungrabEvent);
1030 }
1031
1033
1034 // Send grab event to current grabber.
1035 QEvent grabEvent(QEvent::GrabKeyboard);
1036 sendEvent(item, &grabEvent);
1037}
1038
1043{
1045 if (index == -1) {
1046 qWarning("QGraphicsItem::ungrabKeyboard: not a keyboard grabber");
1047 return;
1048 }
1050 // Recursively ungrab the topmost keyboard grabber until we reach this
1051 // item to ensure state consistency.
1052 ungrabKeyboard(keyboardGrabberItems.at(index + 1), itemIsDying);
1053 }
1054
1055 // Send notification about keyboard ungrab.
1056 if (!itemIsDying) {
1058 sendEvent(item, &event);
1059 }
1060
1061 // Remove the item from the list of grabbers.
1063
1064 // Send notification about mouse regrab.
1065 if (!itemIsDying && !keyboardGrabberItems.isEmpty()) {
1068 sendEvent(last, &event);
1069 }
1070}
1071
1076{
1079}
1080
1082{
1083 for (QGraphicsView *view : std::as_const(views))
1084 view->viewport()->setMouseTracking(true);
1085}
1086
1091 const QPointF &scenePos,
1092 QWidget *widget) const
1093{
1094 Q_Q(const QGraphicsScene);
1095 QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
1096 if (!view)
1097 return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
1098
1099 const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
1100 if (!view->isTransformed())
1101 return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);
1102
1103 const QTransform viewTransform = view->viewportTransform();
1104 if (viewTransform.type() <= QTransform::TxScale) {
1105 return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
1106 Qt::DescendingOrder, viewTransform);
1107 }
1108 return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
1109 Qt::DescendingOrder, viewTransform);
1110}
1111
1116{
1117 for (int i = 0x1; i <= 0x10; i <<= 1) {
1118 if (event->buttons() & i) {
1121 event->widget()));
1124 }
1125 }
1126}
1127
1132{
1134}
1135
1140{
1141 if (!sceneEventFilters.contains(watched))
1142 return;
1143
1146 do {
1147 if (it.value() == filter)
1149 else
1150 ++it;
1151 } while (it != end);
1152}
1153
1158{
1161 while (parent) {
1162 if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
1163 return true;
1165 return false;
1166 parent = parent->parentItem();
1167 }
1168 }
1169 return false;
1170}
1171
1176{
1178 return false;
1179
1182 while (it != end) {
1183 // ### The filterer and filteree might both be deleted.
1184 if (it.value()->sceneEventFilter(it.key(), event))
1185 return true;
1186 ++it;
1187 }
1188 return false;
1189}
1190
1201{
1202#if QT_CONFIG(gestures)
1203 if (QGraphicsObject *object = item->toGraphicsObject()) {
1205 if (gestureManager) {
1206 if (gestureManager->filterEvent(object, event))
1207 return true;
1208 }
1209 }
1210#endif // QT_CONFIG(gestures)
1211
1212 if (filterEvent(item, event))
1213 return false;
1215 return false;
1216 if (!item || !item->isEnabled())
1217 return false;
1219 bool spont = event->spontaneous();
1221 return true;
1222 event->m_spont = spont;
1223 }
1224 return item->sceneEvent(event);
1225}
1226
1232{
1233 dest->setWidget(source->widget());
1234 dest->setPos(source->pos());
1235 dest->setScenePos(source->scenePos());
1236 dest->setScreenPos(source->screenPos());
1237 dest->setButtons(source->buttons());
1238 dest->setModifiers(source->modifiers());
1239 dest->setPossibleActions(source->possibleActions());
1240 dest->setProposedAction(source->proposedAction());
1241 dest->setDropAction(source->dropAction());
1242 dest->setSource(source->source());
1243 dest->setMimeData(source->mimeData());
1244}
1245
1250 QGraphicsSceneDragDropEvent *dragDropEvent)
1251{
1252 dragDropEvent->setPos(item->d_ptr->genericMapFromScene(dragDropEvent->scenePos(), dragDropEvent->widget()));
1253 sendEvent(item, dragDropEvent);
1254}
1255
1260 QGraphicsSceneHoverEvent *hoverEvent)
1261{
1263 event.setWidget(hoverEvent->widget());
1264 const QTransform mapFromScene = item->d_ptr->genericMapFromSceneTransform(hoverEvent->widget());
1265 event.setPos(mapFromScene.map(hoverEvent->scenePos()));
1266 event.setScenePos(hoverEvent->scenePos());
1267 event.setScreenPos(hoverEvent->screenPos());
1268 event.setLastPos(mapFromScene.map(hoverEvent->lastScenePos()));
1269 event.setLastScenePos(hoverEvent->lastScenePos());
1270 event.setLastScreenPos(hoverEvent->lastScreenPos());
1271 event.setModifiers(hoverEvent->modifiers());
1272 sendEvent(item, &event);
1273}
1274
1279{
1280 if (mouseEvent->button() == 0 && mouseEvent->buttons() == 0 && lastMouseGrabberItemHasImplicitMouseGrab) {
1281 // ### This is a temporary fix for until we get proper mouse
1282 // grab events.
1284 return;
1285 }
1286
1289 return;
1290
1291 const QTransform mapFromScene = item->d_ptr->genericMapFromSceneTransform(mouseEvent->widget());
1292 const QPointF itemPos = mapFromScene.map(mouseEvent->scenePos());
1293 for (int i = 0x1; i <= 0x10; i <<= 1) {
1298 }
1299 mouseEvent->setPos(itemPos);
1300 mouseEvent->setLastPos(mapFromScene.map(mouseEvent->lastScenePos()));
1301 sendEvent(item, mouseEvent);
1302}
1303
1308{
1309 Q_Q(QGraphicsScene);
1310
1311 // Ignore by default, unless we find a mouse grabber that accepts it.
1312 mouseEvent->ignore();
1313
1314 // Deliver to any existing mouse grabber.
1315 if (!mouseGrabberItems.isEmpty()) {
1317 return;
1318 // The event is ignored by default, but we disregard the event's
1319 // accepted state after delivery; the mouse is grabbed, after all.
1320 sendMouseEvent(mouseEvent);
1321 return;
1322 }
1323
1324 // Start by determining the number of items at the current position.
1325 // Reuse value from earlier calculations if possible.
1328 mouseEvent->scenePos(),
1329 mouseEvent->widget());
1330 }
1331
1332 // Update window activation.
1334 QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : nullptr;
1335 if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
1336 // pass activation to the blocking modal window
1337 newActiveWindow = topItem ? topItem->window() : nullptr;
1338 }
1339
1340 if (newActiveWindow != q->activeWindow())
1341 q->setActiveWindow(newActiveWindow);
1342
1343 // Set focus on the topmost enabled item that can take focus.
1344 bool setFocus = false;
1345
1346 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
1349 // Make sure we don't clear focus.
1350 setFocus = true;
1351 break;
1352 }
1354 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
1355 setFocus = true;
1356 if (item != q->focusItem() && item->d_ptr->mouseSetsFocus)
1357 q->setFocusItem(item, Qt::MouseFocusReason);
1358 break;
1359 }
1360 }
1361 if (item->isPanel())
1362 break;
1364 break;
1365 }
1366
1367 // Check for scene modality.
1368 bool sceneModality = false;
1369 for (auto modalPanel : std::as_const(modalPanels)) {
1370 if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
1371 sceneModality = true;
1372 break;
1373 }
1374 }
1375
1376 // If nobody could take focus, clear it.
1377 if (!stickyFocus && !setFocus && !sceneModality)
1378 q->setFocusItem(nullptr, Qt::MouseFocusReason);
1379
1380 // Any item will do.
1381 if (sceneModality && cachedItemsUnderMouse.isEmpty())
1383
1384 // Find a mouse grabber by sending mouse press events to all mouse grabber
1385 // candidates one at a time, until the event is accepted. It's accepted by
1386 // default, so the receiver has to explicitly ignore it for it to pass
1387 // through.
1388 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
1389 if (!(item->acceptedMouseButtons() & mouseEvent->button())) {
1390 // Skip items that don't accept the event's mouse button.
1391 continue;
1392 }
1393
1394 // Check if this item is blocked by a modal panel and deliver the mouse event to the
1395 // blocking panel instead of this item if blocked.
1397
1398 grabMouse(item, /* implicit = */ true);
1399 mouseEvent->accept();
1400
1401 // check if the item we are sending to are disabled (before we send the event)
1402 bool disabled = !item->isEnabled();
1403 bool isPanel = item->isPanel();
1404 if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
1406 // If this item is different from the item that received the last
1407 // mouse event, and mouseEvent is a double-click event, then the
1408 // event is converted to a press. Known limitation:
1409 // Triple-clicking will not generate a double-click, though.
1411 mousePress.m_spont = mouseEvent->spontaneous();
1412 mousePress.accept();
1413 mousePress.setButton(mouseEvent->button());
1414 mousePress.setButtons(mouseEvent->buttons());
1415 mousePress.setScreenPos(mouseEvent->screenPos());
1416 mousePress.setScenePos(mouseEvent->scenePos());
1417 mousePress.setModifiers(mouseEvent->modifiers());
1418 mousePress.setWidget(mouseEvent->widget());
1419 mousePress.setButtonDownPos(mouseEvent->button(),
1420 mouseEvent->buttonDownPos(mouseEvent->button()));
1421 mousePress.setButtonDownScenePos(mouseEvent->button(),
1422 mouseEvent->buttonDownScenePos(mouseEvent->button()));
1423 mousePress.setButtonDownScreenPos(mouseEvent->button(),
1424 mouseEvent->buttonDownScreenPos(mouseEvent->button()));
1425 sendMouseEvent(&mousePress);
1426 mouseEvent->setAccepted(mousePress.isAccepted());
1427 } else {
1428 sendMouseEvent(mouseEvent);
1429 }
1430
1431 bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.constLast() != item;
1432 if (disabled) {
1433 ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
1434 break;
1435 }
1436 if (mouseEvent->isAccepted()) {
1440 return;
1441 }
1442 ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
1443
1444 // Don't propagate through panels.
1445 if (isPanel)
1446 break;
1447 }
1448
1449 // Is the event still ignored? Then the mouse press goes to the scene.
1450 // Reset the mouse grabber, clear the selection, clear focus, and leave
1451 // the event ignored so that it can propagate through the originating
1452 // view.
1453 if (!mouseEvent->isAccepted()) {
1455
1456 QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0;
1457 bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
1458 bool extendSelection = (mouseEvent->modifiers() & Qt::ControlModifier) != 0;
1459 dontClearSelection |= extendSelection;
1460 if (!dontClearSelection) {
1461 // Clear the selection if the originating view isn't in scroll
1462 // hand drag mode. The view will clear the selection if no drag
1463 // happened.
1464 q->clearSelection();
1465 }
1466 }
1467}
1468
1479{
1484 }
1487 for (int i = 0; i < topLevelItems.size(); ++i)
1488 topLevelItems[i]->d_ptr->siblingIndex = i;
1489 }
1490}
1491
1499{
1500 if (this->font == font && this->font.resolveMask() == font.resolveMask())
1501 return;
1503}
1504
1512{
1513 QFont naturalFont = QApplication::font();
1514 naturalFont.setResolveMask(0);
1515 QFont resolvedFont = font.resolve(naturalFont);
1516 updateFont(resolvedFont);
1517}
1518
1526{
1527 Q_Q(QGraphicsScene);
1528
1529 // Update local font setting.
1530 this->font = font;
1531
1532 // Resolve the fonts of all top-level widget items, or widget items
1533 // whose parent is not a widget.
1534 const auto items = q->items();
1535 for (QGraphicsItem *item : items) {
1536 if (!item->parentItem()) {
1537 // Resolvefont for an item is a noop operation, but
1538 // every item can be a widget, or can have a widget
1539 // childre.
1541 }
1542 }
1543
1544 // Send the scene a FontChange event.
1547}
1548
1556{
1557 if (this->palette == palette && this->palette.resolveMask() == palette.resolveMask())
1558 return;
1560}
1561
1569{
1570 QPalette naturalPalette = QGuiApplication::palette();
1571 naturalPalette.setResolveMask(0);
1572 QPalette resolvedPalette = palette.resolve(naturalPalette);
1573 updatePalette(resolvedPalette);
1574}
1575
1583{
1584 Q_Q(QGraphicsScene);
1585
1586 // Update local palette setting.
1587 this->palette = palette;
1588
1589 // Resolve the palettes of all top-level widget items, or widget items
1590 // whose parent is not a widget.
1591 const auto items = q->items();
1592 for (QGraphicsItem *item : items) {
1593 if (!item->parentItem()) {
1594 // ResolvePalette for an item is a noop operation, but
1595 // every item can be a widget, or can have a widget
1596 // children.
1598 }
1599 }
1600
1601 // Send the scene a PaletteChange event.
1604}
1605
1612{
1613 d_func()->init();
1614}
1615
1625{
1626 d_func()->init();
1628}
1629
1640{
1641 d_func()->init();
1643}
1644
1652{
1653 Q_D(QGraphicsScene);
1654
1655 // Remove this scene from qApp's global scene list.
1657 qApp->d_func()->scene_list.removeAll(this);
1658
1659 clear();
1660
1661 // Remove this scene from all associated views.
1662 // Note: d->views is modified by QGraphicsView::setScene, so must make a copy
1663 const auto views = d->views;
1664 for (auto view : std::as_const(views))
1665 view->setScene(nullptr);
1666}
1667
1684{
1685 Q_D(const QGraphicsScene);
1686 if (d->hasSceneRect)
1687 return d->sceneRect;
1688
1689 if (d->dirtyGrowingItemsBoundingRect) {
1690 // Lazily update the growing items bounding rect
1691 QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
1692 QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
1694 thatd->dirtyGrowingItemsBoundingRect = false;
1695 if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
1696 emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
1697 }
1698 return d->growingItemsBoundingRect;
1699}
1701{
1702 Q_D(QGraphicsScene);
1703 if (rect != d->sceneRect) {
1704 d->hasSceneRect = !rect.isNull();
1705 d->sceneRect = rect;
1706 emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
1707 }
1708}
1709
1745 Qt::AspectRatioMode aspectRatioMode)
1746{
1747 // ### Switch to using the recursive rendering algorithm instead.
1748
1749 // Default source rect = scene rect
1750 QRectF sourceRect = source;
1751 if (sourceRect.isNull())
1752 sourceRect = sceneRect();
1753
1754 // Default target rect = device rect
1755 QRectF targetRect = target;
1756 if (targetRect.isNull()) {
1758 targetRect = sourceRect;
1759 else
1760 targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
1761 }
1762
1763 // Find the ideal x / y scaling ratio to fit \a source into \a target.
1764 qreal xratio = targetRect.width() / sourceRect.width();
1765 qreal yratio = targetRect.height() / sourceRect.height();
1766
1767 // Scale according to the aspect ratio mode.
1768 switch (aspectRatioMode) {
1770 xratio = yratio = qMin(xratio, yratio);
1771 break;
1773 xratio = yratio = qMax(xratio, yratio);
1774 break;
1776 break;
1777 }
1778
1779 // Find all items to draw, and reverse the list (we want to draw
1780 // in reverse order).
1782 QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
1783 const qsizetype numItems = itemList.size();
1784 for (qsizetype i = 0; i < numItems; ++i)
1785 itemArray[numItems - i - 1] = itemList.at(i);
1786 itemList.clear();
1787
1788 painter->save();
1789
1790 // Transform the painter.
1792 QTransform painterTransform;
1793 painterTransform *= QTransform()
1794 .translate(targetRect.left(), targetRect.top())
1795 .scale(xratio, yratio)
1796 .translate(-sourceRect.left(), -sourceRect.top());
1797 painter->setWorldTransform(painterTransform, true);
1798
1799 // Generate the style options
1800 QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
1801 for (qsizetype i = 0; i < numItems; ++i)
1802 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
1803
1804 // Render the scene.
1805 drawBackground(painter, sourceRect);
1806 drawItems(painter, numItems, itemArray, styleOptionArray);
1807 drawForeground(painter, sourceRect);
1808
1809 delete [] itemArray;
1810 delete [] styleOptionArray;
1811
1812 painter->restore();
1813}
1814
1832{
1833 Q_D(const QGraphicsScene);
1834 return d->indexMethod;
1835}
1837{
1838 Q_D(QGraphicsScene);
1839 if (d->indexMethod == method)
1840 return;
1841
1842 d->indexMethod = method;
1843
1844 QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder);
1845 delete d->index;
1846 if (method == BspTreeIndex)
1847 d->index = new QGraphicsSceneBspTreeIndex(this);
1848 else
1849 d->index = new QGraphicsSceneLinearIndex(this);
1850 for (int i = oldItems.size() - 1; i >= 0; --i)
1851 d->index->addItem(oldItems.at(i));
1852}
1853
1887{
1888 Q_D(const QGraphicsScene);
1889 QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
1890 return bspTree ? bspTree->bspTreeDepth() : 0;
1891}
1893{
1894 Q_D(QGraphicsScene);
1895 if (depth < 0) {
1896 qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth);
1897 return;
1898 }
1899
1900 QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
1901 if (!bspTree) {
1902 qWarning("QGraphicsScene::setBspTreeDepth: cannot apply if indexing method is not BSP");
1903 return;
1904 }
1905 bspTree->setBspTreeDepth(depth);
1906}
1907
1916{
1917 // Does not take untransformable items into account.
1919 const auto items_ = items();
1920 for (QGraphicsItem *item : items_)
1922 return boundingRect;
1923}
1924
1932{
1933 Q_D(const QGraphicsScene);
1934 return d->index->items(order);
1935}
1936
1971{
1972 Q_D(const QGraphicsScene);
1973 return d->index->items(pos, mode, order, deviceTransform);
1974}
1975
1997{
1998 Q_D(const QGraphicsScene);
1999 return d->index->items(rect, mode, order, deviceTransform);
2000}
2001
2023{
2024 Q_D(const QGraphicsScene);
2025 return d->index->items(polygon, mode, order, deviceTransform);
2026}
2027
2049{
2050 Q_D(const QGraphicsScene);
2051 return d->index->items(path, mode, order, deviceTransform);
2052}
2053
2068{
2069 Q_D(const QGraphicsScene);
2070 if (!item) {
2071 qWarning("QGraphicsScene::collidingItems: cannot find collisions for null item");
2072 return QList<QGraphicsItem *>();
2073 }
2074
2075 // Does not support ItemIgnoresTransformations.
2077 const auto itemsInVicinity = d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder);
2078 for (QGraphicsItem *itemInVicinity : itemsInVicinity) {
2079 if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
2080 tmp << itemInVicinity;
2081 }
2082 return tmp;
2083}
2084
2099{
2102 return itemsAtPoint.isEmpty() ? nullptr : itemsAtPoint.first();
2103}
2104
2129{
2130 Q_D(const QGraphicsScene);
2131
2132 // Optimization: Lazily removes items that are not selected.
2133 QGraphicsScene *that = const_cast<QGraphicsScene *>(this);
2134 QSet<QGraphicsItem *> actuallySelectedSet;
2135 for (QGraphicsItem *item : std::as_const(that->d_func()->selectedItems)) {
2136 if (item->isSelected())
2137 actuallySelectedSet << item;
2138 }
2139
2140 that->d_func()->selectedItems = actuallySelectedSet;
2141
2142 return d->selectedItems.values();
2143}
2144
2153{
2154 Q_D(const QGraphicsScene);
2155 return d->selectionArea;
2156}
2157
2174{
2176}
2177
2193 Qt::ItemSelectionOperation selectionOperation,
2196{
2197 Q_D(QGraphicsScene);
2198
2199 // Note: with boolean path operations, we can improve performance here
2200 // quite a lot by "growing" the old path instead of replacing it. That
2201 // allows us to only check the intersect area for changes, instead of
2202 // reevaluating the whole path over again.
2203 d->selectionArea = path;
2204
2205 QSet<QGraphicsItem *> unselectItems = d->selectedItems;
2206
2207 // Disable emitting selectionChanged() for individual items.
2208 ++d->selectionChanging;
2209 bool changed = false;
2210
2211 // Set all items in path to selected.
2212 const auto items = this->items(path, mode, Qt::DescendingOrder, deviceTransform);
2213 for (QGraphicsItem *item : items) {
2215 if (!item->isSelected())
2216 changed = true;
2217 unselectItems.remove(item);
2218 item->setSelected(true);
2219 }
2220 }
2221
2222 switch (selectionOperation) {
2224 // Deselect all items outside path.
2225 for (QGraphicsItem *item : std::as_const(unselectItems)) {
2226 item->setSelected(false);
2227 changed = true;
2228 }
2229 break;
2230 default:
2231 break;
2232 }
2233
2234 // Re-enable emitting selectionChanged() for individual items.
2235 --d->selectionChanging;
2236
2237 if (!d->selectionChanging && changed)
2239}
2240
2247{
2248 Q_D(QGraphicsScene);
2249
2250 // Disable emitting selectionChanged
2251 ++d->selectionChanging;
2252 // iterate over a copy, as clearing selection might invalidate selectedItems
2253 const auto selectedItems = d->selectedItems;
2254 QSet<QGraphicsItem *> stillSelectedSet;
2255
2257 item->setSelected(false);
2258 // items might override itemChange to prevent deselection
2259 if (item->isSelected())
2260 stillSelectedSet << item;
2261 }
2262 const bool changed = stillSelectedSet != selectedItems;
2263 d->selectedItems = stillSelectedSet;
2264
2265 // Re-enable emitting selectionChanged() for individual items.
2266 --d->selectionChanging;
2267
2268 if (!d->selectionChanging && changed)
2270}
2271
2281{
2282 Q_D(QGraphicsScene);
2283 // NB! We have to clear the index before deleting items; otherwise the
2284 // index might try to access dangling item pointers.
2285 d->index->clear();
2286 // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items
2287 while (!d->topLevelItems.isEmpty())
2288 delete d->topLevelItems.first();
2289 Q_ASSERT(d->topLevelItems.isEmpty());
2290 d->lastItemCount = 0;
2291 d->allItemsIgnoreHoverEvents = true;
2292 d->allItemsUseDefaultCursor = true;
2293 d->allItemsIgnoreTouchEvents = true;
2294 d->focusOnTouch = true;
2295}
2296
2311{
2312 // Build a list of the first item's ancestors
2313 QList<QGraphicsItem *> ancestors;
2314 int n = 0;
2315 if (!items.isEmpty()) {
2317 while ((parent = parent->parentItem()))
2318 ancestors.append(parent);
2319 }
2320
2321 // Find the common ancestor for all items
2322 QGraphicsItem *commonAncestor = nullptr;
2323 if (!ancestors.isEmpty()) {
2324 while (n < items.size()) {
2325 int commonIndex = -1;
2327 do {
2328 int index = ancestors.indexOf(parent, qMax(0, commonIndex));
2329 if (index != -1) {
2330 commonIndex = index;
2331 break;
2332 }
2333 } while ((parent = parent->parentItem()));
2334
2335 if (commonIndex == -1) {
2336 commonAncestor = nullptr;
2337 break;
2338 }
2339
2340 commonAncestor = ancestors.at(commonIndex);
2341 }
2342 }
2343
2344 // Create a new group at that level
2345 QGraphicsItemGroup *group = new QGraphicsItemGroup(commonAncestor);
2346 if (!commonAncestor)
2347 addItem(group);
2348 for (QGraphicsItem *item : items)
2349 group->addToGroup(item);
2350 return group;
2351}
2352
2361{
2362 const auto items = group->childItems();
2363 for (QGraphicsItem *item : items)
2364 group->removeFromGroup(item);
2366 delete group;
2367}
2368
2395{
2396 Q_D(QGraphicsScene);
2397 if (!item) {
2398 qWarning("QGraphicsScene::addItem: cannot add null item");
2399 return;
2400 }
2401 if (item->d_ptr->scene == this) {
2402 qWarning("QGraphicsScene::addItem: item has already been added to this scene");
2403 return;
2404 }
2405 // Remove this item from its existing scene
2406 if (QGraphicsScene *oldScene = item->d_ptr->scene)
2407 oldScene->removeItem(item);
2408
2409 // Notify the item that its scene is changing, and allow the item to
2410 // react.
2412 QVariant::fromValue<QGraphicsScene *>(this)));
2413 QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
2414 if (targetScene != this) {
2415 if (targetScene && item->d_ptr->scene != targetScene)
2416 targetScene->addItem(item);
2417 return;
2418 }
2419
2420 if (d->unpolishedItems.isEmpty()) {
2421 QMetaMethod method = metaObject()->method(d->polishItemsIndex);
2422 method.invoke(this, Qt::QueuedConnection);
2423 }
2424 d->unpolishedItems.append(item);
2425 item->d_ptr->pendingPolish = true;
2426
2427 // Detach this item from its parent if the parent's scene is different
2428 // from this scene.
2429 if (QGraphicsItem *itemParent = item->d_ptr->parent) {
2430 if (itemParent->d_ptr->scene != this)
2431 item->setParentItem(nullptr);
2432 }
2433
2434 // Add the item to this scene
2435 item->d_func()->scene = targetScene;
2436
2437 // Add the item in the index
2438 d->index->addItem(item);
2439
2440 // Add to list of toplevels if this item is a toplevel.
2441 if (!item->d_ptr->parent)
2442 d->registerTopLevelItem(item);
2443
2444 // Add to list of items that require an update. We cannot assume that the
2445 // item is fully constructed, so calling item->update() can lead to a pure
2446 // virtual function call to boundingRect().
2447 d->markDirty(item);
2448 d->dirtyGrowingItemsBoundingRect = true;
2449
2450 // Disable selectionChanged() for individual items
2451 ++d->selectionChanging;
2452 int oldSelectedItemSize = d->selectedItems.size();
2453
2454 // Enable mouse tracking if we haven't already done so, and the item needs it.
2455 // We cannot use itemAcceptsHoverEvents_helper() here, since we need to enable
2456 // mouse tracking also if this item is temporarily blocked by a modal panel.
2457
2458 auto needsMouseTracking = [](const QGraphicsItemPrivate *item) {
2459 return item->acceptsHover
2460 || (item->isWidget && static_cast<const QGraphicsWidgetPrivate *>(item)->hasDecoration());
2461 };
2462
2463 if (d->allItemsIgnoreHoverEvents && needsMouseTracking(item->d_ptr.data())) {
2464 d->allItemsIgnoreHoverEvents = false;
2465 d->enableMouseTrackingOnViews();
2466 }
2467#ifndef QT_NO_CURSOR
2468 if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
2469 d->allItemsUseDefaultCursor = false;
2470 if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
2471 d->enableMouseTrackingOnViews();
2472 }
2473#endif //QT_NO_CURSOR
2474
2475 // Enable touch events if the item accepts touch events.
2476 if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
2477 d->allItemsIgnoreTouchEvents = false;
2478 d->enableTouchEventsOnViews();
2479 }
2480
2481#ifndef QT_NO_GESTURES
2482 for (auto it = item->d_ptr->gestureContext.constBegin();
2484 d->grabGesture(item, it.key());
2485#endif
2486
2487 // Update selection lists
2488 if (item->isSelected())
2489 d->selectedItems << item;
2490 if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
2491 d->addPopup(static_cast<QGraphicsWidget *>(item));
2493 d->enterModal(item);
2494
2495 // Update creation order focus chain. Make sure to leave the widget's
2496 // internal tab order intact.
2497 if (item->isWidget()) {
2498 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
2499 if (!d->tabFocusFirst) {
2500 // No first tab focus widget - make this the first tab focus
2501 // widget.
2502 d->tabFocusFirst = widget;
2503 } else if (!widget->parentWidget() && !widget->isPanel()) {
2504 // Adding a widget that is not part of a tab focus chain.
2505 QGraphicsWidget *myNewPrev = d->tabFocusFirst->d_func()->focusPrev;
2506 myNewPrev->d_func()->focusNext = widget;
2507 widget->d_func()->focusPrev->d_func()->focusNext = d->tabFocusFirst;
2508 d->tabFocusFirst->d_func()->focusPrev = widget->d_func()->focusPrev;
2509 widget->d_func()->focusPrev = myNewPrev;
2510 }
2511 }
2512
2513 // Add all children recursively
2515 for (auto child : std::as_const(item->d_ptr->children))
2516 addItem(child);
2517
2518 // Resolve font and palette.
2519 item->d_ptr->resolveFont(d->font.resolveMask());
2520 item->d_ptr->resolvePalette(d->palette.resolveMask());
2521
2522
2523 // Re-enable selectionChanged() for individual items
2524 --d->selectionChanging;
2525 if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
2527
2528 // Deliver post-change notification
2530
2531 // Update explicit activation
2532 bool autoActivate = true;
2533 if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
2534 d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
2535 if (d->childExplicitActivation && item->isPanel()) {
2536 if (d->childExplicitActivation == 1)
2538 else
2539 autoActivate = false;
2540 d->childExplicitActivation = 0;
2541 } else if (!item->d_ptr->parent) {
2542 d->childExplicitActivation = 0;
2543 }
2544
2545 // Auto-activate this item's panel if nothing else has been activated
2546 if (autoActivate) {
2547 if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
2548 if (isActive())
2550 else
2551 d->lastActivePanel = item;
2552 }
2553 }
2554
2556 d->registerScenePosItem(item);
2557
2558 // Ensure that newly added items that have subfocus set, gain
2559 // focus automatically if there isn't a focus item already.
2560 if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
2561 item->focusItem()->setFocus();
2562
2563 d->updateInputMethodSensitivityInViews();
2564}
2565
2582{
2584 item->setPen(pen);
2585 item->setBrush(brush);
2586 addItem(item);
2587 return item;
2588}
2589
2614{
2616 item->setPen(pen);
2617 addItem(item);
2618 return item;
2619}
2620
2645{
2647 item->setPen(pen);
2648 item->setBrush(brush);
2649 addItem(item);
2650 return item;
2651}
2652
2668{
2670 addItem(item);
2671 return item;
2672}
2673
2690 const QPen &pen, const QBrush &brush)
2691{
2693 item->setPen(pen);
2694 item->setBrush(brush);
2695 addItem(item);
2696 return item;
2697}
2698
2717{
2719 item->setPen(pen);
2720 item->setBrush(brush);
2721 addItem(item);
2722 return item;
2723}
2724
2748{
2750 item->setFont(font);
2751 addItem(item);
2752 return item;
2753}
2754
2770{
2772 item->setFont(font);
2773 addItem(item);
2774 return item;
2775}
2776
2796{
2797 QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(nullptr, wFlags);
2798 proxy->setWidget(widget);
2799 addItem(proxy);
2800 return proxy;
2801}
2802
2811{
2812 // ### Refactoring: This function shares much functionality with _q_removeItemLater()
2813 Q_D(QGraphicsScene);
2814 if (!item) {
2815 qWarning("QGraphicsScene::removeItem: cannot remove 0-item");
2816 return;
2817 }
2818 if (item->scene() != this) {
2819 qWarning("QGraphicsScene::removeItem: item %p's scene (%p)"
2820 " is different from this scene (%p)",
2821 item, item->scene(), this);
2822 return;
2823 }
2824
2825 // Notify the item that it's scene is changing to 0, allowing the item to
2826 // react.
2828 QVariant::fromValue<QGraphicsScene *>(0)));
2829 QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
2830 if (targetScene != nullptr && targetScene != this) {
2831 targetScene->addItem(item);
2832 return;
2833 }
2834
2835 d->removeItemHelper(item);
2836
2837 // Deliver post-change notification
2839
2840 d->updateInputMethodSensitivityInViews();
2841}
2842
2855{
2856 Q_D(const QGraphicsScene);
2857 return isActive() ? d->focusItem : d->passiveFocusItem;
2858}
2859
2877{
2878 Q_D(QGraphicsScene);
2879 if (item)
2880 item->setFocus(focusReason);
2881 else
2882 d->setFocusItemHelper(item, focusReason);
2883}
2884
2893{
2894 Q_D(const QGraphicsScene);
2895 return d->hasFocus;
2896}
2897
2909{
2910 Q_D(QGraphicsScene);
2911 if (d->hasFocus || !isActive())
2912 return;
2913 QFocusEvent event(QEvent::FocusIn, focusReason);
2915}
2916
2927{
2928 Q_D(QGraphicsScene);
2929 if (d->hasFocus) {
2930 d->hasFocus = false;
2931 d->passiveFocusItem = d->focusItem;
2933 }
2934}
2935
2955{
2956 Q_D(QGraphicsScene);
2957 d->stickyFocus = enabled;
2958}
2960{
2961 Q_D(const QGraphicsScene);
2962 return d->stickyFocus;
2963}
2964
2988{
2989 Q_D(const QGraphicsScene);
2990 return !d->mouseGrabberItems.isEmpty() ? d->mouseGrabberItems.last() : 0;
2991}
2992
3010{
3011 Q_D(const QGraphicsScene);
3012 return d->backgroundBrush;
3013}
3015{
3016 Q_D(QGraphicsScene);
3017 d->backgroundBrush = brush;
3018 for (QGraphicsView *view : std::as_const(d->views)) {
3019 view->resetCachedContent();
3020 view->viewport()->update();
3021 }
3022 update();
3023}
3024
3046{
3047 Q_D(const QGraphicsScene);
3048 return d->foregroundBrush;
3049}
3051{
3052 Q_D(QGraphicsScene);
3053 d->foregroundBrush = brush;
3054 const auto views_ = views();
3055 for (QGraphicsView *view : views_)
3056 view->viewport()->update();
3057 update();
3058}
3059
3070{
3071 Q_D(const QGraphicsScene);
3072 if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
3073 return QVariant();
3074 const QTransform matrix = d->focusItem->sceneTransform();
3075 QVariant value = d->focusItem->inputMethodQuery(query);
3076 if (value.userType() == QMetaType::QRectF)
3077 value = matrix.mapRect(value.toRectF());
3078 else if (value.userType() == QMetaType::QPointF)
3079 value = matrix.map(value.toPointF());
3080 else if (value.userType() == QMetaType::QRect)
3081 value = matrix.mapRect(value.toRect());
3082 else if (value.userType() == QMetaType::QPoint)
3083 value = matrix.map(value.toPoint());
3084 return value;
3085}
3086
3094{
3095 Q_D(QGraphicsScene);
3096 if (d->updateAll || (rect.isEmpty() && !rect.isNull()))
3097 return;
3098
3099 // Check if anyone's connected; if not, we can send updates directly to
3100 // the views. Otherwise or if there are no views, use old behavior.
3101 bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty();
3102 if (rect.isNull()) {
3103 d->updateAll = true;
3104 d->updatedRects.clear();
3105 if (directUpdates) {
3106 // Update all views.
3107 for (auto view : std::as_const(d->views))
3108 view->d_func()->fullUpdatePending = true;
3109 }
3110 } else {
3111 if (directUpdates) {
3112 // Update all views.
3113 for (auto view : std::as_const(d->views)) {
3114 if (view->isTransformed())
3115 view->d_func()->updateRectF(view->viewportTransform().mapRect(rect));
3116 else
3117 view->d_func()->updateRectF(rect);
3118 }
3119 } else {
3120 d->updatedRects.insert(rect);
3121 }
3122 }
3123
3124 if (!d->calledEmitUpdated) {
3125 d->calledEmitUpdated = true;
3126 QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
3127 }
3128}
3129
3161{
3162 const auto views_ = views();
3163 for (QGraphicsView *view : views_)
3164 view->invalidateScene(rect, layers);
3165 update(rect);
3166}
3167
3182QList <QGraphicsView *> QGraphicsScene::views() const
3183{
3184 Q_D(const QGraphicsScene);
3185 return d->views;
3186}
3187
3202{
3203 for (int i = 0; i < 2; ++i) {
3204 const auto items_ = items();
3205 for (QGraphicsItem *item : items_)
3206 item->advance(i);
3207 }
3208}
3209
3232{
3233 Q_D(QGraphicsScene);
3234
3235 switch (event->type()) {
3243 case QEvent::TouchBegin:
3245 case QEvent::TouchEnd:
3246 // Reset the under-mouse list to ensure that this event gets fresh
3247 // item-under-mouse data. Be careful about this list; if people delete
3248 // items from inside event handlers, this list can quickly end up
3249 // having stale pointers in it. We need to clear it before dispatching
3250 // events that use it.
3251 // ### this should only be cleared if we received a new mouse move event,
3252 // which relies on us fixing the replay mechanism in QGraphicsView.
3253 d->cachedItemsUnderMouse.clear();
3254 default:
3255 break;
3256 }
3257
3258 switch (event->type()) {
3261 break;
3264 break;
3267 break;
3270 break;
3273 break;
3274 case QEvent::KeyPress:
3275 if (!d->focusItem) {
3276 QKeyEvent *k = static_cast<QKeyEvent *>(event);
3277 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
3278 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
3279 bool res = false;
3280 if (k->key() == Qt::Key_Backtab
3281 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
3282 res = focusNextPrevChild(false);
3283 } else if (k->key() == Qt::Key_Tab) {
3284 res = focusNextPrevChild(true);
3285 }
3286 if (!res)
3287 event->ignore();
3288 return true;
3289 }
3290 }
3291 }
3292 keyPressEvent(static_cast<QKeyEvent *>(event));
3293 break;
3294 case QEvent::KeyRelease:
3295 keyReleaseEvent(static_cast<QKeyEvent *>(event));
3296 break;
3299 while (parent) {
3300 d->sendEvent(parent, event);
3301 if (event->isAccepted())
3302 return true;
3303 parent = parent->parentItem();
3304 }
3305 }
3306 return false;
3308 {
3309 QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
3310 d->lastSceneMousePos = mouseEvent->scenePos();
3311 mouseMoveEvent(mouseEvent);
3312 break;
3313 }
3316 break;
3319 break;
3322 break;
3324 wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event));
3325 break;
3326 case QEvent::FocusIn:
3327 focusInEvent(static_cast<QFocusEvent *>(event));
3328 break;
3329 case QEvent::FocusOut:
3330 focusOutEvent(static_cast<QFocusEvent *>(event));
3331 break;
3335 {
3336 QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
3337 d->lastSceneMousePos = hoverEvent->scenePos();
3338 d->dispatchHoverEvent(hoverEvent);
3339 break;
3340 }
3341 case QEvent::Leave:
3342 Q_ASSERT_X(false, "QGraphicsScene::event",
3343 "QGraphicsScene must not receive QEvent::Leave, use GraphicsSceneLeave");
3344 break;
3346 {
3347 auto *leaveEvent = static_cast<QGraphicsSceneEvent*>(event);
3348 d->leaveScene(leaveEvent->widget());
3349 break;
3350 }
3352 helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event));
3353 break;
3355 inputMethodEvent(static_cast<QInputMethodEvent *>(event));
3356 break;
3358 if (!d->activationRefCount++) {
3359 if (d->lastActivePanel) {
3360 // Activate the last panel.
3361 d->setActivePanelHelper(d->lastActivePanel, true);
3362 } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
3363 // Activate the panel of the first item in the tab focus
3364 // chain.
3365 d->setActivePanelHelper(d->tabFocusFirst, true);
3366 } else {
3367 // Activate all toplevel items.
3369 const auto items_ = items();
3370 for (QGraphicsItem *item : items_) {
3371 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3372 sendEvent(item, &event);
3373 }
3374 }
3375 }
3376 break;
3378 if (!--d->activationRefCount) {
3379 if (d->activePanel) {
3380 // Deactivate the active panel (but keep it so we can
3381 // reactivate it later).
3382 QGraphicsItem *lastActivePanel = d->activePanel;
3383 d->setActivePanelHelper(nullptr, true);
3384 d->lastActivePanel = lastActivePanel;
3385 } else {
3386 // Activate all toplevel items.
3388 const auto items_ = items();
3389 for (QGraphicsItem *item : items_) {
3390 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3391 sendEvent(item, &event);
3392 }
3393 }
3394 }
3395 break;
3397 // Resolve the existing scene font.
3398 d->resolveFont();
3399 break;
3400 }
3401 case QEvent::FontChange:
3402 // Update the entire scene when the font changes.
3403 update();
3404 break;
3406 // Resolve the existing scene palette.
3407 d->resolvePalette();
3408 break;
3409 }
3411 // Update the entire scene when the palette changes.
3412 update();
3413 break;
3415 // Reresolve all widgets' styles. Update all top-level widgets'
3416 // geometries that do not have an explicit style set.
3417 update();
3418 break;
3420 // Because QGraphicsItem is not a QObject, QStyle driven
3421 // animations are forced to update the whole scene
3422 update();
3423 break;
3424 case QEvent::TouchBegin:
3426 case QEvent::TouchEnd:
3427 d->touchEventHandler(static_cast<QTouchEvent *>(event));
3428 break;
3429#ifndef QT_NO_GESTURES
3430 case QEvent::Gesture:
3432 d->gestureEventHandler(static_cast<QGestureEvent *>(event));
3433 break;
3434#endif // QT_NO_GESTURES
3435 default:
3436 return QObject::event(event);
3437 }
3438 return true;
3439}
3440
3448{
3449 if (watched != qApp)
3450 return false;
3451
3452 switch (event->type()) {
3455 break;
3458 break;
3459 default:
3460 break;
3461 }
3462 return false;
3463}
3464
3477{
3478 Q_D(QGraphicsScene);
3479 // Ignore by default.
3480 contextMenuEvent->ignore();
3481
3482 // Send the event to all items at this position until one item accepts the
3483 // event.
3484 const auto items = d->itemsAtPosition(contextMenuEvent->screenPos(),
3485 contextMenuEvent->scenePos(),
3486 contextMenuEvent->widget());
3487 for (QGraphicsItem *item : items) {
3489 contextMenuEvent->widget()));
3490 contextMenuEvent->accept();
3491 if (!d->sendEvent(item, contextMenuEvent))
3492 break;
3493
3494 if (contextMenuEvent->isAccepted())
3495 break;
3496 }
3497}
3498
3510{
3511 Q_D(QGraphicsScene);
3512 d->dragDropItem = nullptr;
3513 d->lastDropAction = Qt::IgnoreAction;
3514 event->accept();
3515}
3516
3527{
3528 Q_D(QGraphicsScene);
3529 event->ignore();
3530
3531 if (!d->mouseGrabberItems.isEmpty()) {
3532 // Mouse grabbers that start drag events lose the mouse grab.
3533 d->clearMouseGrabber();
3534 d->mouseGrabberButtonDownPos.clear();
3535 d->mouseGrabberButtonDownScenePos.clear();
3536 d->mouseGrabberButtonDownScreenPos.clear();
3537 }
3538
3539 bool eventDelivered = false;
3540
3541 // Find the topmost enabled items under the cursor. They are all
3542 // candidates for accepting drag & drop events.
3543 const auto items = d->itemsAtPosition(event->screenPos(),
3544 event->scenePos(),
3545 event->widget());
3546 for (QGraphicsItem *item : items) {
3547 if (!item->isEnabled() || !item->acceptDrops())
3548 continue;
3549
3550 if (item != d->dragDropItem) {
3551 // Enter the new drag drop item. If it accepts the event, we send
3552 // the leave to the parent item.
3554 d->cloneDragDropEvent(&dragEnter, event);
3555 dragEnter.setDropAction(event->proposedAction());
3556 d->sendDragDropEvent(item, &dragEnter);
3557 event->setAccepted(dragEnter.isAccepted());
3558 event->setDropAction(dragEnter.dropAction());
3559 if (!event->isAccepted()) {
3560 // Propagate to the item under
3561 continue;
3562 }
3563
3564 d->lastDropAction = event->dropAction();
3565
3566 if (d->dragDropItem) {
3567 // Leave the last drag drop item. A perfect implementation
3568 // would set the position of this event to the point where
3569 // this event and the last event intersect with the item's
3570 // shape, but that's not easy to do. :-)
3572 d->cloneDragDropEvent(&dragLeave, event);
3573 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3574 }
3575
3576 // We've got a new drag & drop item
3577 d->dragDropItem = item;
3578 }
3579
3580 // Send the move event.
3581 event->setDropAction(d->lastDropAction);
3582 event->accept();
3583 d->sendDragDropEvent(item, event);
3584 if (event->isAccepted())
3585 d->lastDropAction = event->dropAction();
3586 eventDelivered = true;
3587 break;
3588 }
3589
3590 if (!eventDelivered) {
3591 if (d->dragDropItem) {
3592 // Leave the last drag drop item
3594 d->cloneDragDropEvent(&dragLeave, event);
3595 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3596 d->dragDropItem = nullptr;
3597 }
3598 // Propagate
3599 event->setDropAction(Qt::IgnoreAction);
3600 }
3601}
3602
3611{
3612 Q_D(QGraphicsScene);
3613 if (d->dragDropItem) {
3614 // Leave the last drag drop item
3615 d->sendDragDropEvent(d->dragDropItem, event);
3616 d->dragDropItem = nullptr;
3617 }
3618}
3619
3628{
3629 Q_UNUSED(event);
3630 Q_D(QGraphicsScene);
3631 if (d->dragDropItem) {
3632 // Drop on the last drag drop item
3633 d->sendDragDropEvent(d->dragDropItem, event);
3634 d->dragDropItem = nullptr;
3635 }
3636}
3637
3648{
3649 Q_D(QGraphicsScene);
3650
3651 d->hasFocus = true;
3652 switch (focusEvent->reason()) {
3653 case Qt::TabFocusReason:
3654 if (!focusNextPrevChild(true))
3655 focusEvent->ignore();
3656 break;
3658 if (!focusNextPrevChild(false))
3659 focusEvent->ignore();
3660 break;
3661 default:
3662 if (d->passiveFocusItem) {
3663 // Set focus on the last focus item
3664 setFocusItem(d->passiveFocusItem, focusEvent->reason());
3665 }
3666 break;
3667 }
3668}
3669
3680{
3681 Q_D(QGraphicsScene);
3682 d->hasFocus = false;
3683 d->passiveFocusItem = d->focusItem;
3684 setFocusItem(nullptr, focusEvent->reason());
3685
3686 // Remove all popups when the scene loses focus.
3687 if (!d->popupWidgets.isEmpty())
3688 d->removePopup(d->popupWidgets.constFirst());
3689}
3690
3707{
3708#if !QT_CONFIG(tooltip)
3710#else
3711 // Find the first item that does tooltips
3712 Q_D(QGraphicsScene);
3713 const QList<QGraphicsItem *> itemsAtPos = d->itemsAtPosition(helpEvent->screenPos(),
3714 helpEvent->scenePos(),
3715 helpEvent->widget());
3716 QGraphicsItem *toolTipItem = nullptr;
3717 for (auto item : itemsAtPos) {
3718 if (item->d_func()->isProxyWidget()) {
3719 // if the item is a proxy widget, the event is forwarded to it
3721 if (helpEvent->isAccepted())
3722 return;
3723 }
3724 if (!item->toolTip().isEmpty()) {
3725 toolTipItem = item;
3726 break;
3727 }
3728 }
3729
3730 // Show or hide the tooltip
3731 QString text;
3732 QPoint point;
3733 if (toolTipItem && !toolTipItem->toolTip().isEmpty()) {
3734 text = toolTipItem->toolTip();
3735 point = helpEvent->screenPos();
3736 }
3737 QToolTip::showText(point, text, helpEvent->widget());
3738 helpEvent->setAccepted(!text.isEmpty());
3739#endif
3740}
3741
3743{
3744 return (item->d_ptr->acceptsHover
3745 || (item->d_ptr->isWidget
3746 && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))
3748}
3749
3761{
3763 return false;
3764
3765 // Find the first item that accepts hover events, reusing earlier
3766 // calculated data is possible.
3769 hoverEvent->scenePos(),
3770 hoverEvent->widget());
3771 }
3772
3773 QGraphicsItem *item = nullptr;
3774 for (auto tmp : std::as_const(cachedItemsUnderMouse)) {
3776 item = tmp;
3777 break;
3778 }
3779 }
3780
3781 // Find the common ancestor item for the new topmost hoverItem and the
3782 // last item in the hoverItem list.
3783 QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.constLast()) : nullptr;
3784 while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
3785 commonAncestorItem = commonAncestorItem->parentItem();
3786 if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
3787 // The common ancestor isn't in the same panel as the two hovered
3788 // items.
3789 commonAncestorItem = nullptr;
3790 }
3791
3792 // Check if the common ancestor item is known.
3793 int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
3794 // Send hover leaves to any existing hovered children of the common
3795 // ancestor item.
3796 for (int i = hoverItems.size() - 1; i > index; --i) {
3797 QGraphicsItem *lastItem = hoverItems.takeLast();
3798 if (itemAcceptsHoverEvents_helper(lastItem))
3799 sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
3800 }
3801
3802 // Item is a child of a known item. Generate enter events for the
3803 // missing links.
3804 QList<QGraphicsItem *> parents;
3806 while (parent && parent != commonAncestorItem) {
3807 parents.append(parent);
3808 if (parent->isPanel()) {
3809 // Stop at the panel - we don't deliver beyond this point.
3810 break;
3811 }
3812 parent = parent->parentItem();
3813 }
3814 for (auto it = parents.crbegin(), end = parents.crend(); it != end; ++it) {
3816 hoverItems << parent;
3819 }
3820
3821 // Generate a move event for the item itself
3822 if (item
3823 && !hoverItems.isEmpty()
3824 && item == hoverItems.constLast()) {
3826 return true;
3827 }
3828 return false;
3829}
3830
3838{
3839#if QT_CONFIG(tooltip)
3841#endif
3842 QGraphicsView *view = qobject_cast<QGraphicsView *>(viewport->parent());
3843 // Send HoverLeave events to all existing hover items, topmost first.
3844 QGraphicsSceneHoverEvent hoverEvent;
3845 hoverEvent.setWidget(viewport);
3846
3847 if (view) {
3848 QPoint cursorPos = QCursor::pos();
3849 hoverEvent.setScenePos(view->mapToScene(viewport->mapFromGlobal(cursorPos)));
3850 hoverEvent.setLastScenePos(hoverEvent.scenePos());
3851 hoverEvent.setScreenPos(cursorPos);
3852 hoverEvent.setLastScreenPos(hoverEvent.screenPos());
3853 }
3854
3855 while (!hoverItems.isEmpty()) {
3856 QGraphicsItem *lastItem = hoverItems.takeLast();
3857 if (itemAcceptsHoverEvents_helper(lastItem))
3858 sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent);
3859 }
3860}
3861
3870{
3871 // ### Merge this function with keyReleaseEvent; they are identical
3872 // ### (except this comment).
3873 Q_D(QGraphicsScene);
3874 QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.constLast() : 0;
3875 if (!item)
3876 item = focusItem();
3877 if (item) {
3878 QGraphicsItem *p = item;
3879 do {
3880 // Accept the event by default
3881 keyEvent->accept();
3882 // Send it; QGraphicsItem::keyPressEvent ignores it. If the event
3883 // is filtered out, stop propagating it.
3884 if (p->isBlockedByModalPanel())
3885 break;
3886 if (!d->sendEvent(p, keyEvent))
3887 break;
3888 } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
3889 } else {
3890 keyEvent->ignore();
3891 }
3892}
3893
3902{
3903 // ### Merge this function with keyPressEvent; they are identical (except
3904 // ### this comment).
3905 Q_D(QGraphicsScene);
3906 QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.constLast() : 0;
3907 if (!item)
3908 item = focusItem();
3909 if (item) {
3910 QGraphicsItem *p = item;
3911 do {
3912 // Accept the event by default
3913 keyEvent->accept();
3914 // Send it; QGraphicsItem::keyPressEvent ignores it. If the event
3915 // is filtered out, stop propagating it.
3916 if (p->isBlockedByModalPanel())
3917 break;
3918 if (!d->sendEvent(p, keyEvent))
3919 break;
3920 } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
3921 } else {
3922 keyEvent->ignore();
3923 }
3924}
3925
3946{
3947 Q_D(QGraphicsScene);
3948 if (d->mouseGrabberItems.isEmpty()) {
3949 // Dispatch hover events
3951 _q_hoverFromMouseEvent(&hover, mouseEvent);
3952 d->dispatchHoverEvent(&hover);
3953 }
3954
3955 d->mousePressEventHandler(mouseEvent);
3956}
3957
3971{
3972 Q_D(QGraphicsScene);
3973 if (d->mouseGrabberItems.isEmpty()) {
3974 if (mouseEvent->buttons())
3975 return;
3977 _q_hoverFromMouseEvent(&hover, mouseEvent);
3978 mouseEvent->setAccepted(d->dispatchHoverEvent(&hover));
3979 return;
3980 }
3981
3982 // Forward the event to the mouse grabber
3983 d->sendMouseEvent(mouseEvent);
3984 mouseEvent->accept();
3985}
3986
4001{
4002 Q_D(QGraphicsScene);
4003 if (d->mouseGrabberItems.isEmpty()) {
4004 mouseEvent->ignore();
4005 return;
4006 }
4007
4008 // Forward the event to the mouse grabber
4009 d->sendMouseEvent(mouseEvent);
4010 mouseEvent->accept();
4011
4012 // Reset the mouse grabber when the last mouse button has been released.
4013 if (!mouseEvent->buttons()) {
4014 if (!d->mouseGrabberItems.isEmpty()) {
4015 d->lastMouseGrabberItem = d->mouseGrabberItems.constLast();
4016 if (d->lastMouseGrabberItemHasImplicitMouseGrab)
4017 d->mouseGrabberItems.constLast()->ungrabMouse();
4018 } else {
4019 d->lastMouseGrabberItem = nullptr;
4020 }
4021
4022 // Generate a hoverevent
4023 QGraphicsSceneHoverEvent hoverEvent;
4024 _q_hoverFromMouseEvent(&hoverEvent, mouseEvent);
4025 d->dispatchHoverEvent(&hoverEvent);
4026 }
4027}
4028
4049{
4050 Q_D(QGraphicsScene);
4051 d->mousePressEventHandler(mouseEvent);
4052}
4053
4068{
4069 Q_D(QGraphicsScene);
4070 const QList<QGraphicsItem *> wheelCandidates = d->itemsAtPosition(wheelEvent->screenPos(),
4071 wheelEvent->scenePos(),
4072 wheelEvent->widget());
4073
4074 // Find the first popup under the mouse (including the popup's descendants) starting from the last.
4075 // Remove all popups after the one found, or all or them if no popup is under the mouse.
4076 // Then continue with the event.
4077 QList<QGraphicsWidget *>::const_iterator iter = d->popupWidgets.constEnd();
4078 while (iter > d->popupWidgets.constBegin() && !wheelCandidates.isEmpty()) {
4079 --iter;
4080 if (wheelCandidates.first() == *iter || (*iter)->isAncestorOf(wheelCandidates.first()))
4081 break;
4082 d->removePopup(*iter);
4083 }
4084
4085 bool hasSetFocus = false;
4086 for (QGraphicsItem *item : wheelCandidates) {
4087 if (!hasSetFocus && item->isEnabled()
4089 if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
4090 hasSetFocus = true;
4091 if (item != focusItem())
4093 }
4094 }
4095
4096 wheelEvent->setPos(item->d_ptr->genericMapFromScene(wheelEvent->scenePos(),
4097 wheelEvent->widget()));
4098 wheelEvent->accept();
4099 bool isPanel = item->isPanel();
4100 bool ret = d->sendEvent(item, wheelEvent);
4101
4102 if (ret && (isPanel || wheelEvent->isAccepted()))
4103 break;
4104 }
4105}
4106
4118{
4119 Q_D(QGraphicsScene);
4120 if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
4121 d->sendEvent(d->focusItem, event);
4122 return;
4123 }
4124 if (d->lastFocusItem && d->lastFocusItem != d->focusItem && (d->lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
4125 d->sendEvent(d->lastFocusItem, event);
4126}
4127
4142{
4143 Q_D(QGraphicsScene);
4144
4145 if (d->backgroundBrush.style() != Qt::NoBrush) {
4146 if (d->painterStateProtection)
4147 painter->save();
4148 painter->setBrushOrigin(0, 0);
4150 if (d->painterStateProtection)
4151 painter->restore();
4152 }
4153}
4154
4169{
4170 Q_D(QGraphicsScene);
4171
4172 if (d->foregroundBrush.style() != Qt::NoBrush) {
4173 if (d->painterStateProtection)
4174 painter->save();
4175 painter->setBrushOrigin(0, 0);
4177 if (d->painterStateProtection)
4178 painter->restore();
4179 }
4180}
4181
4184 bool useWindowOpacity, bool painterStateProtection)
4185{
4186 if (!item->isWidget()) {
4188 return;
4189 }
4190 QGraphicsWidget *widgetItem = static_cast<QGraphicsWidget *>(item);
4191 QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(widgetItem);
4192 const qreal windowOpacity = (proxy && proxy->widget() && useWindowOpacity)
4193 ? proxy->widget()->windowOpacity() : 1.0;
4194 const qreal oldPainterOpacity = painter->opacity();
4195
4196 if (qFuzzyIsNull(windowOpacity))
4197 return;
4198 // Set new painter opacity.
4199 if (windowOpacity < 1.0)
4200 painter->setOpacity(oldPainterOpacity * windowOpacity);
4201
4202 // set layoutdirection on the painter
4203 Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
4205
4206 if (widgetItem->isWindow() && widgetItem->windowType() != Qt::Popup && widgetItem->windowType() != Qt::ToolTip
4207 && !(widgetItem->windowFlags() & Qt::FramelessWindowHint)) {
4208 if (painterStateProtection)
4209 painter->save();
4210 widgetItem->paintWindowFrame(painter, option, widget);
4211 if (painterStateProtection)
4212 painter->restore();
4213 } else if (widgetItem->autoFillBackground()) {
4214 painter->fillRect(option->exposedRect, widgetItem->palette().window());
4215 }
4216
4217 widgetItem->paint(painter, option, widget);
4218
4219 // Restore layoutdirection on the painter.
4220 painter->setLayoutDirection(oldLayoutDirection);
4221 // Restore painter opacity.
4222 if (windowOpacity < 1.0)
4223 painter->setOpacity(oldPainterOpacity);
4224}
4225
4226static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &pixmapExposed,
4227 const QTransform &itemToPixmap, QPainter::RenderHints renderHints,
4228 const QStyleOptionGraphicsItem *option, bool painterStateProtection)
4229{
4230 QPixmap subPix;
4231 QPainter pixmapPainter;
4232 QRect br = pixmapExposed.boundingRect();
4233
4234 // Don't use subpixmap if we get a full update.
4235 if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) {
4237 pixmapPainter.begin(pix);
4238 } else {
4239 subPix = QPixmap(br.size() * pix->devicePixelRatio());
4241 subPix.fill(Qt::transparent);
4242 pixmapPainter.begin(&subPix);
4243 pixmapPainter.translate(-br.topLeft());
4244 if (!pixmapExposed.isEmpty()) {
4245 // Applied to subPix; paint is adjusted to the coordinate space is
4246 // correct.
4247 pixmapPainter.setClipRegion(pixmapExposed);
4248 }
4249 }
4250
4251 pixmapPainter.setRenderHints(pixmapPainter.renderHints(), false);
4252 pixmapPainter.setRenderHints(renderHints, true);
4253 pixmapPainter.setWorldTransform(itemToPixmap, true);
4254
4255 // Render.
4256 _q_paintItem(item, &pixmapPainter, option, nullptr, false, painterStateProtection);
4257 pixmapPainter.end();
4258
4259 if (!subPix.isNull()) {
4260 // Blit the subpixmap into the main pixmap.
4261 pixmapPainter.begin(pix);
4263 pixmapPainter.setClipRegion(pixmapExposed);
4264 pixmapPainter.drawPixmap(br.topLeft(), subPix);
4265 pixmapPainter.end();
4266 }
4267}
4268
4269// Copied from qpaintengine_vg.cpp
4270// Returns \c true for 90, 180, and 270 degree rotations.
4271static inline bool transformIsSimple(const QTransform& transform)
4272{
4274 if (type <= QTransform::TxScale) {
4275 return true;
4276 } else if (type == QTransform::TxRotate) {
4277 // Check for 90, and 270 degree rotations.
4278 qreal m11 = transform.m11();
4279 qreal m12 = transform.m12();
4280 qreal m21 = transform.m21();
4281 qreal m22 = transform.m22();
4282 if (m11 == 0.0f && m22 == 0.0f) {
4283 if (m12 == 1.0f && m21 == -1.0f)
4284 return true; // 90 degrees.
4285 else if (m12 == -1.0f && m21 == 1.0f)
4286 return true; // 270 degrees.
4287 else if (m12 == -1.0f && m21 == -1.0f)
4288 return true; // 90 degrees inverted y.
4289 else if (m12 == 1.0f && m21 == 1.0f)
4290 return true; // 270 degrees inverted y.
4291 }
4292 }
4293 return false;
4294}
4295
4303 bool painterStateProtection)
4304{
4305 QGraphicsItemPrivate *itemd = item->d_ptr.data();
4307
4308 // Render directly, using no cache.
4309 if (cacheMode == QGraphicsItem::NoCache) {
4311 return;
4312 }
4313
4314 const qreal devicePixelRatio = painter->device()->devicePixelRatio();
4315 const qreal oldPainterOpacity = painter->opacity();
4316 qreal newPainterOpacity = oldPainterOpacity;
4317 QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(item)) : 0;
4318 if (proxy && proxy->widget()) {
4319 const qreal windowOpacity = proxy->widget()->windowOpacity();
4320 if (windowOpacity < 1.0)
4321 newPainterOpacity *= windowOpacity;
4322 }
4323
4324 // Item's (local) bounding rect
4325 QRectF brect = item->boundingRect();
4326 QRectF adjustedBrect(brect);
4327 _q_adjustRect(&adjustedBrect);
4328 if (adjustedBrect.isEmpty())
4329 return;
4330
4331 // Fetch the off-screen transparent buffer and exposed area info.
4332 QPixmapCache::Key pixmapKey;
4333 QPixmap pix;
4334
4335 bool pixmapFound;
4336 QGraphicsItemCache *itemCache = itemd->extraItemCache();
4337 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4338 pixmapKey = itemCache->key;
4339 } else {
4340 pixmapKey = itemCache->deviceData.value(widget).key;
4341 }
4342
4343 // Find pixmap in cache.
4344 pixmapFound = QPixmapCache::find(pixmapKey, &pix);
4345
4346 // Render using item coordinate cache mode.
4347 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4348 QSize pixmapSize;
4349 bool fixedCacheSize = itemCache->fixedSize.isValid();
4350 QRect br = brect.toAlignedRect();
4351 if (fixedCacheSize) {
4352 pixmapSize = itemCache->fixedSize;
4353 } else {
4354 pixmapSize = br.size();
4355 }
4356
4357 pixmapSize *= devicePixelRatio;
4358
4359 // Create or recreate the pixmap.
4360 int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
4361 QSize adjustSize(adjust*2, adjust*2);
4362 br.adjust(-adjust / devicePixelRatio, -adjust / devicePixelRatio, adjust / devicePixelRatio, adjust / devicePixelRatio);
4363 if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
4364 pix = QPixmap(pixmapSize + adjustSize);
4365 itemCache->boundingRect = br;
4366 itemCache->exposed.clear();
4367 itemCache->allExposed = true;
4368 } else if (itemCache->boundingRect != br) {
4369 itemCache->boundingRect = br;
4370 itemCache->exposed.clear();
4371 itemCache->allExposed = true;
4372 }
4373
4374 // Redraw any newly exposed areas.
4375 if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
4376
4377 //We know that we will modify the pixmap, removing it from the cache
4378 //will detach the one we have and avoid a deep copy
4379 if (pixmapFound)
4380 QPixmapCache::remove(pixmapKey);
4381
4382 // Fit the item's bounding rect into the pixmap's coordinates.
4383 QTransform itemToPixmap;
4384 if (fixedCacheSize) {
4385 const QPointF scale((pixmapSize.width() / devicePixelRatio) / brect.width(),
4386 (pixmapSize.height() / devicePixelRatio) / brect.height());
4387 itemToPixmap.scale(scale.x(), scale.y());
4388 }
4389 itemToPixmap.translate(-br.x(), -br.y());
4390
4391 // Generate the item's exposedRect and map its list of expose
4392 // rects to device coordinates.
4394 QRegion pixmapExposed;
4395 QRectF exposedRect;
4396 if (!itemCache->allExposed) {
4397 for (const auto &rect : std::as_const(itemCache->exposed)) {
4398 exposedRect |= rect;
4399 pixmapExposed += itemToPixmap.mapRect(rect).toAlignedRect();
4400 }
4401 } else {
4402 exposedRect = brect;
4403 }
4404 styleOptionTmp.exposedRect = exposedRect;
4405
4406 // Render.
4407 pix.setDevicePixelRatio(devicePixelRatio);
4408 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4410
4411 // insert this pixmap into the cache.
4412 itemCache->key = QPixmapCache::insert(pix);
4413
4414 // Reset expose data.
4415 itemCache->allExposed = false;
4416 itemCache->exposed.clear();
4417 }
4418
4419 // Redraw the exposed area using the transformed painter. Depending on
4420 // the hardware, this may be a server-side operation, or an expensive
4421 // qpixmap-image-transform-pixmap roundtrip.
4422 if (newPainterOpacity != oldPainterOpacity) {
4423 painter->setOpacity(newPainterOpacity);
4424 painter->drawPixmap(br.topLeft(), pix);
4425 painter->setOpacity(oldPainterOpacity);
4426 } else {
4427 painter->drawPixmap(br.topLeft(), pix);
4428 }
4429 return;
4430 }
4431
4432 // Render using device coordinate cache mode.
4433 if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
4434 // Find the item's bounds in device coordinates.
4435 QRectF deviceBounds = painter->worldTransform().mapRect(brect);
4436 QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
4437 if (deviceRect.isEmpty())
4438 return;
4439 QRect viewRect = widget ? widget->rect() : QRect();
4440 if (widget && !viewRect.intersects(deviceRect))
4441 return;
4442
4443 // Resort to direct rendering if the device rect exceeds the
4444 // (optional) maximum bounds. (QGraphicsSvgItem uses this).
4445 QSize maximumCacheSize =
4447 if (!maximumCacheSize.isEmpty()
4448 && (deviceRect.width() > maximumCacheSize.width()
4449 || deviceRect.height() > maximumCacheSize.height())) {
4451 oldPainterOpacity != newPainterOpacity, painterStateProtection);
4452 return;
4453 }
4454
4455 // Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
4456 // If the world transform is rotated we always recreate the cache to avoid
4457 // wrong blending.
4458 bool pixModified = false;
4459 QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
4460 bool invertable = true;
4461 QTransform diff = deviceData->lastTransform.inverted(&invertable);
4462 if (invertable)
4463 diff *= painter->worldTransform();
4464 deviceData->lastTransform = painter->worldTransform();
4465 bool allowPartialCacheExposure = false;
4466 bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
4468 if (!simpleTransform) {
4469 pixModified = true;
4470 itemCache->allExposed = true;
4471 itemCache->exposed.clear();
4472 deviceData->cacheIndent = QPoint();
4473 pix = QPixmap();
4474 } else if (!viewRect.isNull()) {
4475 allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
4476 }
4477
4478 // Allow partial cache exposure if the device rect isn't fully contained and
4479 // deviceRect is 20% taller or wider than the viewRect.
4480 if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
4481 allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
4482 || (viewRect.height() * 1.2 < deviceRect.height());
4483 }
4484
4485 QRegion scrollExposure;
4486 if (allowPartialCacheExposure) {
4487 // Part of pixmap is drawn. Either device contains viewrect (big
4488 // item covers whole screen) or parts of device are outside the
4489 // viewport. In either case the device rect must be the intersect
4490 // between the two.
4491 int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
4492 int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
4493 QPoint newCacheIndent(dx, dy);
4494 deviceRect &= viewRect;
4495
4496 if (pix.isNull()) {
4497 deviceData->cacheIndent = QPoint();
4498 itemCache->allExposed = true;
4499 itemCache->exposed.clear();
4500 pixModified = true;
4501 }
4502
4503 // Copy / "scroll" the old pixmap onto the new ole and calculate
4504 // scrolled exposure.
4505 if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size() / devicePixelRatio) {
4506 QPoint diff = newCacheIndent - deviceData->cacheIndent;
4507 QPixmap newPix(deviceRect.size() * devicePixelRatio);
4508 // ### Investigate removing this fill (test with Plasma and
4509 // graphicssystem raster).
4510 newPix.fill(Qt::transparent);
4511 if (!pix.isNull()) {
4512 newPix.setDevicePixelRatio(devicePixelRatio);
4513 QPainter newPixPainter(&newPix);
4514 newPixPainter.drawPixmap(-diff, pix);
4515 newPixPainter.end();
4516 }
4517 QRegion exposed;
4518 exposed += QRect(QPoint(0,0), newPix.size() / devicePixelRatio);
4519 if (!pix.isNull())
4520 exposed -= QRect(-diff, pix.size() / devicePixelRatio);
4521 scrollExposure = exposed;
4522
4523 pix = newPix;
4524 pixModified = true;
4525 }
4526 deviceData->cacheIndent = newCacheIndent;
4527 } else {
4528 // Full pixmap is drawn.
4529 deviceData->cacheIndent = QPoint();
4530
4531 // Auto-adjust the pixmap size.
4532 if (deviceRect.size() != pix.size() / devicePixelRatio) {
4533 // exposed needs to cover the whole pixmap
4534 pix = QPixmap(deviceRect.size() * devicePixelRatio);
4535 pixModified = true;
4536 itemCache->allExposed = true;
4537 itemCache->exposed.clear();
4538 }
4539 }
4540
4541 // Check for newly invalidated areas.
4542 if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
4543 //We know that we will modify the pixmap, removing it from the cache
4544 //will detach the one we have and avoid a deep copy
4545 if (pixmapFound)
4546 QPixmapCache::remove(pixmapKey);
4547
4548 // Construct an item-to-pixmap transform.
4550 QTransform itemToPixmap = painter->worldTransform();
4551 if (!p.isNull())
4552 itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
4553
4554 // Map the item's logical expose to pixmap coordinates.
4555 QRegion pixmapExposed = scrollExposure;
4556 if (!itemCache->allExposed) {
4557 for (const auto &rect : std::as_const(itemCache->exposed))
4558 pixmapExposed += itemToPixmap.mapRect(rect).toRect().adjusted(-1, -1, 1, 1);
4559 }
4560
4561 // Calculate the style option's exposedRect.
4562 QRectF br;
4563 if (itemCache->allExposed) {
4564 br = item->boundingRect();
4565 } else {
4566 for (const auto &rect : std::as_const(itemCache->exposed))
4567 br |= rect;
4568 QTransform pixmapToItem = itemToPixmap.inverted();
4569 for (const QRect &r : std::as_const(scrollExposure))
4570 br |= pixmapToItem.mapRect(r);
4571 }
4573 styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
4574
4575 // Render the exposed areas.
4576 pix.setDevicePixelRatio(devicePixelRatio);
4577 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4579
4580 // Reset expose data.
4581 pixModified = true;
4582 itemCache->allExposed = false;
4583 itemCache->exposed.clear();
4584 }
4585
4586 if (pixModified) {
4587 // Insert this pixmap into the cache.
4588 deviceData->key = QPixmapCache::insert(pix);
4589 }
4590
4591 // Redraw the exposed area using an untransformed painter. This
4592 // effectively becomes a bitblit that does not transform the cache.
4593 QTransform restoreTransform = painter->worldTransform();
4595 if (newPainterOpacity != oldPainterOpacity) {
4596 painter->setOpacity(newPainterOpacity);
4598 painter->setOpacity(oldPainterOpacity);
4599 } else {
4601 }
4602 painter->setWorldTransform(restoreTransform);
4603 return;
4604 }
4605}
4606
4608 QRegion *exposedRegion, QWidget *widget)
4609{
4610 // Make sure we don't have unpolished items before we draw.
4611 if (!unpolishedItems.isEmpty())
4613
4614 updateAll = false;
4615 QRectF exposedSceneRect;
4616 if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
4617 exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
4618 if (viewTransform)
4619 exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
4620 }
4621 const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder);
4622 for (const auto subTree : tli)
4623 drawSubtreeRecursive(subTree, painter, viewTransform, exposedRegion, widget);
4624}
4625
4627 const QTransform *const viewTransform,
4628 QRegion *exposedRegion, QWidget *widget,
4629 qreal parentOpacity, const QTransform *const effectTransform)
4630{
4631 Q_ASSERT(item);
4632
4633 if (!item->d_ptr->visible)
4634 return;
4635
4636 const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
4637 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
4638 if (!itemHasContents && !itemHasChildren)
4639 return; // Item has neither contents nor children!(?)
4640
4641 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
4642 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4643 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
4644 return;
4645
4647 QTransform *transformPtr = nullptr;
4648 bool translateOnlyTransform = false;
4649#define ENSURE_TRANSFORM_PTR \
4650 if (!transformPtr) { \
4651 Q_ASSERT(!itemIsUntransformable); \
4652 if (viewTransform) { \
4653 transform = item->d_ptr->sceneTransform; \
4654 transform *= *viewTransform; \
4655 transformPtr = &transform; \
4656 } else { \
4657 transformPtr = &item->d_ptr->sceneTransform; \
4658 translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
4659 } \
4660 }
4661
4662 // Update the item's scene transform if the item is transformable;
4663 // otherwise calculate the full transform,
4664 bool wasDirtyParentSceneTransform = false;
4665 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
4666 if (itemIsUntransformable) {
4667 transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
4668 transformPtr = &transform;
4669 } else if (item->d_ptr->dirtySceneTransform) {
4672 wasDirtyParentSceneTransform = true;
4673 }
4674
4675 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
4677 bool drawItem = itemHasContents && !itemIsFullyTransparent;
4678 if (drawItem || minimumRenderSize > 0.0) {
4681 QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
4682 : transformPtr->mapRect(brect);
4683
4684 bool itemIsTooSmallToRender = false;
4685 if (minimumRenderSize > 0.0
4686 && (preciseViewBoundingRect.width() < minimumRenderSize
4687 || preciseViewBoundingRect.height() < minimumRenderSize)) {
4688 itemIsTooSmallToRender = true;
4689 drawItem = false;
4690 }
4691
4692 bool itemIsOutsideVisibleRect = false;
4693 if (drawItem) {
4694 QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
4695 viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
4696 if (widget)
4697 item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
4698 drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
4699 : !viewBoundingRect.normalized().isEmpty();
4700 itemIsOutsideVisibleRect = !drawItem;
4701 }
4702
4703 if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
4704 // We cannot simply use !drawItem here. If we did it is possible
4705 // to enter the outer if statement with drawItem == false and minimumRenderSize > 0
4706 // and finally end up inside this inner if, even though none of the above two
4707 // conditions are met. In that case we should not return from this function
4708 // but call draw() instead.
4709 if (!itemHasChildren)
4710 return;
4711 if (itemClipsChildrenToShape) {
4712 if (wasDirtyParentSceneTransform)
4714 return;
4715 }
4716 }
4717 } // else we know for sure this item has children we must process.
4718
4719 if (itemHasChildren && itemClipsChildrenToShape)
4721
4722#if QT_CONFIG(graphicseffect)
4725 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
4726 painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
4728 QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
4729 (source->d_func());
4730 sourced->info = &info;
4731 const QTransform restoreTransform = painter->worldTransform();
4732 if (effectTransform)
4733 painter->setWorldTransform(*transformPtr * *effectTransform);
4734 else
4735 painter->setWorldTransform(*transformPtr);
4736 painter->setOpacity(opacity);
4737
4738 if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
4739 && sourced->lastEffectTransform != painter->worldTransform())
4740 {
4741 if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
4743 {
4744 QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
4745 QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
4746
4747 sourced->setCachedOffset(effectRect.topLeft());
4748 } else {
4749 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
4750 }
4751
4752 sourced->lastEffectTransform = painter->worldTransform();
4753 }
4754
4756 painter->setWorldTransform(restoreTransform);
4757 sourced->info = nullptr;
4758 } else
4759#endif // QT_CONFIG(graphicseffect)
4760 {
4761 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
4762 effectTransform, wasDirtyParentSceneTransform, drawItem);
4763 }
4764}
4765
4767{
4768 painter->save();
4769 QRectF clipRect;
4770 const QPainterPath clipPath(item->shape());
4771 if (QPathClipper::pathToRect(clipPath, &clipRect))
4773 else
4775}
4776
4777static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr,
4778 const QTransform *effectTransform)
4779{
4780 Q_ASSERT(transformPtr);
4781 if (effectTransform)
4782 painter->setWorldTransform(*transformPtr * *effectTransform);
4783 else
4784 painter->setWorldTransform(*transformPtr);
4785}
4786
4788 const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
4789 qreal opacity, const QTransform *effectTransform,
4790 bool wasDirtyParentSceneTransform, bool drawItem)
4791{
4792 const auto &children = item->d_ptr->children;
4793
4794 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4795 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
4796 const bool itemHasChildren = !children.isEmpty();
4797 bool setChildClip = itemClipsChildrenToShape;
4798 bool itemHasChildrenStackedBehind = false;
4799
4800 int i = 0;
4801 if (itemHasChildren) {
4802 if (itemClipsChildrenToShape)
4803 setWorldTransform(painter, transformPtr, effectTransform);
4804
4806 // Items with the 'ItemStacksBehindParent' flag are put in front of the list
4807 // so all we have to do is to check the first item.
4808 itemHasChildrenStackedBehind = (children.at(0)->d_ptr->flags
4810
4811 if (itemHasChildrenStackedBehind) {
4812 if (itemClipsChildrenToShape) {
4814 setChildClip = false;
4815 }
4816
4817 // Draw children behind
4818 for (i = 0; i < children.size(); ++i) {
4820 if (wasDirtyParentSceneTransform)
4821 child->d_ptr->dirtySceneTransform = 1;
4822 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
4823 break;
4824 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4825 continue;
4826 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4827 }
4828 }
4829 }
4830
4831 // Draw item
4832 if (drawItem) {
4833 Q_ASSERT(!itemIsFullyTransparent);
4835 Q_ASSERT(transformPtr);
4836 item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
4837 ? *exposedRegion : QRegion(), exposedRegion == nullptr);
4838
4839 const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
4840 bool restorePainterClip = false;
4841
4842 if (!itemHasChildren || !itemClipsChildrenToShape) {
4843 // Item does not have children or clip children to shape.
4844 setWorldTransform(painter, transformPtr, effectTransform);
4845 if ((restorePainterClip = itemClipsToShape))
4847 } else if (itemHasChildrenStackedBehind){
4848 // Item clips children to shape and has children stacked behind, which means
4849 // the painter is already clipped to the item's shape.
4850 if (itemClipsToShape) {
4851 // The clip is already correct. Ensure correct world transform.
4852 setWorldTransform(painter, transformPtr, effectTransform);
4853 } else {
4854 // Remove clip (this also ensures correct world transform).
4855 painter->restore();
4856 setChildClip = true;
4857 }
4858 } else if (itemClipsToShape) {
4859 // Item clips children and itself to shape. It does not have hildren stacked
4860 // behind, which means the clip has not yet been set. We set it now and re-use it
4861 // for the children.
4863 setChildClip = false;
4864 }
4865
4866 if (painterStateProtection && !restorePainterClip)
4867 painter->save();
4868
4869 painter->setOpacity(opacity);
4870 if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
4872 else
4874
4875 if (painterStateProtection || restorePainterClip)
4876 painter->restore();
4877
4878 static int drawRect = qEnvironmentVariableIntValue("QT_DRAW_SCENE_ITEM_RECTS");
4879 if (drawRect) {
4880 QPen oldPen = painter->pen();
4881 QBrush oldBrush = painter->brush();
4882 quintptr ptr = reinterpret_cast<quintptr>(item);
4883 const QColor color = QColor::fromHsv(ptr % 255, 255, 255);
4887 painter->setPen(oldPen);
4888 painter->setBrush(oldBrush);
4889 }
4890 }
4891
4892 // Draw children in front
4893 if (itemHasChildren) {
4894 if (setChildClip)
4896
4897 for (; i < children.size(); ++i) {
4899 if (wasDirtyParentSceneTransform)
4900 child->d_ptr->dirtySceneTransform = 1;
4901 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4902 continue;
4903 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4904 }
4905
4906 // Restore child clip
4907 if (itemClipsChildrenToShape)
4908 painter->restore();
4909 }
4910}
4911
4912void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
4913 bool force, bool ignoreOpacity, bool removingItemFromScene,
4914 bool updateBoundingRect)
4915{
4916 Q_ASSERT(item);
4917 if (updateAll)
4918 return;
4919
4920 if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
4921 // If any of the item's ancestors ignore opacity, it means that the opacity
4922 // was set to 0 (and the update request has not yet been processed). That
4923 // also means that we have to ignore the opacity for the item itself; otherwise
4924 // things like: parent->setOpacity(0); scene->removeItem(child) won't work.
4925 // Note that we only do this when removing items from the scene. In all other
4926 // cases the ignoreOpacity bit propagates properly in processDirtyItems, but
4927 // since the item is removed immediately it won't be processed there.
4929 while (p) {
4930 if (p->d_ptr->ignoreOpacity) {
4931 item->d_ptr->ignoreOpacity = true;
4932 break;
4933 }
4934 p = p->d_ptr->parent;
4935 }
4936 }
4937
4938 if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force,
4939 /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
4940 /*ignoreOpacity=*/ignoreOpacity)) {
4941 if (item->d_ptr->dirty) {
4942 // The item is already marked as dirty and will be processed later. However,
4943 // we have to make sure ignoreVisible and ignoreOpacity are set properly;
4944 // otherwise things like: item->update(); item->hide() (force is now true)
4945 // won't work as expected.
4946 if (force)
4947 item->d_ptr->ignoreVisible = 1;
4948 if (ignoreOpacity)
4949 item->d_ptr->ignoreOpacity = 1;
4950 }
4951 return;
4952 }
4953
4954 const bool fullItemUpdate = rect.isNull();
4955 if (!fullItemUpdate && rect.isEmpty())
4956 return;
4957
4959 QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
4961// QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
4963 }
4964
4965 if (removingItemFromScene) {
4966 // Note that this function can be called from the item's destructor, so
4967 // do NOT call any virtual functions on it within this block.
4969 // This block of code is kept for compatibility. Since 4.5, by default
4970 // QGraphicsView does not connect the signal and we use the below
4971 // method of delivering updates.
4972 q_func()->update();
4973 return;
4974 }
4975
4976 for (auto view : std::as_const(views)) {
4977 QGraphicsViewPrivate *viewPrivate = view->d_func();
4978 QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
4979 rect.translate(viewPrivate->dirtyScrollOffset);
4980 viewPrivate->updateRect(rect);
4981 }
4982 return;
4983 }
4984
4985 bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
4986 if (!hasNoContents) {
4987 item->d_ptr->dirty = 1;
4988 if (fullItemUpdate)
4990 else if (!item->d_ptr->fullUpdatePending)
4992 } else if (item->d_ptr->graphicsEffect) {
4993 invalidateChildren = true;
4994 }
4995
4996 if (invalidateChildren) {
4998 item->d_ptr->dirtyChildren = 1;
4999 }
5000
5001 if (force)
5002 item->d_ptr->ignoreVisible = 1;
5003 if (ignoreOpacity)
5004 item->d_ptr->ignoreOpacity = 1;
5005
5006 if (!updateBoundingRect)
5008}
5009
5011 const QRectF &rect, bool itemIsUntransformable)
5012{
5013 Q_ASSERT(view);
5014 Q_ASSERT(item);
5015
5016 QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr);
5017 QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr);
5018
5019 if (itemIsUntransformable) {
5020 const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
5021 if (!item->hasBoundingRegionGranularity)
5022 return view->updateRectF(xform.mapRect(rect));
5023 return view->updateRegion(rect, xform);
5024 }
5025
5026 if (item->sceneTransformTranslateOnly && view->identityMatrix) {
5027 const qreal dx = item->sceneTransform.dx();
5028 const qreal dy = item->sceneTransform.dy();
5029 QRectF r(rect);
5030 r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
5031 return view->updateRectF(r);
5032 }
5033
5034 if (!viewq->isTransformed()) {
5035 if (!item->hasBoundingRegionGranularity)
5036 return view->updateRectF(item->sceneTransform.mapRect(rect));
5037 return view->updateRegion(rect, item->sceneTransform);
5038 }
5039
5041 xform *= viewq->viewportTransform();
5042 if (!item->hasBoundingRegionGranularity)
5043 return view->updateRectF(xform.mapRect(rect));
5044 return view->updateRegion(rect, xform);
5045}
5046
5048 qreal parentOpacity)
5049{
5050 Q_Q(QGraphicsScene);
5051 Q_ASSERT(item);
5053
5054 if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
5056 return;
5057 }
5058
5059 const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
5060 if (itemIsHidden) {
5061 resetDirtyItem(item, /*recursive=*/true);
5062 return;
5063 }
5064
5065 bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
5066 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
5067 if (!itemHasContents) {
5068 if (!itemHasChildren) {
5070 return; // Item has neither contents nor children!(?)
5071 }
5073 itemHasContents = true;
5074 }
5075
5076 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
5077 const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
5079 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
5080 resetDirtyItem(item, /*recursive=*/itemHasChildren);
5081 return;
5082 }
5083
5084 bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
5085 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
5086 if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
5089 }
5090
5091 const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
5092 if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
5093 // Make sure we don't process invisible items or items with no content.
5094 item->d_ptr->dirty = 0;
5096 // Might have a dirty view bounding rect otherwise.
5097 if (itemIsFullyTransparent || !itemHasContents)
5099 }
5100
5102 // Update growingItemsBoundingRect.
5106 } else {
5108 }
5109 }
5110
5111 // Process item.
5113 const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
5114 const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
5115
5116 if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
5117 // This block of code is kept for compatibility. Since 4.5, by default
5118 // QGraphicsView does not connect the signal and we use the below
5119 // method of delivering updates.
5121 q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
5123 } else {
5124 QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
5125 if (!rect.isEmpty())
5126 q->update(rect);
5127 }
5128 } else {
5129 QRectF dirtyRect;
5130 bool uninitializedDirtyRect = true;
5131
5132 for (auto view : std::as_const(views)) {
5133 QGraphicsViewPrivate *viewPrivate = view->d_func();
5134 QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
5135 if (viewPrivate->fullUpdatePending
5137 // Okay, if we have a full update pending or no viewport update, this item's
5138 // paintedViewBoundingRect will be updated correctly in the next paintEvent if
5139 // it is inside the viewport, but for now we can pretend that it is outside.
5140 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5141 continue;
5142 }
5143
5145 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
5146 if (!viewPrivate->updateRect(paintedViewBoundingRect))
5147 paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
5148 }
5149
5150 if (!item->d_ptr->dirty)
5151 continue;
5152
5154 && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
5155 && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
5156 continue; // Outside viewport.
5157 }
5158
5159 if (uninitializedDirtyRect) {
5160 dirtyRect = itemBoundingRect;
5161 if (!item->d_ptr->fullUpdatePending) {
5163 dirtyRect &= item->d_ptr->needsRepaint;
5164 }
5165 uninitializedDirtyRect = false;
5166 }
5167
5168 if (dirtyRect.isEmpty())
5169 continue; // Discard updates outside the bounding rect.
5170
5171 if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
5173 paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
5174 }
5175 }
5176 }
5177 }
5178
5179 // Process children.
5180 if (itemHasChildren && item->d_ptr->dirtyChildren) {
5181 const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
5183 // Items with no content are threated as 'dummy' items which means they are never drawn and
5184 // 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
5185 // such an item changes geometry, its children have to take care of the update regardless
5186 // of whether the item clips children to shape or not.
5187 const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
5188 if (itemClipsChildrenToShape && !bypassUpdateClip) {
5189 // Make sure child updates are clipped to the item's bounding rect.
5190 for (auto view : std::as_const(views))
5191 view->d_func()->setUpdateClip(item);
5192 }
5193 if (!dirtyAncestorContainsChildren) {
5194 dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
5195 && itemClipsChildrenToShape;
5196 }
5197 const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
5198 const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
5199 const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
5200 for (auto child : std::as_const(item->d_ptr->children)) {
5201 if (wasDirtyParentSceneTransform)
5202 child->d_ptr->dirtySceneTransform = 1;
5203 if (wasDirtyParentViewBoundingRects)
5204 child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
5205 if (parentIgnoresVisible)
5206 child->d_ptr->ignoreVisible = 1;
5207 if (parentIgnoresOpacity)
5208 child->d_ptr->ignoreOpacity = 1;
5209 if (allChildrenDirty) {
5210 child->d_ptr->dirty = 1;
5211 child->d_ptr->fullUpdatePending = 1;
5212 child->d_ptr->dirtyChildren = 1;
5213 child->d_ptr->allChildrenDirty = 1;
5214 }
5215 processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
5216 }
5217
5218 if (itemClipsChildrenToShape) {
5219 // Reset updateClip.
5220 for (auto view : std::as_const(views))
5221 view->d_func()->setUpdateClip(nullptr);
5222 }
5223 } else if (wasDirtyParentSceneTransform) {
5225 }
5226
5228}
5229
5262 int numItems,
5264 const QStyleOptionGraphicsItem options[], QWidget *widget)
5265{
5266 Q_D(QGraphicsScene);
5267 // Make sure we don't have unpolished items before we draw.
5268 if (!d->unpolishedItems.isEmpty())
5269 d->_q_polishItems();
5270
5271 const qreal opacity = painter->opacity();
5272 QTransform viewTransform = painter->worldTransform();
5273 Q_UNUSED(options);
5274
5275 // Determine view, expose and flags.
5276 QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
5277 QRegion *expose = nullptr;
5278 const quint32 oldRectAdjust = d->rectAdjust;
5279 if (view) {
5280 d->updateAll = false;
5281 expose = &view->d_func()->exposedRegion;
5282 if (view->d_func()->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
5283 d->rectAdjust = 1;
5284 else
5285 d->rectAdjust = 2;
5286 }
5287
5288 // Find all toplevels, they are already sorted.
5289 QList<QGraphicsItem *> topLevelItems;
5290 for (int i = 0; i < numItems; ++i) {
5291 QGraphicsItem *item = items[i]->topLevelItem();
5292 if (!item->d_ptr->itemDiscovered) {
5293 topLevelItems << item;
5295 d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
5296 }
5297 }
5298
5299 d->rectAdjust = oldRectAdjust;
5300 // Reset discovery bits.
5301 for (auto topLevelItem : std::as_const(topLevelItems))
5302 topLevelItem->d_ptr->itemDiscovered = 0;
5303
5304 painter->setWorldTransform(viewTransform);
5305 painter->setOpacity(opacity);
5306}
5307
5322{
5323 Q_D(QGraphicsScene);
5324
5326 if (item && !item->isWidget()) {
5327 // Tab out of the scene.
5328 return false;
5329 }
5330 if (!item) {
5331 if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
5332 // Restore focus to the last focusable non-widget item that had
5333 // focus.
5335 return true;
5336 }
5337 if (d->activePanel) {
5338 if (d->activePanel->flags() & QGraphicsItem::ItemIsFocusable) {
5340 return true;
5341 }
5342 if (d->activePanel->isWidget()) {
5343 QGraphicsWidget *test = static_cast<QGraphicsWidget *>(d->activePanel);
5344 QGraphicsWidget *fw = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5345 do {
5346 if (fw->focusPolicy() & Qt::TabFocus) {
5348 return true;
5349 }
5350 fw = next ? fw->d_func()->focusNext : fw->d_func()->focusPrev;
5351 } while (fw != d->activePanel);
5352 }
5353 }
5354 }
5355 if (!item && !d->tabFocusFirst) {
5356 // No widgets...
5357 return false;
5358 }
5359
5360 // The item must be a widget.
5361 QGraphicsWidget *widget = nullptr;
5362 if (!item) {
5363 widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
5364 } else {
5365 QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item);
5366 widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5367 if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) {
5368 // Tab out of the scene.
5369 return false;
5370 }
5371 }
5372 QGraphicsWidget *widgetThatHadFocus = widget;
5373
5374 // Run around the focus chain until we find a widget that can take tab focus.
5375 do {
5377 && widget->isEnabled() && widget->isVisibleTo(nullptr)
5379 && (!item || !item->isPanel() || item->isAncestorOf(widget))
5380 ) {
5382 return true;
5383 }
5384 widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
5385 if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
5386 return false;
5387 } while (widget != widgetThatHadFocus);
5388
5389 return false;
5390}
5391
5461{
5462 Q_D(const QGraphicsScene);
5463 // ### This function, and the use of styles in general, is non-reentrant.
5464 return d->style ? d->style : QApplication::style();
5465}
5466
5485{
5486 Q_D(QGraphicsScene);
5487 // ### This function, and the use of styles in general, is non-reentrant.
5488 if (style == d->style)
5489 return;
5490
5491 // Delete the old style,
5492 delete d->style;
5493 if ((d->style = style))
5494 d->style->setParent(this);
5495
5496 // Notify the scene.
5499
5500 // Notify all widgets that don't have a style explicitly set.
5501 const auto items_ = items();
5502 for (QGraphicsItem *item : items_) {
5503 if (item->isWidget()) {
5504 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
5507 }
5508 }
5509}
5510
5535{
5536 Q_D(const QGraphicsScene);
5537 return d->font;
5538}
5540{
5541 Q_D(QGraphicsScene);
5542 QFont naturalFont = QApplication::font();
5543 naturalFont.setResolveMask(0);
5544 QFont resolvedFont = font.resolve(naturalFont);
5545 d->setFont_helper(resolvedFont);
5546}
5547
5572{
5573 Q_D(const QGraphicsScene);
5574 return d->palette;
5575}
5577{
5578 Q_D(QGraphicsScene);
5579 QPalette naturalPalette = QGuiApplication::palette();
5580 naturalPalette.setResolveMask(0);
5581 QPalette resolvedPalette = palette.resolve(naturalPalette);
5582 d->setPalette_helper(resolvedPalette);
5583}
5584
5594{
5595 Q_D(const QGraphicsScene);
5596 return d->activationRefCount > 0;
5597}
5598
5607{
5608 Q_D(const QGraphicsScene);
5609 return d->activePanel;
5610}
5611
5624{
5625 Q_D(QGraphicsScene);
5626 d->setActivePanelHelper(item, false);
5627}
5628
5638{
5639 Q_D(const QGraphicsScene);
5640 if (d->activePanel && d->activePanel->isWindow())
5641 return static_cast<QGraphicsWidget *>(d->activePanel);
5642 return nullptr;
5643}
5644
5654{
5655 if (widget && widget->scene() != this) {
5656 qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
5657 widget);
5658 return;
5659 }
5660
5661 // Activate the widget's panel (all windows are panels).
5662 QGraphicsItem *panel = widget ? widget->panel() : nullptr;
5664
5665 // Raise
5666 if (panel) {
5667 QGraphicsItem *parent = panel->parentItem();
5668 // Raise ### inefficient for toplevels
5669
5670 // Find the highest z value.
5671 qreal z = panel->zValue();
5672 const auto siblings = parent ? parent->childItems() : items();
5673 for (QGraphicsItem *sibling : siblings) {
5674 if (sibling != panel && sibling->isWindow())
5675 z = qMax(z, sibling->zValue());
5676 }
5677
5678 // This will probably never overflow.
5679 const qreal litt = qreal(0.001);
5680 panel->setZValue(z + litt);
5681 }
5682}
5683
5697{
5698 Q_D(QGraphicsScene);
5699 if (!item) {
5700 qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
5701 return false;
5702 }
5703 if (item->scene() != this) {
5704 qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
5705 " is different from this scene (%p)",
5706 item, item->scene(), this);
5707 return false;
5708 }
5709 return d->sendEvent(item, event);
5710}
5711
5744{
5745 Q_D(const QGraphicsScene);
5746 return d->minimumRenderSize;
5747}
5749{
5750 Q_D(QGraphicsScene);
5751 d->minimumRenderSize = minSize;
5752 update();
5753}
5754
5779{
5780 Q_D(const QGraphicsScene);
5781 return d->focusOnTouch;
5782}
5783
5785{
5786 Q_D(QGraphicsScene);
5787 d->focusOnTouch = enabled;
5788}
5789
5791{
5792 views << view;
5793#ifndef QT_NO_GESTURES
5794 for (auto it = grabbedGestures.constBegin();
5795 it != grabbedGestures.constEnd(); ++it)
5796 view->viewport()->grabGesture(it.key());
5797#endif
5798}
5799
5801{
5803}
5804
5806{
5807 const QTransform mapFromScene =
5808 item->d_ptr->genericMapFromSceneTransform(static_cast<const QWidget *>(touchEvent->target()));
5809
5810 for (int i = 0; i < touchEvent->pointCount(); ++i) {
5811 auto &pt = touchEvent->point(i);
5812 QMutableEventPoint::setPosition(pt, mapFromScene.map(pt.scenePosition()));
5813 }
5814}
5815
5817{
5818 int closestTouchPointId = -1;
5819 qreal closestDistance = qreal(0.);
5820 for (const QEventPoint &touchPoint : std::as_const(sceneCurrentTouchPoints)) {
5821 qreal distance = QLineF(scenePos, touchPoint.scenePosition()).length();
5822 if (closestTouchPointId == -1|| distance < closestDistance) {
5823 closestTouchPointId = touchPoint.id();
5824 closestDistance = distance;
5825 }
5826 }
5827 return closestTouchPointId;
5828}
5829
5831{
5832 typedef QPair<QEventPoint::States, QList<QEventPoint> > StatesAndTouchPoints;
5834
5835 const auto &touchPoints = sceneTouchEvent->points();
5836 for (const auto &touchPoint : touchPoints) {
5837 // update state
5838 QGraphicsItem *item = nullptr;
5839 if (touchPoint.state() == QEventPoint::State::Pressed) {
5840 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchPad) {
5841 // on touch-pad devices, send all touch points to the same item
5843 ? 0
5844 : itemForTouchPointId.constBegin().value();
5845 }
5846
5847 if (!item) {
5848 // determine which item this touch point will go to
5849 cachedItemsUnderMouse = itemsAtPosition(touchPoint.globalPosition().toPoint(),
5850 touchPoint.scenePosition(),
5851 static_cast<QWidget *>(sceneTouchEvent->target()));
5853 }
5854
5855 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchScreen) {
5856 // on touch-screens, combine this touch point with the closest one we find
5857 int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePosition());
5858 QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
5859 if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
5860 item = closestItem;
5861 }
5862 if (!item)
5863 continue;
5864
5865 itemForTouchPointId.insert(touchPoint.id(), item);
5866 sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
5867 } else if (touchPoint.state() == QEventPoint::State::Released) {
5868 item = itemForTouchPointId.take(touchPoint.id());
5869 if (!item)
5870 continue;
5871
5872 sceneCurrentTouchPoints.remove(touchPoint.id());
5873 } else {
5874 item = itemForTouchPointId.value(touchPoint.id());
5875 if (!item)
5876 continue;
5877 Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
5878 sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
5879 }
5880
5881 StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
5882 statesAndTouchPoints.first = QEventPoint::States(statesAndTouchPoints.first | touchPoint.state());
5883 statesAndTouchPoints.second.append(touchPoint);
5884 }
5885
5886 if (itemsNeedingEvents.isEmpty()) {
5887 sceneTouchEvent->ignore();
5888 return;
5889 }
5890
5891 bool ignoreSceneTouchEvent = true;
5894 for (; it != end; ++it) {
5895 QGraphicsItem *item = it.key();
5896
5898
5899 // determine event type from the state mask
5900 QEvent::Type eventType;
5901 switch (it.value().first) {
5903 // all touch points have pressed state
5904 eventType = QEvent::TouchBegin;
5905 break;
5907 // all touch points have released state
5908 eventType = QEvent::TouchEnd;
5909 break;
5911 // don't send the event if nothing changed
5912 continue;
5913 default:
5914 // all other combinations
5915 eventType = QEvent::TouchUpdate;
5916 break;
5917 }
5918
5919 QMutableTouchEvent touchEvent(eventType, sceneTouchEvent->pointingDevice(), sceneTouchEvent->modifiers(), it.value().second);
5920 touchEvent.setTarget(sceneTouchEvent->target());
5921 touchEvent.setModifiers(sceneTouchEvent->modifiers());
5922 touchEvent.setTimestamp(sceneTouchEvent->timestamp());
5923
5924 switch (touchEvent.type()) {
5925 case QEvent::TouchBegin:
5926 {
5927 // if the TouchBegin handler recurses, we assume that means the event
5928 // has been implicitly accepted and continue to send touch events
5930 bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted();
5931 if (!res) {
5932 // forget about these touch points, we didn't handle them
5933 const auto &unhandledTouchPoints = touchEvent.points();
5934 for (const auto &touchPoint : unhandledTouchPoints) {
5935 itemForTouchPointId.remove(touchPoint.id());
5936 sceneCurrentTouchPoints.remove(touchPoint.id());
5937 }
5938 ignoreSceneTouchEvent = false;
5939 }
5940 break;
5941 }
5942 default:
5944 updateTouchPointsForItem(item, &touchEvent);
5945 (void) sendEvent(item, &touchEvent);
5946 ignoreSceneTouchEvent = false;
5947 }
5948 break;
5949 }
5950 }
5951 // don't override the acceptance state of the individual points
5952 sceneTouchEvent->QInputEvent::setAccepted(ignoreSceneTouchEvent);
5953}
5954
5956{
5957 Q_Q(QGraphicsScene);
5958
5959 if (focusOnTouch) {
5961 const QEventPoint &firstTouchPoint = touchEvent->points().first();
5963 firstTouchPoint.scenePosition(),
5964 static_cast<QWidget *>(touchEvent->target()));
5965 }
5966
5967 // Set focus on the topmost enabled item that can take focus.
5968 bool setFocus = false;
5969
5970 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
5972 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
5973 setFocus = true;
5974 if (item != q->focusItem())
5975 q->setFocusItem(item, Qt::MouseFocusReason);
5976 break;
5977 }
5978 }
5979 if (item->isPanel())
5980 break;
5982 break;
5984 // Make sure we don't clear focus.
5985 setFocus = true;
5986 break;
5987 }
5988 }
5989
5990 // If nobody could take focus, clear it.
5991 if (!stickyFocus && !setFocus)
5992 q->setFocusItem(nullptr, Qt::MouseFocusReason);
5993 }
5994
5995 bool res = false;
5996 bool eventAccepted = touchEvent->isAccepted();
5997 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
5998 // first, try to deliver the touch event
5999 updateTouchPointsForItem(item, touchEvent);
6000 bool acceptTouchEvents = item->acceptTouchEvents();
6001 touchEvent->setAccepted(acceptTouchEvents);
6002 res = acceptTouchEvents && sendEvent(item, touchEvent);
6003 eventAccepted = touchEvent->isAccepted();
6004 if (itemForTouchPointId.value(touchEvent->points().first().id()) == 0) {
6005 // item was deleted
6006 item = nullptr;
6007 } else {
6008 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
6009 }
6010 touchEvent->m_spont = false;
6011 if (res && eventAccepted) {
6012 // the first item to accept the TouchBegin gets an implicit grab.
6013 const auto &touchPoints = touchEvent->points();
6014 for (const auto &touchPoint : touchPoints)
6015 itemForTouchPointId[touchPoint.id()] = item; // can be zero
6016 break;
6017 }
6018 if (item && item->isPanel())
6019 break;
6020 }
6021
6022 // don't override the acceptance state of the touch points
6023 touchEvent->QInputEvent::setAccepted(eventAccepted);
6024 return res;
6025}
6026
6028{
6029 for (QGraphicsView *view : std::as_const(views))
6030 view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
6031}
6032
6034{
6035 for (auto view : std::as_const(views))
6036 view->d_func()->updateInputMethodSensitivity();
6037}
6038
6040{
6041 Q_Q(QGraphicsScene);
6042 Q_ASSERT(panel && panel->isPanel());
6043
6044 QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality;
6045 if (previousModality != QGraphicsItem::NonModal) {
6046 // the panel is changing from one modality type to another... temporarily set it back so
6047 // that blockedPanels is populated correctly
6048 panel->d_ptr->panelModality = previousModality;
6049 }
6050
6051 QSet<QGraphicsItem *> blockedPanels;
6052 {
6053 const auto items_ = q->items();
6054 for (const auto &item : items_) {
6056 blockedPanels.insert(item);
6057 }
6058 }
6059 // blockedPanels contains all currently blocked panels
6060
6061 if (previousModality != QGraphicsItem::NonModal) {
6062 // reset the modality to the proper value, since we changed it above
6063 panel->d_ptr->panelModality = panelModality;
6064 // remove this panel so that it will be reinserted at the front of the stack
6066 }
6067
6069
6070 if (!hoverItems.isEmpty()) {
6071 // send GraphicsSceneHoverLeave events to newly blocked hoverItems
6072 QGraphicsSceneHoverEvent hoverEvent;
6073 hoverEvent.setScenePos(lastSceneMousePos);
6074 dispatchHoverEvent(&hoverEvent);
6075 }
6076
6080 ungrabMouse(item, /*itemIsDying =*/ false);
6081 }
6082
6083 QEvent windowBlockedEvent(QEvent::WindowBlocked);
6084 QEvent windowUnblockedEvent(QEvent::WindowUnblocked);
6085 const auto items_ = q->items();
6086 for (const auto &item : items_) {
6087 if (item->isPanel()) {
6088 if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) {
6089 // send QEvent::WindowBlocked to newly blocked panels
6090 sendEvent(item, &windowBlockedEvent);
6091 } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) {
6092 // send QEvent::WindowUnblocked to unblocked panels when downgrading
6093 // a panel from SceneModal to PanelModal
6094 sendEvent(item, &windowUnblockedEvent);
6095 }
6096 }
6097 }
6098}
6099
6101{
6102 Q_Q(QGraphicsScene);
6103 Q_ASSERT(panel && panel->isPanel());
6104
6105 QSet<QGraphicsItem *> blockedPanels;
6106 {
6107 const auto items_ = q->items();
6108 for (const auto &item : items_) {
6110 blockedPanels.insert(item);
6111 }
6112 }
6113
6115
6116 {
6118 const auto items_ = q->items();
6119 for (const auto &item : items_) {
6120 if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel())
6121 sendEvent(item, &e);
6122 }
6123 }
6124
6125 // send GraphicsSceneHoverEnter events to newly unblocked items
6126 QGraphicsSceneHoverEvent hoverEvent;
6127 hoverEvent.setScenePos(lastSceneMousePos);
6128 dispatchHoverEvent(&hoverEvent);
6129}
6130
6131#ifndef QT_NO_GESTURES
6133 Qt::GestureFlag flag,
6135 QSet<QGraphicsObject *> *itemsSet,
6136 QSet<QGesture *> *normal,
6137 QSet<QGesture *> *conflicts)
6138{
6139 QSet<QGesture *> normalGestures; // that are not in conflicted state.
6140 for (QGesture *gesture : gestures) {
6141 if (!gesture->hasHotSpot())
6142 continue;
6143 const Qt::GestureType gestureType = gesture->gestureType();
6144 const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, nullptr);
6145 for (int j = 0; j < items.size(); ++j) {
6147
6148 // Check if the item is blocked by a modal panel and use it as
6149 // a target instead of this item.
6151
6152 if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
6153 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
6155 d->gestureContext.constFind(gestureType);
6156 if (it != d->gestureContext.constEnd() && (!flag || (it.value() & flag))) {
6157 if (normalGestures.contains(gesture)) {
6158 normalGestures.remove(gesture);
6159 if (conflicts)
6160 conflicts->insert(gesture);
6161 } else {
6162 normalGestures.insert(gesture);
6163 }
6164 if (targets)
6165 (*targets)[itemobj].insert(gesture);
6166 if (itemsSet)
6167 (*itemsSet).insert(itemobj);
6168 }
6169 }
6170 // Don't propagate through panels.
6171 if (item->isPanel())
6172 break;
6173 }
6174 }
6175 if (normal)
6176 *normal = normalGestures;
6177}
6178
6180{
6181 QWidget *viewport = event->widget();
6182 if (!viewport)
6183 return;
6184 QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
6185 if (!graphicsView)
6186 return;
6187
6188 const QList<QGesture *> allGestures = event->gestures();
6189 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6190 << "Gestures:" << allGestures;
6191
6192 QSet<QGesture *> startedGestures;
6193 QPoint delta = viewport->mapFromGlobal(QPoint());
6194 QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
6195 * graphicsView->viewportTransform().inverted();
6196 for (QGesture *gesture : allGestures) {
6197 // cache scene coordinates of the hot spot
6198 if (gesture->hasHotSpot()) {
6199 gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
6200 } else {
6201 gesture->d_func()->sceneHotSpot = QPointF();
6202 }
6203
6205 if (!target) {
6206 // when we are not in started mode but don't have a target
6207 // then the only one interested in gesture is the view/scene
6208 if (gesture->state() == Qt::GestureStarted)
6209 startedGestures.insert(gesture);
6210 }
6211 }
6212
6213 if (!startedGestures.isEmpty()) {
6214 QSet<QGesture *> normalGestures; // that have just one target
6215 QSet<QGesture *> conflictedGestures; // that have multiple possible targets
6216 gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, nullptr,
6217 &normalGestures, &conflictedGestures);
6220 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6221 << "Normal gestures:" << normalGestures
6222 << "Conflicting gestures:" << conflictedGestures;
6223
6224 // deliver conflicted gestures as override events AND remember
6225 // initial gesture targets
6226 if (!conflictedGestures.isEmpty()) {
6227 for (int i = 0; i < cachedTargetItems.size(); ++i) {
6229
6230 // get gestures to deliver to the current item
6231 const QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
6232 if (gestures.isEmpty())
6233 continue;
6234
6235 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6236 << "delivering override to"
6237 << item.data() << gestures;
6238 // send gesture override
6239 QGestureEvent ev(gestures.values());
6241 ev.setWidget(event->widget());
6242 // mark event and individual gestures as ignored
6243 ev.ignore();
6244 for (QGesture *g : gestures)
6245 ev.setAccepted(g, false);
6246 sendEvent(item.data(), &ev);
6247 // mark all accepted gestures to deliver them as normal gesture events
6248 for (QGesture *g : gestures) {
6249 if (ev.isAccepted() || ev.isAccepted(g)) {
6250 conflictedGestures.remove(g);
6251 // mark the item as a gesture target
6252 if (item) {
6257 for(; it != e; ++it)
6258 it.value().remove(g);
6260 }
6261 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6262 << "override was accepted:"
6263 << g << item.data();
6264 }
6265 // remember the first item that received the override event
6266 // as it most likely become a target if no one else accepts
6267 // the override event
6268 if (!gestureTargets.contains(g) && item)
6270
6271 }
6272 if (conflictedGestures.isEmpty())
6273 break;
6274 }
6275 }
6276 // remember the initial target item for each gesture that was not in
6277 // the conflicted state.
6278 if (!normalGestures.isEmpty()) {
6279 for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
6281
6282 // get gestures to deliver to the current item
6283 const auto gestures = cachedItemGestures.value(item);
6284 for (QGesture *g : gestures) {
6285 if (!gestureTargets.contains(g)) {
6287 normalGestures.remove(g);
6288 }
6289 }
6290 }
6291 }
6292 }
6293
6294
6295 // deliver all gesture events
6296 QSet<QGesture *> undeliveredGestures;
6297 QSet<QGesture *> parentPropagatedGestures;
6298 for (QGesture *gesture : allGestures) {
6299 if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
6302 undeliveredGestures.insert(gesture);
6303 QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
6304 const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
6306 parentPropagatedGestures.insert(gesture);
6307 } else {
6308 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6309 << "no target for" << gesture << "at"
6310 << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
6311 }
6312 }
6314 for (int i = 0; i < cachedTargetItems.size(); ++i) {
6316 const QSet<QGesture *> gestures = (undeliveredGestures
6317 & cachedItemGestures.value(receiver.data()))
6319
6320 if (gestures.isEmpty())
6321 continue;
6322
6323 cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
6324 const bool isPanel = receiver.data()->isPanel();
6325
6326 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6327 << "delivering to"
6328 << receiver.data() << gestures;
6329 QGestureEvent ev(gestures.values());
6330 ev.setWidget(event->widget());
6331 sendEvent(receiver.data(), &ev);
6332 QSet<QGesture *> ignoredGestures;
6333 for (QGesture *g : gestures) {
6334 if (!ev.isAccepted() && !ev.isAccepted(g)) {
6335 // if the gesture was ignored by its target, we will update the
6336 // targetItems list with a possible target items (items that
6337 // want to receive partial gestures).
6338 // ### won't work if the target was destroyed in the event
6339 // we will just stop delivering it.
6340 if (receiver && receiver.data() == gestureTargets.value(g, 0))
6341 ignoredGestures.insert(g);
6342 } else {
6343 if (receiver && g->state() == Qt::GestureStarted) {
6344 // someone accepted the propagated initial GestureStarted
6345 // event, let it be the new target for all following events.
6346 gestureTargets[g] = receiver.data();
6347 }
6348 undeliveredGestures.remove(g);
6349 }
6350 }
6351 if (undeliveredGestures.isEmpty())
6352 break;
6353
6354 // ignoredGestures list is only filled when delivering to the gesture
6355 // target item, so it is safe to assume item == target.
6356 if (!ignoredGestures.isEmpty() && !isPanel) {
6357 // look for new potential targets for gestures that were ignored
6358 // and should be propagated.
6359
6361
6362 if (receiver) {
6363 // first if the gesture should be propagated to parents only
6364 for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
6365 it != ignoredGestures.end();) {
6366 if (parentPropagatedGestures.contains(*it)) {
6367 QGesture *gesture = *it;
6368 const Qt::GestureType gestureType = gesture->gestureType();
6369 QGraphicsItem *item = receiver.data();
6370 while (item) {
6372 if (item->d_func()->gestureContext.contains(gestureType)) {
6373 targetsSet.insert(obj);
6374 cachedItemGestures[obj].insert(gesture);
6375 }
6376 }
6377 if (item->isPanel())
6378 break;
6379 item = item->parentItem();
6380 }
6381
6382 it = ignoredGestures.erase(it);
6383 continue;
6384 }
6385 ++it;
6386 }
6387 }
6388
6390 &cachedItemGestures, &targetsSet, nullptr, nullptr);
6391
6392 cachedTargetItems = targetsSet.values();
6394 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6395 << "new targets:" << cachedTargetItems;
6396 i = -1; // start delivery again
6397 continue;
6398 }
6399 }
6400
6401 for (QGesture *g : std::as_const(startedGestures)) {
6402 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
6403 DEBUG() << "lets try to cancel some";
6404 // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
6406 }
6407 }
6408
6409 // forget about targets for gestures that have ended
6410 for (QGesture *g : allGestures) {
6411 switch (g->state()) {
6415 break;
6416 default:
6417 break;
6418 }
6419 }
6420
6424}
6425
6427{
6428 Q_ASSERT(original);
6429 QGraphicsItem *originalItem = gestureTargets.value(original);
6430 if (originalItem == nullptr) // we only act on accepted gestures, which implies it has a target.
6431 return;
6432
6433 // iterate over all active gestures and for each find the owner
6434 // if the owner is part of our sub-hierarchy, cancel it.
6435
6436 QSet<QGesture *> canceledGestures;
6438 while (iter != gestureTargets.end()) {
6439 QGraphicsObject *item = iter.value();
6440 // note that we don't touch the gestures for our originalItem
6441 if (item != originalItem && originalItem->isAncestorOf(item)) {
6442 DEBUG() << " found a gesture to cancel" << iter.key();
6443 iter.key()->d_func()->state = Qt::GestureCanceled;
6444 canceledGestures << iter.key();
6445 }
6446 ++iter;
6447 }
6448
6449 // sort them per target item by cherry picking from almostCanceledGestures and delivering
6450 QSet<QGesture *> almostCanceledGestures = canceledGestures;
6452 while (!almostCanceledGestures.isEmpty()) {
6453 QGraphicsObject *target = nullptr;
6454 QSet<QGesture*> gestures;
6455 setIter = almostCanceledGestures.begin();
6456 // sort per target item
6457 while (setIter != almostCanceledGestures.end()) {
6459 if (target == nullptr)
6460 target = item;
6461 if (target == item) {
6462 gestures << *setIter;
6463 setIter = almostCanceledGestures.erase(setIter);
6464 } else {
6465 ++setIter;
6466 }
6467 }
6469
6470 const QList<QGesture *> list = gestures.values();
6471 QGestureEvent ev(list);
6472 sendEvent(target, &ev);
6473
6474 if (!ev.isAccepted()) {
6475 for (QGesture *g : list) {
6476
6477 if (ev.isAccepted(g))
6478 continue;
6479
6480 if (!g->hasHotSpot())
6481 continue;
6482
6483 const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, nullptr);
6484 for (const auto &item : items) {
6486 if (!object)
6487 continue;
6488 QGraphicsItemPrivate *d = object->QGraphicsItem::d_func();
6489 if (d->gestureContext.contains(g->gestureType())) {
6491 list << g;
6492 QGestureEvent ev(list);
6493 sendEvent(object, &ev);
6494 if (ev.isAccepted() || ev.isAccepted(g))
6495 break; // successfully delivered
6496 }
6497 }
6498 }
6499 }
6500 }
6501
6503 Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager.
6504 for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
6505 gestureManager->recycle(*setIter);
6506 gestureTargets.remove(*setIter);
6507 }
6508}
6509
6511{
6512 (void)QGestureManager::instance(); // create a gesture manager
6513 if (!grabbedGestures[gesture]++) {
6514 for (QGraphicsView *view : std::as_const(views))
6515 view->viewport()->grabGesture(gesture);
6516 }
6517}
6518
6520{
6521 // we know this can only be an object
6523 QGraphicsObject *obj = static_cast<QGraphicsObject *>(item);
6525 if (!--grabbedGestures[gesture]) {
6526 for (QGraphicsView *view : std::as_const(views))
6527 view->viewport()->ungrabGesture(gesture);
6528 }
6529}
6530#endif // QT_NO_GESTURES
6531
6533
6534#include "moc_qgraphicsscene.cpp"
static QApplicationPrivate * instance()
QGestureManager * gestureManager
static QStyle * style()
Returns the application's style object.
static QFont font()
Returns the default application font.
\inmodule QtGui
Definition qbrush.h:30
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QColor fromHsv(int h, int s, int v, int a=255)
Static convenience function that returns a QColor constructed from the HSV color values,...
Definition qcolor.cpp:2499
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
Definition qcursor.cpp:188
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
QPointF globalPosition
the global position of this point.
Definition qeventpoint.h:44
int id
the ID number of this event point.
Definition qeventpoint.h:25
QPointF scenePosition
the scene position of this point.
Definition qeventpoint.h:40
\inmodule QtCore
Definition qcoreevent.h:45
virtual void setAccepted(bool accepted)
Definition qcoreevent.h:302
bool spontaneous() const
Returns true if the event originated outside the application (a system event); otherwise returns fals...
Definition qcoreevent.h:300
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ GraphicsSceneDragLeave
Definition qcoreevent.h:200
@ GraphicsSceneMouseMove
Definition qcoreevent.h:189
@ ApplicationPaletteChange
Definition qcoreevent.h:93
@ GestureOverride
Definition qcoreevent.h:254
@ GraphicsSceneContextMenu
Definition qcoreevent.h:193
@ GraphicsSceneMouseRelease
Definition qcoreevent.h:191
@ WindowBlocked
Definition qcoreevent.h:141
@ WindowUnblocked
Definition qcoreevent.h:142
@ GraphicsSceneDragEnter
Definition qcoreevent.h:198
@ GraphicsSceneDragMove
Definition qcoreevent.h:199
@ ShortcutOverride
Definition qcoreevent.h:158
@ FocusOut
Definition qcoreevent.h:67
@ InputMethod
Definition qcoreevent.h:120
@ GraphicsSceneMousePress
Definition qcoreevent.h:190
@ StyleChange
Definition qcoreevent.h:136
@ UngrabMouse
Definition qcoreevent.h:234
@ FontChange
Definition qcoreevent.h:133
@ KeyRelease
Definition qcoreevent.h:65
@ KeyPress
Definition qcoreevent.h:64
@ StyleAnimationUpdate
Definition qcoreevent.h:272
@ FocusIn
Definition qcoreevent.h:66
@ ActivationChange
Definition qcoreevent.h:135
@ TouchUpdate
Definition qcoreevent.h:242
@ TouchBegin
Definition qcoreevent.h:241
@ GraphicsSceneHoverLeave
Definition qcoreevent.h:196
@ WindowActivate
Definition qcoreevent.h:83
@ GraphicsSceneMouseDoubleClick
Definition qcoreevent.h:192
@ GraphicsSceneWheel
Definition qcoreevent.h:202
@ GraphicsSceneDrop
Definition qcoreevent.h:201
@ PaletteChange
Definition qcoreevent.h:94
@ GraphicsSceneHoverEnter
Definition qcoreevent.h:194
@ UngrabKeyboard
Definition qcoreevent.h:236
@ GraphicsSceneHoverMove
Definition qcoreevent.h:195
@ ApplicationFontChange
Definition qcoreevent.h:91
@ GraphicsSceneHelp
Definition qcoreevent.h:197
@ GrabKeyboard
Definition qcoreevent.h:235
@ WindowDeactivate
Definition qcoreevent.h:84
@ GrabMouse
Definition qcoreevent.h:233
@ GraphicsSceneLeave
Definition qcoreevent.h:203
Type type() const
Returns the event type.
Definition qcoreevent.h:299
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition qcoreevent.h:306
bool isAccepted() const
Definition qcoreevent.h:303
quint16 t
Definition qcoreevent.h:323
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:305
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:469
Qt::FocusReason reason() const
Returns the reason for this focus event.
Definition qevent.cpp:1566
\reentrant
Definition qfont.h:20
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition qfont.cpp:1854
void setResolveMask(uint mask)
Definition qfont.h:252
uint resolveMask() const
Definition qfont.h:251
The QGestureEvent class provides the description of triggered gestures.
Definition qgesture.h:244
void setWidget(QWidget *widget)
bool isAccepted(QGesture *) const
Returns true if the gesture is accepted; otherwise returns false.
Definition qgesture.cpp:962
void ignore(QGesture *)
Clears the accept flag parameter of the given gesture object, the equivalent of calling \l{QGestureEv...
Definition qgesture.cpp:953
void setAccepted(QGesture *, bool)
Sets the accept flag of the given gesture object to the specified value.
Definition qgesture.cpp:923
void recycle(QGesture *gesture)
bool filterEvent(QWidget *receiver, QEvent *event)
static QGestureManager * instance(InstanceCreation ic=ForceCreation)
void cleanupCachedGestures(QObject *target, Qt::GestureType type)
The QGesture class represents a gesture, containing properties that describe the corresponding user i...
Definition qgesture.h:29
@ CancelAllInContext
Definition qgesture.h:55
Qt::GestureType gestureType
the type of the gesture
Definition qgesture.h:34
The QGraphicsEffectSource class represents the source on which a QGraphicsEffect is installed on.
QGraphicsEffectSource * source() const
virtual void draw(QPainter *painter)=0
This pure virtual function draws the effect and is called whenever the source needs to be drawn.
bool isEnabled() const
The QGraphicsEllipseItem class provides an ellipse item that you can add to a QGraphicsScene.
QList< QRectF > exposed
QPixmapCache::Key key
QHash< QPaintDevice *, DeviceData > deviceData
The QGraphicsItemGroup class provides a container that treats a group of items as a single item.
void invalidateChildrenSceneTransform()
QVariant extra(Extra type) const
QGraphicsScene * scene
static bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b)
void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, const QRegion &exposedRegion, bool allItems=false) const
QGraphicsEffect * graphicsEffect
void markParentDirty(bool updateBoundingRect=false)
QMap< Qt::GestureType, Qt::GestureFlags > gestureContext
bool itemIsUntransformable() const
bool discardUpdateRequest(bool ignoreVisibleBit=false, bool ignoreDirtyBit=false, bool ignoreOpacity=false) const
bool childrenCombineOpacity() const
void clearSubFocus(QGraphicsItem *rootItem=nullptr, QGraphicsItem *stopItem=nullptr)
QList< QGraphicsItem * > children
QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const
virtual void updateSceneTransformFromParent()
QTransform genericMapFromSceneTransform(const QWidget *viewport=nullptr) const
quint32 paintedViewBoundingRectsNeedRepaint
QGraphicsItem * parent
virtual void resolvePalette(uint inheritedMask)
QHash< QWidget *, QRect > paintedViewBoundingRects
QGraphicsItemCache * extraItemCache() const
virtual void resolveFont(uint inheritedMask)
qreal combineOpacityFromParent(qreal parentOpacity) const
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
virtual bool contains(const QPointF &point) const
Returns true if this item contains point, which is in local coordinates; otherwise,...
QTransform deviceTransform(const QTransform &viewportTransform) const
bool isWidget() const
void setSelected(bool selected)
If selected is true and this item is selectable, this item is selected; otherwise,...
bool acceptDrops() const
Returns true if this item can accept drag and drop events; otherwise, returns false.
QScopedPointer< QGraphicsItemPrivate > d_ptr
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value)
This virtual function is called by QGraphicsItem to notify custom items that some part of the item's ...
qreal boundingRegionGranularity() const
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr)=0
This function, which is usually called by QGraphicsView, paints the contents of an item in local coor...
bool isWindow() const
void clearFocus()
Takes keyboard input focus from the item.
QGraphicsScene * scene() const
Returns the current scene for the item, or \nullptr if the item is not stored in a scene.
bool isSelected() const
Returns true if this item is selected; otherwise, false is returned.
virtual bool collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns true if this item collides with other; otherwise returns false.
virtual QPainterPath shape() const
Returns the shape of this item as a QPainterPath in local coordinates.
@ ItemContainsChildrenInShape
@ ItemSendsScenePositionChanges
@ ItemStopsClickFocusPropagation
QGraphicsWidget * window() const
QRectF sceneBoundingRect() const
Returns the bounding rect of this item in scene coordinates, by combining sceneTransform() with bound...
virtual QRectF boundingRect() const =0
This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be ...
bool isEnabled() const
Returns true if the item is enabled; otherwise, false is returned.
bool isBlockedByModalPanel(QGraphicsItem **blockingPanel=nullptr) const
QGraphicsObject * toGraphicsObject()
virtual void advance(int phase)
This virtual function is called twice for all items by the QGraphicsScene::advance() slot.
void setParentItem(QGraphicsItem *parent)
Sets this item's parent item to newParent.
Qt::MouseButtons acceptedMouseButtons() const
Returns the mouse buttons that this item accepts mouse events for.
QVariant data(int key) const
Returns this item's custom data for the key key as a QVariant.
bool isPanel() const
QGraphicsItem * panel() const
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
QTransform sceneTransform() const
QGraphicsItem * commonAncestorItem(const QGraphicsItem *other) const
bool isVisible() const
Returns true if the item is visible; otherwise, false is returned.
QGraphicsItem * focusItem() const
PanelModality panelModality() const
void setFocus(Qt::FocusReason focusReason=Qt::OtherFocusReason)
Gives keyboard input focus to this item.
GraphicsItemFlags flags() const
Returns this item's flags.
virtual bool sceneEvent(QEvent *event)
This virtual function receives events to this item.
bool acceptTouchEvents() const
bool isAncestorOf(const QGraphicsItem *child) const
Returns true if this item is an ancestor of child (i.e., if this item is child's parent,...
The QGraphicsLineItem class provides a line item that you can add to a QGraphicsScene.
The QGraphicsObject class provides a base class for all graphics items that require signals,...
The QGraphicsPixmapItem class provides a pixmap item that you can add to a QGraphicsScene.
The QGraphicsPolygonItem class provides a polygon item that you can add to a QGraphicsScene.
The QGraphicsProxyWidget class provides a proxy layer for embedding a QWidget in a QGraphicsScene.
The QGraphicsRectItem class provides a rectangle item that you can add to a QGraphicsScene.
The QGraphicsSceneBspTreeIndex class provides an implementation of a BSP indexing algorithm for disco...
int bspTreeDepth
the depth of the BSP index tree
The QGraphicsSceneContextMenuEvent class provides context menu events in the graphics view framework.
The QGraphicsSceneDragDropEvent class provides events for drag and drop in the graphics view framewor...
void setButtons(Qt::MouseButtons buttons)
void setMimeData(const QMimeData *data)
void setPossibleActions(Qt::DropActions actions)
void setProposedAction(Qt::DropAction action)
void setModifiers(Qt::KeyboardModifiers modifiers)
Qt::DropAction dropAction() const
Returns the action that was performed in this drag and drop.
void setDropAction(Qt::DropAction action)
This function lets the receiver of the drop set the drop action that was performed to action,...
void setScreenPos(const QPoint &pos)
void setPos(const QPointF &pos)
void setScenePos(const QPointF &pos)
QPointF scenePos() const
Returns the position of the mouse in scene coordinates.
The QGraphicsSceneEvent class provides a base class for all graphics view related events.
void setWidget(QWidget *widget)
QWidget * widget() const
Returns the widget where the event originated, or \nullptr if the event originates from another appli...
The QGraphicsSceneHelpEvent class provides events when a tooltip is requested.
The QGraphicsSceneHoverEvent class provides hover events in the graphics view framework.
void setScreenPos(const QPoint &pos)
void setPos(const QPointF &pos)
void setLastPos(const QPointF &pos)
QPoint screenPos() const
Returns the position of the mouse cursor in screen coordinates at the moment the hover event was sent...
void setScenePos(const QPointF &pos)
QPointF scenePos() const
Returns the position of the mouse cursor in scene coordinates at the moment the hover event was sent.
void setModifiers(Qt::KeyboardModifiers modifiers)
void setLastScenePos(const QPointF &pos)
void setLastScreenPos(const QPoint &pos)
Qt::KeyboardModifiers modifiers() const
The QGraphicsSceneLinearIndex class provides an implementation of a linear indexing algorithm for dis...
The QGraphicsSceneMouseEvent class provides mouse events in the graphics view framework.
Qt::MouseButton button() const
Returns the mouse button (if any) that caused the event.
QPointF pos() const
Returns the mouse cursor position in item coordinates.
void setButtonDownPos(Qt::MouseButton button, const QPointF &pos)
QPointF lastScenePos() const
Returns the last recorded mouse cursor position in scene coordinates.
QPointF buttonDownScenePos(Qt::MouseButton button) const
Returns the mouse cursor position in scene coordinates where the specified button was clicked.
QPoint buttonDownScreenPos(Qt::MouseButton button) const
Returns the mouse cursor position in screen coordinates where the specified button was clicked.
void setLastPos(const QPointF &pos)
QPoint lastScreenPos() const
Returns the last recorded mouse cursor position in screen coordinates.
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifiers in use at the time the event was sent.
QPoint screenPos() const
Returns the mouse cursor position in screen coordinates.
void setPos(const QPointF &pos)
Qt::MouseButtons buttons() const
Returns the combination of mouse buttons that were pressed at the time the event was sent.
void setButtonDownScenePos(Qt::MouseButton button, const QPointF &pos)
QPointF lastPos() const
Returns the last recorded mouse cursor position in item coordinates.
QPointF scenePos() const
Returns the mouse cursor position in scene coordinates.
void setButtonDownScreenPos(Qt::MouseButton button, const QPoint &pos)
QPointF buttonDownPos(Qt::MouseButton button) const
Returns the mouse cursor position in item coordinates where the specified button was clicked.
QList< QGraphicsItem * > cachedItemsUnderMouse
QMultiMap< QGraphicsItem *, QGraphicsItem * > sceneEventFilters
QList< QGraphicsView * > views
QHash< QGraphicsObject *, QSet< QGesture * > > cachedItemGestures
void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter)
void setScenePosItemEnabled(QGraphicsItem *item, bool enabled)
void addView(QGraphicsView *view)
void resetDirtyItem(QGraphicsItem *item, bool recursive=false)
QList< QGraphicsItem * > itemsAtPosition(const QPoint &screenPos, const QPointF &scenePos, QWidget *widget) const
Returns all items for the screen position in event.
void registerScenePosItem(QGraphicsItem *item)
QHash< QGesture *, QGraphicsObject * > gestureTargets
QList< QGraphicsItem * > modalPanels
QList< QGraphicsItem * > mouseGrabberItems
void gestureEventHandler(QGestureEvent *event)
QHash< QGraphicsObject *, QSet< QGesture * > > cachedAlreadyDeliveredGestures
QSet< QGraphicsItem * > scenePosItems
int findClosestTouchPointId(const QPointF &scenePos)
void leaveModal(QGraphicsItem *item)
QGraphicsItem * lastFocusItem
QList< QGraphicsWidget * > popupWidgets
void ungrabMouse(QGraphicsItem *item, bool itemIsDying=false)
QStyleOptionGraphicsItem styleOptionTmp
bool sendEvent(QGraphicsItem *item, QEvent *event)
QMap< int, QEventPoint > sceneCurrentTouchPoints
void grabMouse(QGraphicsItem *item, bool implicit=false)
void addPopup(QGraphicsWidget *widget)
void markDirty(QGraphicsItem *item, const QRectF &rect=QRectF(), bool invalidateChildren=false, bool force=false, bool ignoreOpacity=false, bool removingItemFromScene=false, bool updateBoundingRect=false)
QList< QGraphicsItem * > unpolishedItems
static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent)
void gestureTargetsAtHotSpots(const QSet< QGesture * > &gestures, Qt::GestureFlag flag, QHash< QGraphicsObject *, QSet< QGesture * > > *targets, QSet< QGraphicsObject * > *itemsSet=nullptr, QSet< QGesture * > *normal=nullptr, QSet< QGesture * > *conflicts=nullptr)
void removeView(QGraphicsView *view)
QMap< Qt::MouseButton, QPoint > mouseGrabberButtonDownScreenPos
QGraphicsWidget * tabFocusFirst
void ungrabGesture(QGraphicsItem *, Qt::GestureType gesture)
QHash< Qt::GestureType, int > grabbedGestures
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent)
QSet< QGraphicsItem * > selectedItems
void ungrabKeyboard(QGraphicsItem *item, bool itemIsDying=false)
void grabKeyboard(QGraphicsItem *item)
void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter)
void updateFont(const QFont &font)
bool filterDescendantEvent(QGraphicsItem *item, QEvent *event)
void touchEventHandler(QTouchEvent *touchEvent)
QGraphicsItem * passiveFocusItem
QList< QGraphicsObject * > cachedTargetItems
QGraphicsItem * activePanel
void drawItems(QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget)
void updatePalette(const QPalette &palette)
static QGraphicsScenePrivate * get(QGraphicsScene *q)
QList< QGraphicsItem * > hoverItems
void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason, bool emitFocusChanged=true)
void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection)
bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent)
QGraphicsItem * focusItem
void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, QRegion *exposedRegion, QWidget *widget, qreal parentOpacity=qreal(1.0), const QTransform *const effectTransform=nullptr)
void setFont_helper(const QFont &font)
void unregisterTopLevelItem(QGraphicsItem *item)
void cancelGesturesForChildren(QGesture *original)
void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent)
void enterModal(QGraphicsItem *item, QGraphicsItem::PanelModality panelModality=QGraphicsItem::NonModal)
void registerTopLevelItem(QGraphicsItem *item)
std::set< QRectF, UpdatedRectsCmp > updatedRects
QGraphicsItem * lastMouseGrabberItem
void leaveScene(QWidget *viewport)
bool dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
This event handler, for event hoverEvent, can be reimplemented in a subclass to receive hover enter e...
QGraphicsScene::ItemIndexMethod indexMethod
bool itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
void grabGesture(QGraphicsItem *, Qt::GestureType gesture)
quint32 scenePosDescendantsUpdatePending
QGraphicsItem * lastActivePanel
bool filterEvent(QGraphicsItem *item, QEvent *event)
QMap< Qt::MouseButton, QPointF > mouseGrabberButtonDownScenePos
void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren=false, qreal parentOpacity=qreal(1.0))
QGraphicsSceneIndex * index
QGraphicsItem * dragDropItem
QMap< int, QGraphicsItem * > itemForTouchPointId
void unregisterScenePosItem(QGraphicsItem *item)
void removeItemHelper(QGraphicsItem *item)
QList< QGraphicsItem * > keyboardGrabberItems
void sendHoverEvent(QEvent::Type type, QGraphicsItem *item, QGraphicsSceneHoverEvent *hoverEvent)
void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, QRegion *, QWidget *, qreal, const QTransform *const, bool, bool)
void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent)
void cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest, QGraphicsSceneDragDropEvent *source)
void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event)
QMap< Qt::MouseButton, QPointF > mouseGrabberButtonDownPos
quint32 lastMouseGrabberItemHasImplicitMouseGrab
void setPalette_helper(const QPalette &palette)
void removePopup(QGraphicsWidget *widget, bool itemIsDying=false)
void ensureSequentialTopLevelSiblingIndexes()
QList< QGraphicsItem * > topLevelItems
void sendDragDropEvent(QGraphicsItem *item, QGraphicsSceneDragDropEvent *dragDropEvent)
The QGraphicsSceneWheelEvent class provides wheel events in the graphics view framework.
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.
qreal minimumRenderSize
the minimal view-transformed size an item must have to be drawn
QList< QGraphicsItem * > items(Qt::SortOrder order=Qt::DescendingOrder) const
Returns an ordered list of all items on the scene.
void removeItem(QGraphicsItem *item)
Removes the item item and all its children from the scene.
void setFont(const QFont &font)
bool hasFocus() const
Returns true if the scene has focus; otherwise returns false.
void addItem(QGraphicsItem *item)
Adds or moves the item and all its children to this scene.
virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive drag move events f...
void changed(const QList< QRectF > &region)
This signal is emitted by QGraphicsScene when control reaches the event loop, if the scene content ch...
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event mouseEvent, can be reimplemented in a subclass to receive mouse press e...
QGraphicsProxyWidget * addWidget(QWidget *widget, Qt::WindowFlags wFlags=Qt::WindowFlags())
Creates a new QGraphicsProxyWidget for widget, adds it to the scene, and returns a pointer to the pro...
void destroyItemGroup(QGraphicsItemGroup *group)
Reparents all items in group to group's parent item, then removes group from the scene,...
void clearSelection()
Clears the current selection.
virtual void helpEvent(QGraphicsSceneHelpEvent *event)
This event handler, for event helpEvent, can be reimplemented in a subclass to receive help events.
void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason=Qt::OtherFocusReason)
Sets the scene's focus item to item, with the focus reason focusReason, after removing focus from any...
bool stickyFocus
whether clicking into the scene background will clear focus
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive drop events for th...
bool sendEvent(QGraphicsItem *item, QEvent *event)
virtual void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[], QWidget *widget=nullptr)
QStyle * style() const
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event mouseEvent, can be reimplemented in a subclass to receive mouse move ev...
void setFocusOnTouch(bool enabled)
bool isActive() const
QGraphicsPathItem * addPath(const QPainterPath &path, const QPen &pen=QPen(), const QBrush &brush=QBrush())
Creates and adds a path item to the scene, and returns the item pointer.
virtual void wheelEvent(QGraphicsSceneWheelEvent *event)
This event handler, for event wheelEvent, can be reimplemented in a subclass to receive mouse wheel e...
void setBspTreeDepth(int depth)
QGraphicsEllipseItem * addEllipse(const QRectF &rect, const QPen &pen=QPen(), const QBrush &brush=QBrush())
Creates and adds an ellipse item to the scene, and returns the item pointer.
void setStickyFocus(bool enabled)
virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive drag leave events ...
void setActivePanel(QGraphicsItem *item)
virtual void focusInEvent(QFocusEvent *event)
This event handler, for event focusEvent, can be reimplemented in a subclass to receive focus in even...
void invalidate(const QRectF &rect=QRectF(), SceneLayers layers=AllLayers)
Invalidates and schedules a redraw of the layers in rect on the scene.
QList< QGraphicsItem * > selectedItems() const
Returns a list of all currently selected items.
QGraphicsScene(QObject *parent=nullptr)
Constructs a QGraphicsScene object.
bool eventFilter(QObject *watched, QEvent *event) override
\reimp
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event mouseEvent, can be reimplemented in a subclass to receive mouse release...
QRectF sceneRect
the scene rectangle; the bounding rectangle of the scene
virtual void drawBackground(QPainter *painter, const QRectF &rect)
Draws the background of the scene using painter, before any items and the foreground are drawn.
void setForegroundBrush(const QBrush &brush)
void setStyle(QStyle *style)
QGraphicsItem * activePanel() const
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event mouseEvent, can be reimplemented in a subclass to receive mouse double-...
void advance()
This slot advances the scene by one step, by calling QGraphicsItem::advance() for all items on the sc...
QBrush foregroundBrush
the foreground brush of the scene.
int bspTreeDepth
the depth of QGraphicsScene's BSP index tree
void setPalette(const QPalette &palette)
virtual ~QGraphicsScene()
Removes and deletes all items from the scene object before destroying the scene object.
QList< QGraphicsView * > views() const
Returns a list of all the views that display this scene.
QRectF itemsBoundingRect() const
Calculates and returns the bounding rect of all items on the scene.
void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
ItemIndexMethod itemIndexMethod
the item indexing method.
QGraphicsPixmapItem * addPixmap(const QPixmap &pixmap)
Creates and adds a pixmap item to the scene, and returns the item pointer.
QGraphicsPolygonItem * addPolygon(const QPolygonF &polygon, const QPen &pen=QPen(), const QBrush &brush=QBrush())
Creates and adds a polygon item to the scene, and returns the item pointer.
void setItemIndexMethod(ItemIndexMethod method)
void selectionChanged()
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
This method is used by input methods to query a set of properties of the scene to be able to support ...
void setSceneRect(const QRectF &rect)
QGraphicsRectItem * addRect(const QRectF &rect, const QPen &pen=QPen(), const QBrush &brush=QBrush())
Creates and adds a rectangle item to the scene, and returns the item pointer.
void sceneRectChanged(const QRectF &rect)
This signal is emitted by QGraphicsScene whenever the scene rect changes.
QBrush backgroundBrush
the background brush of the scene.
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
This event handler, for event contextMenuEvent, can be reimplemented in a subclass to receive context...
void update(const QRectF &rect=QRectF())
Schedules a redraw of the area rect on the scene.
virtual bool focusNextPrevChild(bool next)
bool focusOnTouch
whether items gain focus when receiving a {touch begin} event.
virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive drag enter events ...
QPalette palette
the scene's default palette
void setActiveWindow(QGraphicsWidget *widget)
QList< QGraphicsItem * > collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns a list of all items that collide with item.
ItemIndexMethod
This enum describes the indexing algorithms QGraphicsScene provides for managing positional informati...
QPainterPath selectionArea() const
Returns the selection area that was previously set with setSelectionArea(), or an empty QPainterPath ...
QFont font
the scene's default font
QGraphicsItemGroup * createItemGroup(const QList< QGraphicsItem * > &items)
Groups all items in items into a new QGraphicsItemGroup, and returns a pointer to the group.
void clearFocus()
Clears focus from the scene.
QGraphicsWidget * activeWindow() const
virtual void keyPressEvent(QKeyEvent *event)
This event handler, for event keyEvent, can be reimplemented in a subclass to receive keypress events...
QGraphicsLineItem * addLine(const QLineF &line, const QPen &pen=QPen())
Creates and adds a line item to the scene, and returns the item pointer.
friend class QGraphicsSceneBspTreeIndex
virtual void inputMethodEvent(QInputMethodEvent *event)
This event handler, for event event, can be reimplemented in a subclass to receive input method event...
void setBackgroundBrush(const QBrush &brush)
virtual void focusOutEvent(QFocusEvent *event)
This event handler, for event focusEvent, can be reimplemented in a subclass to receive focus out eve...
QGraphicsTextItem * addText(const QString &text, const QFont &font=QFont())
Creates and adds a text item to the scene, and returns the item pointer.
virtual void keyReleaseEvent(QKeyEvent *event)
This event handler, for event keyEvent, can be reimplemented in a subclass to receive key release eve...
void setMinimumRenderSize(qreal minSize)
void setFocus(Qt::FocusReason focusReason=Qt::OtherFocusReason)
Sets focus on the scene by sending a QFocusEvent to the scene, passing focusReason as the reason.
QGraphicsItem * focusItem() const
When the scene is active, this functions returns the scene's current focus item, or \nullptr if no it...
bool event(QEvent *event) override
Processes the event event, and dispatches it to the respective event handlers.
void render(QPainter *painter, const QRectF &target=QRectF(), const QRectF &source=QRectF(), Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio)
Renders the source rect from scene into target, using painter.
QGraphicsSimpleTextItem * addSimpleText(const QString &text, const QFont &font=QFont())
Creates and adds a QGraphicsSimpleTextItem to the scene, and returns the item pointer.
QGraphicsItem * mouseGrabberItem() const
Returns the current mouse grabber item, or \nullptr if no item is currently grabbing the mouse.
virtual void drawForeground(QPainter *painter, const QRectF &rect)
Draws the foreground of the scene using painter, after the background and all items have been drawn.
QGraphicsItem * itemAt(const QPointF &pos, const QTransform &deviceTransform) const
The QGraphicsSimpleTextItem class provides a simple text path item that you can add to a QGraphicsSce...
The QGraphicsTextItem class provides a text item that you can add to a QGraphicsScene to display form...
bool updateRect(const QRect &rect)
QGraphicsView::ViewportUpdateMode viewportUpdateMode
The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene.
bool isTransformed() const
QTransform viewportTransform() const
Returns a matrix that maps scene coordinates to viewport coordinates.
QGraphicsWidget * focusNext
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.
Qt::WindowFlags windowFlags
the widget's window flags
Qt::WindowType windowType() const
Returns the widgets window type.
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
virtual void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr)
This virtual function is called by QGraphicsScene to draw the window frame for windows using painter,...
bool autoFillBackground
whether the widget background is filled automatically
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
QPalette palette
the widget's palette
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
static QPalette palette()
Returns the current application palette.
static QInputMethod * inputMethod()
returns the input method.
\inmodule QtCore
Definition qhash.h:1135
\inmodule QtCore
Definition qhash.h:1093
\inmodule QtCore
Definition qhash.h:818
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:956
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1202
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1209
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1205
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition qhash.h:1076
iterator erase(const_iterator it)
Definition qhash.h:1223
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:926
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
DeviceType type
quint64 timestamp() const
Returns the window system's timestamp for this event.
Definition qevent.h:58
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately before the event occurred.
Definition qevent.h:56
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:624
void commit()
Commits the word user is currently composing to the editor.
The QKeyEvent class describes a key event.
Definition qevent.h:423
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1465
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:433
\inmodule QtCore
Definition qline.h:182
qreal length() const
Returns the length of the line.
Definition qline.cpp:542
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
T & first()
Definition qlist.h:628
void removeAt(qsizetype i)
Definition qlist.h:573
const T & constLast() const noexcept
Definition qlist.h:633
bool removeOne(const AT &t)
Definition qlist.h:581
iterator end()
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
T value(qsizetype i) const
Definition qlist.h:661
const_reverse_iterator crbegin() const noexcept
Definition qlist.h:621
const_iterator constBegin() const noexcept
Definition qlist.h:615
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
value_type takeLast()
Definition qlist.h:550
qsizetype removeAll(const AT &t)
Definition qlist.h:575
void squeeze()
Definition qlist.h:767
void prepend(rvalue_ref t)
Definition qlist.h:456
iterator begin()
Definition qlist.h:608
const T & constFirst() const noexcept
Definition qlist.h:630
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
const_iterator constEnd() const noexcept
Definition qlist.h:616
void clear()
Definition qlist.h:417
const_reverse_iterator crend() const noexcept
Definition qlist.h:622
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:356
iterator erase(const_iterator it)
Definition qmap.h:618
bool contains(const Key &key) const
Definition qmap.h:340
size_type remove(const Key &key)
Definition qmap.h:299
bool isEmpty() const
Definition qmap.h:268
T & first()
Definition qmap.h:418
iterator begin()
Definition qmap.h:597
iterator end()
Definition qmap.h:601
const_iterator constBegin() const
Definition qmap.h:599
const_iterator constEnd() const
Definition qmap.h:603
T take(const Key &key)
Definition qmap.h:321
\inmodule QtCore
Definition qmetaobject.h:18
iterator lowerBound(const Key &key)
Definition qmap.h:1397
bool contains(const Key &key) const
Definition qmap.h:1018
iterator end()
Definition qmap.h:1300
iterator insert(const Key &key, const T &value)
Definition qmap.h:1425
iterator erase(const_iterator it)
Definition qmap.h:1317
iterator upperBound(const Key &key)
Definition qmap.h:1411
iterator begin()
Definition qmap.h:1296
QObject * q_ptr
Definition qobject.h:60
QObjectList children
Definition qobject.h:62
QObject * parent
Definition qobject.h:61
bool isSignalConnected(uint signalIdx, bool checkDeclarative=true) const
Definition qobject.cpp:450
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1363
QScopedPointer< QObjectData > d_ptr
Definition qobject.h:338
qreal devicePixelRatio() const
virtual int devType() const
int width() const
int height() const
\inmodule QtGui
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
const QPen & pen() const
Returns the painter's current pen.
Qt::LayoutDirection layoutDirection() const
Returns the layout direction used by the painter when drawing text.
RenderHints renderHints() const
Returns a flag that specifies the rendering hints that are set for this painter.
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition qpainter.h:519
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or \nullptr if the painter is n...
qreal opacity() const
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation.
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool begin(QPaintDevice *)
Begins painting the paint device and returns true if successful; otherwise returns false.
void setBrushOrigin(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpainter.h:698
void setClipPath(const QPainterPath &path, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip path for the painter to the given path, with the clip operation.
void setLayoutDirection(Qt::LayoutDirection direction)
Sets the layout direction used by the painter when drawing text, to the specified direction.
void restore()
Restores the current painter state (pops a saved state off the stack).
const QTransform & worldTransform() const
Returns the world transformation matrix.
const QBrush & brush() const
Returns the painter's current brush.
void setOpacity(qreal opacity)
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
void save()
Saves the current painter state (pushes the state onto a stack).
void setWorldTransform(const QTransform &matrix, bool combine=false)
Sets the world transformation matrix.
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device.
void setBrush(const QBrush &brush)
Sets the painter's brush to the given brush.
bool end()
Ends painting.
@ CompositionMode_Source
Definition qpainter.h:101
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
void setRenderHints(RenderHints hints, bool on=true)
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
void setClipRegion(const QRegion &, Qt::ClipOperation op=Qt::ReplaceClip)
Sets the clip region to the given region using the specified clip operation.
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
void setResolveMask(ResolveMask mask)
ResolveMask resolveMask() const
QPalette resolve(const QPalette &other) const
Returns a new QPalette that is a union of this instance and other.
const QBrush & window() const
Returns the window (general background) brush of the current color group.
Definition qpalette.h:92
static bool pathToRect(const QPainterPath &path, QRectF *rect=nullptr)
\inmodule QtGui
Definition qpen.h:25
The QPixmapCache::Key class can be used for efficient access to the QPixmapCache.
static bool find(const QString &key, QPixmap *pixmap)
Looks for a cached pixmap associated with the given key in the cache.
static void remove(const QString &key)
Removes the pixmap associated with key from the cache.
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
QSize size() const
Returns the size of the pixmap.
Definition qpixmap.cpp:497
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:460
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the pixmap.
Definition qpixmap.cpp:608
QRect rect() const
Returns the pixmap's enclosing rectangle.
Definition qpixmap.cpp:509
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition qpixmap.cpp:854
qreal devicePixelRatio() const
Returns the device pixel ratio for the pixmap.
Definition qpixmap.cpp:580
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:394
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
const QPointingDevice * pointingDevice() const
Returns the source device from which this event originates.
Definition qevent.cpp:327
const QList< QEventPoint > & points() const
Returns a list of points in this pointer event.
Definition qevent.h:86
\inmodule QtCore
Definition qpointer.h:18
T * data() const
Definition qpointer.h:56
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
void update()
Schedules the window to render another frame.
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:647
QRect toAlignedRect() const noexcept
Definition qrect.cpp:2330
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr QRectF translated(qreal dx, qreal dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:748
constexpr QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:799
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:496
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:644
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:845
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:497
constexpr void setRect(qreal x, qreal y, qreal w, qreal h) noexcept
Sets the coordinates of the rectangle's top-left corner to (x, y), and its size to the given width an...
Definition qrect.h:767
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:166
bool intersects(const QRect &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e., there is at least one pixel...
Definition qrect.cpp:1065
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:372
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
QRect normalized() const noexcept
Returns a normalized rectangle; i.e., a rectangle that has a non-negative width and height.
Definition qrect.cpp:273
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:163
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:369
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:851
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:241
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
Definition qrect.h:244
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
QRect boundingRect() const noexcept
Returns the bounding rectangle of this region.
int rectCount() const noexcept
bool intersects(const QRegion &r) const
Definition qregion.cpp:613
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
T * data() const noexcept
Returns the value of the pointer referenced by this object.
Definition qset.h:18
qsizetype size() const
Definition qset.h:50
QList< T > values() const
Definition qset.h:297
bool remove(const T &value)
Definition qset.h:63
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
bool isEmpty() const
Definition qset.h:52
iterator erase(const_iterator i)
Definition qset.h:145
bool contains(const T &value) const
Definition qset.h:71
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:123
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem.
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
QEventPoint & point(int touchId)
QMap< int, QEventPoint > points
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr, const QRect &rect={}, int msecShowTime=-1)
Shows text as a tool tip, with the global position pos as the point of interest.
Definition qtooltip.cpp:427
static void hideText()
Definition qtooltip.h:19
The QTouchEvent class contains parameters that describe a touch event.
Definition qevent.h:916
QObject * target() const
Returns the target object within the window on which the event occurred.
Definition qevent.h:934
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
qreal dx() const
Returns the horizontal translation factor.
Definition qtransform.h:235
QPoint map(const QPoint &p) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis.
QTransform inverted(bool *invertible=nullptr) const
Returns an inverted copy of this matrix.
TransformationType type() const
Returns the transformation type of this matrix.
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
QRect mapRect(const QRect &) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
TransformationType
\value TxNone \value TxTranslate \value TxScale \value TxRotate \value TxShear \value TxProject
Definition qtransform.h:22
qreal dy() const
Returns the vertical translation factor.
Definition qtransform.h:239
\inmodule QtCore
Definition qvariant.h:64
QSize toSize() const
Returns the variant as a QSize if the variant has userType() \l QMetaType::QSize; otherwise returns a...
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
bool isVisibleTo(const QWidget *) const
Returns true if this widget would become visible if ancestor is shown; otherwise returns false.
Definition qwidget.cpp:8689
QWidget * focusWidget() const
Returns the last child of this widget that setFocus had been called on.
Definition qwidget.cpp:6851
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
void setFocus()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:423
bool isEnabled() const
Definition qwidget.h:814
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
Definition qwidget.h:140
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
bool isVisible() const
Definition qwidget.h:874
QPointF mapFromGlobal(const QPointF &) const
Translates the global screen coordinate pos to widget coordinates.
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
QOpenGLWidget * widget
[1]
QString text
QPushButton * button
[2]
double e
QSet< QString >::iterator it
auto signalIndex
rect
[4]
QPixmap pix
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
InputMethodQuery
MouseButton
Definition qnamespace.h:55
@ WA_AcceptTouchEvents
Definition qnamespace.h:403
@ WA_SetStyle
Definition qnamespace.h:355
@ IntersectClip
LayoutDirection
AspectRatioMode
@ KeepAspectRatioByExpanding
@ KeepAspectRatio
@ IgnoreAspectRatio
@ GestureCanceled
@ GestureStarted
@ GestureFinished
@ WheelFocus
Definition qnamespace.h:110
@ ClickFocus
Definition qnamespace.h:108
@ TabFocus
Definition qnamespace.h:107
ItemSelectionOperation
@ ReplaceSelection
@ transparent
Definition qnamespace.h:46
@ Key_Tab
Definition qnamespace.h:659
@ Key_Backtab
Definition qnamespace.h:660
SortOrder
Definition qnamespace.h:120
@ DescendingOrder
Definition qnamespace.h:122
@ AscendingOrder
Definition qnamespace.h:121
@ ShiftModifier
@ ControlModifier
@ AltModifier
ItemSelectionMode
@ IntersectsItemShape
@ IntersectsItemBoundingRect
@ NoBrush
@ IgnoreAction
@ QueuedConnection
@ DeviceCoordinates
@ LogicalCoordinates
GestureType
GestureFlag
@ ReceivePartialGestures
@ IgnoredGesturesPropagateToParent
constexpr Initialization Uninitialized
@ FramelessWindowHint
Definition qnamespace.h:224
@ ToolTip
Definition qnamespace.h:212
@ Popup
Definition qnamespace.h:210
FocusReason
@ PopupFocusReason
@ BacktabFocusReason
@ MouseFocusReason
@ OtherFocusReason
@ ActiveWindowFocusReason
@ TabFocusReason
Definition brush.cpp:5
std::pair< T1, T2 > QPair
#define qApp
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const EGLAttrib EGLOutputLayerEXT * layers
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:303
bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
Returns true if item1 is on top of item2.
static void setClip(QPainter *painter, QGraphicsItem *item)
static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
static void setWorldTransform(QPainter *painter, const QTransform *const transformPtr, const QTransform *effectTransform)
static bool transformIsSimple(const QTransform &transform)
QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
#define ENSURE_TRANSFORM_PTR
static void _q_paintItem(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool useWindowOpacity, bool painterStateProtection)
static bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, const QRectF &rect, bool itemIsUntransformable)
static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &pixmapExposed, const QTransform &itemToPixmap, QPainter::RenderHints renderHints, const QStyleOptionGraphicsItem *option, bool painterStateProtection)
static QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
static QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item)
static void _q_adjustRect(QRectF *rect)
bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
#define qWarning
Definition qlogging.h:162
return ret
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum mode
GLint GLsizei GLsizei height
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei GLsizei GLfloat distance
GLint GLsizei width
GLenum type
GLboolean GLuint group
GLenum target
GLbitfield flags
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLboolean GLboolean g
GLfloat n
GLint y
GLsizei GLsizei GLchar * source
struct _cl_event * event
GLuint GLenum GLenum transform
GLhandleARB obj
[2]
GLenum query
GLuint res
GLuint GLenum matrix
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
GLuint GLenum option
GLfixed GLfixed GLint GLint order
GLenum GLenum GLenum GLenum GLenum scale
static const QRectF boundingRect(const QPointF *points, int pointCount)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
size_t quintptr
Definition qtypes.h:72
ptrdiff_t qsizetype
Definition qtypes.h:70
double qreal
Definition qtypes.h:92
#define enabled
#define disabled
QWidget * panel
Definition settings.cpp:7
QList< int > list
[14]
QFileInfo info(fileName)
[8]
QFileInfo fi("c:/temp/foo")
[newstuff]
obj metaObject() -> className()
QObject::connect nullptr
QGraphicsItem * item
view viewport() -> scroll(dx, dy, deviceRect)
rect deviceTransform(view->viewportTransform()).map(QPointF(0
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
widget render & pixmap
QPainter painter(this)
[7]
QNetworkProxy proxy
[0]
QQuickView * view
[0]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:955
bool contains(const AT &t) const noexcept
Definition qlist.h:44
qsizetype lastIndexOf(const AT &t, qsizetype from=-1) const noexcept
Definition qlist.h:962
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent