QtBase  v6.3.1
qgraphicsscene.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
204 #include "qgraphicsscene.h"
205 
206 #include "qgraphicsitem.h"
207 #include "qgraphicsitem_p.h"
208 #include "qgraphicslayout.h"
209 #include "qgraphicsscene_p.h"
210 #include "qgraphicssceneevent.h"
211 #include "qgraphicsview.h"
212 #include "qgraphicsview_p.h"
213 #include "qgraphicswidget.h"
214 #include "qgraphicswidget_p.h"
215 #include "qgraphicssceneindex_p.h"
218 
219 #include <QtCore/qdebug.h>
220 #include <QtCore/qlist.h>
221 #include <QtCore/qmath.h>
222 #include <QtCore/qrect.h>
223 #include <QtCore/qset.h>
224 #include <QtCore/qstack.h>
225 #include <QtCore/qtimer.h>
226 #include <QtCore/qvarlengtharray.h>
227 #include <QtCore/QMetaMethod>
228 #include <QtWidgets/qapplication.h>
229 #include <QtGui/qevent.h>
230 #include <QtWidgets/qgraphicslayout.h>
231 #include <QtWidgets/qgraphicsproxywidget.h>
232 #include <QtWidgets/qgraphicswidget.h>
233 #include <QtGui/qpaintengine.h>
234 #include <QtGui/qpainter.h>
235 #include <QtGui/qpainterpath.h>
236 #include <QtGui/qpixmapcache.h>
237 #include <QtGui/qpolygon.h>
238 #include <QtGui/qpointingdevice.h>
239 #include <QtWidgets/qstyleoption.h>
240 #if QT_CONFIG(tooltip)
241 #include <QtWidgets/qtooltip.h>
242 #endif
243 #include <QtGui/qtransform.h>
244 #include <QtGui/qinputmethod.h>
245 #include <private/qapplication_p.h>
246 #include <private/qevent_p.h>
247 #include <QtGui/private/qeventpoint_p.h>
248 #include <private/qobject_p.h>
249 #if QT_CONFIG(graphicseffect)
250 #include <private/qgraphicseffect_p.h>
251 #endif
252 #include <private/qgesturemanager_p.h>
253 #include <private/qpathclipper_p.h>
254 
255 // #define GESTURE_DEBUG
256 #ifndef GESTURE_DEBUG
257 # define DEBUG if (0) qDebug
258 #else
259 # define DEBUG qDebug
260 #endif
261 
263 
265 
266 static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
267 {
268  hover->setWidget(mouseEvent->widget());
269  hover->setPos(mouseEvent->pos());
270  hover->setScenePos(mouseEvent->scenePos());
271  hover->setScreenPos(mouseEvent->screenPos());
272  hover->setLastPos(mouseEvent->lastPos());
273  hover->setLastScenePos(mouseEvent->lastScenePos());
274  hover->setLastScreenPos(mouseEvent->lastScreenPos());
275  hover->setModifiers(mouseEvent->modifiers());
276  hover->setAccepted(mouseEvent->isAccepted());
277 }
278 
283  : indexMethod(QGraphicsScene::BspTreeIndex),
284  index(nullptr),
285  lastItemCount(0),
286  hasSceneRect(false),
287  dirtyGrowingItemsBoundingRect(true),
288  updateAll(false),
289  calledEmitUpdated(false),
290  processDirtyItemsEmitted(false),
291  needSortTopLevelItems(true),
292  holesInTopLevelSiblingIndex(false),
293  topLevelSequentialOrdering(true),
294  scenePosDescendantsUpdatePending(false),
295  stickyFocus(false),
296  hasFocus(false),
297  lastMouseGrabberItemHasImplicitMouseGrab(false),
298  allItemsIgnoreHoverEvents(true),
299  allItemsUseDefaultCursor(true),
300  painterStateProtection(true),
301  sortCacheEnabled(false),
302  allItemsIgnoreTouchEvents(true),
303  focusOnTouch(true),
304  minimumRenderSize(0.0),
305  selectionChanging(0),
306  rectAdjust(2),
307  focusItem(nullptr),
308  lastFocusItem(nullptr),
309  passiveFocusItem(nullptr),
310  tabFocusFirst(nullptr),
311  activePanel(nullptr),
312  lastActivePanel(nullptr),
313  activationRefCount(0),
314  childExplicitActivation(0),
315  lastMouseGrabberItem(nullptr),
316  dragDropItem(nullptr),
317  enterWidget(nullptr),
318  lastDropAction(Qt::IgnoreAction),
319  style(nullptr)
320 {
321 }
322 
327 {
328  Q_Q(QGraphicsScene);
329 
331 
332  // Keep this index so we can check for connected slots later on.
333  changedSignalIndex = signalIndex("changed(QList<QRectF>)");
334  processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()");
335  polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()");
336 
337  qApp->d_func()->scene_list.append(q);
338  q->update();
339 }
340 
345 {
346  return q->d_func();
347 }
348 
350 {
351  Q_Q(QGraphicsScene);
352  calledEmitUpdated = false;
353 
355  if (!hasSceneRect) {
356  const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
357  growingItemsBoundingRect |= q->itemsBoundingRect();
358  if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
359  emit q->sceneRectChanged(growingItemsBoundingRect);
360  }
362  }
363 
364  // Ensure all views are connected if anything is connected. This disables
365  // the optimization that items send updates directly to the views, but it
366  // needs to happen in order to keep compatibility with the behavior from
367  // Qt 4.4 and backward.
369  for (auto view : qAsConst(views)) {
370  if (!view->d_func()->connectedToScene) {
371  view->d_func()->connectedToScene = true;
372  q->connect(q, SIGNAL(changed(QList<QRectF>)),
373  view, SLOT(updateScene(QList<QRectF>)));
374  }
375  }
376  } else {
377  if (views.isEmpty()) {
378  updateAll = false;
379  return;
380  }
381  for (auto view : qAsConst(views))
382  view->d_func()->processPendingUpdates();
383  // It's important that we update all views before we dispatch, hence two for-loops.
384  for (auto view : qAsConst(views))
385  view->d_func()->dispatchPendingUpdateRequests();
386  return;
387  }
388 
389  // Notify the changes to anybody interested.
390  QList<QRectF> oldUpdatedRects;
391  if (updateAll) {
392  oldUpdatedRects << q->sceneRect();
393  } else {
394  // Switch to a ranged constructor in Qt 6...
395  oldUpdatedRects.reserve(int(updatedRects.size()));
396  std::copy(updatedRects.cbegin(), updatedRects.cend(),
397  std::back_inserter(oldUpdatedRects));
398  }
399 
400  updateAll = false;
401  updatedRects.clear();
402  emit q->changed(oldUpdatedRects);
403 }
404 
411 {
413  needSortTopLevelItems = true; // ### maybe false
416 }
417 
424 {
429  else
431  // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
432  // the item is not guaranteed to be at the index after the list is sorted
433  // (see ensureSortedTopLevelItems()).
434  item->d_ptr->siblingIndex = -1;
437 }
438 
443 {
444  if (unpolishedItems.isEmpty())
445  return;
446 
447  const QVariant booleanTrueVariant(true);
448  QGraphicsItem *item = nullptr;
449  QGraphicsItemPrivate *itemd = nullptr;
450  const int oldUnpolishedCount = unpolishedItems.count();
451 
452  for (int i = 0; i < oldUnpolishedCount; ++i) {
454  if (!item)
455  continue;
456  itemd = item->d_ptr.data();
457  itemd->pendingPolish = false;
458  if (!itemd->explicitlyHidden) {
459  item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
461  }
462  if (itemd->isWidget) {
465  }
466  }
467 
468  if (unpolishedItems.count() == oldUnpolishedCount) {
469  // No new items were added to the vector.
471  } else {
472  // New items were appended; keep them and remove the old ones.
473  unpolishedItems.remove(0, oldUnpolishedCount);
476  }
477 }
478 
480 {
481  processDirtyItemsEmitted = false;
482 
483  if (updateAll) {
485  // No need for further processing (except resetting the dirty states).
486  // The growingItemsBoundingRect is updated in _q_emitUpdated.
487  for (auto topLevelItem : qAsConst(topLevelItems))
488  resetDirtyItem(topLevelItem, /*recursive=*/true);
489  return;
490  }
491 
492  const bool wasPendingSceneUpdate = calledEmitUpdated;
493  const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
494 
495  // Process items recursively.
496  for (auto topLevelItem : qAsConst(topLevelItems))
497  processDirtyItemsRecursive(topLevelItem);
498 
500  if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
501  emit q_func()->sceneRectChanged(growingItemsBoundingRect);
502 
503  if (wasPendingSceneUpdate)
504  return;
505 
506  for (auto view : qAsConst(views))
507  view->d_func()->processPendingUpdates();
508 
509  if (calledEmitUpdated) {
510  // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
511  // and we cannot wait for the control to reach the eventloop before the
512  // changed signal is emitted, so we emit it now.
513  _q_emitUpdated();
514  }
515 
516  // Immediately dispatch all pending update requests on the views.
517  for (auto view : qAsConst(views))
518  view->d_func()->dispatchPendingUpdateRequests();
519 }
520 
525 {
527  while (p) {
529  p = p->d_ptr->parent;
530  }
533  QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection);
534  }
535 }
536 
541 {
544 }
545 
550 {
553 }
554 
559 {
560  for (QGraphicsItem *item : qAsConst(scenePosItems)) {
562  while (p) {
564  p = p->d_ptr->parent;
565  }
566  }
568 }
569 
583 {
584  Q_Q(QGraphicsScene);
585 
586  // Clear focus on the item to remove any reference in the focusWidget chain.
587  item->clearFocus();
588 
589  markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false,
590  /*ignoreOpacity=*/false, /*removingItemFromScene=*/true);
591 
592  if (item->d_ptr->inDestructor) {
593  // The item is actually in its destructor, we call the special method in the index.
594  index->deleteItem(item);
595  } else {
596  // Can potentially call item->boundingRect() (virtual function), that's why
597  // we only can call this function if the item is not in its destructor.
598  index->removeItem(item);
599  }
600 
602 
605 
606  QGraphicsScene *oldScene = item->d_func()->scene;
607  item->d_func()->scene = nullptr;
608 
609  //We need to remove all children first because they might use their parent
610  //attributes (e.g. sceneTransform).
611  if (!item->d_ptr->inDestructor) {
612  // Remove all children recursively
613  for (auto child : qAsConst(item->d_ptr->children))
614  q->removeItem(child);
615  }
616 
617  if (!item->d_ptr->inDestructor && !item->parentItem() && item->isWidget()) {
618  QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
619  widget->d_func()->fixFocusChainBeforeReparenting(nullptr, oldScene, nullptr);
620  }
621 
622  // Unregister focus proxy.
624 
625  // Remove from parent, or unregister from toplevels.
626  if (QGraphicsItem *parentItem = item->parentItem()) {
627  if (parentItem->scene()) {
628  Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
629  "Parent item's scene is different from this item's scene");
630  item->setParentItem(nullptr);
631  }
632  } else {
634  }
635 
636  // Reset the mouse grabber and focus item data.
637  if (item == focusItem)
638  focusItem = nullptr;
639  if (item == lastFocusItem)
640  lastFocusItem = nullptr;
641  if (item == passiveFocusItem)
642  passiveFocusItem = nullptr;
643  if (item == activePanel) {
644  // ### deactivate...
645  activePanel = nullptr;
646  }
647  if (item == lastActivePanel)
648  lastActivePanel = nullptr;
649 
650  // Change tabFocusFirst to the next widget in focus chain if removing the current one.
651  if (item == tabFocusFirst) {
652  QGraphicsWidgetPrivate *wd = tabFocusFirst->d_func();
653  if (wd->focusNext && wd->focusNext != tabFocusFirst && wd->focusNext->scene() == q)
654  tabFocusFirst = wd->focusNext;
655  else
656  tabFocusFirst = nullptr;
657  }
658 
659  // Cancel active touches
660  {
662  while (it != itemForTouchPointId.end()) {
663  if (it.value() == item) {
666  } else {
667  ++it;
668  }
669  }
670  }
671 
672  // Disable selectionChanged() for individual items
674  int oldSelectedItemsSize = selectedItems.size();
675 
676  // Update selected & hovered item bookkeeping
680  if (item->d_ptr->pendingPolish) {
681  const int unpolishedIndex = unpolishedItems.indexOf(item);
682  if (unpolishedIndex != -1)
683  unpolishedItems[unpolishedIndex] = 0;
684  item->d_ptr->pendingPolish = false;
685  }
687 
688  //We remove all references of item from the sceneEventFilter arrays
690  while (iterator != sceneEventFilters.end()) {
691  if (iterator.value() == item || iterator.key() == item)
693  else
694  ++iterator;
695  }
696 
698  leaveModal(item);
699 
700  // Reset the mouse grabber and focus item data.
702  ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
703 
704  // Reset the keyboard grabber
706  ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
707 
708  // Reset the last mouse grabber item
709  if (item == lastMouseGrabberItem)
710  lastMouseGrabberItem = nullptr;
711 
712  // Reset the current drop item
713  if (item == dragDropItem)
714  dragDropItem = nullptr;
715 
716  // Re-enable selectionChanged() for individual items
718  if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
719  emit q->selectionChanged();
720 
721 #ifndef QT_NO_GESTURES
722  for (auto it = gestureTargets.begin(); it != gestureTargets.end();) {
723  if (it.value() == item)
725  else
726  ++it;
727  }
728 
733  }
734 
735  for (auto it = item->d_ptr->gestureContext.constBegin();
737  ungrabGesture(item, it.key());
738 #endif // QT_NO_GESTURES
739 }
740 
745 {
746  Q_Q(QGraphicsScene);
747  if (item && item->scene() != q) {
748  qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene",
749  item);
750  return;
751  }
752 
753  // Ensure the scene has focus when we change panel activation.
754  q->setFocus(Qt::ActiveWindowFocusReason);
755 
756  // Find the item's panel.
757  QGraphicsItem *panel = item ? item->panel() : nullptr;
758  lastActivePanel = panel ? activePanel : nullptr;
759  if (panel == activePanel || (!q->isActive() && !duringActivationEvent))
760  return;
761 
762  QGraphicsItem *oldFocusItem = focusItem;
763 
764  // Deactivate the last active panel.
765  if (activePanel) {
767  // Remove focus from the current focus item.
768  if (fi == q->focusItem())
769  setFocusItemHelper(nullptr, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
770  }
771 
773  q->sendEvent(activePanel, &event);
774  } else if (panel && !duringActivationEvent) {
775  // Deactivate the scene if changing activation to a panel.
776  const auto items = q->items();
778  for (QGraphicsItem *item : items) {
779  if (item->isVisible() && !item->isPanel() && !item->parentItem())
780  q->sendEvent(item, &event);
781  }
782  }
783 
784  // Update activate state.
785  activePanel = panel;
788 
789  // Activate
790  if (panel) {
792  q->sendEvent(panel, &event);
793 
794  // Set focus on the panel's focus item, or itself if it's
795  // focusable, or on the first focusable item in the panel's
796  // focus chain as a last resort.
797  if (QGraphicsItem *focusItem = panel->focusItem()) {
798  setFocusItemHelper(focusItem, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
799  } else if (panel->flags() & QGraphicsItem::ItemIsFocusable) {
800  setFocusItemHelper(panel, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
801  } else if (panel->isWidget()) {
802  QGraphicsWidget *fw = static_cast<QGraphicsWidget *>(panel)->d_func()->focusNext;
803  do {
804  if (fw->focusPolicy() & Qt::TabFocus) {
805  setFocusItemHelper(fw, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false);
806  break;
807  }
808  fw = fw->d_func()->focusNext;
809  } while (fw != panel);
810  }
811  } else if (q->isActive()) {
812  const auto items = q->items();
813  // Activate the scene
815  for (QGraphicsItem *item : items) {
816  if (item->isVisible() && !item->isPanel() && !item->parentItem())
817  q->sendEvent(item, &event);
818  }
819  }
820 
821  emit q->focusItemChanged(focusItem, oldFocusItem, Qt::ActiveWindowFocusReason);
822 }
823 
835  Qt::FocusReason focusReason,
836  bool emitFocusChanged)
837 {
838  Q_Q(QGraphicsScene);
839  if (item == focusItem)
840  return;
841 
842  // Clear focus if asked to set focus on something that can't
843  // accept input focus.
845  || !item->isVisible() || !item->isEnabled())) {
846  item = nullptr;
847  }
848 
849  // Set focus on the scene if an item requests focus.
850  if (item) {
851  q->setFocus(focusReason);
852  if (item == focusItem) {
853  if (emitFocusChanged)
854  emit q->focusItemChanged(focusItem, (QGraphicsItem *)nullptr, focusReason);
855  return;
856  }
857  }
858 
859  QGraphicsItem *oldFocusItem = focusItem;
860  if (focusItem) {
862 
863 #ifndef QT_NO_IM
865  // Close any external input method panel. This happens
866  // automatically by removing WA_InputMethodEnabled on
867  // the views, but if we are changing focus, we have to
868  // do it ourselves.
869  if (qApp)
871  }
872 #endif //QT_NO_IM
873 
874  focusItem = nullptr;
875  QFocusEvent event(QEvent::FocusOut, focusReason);
877  }
878 
879  // This handles the case that the item has been removed from the
880  // scene in response to the FocusOut event.
881  if (item && item->scene() != q)
882  item = nullptr;
883 
884  if (item)
885  focusItem = item;
887 
888  if (item) {
889  QFocusEvent event(QEvent::FocusIn, focusReason);
890  sendEvent(item, &event);
891  }
892 
893  if (emitFocusChanged)
894  emit q->focusItemChanged(focusItem, oldFocusItem, focusReason);
895 }
896 
901 {
902  Q_ASSERT(widget);
904  popupWidgets << widget;
905  if (QGraphicsWidget *focusWidget = widget->focusWidget()) {
906  focusWidget->setFocus(Qt::PopupFocusReason);
907  } else {
909  if (focusItem && popupWidgets.size() == 1) {
912  }
913  }
915 }
916 
927 {
928  Q_ASSERT(widget);
930  Q_ASSERT(index != -1);
931 
932  for (int i = popupWidgets.size() - 1; i >= index; --i) {
934  ungrabMouse(widget, itemIsDying);
935  if (focusItem && popupWidgets.isEmpty()) {
938  } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) {
939  ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying);
940  }
941  if (!itemIsDying && widget->isVisible()) {
942  widget->QGraphicsItem::d_ptr->setVisibleHelper(false, /* explicit = */ false);
943  }
944  }
945 }
946 
951 {
952  // Append to list of mouse grabber items, and send a mouse grab event.
954  if (mouseGrabberItems.constLast() == item) {
955  Q_ASSERT(!implicit);
957  qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
958  } else {
959  // Upgrade to an explicit mouse grab
961  }
962  } else {
963  qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
965  }
966  return;
967  }
968 
969  // Send ungrab event to the last grabber.
970  if (!mouseGrabberItems.isEmpty()) {
973  // Implicit mouse grab is immediately lost.
974  last->ungrabMouse();
975  } else {
976  // Just send ungrab event to current grabber.
977  QEvent ungrabEvent(QEvent::UngrabMouse);
978  sendEvent(last, &ungrabEvent);
979  }
980  }
981 
984 
985  // Send grab event to current grabber.
986  QEvent grabEvent(QEvent::GrabMouse);
987  sendEvent(item, &grabEvent);
988 }
989 
994 {
996  if (index == -1) {
997  qWarning("QGraphicsItem::ungrabMouse: not a mouse grabber");
998  return;
999  }
1000 
1001  if (item != mouseGrabberItems.constLast()) {
1002  // Recursively ungrab the next mouse grabber until we reach this item
1003  // to ensure state consistency.
1004  ungrabMouse(mouseGrabberItems.at(index + 1), itemIsDying);
1005  }
1006  if (!popupWidgets.isEmpty() && item == popupWidgets.constLast()) {
1007  // If the item is a popup, go via removePopup to ensure state
1008  // consistency and that it gets hidden correctly - beware that
1009  // removePopup() reenters this function to continue removing the grab.
1010  removePopup(popupWidgets.constLast(), itemIsDying);
1011  return;
1012  }
1013 
1014  // Send notification about mouse ungrab.
1015  if (!itemIsDying) {
1017  sendEvent(item, &event);
1018  }
1019 
1020  // Remove the item from the list of grabbers. Whenever this happens, we
1021  // reset the implicitGrab (there can be only ever be one implicit grabber
1022  // in a scene, and it is always the latest grabber; if the implicit grab
1023  // is lost, it is not automatically regained.
1026 
1027  // Send notification about mouse regrab. ### It's unfortunate that all the
1028  // items get a GrabMouse event, but this is a rare case with a simple
1029  // implementation and it does ensure a consistent state.
1030  if (!itemIsDying && !mouseGrabberItems.isEmpty()) {
1033  sendEvent(last, &event);
1034  }
1035 }
1036 
1041 {
1042  if (!mouseGrabberItems.isEmpty())
1044  lastMouseGrabberItem = nullptr;
1045 }
1046 
1051 {
1054  qWarning("QGraphicsItem::grabKeyboard: already a keyboard grabber");
1055  else
1056  qWarning("QGraphicsItem::grabKeyboard: already blocked by keyboard grabber: %p",
1058  return;
1059  }
1060 
1061  // Send ungrab event to the last grabber.
1062  if (!keyboardGrabberItems.isEmpty()) {
1063  // Just send ungrab event to current grabber.
1064  QEvent ungrabEvent(QEvent::UngrabKeyboard);
1065  sendEvent(keyboardGrabberItems.constLast(), &ungrabEvent);
1066  }
1067 
1069 
1070  // Send grab event to current grabber.
1071  QEvent grabEvent(QEvent::GrabKeyboard);
1072  sendEvent(item, &grabEvent);
1073 }
1074 
1079 {
1081  if (index == -1) {
1082  qWarning("QGraphicsItem::ungrabKeyboard: not a keyboard grabber");
1083  return;
1084  }
1085  if (item != keyboardGrabberItems.constLast()) {
1086  // Recursively ungrab the topmost keyboard grabber until we reach this
1087  // item to ensure state consistency.
1088  ungrabKeyboard(keyboardGrabberItems.at(index + 1), itemIsDying);
1089  }
1090 
1091  // Send notification about keyboard ungrab.
1092  if (!itemIsDying) {
1094  sendEvent(item, &event);
1095  }
1096 
1097  // Remove the item from the list of grabbers.
1099 
1100  // Send notification about mouse regrab.
1101  if (!itemIsDying && !keyboardGrabberItems.isEmpty()) {
1104  sendEvent(last, &event);
1105  }
1106 }
1107 
1112 {
1115 }
1116 
1118 {
1119  for (QGraphicsView *view : qAsConst(views))
1120  view->viewport()->setMouseTracking(true);
1121 }
1122 
1127  const QPointF &scenePos,
1128  QWidget *widget) const
1129 {
1130  Q_Q(const QGraphicsScene);
1131  QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
1132  if (!view)
1133  return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
1134 
1135  const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
1136  if (!view->isTransformed())
1137  return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);
1138 
1139  const QTransform viewTransform = view->viewportTransform();
1140  if (viewTransform.type() <= QTransform::TxScale) {
1141  return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
1142  Qt::DescendingOrder, viewTransform);
1143  }
1144  return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
1145  Qt::DescendingOrder, viewTransform);
1146 }
1147 
1152 {
1153  for (int i = 0x1; i <= 0x10; i <<= 1) {
1154  if (event->buttons() & i) {
1157  event->widget()));
1160  }
1161  }
1162 }
1163 
1168 {
1169  sceneEventFilters.insert(watched, filter);
1170 }
1171 
1176 {
1177  if (!sceneEventFilters.contains(watched))
1178  return;
1179 
1182  do {
1183  if (it.value() == filter)
1185  else
1186  ++it;
1187  } while (it != end);
1188 }
1189 
1194 {
1197  while (parent) {
1198  if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
1199  return true;
1201  return false;
1202  parent = parent->parentItem();
1203  }
1204  }
1205  return false;
1206 }
1207 
1212 {
1214  return false;
1215 
1218  while (it != end) {
1219  // ### The filterer and filteree might both be deleted.
1220  if (it.value()->sceneEventFilter(it.key(), event))
1221  return true;
1222  ++it;
1223  }
1224  return false;
1225 }
1226 
1237 {
1238 #if QT_CONFIG(gestures)
1239  if (QGraphicsObject *object = item->toGraphicsObject()) {
1241  if (gestureManager) {
1242  if (gestureManager->filterEvent(object, event))
1243  return true;
1244  }
1245  }
1246 #endif // QT_CONFIG(gestures)
1247 
1248  if (filterEvent(item, event))
1249  return false;
1251  return false;
1252  if (!item || !item->isEnabled())
1253  return false;
1254  if (QGraphicsObject *o = item->toGraphicsObject()) {
1255  bool spont = event->spontaneous();
1257  return true;
1258  event->m_spont = spont;
1259  }
1260  return item->sceneEvent(event);
1261 }
1262 
1268 {
1269  dest->setWidget(source->widget());
1270  dest->setPos(source->pos());
1271  dest->setScenePos(source->scenePos());
1272  dest->setScreenPos(source->screenPos());
1273  dest->setButtons(source->buttons());
1274  dest->setModifiers(source->modifiers());
1275  dest->setPossibleActions(source->possibleActions());
1276  dest->setProposedAction(source->proposedAction());
1277  dest->setDropAction(source->dropAction());
1278  dest->setSource(source->source());
1279  dest->setMimeData(source->mimeData());
1280 }
1281 
1286  QGraphicsSceneDragDropEvent *dragDropEvent)
1287 {
1288  dragDropEvent->setPos(item->d_ptr->genericMapFromScene(dragDropEvent->scenePos(), dragDropEvent->widget()));
1289  sendEvent(item, dragDropEvent);
1290 }
1291 
1296  QGraphicsSceneHoverEvent *hoverEvent)
1297 {
1299  event.setWidget(hoverEvent->widget());
1300  const QTransform mapFromScene = item->d_ptr->genericMapFromSceneTransform(hoverEvent->widget());
1301  event.setPos(mapFromScene.map(hoverEvent->scenePos()));
1302  event.setScenePos(hoverEvent->scenePos());
1303  event.setScreenPos(hoverEvent->screenPos());
1304  event.setLastPos(mapFromScene.map(hoverEvent->lastScenePos()));
1305  event.setLastScenePos(hoverEvent->lastScenePos());
1306  event.setLastScreenPos(hoverEvent->lastScreenPos());
1307  event.setModifiers(hoverEvent->modifiers());
1308  sendEvent(item, &event);
1309 }
1310 
1315 {
1316  if (mouseEvent->button() == 0 && mouseEvent->buttons() == 0 && lastMouseGrabberItemHasImplicitMouseGrab) {
1317  // ### This is a temporary fix for until we get proper mouse
1318  // grab events.
1320  return;
1321  }
1322 
1324  if (item->isBlockedByModalPanel())
1325  return;
1326 
1327  const QTransform mapFromScene = item->d_ptr->genericMapFromSceneTransform(mouseEvent->widget());
1328  const QPointF itemPos = mapFromScene.map(mouseEvent->scenePos());
1329  for (int i = 0x1; i <= 0x10; i <<= 1) {
1334  }
1335  mouseEvent->setPos(itemPos);
1336  mouseEvent->setLastPos(mapFromScene.map(mouseEvent->lastScenePos()));
1337  sendEvent(item, mouseEvent);
1338 }
1339 
1344 {
1345  Q_Q(QGraphicsScene);
1346 
1347  // Ignore by default, unless we find a mouse grabber that accepts it.
1348  mouseEvent->ignore();
1349 
1350  // Deliver to any existing mouse grabber.
1351  if (!mouseGrabberItems.isEmpty()) {
1353  return;
1354  // The event is ignored by default, but we disregard the event's
1355  // accepted state after delivery; the mouse is grabbed, after all.
1356  sendMouseEvent(mouseEvent);
1357  return;
1358  }
1359 
1360  // Start by determining the number of items at the current position.
1361  // Reuse value from earlier calculations if possible.
1364  mouseEvent->scenePos(),
1365  mouseEvent->widget());
1366  }
1367 
1368  // Update window activation.
1370  QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : nullptr;
1371  if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
1372  // pass activation to the blocking modal window
1373  newActiveWindow = topItem ? topItem->window() : nullptr;
1374  }
1375 
1376  if (newActiveWindow != q->activeWindow())
1377  q->setActiveWindow(newActiveWindow);
1378 
1379  // Set focus on the topmost enabled item that can take focus.
1380  bool setFocus = false;
1381 
1382  for (QGraphicsItem *item : qAsConst(cachedItemsUnderMouse)) {
1385  // Make sure we don't clear focus.
1386  setFocus = true;
1387  break;
1388  }
1390  if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
1391  setFocus = true;
1392  if (item != q->focusItem() && item->d_ptr->mouseSetsFocus)
1393  q->setFocusItem(item, Qt::MouseFocusReason);
1394  break;
1395  }
1396  }
1397  if (item->isPanel())
1398  break;
1400  break;
1401  }
1402 
1403  // Check for scene modality.
1404  bool sceneModality = false;
1405  for (auto modalPanel : qAsConst(modalPanels)) {
1406  if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
1407  sceneModality = true;
1408  break;
1409  }
1410  }
1411 
1412  // If nobody could take focus, clear it.
1413  if (!stickyFocus && !setFocus && !sceneModality)
1414  q->setFocusItem(nullptr, Qt::MouseFocusReason);
1415 
1416  // Any item will do.
1417  if (sceneModality && cachedItemsUnderMouse.isEmpty())
1419 
1420  // Find a mouse grabber by sending mouse press events to all mouse grabber
1421  // candidates one at a time, until the event is accepted. It's accepted by
1422  // default, so the receiver has to explicitly ignore it for it to pass
1423  // through.
1424  for (QGraphicsItem *item : qAsConst(cachedItemsUnderMouse)) {
1425  if (!(item->acceptedMouseButtons() & mouseEvent->button())) {
1426  // Skip items that don't accept the event's mouse button.
1427  continue;
1428  }
1429 
1430  // Check if this item is blocked by a modal panel and deliver the mouse event to the
1431  // blocking panel instead of this item if blocked.
1433 
1434  grabMouse(item, /* implicit = */ true);
1435  mouseEvent->accept();
1436 
1437  // check if the item we are sending to are disabled (before we send the event)
1438  bool disabled = !item->isEnabled();
1439  bool isPanel = item->isPanel();
1440  if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
1442  // If this item is different from the item that received the last
1443  // mouse event, and mouseEvent is a double-click event, then the
1444  // event is converted to a press. Known limitation:
1445  // Triple-clicking will not generate a double-click, though.
1447  mousePress.m_spont = mouseEvent->spontaneous();
1448  mousePress.accept();
1449  mousePress.setButton(mouseEvent->button());
1450  mousePress.setButtons(mouseEvent->buttons());
1451  mousePress.setScreenPos(mouseEvent->screenPos());
1452  mousePress.setScenePos(mouseEvent->scenePos());
1453  mousePress.setModifiers(mouseEvent->modifiers());
1454  mousePress.setWidget(mouseEvent->widget());
1455  mousePress.setButtonDownPos(mouseEvent->button(),
1456  mouseEvent->buttonDownPos(mouseEvent->button()));
1457  mousePress.setButtonDownScenePos(mouseEvent->button(),
1458  mouseEvent->buttonDownScenePos(mouseEvent->button()));
1459  mousePress.setButtonDownScreenPos(mouseEvent->button(),
1460  mouseEvent->buttonDownScreenPos(mouseEvent->button()));
1462  mouseEvent->setAccepted(mousePress.isAccepted());
1463  } else {
1464  sendMouseEvent(mouseEvent);
1465  }
1466 
1467  bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.constLast() != item;
1468  if (disabled) {
1469  ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
1470  break;
1471  }
1472  if (mouseEvent->isAccepted()) {
1473  if (!mouseGrabberItems.isEmpty())
1476  return;
1477  }
1478  ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
1479 
1480  // Don't propagate through panels.
1481  if (isPanel)
1482  break;
1483  }
1484 
1485  // Is the event still ignored? Then the mouse press goes to the scene.
1486  // Reset the mouse grabber, clear the selection, clear focus, and leave
1487  // the event ignored so that it can propagate through the originating
1488  // view.
1489  if (!mouseEvent->isAccepted()) {
1491 
1492  QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0;
1493  bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
1494  bool extendSelection = (mouseEvent->modifiers() & Qt::ControlModifier) != 0;
1495  dontClearSelection |= extendSelection;
1496  if (!dontClearSelection) {
1497  // Clear the selection if the originating view isn't in scroll
1498  // hand drag mode. The view will clear the selection if no drag
1499  // happened.
1500  q->clearSelection();
1501  }
1502  }
1503 }
1504 
1515 {
1520  }
1523  for (int i = 0; i < topLevelItems.size(); ++i)
1524  topLevelItems[i]->d_ptr->siblingIndex = i;
1525  }
1526 }
1527 
1535 {
1536  if (this->font == font && this->font.resolveMask() == font.resolveMask())
1537  return;
1538  updateFont(font);
1539 }
1540 
1548 {
1549  QFont naturalFont = QApplication::font();
1550  naturalFont.setResolveMask(0);
1551  QFont resolvedFont = font.resolve(naturalFont);
1552  updateFont(resolvedFont);
1553 }
1554 
1562 {
1563  Q_Q(QGraphicsScene);
1564 
1565  // Update local font setting.
1566  this->font = font;
1567 
1568  // Resolve the fonts of all top-level widget items, or widget items
1569  // whose parent is not a widget.
1570  const auto items = q->items();
1571  for (QGraphicsItem *item : items) {
1572  if (!item->parentItem()) {
1573  // Resolvefont for an item is a noop operation, but
1574  // every item can be a widget, or can have a widget
1575  // childre.
1577  }
1578  }
1579 
1580  // Send the scene a FontChange event.
1583 }
1584 
1592 {
1593  if (this->palette == palette && this->palette.resolveMask() == palette.resolveMask())
1594  return;
1596 }
1597 
1605 {
1606  QPalette naturalPalette = QGuiApplication::palette();
1607  naturalPalette.setResolveMask(0);
1608  QPalette resolvedPalette = palette.resolve(naturalPalette);
1609  updatePalette(resolvedPalette);
1610 }
1611 
1619 {
1620  Q_Q(QGraphicsScene);
1621 
1622  // Update local palette setting.
1623  this->palette = palette;
1624 
1625  // Resolve the palettes of all top-level widget items, or widget items
1626  // whose parent is not a widget.
1627  const auto items = q->items();
1628  for (QGraphicsItem *item : items) {
1629  if (!item->parentItem()) {
1630  // ResolvePalette for an item is a noop operation, but
1631  // every item can be a widget, or can have a widget
1632  // children.
1634  }
1635  }
1636 
1637  // Send the scene a PaletteChange event.
1640 }
1641 
1648 {
1649  d_func()->init();
1650 }
1651 
1661 {
1662  d_func()->init();
1664 }
1665 
1676 {
1677  d_func()->init();
1678  setSceneRect(x, y, width, height);
1679 }
1680 
1688 {
1689  Q_D(QGraphicsScene);
1690 
1691  // Remove this scene from qApp's global scene list.
1692  if (!QApplicationPrivate::is_app_closing)
1693  qApp->d_func()->scene_list.removeAll(this);
1694 
1695  clear();
1696 
1697  // Remove this scene from all associated views.
1698  // Note: d->views is modified by QGraphicsView::setScene, so must make a copy
1699  const auto views = d->views;
1700  for (auto view : qAsConst(views))
1701  view->setScene(nullptr);
1702 }
1703 
1720 {
1721  Q_D(const QGraphicsScene);
1722  if (d->hasSceneRect)
1723  return d->sceneRect;
1724 
1725  if (d->dirtyGrowingItemsBoundingRect) {
1726  // Lazily update the growing items bounding rect
1727  QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
1728  QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
1730  thatd->dirtyGrowingItemsBoundingRect = false;
1731  if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
1732  emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
1733  }
1734  return d->growingItemsBoundingRect;
1735 }
1737 {
1738  Q_D(QGraphicsScene);
1739  if (rect != d->sceneRect) {
1740  d->hasSceneRect = !rect.isNull();
1741  d->sceneRect = rect;
1742  emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
1743  }
1744 }
1745 
1781  Qt::AspectRatioMode aspectRatioMode)
1782 {
1783  // ### Switch to using the recursive rendering algorithm instead.
1784 
1785  // Default source rect = scene rect
1786  QRectF sourceRect = source;
1787  if (sourceRect.isNull())
1788  sourceRect = sceneRect();
1789 
1790  // Default target rect = device rect
1791  QRectF targetRect = target;
1792  if (targetRect.isNull()) {
1794  targetRect = sourceRect;
1795  else
1796  targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
1797  }
1798 
1799  // Find the ideal x / y scaling ratio to fit \a source into \a target.
1800  qreal xratio = targetRect.width() / sourceRect.width();
1801  qreal yratio = targetRect.height() / sourceRect.height();
1802 
1803  // Scale according to the aspect ratio mode.
1804  switch (aspectRatioMode) {
1805  case Qt::KeepAspectRatio:
1806  xratio = yratio = qMin(xratio, yratio);
1807  break;
1809  xratio = yratio = qMax(xratio, yratio);
1810  break;
1811  case Qt::IgnoreAspectRatio:
1812  break;
1813  }
1814 
1815  // Find all items to draw, and reverse the list (we want to draw
1816  // in reverse order).
1818  QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
1819  const int numItems = itemList.size();
1820  for (int i = 0; i < numItems; ++i)
1821  itemArray[numItems - i - 1] = itemList.at(i);
1822  itemList.clear();
1823 
1824  painter->save();
1825 
1826  // Transform the painter.
1827  painter->setClipRect(targetRect, Qt::IntersectClip);
1828  QTransform painterTransform;
1829  painterTransform *= QTransform()
1830  .translate(targetRect.left(), targetRect.top())
1831  .scale(xratio, yratio)
1832  .translate(-sourceRect.left(), -sourceRect.top());
1833  painter->setWorldTransform(painterTransform, true);
1834 
1835  // Generate the style options
1836  QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
1837  for (int i = 0; i < numItems; ++i)
1838  itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
1839 
1840  // Render the scene.
1841  drawBackground(painter, sourceRect);
1842  drawItems(painter, numItems, itemArray, styleOptionArray);
1843  drawForeground(painter, sourceRect);
1844 
1845  delete [] itemArray;
1846  delete [] styleOptionArray;
1847 
1848  painter->restore();
1849 }
1850 
1868 {
1869  Q_D(const QGraphicsScene);
1870  return d->indexMethod;
1871 }
1873 {
1874  Q_D(QGraphicsScene);
1875  if (d->indexMethod == method)
1876  return;
1877 
1878  d->indexMethod = method;
1879 
1880  QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder);
1881  delete d->index;
1882  if (method == BspTreeIndex)
1883  d->index = new QGraphicsSceneBspTreeIndex(this);
1884  else
1885  d->index = new QGraphicsSceneLinearIndex(this);
1886  for (int i = oldItems.size() - 1; i >= 0; --i)
1887  d->index->addItem(oldItems.at(i));
1888 }
1889 
1923 {
1924  Q_D(const QGraphicsScene);
1925  QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
1926  return bspTree ? bspTree->bspTreeDepth() : 0;
1927 }
1929 {
1930  Q_D(QGraphicsScene);
1931  if (depth < 0) {
1932  qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth);
1933  return;
1934  }
1935 
1936  QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
1937  if (!bspTree) {
1938  qWarning("QGraphicsScene::setBspTreeDepth: cannot apply if indexing method is not BSP");
1939  return;
1940  }
1941  bspTree->setBspTreeDepth(depth);
1942 }
1943 
1952 {
1953  // Does not take untransformable items into account.
1954  QRectF boundingRect;
1955  const auto items_ = items();
1956  for (QGraphicsItem *item : items_)
1957  boundingRect |= item->sceneBoundingRect();
1958  return boundingRect;
1959 }
1960 
1968 {
1969  Q_D(const QGraphicsScene);
1970  return d->index->items(order);
1971 }
1972 
2007 {
2008  Q_D(const QGraphicsScene);
2009  return d->index->items(pos, mode, order, deviceTransform);
2010 }
2011 
2033 {
2034  Q_D(const QGraphicsScene);
2035  return d->index->items(rect, mode, order, deviceTransform);
2036 }
2037 
2059 {
2060  Q_D(const QGraphicsScene);
2061  return d->index->items(polygon, mode, order, deviceTransform);
2062 }
2063 
2085 {
2086  Q_D(const QGraphicsScene);
2087  return d->index->items(path, mode, order, deviceTransform);
2088 }
2089 
2104 {
2105  Q_D(const QGraphicsScene);
2106  if (!item) {
2107  qWarning("QGraphicsScene::collidingItems: cannot find collisions for null item");
2108  return QList<QGraphicsItem *>();
2109  }
2110 
2111  // Does not support ItemIgnoresTransformations.
2113  const auto itemsInVicinity = d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder);
2114  for (QGraphicsItem *itemInVicinity : itemsInVicinity) {
2115  if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
2116  tmp << itemInVicinity;
2117  }
2118  return tmp;
2119 }
2120 
2135 {
2138  return itemsAtPoint.isEmpty() ? nullptr : itemsAtPoint.first();
2139 }
2140 
2165 {
2166  Q_D(const QGraphicsScene);
2167 
2168  // Optimization: Lazily removes items that are not selected.
2169  QGraphicsScene *that = const_cast<QGraphicsScene *>(this);
2170  QSet<QGraphicsItem *> actuallySelectedSet;
2171  for (QGraphicsItem *item : qAsConst(that->d_func()->selectedItems)) {
2172  if (item->isSelected())
2173  actuallySelectedSet << item;
2174  }
2175 
2176  that->d_func()->selectedItems = actuallySelectedSet;
2177 
2178  return d->selectedItems.values();
2179 }
2180 
2189 {
2190  Q_D(const QGraphicsScene);
2191  return d->selectionArea;
2192 }
2193 
2210 {
2212 }
2213 
2229  Qt::ItemSelectionOperation selectionOperation,
2231  const QTransform &deviceTransform)
2232 {
2233  Q_D(QGraphicsScene);
2234 
2235  // Note: with boolean path operations, we can improve performance here
2236  // quite a lot by "growing" the old path instead of replacing it. That
2237  // allows us to only check the intersect area for changes, instead of
2238  // reevaluating the whole path over again.
2239  d->selectionArea = path;
2240 
2241  QSet<QGraphicsItem *> unselectItems = d->selectedItems;
2242 
2243  // Disable emitting selectionChanged() for individual items.
2244  ++d->selectionChanging;
2245  bool changed = false;
2246 
2247  // Set all items in path to selected.
2248  const auto items = this->items(path, mode, Qt::DescendingOrder, deviceTransform);
2249  for (QGraphicsItem *item : items) {
2251  if (!item->isSelected())
2252  changed = true;
2253  unselectItems.remove(item);
2254  item->setSelected(true);
2255  }
2256  }
2257 
2258  switch (selectionOperation) {
2259  case Qt::ReplaceSelection:
2260  // Deselect all items outside path.
2261  for (QGraphicsItem *item : qAsConst(unselectItems)) {
2262  item->setSelected(false);
2263  changed = true;
2264  }
2265  break;
2266  default:
2267  break;
2268  }
2269 
2270  // Re-enable emitting selectionChanged() for individual items.
2271  --d->selectionChanging;
2272 
2273  if (!d->selectionChanging && changed)
2275 }
2276 
2283 {
2284  Q_D(QGraphicsScene);
2285 
2286  // Disable emitting selectionChanged
2287  ++d->selectionChanging;
2288  // iterate over a copy, as clearing selection might invalidate selectedItems
2289  const auto selectedItems = d->selectedItems;
2290  bool changed = !selectedItems.isEmpty();
2291 
2293  item->setSelected(false);
2294  d->selectedItems.clear();
2295 
2296  // Re-enable emitting selectionChanged() for individual items.
2297  --d->selectionChanging;
2298 
2299  if (!d->selectionChanging && changed)
2301 }
2302 
2312 {
2313  Q_D(QGraphicsScene);
2314  // NB! We have to clear the index before deleting items; otherwise the
2315  // index might try to access dangling item pointers.
2316  d->index->clear();
2317  // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items
2318  while (!d->topLevelItems.isEmpty())
2319  delete d->topLevelItems.first();
2320  Q_ASSERT(d->topLevelItems.isEmpty());
2321  d->lastItemCount = 0;
2322  d->allItemsIgnoreHoverEvents = true;
2323  d->allItemsUseDefaultCursor = true;
2324  d->allItemsIgnoreTouchEvents = true;
2325  d->focusOnTouch = true;
2326 }
2327 
2342 {
2343  // Build a list of the first item's ancestors
2344  QList<QGraphicsItem *> ancestors;
2345  int n = 0;
2346  if (!items.isEmpty()) {
2347  QGraphicsItem *parent = items.at(n++);
2348  while ((parent = parent->parentItem()))
2349  ancestors.append(parent);
2350  }
2351 
2352  // Find the common ancestor for all items
2353  QGraphicsItem *commonAncestor = nullptr;
2354  if (!ancestors.isEmpty()) {
2355  while (n < items.size()) {
2356  int commonIndex = -1;
2357  QGraphicsItem *parent = items.at(n++);
2358  do {
2359  int index = ancestors.indexOf(parent, qMax(0, commonIndex));
2360  if (index != -1) {
2361  commonIndex = index;
2362  break;
2363  }
2364  } while ((parent = parent->parentItem()));
2365 
2366  if (commonIndex == -1) {
2367  commonAncestor = nullptr;
2368  break;
2369  }
2370 
2371  commonAncestor = ancestors.at(commonIndex);
2372  }
2373  }
2374 
2375  // Create a new group at that level
2376  QGraphicsItemGroup *group = new QGraphicsItemGroup(commonAncestor);
2377  if (!commonAncestor)
2378  addItem(group);
2379  for (QGraphicsItem *item : items)
2380  group->addToGroup(item);
2381  return group;
2382 }
2383 
2392 {
2393  const auto items = group->childItems();
2394  for (QGraphicsItem *item : items)
2395  group->removeFromGroup(item);
2396  removeItem(group);
2397  delete group;
2398 }
2399 
2426 {
2427  Q_D(QGraphicsScene);
2428  if (!item) {
2429  qWarning("QGraphicsScene::addItem: cannot add null item");
2430  return;
2431  }
2432  if (item->d_ptr->scene == this) {
2433  qWarning("QGraphicsScene::addItem: item has already been added to this scene");
2434  return;
2435  }
2436  // Remove this item from its existing scene
2437  if (QGraphicsScene *oldScene = item->d_ptr->scene)
2438  oldScene->removeItem(item);
2439 
2440  // Notify the item that its scene is changing, and allow the item to
2441  // react.
2442  const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
2443  QVariant::fromValue<QGraphicsScene *>(this)));
2444  QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
2445  if (targetScene != this) {
2446  if (targetScene && item->d_ptr->scene != targetScene)
2447  targetScene->addItem(item);
2448  return;
2449  }
2450 
2451  // QDeclarativeItems do not rely on initial itemChanged message, as the componentComplete
2452  // function allows far more opportunity for delayed-construction optimization.
2453  if (!item->d_ptr->isDeclarativeItem) {
2454  if (d->unpolishedItems.isEmpty()) {
2455  QMetaMethod method = metaObject()->method(d->polishItemsIndex);
2456  method.invoke(this, Qt::QueuedConnection);
2457  }
2458  d->unpolishedItems.append(item);
2459  item->d_ptr->pendingPolish = true;
2460  }
2461 
2462  // Detach this item from its parent if the parent's scene is different
2463  // from this scene.
2464  if (QGraphicsItem *itemParent = item->d_ptr->parent) {
2465  if (itemParent->d_ptr->scene != this)
2466  item->setParentItem(nullptr);
2467  }
2468 
2469  // Add the item to this scene
2470  item->d_func()->scene = targetScene;
2471 
2472  // Add the item in the index
2473  d->index->addItem(item);
2474 
2475  // Add to list of toplevels if this item is a toplevel.
2476  if (!item->d_ptr->parent)
2477  d->registerTopLevelItem(item);
2478 
2479  // Add to list of items that require an update. We cannot assume that the
2480  // item is fully constructed, so calling item->update() can lead to a pure
2481  // virtual function call to boundingRect().
2482  d->markDirty(item);
2483  d->dirtyGrowingItemsBoundingRect = true;
2484 
2485  // Disable selectionChanged() for individual items
2486  ++d->selectionChanging;
2487  int oldSelectedItemSize = d->selectedItems.size();
2488 
2489  // Enable mouse tracking if we haven't already done so, and the item needs it.
2490  // We cannot use itemAcceptsHoverEvents_helper() here, since we need to enable
2491  // mouse tracking also if this item is temporarily blocked by a modal panel.
2492 
2493  auto needsMouseTracking = [](const QGraphicsItemPrivate *item) {
2494  return item->acceptsHover
2495  || (item->isWidget && static_cast<const QGraphicsWidgetPrivate *>(item)->hasDecoration());
2496  };
2497 
2498  if (d->allItemsIgnoreHoverEvents && needsMouseTracking(item->d_ptr.data())) {
2499  d->allItemsIgnoreHoverEvents = false;
2500  d->enableMouseTrackingOnViews();
2501  }
2502 #ifndef QT_NO_CURSOR
2503  if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
2504  d->allItemsUseDefaultCursor = false;
2505  if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
2506  d->enableMouseTrackingOnViews();
2507  }
2508 #endif //QT_NO_CURSOR
2509 
2510  // Enable touch events if the item accepts touch events.
2511  if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
2512  d->allItemsIgnoreTouchEvents = false;
2513  d->enableTouchEventsOnViews();
2514  }
2515 
2516 #ifndef QT_NO_GESTURES
2517  for (auto it = item->d_ptr->gestureContext.constBegin();
2518  it != item->d_ptr->gestureContext.constEnd(); ++it)
2519  d->grabGesture(item, it.key());
2520 #endif
2521 
2522  // Update selection lists
2523  if (item->isSelected())
2524  d->selectedItems << item;
2525  if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
2526  d->addPopup(static_cast<QGraphicsWidget *>(item));
2528  d->enterModal(item);
2529 
2530  // Update creation order focus chain. Make sure to leave the widget's
2531  // internal tab order intact.
2532  if (item->isWidget()) {
2533  QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
2534  if (!d->tabFocusFirst) {
2535  // No first tab focus widget - make this the first tab focus
2536  // widget.
2537  d->tabFocusFirst = widget;
2538  } else if (!widget->parentWidget() && !widget->isPanel()) {
2539  // Adding a widget that is not part of a tab focus chain.
2540  QGraphicsWidget *myNewPrev = d->tabFocusFirst->d_func()->focusPrev;
2541  myNewPrev->d_func()->focusNext = widget;
2542  widget->d_func()->focusPrev->d_func()->focusNext = d->tabFocusFirst;
2543  d->tabFocusFirst->d_func()->focusPrev = widget->d_func()->focusPrev;
2544  widget->d_func()->focusPrev = myNewPrev;
2545  }
2546  }
2547 
2548  // Add all children recursively
2550  for (auto child : qAsConst(item->d_ptr->children))
2551  addItem(child);
2552 
2553  // Resolve font and palette.
2554  item->d_ptr->resolveFont(d->font.resolveMask());
2555  item->d_ptr->resolvePalette(d->palette.resolveMask());
2556 
2557 
2558  // Re-enable selectionChanged() for individual items
2559  --d->selectionChanging;
2560  if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
2562 
2563  // Deliver post-change notification
2565 
2566  // Update explicit activation
2567  bool autoActivate = true;
2568  if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
2569  d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
2570  if (d->childExplicitActivation && item->isPanel()) {
2571  if (d->childExplicitActivation == 1)
2573  else
2574  autoActivate = false;
2575  d->childExplicitActivation = 0;
2576  } else if (!item->d_ptr->parent) {
2577  d->childExplicitActivation = 0;
2578  }
2579 
2580  // Auto-activate this item's panel if nothing else has been activated
2581  if (autoActivate) {
2582  if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
2583  if (isActive())
2585  else
2586  d->lastActivePanel = item;
2587  }
2588  }
2589 
2591  d->registerScenePosItem(item);
2592 
2593  // Ensure that newly added items that have subfocus set, gain
2594  // focus automatically if there isn't a focus item already.
2595  if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
2596  item->focusItem()->setFocus();
2597 
2598  d->updateInputMethodSensitivityInViews();
2599 }
2600 
2617 {
2619  item->setPen(pen);
2620  item->setBrush(brush);
2621  addItem(item);
2622  return item;
2623 }
2624 
2649 {
2651  item->setPen(pen);
2652  addItem(item);
2653  return item;
2654 }
2655 
2680 {
2682  item->setPen(pen);
2683  item->setBrush(brush);
2684  addItem(item);
2685  return item;
2686 }
2687 
2703 {
2705  addItem(item);
2706  return item;
2707 }
2708 
2725  const QPen &pen, const QBrush &brush)
2726 {
2728  item->setPen(pen);
2729  item->setBrush(brush);
2730  addItem(item);
2731  return item;
2732 }
2733 
2752 {
2754  item->setPen(pen);
2755  item->setBrush(brush);
2756  addItem(item);
2757  return item;
2758 }
2759 
2783 {
2785  item->setFont(font);
2786  addItem(item);
2787  return item;
2788 }
2789 
2805 {
2807  item->setFont(font);
2808  addItem(item);
2809  return item;
2810 }
2811 
2831 {
2832  QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(nullptr, wFlags);
2833  proxy->setWidget(widget);
2834  addItem(proxy);
2835  return proxy;
2836 }
2837 
2846 {
2847  // ### Refactoring: This function shares much functionality with _q_removeItemLater()
2848  Q_D(QGraphicsScene);
2849  if (!item) {
2850  qWarning("QGraphicsScene::removeItem: cannot remove 0-item");
2851  return;
2852  }
2853  if (item->scene() != this) {
2854  qWarning("QGraphicsScene::removeItem: item %p's scene (%p)"
2855  " is different from this scene (%p)",
2856  item, item->scene(), this);
2857  return;
2858  }
2859 
2860  // Notify the item that it's scene is changing to 0, allowing the item to
2861  // react.
2862  const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
2863  QVariant::fromValue<QGraphicsScene *>(0)));
2864  QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
2865  if (targetScene != nullptr && targetScene != this) {
2866  targetScene->addItem(item);
2867  return;
2868  }
2869 
2870  d->removeItemHelper(item);
2871 
2872  // Deliver post-change notification
2874 
2875  d->updateInputMethodSensitivityInViews();
2876 }
2877 
2890 {
2891  Q_D(const QGraphicsScene);
2892  return isActive() ? d->focusItem : d->passiveFocusItem;
2893 }
2894 
2912 {
2913  Q_D(QGraphicsScene);
2914  if (item)
2915  item->setFocus(focusReason);
2916  else
2917  d->setFocusItemHelper(item, focusReason);
2918 }
2919 
2928 {
2929  Q_D(const QGraphicsScene);
2930  return d->hasFocus;
2931 }
2932 
2944 {
2945  Q_D(QGraphicsScene);
2946  if (d->hasFocus || !isActive())
2947  return;
2948  QFocusEvent event(QEvent::FocusIn, focusReason);
2950 }
2951 
2962 {
2963  Q_D(QGraphicsScene);
2964  if (d->hasFocus) {
2965  d->hasFocus = false;
2966  d->passiveFocusItem = d->focusItem;
2968  }
2969 }
2970 
2990 {
2991  Q_D(QGraphicsScene);
2992  d->stickyFocus = enabled;
2993 }
2995 {
2996  Q_D(const QGraphicsScene);
2997  return d->stickyFocus;
2998 }
2999 
3023 {
3024  Q_D(const QGraphicsScene);
3025  return !d->mouseGrabberItems.isEmpty() ? d->mouseGrabberItems.last() : 0;
3026 }
3027 
3045 {
3046  Q_D(const QGraphicsScene);
3047  return d->backgroundBrush;
3048 }
3050 {
3051  Q_D(QGraphicsScene);
3052  d->backgroundBrush = brush;
3053  for (QGraphicsView *view : qAsConst(d->views)) {
3054  view->resetCachedContent();
3055  view->viewport()->update();
3056  }
3057  update();
3058 }
3059 
3081 {
3082  Q_D(const QGraphicsScene);
3083  return d->foregroundBrush;
3084 }
3086 {
3087  Q_D(QGraphicsScene);
3088  d->foregroundBrush = brush;
3089  const auto views_ = views();
3090  for (QGraphicsView *view : views_)
3091  view->viewport()->update();
3092  update();
3093 }
3094 
3105 {
3106  Q_D(const QGraphicsScene);
3107  if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
3108  return QVariant();
3109  const QTransform matrix = d->focusItem->sceneTransform();
3110  QVariant value = d->focusItem->inputMethodQuery(query);
3111  if (value.userType() == QMetaType::QRectF)
3112  value = matrix.mapRect(value.toRectF());
3113  else if (value.userType() == QMetaType::QPointF)
3114  value = matrix.map(value.toPointF());
3115  else if (value.userType() == QMetaType::QRect)
3116  value = matrix.mapRect(value.toRect());
3117  else if (value.userType() == QMetaType::QPoint)
3118  value = matrix.map(value.toPoint());
3119  return value;
3120 }
3121 
3129 {
3130  Q_D(QGraphicsScene);
3131  if (d->updateAll || (rect.isEmpty() && !rect.isNull()))
3132  return;
3133 
3134  // Check if anyone's connected; if not, we can send updates directly to
3135  // the views. Otherwise or if there are no views, use old behavior.
3136  bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty();
3137  if (rect.isNull()) {
3138  d->updateAll = true;
3139  d->updatedRects.clear();
3140  if (directUpdates) {
3141  // Update all views.
3142  for (auto view : qAsConst(d->views))
3143  view->d_func()->fullUpdatePending = true;
3144  }
3145  } else {
3146  if (directUpdates) {
3147  // Update all views.
3148  for (auto view : qAsConst(d->views)) {
3149  if (view->isTransformed())
3150  view->d_func()->updateRectF(view->viewportTransform().mapRect(rect));
3151  else
3152  view->d_func()->updateRectF(rect);
3153  }
3154  } else {
3155  d->updatedRects.insert(rect);
3156  }
3157  }
3158 
3159  if (!d->calledEmitUpdated) {
3160  d->calledEmitUpdated = true;
3161  QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
3162  }
3163 }
3164 
3196 {
3197  const auto views_ = views();
3198  for (QGraphicsView *view : views_)
3199  view->invalidateScene(rect, layers);
3200  update(rect);
3201 }
3202 
3218 {
3219  Q_D(const QGraphicsScene);
3220  return d->views;
3221 }
3222 
3237 {
3238  for (int i = 0; i < 2; ++i) {
3239  const auto items_ = items();
3240  for (QGraphicsItem *item : items_)
3241  item->advance(i);
3242  }
3243 }
3244 
3267 {
3268  Q_D(QGraphicsScene);
3269 
3270  switch (event->type()) {
3278  case QEvent::TouchBegin:
3279  case QEvent::TouchUpdate:
3280  case QEvent::TouchEnd:
3281  // Reset the under-mouse list to ensure that this event gets fresh
3282  // item-under-mouse data. Be careful about this list; if people delete
3283  // items from inside event handlers, this list can quickly end up
3284  // having stale pointers in it. We need to clear it before dispatching
3285  // events that use it.
3286  // ### this should only be cleared if we received a new mouse move event,
3287  // which relies on us fixing the replay mechanism in QGraphicsView.
3288  d->cachedItemsUnderMouse.clear();
3289  default:
3290  break;
3291  }
3292 
3293  switch (event->type()) {
3296  break;
3299  break;
3302  break;
3304  dropEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
3305  break;
3308  break;
3309  case QEvent::KeyPress:
3310  if (!d->focusItem) {
3311  QKeyEvent *k = static_cast<QKeyEvent *>(event);
3312  if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
3313  if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
3314  bool res = false;
3315  if (k->key() == Qt::Key_Backtab
3316  || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
3317  res = focusNextPrevChild(false);
3318  } else if (k->key() == Qt::Key_Tab) {
3319  res = focusNextPrevChild(true);
3320  }
3321  if (!res)
3322  event->ignore();
3323  return true;
3324  }
3325  }
3326  }
3327  keyPressEvent(static_cast<QKeyEvent *>(event));
3328  break;
3329  case QEvent::KeyRelease:
3330  keyReleaseEvent(static_cast<QKeyEvent *>(event));
3331  break;
3332  case QEvent::ShortcutOverride: {
3334  while (parent) {
3335  d->sendEvent(parent, event);
3336  if (event->isAccepted())
3337  return true;
3338  parent = parent->parentItem();
3339  }
3340  }
3341  return false;
3343  {
3344  QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
3345  d->lastSceneMousePos = mouseEvent->scenePos();
3346  mouseMoveEvent(mouseEvent);
3347  break;
3348  }
3351  break;
3354  break;
3357  break;
3359  wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event));
3360  break;
3361  case QEvent::FocusIn:
3362  focusInEvent(static_cast<QFocusEvent *>(event));
3363  break;
3364  case QEvent::FocusOut:
3365  focusOutEvent(static_cast<QFocusEvent *>(event));
3366  break;
3370  {
3371  QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
3372  d->lastSceneMousePos = hoverEvent->scenePos();
3373  d->dispatchHoverEvent(hoverEvent);
3374  break;
3375  }
3376  case QEvent::Leave:
3377  Q_ASSERT_X(false, "QGraphicsScene::event",
3378  "QGraphicsScene must not receive QEvent::Leave, use GraphicsSceneLeave");
3379  break;
3381  {
3382  auto *leaveEvent = static_cast<QGraphicsSceneEvent*>(event);
3383  d->leaveScene(leaveEvent->widget());
3384  break;
3385  }
3387  helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event));
3388  break;
3389  case QEvent::InputMethod:
3390  inputMethodEvent(static_cast<QInputMethodEvent *>(event));
3391  break;
3393  if (!d->activationRefCount++) {
3394  if (d->lastActivePanel) {
3395  // Activate the last panel.
3396  d->setActivePanelHelper(d->lastActivePanel, true);
3397  } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
3398  // Activate the panel of the first item in the tab focus
3399  // chain.
3400  d->setActivePanelHelper(d->tabFocusFirst, true);
3401  } else {
3402  // Activate all toplevel items.
3404  const auto items_ = items();
3405  for (QGraphicsItem *item : items_) {
3406  if (item->isVisible() && !item->isPanel() && !item->parentItem())
3407  sendEvent(item, &event);
3408  }
3409  }
3410  }
3411  break;
3413  if (!--d->activationRefCount) {
3414  if (d->activePanel) {
3415  // Deactivate the active panel (but keep it so we can
3416  // reactivate it later).
3417  QGraphicsItem *lastActivePanel = d->activePanel;
3418  d->setActivePanelHelper(nullptr, true);
3419  d->lastActivePanel = lastActivePanel;
3420  } else {
3421  // Activate all toplevel items.
3423  const auto items_ = items();
3424  for (QGraphicsItem *item : items_) {
3425  if (item->isVisible() && !item->isPanel() && !item->parentItem())
3426  sendEvent(item, &event);
3427  }
3428  }
3429  }
3430  break;
3432  // Resolve the existing scene font.
3433  d->resolveFont();
3434  break;
3435  }
3436  case QEvent::FontChange:
3437  // Update the entire scene when the font changes.
3438  update();
3439  break;
3441  // Resolve the existing scene palette.
3442  d->resolvePalette();
3443  break;
3444  }
3445  case QEvent::PaletteChange:
3446  // Update the entire scene when the palette changes.
3447  update();
3448  break;
3449  case QEvent::StyleChange:
3450  // Reresolve all widgets' styles. Update all top-level widgets'
3451  // geometries that do not have an explicit style set.
3452  update();
3453  break;
3455  // Because QGraphicsItem is not a QObject, QStyle driven
3456  // animations are forced to update the whole scene
3457  update();
3458  break;
3459  case QEvent::TouchBegin:
3460  case QEvent::TouchUpdate:
3461  case QEvent::TouchEnd:
3462  d->touchEventHandler(static_cast<QTouchEvent *>(event));
3463  break;
3464 #ifndef QT_NO_GESTURES
3465  case QEvent::Gesture:
3467  d->gestureEventHandler(static_cast<QGestureEvent *>(event));
3468  break;
3469 #endif // QT_NO_GESTURES
3470  default:
3471  return QObject::event(event);
3472  }
3473  return true;
3474 }
3475 
3483 {
3484  if (watched != qApp)
3485  return false;
3486 
3487  switch (event->type()) {
3490  break;
3493  break;
3494  default:
3495  break;
3496  }
3497  return false;
3498 }
3499 
3512 {
3513  Q_D(QGraphicsScene);
3514  // Ignore by default.
3515  contextMenuEvent->ignore();
3516 
3517  // Send the event to all items at this position until one item accepts the
3518  // event.
3519  const auto items = d->itemsAtPosition(contextMenuEvent->screenPos(),
3520  contextMenuEvent->scenePos(),
3521  contextMenuEvent->widget());
3522  for (QGraphicsItem *item : items) {
3524  contextMenuEvent->widget()));
3525  contextMenuEvent->accept();
3526  if (!d->sendEvent(item, contextMenuEvent))
3527  break;
3528 
3529  if (contextMenuEvent->isAccepted())
3530  break;
3531  }
3532 }
3533 
3545 {
3546  Q_D(QGraphicsScene);
3547  d->dragDropItem = nullptr;
3548  d->lastDropAction = Qt::IgnoreAction;
3549  event->accept();
3550 }
3551 
3562 {
3563  Q_D(QGraphicsScene);
3564  event->ignore();
3565 
3566  if (!d->mouseGrabberItems.isEmpty()) {
3567  // Mouse grabbers that start drag events lose the mouse grab.
3568  d->clearMouseGrabber();
3569  d->mouseGrabberButtonDownPos.clear();
3570  d->mouseGrabberButtonDownScenePos.clear();
3571  d->mouseGrabberButtonDownScreenPos.clear();
3572  }
3573 
3574  bool eventDelivered = false;
3575 
3576  // Find the topmost enabled items under the cursor. They are all
3577  // candidates for accepting drag & drop events.
3578  const auto items = d->itemsAtPosition(event->screenPos(),
3579  event->scenePos(),
3580  event->widget());
3581  for (QGraphicsItem *item : items) {
3582  if (!item->isEnabled() || !item->acceptDrops())
3583  continue;
3584 
3585  if (item != d->dragDropItem) {
3586  // Enter the new drag drop item. If it accepts the event, we send
3587  // the leave to the parent item.
3589  d->cloneDragDropEvent(&dragEnter, event);
3590  dragEnter.setDropAction(event->proposedAction());
3591  d->sendDragDropEvent(item, &dragEnter);
3592  event->setAccepted(dragEnter.isAccepted());
3593  event->setDropAction(dragEnter.dropAction());
3594  if (!event->isAccepted()) {
3595  // Propagate to the item under
3596  continue;
3597  }
3598 
3599  d->lastDropAction = event->dropAction();
3600 
3601  if (d->dragDropItem) {
3602  // Leave the last drag drop item. A perfect implementation
3603  // would set the position of this event to the point where
3604  // this event and the last event intersect with the item's
3605  // shape, but that's not easy to do. :-)
3607  d->cloneDragDropEvent(&dragLeave, event);
3608  d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3609  }
3610 
3611  // We've got a new drag & drop item
3612  d->dragDropItem = item;
3613  }
3614 
3615  // Send the move event.
3616  event->setDropAction(d->lastDropAction);
3617  event->accept();
3618  d->sendDragDropEvent(item, event);
3619  if (event->isAccepted())
3620  d->lastDropAction = event->dropAction();
3621  eventDelivered = true;
3622  break;
3623  }
3624 
3625  if (!eventDelivered) {
3626  if (d->dragDropItem) {
3627  // Leave the last drag drop item
3629  d->cloneDragDropEvent(&dragLeave, event);
3630  d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3631  d->dragDropItem = nullptr;
3632  }
3633  // Propagate
3634  event->setDropAction(Qt::IgnoreAction);
3635  }
3636 }
3637 
3646 {
3647  Q_D(QGraphicsScene);
3648  if (d->dragDropItem) {
3649  // Leave the last drag drop item
3650  d->sendDragDropEvent(d->dragDropItem, event);
3651  d->dragDropItem = nullptr;
3652  }
3653 }
3654 
3663 {
3664  Q_UNUSED(event);
3665  Q_D(QGraphicsScene);
3666  if (d->dragDropItem) {
3667  // Drop on the last drag drop item
3668  d->sendDragDropEvent(d->dragDropItem, event);
3669  d->dragDropItem = nullptr;
3670  }
3671 }
3672 
3683 {
3684  Q_D(QGraphicsScene);
3685 
3686  d->hasFocus = true;
3687  switch (focusEvent->reason()) {
3688  case Qt::TabFocusReason:
3689  if (!focusNextPrevChild(true))
3690  focusEvent->ignore();
3691  break;
3693  if (!focusNextPrevChild(false))
3694  focusEvent->ignore();
3695  break;
3696  default:
3697  if (d->passiveFocusItem) {
3698  // Set focus on the last focus item
3699  setFocusItem(d->passiveFocusItem, focusEvent->reason());
3700  }
3701  break;
3702  }
3703 }
3704 
3715 {
3716  Q_D(QGraphicsScene);
3717  d->hasFocus = false;
3718  d->passiveFocusItem = d->focusItem;
3719  setFocusItem(nullptr, focusEvent->reason());
3720 
3721  // Remove all popups when the scene loses focus.
3722  if (!d->popupWidgets.isEmpty())
3723  d->removePopup(d->popupWidgets.constFirst());
3724 }
3725 
3742 {
3743 #if !QT_CONFIG(tooltip)
3745 #else
3746  // Find the first item that does tooltips
3747  Q_D(QGraphicsScene);
3748  const QList<QGraphicsItem *> itemsAtPos = d->itemsAtPosition(helpEvent->screenPos(),
3749  helpEvent->scenePos(),
3750  helpEvent->widget());
3751  QGraphicsItem *toolTipItem = nullptr;
3752  for (auto item : itemsAtPos) {
3753  if (item->d_func()->isProxyWidget()) {
3754  // if the item is a proxy widget, the event is forwarded to it
3756  if (helpEvent->isAccepted())
3757  return;
3758  }
3759  if (!item->toolTip().isEmpty()) {
3760  toolTipItem = item;
3761  break;
3762  }
3763  }
3764 
3765  // Show or hide the tooltip
3766  QString text;
3767  QPoint point;
3768  if (toolTipItem && !toolTipItem->toolTip().isEmpty()) {
3769  text = toolTipItem->toolTip();
3770  point = helpEvent->screenPos();
3771  }
3772  QToolTip::showText(point, text, helpEvent->widget());
3773  helpEvent->setAccepted(!text.isEmpty());
3774 #endif
3775 }
3776 
3778 {
3779  return (item->d_ptr->acceptsHover
3780  || (item->d_ptr->isWidget
3781  && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))
3782  && !item->isBlockedByModalPanel();
3783 }
3784 
3796 {
3798  return false;
3799 
3800  // Find the first item that accepts hover events, reusing earlier
3801  // calculated data is possible.
3804  hoverEvent->scenePos(),
3805  hoverEvent->widget());
3806  }
3807 
3808  QGraphicsItem *item = nullptr;
3809  for (auto tmp : qAsConst(cachedItemsUnderMouse)) {
3810  if (itemAcceptsHoverEvents_helper(tmp)) {
3811  item = tmp;
3812  break;
3813  }
3814  }
3815 
3816  // Find the common ancestor item for the new topmost hoverItem and the
3817  // last item in the hoverItem list.
3818  QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.constLast()) : nullptr;
3819  while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
3820  commonAncestorItem = commonAncestorItem->parentItem();
3821  if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
3822  // The common ancestor isn't in the same panel as the two hovered
3823  // items.
3824  commonAncestorItem = nullptr;
3825  }
3826 
3827  // Check if the common ancestor item is known.
3828  int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
3829  // Send hover leaves to any existing hovered children of the common
3830  // ancestor item.
3831  for (int i = hoverItems.size() - 1; i > index; --i) {
3832  QGraphicsItem *lastItem = hoverItems.takeLast();
3833  if (itemAcceptsHoverEvents_helper(lastItem))
3834  sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
3835  }
3836 
3837  // Item is a child of a known item. Generate enter events for the
3838  // missing links.
3839  QList<QGraphicsItem *> parents;
3841  while (parent && parent != commonAncestorItem) {
3842  parents.append(parent);
3843  if (parent->isPanel()) {
3844  // Stop at the panel - we don't deliver beyond this point.
3845  break;
3846  }
3847  parent = parent->parentItem();
3848  }
3849  for (auto it = parents.crbegin(), end = parents.crend(); it != end; ++it) {
3850  QGraphicsItem *parent = *it;
3851  hoverItems << parent;
3854  }
3855 
3856  // Generate a move event for the item itself
3857  if (item
3858  && !hoverItems.isEmpty()
3859  && item == hoverItems.constLast()) {
3861  return true;
3862  }
3863  return false;
3864 }
3865 
3873 {
3874 #if QT_CONFIG(tooltip)
3876 #endif
3877  QGraphicsView *view = qobject_cast<QGraphicsView *>(viewport->parent());
3878  // Send HoverLeave events to all existing hover items, topmost first.
3879  QGraphicsSceneHoverEvent hoverEvent;
3880  hoverEvent.setWidget(viewport);
3881 
3882  if (view) {
3883  QPoint cursorPos = QCursor::pos();
3884  hoverEvent.setScenePos(view->mapToScene(viewport->mapFromGlobal(cursorPos)));
3885  hoverEvent.setLastScenePos(hoverEvent.scenePos());
3886  hoverEvent.setScreenPos(cursorPos);
3887  hoverEvent.setLastScreenPos(hoverEvent.screenPos());
3888  }
3889 
3890  while (!hoverItems.isEmpty()) {
3891  QGraphicsItem *lastItem = hoverItems.takeLast();
3892  if (itemAcceptsHoverEvents_helper(lastItem))
3893  sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent);
3894  }
3895 }
3896 
3905 {
3906  // ### Merge this function with keyReleaseEvent; they are identical
3907  // ### (except this comment).
3908  Q_D(QGraphicsScene);
3909  QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.constLast() : 0;
3910  if (!item)
3911  item = focusItem();
3912  if (item) {
3913  QGraphicsItem *p = item;
3914  do {
3915  // Accept the event by default
3916  keyEvent->accept();
3917  // Send it; QGraphicsItem::keyPressEvent ignores it. If the event
3918  // is filtered out, stop propagating it.
3919  if (p->isBlockedByModalPanel())
3920  break;
3921  if (!d->sendEvent(p, keyEvent))
3922  break;
3923  } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
3924  } else {
3925  keyEvent->ignore();
3926  }
3927 }
3928 
3937 {
3938  // ### Merge this function with keyPressEvent; they are identical (except
3939  // ### this comment).
3940  Q_D(QGraphicsScene);
3941  QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.constLast() : 0;
3942  if (!item)
3943  item = focusItem();
3944  if (item) {
3945  QGraphicsItem *p = item;
3946  do {
3947  // Accept the event by default
3948  keyEvent->accept();
3949  // Send it; QGraphicsItem::keyPressEvent ignores it. If the event
3950  // is filtered out, stop propagating it.
3951  if (p->isBlockedByModalPanel())
3952  break;
3953  if (!d->sendEvent(p, keyEvent))
3954  break;
3955  } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
3956  } else {
3957  keyEvent->ignore();
3958  }
3959 }
3960 
3981 {
3982  Q_D(QGraphicsScene);
3983  if (d->mouseGrabberItems.isEmpty()) {
3984  // Dispatch hover events
3986  _q_hoverFromMouseEvent(&hover, mouseEvent);
3987  d->dispatchHoverEvent(&hover);
3988  }
3989 
3990  d->mousePressEventHandler(mouseEvent);
3991 }
3992 
4006 {
4007  Q_D(QGraphicsScene);
4008  if (d->mouseGrabberItems.isEmpty()) {
4009  if (mouseEvent->buttons())
4010  return;
4012  _q_hoverFromMouseEvent(&hover, mouseEvent);
4013  mouseEvent->setAccepted(d->dispatchHoverEvent(&hover));
4014  return;
4015  }
4016 
4017  // Forward the event to the mouse grabber
4018  d->sendMouseEvent(mouseEvent);
4019  mouseEvent->accept();
4020 }
4021 
4036 {
4037  Q_D(QGraphicsScene);
4038  if (d->mouseGrabberItems.isEmpty()) {
4039  mouseEvent->ignore();
4040  return;
4041  }
4042 
4043  // Forward the event to the mouse grabber
4044  d->sendMouseEvent(mouseEvent);
4045  mouseEvent->accept();
4046 
4047  // Reset the mouse grabber when the last mouse button has been released.
4048  if (!mouseEvent->buttons()) {
4049  if (!d->mouseGrabberItems.isEmpty()) {
4050  d->lastMouseGrabberItem = d->mouseGrabberItems.constLast();
4051  if (d->lastMouseGrabberItemHasImplicitMouseGrab)
4052  d->mouseGrabberItems.constLast()->ungrabMouse();
4053  } else {
4054  d->lastMouseGrabberItem = nullptr;
4055  }
4056 
4057  // Generate a hoverevent
4058  QGraphicsSceneHoverEvent hoverEvent;
4059  _q_hoverFromMouseEvent(&hoverEvent, mouseEvent);
4060  d->dispatchHoverEvent(&hoverEvent);
4061  }
4062 }
4063 
4084 {
4085  Q_D(QGraphicsScene);
4086  d->mousePressEventHandler(mouseEvent);
4087 }
4088 
4103 {
4104  Q_D(QGraphicsScene);
4105  const QList<QGraphicsItem *> wheelCandidates = d->itemsAtPosition(wheelEvent->screenPos(),
4106  wheelEvent->scenePos(),
4107  wheelEvent->widget());
4108 
4109  // Find the first popup under the mouse (including the popup's descendants) starting from the last.
4110  // Remove all popups after the one found, or all or them if no popup is under the mouse.
4111  // Then continue with the event.
4112  QList<QGraphicsWidget *>::const_iterator iter = d->popupWidgets.constEnd();
4113  while (iter > d->popupWidgets.constBegin() && !wheelCandidates.isEmpty()) {
4114  --iter;
4115  if (wheelCandidates.first() == *iter || (*iter)->isAncestorOf(wheelCandidates.first()))
4116  break;
4117  d->removePopup(*iter);
4118  }
4119 
4120  bool hasSetFocus = false;
4121  for (QGraphicsItem *item : wheelCandidates) {
4122  if (!hasSetFocus && item->isEnabled()
4124  if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
4125  hasSetFocus = true;
4126  if (item != focusItem())
4128  }
4129  }
4130 
4131  wheelEvent->setPos(item->d_ptr->genericMapFromScene(wheelEvent->scenePos(),
4132  wheelEvent->widget()));
4133  wheelEvent->accept();
4134  bool isPanel = item->isPanel();
4135  bool ret = d->sendEvent(item, wheelEvent);
4136 
4137  if (ret && (isPanel || wheelEvent->isAccepted()))
4138  break;
4139  }
4140 }
4141 
4153 {
4154  Q_D(QGraphicsScene);
4155  if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
4156  d->sendEvent(d->focusItem, event);
4157  return;
4158  }
4159  if (d->lastFocusItem && d->lastFocusItem != d->focusItem && (d->lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
4160  d->sendEvent(d->lastFocusItem, event);
4161 }
4162 
4177 {
4178  Q_D(QGraphicsScene);
4179 
4180  if (d->backgroundBrush.style() != Qt::NoBrush) {
4181  if (d->painterStateProtection)
4182  painter->save();
4183  painter->setBrushOrigin(0, 0);
4185  if (d->painterStateProtection)
4186  painter->restore();
4187  }
4188 }
4189 
4204 {
4205  Q_D(QGraphicsScene);
4206 
4207  if (d->foregroundBrush.style() != Qt::NoBrush) {
4208  if (d->painterStateProtection)
4209  painter->save();
4210  painter->setBrushOrigin(0, 0);
4212  if (d->painterStateProtection)
4213  painter->restore();
4214  }
4215 }
4216 
4217 static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
4219  bool useWindowOpacity, bool painterStateProtection)
4220 {
4221  if (!item->isWidget()) {
4223  return;
4224  }
4225  QGraphicsWidget *widgetItem = static_cast<QGraphicsWidget *>(item);
4226  QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(widgetItem);
4227  const qreal windowOpacity = (proxy && proxy->widget() && useWindowOpacity)
4228  ? proxy->widget()->windowOpacity() : 1.0;
4229  const qreal oldPainterOpacity = painter->opacity();
4230 
4231  if (qFuzzyIsNull(windowOpacity))
4232  return;
4233  // Set new painter opacity.
4234  if (windowOpacity < 1.0)
4235  painter->setOpacity(oldPainterOpacity * windowOpacity);
4236 
4237  // set layoutdirection on the painter
4238  Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
4239  painter->setLayoutDirection(widgetItem->layoutDirection());
4240 
4241  if (widgetItem->isWindow() && widgetItem->windowType() != Qt::Popup && widgetItem->windowType() != Qt::ToolTip
4242  && !(widgetItem->windowFlags() & Qt::FramelessWindowHint)) {
4243  if (painterStateProtection)
4244  painter->save();
4245  widgetItem->paintWindowFrame(painter, option, widget);
4246  if (painterStateProtection)
4247  painter->restore();
4248  } else if (widgetItem->autoFillBackground()) {
4249  painter->fillRect(option->exposedRect, widgetItem->palette().window());
4250  }
4251 
4252  widgetItem->paint(painter, option, widget);
4253 
4254  // Restore layoutdirection on the painter.
4255  painter->setLayoutDirection(oldLayoutDirection);
4256  // Restore painter opacity.
4257  if (windowOpacity < 1.0)
4258  painter->setOpacity(oldPainterOpacity);
4259 }
4260 
4261 static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &pixmapExposed,
4262  const QTransform &itemToPixmap, QPainter::RenderHints renderHints,
4263  const QStyleOptionGraphicsItem *option, bool painterStateProtection)
4264 {
4265  QPixmap subPix;
4266  QPainter pixmapPainter;
4267  QRect br = pixmapExposed.boundingRect();
4268 
4269  // Don't use subpixmap if we get a full update.
4270  if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) {
4272  pixmapPainter.begin(pix);
4273  } else {
4274  subPix = QPixmap(br.size() * pix->devicePixelRatio());
4276  subPix.fill(Qt::transparent);
4277  pixmapPainter.begin(&subPix);
4278  pixmapPainter.translate(-br.topLeft());
4279  if (!pixmapExposed.isEmpty()) {
4280  // Applied to subPix; paint is adjusted to the coordinate space is
4281  // correct.
4282  pixmapPainter.setClipRegion(pixmapExposed);
4283  }
4284  }
4285 
4286  pixmapPainter.setRenderHints(pixmapPainter.renderHints(), false);
4287  pixmapPainter.setRenderHints(renderHints, true);
4288  pixmapPainter.setWorldTransform(itemToPixmap, true);
4289 
4290  // Render.
4291  _q_paintItem(item, &pixmapPainter, option, nullptr, false, painterStateProtection);
4292  pixmapPainter.end();
4293 
4294  if (!subPix.isNull()) {
4295  // Blit the subpixmap into the main pixmap.
4296  pixmapPainter.begin(pix);
4298  pixmapPainter.setClipRegion(pixmapExposed);
4299  pixmapPainter.drawPixmap(br.topLeft(), subPix);
4300  pixmapPainter.end();
4301  }
4302 }
4303 
4304 // Copied from qpaintengine_vg.cpp
4305 // Returns \c true for 90, 180, and 270 degree rotations.
4306 static inline bool transformIsSimple(const QTransform& transform)
4307 {
4309  if (type <= QTransform::TxScale) {
4310  return true;
4311  } else if (type == QTransform::TxRotate) {
4312  // Check for 90, and 270 degree rotations.
4313  qreal m11 = transform.m11();
4314  qreal m12 = transform.m12();
4315  qreal m21 = transform.m21();
4316  qreal m22 = transform.m22();
4317  if (m11 == 0.0f && m22 == 0.0f) {
4318  if (m12 == 1.0f && m21 == -1.0f)
4319  return true; // 90 degrees.
4320  else if (m12 == -1.0f && m21 == 1.0f)
4321  return true; // 270 degrees.
4322  else if (m12 == -1.0f && m21 == -1.0f)
4323  return true; // 90 degrees inverted y.
4324  else if (m12 == 1.0f && m21 == 1.0f)
4325  return true; // 270 degrees inverted y.
4326  }
4327  }
4328  return false;
4329 }
4330 
4338  bool painterStateProtection)
4339 {
4340  QGraphicsItemPrivate *itemd = item->d_ptr.data();
4342 
4343  // Render directly, using no cache.
4344  if (cacheMode == QGraphicsItem::NoCache) {
4345  _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget, true, painterStateProtection);
4346  return;
4347  }
4348 
4349  const qreal devicePixelRatio = painter->device()->devicePixelRatio();
4350  const qreal oldPainterOpacity = painter->opacity();
4351  qreal newPainterOpacity = oldPainterOpacity;
4352  QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(item)) : 0;
4353  if (proxy && proxy->widget()) {
4354  const qreal windowOpacity = proxy->widget()->windowOpacity();
4355  if (windowOpacity < 1.0)
4356  newPainterOpacity *= windowOpacity;
4357  }
4358 
4359  // Item's (local) bounding rect
4360  QRectF brect = item->boundingRect();
4361  QRectF adjustedBrect(brect);
4362  _q_adjustRect(&adjustedBrect);
4363  if (adjustedBrect.isEmpty())
4364  return;
4365 
4366  // Fetch the off-screen transparent buffer and exposed area info.
4367  QPixmapCache::Key pixmapKey;
4368  QPixmap pix;
4369 
4370  bool pixmapFound;
4371  QGraphicsItemCache *itemCache = itemd->extraItemCache();
4372  if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4373  pixmapKey = itemCache->key;
4374  } else {
4375  pixmapKey = itemCache->deviceData.value(widget).key;
4376  }
4377 
4378  // Find pixmap in cache.
4379  pixmapFound = QPixmapCache::find(pixmapKey, &pix);
4380 
4381  // Render using item coordinate cache mode.
4382  if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4383  QSize pixmapSize;
4384  bool fixedCacheSize = itemCache->fixedSize.isValid();
4385  QRect br = brect.toAlignedRect();
4386  if (fixedCacheSize) {
4387  pixmapSize = itemCache->fixedSize;
4388  } else {
4389  pixmapSize = br.size();
4390  }
4391 
4392  pixmapSize *= devicePixelRatio;
4393 
4394  // Create or recreate the pixmap.
4395  int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
4396  QSize adjustSize(adjust*2, adjust*2);
4397  br.adjust(-adjust / devicePixelRatio, -adjust / devicePixelRatio, adjust / devicePixelRatio, adjust / devicePixelRatio);
4398  if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
4399  pix = QPixmap(pixmapSize + adjustSize);
4400  itemCache->boundingRect = br;
4401  itemCache->exposed.clear();
4402  itemCache->allExposed = true;
4403  } else if (itemCache->boundingRect != br) {
4404  itemCache->boundingRect = br;
4405  itemCache->exposed.clear();
4406  itemCache->allExposed = true;
4407  }
4408 
4409  // Redraw any newly exposed areas.
4410  if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
4411 
4412  //We know that we will modify the pixmap, removing it from the cache
4413  //will detach the one we have and avoid a deep copy
4414  if (pixmapFound)
4415  QPixmapCache::remove(pixmapKey);
4416 
4417  // Fit the item's bounding rect into the pixmap's coordinates.
4418  QTransform itemToPixmap;
4419  if (fixedCacheSize) {
4420  const QPointF scale((pixmapSize.width() / devicePixelRatio) / brect.width(),
4421  (pixmapSize.height() / devicePixelRatio) / brect.height());
4422  itemToPixmap.scale(scale.x(), scale.y());
4423  }
4424  itemToPixmap.translate(-br.x(), -br.y());
4425 
4426  // Generate the item's exposedRect and map its list of expose
4427  // rects to device coordinates.
4429  QRegion pixmapExposed;
4430  QRectF exposedRect;
4431  if (!itemCache->allExposed) {
4432  for (const auto &rect : qAsConst(itemCache->exposed)) {
4433  exposedRect |= rect;
4434  pixmapExposed += itemToPixmap.mapRect(rect).toAlignedRect();
4435  }
4436  } else {
4437  exposedRect = brect;
4438  }
4439  styleOptionTmp.exposedRect = exposedRect;
4440 
4441  // Render.
4442  pix.setDevicePixelRatio(devicePixelRatio);
4443  _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4445 
4446  // insert this pixmap into the cache.
4447  itemCache->key = QPixmapCache::insert(pix);
4448 
4449  // Reset expose data.
4450  itemCache->allExposed = false;
4451  itemCache->exposed.clear();
4452  }
4453 
4454  // Redraw the exposed area using the transformed painter. Depending on
4455  // the hardware, this may be a server-side operation, or an expensive
4456  // qpixmap-image-transform-pixmap roundtrip.
4457  if (newPainterOpacity != oldPainterOpacity) {
4458  painter->setOpacity(newPainterOpacity);
4459  painter->drawPixmap(br.topLeft(), pix);
4460  painter->setOpacity(oldPainterOpacity);
4461  } else {
4462  painter->drawPixmap(br.topLeft(), pix);
4463  }
4464  return;
4465  }
4466 
4467  // Render using device coordinate cache mode.
4468  if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
4469  // Find the item's bounds in device coordinates.
4470  QRectF deviceBounds = painter->worldTransform().mapRect(brect);
4471  QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
4472  if (deviceRect.isEmpty())
4473  return;
4474  QRect viewRect = widget ? widget->rect() : QRect();
4475  if (widget && !viewRect.intersects(deviceRect))
4476  return;
4477 
4478  // Resort to direct rendering if the device rect exceeds the
4479  // (optional) maximum bounds. (QGraphicsSvgItem uses this).
4480  QSize maximumCacheSize =
4482  if (!maximumCacheSize.isEmpty()
4483  && (deviceRect.width() > maximumCacheSize.width()
4484  || deviceRect.height() > maximumCacheSize.height())) {
4485  _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget,
4486  oldPainterOpacity != newPainterOpacity, painterStateProtection);
4487  return;
4488  }
4489 
4490  // Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
4491  // If the world transform is rotated we always recreate the cache to avoid
4492  // wrong blending.
4493  bool pixModified = false;
4494  QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
4495  bool invertable = true;
4496  QTransform diff = deviceData->lastTransform.inverted(&invertable);
4497  if (invertable)
4498  diff *= painter->worldTransform();
4499  deviceData->lastTransform = painter->worldTransform();
4500  bool allowPartialCacheExposure = false;
4501  bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
4502  && transformIsSimple(painter->worldTransform());
4503  if (!simpleTransform) {
4504  pixModified = true;
4505  itemCache->allExposed = true;
4506  itemCache->exposed.clear();
4507  deviceData->cacheIndent = QPoint();
4508  pix = QPixmap();
4509  } else if (!viewRect.isNull()) {
4510  allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
4511  }
4512 
4513  // Allow partial cache exposure if the device rect isn't fully contained and
4514  // deviceRect is 20% taller or wider than the viewRect.
4515  if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
4516  allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
4517  || (viewRect.height() * 1.2 < deviceRect.height());
4518  }
4519 
4520  QRegion scrollExposure;
4521  if (allowPartialCacheExposure) {
4522  // Part of pixmap is drawn. Either device contains viewrect (big
4523  // item covers whole screen) or parts of device are outside the
4524  // viewport. In either case the device rect must be the intersect
4525  // between the two.
4526  int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
4527  int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
4528  QPoint newCacheIndent(dx, dy);
4529  deviceRect &= viewRect;
4530 
4531  if (pix.isNull()) {
4532  deviceData->cacheIndent = QPoint();
4533  itemCache->allExposed = true;
4534  itemCache->exposed.clear();
4535  pixModified = true;
4536  }
4537 
4538  // Copy / "scroll" the old pixmap onto the new ole and calculate
4539  // scrolled exposure.
4540  if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size() / devicePixelRatio) {
4541  QPoint diff = newCacheIndent - deviceData->cacheIndent;
4542  QPixmap newPix(deviceRect.size() * devicePixelRatio);
4543  // ### Investigate removing this fill (test with Plasma and
4544  // graphicssystem raster).
4545  newPix.fill(Qt::transparent);
4546  if (!pix.isNull()) {
4547  newPix.setDevicePixelRatio(devicePixelRatio);
4548  QPainter newPixPainter(&newPix);
4549  newPixPainter.drawPixmap(-diff, pix);
4550  newPixPainter.end();
4551  }
4552  QRegion exposed;
4553  exposed += QRect(QPoint(0,0), newPix.size() / devicePixelRatio);
4554  if (!pix.isNull())
4555  exposed -= QRect(-diff, pix.size() / devicePixelRatio);
4556  scrollExposure = exposed;
4557 
4558  pix = newPix;
4559  pixModified = true;
4560  }
4561  deviceData->cacheIndent = newCacheIndent;
4562  } else {
4563  // Full pixmap is drawn.
4564  deviceData->cacheIndent = QPoint();
4565 
4566  // Auto-adjust the pixmap size.
4567  if (deviceRect.size() != pix.size() / devicePixelRatio) {
4568  // exposed needs to cover the whole pixmap
4569  pix = QPixmap(deviceRect.size() * devicePixelRatio);
4570  pixModified = true;
4571  itemCache->allExposed = true;
4572  itemCache->exposed.clear();
4573  }
4574  }
4575 
4576  // Check for newly invalidated areas.
4577  if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
4578  //We know that we will modify the pixmap, removing it from the cache
4579  //will detach the one we have and avoid a deep copy
4580  if (pixmapFound)
4581  QPixmapCache::remove(pixmapKey);
4582 
4583  // Construct an item-to-pixmap transform.
4585  QTransform itemToPixmap = painter->worldTransform();
4586  if (!p.isNull())
4587  itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
4588 
4589  // Map the item's logical expose to pixmap coordinates.
4590  QRegion pixmapExposed = scrollExposure;
4591  if (!itemCache->allExposed) {
4592  for (const auto &rect : qAsConst(itemCache->exposed))
4593  pixmapExposed += itemToPixmap.mapRect(rect).toRect().adjusted(-1, -1, 1, 1);
4594  }
4595 
4596  // Calculate the style option's exposedRect.
4597  QRectF br;
4598  if (itemCache->allExposed) {
4599  br = item->boundingRect();
4600  } else {
4601  for (const auto &rect : qAsConst(itemCache->exposed))
4602  br |= rect;
4603  QTransform pixmapToItem = itemToPixmap.inverted();
4604  for (const QRect &r : qAsConst(scrollExposure))
4605  br |= pixmapToItem.mapRect(r);
4606  }
4608  styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
4609 
4610  // Render the exposed areas.
4611  pix.setDevicePixelRatio(devicePixelRatio);
4612  _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4614 
4615  // Reset expose data.
4616  pixModified = true;
4617  itemCache->allExposed = false;
4618  itemCache->exposed.clear();
4619  }
4620 
4621  if (pixModified) {
4622  // Insert this pixmap into the cache.
4623  deviceData->key = QPixmapCache::insert(pix);
4624  }
4625 
4626  // Redraw the exposed area using an untransformed painter. This
4627  // effectively becomes a bitblit that does not transform the cache.
4628  QTransform restoreTransform = painter->worldTransform();
4630  if (newPainterOpacity != oldPainterOpacity) {
4631  painter->setOpacity(newPainterOpacity);
4633  painter->setOpacity(oldPainterOpacity);
4634  } else {
4636  }
4637  painter->setWorldTransform(restoreTransform);
4638  return;
4639  }
4640 }
4641 
4643  QRegion *exposedRegion, QWidget *widget)
4644 {
4645  // Make sure we don't have unpolished items before we draw.
4646  if (!unpolishedItems.isEmpty())
4647  _q_polishItems();
4648 
4649  updateAll = false;
4650  QRectF exposedSceneRect;
4651  if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
4652  exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
4653  if (viewTransform)
4654  exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
4655  }
4656  const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder);
4657  for (const auto subTree : tli)
4658  drawSubtreeRecursive(subTree, painter, viewTransform, exposedRegion, widget);
4659 }
4660 
4662  const QTransform *const viewTransform,
4663  QRegion *exposedRegion, QWidget *widget,
4664  qreal parentOpacity, const QTransform *const effectTransform)
4665 {
4666  Q_ASSERT(item);
4667 
4668  if (!item->d_ptr->visible)
4669  return;
4670 
4671  const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
4672  const bool itemHasChildren = !item->d_ptr->children.isEmpty();
4673  if (!itemHasContents && !itemHasChildren)
4674  return; // Item has neither contents nor children!(?)
4675 
4676  const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
4677  const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4678  if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
4679  return;
4680 
4682  QTransform *transformPtr = nullptr;
4683  bool translateOnlyTransform = false;
4684 #define ENSURE_TRANSFORM_PTR \
4685  if (!transformPtr) { \
4686  Q_ASSERT(!itemIsUntransformable); \
4687  if (viewTransform) { \
4688  transform = item->d_ptr->sceneTransform; \
4689  transform *= *viewTransform; \
4690  transformPtr = &transform; \
4691  } else { \
4692  transformPtr = &item->d_ptr->sceneTransform; \
4693  translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
4694  } \
4695  }
4696 
4697  // Update the item's scene transform if the item is transformable;
4698  // otherwise calculate the full transform,
4699  bool wasDirtyParentSceneTransform = false;
4700  const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
4701  if (itemIsUntransformable) {
4702  transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
4703  transformPtr = &transform;
4704  } else if (item->d_ptr->dirtySceneTransform) {
4707  wasDirtyParentSceneTransform = true;
4708  }
4709 
4710  const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
4712  bool drawItem = itemHasContents && !itemIsFullyTransparent;
4713  if (drawItem || minimumRenderSize > 0.0) {
4714  const QRectF brect = adjustedItemEffectiveBoundingRect(item);
4716  QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
4717  : transformPtr->mapRect(brect);
4718 
4719  bool itemIsTooSmallToRender = false;
4720  if (minimumRenderSize > 0.0
4721  && (preciseViewBoundingRect.width() < minimumRenderSize
4722  || preciseViewBoundingRect.height() < minimumRenderSize)) {
4723  itemIsTooSmallToRender = true;
4724  drawItem = false;
4725  }
4726 
4727  bool itemIsOutsideVisibleRect = false;
4728  if (drawItem) {
4729  QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
4730  viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
4731  if (widget)
4732  item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
4733  drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
4734  : !viewBoundingRect.normalized().isEmpty();
4735  itemIsOutsideVisibleRect = !drawItem;
4736  }
4737 
4738  if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
4739  // We cannot simply use !drawItem here. If we did it is possible
4740  // to enter the outer if statement with drawItem == false and minimumRenderSize > 0
4741  // and finally end up inside this inner if, even though none of the above two
4742  // conditions are met. In that case we should not return from this function
4743  // but call draw() instead.
4744  if (!itemHasChildren)
4745  return;
4746  if (itemClipsChildrenToShape) {
4747  if (wasDirtyParentSceneTransform)
4749  return;
4750  }
4751  }
4752  } // else we know for sure this item has children we must process.
4753 
4754  if (itemHasChildren && itemClipsChildrenToShape)
4756 
4757 #if QT_CONFIG(graphicseffect)
4760  QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
4761  painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
4763  QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
4764  (source->d_func());
4765  sourced->info = &info;
4766  const QTransform restoreTransform = painter->worldTransform();
4767  if (effectTransform)
4768  painter->setWorldTransform(*transformPtr * *effectTransform);
4769  else
4770  painter->setWorldTransform(*transformPtr);
4771  painter->setOpacity(opacity);
4772 
4773  if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
4774  && sourced->lastEffectTransform != painter->worldTransform())
4775  {
4776  if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
4778  {
4779  QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
4780  QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
4781 
4782  sourced->setCachedOffset(effectRect.topLeft());
4783  } else {
4784  sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
4785  }
4786 
4787  sourced->lastEffectTransform = painter->worldTransform();
4788  }
4789 
4791  painter->setWorldTransform(restoreTransform);
4792  sourced->info = nullptr;
4793  } else
4794 #endif // QT_CONFIG(graphicseffect)
4795  {
4796  draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
4797  effectTransform, wasDirtyParentSceneTransform, drawItem);
4798  }
4799 }
4800 
4801 static inline void setClip(QPainter *painter, QGraphicsItem *item)
4802 {
4803  painter->save();
4804  QRectF clipRect;
4805  const QPainterPath clipPath(item->shape());
4806  if (QPathClipper::pathToRect(clipPath, &clipRect))
4808  else
4810 }
4811 
4812 static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr,
4813  const QTransform *effectTransform)
4814 {
4815  Q_ASSERT(transformPtr);
4816  if (effectTransform)
4817  painter->setWorldTransform(*transformPtr * *effectTransform);
4818  else
4819  painter->setWorldTransform(*transformPtr);
4820 }
4821 
4823  const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
4824  qreal opacity, const QTransform *effectTransform,
4825  bool wasDirtyParentSceneTransform, bool drawItem)
4826 {
4827  const auto &children = item->d_ptr->children;
4828 
4829  const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4830  const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
4831  const bool itemHasChildren = !children.isEmpty();
4832  bool setChildClip = itemClipsChildrenToShape;
4833  bool itemHasChildrenStackedBehind = false;
4834 
4835  int i = 0;
4836  if (itemHasChildren) {
4837  if (itemClipsChildrenToShape)
4838  setWorldTransform(painter, transformPtr, effectTransform);
4839 
4841  // Items with the 'ItemStacksBehindParent' flag are put in front of the list
4842  // so all we have to do is to check the first item.
4843  itemHasChildrenStackedBehind = (children.at(0)->d_ptr->flags
4845 
4846  if (itemHasChildrenStackedBehind) {
4847  if (itemClipsChildrenToShape) {
4848  setClip(painter, item);
4849  setChildClip = false;
4850  }
4851 
4852  // Draw children behind
4853  for (i = 0; i < children.size(); ++i) {
4855  if (wasDirtyParentSceneTransform)
4856  child->d_ptr->dirtySceneTransform = 1;
4857  if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
4858  break;
4859  if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4860  continue;
4861  drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4862  }
4863  }
4864  }
4865 
4866  // Draw item
4867  if (drawItem) {
4868  Q_ASSERT(!itemIsFullyTransparent);
4870  Q_ASSERT(transformPtr);
4871  item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
4872  ? *exposedRegion : QRegion(), exposedRegion == nullptr);
4873 
4874  const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
4875  bool restorePainterClip = false;
4876 
4877  if (!itemHasChildren || !itemClipsChildrenToShape) {
4878  // Item does not have children or clip children to shape.
4879  setWorldTransform(painter, transformPtr, effectTransform);
4880  if ((restorePainterClip = itemClipsToShape))
4881  setClip(painter, item);
4882  } else if (itemHasChildrenStackedBehind){
4883  // Item clips children to shape and has children stacked behind, which means
4884  // the painter is already clipped to the item's shape.
4885  if (itemClipsToShape) {
4886  // The clip is already correct. Ensure correct world transform.
4887  setWorldTransform(painter, transformPtr, effectTransform);
4888  } else {
4889  // Remove clip (this also ensures correct world transform).
4890  painter->restore();
4891  setChildClip = true;
4892  }
4893  } else if (itemClipsToShape) {
4894  // Item clips children and itself to shape. It does not have hildren stacked
4895  // behind, which means the clip has not yet been set. We set it now and re-use it
4896  // for the children.
4897  setClip(painter, item);
4898  setChildClip = false;
4899  }
4900 
4901  if (painterStateProtection && !restorePainterClip)
4902  painter->save();
4903 
4904  painter->setOpacity(opacity);
4905  if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
4907  else
4909 
4910  if (painterStateProtection || restorePainterClip)
4911  painter->restore();
4912 
4913  static int drawRect = qEnvironmentVariableIntValue("QT_DRAW_SCENE_ITEM_RECTS");
4914  if (drawRect) {
4915  QPen oldPen = painter->pen();
4916  QBrush oldBrush = painter->brush();
4917  quintptr ptr = reinterpret_cast<quintptr>(item);
4918  const QColor color = QColor::fromHsv(ptr % 255, 255, 255);
4919  painter->setPen(color);
4921  painter->drawRect(adjustedItemBoundingRect(item));
4922  painter->setPen(oldPen);
4923  painter->setBrush(oldBrush);
4924  }
4925  }
4926 
4927  // Draw children in front
4928  if (itemHasChildren) {
4929  if (setChildClip)
4930  setClip(painter, item);
4931 
4932  for (; i < children.size(); ++i) {
4934  if (wasDirtyParentSceneTransform)
4935  child->d_ptr->dirtySceneTransform = 1;
4936  if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4937  continue;
4938  drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4939  }
4940 
4941  // Restore child clip
4942  if (itemClipsChildrenToShape)
4943  painter->restore();
4944  }
4945 }
4946 
4947 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
4948  bool force, bool ignoreOpacity, bool removingItemFromScene,
4949  bool updateBoundingRect)
4950 {
4951  Q_ASSERT(item);
4952  if (updateAll)
4953  return;
4954 
4955  if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
4956  // If any of the item's ancestors ignore opacity, it means that the opacity
4957  // was set to 0 (and the update request has not yet been processed). That
4958  // also means that we have to ignore the opacity for the item itself; otherwise
4959  // things like: parent->setOpacity(0); scene->removeItem(child) won't work.
4960  // Note that we only do this when removing items from the scene. In all other
4961  // cases the ignoreOpacity bit propagates properly in processDirtyItems, but
4962  // since the item is removed immediately it won't be processed there.
4964  while (p) {
4965  if (p->d_ptr->ignoreOpacity) {
4966  item->d_ptr->ignoreOpacity = true;
4967  break;
4968  }
4969  p = p->d_ptr->parent;
4970  }
4971  }
4972 
4973  if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force,
4974  /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
4975  /*ignoreOpacity=*/ignoreOpacity)) {
4976  if (item->d_ptr->dirty) {
4977  // The item is already marked as dirty and will be processed later. However,
4978  // we have to make sure ignoreVisible and ignoreOpacity are set properly;
4979  // otherwise things like: item->update(); item->hide() (force is now true)
4980  // won't work as expected.
4981  if (force)
4982  item->d_ptr->ignoreVisible = 1;
4983  if (ignoreOpacity)
4984  item->d_ptr->ignoreOpacity = 1;
4985  }
4986  return;
4987  }
4988 
4989  const bool fullItemUpdate = rect.isNull();
4990  if (!fullItemUpdate && rect.isEmpty())
4991  return;
4992 
4993  if (!processDirtyItemsEmitted) {
4994  QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
4996 // QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
4997  processDirtyItemsEmitted = true;
4998  }
4999 
5000  if (removingItemFromScene) {
5001  // Note that this function can be called from the item's destructor, so
5002  // do NOT call any virtual functions on it within this block.
5004  // This block of code is kept for compatibility. Since 4.5, by default
5005  // QGraphicsView does not connect the signal and we use the below
5006  // method of delivering updates.
5007  q_func()->update();
5008  return;
5009  }
5010 
5011  for (auto view : qAsConst(views)) {
5012  QGraphicsViewPrivate *viewPrivate = view->d_func();
5013  QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
5014  rect.translate(viewPrivate->dirtyScrollOffset);
5015  viewPrivate->updateRect(rect);
5016  }
5017  return;
5018  }
5019 
5020  bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
5021  if (!hasNoContents) {
5022  item->d_ptr->dirty = 1;
5023  if (fullItemUpdate)
5025  else if (!item->d_ptr->fullUpdatePending)
5026  item->d_ptr->needsRepaint |= rect;
5027  } else if (item->d_ptr->graphicsEffect) {
5028  invalidateChildren = true;
5029  }
5030 
5031  if (invalidateChildren) {
5032  item->d_ptr->allChildrenDirty = 1;
5033  item->d_ptr->dirtyChildren = 1;
5034  }
5035 
5036  if (force)
5037  item->d_ptr->ignoreVisible = 1;
5038  if (ignoreOpacity)
5039  item->d_ptr->ignoreOpacity = 1;
5040 
5041  if (!updateBoundingRect)
5043 }
5044 
5045 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
5046  const QRectF &rect, bool itemIsUntransformable)
5047 {
5048  Q_ASSERT(view);
5049  Q_ASSERT(item);
5050 
5051  QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr);
5052  QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr);
5053 
5054  if (itemIsUntransformable) {
5055  const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
5056  if (!item->hasBoundingRegionGranularity)
5057  return view->updateRectF(xform.mapRect(rect));
5058  return view->updateRegion(rect, xform);
5059  }
5060 
5061  if (item->sceneTransformTranslateOnly && view->identityMatrix) {
5062  const qreal dx = item->sceneTransform.dx();
5063  const qreal dy = item->sceneTransform.dy();
5064  QRectF r(rect);
5065  r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
5066  return view->updateRectF(r);
5067  }
5068 
5069  if (!viewq->isTransformed()) {
5070  if (!item->hasBoundingRegionGranularity)
5071  return view->updateRectF(item->sceneTransform.mapRect(rect));
5072  return view->updateRegion(rect, item->sceneTransform);
5073  }
5074 
5076  xform *= viewq->viewportTransform();
5077  if (!item->hasBoundingRegionGranularity)
5078  return view->updateRectF(xform.mapRect(rect));
5079  return view->updateRegion(rect, xform);
5080 }
5081 
5083  qreal parentOpacity)
5084 {
5085  Q_Q(QGraphicsScene);
5086  Q_ASSERT(item);
5087  Q_ASSERT(!updateAll);
5088 
5089  if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
5091  return;
5092  }
5093 
5094  const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
5095  if (itemIsHidden) {
5096  resetDirtyItem(item, /*recursive=*/true);
5097  return;
5098  }
5099 
5100  bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
5101  const bool itemHasChildren = !item->d_ptr->children.isEmpty();
5102  if (!itemHasContents) {
5103  if (!itemHasChildren) {
5105  return; // Item has neither contents nor children!(?)
5106  }
5107  if (item->d_ptr->graphicsEffect)
5108  itemHasContents = true;
5109  }
5110 
5111  const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
5112  const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
5114  if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
5115  resetDirtyItem(item, /*recursive=*/itemHasChildren);
5116  return;
5117  }
5118 
5119  bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
5120  const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
5121  if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
5124  }
5125 
5126  const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
5127  if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
5128  // Make sure we don't process invisible items or items with no content.
5129  item->d_ptr->dirty = 0;
5131  // Might have a dirty view bounding rect otherwise.
5132  if (itemIsFullyTransparent || !itemHasContents)
5134  }
5135 
5137  // Update growingItemsBoundingRect.
5140  item->d_ptr->sceneTransform.dy());
5141  } else {
5143  }
5144  }
5145 
5146  // Process item.
5148  const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
5149  const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
5150 
5151  if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
5152  // This block of code is kept for compatibility. Since 4.5, by default
5153  // QGraphicsView does not connect the signal and we use the below
5154  // method of delivering updates.
5156  q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
5157  item->d_ptr->sceneTransform.dy()));
5158  } else {
5159  QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
5160  if (!rect.isEmpty())
5161  q->update(rect);
5162  }
5163  } else {
5164  QRectF dirtyRect;
5165  bool uninitializedDirtyRect = true;
5166 
5167  for (auto view : qAsConst(views)) {
5168  QGraphicsViewPrivate *viewPrivate = view->d_func();
5169  QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
5170  if (viewPrivate->fullUpdatePending
5172  // Okay, if we have a full update pending or no viewport update, this item's
5173  // paintedViewBoundingRect will be updated correctly in the next paintEvent if
5174  // it is inside the viewport, but for now we can pretend that it is outside.
5175  paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5176  continue;
5177  }
5178 
5180  paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
5181  if (!viewPrivate->updateRect(paintedViewBoundingRect))
5182  paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
5183  }
5184 
5185  if (!item->d_ptr->dirty)
5186  continue;
5187 
5189  && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
5190  && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
5191  continue; // Outside viewport.
5192  }
5193 
5194  if (uninitializedDirtyRect) {
5195  dirtyRect = itemBoundingRect;
5196  if (!item->d_ptr->fullUpdatePending) {
5197  _q_adjustRect(&item->d_ptr->needsRepaint);
5198  dirtyRect &= item->d_ptr->needsRepaint;
5199  }
5200  uninitializedDirtyRect = false;
5201  }
5202 
5203  if (dirtyRect.isEmpty())
5204  continue; // Discard updates outside the bounding rect.
5205 
5206  if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
5208  paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
5209  }
5210  }
5211  }
5212  }
5213 
5214  // Process children.
5215  if (itemHasChildren && item->d_ptr->dirtyChildren) {
5216  const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
5218  // Items with no content are threated as 'dummy' items which means they are never drawn and
5219  // 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
5220  // such an item changes geometry, its children have to take care of the update regardless
5221  // of whether the item clips children to shape or not.
5222  const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
5223  if (itemClipsChildrenToShape && !bypassUpdateClip) {
5224  // Make sure child updates are clipped to the item's bounding rect.
5225  for (auto view : qAsConst(views))
5226  view->d_func()->setUpdateClip(item);
5227  }
5228  if (!dirtyAncestorContainsChildren) {
5229  dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
5230  && itemClipsChildrenToShape;
5231  }
5232  const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
5233  const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
5234  const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
5235  for (auto child : qAsConst(item->d_ptr->children)) {
5236  if (wasDirtyParentSceneTransform)
5237  child->d_ptr->dirtySceneTransform = 1;
5238  if (wasDirtyParentViewBoundingRects)
5239  child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
5240  if (parentIgnoresVisible)
5241  child->d_ptr->ignoreVisible = 1;
5242  if (parentIgnoresOpacity)
5243  child->d_ptr->ignoreOpacity = 1;
5244  if (allChildrenDirty) {
5245  child->d_ptr->dirty = 1;
5246  child->d_ptr->fullUpdatePending = 1;
5247  child->d_ptr->dirtyChildren = 1;
5248  child->d_ptr->allChildrenDirty = 1;
5249  }
5250  processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
5251  }
5252 
5253  if (itemClipsChildrenToShape) {
5254  // Reset updateClip.
5255  for (auto view : qAsConst(views))
5256  view->d_func()->setUpdateClip(nullptr);
5257  }
5258  } else if (wasDirtyParentSceneTransform) {
5260  }
5261 
5263 }
5264 
5297  int numItems,
5298  QGraphicsItem *items[],
5299  const QStyleOptionGraphicsItem options[], QWidget *widget)
5300 {
5301  Q_D(QGraphicsScene);
5302  // Make sure we don't have unpolished items before we draw.
5303  if (!d->unpolishedItems.isEmpty())
5304  d->_q_polishItems();
5305 
5306  const qreal opacity = painter->opacity();
5307  QTransform viewTransform = painter->worldTransform();
5308  Q_UNUSED(options);
5309 
5310  // Determine view, expose and flags.
5311  QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
5312  QRegion *expose = nullptr;
5313  const quint32 oldRectAdjust = d->rectAdjust;
5314  if (view) {
5315  d->updateAll = false;
5316  expose = &view->d_func()->exposedRegion;
5317  if (view->d_func()->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
5318  d->rectAdjust = 1;
5319  else
5320  d->rectAdjust = 2;
5321  }
5322 
5323  // Find all toplevels, they are already sorted.
5324  QList<QGraphicsItem *> topLevelItems;
5325  for (int i = 0; i < numItems; ++i) {
5326  QGraphicsItem *item = items[i]->topLevelItem();
5327  if (!item->d_ptr->itemDiscovered) {
5328  topLevelItems << item;
5329  item->d_ptr->itemDiscovered = 1;
5330  d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
5331  }
5332  }
5333 
5334  d->rectAdjust = oldRectAdjust;
5335  // Reset discovery bits.
5336  for (auto topLevelItem : qAsConst(topLevelItems))
5337  topLevelItem->d_ptr->itemDiscovered = 0;
5338 
5339  painter->setWorldTransform(viewTransform);
5340  painter->setOpacity(opacity);
5341 }
5342 
5357 {
5358  Q_D(QGraphicsScene);
5359 
5361  if (item && !item->isWidget()) {
5362  // Tab out of the scene.
5363  return false;
5364  }
5365  if (!item) {
5366  if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
5367  // Restore focus to the last focusable non-widget item that had
5368  // focus.
5370  return true;
5371  }
5372  if (d->activePanel) {
5373  if (d->activePanel->flags() & QGraphicsItem::ItemIsFocusable) {
5375  return true;
5376  }
5377  if (d->activePanel->isWidget()) {
5378  QGraphicsWidget *test = static_cast<QGraphicsWidget *>(d->activePanel);
5379  QGraphicsWidget *fw = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5380  do {
5381  if (fw->focusPolicy() & Qt::TabFocus) {
5383  return true;
5384  }
5385  fw = next ? fw->d_func()->focusNext : fw->d_func()->focusPrev;
5386  } while (fw != d->activePanel);
5387  }
5388  }
5389  }
5390  if (!item && !d->tabFocusFirst) {
5391  // No widgets...
5392  return false;
5393  }
5394 
5395  // The item must be a widget.
5396  QGraphicsWidget *widget = nullptr;
5397  if (!item) {
5398  widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
5399  } else {
5400  QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item);
5401  widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5402  if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) {
5403  // Tab out of the scene.
5404  return false;
5405  }
5406  }
5407  QGraphicsWidget *widgetThatHadFocus = widget;
5408 
5409  // Run around the focus chain until we find a widget that can take tab focus.
5410  do {
5411  if (widget->flags() & QGraphicsItem::ItemIsFocusable
5412  && widget->isEnabled() && widget->isVisibleTo(nullptr)
5413  && (widget->focusPolicy() & Qt::TabFocus)
5414  && (!item || !item->isPanel() || item->isAncestorOf(widget))
5415  ) {
5417  return true;
5418  }
5419  widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
5420  if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
5421  return false;
5422  } while (widget != widgetThatHadFocus);
5423 
5424  return false;
5425 }
5426 
5496 {
5497  Q_D(const QGraphicsScene);
5498  // ### This function, and the use of styles in general, is non-reentrant.
5499  return d->style ? d->style : QApplication::style();
5500 }
5501 
5520 {
5521  Q_D(QGraphicsScene);
5522  // ### This function, and the use of styles in general, is non-reentrant.
5523  if (style == d->style)
5524  return;
5525 
5526  // Delete the old style,
5527  delete d->style;
5528  if ((d->style = style))
5529  d->style->setParent(this);
5530 
5531  // Notify the scene.
5534 
5535  // Notify all widgets that don't have a style explicitly set.
5536  const auto items_ = items();
5537  for (QGraphicsItem *item : items_) {
5538  if (item->isWidget()) {
5539  QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
5542  }
5543  }
5544 }
5545 
5570 {
5571  Q_D(const QGraphicsScene);
5572  return d->font;
5573 }
5575 {
5576  Q_D(QGraphicsScene);
5577  QFont naturalFont = QApplication::font();
5578  naturalFont.setResolveMask(0);
5579  QFont resolvedFont = font.resolve(naturalFont);
5580  d->setFont_helper(resolvedFont);
5581 }
5582 
5607 {
5608  Q_D(const QGraphicsScene);
5609  return d->palette;
5610 }
5612 {
5613  Q_D(QGraphicsScene);
5614  QPalette naturalPalette = QGuiApplication::palette();
5615  naturalPalette.setResolveMask(0);
5616  QPalette resolvedPalette = palette.resolve(naturalPalette);
5617  d->setPalette_helper(resolvedPalette);
5618 }
5619 
5629 {
5630  Q_D(const QGraphicsScene);
5631  return d->activationRefCount > 0;
5632 }
5633 
5642 {
5643  Q_D(const QGraphicsScene);
5644  return d->activePanel;
5645 }
5646 
5659 {
5660  Q_D(QGraphicsScene);
5661  d->setActivePanelHelper(item, false);
5662 }
5663 
5673 {
5674  Q_D(const QGraphicsScene);
5675  if (d->activePanel && d->activePanel->isWindow())
5676  return static_cast<QGraphicsWidget *>(d->activePanel);
5677  return nullptr;
5678 }
5679 
5689 {
5690  if (widget && widget->scene() != this) {
5691  qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
5692  widget);
5693  return;
5694  }
5695 
5696  // Activate the widget's panel (all windows are panels).
5697  QGraphicsItem *panel = widget ? widget->panel() : nullptr;
5699 
5700  // Raise
5701  if (panel) {
5702  QGraphicsItem *parent = panel->parentItem();
5703  // Raise ### inefficient for toplevels
5704 
5705  // Find the highest z value.
5706  qreal z = panel->zValue();
5707  const auto siblings = parent ? parent->childItems() : items();
5708  for (QGraphicsItem *sibling : siblings) {
5709  if (sibling != panel && sibling->isWindow())
5710  z = qMax(z, sibling->zValue());
5711  }
5712 
5713  // This will probably never overflow.
5714  const qreal litt = qreal(0.001);
5715  panel->setZValue(z + litt);
5716  }
5717 }
5718 
5732 {
5733  Q_D(QGraphicsScene);
5734  if (!item) {
5735  qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
5736  return false;
5737  }
5738  if (item->scene() != this) {
5739  qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
5740  " is different from this scene (%p)",
5741  item, item->scene(), this);
5742  return false;
5743  }
5744  return d->sendEvent(item, event);
5745 }
5746 
5779 {
5780  Q_D(const QGraphicsScene);
5781  return d->minimumRenderSize;
5782 }
5784 {
5785  Q_D(QGraphicsScene);
5786  d->minimumRenderSize = minSize;
5787  update();
5788 }
5789 
5814 {
5815  Q_D(const QGraphicsScene);
5816  return d->focusOnTouch;
5817 }
5818 
5820 {
5821  Q_D(QGraphicsScene);
5822  d->focusOnTouch = enabled;
5823 }
5824 
5826 {
5827  views << view;
5828 #ifndef QT_NO_GESTURES
5829  for (auto it = grabbedGestures.constBegin();
5830  it != grabbedGestures.constEnd(); ++it)
5831  view->viewport()->grabGesture(it.key());
5832 #endif
5833 }
5834 
5836 {
5837  views.removeAll(view);
5838 }
5839 
5841 {
5842  const QTransform mapFromScene =
5843  item->d_ptr->genericMapFromSceneTransform(static_cast<const QWidget *>(touchEvent->target()));
5844 
5845  for (int i = 0; i < touchEvent->pointCount(); ++i) {
5846  auto &pt = touchEvent->point(i);
5847  QMutableEventPoint::setPosition(pt, mapFromScene.map(pt.scenePosition()));
5848  }
5849 }
5850 
5852 {
5853  int closestTouchPointId = -1;
5854  qreal closestDistance = qreal(0.);
5855  for (const QEventPoint &touchPoint : qAsConst(sceneCurrentTouchPoints)) {
5856  qreal distance = QLineF(scenePos, touchPoint.scenePosition()).length();
5857  if (closestTouchPointId == -1|| distance < closestDistance) {
5858  closestTouchPointId = touchPoint.id();
5859  closestDistance = distance;
5860  }
5861  }
5862  return closestTouchPointId;
5863 }
5864 
5866 {
5867  typedef QPair<QEventPoint::States, QList<QEventPoint> > StatesAndTouchPoints;
5869 
5870  const auto &touchPoints = sceneTouchEvent->points();
5871  for (const auto &touchPoint : touchPoints) {
5872  // update state
5873  QGraphicsItem *item = nullptr;
5874  if (touchPoint.state() == QEventPoint::State::Pressed) {
5875  if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchPad) {
5876  // on touch-pad devices, send all touch points to the same item
5878  ? 0
5879  : itemForTouchPointId.constBegin().value();
5880  }
5881 
5882  if (!item) {
5883  // determine which item this touch point will go to
5884  cachedItemsUnderMouse = itemsAtPosition(touchPoint.globalPosition().toPoint(),
5885  touchPoint.scenePosition(),
5886  static_cast<QWidget *>(sceneTouchEvent->target()));
5888  }
5889 
5890  if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchScreen) {
5891  // on touch-screens, combine this touch point with the closest one we find
5892  int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePosition());
5893  QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
5894  if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
5895  item = closestItem;
5896  }
5897  if (!item)
5898  continue;
5899 
5900  itemForTouchPointId.insert(touchPoint.id(), item);
5901  sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
5902  } else if (touchPoint.state() == QEventPoint::State::Released) {
5903  item = itemForTouchPointId.take(touchPoint.id());
5904  if (!item)
5905  continue;
5906 
5907  sceneCurrentTouchPoints.remove(touchPoint.id());
5908  } else {
5909  item = itemForTouchPointId.value(touchPoint.id());
5910  if (!item)
5911  continue;
5912  Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
5913  sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
5914  }
5915 
5916  StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
5917  statesAndTouchPoints.first = QEventPoint::States(statesAndTouchPoints.first | touchPoint.state());
5918  statesAndTouchPoints.second.append(touchPoint);
5919  }
5920 
5921  if (itemsNeedingEvents.isEmpty()) {
5922  sceneTouchEvent->ignore();
5923  return;
5924  }
5925 
5926  bool ignoreSceneTouchEvent = true;
5929  for (; it != end; ++it) {
5930  QGraphicsItem *item = it.key();
5931 
5933 
5934  // determine event type from the state mask
5935  QEvent::Type eventType;
5936  switch (it.value().first) {
5937  case QEventPoint::State::Pressed:
5938  // all touch points have pressed state
5939  eventType = QEvent::TouchBegin;
5940  break;
5941  case QEventPoint::State::Released:
5942  // all touch points have released state
5943  eventType = QEvent::TouchEnd;
5944  break;
5945  case QEventPoint::State::Stationary:
5946  // don't send the event if nothing changed
5947  continue;
5948  default:
5949  // all other combinations
5950  eventType = QEvent::TouchUpdate;
5951  break;
5952  }
5953 
5954  QMutableTouchEvent touchEvent(eventType, sceneTouchEvent->pointingDevice(), sceneTouchEvent->modifiers(), it.value().second);
5955  touchEvent.setTarget(sceneTouchEvent->target());
5956  touchEvent.setModifiers(sceneTouchEvent->modifiers());
5957  touchEvent.setTimestamp(sceneTouchEvent->timestamp());
5958 
5959  switch (touchEvent.type()) {
5960  case QEvent::TouchBegin:
5961  {
5962  // if the TouchBegin handler recurses, we assume that means the event
5963  // has been implicitly accepted and continue to send touch events
5965  bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted();
5966  if (!res) {
5967  // forget about these touch points, we didn't handle them
5968  const auto &unhandledTouchPoints = touchEvent.points();
5969  for (const auto &touchPoint : unhandledTouchPoints) {
5970  itemForTouchPointId.remove(touchPoint.id());
5971  sceneCurrentTouchPoints.remove(touchPoint.id());
5972  }
5973  ignoreSceneTouchEvent = false;
5974  }
5975  break;
5976  }
5977  default:
5981  ignoreSceneTouchEvent = false;
5982  }
5983  break;
5984  }
5985  }
5986  // don't override the acceptance state of the individual points
5987  sceneTouchEvent->QInputEvent::setAccepted(ignoreSceneTouchEvent);
5988 }
5989 
5991 {
5992  Q_Q(QGraphicsScene);
5993 
5994  if (focusOnTouch) {
5996  const QEventPoint &firstTouchPoint = touchEvent->points().first();
5997  cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.globalPosition().toPoint(),
5998  firstTouchPoint.scenePosition(),
5999  static_cast<QWidget *>(touchEvent->target()));
6000  }
6001 
6002  // Set focus on the topmost enabled item that can take focus.
6003  bool setFocus = false;
6004 
6005  for (QGraphicsItem *item : qAsConst(cachedItemsUnderMouse)) {
6007  if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
6008  setFocus = true;
6009  if (item != q->focusItem())
6010  q->setFocusItem(item, Qt::MouseFocusReason);
6011  break;
6012  }
6013  }
6014  if (item->isPanel())
6015  break;
6017  break;
6019  // Make sure we don't clear focus.
6020  setFocus = true;
6021  break;
6022  }
6023  }
6024 
6025  // If nobody could take focus, clear it.
6026  if (!stickyFocus && !setFocus)
6027  q->setFocusItem(nullptr, Qt::MouseFocusReason);
6028  }
6029 
6030  bool res = false;
6031  bool eventAccepted = touchEvent->isAccepted();
6032  for (QGraphicsItem *item : qAsConst(cachedItemsUnderMouse)) {
6033  // first, try to deliver the touch event
6035  bool acceptTouchEvents = item->acceptTouchEvents();
6036  touchEvent->setAccepted(acceptTouchEvents);
6037  res = acceptTouchEvents && sendEvent(item, touchEvent);
6038  eventAccepted = touchEvent->isAccepted();
6039  if (itemForTouchPointId.value(touchEvent->points().first().id()) == 0) {
6040  // item was deleted
6041  item = nullptr;
6042  } else {
6043  item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
6044  }
6045  touchEvent->m_spont = false;
6046  if (res && eventAccepted) {
6047  // the first item to accept the TouchBegin gets an implicit grab.
6048  const auto &touchPoints = touchEvent->points();
6049  for (const auto &touchPoint : touchPoints)
6050  itemForTouchPointId[touchPoint.id()] = item; // can be zero
6051  break;
6052  }
6053  if (item && item->isPanel())
6054  break;
6055  }
6056 
6057  // don't override the acceptance state of the touch points
6058  touchEvent->QInputEvent::setAccepted(eventAccepted);
6059  return res;
6060 }
6061 
6063 {
6064  for (QGraphicsView *view : qAsConst(views))
6065  view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
6066 }
6067 
6069 {
6070  for (auto view : qAsConst(views))
6071  view->d_func()->updateInputMethodSensitivity();
6072 }
6073 
6075 {
6076  Q_Q(QGraphicsScene);
6077  Q_ASSERT(panel && panel->isPanel());
6078 
6079  QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality;
6080  if (previousModality != QGraphicsItem::NonModal) {
6081  // the panel is changing from one modality type to another... temporarily set it back so
6082  // that blockedPanels is populated correctly
6083  panel->d_ptr->panelModality = previousModality;
6084  }
6085 
6086  QSet<QGraphicsItem *> blockedPanels;
6087  {
6088  const auto items_ = q->items();
6089  for (const auto &item : items_) {
6090  if (item->isPanel() && item->isBlockedByModalPanel())
6091  blockedPanels.insert(item);
6092  }
6093  }
6094  // blockedPanels contains all currently blocked panels
6095 
6096  if (previousModality != QGraphicsItem::NonModal) {
6097  // reset the modality to the proper value, since we changed it above
6098  panel->d_ptr->panelModality = panelModality;
6099  // remove this panel so that it will be reinserted at the front of the stack
6101  }
6102 
6104 
6105  if (!hoverItems.isEmpty()) {
6106  // send GraphicsSceneHoverLeave events to newly blocked hoverItems
6107  QGraphicsSceneHoverEvent hoverEvent;
6108  hoverEvent.setScenePos(lastSceneMousePos);
6109  dispatchHoverEvent(&hoverEvent);
6110  }
6111 
6114  if (item->isBlockedByModalPanel())
6115  ungrabMouse(item, /*itemIsDying =*/ false);
6116  }
6117 
6118  QEvent windowBlockedEvent(QEvent::WindowBlocked);
6119  QEvent windowUnblockedEvent(QEvent::WindowUnblocked);
6120  const auto items_ = q->items();
6121  for (const auto &item : items_) {
6122  if (item->isPanel()) {
6123  if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) {
6124  // send QEvent::WindowBlocked to newly blocked panels
6125  sendEvent(item, &windowBlockedEvent);
6126  } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) {
6127  // send QEvent::WindowUnblocked to unblocked panels when downgrading
6128  // a panel from SceneModal to PanelModal
6129  sendEvent(item, &windowUnblockedEvent);
6130  }
6131  }
6132  }
6133 }
6134 
6136 {
6137  Q_Q(QGraphicsScene);
6138  Q_ASSERT(panel && panel->isPanel());
6139 
6140  QSet<QGraphicsItem *> blockedPanels;
6141  {
6142  const auto items_ = q->items();
6143  for (const auto &item : items_) {
6144  if (item->isPanel() && item->isBlockedByModalPanel())
6145  blockedPanels.insert(item);
6146  }
6147  }
6148 
6150 
6151  {
6153  const auto items_ = q->items();
6154  for (const auto &item : items_) {
6155  if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel())
6156  sendEvent(item, &e);
6157  }
6158  }
6159 
6160  // send GraphicsSceneHoverEnter events to newly unblocked items
6161  QGraphicsSceneHoverEvent hoverEvent;
6162  hoverEvent.setScenePos(lastSceneMousePos);
6163  dispatchHoverEvent(&hoverEvent);
6164 }
6165 
6166 #ifndef QT_NO_GESTURES
6168  Qt::GestureFlag flag,
6169  QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
6170  QSet<QGraphicsObject *> *itemsSet,
6171  QSet<QGesture *> *normal,
6172  QSet<QGesture *> *conflicts)
6173 {
6174  QSet<QGesture *> normalGestures; // that are not in conflicted state.
6175  for (QGesture *gesture : gestures) {
6176  if (!gesture->hasHotSpot())
6177  continue;
6178  const Qt::GestureType gestureType = gesture->gestureType();
6179  const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, nullptr);
6180  for (int j = 0; j < items.size(); ++j) {
6181  QGraphicsItem *item = items.at(j);
6182 
6183  // Check if the item is blocked by a modal panel and use it as
6184  // a target instead of this item.
6186 
6187  if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
6188  QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
6190  d->gestureContext.constFind(gestureType);
6191  if (it != d->gestureContext.constEnd() && (!flag || (it.value() & flag))) {
6192  if (normalGestures.contains(gesture)) {
6193  normalGestures.remove(gesture);
6194  if (conflicts)
6195  conflicts->insert(gesture);
6196  } else {
6197  normalGestures.insert(gesture);
6198  }
6199  if (targets)
6200  (*targets)[itemobj].insert(gesture);
6201  if (itemsSet)
6202  (*itemsSet).insert(itemobj);
6203  }
6204  }
6205  // Don't propagate through panels.
6206  if (item->isPanel())
6207  break;
6208  }
6209  }
6210  if (normal)
6211  *normal = normalGestures;
6212 }
6213 
6215 {
6216  QWidget *viewport = event->widget();
6217  if (!viewport)
6218  return;
6219  QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
6220  if (!graphicsView)
6221  return;
6222 
6223  const QList<QGesture *> allGestures = event->gestures();
6224  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6225  << "Gestures:" << allGestures;
6226 
6227  QSet<QGesture *> startedGestures;
6228  QPoint delta = viewport->mapFromGlobal(QPoint());
6229  QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
6230  * graphicsView->viewportTransform().inverted();
6231  for (QGesture *gesture : allGestures) {
6232  // cache scene coordinates of the hot spot
6233  if (gesture->hasHotSpot()) {
6234  gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
6235  } else {
6236  gesture->d_func()->sceneHotSpot = QPointF();
6237  }
6238 
6239  QGraphicsObject *target = gestureTargets.value(gesture, 0);
6240  if (!target) {
6241  // when we are not in started mode but don't have a target
6242  // then the only one interested in gesture is the view/scene
6243  if (gesture->state() == Qt::GestureStarted)
6244  startedGestures.insert(gesture);
6245  }
6246  }
6247 
6248  if (!startedGestures.isEmpty()) {
6249  QSet<QGesture *> normalGestures; // that have just one target
6250  QSet<QGesture *> conflictedGestures; // that have multiple possible targets
6251  gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, nullptr,
6252  &normalGestures, &conflictedGestures);
6255  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6256  << "Normal gestures:" << normalGestures
6257  << "Conflicting gestures:" << conflictedGestures;
6258 
6259  // deliver conflicted gestures as override events AND remember
6260  // initial gesture targets
6261  if (!conflictedGestures.isEmpty()) {
6262  for (int i = 0; i < cachedTargetItems.size(); ++i) {
6264 
6265  // get gestures to deliver to the current item
6266  const QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
6267  if (gestures.isEmpty())
6268  continue;
6269 
6270  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6271  << "delivering override to"
6272  << item.data() << gestures;
6273  // send gesture override
6274  QGestureEvent ev(gestures.values());
6276  ev.setWidget(event->widget());
6277  // mark event and individual gestures as ignored
6278  ev.ignore();
6279  for (QGesture *g : gestures)
6280  ev.setAccepted(g, false);
6281  sendEvent(item.data(), &ev);
6282  // mark all accepted gestures to deliver them as normal gesture events
6283  for (QGesture *g : gestures) {
6284  if (ev.isAccepted() || ev.isAccepted(g)) {
6285  conflictedGestures.remove(g);
6286  // mark the item as a gesture target
6287  if (item) {
6291  e = cachedItemGestures.end();
6292  for(; it != e; ++it)
6293  it.value().remove(g);
6295  }
6296  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6297  << "override was accepted:"
6298  << g << item.data();
6299  }
6300  // remember the first item that received the override event
6301  // as it most likely become a target if no one else accepts
6302  // the override event
6303  if (!gestureTargets.contains(g) && item)
6305 
6306  }
6307  if (conflictedGestures.isEmpty())
6308  break;
6309  }
6310  }
6311  // remember the initial target item for each gesture that was not in
6312  // the conflicted state.
6313  if (!normalGestures.isEmpty()) {
6314  for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
6316 
6317  // get gestures to deliver to the current item
6318  const auto gestures = cachedItemGestures.value(item);
6319  for (QGesture *g : gestures) {
6320  if (!gestureTargets.contains(g)) {
6322  normalGestures.remove(g);
6323  }
6324  }
6325  }
6326  }
6327  }
6328 
6329 
6330  // deliver all gesture events
6331  QSet<QGesture *> undeliveredGestures;
6332  QSet<QGesture *> parentPropagatedGestures;
6333  for (QGesture *gesture : allGestures) {
6334  if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
6335  cachedItemGestures[target].insert(gesture);
6337  undeliveredGestures.insert(gesture);
6338  QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
6339  const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
6341  parentPropagatedGestures.insert(gesture);
6342  } else {
6343  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6344  << "no target for" << gesture << "at"
6345  << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
6346  }
6347  }
6349  for (int i = 0; i < cachedTargetItems.size(); ++i) {
6351  const QSet<QGesture *> gestures = (undeliveredGestures
6352  & cachedItemGestures.value(receiver.data()))
6354 
6355  if (gestures.isEmpty())
6356  continue;
6357 
6358  cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
6359  const bool isPanel = receiver.data()->isPanel();
6360 
6361  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6362  << "delivering to"
6363  << receiver.data() << gestures;
6364  QGestureEvent ev(gestures.values());
6365  ev.setWidget(event->widget());
6366  sendEvent(receiver.data(), &ev);
6367  QSet<QGesture *> ignoredGestures;
6368  for (QGesture *g : gestures) {
6369  if (!ev.isAccepted() && !ev.isAccepted(g)) {
6370  // if the gesture was ignored by its target, we will update the
6371  // targetItems list with a possible target items (items that
6372  // want to receive partial gestures).
6373  // ### won't work if the target was destroyed in the event
6374  // we will just stop delivering it.
6375  if (receiver && receiver.data() == gestureTargets.value(g, 0))
6376  ignoredGestures.insert(g);
6377  } else {
6378  if (receiver && g->state() == Qt::GestureStarted) {
6379  // someone accepted the propagated initial GestureStarted
6380  // event, let it be the new target for all following events.
6381  gestureTargets[g] = receiver.data();
6382  }
6383  undeliveredGestures.remove(g);
6384  }
6385  }
6386  if (undeliveredGestures.isEmpty())
6387  break;
6388 
6389  // ignoredGestures list is only filled when delivering to the gesture
6390  // target item, so it is safe to assume item == target.
6391  if (!ignoredGestures.isEmpty() && !isPanel) {
6392  // look for new potential targets for gestures that were ignored
6393  // and should be propagated.
6394 
6396 
6397  if (receiver) {
6398  // first if the gesture should be propagated to parents only
6399  for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
6400  it != ignoredGestures.end();) {
6401  if (parentPropagatedGestures.contains(*it)) {
6402  QGesture *gesture = *it;
6403  const Qt::GestureType gestureType = gesture->gestureType();
6404  QGraphicsItem *item = receiver.data();
6405  while (item) {
6407  if (item->d_func()->gestureContext.contains(gestureType)) {
6408  targetsSet.insert(obj);
6409  cachedItemGestures[obj].insert(gesture);
6410  }
6411  }
6412  if (item->isPanel())
6413  break;
6414  item = item->parentItem();
6415  }
6416 
6417  it = ignoredGestures.erase(it);
6418  continue;
6419  }
6420  ++it;
6421  }
6422  }
6423 
6425  &cachedItemGestures, &targetsSet, nullptr, nullptr);
6426 
6427  cachedTargetItems = targetsSet.values();
6429  DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
6430  << "new targets:" << cachedTargetItems;
6431  i = -1; // start delivery again
6432  continue;
6433  }
6434  }
6435 
6436  for (QGesture *g : qAsConst(startedGestures)) {
6437  if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
6438  DEBUG() << "lets try to cancel some";
6439  // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
6441  }
6442  }
6443 
6444  // forget about targets for gestures that have ended
6445  for (QGesture *g : allGestures) {
6446  switch (g->state()) {
6447  case Qt::GestureFinished:
6448  case Qt::GestureCanceled:
6450  break;
6451  default:
6452  break;
6453  }
6454  }
6455 
6459 }
6460 
6462 {
6463  Q_ASSERT(original);
6464  QGraphicsItem *originalItem = gestureTargets.value(original);
6465  if (originalItem == nullptr) // we only act on accepted gestures, which implies it has a target.
6466  return;
6467 
6468  // iterate over all active gestures and for each find the owner
6469  // if the owner is part of our sub-hierarchy, cancel it.
6470 
6471  QSet<QGesture *> canceledGestures;
6473  while (iter != gestureTargets.end()) {
6474  QGraphicsObject *item = iter.value();
6475  // note that we don't touch the gestures for our originalItem
6476  if (item != originalItem && originalItem->isAncestorOf(item)) {
6477  DEBUG() << " found a gesture to cancel" << iter.key();
6478  iter.key()->d_func()->state = Qt::GestureCanceled;
6479  canceledGestures << iter.key();
6480  }
6481  ++iter;
6482  }
6483 
6484  // sort them per target item by cherry picking from almostCanceledGestures and delivering
6485  QSet<QGesture *> almostCanceledGestures = canceledGestures;
6487  while (!almostCanceledGestures.isEmpty()) {
6488  QGraphicsObject *target = nullptr;
6489  QSet<QGesture*> gestures;
6490  setIter = almostCanceledGestures.begin();
6491  // sort per target item
6492  while (setIter != almostCanceledGestures.end()) {
6494  if (target == nullptr)
6495  target = item;
6496  if (target == item) {
6497  gestures << *setIter;
6498  setIter = almostCanceledGestures.erase(setIter);
6499  } else {
6500  ++setIter;
6501  }
6502  }
6503  Q_ASSERT(target);
6504 
6505  const QList<QGesture *> list = gestures.values();
6506  QGestureEvent ev(list);
6507  sendEvent(target, &ev);
6508 
6509  if (!ev.isAccepted()) {
6510  for (QGesture *g : list) {
6511 
6512  if (ev.isAccepted(g))
6513  continue;
6514 
6515  if (!g->hasHotSpot())
6516  continue;
6517 
6518  const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, nullptr);
6519  for (const auto &item : items) {
6520  QGraphicsObject *object = item->toGraphicsObject();
6521  if (!object)
6522  continue;
6523  QGraphicsItemPrivate *d = object->QGraphicsItem::d_func();
6524  if (d->gestureContext.contains(g->gestureType())) {
6526  list << g;
6527  QGestureEvent ev(list);
6528  sendEvent(object, &ev);
6529  if (ev.isAccepted() || ev.isAccepted(g))
6530  break; // successfully delivered
6531  }
6532  }
6533  }
6534  }
6535  }
6536 
6538  Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager.
6539  for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
6540  gestureManager->recycle(*setIter);
6541  gestureTargets.remove(*setIter);
6542  }
6543 }
6544 
6546 {
6547  (void)QGestureManager::instance(); // create a gesture manager
6548  if (!grabbedGestures[gesture]++) {
6549  for (QGraphicsView *view : qAsConst(views))
6550  view->viewport()->grabGesture(gesture);
6551  }
6552 }
6553 
6555 {
6556  // we know this can only be an object
6558  QGraphicsObject *obj = static_cast<QGraphicsObject *>(item);
6560  if (!--grabbedGestures[gesture]) {
6561  for (QGraphicsView *view : qAsConst(views))
6562  view->viewport()->ungrabGesture(gesture);
6563  }
6564 }
6565 #endif // QT_NO_GESTURES
6566 
6568 
6569 #include "moc_qgraphicsscene.cpp"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Arabic default style
Definition: afstyles.h:94
#define value
[5]
static QStyle * style()
static QFont font()
bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
QGestureManager * gestureManager
static QApplicationPrivate * instance()
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:66
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
static QColor fromHsv(int h, int s, int v, int a=255)
Definition: qcolor.cpp:2496
static bool sendEvent(QObject *receiver, QEvent *event)
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static QPoint pos()
Definition: qcursor.cpp:224
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
virtual void setAccepted(bool accepted)
Definition: qcoreevent.h:310
bool spontaneous() const
Definition: qcoreevent.h:308
@ GraphicsSceneDragLeave
Definition: qcoreevent.h:213
@ GraphicsSceneMouseMove
Definition: qcoreevent.h:202
@ ApplicationPaletteChange
Definition: qcoreevent.h:106
@ Gesture
Definition: qcoreevent.h:266
@ GestureOverride
Definition: qcoreevent.h:267
@ GraphicsSceneContextMenu
Definition: qcoreevent.h:206
@ GraphicsSceneMouseRelease
Definition: qcoreevent.h:204
@ WindowBlocked
Definition: qcoreevent.h:154
@ WindowUnblocked
Definition: qcoreevent.h:155
@ GraphicsSceneDragEnter
Definition: qcoreevent.h:211
@ GraphicsSceneDragMove
Definition: qcoreevent.h:212
@ ShortcutOverride
Definition: qcoreevent.h:171
@ FocusOut
Definition: qcoreevent.h:80
@ InputMethod
Definition: qcoreevent.h:133
@ GraphicsSceneMousePress
Definition: qcoreevent.h:203
@ StyleChange
Definition: qcoreevent.h:149
@ UngrabMouse
Definition: qcoreevent.h:247
@ FontChange
Definition: qcoreevent.h:146
@ KeyRelease
Definition: qcoreevent.h:78
@ Leave
Definition: qcoreevent.h:83
@ KeyPress
Definition: qcoreevent.h:77
@ StyleAnimationUpdate
Definition: qcoreevent.h:285
@ FocusIn
Definition: qcoreevent.h:79
@ ActivationChange
Definition: qcoreevent.h:148
@ TouchEnd
Definition: qcoreevent.h:256
@ TouchUpdate
Definition: qcoreevent.h:255
@ TouchBegin
Definition: qcoreevent.h:254
@ GraphicsSceneHoverLeave
Definition: qcoreevent.h:209
@ WindowActivate
Definition: qcoreevent.h:96
@ GraphicsSceneMouseDoubleClick
Definition: qcoreevent.h:205
@ GraphicsSceneWheel
Definition: qcoreevent.h:215
@ GraphicsSceneDrop
Definition: qcoreevent.h:214
@ PaletteChange
Definition: qcoreevent.h:107
@ GraphicsSceneHoverEnter
Definition: qcoreevent.h:207
@ UngrabKeyboard
Definition: qcoreevent.h:249
@ GraphicsSceneHoverMove
Definition: qcoreevent.h:208
@ ApplicationFontChange
Definition: qcoreevent.h:104
@ GraphicsSceneHelp
Definition: qcoreevent.h:210
@ GrabKeyboard
Definition: qcoreevent.h:248
@ Polish
Definition: qcoreevent.h:124
@ WindowDeactivate
Definition: qcoreevent.h:97
@ GrabMouse
Definition: qcoreevent.h:246
@ GraphicsSceneLeave
Definition: qcoreevent.h:216
Type type() const
Definition: qcoreevent.h:307
void ignore()
Definition: qcoreevent.h:314
bool isAccepted() const
Definition: qcoreevent.h:311
quint16 t
Definition: qcoreevent.h:331
void accept()
Definition: qcoreevent.h:313
The QEventPoint class provides information about a point in a QPointerEvent.
Definition: qeventpoint.h:56
The QFocusEvent class contains event parameters for widget focus events. \inmodule QtGui.
Definition: qevent.h:520
Qt::FocusReason reason() const
Definition: qevent.cpp:1608
The QFont class specifies a query for a font used for drawing text.
Definition: qfont.h:56
QFont resolve(const QFont &) const
Definition: qfont.cpp:1874
void setResolveMask(uint mask)
Definition: qfont.h:275
uint resolveMask() const
Definition: qfont.h:274
The QGestureEvent class provides the description of triggered gestures.
Definition: qgesture.h:276
void setWidget(QWidget *widget)
Definition: qgesture.cpp:1059
bool isAccepted(QGesture *) const
Definition: qgesture.cpp:991
void ignore(QGesture *)
Definition: qgesture.cpp:982
void setAccepted(QGesture *, bool)
Definition: qgesture.cpp:952
The QGesture class represents a gesture, containing properties that describe the corresponding user i...
Definition: qgesture.h:62
@ CancelAllInContext
Definition: qgesture.h:88
Qt::GestureType gestureType
the type of the gesture
Definition: qgesture.h:67
void recycle(QGesture *gesture)
bool filterEvent(QWidget *receiver, QEvent *event)
static QGestureManager * instance(InstanceCreation ic=ForceCreation)
void cleanupCachedGestures(QObject *target, Qt::GestureType type)
QGraphicsEffectSource * source() const
virtual void draw(QPainter *painter)=0
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.
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:83
virtual bool contains(const QPointF &point) const
QTransform deviceTransform(const QTransform &viewportTransform) const
bool isWidget() const
void setSelected(bool selected)
bool acceptDrops() const
QScopedPointer< QGraphicsItemPrivate > d_ptr
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value)
qreal boundingRegionGranularity() const
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr)=0
bool isWindow() const
QGraphicsScene * scene() const
bool isSelected() const
virtual bool collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
virtual QPainterPath shape() const
@ ItemClipsChildrenToShape
Definition: qgraphicsitem.h:90
@ ItemContainsChildrenInShape
@ ItemSendsScenePositionChanges
@ ItemIgnoresParentOpacity
Definition: qgraphicsitem.h:92
@ ItemStopsClickFocusPropagation
QGraphicsWidget * window() const
QRectF sceneBoundingRect() const
virtual QRectF boundingRect() const =0
bool isEnabled() const
bool isBlockedByModalPanel(QGraphicsItem **blockingPanel=nullptr) const
QGraphicsObject * toGraphicsObject()
virtual void advance(int phase)
void setParentItem(QGraphicsItem *parent)
Qt::MouseButtons acceptedMouseButtons() const
QVariant data(int key) const
bool isPanel() const
QGraphicsItem * panel() const
QGraphicsItem * parentItem() const
QTransform sceneTransform() const
QGraphicsItem * commonAncestorItem(const QGraphicsItem *other) const
bool isVisible() const
QGraphicsItem * focusItem() const
PanelModality panelModality() const
void setFocus(Qt::FocusReason focusReason=Qt::OtherFocusReason)
GraphicsItemFlags flags() const
virtual bool sceneEvent(QEvent *event)
bool acceptTouchEvents() const
bool isAncestorOf(const QGraphicsItem *child) const
bool isOpacityNull() const
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
quint32 sceneTransformTranslateOnly
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 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
void setDropAction(Qt::DropAction action)
void setScreenPos(const QPoint &pos)
void setPos(const QPointF &pos)
void setScenePos(const QPointF &pos)
The QGraphicsSceneEvent class provides a base class for all graphics view related events.
void setWidget(QWidget *widget)
QWidget * widget() const
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)
void setScenePos(const QPointF &pos)
void setModifiers(Qt::KeyboardModifiers modifiers)
void setLastScenePos(const QPointF &pos)
void setLastScreenPos(const QPoint &pos)
Qt::KeyboardModifiers modifiers() const
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
void removeItem(QGraphicsItem *item)
void setFont(const QFont &font)
bool hasFocus() const
void addItem(QGraphicsItem *item)
virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
void changed(const QList< QRectF > &region)
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
QGraphicsProxyWidget * addWidget(QWidget *widget, Qt::WindowFlags wFlags=Qt::WindowFlags())
void destroyItemGroup(QGraphicsItemGroup *group)
virtual void helpEvent(QGraphicsSceneHelpEvent *event)
void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason=Qt::OtherFocusReason)
bool stickyFocus
whether clicking into the scene background will clear focus
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
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)
void setFocusOnTouch(bool enabled)
bool isActive() const
QGraphicsPathItem * addPath(const QPainterPath &path, const QPen &pen=QPen(), const QBrush &brush=QBrush())
virtual void wheelEvent(QGraphicsSceneWheelEvent *event)
void setBspTreeDepth(int depth)
QGraphicsEllipseItem * addEllipse(const QRectF &rect, const QPen &pen=QPen(), const QBrush &brush=QBrush())
void setStickyFocus(bool enabled)
virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
void setActivePanel(QGraphicsItem *item)
virtual void focusInEvent(QFocusEvent *event)
QList< QGraphicsItem * > selectedItems() const
QGraphicsScene(QObject *parent=nullptr)
bool eventFilter(QObject *watched, QEvent *event) override
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
QRectF sceneRect
the scene rectangle; the bounding rectangle of the scene
virtual void drawBackground(QPainter *painter, const QRectF &rect)
void setForegroundBrush(const QBrush &brush)
void setStyle(QStyle *style)
QGraphicsItem * activePanel() const
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
QBrush foregroundBrush
the foreground brush of the scene.
int bspTreeDepth
the depth of QGraphicsScene's BSP index tree
void invalidate(qreal x, qreal y, qreal w, qreal h, SceneLayers layers=AllLayers)
void setPalette(const QPalette &palette)
virtual ~QGraphicsScene()
QList< QGraphicsView * > views() const
QRectF itemsBoundingRect() const
void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
ItemIndexMethod itemIndexMethod
the item indexing method.
void update(qreal x, qreal y, qreal w, qreal h)
QGraphicsPixmapItem * addPixmap(const QPixmap &pixmap)
QGraphicsPolygonItem * addPolygon(const QPolygonF &polygon, const QPen &pen=QPen(), const QBrush &brush=QBrush())
void setItemIndexMethod(ItemIndexMethod method)
void selectionChanged()
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
void setSceneRect(const QRectF &rect)
QGraphicsRectItem * addRect(const QRectF &rect, const QPen &pen=QPen(), const QBrush &brush=QBrush())
void sceneRectChanged(const QRectF &rect)
QBrush backgroundBrush
the background brush of the scene.
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
virtual bool focusNextPrevChild(bool next)
bool focusOnTouch
whether items gain focus when receiving a {touch begin} event.
virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
QPalette palette
the scene's default palette
void setActiveWindow(QGraphicsWidget *widget)
QList< QGraphicsItem * > collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
QPainterPath selectionArea() const
QFont font
the scene's default font
QGraphicsItemGroup * createItemGroup(const QList< QGraphicsItem * > &items)
QGraphicsWidget * activeWindow() const
virtual void keyPressEvent(QKeyEvent *event)
QGraphicsLineItem * addLine(const QLineF &line, const QPen &pen=QPen())
friend class QGraphicsSceneBspTreeIndex
virtual void inputMethodEvent(QInputMethodEvent *event)
void setBackgroundBrush(const QBrush &brush)
virtual void focusOutEvent(QFocusEvent *event)
QGraphicsTextItem * addText(const QString &text, const QFont &font=QFont())
virtual void keyReleaseEvent(QKeyEvent *event)
void setMinimumRenderSize(qreal minSize)
void setFocus(Qt::FocusReason focusReason=Qt::OtherFocusReason)
QGraphicsItem * focusItem() const
bool event(QEvent *event) override
void render(QPainter *painter, const QRectF &target=QRectF(), const QRectF &source=QRectF(), Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio)
QGraphicsSimpleTextItem * addSimpleText(const QString &text, const QFont &font=QFont())
QGraphicsItem * mouseGrabberItem() const
virtual void drawForeground(QPainter *painter, const QRectF &rect)
QGraphicsItem * itemAt(const QPointF &pos, const QTransform &deviceTransform) 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
void setButtonDownPos(Qt::MouseButton button, const QPointF &pos)
QPointF buttonDownScenePos(Qt::MouseButton button) const
QPoint buttonDownScreenPos(Qt::MouseButton button) const
void setLastPos(const QPointF &pos)
Qt::KeyboardModifiers modifiers() const
void setPos(const QPointF &pos)
Qt::MouseButtons buttons() const
void setButtonDownScenePos(Qt::MouseButton button, const QPointF &pos)
void setButtonDownScreenPos(Qt::MouseButton button, const QPoint &pos)
QPointF buttonDownPos(Qt::MouseButton button) const
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
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)
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
void updateInputMethodSensitivityInViews()
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 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...
The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene.
Definition: qgraphicsview.h:60
bool isTransformed() const
QTransform viewportTransform() const
bool updateRect(const QRect &rect)
QGraphicsView::ViewportUpdateMode viewportUpdateMode
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
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
virtual void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr)
bool autoFillBackground
whether the widget background is filled automatically
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
QPalette palette
the widget's palette
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
QGraphicsWidget * focusNext
static QPalette palette()
static QInputMethod * inputMethod()
The QHash::const_iterator class provides an STL-style const iterator for QHash.
Definition: qhash.h:1088
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qhash.h:773
bool remove(const Key &key)
Definition: qhash.h:911
iterator begin()
Definition: qhash.h:1155
const_iterator constEnd() const noexcept
Definition: qhash.h:1162
const_iterator constBegin() const noexcept
Definition: qhash.h:1158
QList< Key > keys() const
Definition: qhash.h:1029
iterator erase(const_iterator it)
Definition: qhash.h:1172
bool contains(const Key &key) const noexcept
Definition: qhash.h:944
T value(const Key &key) const noexcept
Definition: qhash.h:997
iterator end() noexcept
Definition: qhash.h:1159
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Definition: qhash.h:904
bool isEmpty() const noexcept
Definition: qhash.h:881
iterator insert(const Key &key, const T &value)
Definition: qhash.h:1228
DeviceType type
Definition: qinputdevice.h:57
quint64 timestamp() const
Definition: qevent.h:87
Qt::KeyboardModifiers modifiers() const
Definition: qevent.h:85
The QInputMethodEvent class provides parameters for input method events. \inmodule QtGui.
Definition: qevent.h:696
The QKeyEvent class describes a key event.
Definition: qevent.h:471
Qt::KeyboardModifiers modifiers() const
Definition: qevent.cpp:1502
int key() const
Definition: qevent.h:484
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:215
qreal length() const
Definition: qline.cpp:569
qsizetype size() const noexcept
Definition: qlist.h:414
bool isEmpty() const noexcept
Definition: qlist.h:418
void removeAt(qsizetype i)
Definition: qlist.h:588
bool removeOne(const AT &t)
Definition: qlist.h:596
const T & constFirst() const noexcept
Definition: qlist.h:645
iterator end()
Definition: qlist.h:624
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
T value(qsizetype i) const
Definition: qlist.h:676
const_reverse_iterator crbegin() const noexcept
Definition: qlist.h:636
const_iterator constBegin() const noexcept
Definition: qlist.h:630
void remove(qsizetype i, qsizetype n=1)
Definition: qlist.h:798
value_type takeLast()
Definition: qlist.h:565
qsizetype removeAll(const AT &t)
Definition: qlist.h:590
qsizetype count() const noexcept
Definition: qlist.h:415
void squeeze()
Definition: qlist.h:778
void prepend(rvalue_ref t)
Definition: qlist.h:484
iterator begin()
Definition: qlist.h:623
void reserve(qsizetype size)
Definition: qlist.h:757
const T & constLast() const noexcept
Definition: qlist.h:648
T & first()
Definition: qlist.h:643
void append(parameter_type t)
Definition: qlist.h:469
const_iterator constEnd() const noexcept
Definition: qlist.h:631
void clear()
Definition: qlist.h:445
const_reverse_iterator crend() const noexcept
Definition: qlist.h:637
Definition: qmap.h:222
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:392
iterator erase(const_iterator it)
Definition: qmap.h:650
bool contains(const Key &key) const
Definition: qmap.h:376
T & first()
Definition: qmap.h:454
size_type remove(const Key &key)
Definition: qmap.h:335
bool isEmpty() const
Definition: qmap.h:304
iterator begin()
Definition: qmap.h:633
iterator end()
Definition: qmap.h:637
const_iterator constBegin() const
Definition: qmap.h:635
const_iterator constEnd() const
Definition: qmap.h:639
T take(const Key &key)
Definition: qmap.h:357
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:54
iterator lowerBound(const Key &key)
Definition: qmap.h:1425
bool contains(const Key &key) const
Definition: qmap.h:1050
iterator end()
Definition: qmap.h:1332
iterator insert(const Key &key, const T &value)
Definition: qmap.h:1453
iterator erase(const_iterator it)
Definition: qmap.h:1345
iterator upperBound(const Key &key)
Definition: qmap.h:1439
iterator begin()
Definition: qmap.h:1328
QObject * q_ptr
Definition: qobject.h:98
QObjectList children
Definition: qobject.h:100
QObject * parent
Definition: qobject.h:99
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
QObject * parent() const
Definition: qobject.h:409
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
QScopedPointer< QObjectData > d_ptr
Definition: qobject.h:436
bool isSignalConnected(uint signalIdx, bool checkDeclarative=true) const
Definition: qobject.cpp:460
int signalIndex(const char *signalName, const QMetaObject **meta=nullptr) const
Definition: qobject.cpp:4018
qreal devicePixelRatio() const
Definition: qpaintdevice.h:85
virtual int devType() const
Definition: qpaintdevice.h:113
int width() const
Definition: qpaintdevice.h:77
int height() const
Definition: qpaintdevice.h:78
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:82
const QPen & pen() const
Definition: qpainter.cpp:3736
Qt::LayoutDirection layoutDirection() const
Definition: qpainter.cpp:7367
RenderHints renderHints() const
Definition: qpainter.cpp:6897
void drawRect(const QRectF &rect)
Definition: qpainter.h:554
QPaintDevice * device() const
Definition: qpainter.cpp:1529
qreal opacity() const
Definition: qpainter.cpp:2044
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Definition: qpainter.cpp:2717
void setPen(const QColor &color)
Definition: qpainter.cpp:3640
bool begin(QPaintDevice *)
Definition: qpainter.cpp:1709
void setBrushOrigin(int x, int y)
Definition: qpainter.h:733
void setClipPath(const QPainterPath &path, Qt::ClipOperation op=Qt::ReplaceClip)
Definition: qpainter.cpp:3038
void setLayoutDirection(Qt::LayoutDirection direction)
Definition: qpainter.cpp:7355
void restore()
Definition: qpainter.cpp:1611
const QTransform & worldTransform() const
Definition: qpainter.cpp:7967
const QBrush & brush() const
Definition: qpainter.cpp:3813
void setOpacity(qreal opacity)
Definition: qpainter.cpp:2065
void setCompositionMode(CompositionMode mode)
Definition: qpainter.cpp:2353
void save()
Definition: qpainter.cpp:1577
void setWorldTransform(const QTransform &matrix, bool combine=false)
Definition: qpainter.cpp:7945
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Definition: qpainter.cpp:4883
void setBrush(const QBrush &brush)
Definition: qpainter.cpp:3755
bool end()
Definition: qpainter.cpp:1877
@ CompositionMode_Source
Definition: qpainter.h:136
void translate(const QPointF &offset)
Definition: qpainter.cpp:2993
void setRenderHints(RenderHints hints, bool on=true)
Definition: qpainter.cpp:6871
void fillRect(const QRectF &, const QBrush &)
Definition: qpainter.cpp:6644
void setClipRegion(const QRegion &, Qt::ClipOperation op=Qt::ReplaceClip)
Definition: qpainter.cpp:2826
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:65
The QPalette class contains color groups for each widget state.
Definition: qpalette.h:55
void setResolveMask(ResolveMask mask)
Definition: qpalette.cpp:964
ResolveMask resolveMask() const
Definition: qpalette.cpp:956
QPalette resolve(const QPalette &other) const
Definition: qpalette.cpp:928
const QBrush & window() const
Definition: qpalette.h:127
static bool pathToRect(const QPainterPath &path, QRectF *rect=nullptr)
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:61
The QPixmapCache::Key class can be used for efficient access to the QPixmapCache. \inmodule QtGui.
Definition: qpixmapcache.h:54
static bool find(const QString &key, QPixmap *pixmap)
static void remove(const QString &key)
static bool insert(const QString &key, const QPixmap &pixmap)
The QPixmap class is an off-screen image representation that can be used as a paint device.
Definition: qpixmap.h:63
QSize size() const
Definition: qpixmap.cpp:528
bool isNull() const
Definition: qpixmap.cpp:491
void setDevicePixelRatio(qreal scaleFactor)
Definition: qpixmap.cpp:639
QRect rect() const
Definition: qpixmap.cpp:540
void fill(const QColor &fillColor=Qt::white)
Definition: qpixmap.cpp:883
qreal devicePixelRatio() const
Definition: qpixmap.cpp:611
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:242
constexpr QPoint toPoint() const
Definition: qpoint.h:420
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
constexpr int x() const noexcept
Definition: qpoint.h:155
constexpr int y() const noexcept
Definition: qpoint.h:160
const QPointingDevice * pointingDevice() const
Definition: qevent.cpp:354
const QList< QEventPoint > & points() const
Definition: qevent.h:118
The QPointer class is a template class that provides guarded pointers to QObject.
Definition: qpointer.h:54
T * data() const
Definition: qpointer.h:76
The QPolygonF class provides a list of points using floating point precision. \inmodule QtGui.
Definition: qpolygon.h:128
The QRectF class defines a finite rectangle in the plane using floating point precision.
Definition: qrect.h:511
constexpr bool isEmpty() const noexcept
Definition: qrect.h:670
QRect toAlignedRect() const noexcept
Definition: qrect.cpp:2351
constexpr qreal height() const noexcept
Definition: qrect.h:741
constexpr qreal width() const noexcept
Definition: qrect.h:738
constexpr QRectF translated(qreal dx, qreal dy) const noexcept
Definition: qrect.h:771
constexpr QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Definition: qrect.h:822
constexpr qreal left() const noexcept
Definition: qrect.h:524
constexpr bool isNull() const noexcept
Definition: qrect.h:667
constexpr QRect toRect() const noexcept
Definition: qrect.h:866
constexpr qreal top() const noexcept
Definition: qrect.h:525
constexpr void setRect(qreal x, qreal y, qreal w, qreal h) noexcept
Definition: qrect.h:790
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
constexpr bool isEmpty() const noexcept
Definition: qrect.h:194
bool intersects(const QRect &r) const noexcept
Definition: qrect.cpp:1101
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Definition: qrect.h:400
constexpr int height() const noexcept
Definition: qrect.h:266
QRect normalized() const noexcept
Definition: qrect.cpp:309
constexpr bool isNull() const noexcept
Definition: qrect.h:191
constexpr QPoint topLeft() const noexcept
Definition: qrect.h:248
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Definition: qrect.h:397
constexpr int top() const noexcept
Definition: qrect.h:203
bool contains(const QRect &r, bool proper=false) const noexcept
Definition: qrect.cpp:887
constexpr int left() const noexcept
Definition: qrect.h:200
constexpr int x() const noexcept
Definition: qrect.h:212
constexpr QSize size() const noexcept
Definition: qrect.h:269
constexpr void translate(int dx, int dy) noexcept
Definition: qrect.h:272
constexpr int width() const noexcept
Definition: qrect.h:263
constexpr int y() const noexcept
Definition: qrect.h:215
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:63
QRect boundingRect() const noexcept
int rectCount() const noexcept
bool intersects(const QRegion &r) const
Definition: qregion.cpp:649
bool isEmpty() const
T * data() const noexcept
qsizetype size() const
Definition: qset.h:86
QList< T > values() const
Definition: qset.h:333
bool remove(const T &value)
Definition: qset.h:99
iterator begin()
Definition: qset.h:172
iterator end()
Definition: qset.h:176
bool isEmpty() const
Definition: qset.h:88
iterator erase(const_iterator i)
Definition: qset.h:181
bool contains(const T &value) const
Definition: qset.h:107
iterator insert(const T &value)
Definition: qset.h:191
The QSizeF class defines the size of a two-dimensional object using floating point precision.
Definition: qsize.h:235
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
constexpr int height() const noexcept
Definition: qsize.h:160
constexpr int width() const noexcept
Definition: qsize.h:157
constexpr bool isEmpty() const noexcept
Definition: qsize.h:151
constexpr bool isValid() const noexcept
Definition: qsize.h:154
The QString class provides a Unicode character string.
Definition: qstring.h:388
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition: qstyle.h:65
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem.
Definition: qstyleoption.h:684
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)
Definition: qtooltip.cpp:459
static void hideText()
Definition: qtooltip.h:55
The QTouchEvent class contains parameters that describe a touch event.
Definition: qevent.h:1020
QObject * target() const
Definition: qevent.h:1041
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:56
QTransform & scale(qreal sx, qreal sy)
Definition: qtransform.cpp:460
qreal dx() const
Definition: qtransform.h:262
QPoint map(const QPoint &p) const
static QTransform fromTranslate(qreal dx, qreal dy)
Definition: qtransform.cpp:437
QTransform inverted(bool *invertible=nullptr) const
Definition: qtransform.cpp:339
TransformationType type() const
QTransform & translate(qreal dx, qreal dy)
Definition: qtransform.cpp:392
QRect mapRect(const QRect &) const
TransformationType
Definition: qtransform.h:58
qreal dy() const
Definition: qtransform.h:266
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
QSize toSize() const
Definition: qvariant.cpp:1560
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
bool isVisibleTo(const QWidget *) const
Definition: qwidget.cpp:8549
QWidget * focusWidget() const
Definition: qwidget.cpp:6810
QRect rect
the internal geometry of the widget excluding any window frame
Definition: qwidget.h:150
void setFocus()
Definition: qwidget.h:454
bool isEnabled() const
Definition: qwidget.h:847
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
Definition: qwidget.h:174
QWidget * parentWidget() const
Definition: qwidget.h:937
bool isWindow() const
Definition: qwidget.h:844
bool isVisible() const
Definition: qwidget.h:907
QPointF mapFromGlobal(const QPointF &) const
bool testAttribute(Qt::WidgetAttribute) const
Definition: qwidget.h:943
QOpenGLWidget * widget
[1]
QString text
[meta data]
QPushButton * button
[2]
double e
rect
[4]
QPixmap pix
palette
#define true
Definition: ftrandom.c:51
backing_store_ptr info
[4]
Definition: jmemsys.h:161
short next
Definition: keywords.cpp:454
typename C::iterator iterator
QHighDpiScaling::Point position(T, QHighDpiScaling::Point::Kind)
void mousePress(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:159
QTouchEventSequence touchEvent(QWindow *window, QPointingDevice *device, bool autoCommit=true)
Definition: qtesttouch.h:78
Definition: qnamespace.h:55
InputMethodQuery
Definition: qnamespace.h:1380
MouseButton
Definition: qnamespace.h:81
@ WA_AcceptTouchEvents
Definition: qnamespace.h:429
@ WA_SetStyle
Definition: qnamespace.h:381
@ IntersectClip
Definition: qnamespace.h:1333
LayoutDirection
Definition: qnamespace.h:1462
AspectRatioMode
Definition: qnamespace.h:1211
@ KeepAspectRatioByExpanding
Definition: qnamespace.h:1214
@ KeepAspectRatio
Definition: qnamespace.h:1213
@ IgnoreAspectRatio
Definition: qnamespace.h:1212
@ GestureCanceled
Definition: qnamespace.h:1637
@ GestureStarted
Definition: qnamespace.h:1634
@ GestureFinished
Definition: qnamespace.h:1636
@ WheelFocus
Definition: qnamespace.h:136
@ ClickFocus
Definition: qnamespace.h:134
@ TabFocus
Definition: qnamespace.h:133
ItemSelectionOperation
Definition: qnamespace.h:1344
@ ReplaceSelection
Definition: qnamespace.h:1345
@ transparent
Definition: qnamespace.h:78
@ Key_Tab
Definition: qnamespace.h:685
@ Key_Backtab
Definition: qnamespace.h:686
SortOrder
Definition: qnamespace.h:146
@ DescendingOrder
Definition: qnamespace.h:148
@ AscendingOrder
Definition: qnamespace.h:147
@ ShiftModifier
Definition: qnamespace.h:1075
@ ControlModifier
Definition: qnamespace.h:1076
@ AltModifier
Definition: qnamespace.h:1077
ItemSelectionMode
Definition: qnamespace.h:1337
@ IntersectsItemShape
Definition: qnamespace.h:1339
@ IntersectsItemBoundingRect
Definition: qnamespace.h:1341
@ NoBrush
Definition: qnamespace.h:1140
@ IgnoreAction
Definition: qnamespace.h:1490
@ QueuedConnection
Definition: qnamespace.h:1307
@ DeviceCoordinates
Definition: qnamespace.h:1616
@ LogicalCoordinates
Definition: qnamespace.h:1617
GestureType
Definition: qnamespace.h:1641
GestureFlag
Definition: qnamespace.h:1654
@ ReceivePartialGestures
Definition: qnamespace.h:1656
@ IgnoredGesturesPropagateToParent
Definition: qnamespace.h:1657
constexpr Initialization Uninitialized
Definition: qnamespace.h:1613
@ FramelessWindowHint
Definition: qnamespace.h:250
@ ToolTip
Definition: qnamespace.h:238
@ Popup
Definition: qnamespace.h:236
FocusReason
Definition: qnamespace.h:1360
@ PopupFocusReason
Definition: qnamespace.h:1365
@ BacktabFocusReason
Definition: qnamespace.h:1363
@ MouseFocusReason
Definition: qnamespace.h:1361
@ OtherFocusReason
Definition: qnamespace.h:1368
@ ActiveWindowFocusReason
Definition: qnamespace.h:1364
@ TabFocusReason
Definition: qnamespace.h:1362
Definition: brush.cpp:52
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
void
Definition: png.h:1080
std::pair< T1, T2 > QPair
Definition: qcontainerfwd.h:56
#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 * 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
const EGLAttrib EGLOutputLayerEXT * layers
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition: qfloat16.h:249
unsigned int quint32
Definition: qglobal.h:288
size_t quintptr
Definition: qglobal.h:310
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
#define ENSURE_TRANSFORM_PTR
#define DEBUG
@ text
#define qWarning
Definition: qlogging.h:179
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLenum type
Definition: qopengl.h:270
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum mode
GLboolean r
[2]
GLint GLsizei GLsizei height
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei GLsizei GLfloat distance
GLint GLsizei width
GLuint color
[2]
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
Definition: qopenglext.h:2998
GLuint GLenum GLenum transform
Definition: qopenglext.h:11564
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
GLenum query
Definition: qopenglext.h:2738
GLuint res
Definition: qopenglext.h:8867
GLuint GLenum matrix
Definition: qopenglext.h:11564
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLsizei const GLchar *const * path
Definition: qopenglext.h:4283
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLuint GLenum option
Definition: qopenglext.h:5929
GLfixed GLfixed GLint GLint order
Definition: qopenglext.h:5206
GLenum GLenum GLenum GLenum GLenum scale
Definition: qopenglext.h:10817
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
#define emit
Definition: qtmetamacros.h:85
#define enabled
Definition: qopenglext.h:3098
#define disabled
Q_UNUSED(salary)
[21]
QWidget * panel
Definition: settings.cpp:54
QFileInfo fi("c:/temp/foo")
[newstuff]
obj metaObject() -> className()
QObject::connect nullptr
QGraphicsItem * item
QTransform xform
[18]
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]
QStringList::Iterator it
QStringList list
[0]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition: qlist.h:966
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
qsizetype lastIndexOf(const AT &t, qsizetype from=-1) const noexcept
Definition: qlist.h:973
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())
QThreadStorage< int * > dummy[8]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent