Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgraphicsitem.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
755#include "qgraphicsitem.h"
756
757#include "qgraphicsscene.h"
758#include "qgraphicsscene_p.h"
759#include "qgraphicssceneevent.h"
760#include "qgraphicsview.h"
761#include "qgraphicswidget.h"
762#include "qgraphicsproxywidget.h"
764#include <QtCore/qbitarray.h>
765#include <QtCore/qpoint.h>
766#include <QtCore/qstack.h>
767#include <QtCore/qtimer.h>
768#include <QtCore/qvariant.h>
769#include <QtCore/qvarlengtharray.h>
770#include <QtCore/qnumeric.h>
771#include <QtWidgets/qapplication.h>
772#include <QtGui/qbitmap.h>
773#include <QtGui/qpainter.h>
774#include <QtGui/qpainterpath.h>
775#include <QtGui/qpixmapcache.h>
776#include <QtWidgets/qstyleoption.h>
777#include <QtGui/qevent.h>
778#include <QtGui/qinputmethod.h>
779#if QT_CONFIG(graphicseffect)
780#include <QtWidgets/qgraphicseffect.h>
781#endif
782
783#include <private/qgraphicsitem_p.h>
784#include <private/qgraphicswidget_p.h>
785#include <private/qwidgettextcontrol_p.h>
786#include <private/qtextdocumentlayout_p.h>
787#include <private/qtextengine_p.h>
788#include <private/qwidget_p.h>
789#include <private/qapplication_p.h>
790#include <private/qgesturemanager_p.h>
791#include <private/qdebug_p.h>
792
794
796
797static inline void _q_adjustRect(QRect *rect)
798{
799 Q_ASSERT(rect);
800 if (!rect->width())
801 rect->adjust(0, 0, 1, 0);
802 if (!rect->height())
803 rect->adjust(0, 0, 0, 1);
804}
805
806/*
807 ### Move this into QGraphicsItemPrivate
808 */
810{
811public:
812 QHash<const QGraphicsItem *, QMap<int, QVariant> > data;
813};
815
816
823{
824 // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
825 // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
826 const qreal penWidthZero = qreal(0.00000001);
827
828 if (path == QPainterPath() || pen == Qt::NoPen)
829 return path;
831 ps.setCapStyle(pen.capStyle());
832 if (pen.widthF() <= 0.0)
833 ps.setWidth(penWidthZero);
834 else
835 ps.setWidth(pen.widthF());
836 ps.setJoinStyle(pen.joinStyle());
837 ps.setMiterLimit(pen.miterLimit());
839 p.addPath(path);
840 return p;
841}
842
847 : z(0),
848 opacity(1.),
849 scene(nullptr),
850 parent(nullptr),
851 transformData(nullptr),
852 graphicsEffect(nullptr),
853 index(-1),
854 siblingIndex(-1),
855 itemDepth(-1),
856 focusProxy(nullptr),
857 subFocusItem(nullptr),
858 focusScopeItem(nullptr),
859 imHints(Qt::ImhNone),
860 panelModality(QGraphicsItem::NonModal),
861 acceptedMouseButtons(0x1f),
862 visible(true),
863 explicitlyHidden(false),
864 enabled(true),
865 explicitlyDisabled(false),
866 selected(false),
867 acceptsHover(false),
868 acceptDrops(false),
869 isMemberOfGroup(false),
870 handlesChildEvents(false),
871 itemDiscovered(false),
872 hasCursor(false),
873 ancestorFlags(0),
874 cacheMode(0),
875 hasBoundingRegionGranularity(false),
876 isWidget(false),
877 dirty(false),
878 dirtyChildren(false),
879 localCollisionHack(false),
880 inSetPosHelper(false),
881 needSortChildren(false),
882 allChildrenDirty(false),
883 fullUpdatePending(false),
884 flags(0),
885 paintedViewBoundingRectsNeedRepaint(false),
886 dirtySceneTransform(true),
887 geometryChanged(true),
888 inDestructor(false),
889 isObject(false),
890 ignoreVisible(false),
891 ignoreOpacity(false),
892 acceptTouchEvents(false),
893 acceptedTouchBeginEvent(false),
894 filtersDescendantEvents(false),
895 sceneTransformTranslateOnly(false),
896 notifyBoundingRectChanged(false),
897 notifyInvalidated(false),
898 mouseSetsFocus(true),
899 explicitActivate(false),
900 wantsActive(false),
901 holesInSiblingIndex(false),
902 sequentialOrdering(true),
903 updateDueToGraphicsEffect(false),
904 scenePosDescendants(false),
905 pendingPolish(false),
906 mayHaveChildWithGraphicsEffect(false),
907 sendParentChangeNotification(false),
908 dirtyChildrenBoundingRect(true),
909 globalStackingOrder(-1),
910 q_ptr(nullptr)
911{
912}
913
920
929 AncestorFlag flag, bool enabled, bool root)
930{
931 Q_Q(QGraphicsItem);
932 if (root) {
933 // For root items only. This is the item that has either enabled or
934 // disabled \a childFlag, or has been reparented.
935 switch (int(childFlag)) {
936 case -2:
938 enabled = q->filtersChildEvents();
939 break;
940 case -1:
942 enabled = q->handlesChildEvents();
943 break;
947 break;
951 break;
955 break;
956 default:
957 return;
958 }
959
960 if (parent) {
961 // Inherit the enabled-state from our parents.
962 if ((parent->d_ptr->ancestorFlags & flag)
963 || (int(parent->d_ptr->flags & childFlag) == childFlag)
964 || (int(childFlag) == -1 && parent->d_ptr->handlesChildEvents)
965 || (int(childFlag) == -2 && parent->d_ptr->filtersDescendantEvents)) {
966 enabled = true;
967 ancestorFlags |= flag;
968 } else {
969 ancestorFlags &= ~flag;
970 }
971 } else {
972 // Top-level root items don't have any ancestors, so there are no
973 // ancestor flags either.
974 ancestorFlags = 0;
975 }
976 } else {
977 // Don't set or propagate the ancestor flag if it's already correct.
978 if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled))
979 return;
980
981 // Set the flag.
982 if (enabled)
983 ancestorFlags |= flag;
984 else
985 ancestorFlags &= ~flag;
986
987 // Don't process children if the item has the main flag set on itself.
988 if ((int(childFlag) != -1 && int(flags & childFlag) == childFlag)
989 || (int(childFlag) == -1 && handlesChildEvents)
990 || (int(childFlag) == -2 && filtersDescendantEvents))
991 return;
992 }
993
994 for (int i = 0; i < children.size(); ++i)
995 children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);
996}
997
999{
1000 int flags = 0;
1001 if (parent) {
1002 // Inherit the parent's ancestor flags.
1004 flags = pd->ancestorFlags;
1005
1006 // Add in flags from the parent.
1009 if (pd->handlesChildEvents)
1017 }
1018
1019 if (ancestorFlags == flags)
1020 return; // No change; stop propagation.
1022
1023 // Propagate to children recursively.
1024 for (int i = 0; i < children.size(); ++i)
1026}
1027
1034{
1035 Q_Q(QGraphicsItem);
1037 if (!qgraphicsitem_cast<QGraphicsItemGroup *>(q)) {
1038 for (QGraphicsItem *child : std::as_const(children))
1039 child->d_func()->setIsMemberOfGroup(enabled);
1040 }
1041}
1042
1049{
1050 Q_Q(QGraphicsItem);
1051 switch (event->type()) {
1056 QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
1057 mouseEvent->setPos(item->mapFromItem(q, mouseEvent->pos()));
1058 mouseEvent->setLastPos(item->mapFromItem(q, mouseEvent->pos()));
1059 for (int i = 0x1; i <= 0x10; i <<= 1) {
1060 if (mouseEvent->buttons() & i) {
1062 mouseEvent->setButtonDownPos(button, item->mapFromItem(q, mouseEvent->buttonDownPos(button)));
1063 }
1064 }
1065 break;
1066 }
1068 QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
1069 wheelEvent->setPos(item->mapFromItem(q, wheelEvent->pos()));
1070 break;
1071 }
1074 contextEvent->setPos(item->mapFromItem(q, contextEvent->pos()));
1075 break;
1076 }
1078 QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
1079 hoverEvent->setPos(item->mapFromItem(q, hoverEvent->pos()));
1080 break;
1081 }
1082 default:
1083 break;
1084 }
1085}
1086
1096{
1097 Q_Q(const QGraphicsItem);
1098 if (!itemIsUntransformable())
1099 return sceneTransform.inverted();
1100 const QGraphicsView *view = viewport
1101 ? qobject_cast<QGraphicsView *>(viewport->parentWidget())
1102 : nullptr;
1103 if (view == nullptr)
1104 return sceneTransform.inverted();
1105 // ### More ping pong than needed.
1106 const QTransform viewportTransform = view->viewportTransform();
1107 return viewportTransform * q->deviceTransform(viewportTransform).inverted();
1108}
1109
1115
1125{
1126 // COMBINE
1127 if (viewTransform && itemIsUntransformable()) {
1128 *x = q_ptr->deviceTransform(*viewTransform);
1129 } else {
1130 if (transformData)
1132 if (!pos.isNull())
1134 }
1135}
1136
1147{
1148 // COMBINE
1149 if (viewTransform && itemIsUntransformable()) {
1150 *x = q_ptr->deviceTransform(*viewTransform);
1151 } else {
1152 x->translate(pos.x(), pos.y());
1153 if (transformData)
1155 }
1156}
1157
1159{
1160 if (parent) {
1164 parent->d_ptr->sceneTransform.dy() + pos.y());
1165 } else {
1168 }
1169 if (transformData) {
1172 } else {
1174 }
1175 } else if (!transformData) {
1178 } else if (transformData->onlyTransform) {
1180 if (!pos.isNull())
1183 } else if (pos.isNull()) {
1186 } else {
1190 }
1192}
1193
1202 const QVariant *thisPointerVariant)
1203{
1204 Q_Q(QGraphicsItem);
1205 if (newParent == parent)
1206 return;
1207
1208 if (isWidget)
1209 static_cast<QGraphicsWidgetPrivate *>(this)->fixFocusChainBeforeReparenting((newParent &&
1210 newParent->isWidget()) ? static_cast<QGraphicsWidget *>(newParent) : nullptr,
1211 scene);
1212 if (scene) {
1213 // Deliver the change to the index
1214 if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
1215 scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent);
1216
1217 // Disable scene pos notifications for old ancestors
1219 scene->d_func()->setScenePosItemEnabled(q, false);
1220 }
1221
1222 if (subFocusItem && parent) {
1223 // Make sure none of the old parents point to this guy.
1225 }
1226
1227 // We anticipate geometry changes. If the item is deleted, it will be
1228 // removed from the index at a later stage, and the whole scene will be
1229 // updated.
1230 if (!inDestructor)
1232
1233 if (parent) {
1234 // Remove from current parent
1236 if (thisPointerVariant)
1238 }
1239
1240 // Update toplevelitem list. If this item is being deleted, its parent
1241 // will be 0 but we don't want to register/unregister it in the TLI list.
1242 if (scene && !inDestructor) {
1243 if (parent && !newParent) {
1244 scene->d_func()->registerTopLevelItem(q);
1245 } else if (!parent && newParent) {
1246 scene->d_func()->unregisterTopLevelItem(q);
1247 }
1248 }
1249
1250 // Ensure any last parent focus scope does not point to this item or any of
1251 // its descendents.
1253 QGraphicsItem *parentFocusScopeItem = nullptr;
1254 while (p) {
1255 if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
1256 // If this item's focus scope's focus scope item points
1257 // to this item or a descendent, then clear it.
1259 if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
1260 parentFocusScopeItem = fsi;
1261 p->d_ptr->focusScopeItem = nullptr;
1262 fsi->d_ptr->focusScopeItemChange(false);
1263 }
1264 break;
1265 }
1266 p = p->d_ptr->parent;
1267 }
1268
1269 // Update graphics effect optimization flag
1270 if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect))
1272
1273 // Update focus scope item ptr in new scope.
1274 QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
1275 if (newFocusScopeItem && newParent) {
1276 QGraphicsItem *p = newParent;
1277 while (p) {
1278 if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
1279 if (subFocusItem && subFocusItem != q_ptr) {
1280 // Find the subFocusItem's topmost focus scope within the new parent's focusscope
1281 QGraphicsItem *ancestorScope = nullptr;
1283 while (p2 && p2 != p) {
1284 if (p2->d_ptr->flags & QGraphicsItem::ItemIsFocusScope)
1285 ancestorScope = p2;
1286 if (p2->d_ptr->flags & QGraphicsItem::ItemIsPanel)
1287 break;
1288 if (p2 == q_ptr)
1289 break;
1290 p2 = p2->d_ptr->parent;
1291 }
1292 if (ancestorScope)
1293 newFocusScopeItem = ancestorScope;
1294 }
1295
1296 p->d_ptr->focusScopeItem = newFocusScopeItem;
1297 newFocusScopeItem->d_ptr->focusScopeItemChange(true);
1298 // Ensure the new item is no longer the subFocusItem. The
1299 // only way to set focus on a child of a focus scope is
1300 // by setting focus on the scope itself.
1301 if (subFocusItem && !p->focusItem())
1303 break;
1304 }
1305 p = p->d_ptr->parent;
1306 }
1307 }
1308
1309 // Resolve depth.
1311
1312 if ((parent = newParent)) {
1313 if (parent->d_func()->scene && parent->d_func()->scene != scene) {
1314 // Move this item to its new parent's scene
1315 parent->d_func()->scene->addItem(q);
1316 } else if (!parent->d_func()->scene && scene) {
1317 // Remove this item from its former scene
1318 scene->removeItem(q);
1319 }
1320
1322 if (thisPointerVariant)
1324 if (scene) {
1325 // Re-enable scene pos notifications for new ancestors
1327 scene->d_func()->setScenePosItemEnabled(q, true);
1328 }
1329
1330 // Propagate dirty flags to the new parent
1331 markParentDirty(/*updateBoundingRect=*/true);
1332
1333 // Inherit ancestor flags from the new parent.
1335
1336 // Update item visible / enabled.
1337 if (parent->d_ptr->visible != visible) {
1339 setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false);
1340 }
1341 if (parent->isEnabled() != enabled) {
1343 setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false);
1344 }
1345
1346 // Auto-activate if visible and the parent is active.
1347 if (visible && parent->isActive())
1348 q->setActive(true);
1349 } else {
1350 // Inherit ancestor flags from the new parent.
1352
1353 if (!inDestructor) {
1354 // Update item visible / enabled.
1355 if (!visible && !explicitlyHidden)
1356 setVisibleHelper(true, /* explicit = */ false);
1357 if (!enabled && !explicitlyDisabled)
1358 setEnabledHelper(true, /* explicit = */ false);
1359 }
1360 }
1361
1363 if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData)))
1365
1366 // Restore the sub focus chain.
1367 if (subFocusItem) {
1368 subFocusItem->d_ptr->setSubFocus(newParent);
1369 if (parent && parent->isActive())
1371 }
1372
1373 // Deliver post-change notification
1374 if (newParentVariant)
1375 q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant);
1376
1377 if (isObject)
1378 emit static_cast<QGraphicsObject *>(q)->parentChanged();
1379}
1380
1387{
1388 Q_Q(QGraphicsItem);
1389
1390 QRectF childrenRect;
1391 QRectF *result = rect;
1392 rect = &childrenRect;
1393 const bool setTopMostEffectItem = !topMostEffectItem;
1394
1395 for (int i = 0; i < children.size(); ++i) {
1397 QGraphicsItemPrivate *childd = child->d_ptr.data();
1398 if (setTopMostEffectItem)
1399 topMostEffectItem = child;
1400 bool hasPos = !childd->pos.isNull();
1401 if (hasPos || childd->transformData) {
1402 // COMBINE
1403 QTransform matrix = childd->transformToParent();
1404 if (x)
1405 matrix *= *x;
1406 *rect |= matrix.mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
1407 if (!childd->children.isEmpty())
1408 childd->childrenBoundingRectHelper(&matrix, rect, topMostEffectItem);
1409 } else {
1410 if (x)
1411 *rect |= x->mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
1412 else
1413 *rect |= child->d_ptr->effectiveBoundingRect(topMostEffectItem);
1414 if (!childd->children.isEmpty())
1415 childd->childrenBoundingRectHelper(x, rect, topMostEffectItem);
1416 }
1417 }
1418
1420 if (x)
1421 *rect &= x->mapRect(q->boundingRect());
1422 else
1423 *rect &= q->boundingRect();
1424 }
1425
1426 *result |= *rect;
1427}
1428
1430 const QRegion &exposedRegion, bool allItems) const
1431{
1433 Q_Q(const QGraphicsItem);
1434
1435 // Initialize standard QStyleOption values.
1436 const QRectF brect = q->boundingRect();
1437 option->state = QStyle::State_None;
1438 option->rect = brect.toRect();
1439 option->exposedRect = brect;
1440
1441 // Style animations require a QObject-based animation target.
1442 // If a plain QGraphicsItem is used to draw animated controls,
1443 // QStyle is let to send animation updates to the whole scene.
1444 option->styleObject = q_ptr->toGraphicsObject();
1445 if (!option->styleObject)
1446 option->styleObject = scene;
1447
1448 if (selected)
1450 if (enabled)
1451 option->state |= QStyle::State_Enabled;
1452 if (q->hasFocus())
1454 if (scene) {
1455 if (scene->d_func()->hoverItems.contains(q_ptr))
1457 if (q == scene->mouseGrabberItem())
1458 option->state |= QStyle::State_Sunken;
1459 }
1460
1462 return;
1463
1464 if (!allItems) {
1465 // Determine the item's exposed area
1466 option->exposedRect = QRectF();
1467 const QTransform reverseMap = worldTransform.inverted();
1468 for (const QRect &exposedRect : exposedRegion) {
1469 option->exposedRect |= reverseMap.mapRect(QRectF(exposedRect));
1470 if (option->exposedRect.contains(brect))
1471 break;
1472 }
1473 option->exposedRect &= brect;
1474 }
1475}
1476
1483{
1486 const auto &constDeviceData = deviceData; // avoid detach
1487 for (const auto &data : constDeviceData)
1489 deviceData.clear();
1490 allExposed = true;
1491 exposed.clear();
1492}
1493
1504 : d_ptr(new QGraphicsItemPrivate)
1505{
1506 d_ptr->q_ptr = this;
1507 setParentItem(parent);
1508}
1509
1514 : d_ptr(&dd)
1515{
1516 d_ptr->q_ptr = this;
1517 setParentItem(parent);
1518}
1519
1529{
1530 if (d_ptr->isObject) {
1531 QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
1533 p->wasDeleted = true;
1534 if (p->declarativeData) {
1535 p->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
1537 QAbstractDeclarativeData::destroyed(p->declarativeData, o);
1538 p->declarativeData = nullptr;
1539 p->wasDeleted = false;
1540 }
1541 }
1542
1543 d_ptr->inDestructor = 1;
1545
1546#ifndef QT_NO_GESTURES
1548 QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
1551 manager->cleanupCachedGestures(o, it.key());
1552 }
1553 }
1554#endif
1555
1556 clearFocus();
1557 setFocusProxy(nullptr);
1558
1559 // Update focus scope item ptr.
1561 while (p) {
1562 if (p->flags() & ItemIsFocusScope) {
1563 if (p->d_ptr->focusScopeItem == this)
1564 p->d_ptr->focusScopeItem = nullptr;
1565 break;
1566 }
1567 p = p->d_ptr->parent;
1568 }
1569
1570 if (!d_ptr->children.isEmpty()) {
1571 while (!d_ptr->children.isEmpty())
1572 delete d_ptr->children.first();
1574 }
1575
1576 if (d_ptr->scene) {
1577 d_ptr->scene->d_func()->removeItemHelper(this);
1578 } else {
1580 setParentItem(nullptr);
1581 }
1582
1583#if QT_CONFIG(graphicseffect)
1584 delete d_ptr->graphicsEffect;
1585#endif // QT_CONFIG(graphicseffect)
1586 if (d_ptr->transformData) {
1587 for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
1589 static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = nullptr;
1590 delete t;
1591 }
1592 }
1593 delete d_ptr->transformData;
1594
1595 if (QGraphicsItemCustomDataStore *dataStore = qt_dataStore())
1596 dataStore->data.remove(this);
1597}
1598
1606{
1607 return d_ptr->scene;
1608}
1609
1617{
1618 if (!d_ptr->isMemberOfGroup)
1619 return nullptr;
1620 QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
1621 while ((parent = parent->d_ptr->parent)) {
1622 if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent))
1623 return group;
1624 }
1625 // Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this
1626 // item is a group item.
1627 return nullptr;
1628}
1629
1638{
1639 if (!group) {
1640 if (QGraphicsItemGroup *group = this->group())
1641 group->removeFromGroup(this);
1642 } else {
1643 group->addToGroup(this);
1644 }
1645}
1646
1654{
1655 return d_ptr->parent;
1656}
1657
1667{
1668 QGraphicsItem *parent = const_cast<QGraphicsItem *>(this);
1669 while (QGraphicsItem *grandPa = parent->parentItem())
1670 parent = grandPa;
1671 return parent;
1672}
1673
1683{
1685 return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : nullptr;
1686}
1687
1697{
1699 while (p && !p->isWidget())
1700 p = p->parentItem();
1701 return (p && p->isWidget()) ? static_cast<QGraphicsWidget *>(p) : nullptr;
1702}
1703
1714{
1715 if (const QGraphicsWidget *p = parentWidget())
1716 return p->topLevelWidget();
1717 return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : nullptr;
1718}
1719
1730{
1731 QGraphicsItem *p = panel();
1732 if (p && p->isWindow())
1733 return static_cast<QGraphicsWidget *>(p);
1734 return nullptr;
1735}
1736
1747{
1748 if (d_ptr->flags & ItemIsPanel)
1749 return const_cast<QGraphicsItem *>(this);
1750 return d_ptr->parent ? d_ptr->parent->panel() : nullptr;
1751}
1752
1760{
1761 return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : nullptr;
1762}
1763
1771{
1772 return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : nullptr;
1773}
1774
1790{
1791 if (newParent == this) {
1792 qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
1793 return;
1794 }
1795 if (newParent == d_ptr->parent)
1796 return;
1797
1799 QVariant::fromValue<QGraphicsItem *>(newParent)));
1800 newParent = qvariant_cast<QGraphicsItem *>(newParentVariant);
1801 if (newParent == d_ptr->parent)
1802 return;
1803
1804 const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this));
1805 d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant);
1806}
1807
1818QList<QGraphicsItem *> QGraphicsItem::childItems() const
1819{
1820 const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren();
1821 return d_ptr->children;
1822}
1823
1830{
1831 return d_ptr->isWidget;
1832}
1833
1842{
1843 return d_ptr->isWidget && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
1844}
1845
1853{
1854 return d_ptr->flags & ItemIsPanel;
1855}
1856
1866QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const
1867{
1868 return GraphicsItemFlags(d_ptr->flags);
1869}
1870
1878{
1879 if (enabled)
1880 setFlags(GraphicsItemFlags(d_ptr->flags) | flag);
1881 else
1882 setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag);
1883}
1884
1900void QGraphicsItem::setFlags(GraphicsItemFlags flags)
1901{
1902 // Notify change and check for adjustment.
1903 if (quint32(d_ptr->flags) == quint32(flags))
1904 return;
1905 flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt());
1906 if (quint32(d_ptr->flags) == quint32(flags))
1907 return;
1908 if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
1909 d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags);
1910
1911 // Flags that alter the geometry of the item (or its children).
1913 bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
1914 if (fullUpdate)
1915 d_ptr->updatePaintedViewBoundingRects(/*children=*/true);
1916
1917 // Keep the old flags to compare the diff.
1918 GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags);
1919
1920 // Update flags.
1921 d_ptr->flags = flags;
1922
1923 if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
1924 // Clear focus on the item if it has focus when the focusable flag
1925 // is unset.
1926 clearFocus();
1927 }
1928
1929 if (!(d_ptr->flags & ItemIsSelectable) && isSelected()) {
1930 // Unselect the item if it is selected when the selectable flag is
1931 // unset.
1932 setSelected(false);
1933 }
1934
1936 // Item children clipping changes. Propagate the ancestor flag to
1937 // all children.
1939 // The childrenBoundingRect is clipped to the boundingRect in case of ItemClipsChildrenToShape,
1940 // which means we have to invalidate the cached childrenBoundingRect whenever this flag changes.
1942 d_ptr->markParentDirty(true);
1943 }
1944
1946 // Item children containtment changes. Propagate the ancestor flag to all children.
1948 }
1949
1951 // Item children clipping changes. Propagate the ancestor flag to
1952 // all children.
1954 }
1955
1957 // NB! We change the flags directly here, so we must also update d_ptr->flags.
1958 // Note that this has do be done before the ItemStacksBehindParent check
1959 // below; otherwise we will loose the change.
1960
1961 // Update stack-behind.
1962 if (d_ptr->z < qreal(0.0))
1964 else
1965 flags &= ~ItemStacksBehindParent;
1966 d_ptr->flags = flags;
1967 }
1968
1969 if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
1970 // NB! This check has to come after the ItemNegativeZStacksBehindParent
1971 // check above. Be careful.
1972
1973 // Ensure child item sorting is up to date when toggling this flag.
1974 if (d_ptr->parent)
1976 else if (d_ptr->scene)
1977 d_ptr->scene->d_func()->needSortTopLevelItems = 1;
1978 }
1979
1980 if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) {
1981 // Update input method sensitivity in any views.
1982 if (d_ptr->scene)
1983 d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
1984 }
1985
1986 if ((flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
1987 bool becomesPanel = (flags & ItemIsPanel);
1988 if ((d_ptr->panelModality != NonModal) && d_ptr->scene) {
1989 // update the panel's modal state
1990 if (becomesPanel)
1991 d_ptr->scene->d_func()->enterModal(this);
1992 else
1993 d_ptr->scene->d_func()->leaveModal(this);
1994 }
1995 if (d_ptr->isWidget && (becomesPanel || parentWidget())) {
1996 QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
1997 QGraphicsWidget *focusFirst = w;
1998 QGraphicsWidget *focusLast = w;
1999 for (;;) {
2000 QGraphicsWidget *test = focusLast->d_func()->focusNext;
2001 if (!w->isAncestorOf(test) || test == w)
2002 break;
2003 focusLast = test;
2004 }
2005
2006 if (becomesPanel) {
2007 // unlink own widgets from focus chain
2008 QGraphicsWidget *beforeMe = w->d_func()->focusPrev;
2009 QGraphicsWidget *afterMe = focusLast->d_func()->focusNext;
2010 beforeMe->d_func()->focusNext = afterMe;
2011 afterMe->d_func()->focusPrev = beforeMe;
2012 focusFirst->d_func()->focusPrev = focusLast;
2013 focusLast->d_func()->focusNext = focusFirst;
2014 if (!isAncestorOf(focusFirst->d_func()->focusNext))
2015 focusFirst->d_func()->focusNext = w;
2016 } else if (QGraphicsWidget *pw = parentWidget()) {
2017 // link up own widgets to focus chain
2018 QGraphicsWidget *beforeMe = pw;
2019 QGraphicsWidget *afterMe = pw->d_func()->focusNext;
2020 beforeMe->d_func()->focusNext = w;
2021 afterMe->d_func()->focusPrev = focusLast;
2022 w->d_func()->focusPrev = beforeMe;
2023 focusLast->d_func()->focusNext = afterMe;
2024 }
2025 }
2026 }
2027
2028 if (d_ptr->scene) {
2031 d_ptr->scene->d_func()->registerScenePosItem(this);
2032 else
2033 d_ptr->scene->d_func()->unregisterScenePosItem(this);
2034 }
2035 d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
2036 }
2037
2038 // Notify change.
2040}
2041
2053
2091void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
2092{
2093 CacheMode lastMode = CacheMode(d_ptr->cacheMode);
2094 d_ptr->cacheMode = mode;
2095 bool noVisualChange = (mode == NoCache && lastMode == NoCache)
2096 || (mode == NoCache && lastMode == DeviceCoordinateCache)
2097 || (mode == DeviceCoordinateCache && lastMode == NoCache)
2098 || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache);
2099 if (mode == NoCache) {
2101 } else {
2103
2104 // Reset old cache
2105 cache->purge();
2106
2107 if (mode == ItemCoordinateCache) {
2108 if (lastMode == mode && cache->fixedSize == logicalCacheSize)
2109 noVisualChange = true;
2110 cache->fixedSize = logicalCacheSize;
2111 }
2112 }
2113 if (!noVisualChange)
2114 update();
2115}
2116
2126
2135{
2137 return;
2138
2139 PanelModality previousModality = d_ptr->panelModality;
2140 bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible());
2141 if (enterLeaveModal && panelModality == NonModal)
2142 d_ptr->scene->d_func()->leaveModal(this);
2144 if (enterLeaveModal && d_ptr->panelModality != NonModal)
2145 d_ptr->scene->d_func()->enterModal(this, previousModality);
2146}
2147
2160{
2161 if (!d_ptr->scene)
2162 return false;
2163
2164
2165 QGraphicsItem *dummy = nullptr;
2166 if (!blockingPanel)
2167 blockingPanel = &dummy;
2168
2169 const QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func();
2170 if (scene_d->modalPanels.isEmpty())
2171 return false;
2172
2173 // ###
2174 if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this)
2175 return false;
2176
2177 for (int i = 0; i < scene_d->modalPanels.size(); ++i) {
2178 QGraphicsItem *modalPanel = scene_d->modalPanels.at(i);
2179 if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
2180 // Scene modal panels block all non-descendents.
2181 if (modalPanel != this && !modalPanel->isAncestorOf(this)) {
2182 *blockingPanel = modalPanel;
2183 return true;
2184 }
2185 } else {
2186 // Window modal panels block ancestors and siblings/cousins.
2187 if (modalPanel != this
2188 && !modalPanel->isAncestorOf(this)
2189 && commonAncestorItem(modalPanel)) {
2190 *blockingPanel = modalPanel;
2191 return true;
2192 }
2193 }
2194 }
2195 return false;
2196}
2197
2198#if QT_CONFIG(tooltip)
2205QString QGraphicsItem::toolTip() const
2206{
2208}
2209
2216void QGraphicsItem::setToolTip(const QString &toolTip)
2217{
2218 const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip));
2219 d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString());
2220 itemChange(ItemToolTipHasChanged, toolTipVariant);
2221}
2222#endif // QT_CONFIG(tooltip)
2223
2224#ifndef QT_NO_CURSOR
2241{
2242 return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor));
2243}
2244
2261{
2262 const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor)));
2263 d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant));
2264 d_ptr->hasCursor = 1;
2265 if (d_ptr->scene) {
2266 d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
2267 const auto views = d_ptr->scene->views();
2268 for (QGraphicsView *view : views) {
2269 view->viewport()->setMouseTracking(true);
2270 // Note: Some of this logic is duplicated in QGraphicsView's mouse events.
2271 if (view->underMouse()) {
2272 const QPoint viewPoint = view->mapFromGlobal(QCursor::pos());
2273 const QPointF cursorPos = mapFromScene(view->mapToScene(viewPoint));
2274 // the cursor can only change if the current item is under the mouse
2275 if (boundingRect().contains(cursorPos)) {
2276 const auto itemsUnderCursor = view->items(viewPoint);
2277 for (QGraphicsItem *itemUnderCursor : itemsUnderCursor) {
2278 if (itemUnderCursor->hasCursor()) {
2279 QMetaObject::invokeMethod(view, "_q_setViewportCursor",
2280 Q_ARG(QCursor, itemUnderCursor->cursor()));
2281 break;
2282 }
2283 }
2284 }
2285 break;
2286 }
2287 }
2288 }
2289 itemChange(ItemCursorHasChanged, cursorVariant);
2290}
2291
2301{
2302 return d_ptr->hasCursor;
2303}
2304
2311{
2312 if (!d_ptr->hasCursor)
2313 return;
2315 d_ptr->hasCursor = 0;
2316 if (d_ptr->scene) {
2317 const auto views = d_ptr->scene->views();
2318 for (QGraphicsView *view : views) {
2319 if (view->underMouse() && view->itemAt(view->mapFromGlobal(QCursor::pos())) == this) {
2320 QMetaObject::invokeMethod(view, "_q_unsetViewportCursor");
2321 break;
2322 }
2323 }
2324 }
2325}
2326
2327#endif // QT_NO_CURSOR
2328
2338{
2339 return d_ptr->visible;
2340}
2341
2356{
2357 const QGraphicsItem *p = this;
2359 return false;
2360 do {
2361 if (p == parent)
2362 return true;
2363 if (p->d_ptr->explicitlyHidden)
2364 return false;
2365 } while ((p = p->d_ptr->parent));
2366 return parent == nullptr;
2367}
2368
2375void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
2376 bool update, bool hiddenByPanel)
2377{
2378 Q_Q(QGraphicsItem);
2379
2380 // Update explicit bit.
2381 if (explicitly)
2382 explicitlyHidden = newVisible ? 0 : 1;
2383
2384 // Check if there's nothing to do.
2385 if (visible == quint32(newVisible))
2386 return;
2387
2388 // Don't show child if parent is not visible
2389 if (parent && newVisible && !parent->d_ptr->visible)
2390 return;
2391
2392 // Modify the property.
2394 quint32(newVisible)));
2395 newVisible = newVisibleVariant.toBool();
2396 if (visible == quint32(newVisible))
2397 return;
2398 visible = newVisible;
2399
2400 // Schedule redrawing
2401 if (update) {
2402 QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
2403 if (c)
2404 c->purge();
2405 if (scene) {
2406#if QT_CONFIG(graphicseffect)
2407 invalidateParentGraphicsEffectsRecursively();
2408#endif // QT_CONFIG(graphicseffect)
2409 scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
2410 }
2411 }
2412
2413 // Certain properties are dropped as an item becomes invisible.
2414 bool hasFocus = q_ptr->hasFocus();
2415 if (!newVisible) {
2416 if (scene) {
2417 if (scene->d_func()->mouseGrabberItems.contains(q))
2418 q->ungrabMouse();
2419 if (scene->d_func()->keyboardGrabberItems.contains(q))
2420 q->ungrabKeyboard();
2421 if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
2422 scene->d_func()->leaveModal(q_ptr);
2423 }
2424 if (hasFocus && scene) {
2425 // Hiding the focus item or the closest non-panel ancestor of the focus item
2426 QGraphicsItem *focusItem = scene->focusItem();
2427 bool clear = true;
2428 if (isWidget && !focusItem->isPanel()) {
2429 do {
2430 if (focusItem == q_ptr) {
2431 clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
2432 break;
2433 }
2434 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
2435 }
2436 if (clear)
2437 clearFocusHelper(/* giveFocusToParent = */ false, hiddenByPanel);
2438 }
2439 if (q_ptr->isSelected())
2440 q_ptr->setSelected(false);
2441 } else {
2442 geometryChanged = 1;
2444 if (scene) {
2445 if (isWidget) {
2446 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
2447 if (widget->windowType() == Qt::Popup)
2448 scene->d_func()->addPopup(widget);
2449 }
2450 if (q->isPanel() && panelModality != QGraphicsItem::NonModal) {
2451 scene->d_func()->enterModal(q_ptr);
2452 }
2453 }
2454 }
2455
2456 // Update children with explicitly = false.
2457 const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape
2460 for (QGraphicsItem *child : std::as_const(children)) {
2461 if (!newVisible || !child->d_ptr->explicitlyHidden)
2462 child->d_ptr->setVisibleHelper(newVisible, false, updateChildren, hiddenByPanel);
2463 }
2464
2465 // Update activation
2466 if (scene && q->isPanel()) {
2467 if (newVisible) {
2468 if (parent && parent->isActive())
2469 q->setActive(true);
2470 } else {
2471 if (q->isActive())
2473 }
2474 }
2475
2476 // Enable subfocus
2477 if (scene) {
2478 if (newVisible) {
2479 // Item is shown
2481 bool done = false;
2482 while (p) {
2483 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
2485 if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
2486 done = true;
2487 while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
2488 fsi = fsi->d_ptr->focusScopeItem;
2489 fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
2490 /* focusFromHide = */ false);
2491 }
2492 break;
2493 }
2494 p = p->d_ptr->parent;
2495 }
2496 if (!done) {
2498 if (fi && fi != scene->focusItem()) {
2499 scene->setFocusItem(fi);
2501 !scene->focusItem() &&
2502 q->isAncestorOf(scene->d_func()->lastFocusItem)) {
2503 q_ptr->setFocus();
2504 }
2505 }
2506 } else {
2507 // Item is hidden
2508 if (hasFocus) {
2510 while (p) {
2511 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
2512 if (p->d_ptr->visible) {
2513 p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
2514 /* focusFromHide = */ true);
2515 }
2516 break;
2517 }
2518 p = p->d_ptr->parent;
2519 }
2520 }
2521 }
2522 }
2523
2524 // Deliver post-change notification.
2526
2527 if (isObject)
2528 emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged();
2529}
2530
2564{
2565 d_ptr->setVisibleHelper(visible,
2566 /* explicit = */ true,
2567 /* update = */ true,
2568 /* hiddenByPanel = */ isPanel());
2569}
2570
2597{
2598 return d_ptr->enabled;
2599}
2600
2607void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bool update)
2608{
2609 // Update explicit bit.
2610 if (explicitly)
2611 explicitlyDisabled = newEnabled ? 0 : 1;
2612
2613 // Check if there's nothing to do.
2614 if (enabled == quint32(newEnabled))
2615 return;
2616
2617 // Certain properties are dropped when an item is disabled.
2618 if (!newEnabled) {
2619 if (scene) {
2620 if (scene->mouseGrabberItem() == q_ptr)
2621 q_ptr->ungrabMouse();
2622 if (q_ptr->hasFocus()) {
2623 // Disabling the closest non-panel ancestor of the focus item
2624 // causes focus to pop to the next item, otherwise it's cleared.
2625 QGraphicsItem *focusItem = scene->focusItem();
2626 bool clear = true;
2627 if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) {
2628 do {
2629 if (focusItem == q_ptr) {
2630 clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true);
2631 break;
2632 }
2633 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
2634 }
2635 if (clear)
2636 q_ptr->clearFocus();
2637 }
2638 }
2639 if (q_ptr->isSelected())
2640 q_ptr->setSelected(false);
2641 }
2642
2643 // Modify the property.
2645 quint32(newEnabled)));
2646 enabled = newEnabledVariant.toBool();
2647
2648 // Schedule redraw.
2649 if (update)
2650 q_ptr->update();
2651
2652 for (QGraphicsItem *child : std::as_const(children)) {
2653 if (!newEnabled || !child->d_ptr->explicitlyDisabled)
2654 child->d_ptr->setEnabledHelper(newEnabled, /* explicitly = */ false);
2655 }
2656
2657 // Deliver post-change notification.
2659
2660 if (isObject)
2661 emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged();
2662}
2663
2693{
2694 d_ptr->setEnabledHelper(enabled, /* explicitly = */ true);
2695}
2696
2707{
2708 if (QGraphicsItemGroup *group = this->group())
2709 return group->isSelected();
2710 return d_ptr->selected;
2711}
2712
2738{
2739 if (QGraphicsItemGroup *group = this->group()) {
2740 group->setSelected(selected);
2741 return;
2742 }
2743
2745 selected = false;
2746 if (d_ptr->selected == selected)
2747 return;
2748 const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected)));
2749 bool newSelected = newSelectedVariant.toBool();
2750 if (d_ptr->selected == newSelected)
2751 return;
2752 d_ptr->selected = newSelected;
2753
2754 update();
2755 if (d_ptr->scene) {
2756 QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
2757 if (selected) {
2758 sceneD->selectedItems << this;
2759 } else {
2760 // QGraphicsScene::selectedItems() lazily pulls out all items that are
2761 // no longer selected.
2762 }
2763 if (!sceneD->selectionChanging)
2765 }
2766
2767 // Deliver post-change notification.
2769}
2770
2791{
2792 return d_ptr->opacity;
2793}
2794
2810
2838{
2839 // Notify change.
2840 const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity));
2841
2842 // Normalized opacity
2843 qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1));
2844
2845 // No change? Done.
2846 if (newOpacity == d_ptr->opacity)
2847 return;
2848
2849 bool wasFullyTransparent = d_ptr->isOpacityNull();
2850 d_ptr->opacity = newOpacity;
2851
2852 // Notify change.
2853 itemChange(ItemOpacityHasChanged, newOpacityVariant);
2854
2855 // Update.
2856 if (d_ptr->scene) {
2857#if QT_CONFIG(graphicseffect)
2858 d_ptr->invalidateParentGraphicsEffectsRecursively();
2860 d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged);
2861#endif // QT_CONFIG(graphicseffect)
2862 d_ptr->scene->d_func()->markDirty(this, QRectF(),
2863 /*invalidateChildren=*/true,
2864 /*force=*/false,
2865 /*ignoreOpacity=*/d_ptr->isOpacityNull());
2866 if (wasFullyTransparent)
2868 }
2869
2870 if (d_ptr->isObject)
2871 emit static_cast<QGraphicsObject *>(this)->opacityChanged();
2872}
2873
2879#if QT_CONFIG(graphicseffect)
2880QGraphicsEffect *QGraphicsItem::graphicsEffect() const
2881{
2882 return d_ptr->graphicsEffect;
2883}
2884
2900void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
2901{
2902 if (d_ptr->graphicsEffect == effect)
2903 return;
2904
2905 if (d_ptr->graphicsEffect) {
2906 delete d_ptr->graphicsEffect;
2907 d_ptr->graphicsEffect = nullptr;
2908 } else if (d_ptr->parent) {
2910 }
2911
2912 if (effect) {
2913 // Set new effect.
2917 effect->d_func()->setGraphicsEffectSource(source);
2919 }
2920}
2921#endif // QT_CONFIG(graphicseffect)
2922
2924{
2925#if QT_CONFIG(graphicseffect)
2926 QGraphicsItemPrivate *itemPrivate = this;
2927 do {
2928 // parent chain already notified?
2929 if (itemPrivate->mayHaveChildWithGraphicsEffect)
2930 return;
2931 itemPrivate->mayHaveChildWithGraphicsEffect = 1;
2932 } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : nullptr));
2933#endif
2934}
2935
2947{
2948#if QT_CONFIG(graphicseffect)
2949 Q_Q(const QGraphicsItem);
2951 if (scene && effect && effect->isEnabled()) {
2952 if (scene->d_func()->views.isEmpty())
2953 return effect->boundingRectFor(rect);
2954 QRectF sceneRect = q->mapRectToScene(rect);
2955 QRectF sceneEffectRect;
2956 const auto views = scene->views();
2957 for (QGraphicsView *view : views) {
2958 QRectF deviceRect = view->d_func()->mapRectFromScene(sceneRect);
2959 QRect deviceEffectRect = effect->boundingRectFor(deviceRect).toAlignedRect();
2960 sceneEffectRect |= view->d_func()->mapRectToScene(deviceEffectRect);
2961 }
2962 return q->mapRectFromScene(sceneEffectRect);
2963 }
2964#endif // QT_CONFIG(graphicseffect)
2965 return rect;
2966}
2967
2979{
2980#if QT_CONFIG(graphicseffect)
2981 Q_Q(const QGraphicsItem);
2985 || topMostEffectItem == q)
2986 return brect;
2987
2988 const QGraphicsItem *effectParent = parent;
2989 while (effectParent) {
2990 QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect;
2991 if (scene && effect && effect->isEnabled()) {
2992 const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect);
2993 const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace);
2994 brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
2995 }
2996 if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
2997 || effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
2998 || topMostEffectItem == effectParent) {
2999 return brect;
3000 }
3001 effectParent = effectParent->d_ptr->parent;
3002 }
3003
3004 return brect;
3005#else //QT_CONFIG(graphicseffect)
3006 Q_UNUSED(topMostEffectItem);
3007 return q_ptr->boundingRect();
3008#endif // QT_CONFIG(graphicseffect)
3009
3010}
3011
3024{
3025 // Find translate-only offset
3026 // COMBINE
3028 const QGraphicsItem *parentItem = q_ptr;
3029 const QGraphicsItemPrivate *itemd;
3030 do {
3031 itemd = parentItem->d_ptr.data();
3032 if (itemd->transformData)
3033 break;
3034 offset += itemd->pos;
3035 } while ((parentItem = itemd->parent));
3036
3038 br.translate(offset);
3039 return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
3040}
3041
3050{
3051 return d_ptr->acceptDrops;
3052}
3053
3062{
3063 d_ptr->acceptDrops = on;
3064}
3065
3079{
3080 return Qt::MouseButtons(d_ptr->acceptedMouseButtons);
3081}
3082
3097void QGraphicsItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
3098{
3099 if (Qt::MouseButtons(d_ptr->acceptedMouseButtons) != buttons) {
3100 if (buttons == 0 && d_ptr->scene && d_ptr->scene->mouseGrabberItem() == this
3101 && d_ptr->scene->d_func()->lastMouseGrabberItemHasImplicitMouseGrab) {
3102 ungrabMouse();
3103 }
3105 }
3106}
3107
3118{
3119 return d_ptr->acceptsHover;
3120}
3121
3122
3155{
3157 return;
3159 if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
3160 d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
3161 d_ptr->scene->d_func()->enableMouseTrackingOnViews();
3162 }
3163}
3164
3173{
3174 return d_ptr->acceptTouchEvents;
3175}
3176
3185{
3187 return;
3189 if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) {
3190 d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false;
3191 d_ptr->scene->d_func()->enableTouchEventsOnViews();
3192 }
3193}
3194
3210
3230
3249{
3250 return d_ptr->handlesChildEvents;
3251}
3252
3297{
3298 if (!d_ptr->scene || !d_ptr->scene->isActive())
3299 return false;
3300 return panel() == d_ptr->scene->activePanel();
3301}
3302
3318{
3320 d_ptr->wantsActive = active;
3321 if (d_ptr->scene) {
3322 if (active) {
3323 // Activate this item.
3324 d_ptr->scene->setActivePanel(this);
3325 } else {
3326 QGraphicsItem *activePanel = d_ptr->scene->activePanel();
3327 QGraphicsItem *thisPanel = panel();
3328 if (!activePanel || activePanel == thisPanel) {
3329 // Deactivate this item, and reactivate the parent panel,
3330 // or the last active panel (if any).
3331 QGraphicsItem *nextToActivate = nullptr;
3332 if (d_ptr->parent)
3333 nextToActivate = d_ptr->parent->panel();
3334 if (!nextToActivate)
3335 nextToActivate = d_ptr->scene->d_func()->lastActivePanel;
3336 if (nextToActivate == this || isAncestorOf(nextToActivate))
3337 nextToActivate = nullptr;
3338 d_ptr->scene->setActivePanel(nextToActivate);
3339 }
3340 }
3341 }
3342}
3343
3351{
3352 if (!d_ptr->scene || !d_ptr->scene->isActive())
3353 return false;
3354
3355 if (d_ptr->focusProxy)
3356 return d_ptr->focusProxy->hasFocus();
3357
3358 if (d_ptr->scene->d_func()->focusItem != this)
3359 return false;
3360
3361 return panel() == d_ptr->scene->d_func()->activePanel;
3362}
3363
3385{
3386 d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromHide = */ false);
3387}
3388
3392void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide)
3393{
3394 // Disabled / unfocusable items cannot accept focus.
3396 return;
3397
3398 // Find focus proxy.
3400 while (f->d_ptr->focusProxy)
3401 f = f->d_ptr->focusProxy;
3402
3403 // Return if it already has focus.
3404 if (scene && scene->focusItem() == f)
3405 return;
3406
3407 // Update focus scope item ptr.
3409 while (p) {
3410 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
3411 QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem;
3413 if (oldFocusScopeItem)
3414 oldFocusScopeItem->d_ptr->focusScopeItemChange(false);
3416 if (!p->focusItem() && !focusFromHide) {
3417 // Calling setFocus() on a child of a focus scope that does
3418 // not have focus changes only the focus scope pointer,
3419 // so that focus is restored the next time the scope gains
3420 // focus.
3421 return;
3422 }
3423 break;
3424 }
3425 p = p->d_ptr->parent;
3426 }
3427
3428 if (climb) {
3429 while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible())
3430 f = f->d_ptr->focusScopeItem;
3431 }
3432
3433 // Update the child focus chain.
3434 QGraphicsItem *commonAncestor = nullptr;
3435 if (scene && scene->focusItem() && scene->focusItem()->panel() == q_ptr->panel()) {
3436 commonAncestor = scene->focusItem()->commonAncestorItem(f);
3437 scene->focusItem()->d_ptr->clearSubFocus(scene->focusItem(), commonAncestor);
3438 }
3439
3440 f->d_ptr->setSubFocus(f, commonAncestor);
3441
3442 // Update the scene's focus item.
3443 if (scene) {
3444 QGraphicsItem *p = q_ptr->panel();
3445 if ((!p && scene->isActive()) || (p && p->isActive())) {
3446 // Visible items immediately gain focus from scene.
3447 scene->d_func()->setFocusItemHelper(f, focusReason);
3448 }
3449 }
3450}
3451
3464{
3465 d_ptr->clearFocusHelper(/* giveFocusToParent = */ true,
3466 /* hiddenByParentPanel = */ false);
3467}
3468
3472void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel)
3473{
3478 }
3479
3480 if (giveFocusToParent) {
3481 // Pass focus to the closest parent focus scope
3482 if (!inDestructor) {
3484 while (p) {
3485 if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
3486 if (p->d_ptr->focusScopeItem == q_ptr) {
3487 p->d_ptr->focusScopeItem = nullptr;
3488 if (!subFocusItem->hasFocus()) //if it has focus, focusScopeItemChange is called elsewhere
3489 focusScopeItemChange(false);
3490 }
3491 if (subFocusItem->hasFocus())
3492 p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
3493 /* focusFromHide = */ false);
3494 return;
3495 }
3496 p = p->d_ptr->parent;
3497 }
3498 }
3499 }
3500
3501 if (subFocusItem->hasFocus()) {
3502 // Invisible items with focus must explicitly clear subfocus.
3503 if (!hiddenByParentPanel)
3505
3506 // If this item has the scene's input focus, clear it.
3507 scene->setFocusItem(nullptr);
3508 }
3509}
3510
3520{
3521 return d_ptr->focusProxy;
3522}
3523
3544{
3545 if (item == d_ptr->focusProxy)
3546 return;
3547 if (item == this) {
3548 qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
3549 return;
3550 }
3551 if (item) {
3552 if (item->d_ptr->scene != d_ptr->scene) {
3553 qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
3554 return;
3555 }
3556 for (QGraphicsItem *f = item->focusProxy(); f != nullptr; f = f->focusProxy()) {
3557 if (f == this) {
3558 qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item);
3559 return;
3560 }
3561 }
3562 }
3563
3564 QGraphicsItem *lastFocusProxy = d_ptr->focusProxy;
3565 if (lastFocusProxy)
3566 lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy);
3568 if (item)
3570}
3571
3585
3595
3631{
3632 if (!d_ptr->scene) {
3633 qWarning("QGraphicsItem::grabMouse: cannot grab mouse without scene");
3634 return;
3635 }
3636 if (!d_ptr->visible) {
3637 qWarning("QGraphicsItem::grabMouse: cannot grab mouse while invisible");
3638 return;
3639 }
3640 d_ptr->scene->d_func()->grabMouse(this);
3641}
3642
3650{
3651 if (!d_ptr->scene) {
3652 qWarning("QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
3653 return;
3654 }
3655 d_ptr->scene->d_func()->ungrabMouse(this);
3656}
3657
3693{
3694 if (!d_ptr->scene) {
3695 qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard without scene");
3696 return;
3697 }
3698 if (!d_ptr->visible) {
3699 qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard while invisible");
3700 return;
3701 }
3702 d_ptr->scene->d_func()->grabKeyboard(this);
3703}
3704
3712{
3713 if (!d_ptr->scene) {
3714 qWarning("QGraphicsItem::ungrabKeyboard: cannot ungrab keyboard without scene");
3715 return;
3716 }
3717 d_ptr->scene->d_func()->ungrabKeyboard(this);
3718}
3719
3734{
3735 return d_ptr->pos;
3736}
3737
3755{
3756 if (d_ptr->inDestructor)
3757 return;
3758
3759 if (qIsNaN(x))
3760 return;
3761
3762 setPos(QPointF(x, d_ptr->pos.y()));
3763}
3764
3782{
3783 if (d_ptr->inDestructor)
3784 return;
3785
3786 if (qIsNaN(y))
3787 return;
3788
3789 setPos(QPointF(d_ptr->pos.x(), y));
3790}
3791
3799{
3800 return mapToScene(0, 0);
3801}
3802
3809{
3810 Q_Q(QGraphicsItem);
3811 inSetPosHelper = 1;
3812 if (scene)
3813 q->prepareGeometryChange();
3814 QPointF oldPos = this->pos;
3815 this->pos = pos;
3817 inSetPosHelper = 0;
3818 if (isObject) {
3819 if (pos.x() != oldPos.x())
3820 emit static_cast<QGraphicsObject *>(q_ptr)->xChanged();
3821 if (pos.y() != oldPos.y())
3822 emit static_cast<QGraphicsObject *>(q_ptr)->yChanged();
3823 }
3824}
3825
3838
3850{
3851 if (d_ptr->pos == pos)
3852 return;
3853
3854 if (d_ptr->inDestructor)
3855 return;
3856
3857 // Update and repositition.
3860 if (d_ptr->isWidget)
3861 static_cast<QGraphicsWidget *>(this)->d_func()->setGeometryFromSetPos();
3864 return;
3865 }
3866
3867 // Notify the item that the position is changing.
3868 const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos)));
3869 QPointF newPos = newPosVariant.toPointF();
3870 if (newPos == d_ptr->pos)
3871 return;
3872
3873 // Update and repositition.
3874 d_ptr->setPosHelper(newPos);
3875
3876 // Send post-notification.
3879}
3880
3911void QGraphicsItem::ensureVisible(const QRectF &rect, int xmargin, int ymargin)
3912{
3913 if (d_ptr->scene) {
3914 QRectF sceneRect;
3915 if (!rect.isNull())
3916 sceneRect = sceneTransform().mapRect(rect);
3917 else
3918 sceneRect = sceneBoundingRect();
3919 for (QGraphicsView *view : std::as_const(d_ptr->scene->d_func()->views))
3920 view->ensureVisible(sceneRect, xmargin, ymargin);
3921 }
3922}
3923
3945{
3946 if (!d_ptr->transformData)
3947 return QTransform();
3948 return d_ptr->transformData->transform;
3949}
3950
3963{
3964 if (!d_ptr->transformData)
3965 return 0;
3966 return d_ptr->transformData->rotation;
3967}
3968
3989{
3991 qreal newRotation = angle;
3992
3994 // Notify the item that the rotation is changing.
3995 const QVariant newRotationVariant(itemChange(ItemRotationChange, angle));
3996 newRotation = newRotationVariant.toReal();
3997 }
3998
3999 if (!d_ptr->transformData)
4001
4002 if (d_ptr->transformData->rotation == newRotation)
4003 return;
4004
4005 d_ptr->transformData->rotation = newRotation;
4008
4009 // Send post-notification.
4011 itemChange(ItemRotationHasChanged, newRotation);
4012
4013 if (d_ptr->isObject)
4014 emit static_cast<QGraphicsObject *>(this)->rotationChanged();
4015
4017}
4018
4031{
4032 if (!d_ptr->transformData)
4033 return 1.;
4034 return d_ptr->transformData->scale;
4035}
4036
4055{
4057 qreal newScale = factor;
4058
4060 // Notify the item that the scale is changing.
4061 const QVariant newScaleVariant(itemChange(ItemScaleChange, factor));
4062 newScale = newScaleVariant.toReal();
4063 }
4064
4065 if (!d_ptr->transformData)
4067
4068 if (d_ptr->transformData->scale == newScale)
4069 return;
4070
4071 d_ptr->transformData->scale = newScale;
4074
4075 // Send post-notification.
4078
4079 if (d_ptr->isObject)
4080 emit static_cast<QGraphicsObject *>(this)->scaleChanged();
4081
4083}
4084
4085
4101QList<QGraphicsTransform *> QGraphicsItem::transformations() const
4102{
4103 if (!d_ptr->transformData)
4104 return QList<QGraphicsTransform *>();
4106}
4107
4128void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations)
4129{
4131 if (!d_ptr->transformData)
4134 for (int i = 0; i < transformations.size(); ++i)
4135 transformations.at(i)->d_func()->setItem(this);
4139}
4140
4157
4174
4190
4199{
4201 QPointF newOrigin = origin;
4202
4204 // Notify the item that the origin point is changing.
4205 const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange,
4206 QVariant::fromValue<QPointF>(origin)));
4207 newOrigin = newOriginVariant.toPointF();
4208 }
4209
4210 if (!d_ptr->transformData)
4212
4213 if (d_ptr->transformData->xOrigin == newOrigin.x()
4214 && d_ptr->transformData->yOrigin == newOrigin.y()) {
4215 return;
4216 }
4217
4218 d_ptr->transformData->xOrigin = newOrigin.x();
4219 d_ptr->transformData->yOrigin = newOrigin.y();
4222
4223 // Send post-notification.
4225 itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin));
4226}
4227
4263
4288{
4289 // Ensure we return the standard transform if we're not untransformable.
4290 if (!d_ptr->itemIsUntransformable()) {
4292 return d_ptr->sceneTransform * viewportTransform;
4293 }
4294
4295 // Find the topmost item that ignores view transformations.
4296 const QGraphicsItem *untransformedAncestor = this;
4297 QList<const QGraphicsItem *> parents;
4298 while (untransformedAncestor && ((untransformedAncestor->d_ptr->ancestorFlags
4300 parents.prepend(untransformedAncestor);
4301 untransformedAncestor = untransformedAncestor->parentItem();
4302 }
4303
4304 if (!untransformedAncestor) {
4305 // Assert in debug mode, continue in release.
4306 Q_ASSERT_X(untransformedAncestor, "QGraphicsItem::deviceTransform",
4307 "Invalid object structure!");
4308 return QTransform();
4309 }
4310
4311 // Determine the inherited origin. Find the parent of the topmost untransformable.
4312 // Use its scene transform to map the position of the untransformable. Then use
4313 // that viewport position as the anchoring point for the untransformable subtree.
4314 QGraphicsItem *parentOfUntransformedAncestor = untransformedAncestor->parentItem();
4315 QTransform inheritedMatrix;
4316 if (parentOfUntransformedAncestor)
4317 inheritedMatrix = parentOfUntransformedAncestor->sceneTransform();
4318 QPointF mappedPoint = (inheritedMatrix * viewportTransform).map(untransformedAncestor->pos());
4319
4320 // COMBINE
4321 QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y());
4322 if (untransformedAncestor->d_ptr->transformData)
4323 matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix);
4324
4325 // Then transform and translate all children.
4326 for (int i = 0; i < parents.size(); ++i) {
4327 const QGraphicsItem *parent = parents.at(i);
4329 }
4330
4331 return matrix;
4332}
4333
4352{
4353 // Catch simple cases first.
4354 if (other == nullptr) {
4355 qWarning("QGraphicsItem::itemTransform: null pointer passed");
4356 return QTransform();
4357 }
4358 if (other == this) {
4359 if (ok)
4360 *ok = true;
4361 return QTransform();
4362 }
4363
4364 QGraphicsItem *parent = d_ptr->parent;
4365 const QGraphicsItem *otherParent = other->d_ptr->parent;
4366
4367 // This is other's child
4368 if (parent == other) {
4369 if (ok)
4370 *ok = true;
4371 QTransform x;
4373 return x;
4374 }
4375
4376 // This is other's parent
4377 if (otherParent == this) {
4378 const QPointF &otherPos = other->d_ptr->pos;
4379 if (other->d_ptr->transformData) {
4380 QTransform otherToParent;
4381 other->d_ptr->combineTransformFromParent(&otherToParent);
4382 return otherToParent.inverted(ok);
4383 }
4384 if (ok)
4385 *ok = true;
4386 return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
4387 }
4388
4389 // Siblings
4390 if (parent == otherParent) {
4391 // COMBINE
4392 const QPointF &itemPos = d_ptr->pos;
4393 const QPointF &otherPos = other->d_ptr->pos;
4394 if (!d_ptr->transformData && !other->d_ptr->transformData) {
4395 QPointF delta = itemPos - otherPos;
4396 if (ok)
4397 *ok = true;
4398 return QTransform::fromTranslate(delta.x(), delta.y());
4399 }
4400
4401 QTransform itemToParent;
4402 d_ptr->combineTransformFromParent(&itemToParent);
4403 QTransform otherToParent;
4404 other->d_ptr->combineTransformFromParent(&otherToParent);
4405 return itemToParent * otherToParent.inverted(ok);
4406 }
4407
4408 // Find the closest common ancestor. If the two items don't share an
4409 // ancestor, then the only way is to combine their scene transforms.
4410 const QGraphicsItem *commonAncestor = commonAncestorItem(other);
4411 if (!commonAncestor) {
4413 other->d_ptr->ensureSceneTransform();
4414 return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok);
4415 }
4416
4417 // If the two items are cousins (in sibling branches), map both to the
4418 // common ancestor, and combine the two transforms.
4419 bool cousins = other != commonAncestor && this != commonAncestor;
4420 if (cousins) {
4421 bool good = false;
4422 QTransform thisToScene = itemTransform(commonAncestor, &good);
4423 QTransform otherToScene(Qt::Uninitialized);
4424 if (good)
4425 otherToScene = other->itemTransform(commonAncestor, &good);
4426 if (!good) {
4427 if (ok)
4428 *ok = false;
4429 return QTransform();
4430 }
4431 return thisToScene * otherToScene.inverted(ok);
4432 }
4433
4434 // One is an ancestor of the other; walk the chain.
4435 bool parentOfOther = isAncestorOf(other);
4436 const QGraphicsItem *child = parentOfOther ? other : this;
4437 const QGraphicsItem *root = parentOfOther ? this : other;
4438
4439 QTransform x;
4440 const QGraphicsItem *p = child;
4441 do {
4442 p->d_ptr.data()->combineTransformToParent(&x);
4443 } while ((p = p->d_ptr->parent) && p != root);
4444 if (parentOfOther)
4445 return x.inverted(ok);
4446 if (ok)
4447 *ok = true;
4448 return x;
4449}
4450
4473{
4474 if (!d_ptr->transformData)
4476
4477 QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix);
4478 if (d_ptr->transformData->transform == newTransform)
4479 return;
4480
4481 // Update and set the new transformation.
4483 d_ptr->setTransformHelper(newTransform);
4486 return;
4487 }
4488
4489 // Notify the item that the transformation matrix is changing.
4490 const QVariant newTransformVariant(itemChange(ItemTransformChange,
4491 QVariant::fromValue<QTransform>(newTransform)));
4492 newTransform = qvariant_cast<QTransform>(newTransformVariant);
4493 if (d_ptr->transformData->transform == newTransform)
4494 return;
4495
4496 // Update and set the new transformation.
4497 d_ptr->setTransformHelper(newTransform);
4498
4499 // Send post-notification.
4500 itemChange(ItemTransformHasChanged, newTransformVariant);
4502}
4503
4514{
4515 setTransform(QTransform(), false);
4516}
4517
4535{
4536 Q_UNUSED(phase);
4537}
4538
4548{
4549 return d_ptr->z;
4550}
4551
4567{
4568 const QVariant newZVariant(itemChange(ItemZValueChange, z));
4569 qreal newZ = newZVariant.toReal();
4570 if (newZ == d_ptr->z)
4571 return;
4572
4573 if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) {
4574 // Z Value has changed, we have to notify the index.
4575 d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ);
4576 }
4577
4578 d_ptr->z = newZ;
4579 if (d_ptr->parent)
4581 else if (d_ptr->scene)
4582 d_ptr->scene->d_func()->needSortTopLevelItems = 1;
4583
4584 if (d_ptr->scene)
4585 d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
4586
4587 itemChange(ItemZValueHasChanged, newZVariant);
4588
4591
4592 if (d_ptr->isObject)
4593 emit static_cast<QGraphicsObject *>(this)->zChanged();
4594}
4595
4606{
4607 if (!sequentialOrdering) {
4608 std::sort(children.begin(), children.end(), insertionOrder);
4610 needSortChildren = 1;
4611 }
4612 if (holesInSiblingIndex) {
4614 for (int i = 0; i < children.size(); ++i)
4615 children[i]->d_ptr->siblingIndex = i;
4616 }
4617}
4618
4623{
4624 Q_Q(QGraphicsItem);
4625 if (scene) {
4627 q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos());
4628 if (scenePosDescendants) {
4629 for (QGraphicsItem *item : std::as_const(scene->d_func()->scenePosItems)) {
4630 if (q->isAncestorOf(item))
4632 }
4633 }
4634 }
4635}
4636
4654{
4655 if (sibling == this)
4656 return;
4657 if (!sibling || d_ptr->parent != sibling->parentItem()) {
4658 qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
4659 return;
4660 }
4661 QList<QGraphicsItem *> *siblings = d_ptr->parent
4663 : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : nullptr);
4664 if (!siblings) {
4665 qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
4666 return;
4667 }
4668
4669 // First, make sure that the sibling indexes have no holes. This also
4670 // marks the children list for sorting.
4671 if (d_ptr->parent)
4673 else
4674 d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes();
4675
4676 // Only move items with the same Z value, and that need moving.
4677 int siblingIndex = sibling->d_ptr->siblingIndex;
4678 int myIndex = d_ptr->siblingIndex;
4679 if (myIndex >= siblingIndex) {
4680 siblings->move(myIndex, siblingIndex);
4681 // Fixup the insertion ordering.
4682 for (int i = 0; i < siblings->size(); ++i) {
4683 int &index = siblings->at(i)->d_ptr->siblingIndex;
4684 if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
4685 ++index;
4686 }
4687 d_ptr->siblingIndex = siblingIndex;
4688 for (int i = 0; i < siblings->size(); ++i) {
4689 int &index = siblings->at(i)->d_ptr->siblingIndex;
4690 if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
4691 siblings->at(i)->d_ptr->siblingOrderChange();
4692 }
4694 }
4695}
4696
4724
4765{
4766 // Find translate-only offset
4767 // COMBINE
4769 const QGraphicsItem *parentItem = this;
4770 const QGraphicsItemPrivate *itemd;
4771 do {
4772 itemd = parentItem->d_ptr.data();
4773 if (itemd->transformData)
4774 break;
4775 offset += itemd->pos;
4776 } while ((parentItem = itemd->parent));
4777
4778 QRectF br = boundingRect();
4779 br.translate(offset);
4780 if (!parentItem)
4781 return br;
4784 return br;
4785 }
4787}
4788
4812{
4814 path.addRect(boundingRect());
4815 return path;
4816}
4817
4829{
4830 Q_D(const QGraphicsItem);
4831 return (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
4832 || (d->flags & QGraphicsItem::ItemClipsToShape);
4833}
4834
4856{
4857 Q_D(const QGraphicsItem);
4858 if (!isClipped())
4859 return QPainterPath();
4860
4861 const QRectF thisBoundingRect(boundingRect());
4862 if (thisBoundingRect.isEmpty())
4863 return QPainterPath();
4864
4865 QPainterPath clip;
4866 // Start with the item's bounding rect.
4867 clip.addRect(thisBoundingRect);
4868
4869 if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
4870 const QGraphicsItem *parent = this;
4871 const QGraphicsItem *lastParent = this;
4872
4873 // Intersect any in-between clips starting at the top and moving downwards.
4874 while ((parent = parent->d_ptr->parent)) {
4875 if (parent->d_ptr->flags & ItemClipsChildrenToShape) {
4876 // Map clip to the current parent and intersect with its shape/clipPath
4877 clip = lastParent->itemTransform(parent).map(clip);
4878 clip = clip.intersected(parent->shape());
4879 if (clip.isEmpty())
4880 return clip;
4881 lastParent = parent;
4882 }
4883
4885 break;
4886 }
4887
4888 if (lastParent != this) {
4889 // Map clip back to the item's transform.
4890 // ### what if itemtransform fails
4891 clip = lastParent->itemTransform(this).map(clip);
4892 }
4893 }
4894
4895 if (d->flags & ItemClipsToShape)
4896 clip = clip.intersected(shape());
4897
4898 return clip;
4899}
4900
4913bool QGraphicsItem::contains(const QPointF &point) const
4914{
4915 return isClipped() ? clipPath().contains(point) : shape().contains(point);
4916}
4917
4948{
4949 if (other == this)
4950 return true;
4951 if (!other)
4952 return false;
4953 // The items share the same clip if their closest clipper is the same, or
4954 // if one clips the other.
4956 bool otherClips = (other->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren);
4957 if (clips || otherClips) {
4958 const QGraphicsItem *closestClipper = isAncestorOf(other) ? this : parentItem();
4959 while (closestClipper && !(closestClipper->flags() & ItemClipsChildrenToShape))
4960 closestClipper = closestClipper->parentItem();
4961 const QGraphicsItem *otherClosestClipper = other->isAncestorOf(this) ? other : other->parentItem();
4962 while (otherClosestClipper && !(otherClosestClipper->flags() & ItemClipsChildrenToShape))
4963 otherClosestClipper = otherClosestClipper->parentItem();
4964 if (closestClipper == otherClosestClipper) {
4966 bool res = collidesWithPath(mapFromItem(other, other->shape()), mode);
4968 return res;
4969 }
4970 }
4971
4972 QPainterPath otherShape = other->isClipped() ? other->clipPath() : other->shape();
4973 return collidesWithPath(mapFromItem(other, otherShape), mode);
4974}
4975
4991{
4992 if (path.isEmpty()) {
4993 // No collision with empty paths.
4994 return false;
4995 }
4996
4997 QRectF rectA(boundingRect());
4998 _q_adjustRect(&rectA);
4999 QRectF rectB(path.controlPointRect());
5000 _q_adjustRect(&rectB);
5001 if (!rectA.intersects(rectB)) {
5002 // This we can determine efficiently. If the two rects neither
5003 // intersect nor contain each other, then the two items do not collide.
5004 return false;
5005 }
5006
5007 // For further testing, we need this item's shape or bounding rect.
5008 QPainterPath thisShape;
5010 thisShape = (isClipped() && !d_ptr->localCollisionHack) ? clipPath() : shape();
5011 else
5012 thisShape.addRect(rectA);
5013
5014 if (thisShape == QPainterPath()) {
5015 // Empty shape? No collision.
5016 return false;
5017 }
5018
5019 // Use QPainterPath boolean operations to determine the collision, O(N*logN).
5021 return path.intersects(thisShape);
5022 return path.contains(thisShape);
5023}
5024
5036{
5037 if (d_ptr->scene)
5038 return d_ptr->scene->collidingItems(this, mode);
5039 return QList<QGraphicsItem *>();
5040}
5041
5053 const QGraphicsItem *other,
5054 const QRectF &rect)
5055{
5056 return other->mapToItem(item, other->opaqueArea()).contains(rect);
5057}
5058
5069{
5070 Q_D(const QGraphicsItem);
5071 if (!d->scene)
5072 return false;
5073
5074 QRectF br = boundingRect();
5075 QRectF testRect = rect.isNull() ? br : rect;
5076
5077 const auto items = d->scene->items(mapToScene(br), Qt::IntersectsItemBoundingRect);
5078 for (QGraphicsItem *item : items) {
5079 if (item == this)
5080 break;
5081 if (qt_QGraphicsItem_isObscured(this, item, testRect))
5082 return true;
5083 }
5084 return false;
5085}
5086
5109{
5110 if (!item)
5111 return false;
5112 return qt_closestItemFirst(item, this)
5114}
5115
5130{
5131 return QPainterPath();
5132}
5133
5157QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) const
5158{
5159 // ### Ideally we would have a better way to generate this region,
5160 // preferably something in the lines of QPainterPath::toRegion(QTransform)
5161 // coupled with a way to generate a painter path from a set of painter
5162 // operations (e.g., QPicture::toPainterPath() or so). The current
5163 // approach generates a bitmap with the size of the item's bounding rect
5164 // in device coordinates, scaled by b.r.granularity, then paints the item
5165 // into the bitmap, converts the result to a QRegion and scales the region
5166 // back to device space with inverse granularity.
5167 qreal granularity = boundingRegionGranularity();
5168 QRect deviceRect = itemToDeviceTransform.mapRect(boundingRect()).toRect();
5170 if (granularity == 0.0)
5171 return QRegion(deviceRect);
5172
5173 int pad = 1;
5174 QSize bitmapSize(qMax(1, int(deviceRect.width() * granularity) + pad * 2),
5175 qMax(1, int(deviceRect.height() * granularity) + pad * 2));
5177 mask.fill(0);
5178 QPainter p(&mask);
5179 p.setRenderHints(QPainter::Antialiasing);
5180
5181 // Transform painter (### this code is from QGraphicsScene::drawItemHelper
5182 // and doesn't work properly with perspective transformations).
5183 QPointF viewOrigo = itemToDeviceTransform.map(QPointF(0, 0));
5184 QPointF offset = viewOrigo - deviceRect.topLeft();
5185 p.scale(granularity, granularity);
5186 p.translate(offset);
5187 p.translate(pad, pad);
5188 p.setWorldTransform(itemToDeviceTransform, true);
5189 p.translate(itemToDeviceTransform.inverted().map(QPointF(0, 0)));
5190
5191 // Render
5193 const_cast<QGraphicsItem *>(this)->paint(&p, &option, nullptr);
5194 p.end();
5195
5196 // Transform QRegion back to device space
5197 QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity);
5198 QRegion r;
5199 QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0));
5200 for (const QRect &rect : QRegion(colorMask)) {
5201 QRect xrect = unscale.mapRect(rect).translated(deviceRect.topLeft() - QPoint(pad, pad));
5202 r += xrect.adjusted(-1, -1, 1, 1) & deviceRect;
5203 }
5204 return r;
5205}
5206
5226
5247{
5248 if (granularity < 0.0 || granularity > 1.0) {
5249 qWarning("QGraphicsItem::setBoundingRegionGranularity: invalid granularity %g", granularity);
5250 return;
5251 }
5252 if (granularity == 0.0) {
5255 return;
5256 }
5259 QVariant::fromValue<qreal>(granularity));
5260}
5261
5310bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreVisibleBit, bool ignoreDirtyBit,
5311 bool ignoreOpacity) const
5312{
5313 // No scene, or if the scene is updating everything, means we have nothing
5314 // to do. The only exception is if the scene tracks the growing scene rect.
5315 return !scene
5316 || (!visible && !ignoreVisibleBit && !this->ignoreVisible)
5317 || (!ignoreDirtyBit && fullUpdatePending)
5318 || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
5319}
5320
5325{
5326 if (itemDepth == -1)
5327 const_cast<QGraphicsItemPrivate *>(this)->resolveDepth();
5328
5329 return itemDepth;
5330}
5331
5335#if QT_CONFIG(graphicseffect)
5336void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively()
5337{
5338 QGraphicsItemPrivate *itemPrivate = this;
5339 do {
5340 if (itemPrivate->graphicsEffect) {
5341 itemPrivate->notifyInvalidated = 1;
5342
5343 if (!itemPrivate->updateDueToGraphicsEffect)
5344 static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
5345 }
5346 } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : nullptr));
5347}
5348
5349void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason)
5350{
5352 return;
5353
5354 for (int i = 0; i < children.size(); ++i) {
5355 QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data();
5356 if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity))
5357 continue;
5358 if (childPrivate->graphicsEffect) {
5359 childPrivate->notifyInvalidated = 1;
5360 static_cast<QGraphicsItemEffectSourcePrivate *>(childPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
5361 }
5362
5363 childPrivate->invalidateChildGraphicsEffectsRecursively(reason);
5364 }
5365}
5366#endif // QT_CONFIG(graphicseffect)
5367
5372{
5373 if (itemDepth == -1)
5374 return;
5375
5376 itemDepth = -1;
5377 for (int i = 0; i < children.size(); ++i)
5379}
5380
5387{
5388 if (!parent)
5389 itemDepth = 0;
5390 else {
5391 if (parent->d_ptr->itemDepth == -1)
5394 }
5395}
5396
5404{
5405 // Remove all holes from the sibling index list. Now the max index
5406 // number is equal to the size of the children list.
5408 needSortChildren = 1; // ### maybe 0
5409 child->d_ptr->siblingIndex = children.size();
5411 if (isObject)
5412 emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
5413}
5414
5422{
5423 // When removing elements in the middle of the children list,
5424 // there will be a "gap" in the list of sibling indexes (0,1,3,4).
5426 holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1;
5428 children.removeAt(child->d_ptr->siblingIndex);
5429 else
5431 // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because
5432 // the child is not guaranteed to be at the index after the list is sorted.
5433 // (see ensureSortedChildren()).
5434 child->d_ptr->siblingIndex = -1;
5435 if (isObject)
5436 emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
5437}
5438
5446
5451{
5452 QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
5453 if (!c) {
5454 QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this);
5455 c = new QGraphicsItemCache;
5456 that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c));
5457 }
5458 return c;
5459}
5460
5465{
5466 QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
5467 if (c) {
5468 c->purge();
5469 delete c;
5470 }
5472}
5473
5475{
5476 if (!scene)
5477 return;
5478
5479 for (int i = 0; i < scene->d_func()->views.size(); ++i) {
5480 QGraphicsViewPrivate *viewPrivate = scene->d_func()->views.at(i)->d_func();
5481 QRect rect = paintedViewBoundingRects.value(viewPrivate->viewport);
5482 rect.translate(viewPrivate->dirtyScrollOffset);
5483 viewPrivate->updateRect(rect);
5484 }
5485
5486 if (updateChildren) {
5487 for (int i = 0; i < children.size(); ++i)
5489 }
5490}
5491
5492// Traverses all the ancestors up to the top-level and updates the pointer to
5493// always point to the top-most item that has a dirty scene transform.
5494// It then backtracks to the top-most dirty item and start calculating the
5495// scene transform by combining the item's transform (+pos) with the parent's
5496// cached scene transform (which we at this point know for sure is valid).
5498{
5499 Q_ASSERT(topMostDirtyItem);
5500
5502 *topMostDirtyItem = q_ptr;
5503
5504 if (parent)
5505 parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem);
5506
5507 if (*topMostDirtyItem == q_ptr) {
5509 return; // OK, neither my ancestors nor I have dirty scene transforms.
5510 *topMostDirtyItem = nullptr;
5511 } else if (*topMostDirtyItem) {
5512 return; // Continue backtrack.
5513 }
5514
5515 // This item and all its descendants have dirty scene transforms.
5516 // We're about to validate this item's scene transform, so we have to
5517 // invalidate all the children; otherwise there's no way for the descendants
5518 // to detect that the ancestor has changed.
5520
5521 // COMBINE my transform with the parent's scene transform.
5524}
5525
5530{
5531 // Update focus child chain. Stop at panels, or if this item
5532 // is hidden, stop at the first item with a visible parent.
5534 if (parent->panel() != q_ptr->panel())
5535 return;
5536
5537 do {
5538 // Clear any existing ancestor's subFocusItem.
5539 if (parent != q_ptr && parent->d_ptr->subFocusItem) {
5540 if (parent->d_ptr->subFocusItem == q_ptr)
5541 break;
5542 parent->d_ptr->subFocusItem->d_ptr->clearSubFocus(nullptr, stopItem);
5543 }
5546 } while (!parent->isPanel() && (parent = parent->d_ptr->parent) && (visible || !parent->d_ptr->visible));
5547
5548 if (scene && !scene->isActive()) {
5549 scene->d_func()->passiveFocusItem = subFocusItem;
5550 scene->d_func()->lastFocusItem = subFocusItem;
5551 }
5552}
5553
5558{
5559 // Reset sub focus chain.
5561 do {
5562 if (parent->d_ptr->subFocusItem != q_ptr)
5563 break;
5564 parent->d_ptr->subFocusItem = nullptr;
5565 if (parent != stopItem && !parent->isAncestorOf(stopItem))
5567 } while (!parent->isPanel() && (parent = parent->d_ptr->parent));
5568}
5569
5577{
5578 for (int i = 0; i < focusProxyRefs.size(); ++i)
5579 *focusProxyRefs.at(i) = nullptr;
5581}
5582
5592
5600{
5601 Q_UNUSED(isSubFocusItem);
5602}
5603
5613
5620{
5621 return false;
5622}
5623
5643{
5644 if (rect.isEmpty() && !rect.isNull())
5645 return;
5646
5647 // Make sure we notify effects about invalidated source.
5648#if QT_CONFIG(graphicseffect)
5649 d_ptr->invalidateParentGraphicsEffectsRecursively();
5650#endif // QT_CONFIG(graphicseffect)
5651
5652 if (CacheMode(d_ptr->cacheMode) != NoCache) {
5653 // Invalidate cache.
5655 if (!cache->allExposed) {
5656 if (rect.isNull()) {
5657 cache->allExposed = true;
5658 cache->exposed.clear();
5659 } else {
5660 cache->exposed.append(rect);
5661 }
5662 }
5663 // Only invalidate cache; item is already dirty.
5665 return;
5666 }
5667
5668 if (d_ptr->scene)
5669 d_ptr->scene->d_func()->markDirty(this, rect);
5670}
5671
5700{
5701 Q_D(QGraphicsItem);
5702 if (dx == 0.0 && dy == 0.0)
5703 return;
5704 if (!d->scene)
5705 return;
5706
5707 // Accelerated scrolling means moving pixels from one location to another
5708 // and only redraw the newly exposed area. The following requirements must
5709 // be fulfilled in order to do that:
5710 //
5711 // 1) Item is opaque.
5712 // 2) Item is not overlapped by other items.
5713 //
5714 // There's (yet) no way to detect whether an item is opaque or not, which means
5715 // we cannot do accelerated scrolling unless the cache is enabled. In case of using
5716 // DeviceCoordinate cache we also have to take the device transform into account in
5717 // order to determine whether we can do accelerated scrolling or not. That's left out
5718 // for simplicity here, but it is definitely something we can consider in the future
5719 // as a performance improvement.
5720 if (d->cacheMode != QGraphicsItem::ItemCoordinateCache
5721 || !qFuzzyIsNull(dx - int(dx)) || !qFuzzyIsNull(dy - int(dy))) {
5722 update(rect);
5723 return;
5724 }
5725
5726 QGraphicsItemCache *cache = d->extraItemCache();
5727 if (cache->allExposed || cache->fixedSize.isValid()) {
5728 // Cache is either invalidated or item is scaled (see QGraphicsItem::setCacheMode).
5729 update(rect);
5730 return;
5731 }
5732
5733 // Find pixmap in cache.
5734 QPixmap cachedPixmap;
5735 if (!QPixmapCache::find(cache->key, &cachedPixmap)) {
5736 update(rect);
5737 return;
5738 }
5739
5740 QRect scrollRect = (rect.isNull() ? boundingRect() : rect).toAlignedRect();
5741 if (!scrollRect.intersects(cache->boundingRect))
5742 return; // Nothing to scroll.
5743
5744 // Remove from cache to avoid deep copy when modifying.
5746
5747 QRegion exposed;
5748 cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed);
5749
5750 // Reinsert into cache.
5751 cache->key = QPixmapCache::insert(cachedPixmap);
5752
5753 // Translate the existing expose.
5754 for (int i = 0; i < cache->exposed.size(); ++i) {
5755 QRectF &e = cache->exposed[i];
5756 if (!rect.isNull() && !e.intersects(rect))
5757 continue;
5758 e.translate(dx, dy);
5759 }
5760
5761 // Append newly exposed areas. Note that the exposed region is currently
5762 // in pixmap coordinates, so we have to translate it to item coordinates.
5763 exposed.translate(cache->boundingRect.topLeft());
5764 for (const QRect &exposedRect : exposed)
5765 cache->exposed += exposedRect;
5766
5767 // Trigger update. This will redraw the newly exposed area and make sure
5768 // the pixmap is re-blitted in case there are overlapping items.
5769 d->scene->d_func()->markDirty(this, rect);
5770}
5771
5790{
5791 if (item)
5792 return itemTransform(item).map(point);
5793 return mapToScene(point);
5794}
5795
5813{
5814 // COMBINE
5815 if (!d_ptr->transformData)
5816 return point + d_ptr->pos;
5817 return d_ptr->transformToParent().map(point);
5818}
5819
5836{
5838 return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy());
5839 return d_ptr->sceneTransform.map(point);
5840}
5841
5860{
5861 if (item)
5862 return itemTransform(item).map(rect);
5863 return mapToScene(rect);
5864}
5865
5883{
5884 // COMBINE
5885 if (!d_ptr->transformData)
5886 return rect.translated(d_ptr->pos);
5887 return d_ptr->transformToParent().map(rect);
5888}
5889
5910
5931{
5932 if (item)
5933 return itemTransform(item).mapRect(rect);
5934 return mapRectToScene(rect);
5935}
5936
5955{
5956 // COMBINE
5957 if (!d_ptr->transformData)
5958 return rect.translated(d_ptr->pos);
5960}
5961
5985
6006{
6007 if (item)
6008 return item->itemTransform(this).mapRect(rect);
6009 return mapRectFromScene(rect);
6010}
6011
6031{
6032 // COMBINE
6033 if (!d_ptr->transformData)
6034 return rect.translated(-d_ptr->pos);
6036}
6037
6061
6079{
6080 if (item)
6081 return itemTransform(item).map(polygon);
6082 return mapToScene(polygon);
6083}
6084
6095{
6096 // COMBINE
6097 if (!d_ptr->transformData)
6098 return polygon.translated(d_ptr->pos);
6100}
6101
6115
6126{
6127 if (item)
6128 return itemTransform(item).map(path);
6129 return mapToScene(path);
6130}
6131
6142{
6143 // COMBINE
6144 if (!d_ptr->transformData)
6145 return path.translated(d_ptr->pos);
6146 return d_ptr->transformToParent().map(path);
6147}
6148
6162
6173{
6174 if (item)
6175 return item->itemTransform(this).map(point);
6176 return mapFromScene(point);
6177}
6178
6196{
6197 // COMBINE
6198 if (d_ptr->transformData)
6199 return d_ptr->transformToParent().inverted().map(point);
6200 return point - d_ptr->pos;
6201}
6202
6220{
6222 return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy());
6223 return d_ptr->sceneTransform.inverted().map(point);
6224}
6225
6245{
6246 if (item)
6247 return item->itemTransform(this).map(rect);
6248 return mapFromScene(rect);
6249}
6250
6267{
6268 // COMBINE
6269 if (!d_ptr->transformData)
6270 return rect.translated(-d_ptr->pos);
6272}
6273
6295
6313{
6314 if (item)
6315 return item->itemTransform(this).map(polygon);
6316 return mapFromScene(polygon);
6317}
6318
6327{
6328 // COMBINE
6329 if (!d_ptr->transformData)
6330 return polygon.translated(-d_ptr->pos);
6332}
6333
6347
6358{
6359 if (item)
6360 return item->itemTransform(this).map(path);
6361 return mapFromScene(path);
6362}
6363
6372{
6373 // COMBINE
6374 if (!d_ptr->transformData)
6375 return path.translated(-d_ptr->pos);
6377}
6378
6392
6400{
6401 if (!child || child == this)
6402 return false;
6403 if (child->d_ptr->depth() < d_ptr->depth())
6404 return false;
6405 const QGraphicsItem *ancestor = child;
6406 while ((ancestor = ancestor->d_ptr->parent)) {
6407 if (ancestor == this)
6408 return true;
6409 }
6410 return false;
6411}
6412
6422{
6423 if (!other)
6424 return nullptr;
6425 if (other == this)
6426 return const_cast<QGraphicsItem *>(this);
6427 const QGraphicsItem *thisw = this;
6428 const QGraphicsItem *otherw = other;
6429 int thisDepth = d_ptr->depth();
6430 int otherDepth = other->d_ptr->depth();
6431 while (thisDepth > otherDepth) {
6432 thisw = thisw->d_ptr->parent;
6433 --thisDepth;
6434 }
6435 while (otherDepth > thisDepth) {
6436 otherw = otherw->d_ptr->parent;
6437 --otherDepth;
6438 }
6439 while (thisw && thisw != otherw) {
6440 thisw = thisw->d_ptr->parent;
6441 otherw = otherw->d_ptr->parent;
6442 }
6443 return const_cast<QGraphicsItem *>(thisw);
6444}
6445
6454{
6455 Q_D(const QGraphicsItem);
6456 if (!d->scene)
6457 return false;
6458
6459 QPoint cursorPos = QCursor::pos();
6460 const auto views = d->scene->views();
6461 for (QGraphicsView *view : views) {
6462 if (contains(mapFromScene(view->mapToScene(view->mapFromGlobal(cursorPos)))))
6463 return true;
6464 }
6465 return false;
6466}
6467
6482{
6483 QGraphicsItemCustomDataStore *store = qt_dataStore();
6484 if (!store->data.contains(this))
6485 return QVariant();
6486 return store->data.value(this).value(key);
6487}
6488
6499{
6500 qt_dataStore()->data[this][key] = value;
6501}
6502
6536{
6537 return (int)UserType;
6538}
6539
6560{
6561 if (!d_ptr->scene) {
6562 qWarning("QGraphicsItem::installSceneEventFilter: event filters can only be installed"
6563 " on items in a scene.");
6564 return;
6565 }
6566 if (d_ptr->scene != filterItem->scene()) {
6567 qWarning("QGraphicsItem::installSceneEventFilter: event filters can only be installed"
6568 " on items in the same scene.");
6569 return;
6570 }
6571 d_ptr->scene->d_func()->installSceneEventFilter(this, filterItem);
6572}
6573
6580{
6581 if (!d_ptr->scene || d_ptr->scene != filterItem->scene())
6582 return;
6583 d_ptr->scene->d_func()->removeSceneEventFilter(this, filterItem);
6584}
6585
6603{
6604 Q_UNUSED(watched);
6605 Q_UNUSED(event);
6606 return false;
6607}
6608
6624{
6626 if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave
6627 || event->type() == QEvent::DragEnter || event->type() == QEvent::DragLeave) {
6628 // Hover enter and hover leave events for children are ignored;
6629 // hover move events are forwarded.
6630 return true;
6631 }
6632
6633 QGraphicsItem *handler = this;
6634 do {
6635 handler = handler->d_ptr->parent;
6636 Q_ASSERT(handler);
6638 // Forward the event to the closest parent that handles child
6639 // events, mapping existing item-local coordinates to its
6640 // coordinate system.
6641 d_ptr->remapItemPos(event, handler);
6642 handler->sceneEvent(event);
6643 return true;
6644 }
6645
6646 if (event->type() == QEvent::FocusOut) {
6647 focusOutEvent(static_cast<QFocusEvent *>(event));
6648 return true;
6649 }
6650
6651 if (!d_ptr->visible) {
6652 // Eaten
6653 return true;
6654 }
6655
6656 switch (event->type()) {
6657 case QEvent::FocusIn:
6658 focusInEvent(static_cast<QFocusEvent *>(event));
6659 break;
6662 break;
6665 break;
6668 break;
6671 break;
6674 break;
6677 break;
6680 break;
6683 break;
6686 break;
6689 break;
6692 break;
6695 break;
6697 wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event));
6698 break;
6699 case QEvent::KeyPress: {
6700 QKeyEvent *k = static_cast<QKeyEvent *>(event);
6701 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
6702 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
6703 bool res = false;
6704 if (k->key() == Qt::Key_Backtab
6705 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
6706 if (d_ptr->isWidget) {
6707 res = static_cast<QGraphicsWidget *>(this)->focusNextPrevChild(false);
6708 } else if (d_ptr->scene) {
6709 res = d_ptr->scene->focusNextPrevChild(false);
6710 }
6711 } else if (k->key() == Qt::Key_Tab) {
6712 if (d_ptr->isWidget) {
6713 res = static_cast<QGraphicsWidget *>(this)->focusNextPrevChild(true);
6714 } else if (d_ptr->scene) {
6716 }
6717 }
6718 if (!res)
6719 event->ignore();
6720 return true;
6721 }
6722 }
6723 keyPressEvent(static_cast<QKeyEvent *>(event));
6724 break;
6725 }
6726 case QEvent::KeyRelease:
6727 keyReleaseEvent(static_cast<QKeyEvent *>(event));
6728 break;
6730 inputMethodEvent(static_cast<QInputMethodEvent *>(event));
6731 break;
6734 // Propagate panel activation.
6735 if (d_ptr->scene) {
6736 for (int i = 0; i < d_ptr->children.size(); ++i) {
6738 if (child->isVisible() && !child->isPanel()) {
6739 if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents))
6741 }
6742 }
6743 }
6744 break;
6745 default:
6746 return false;
6747 }
6748
6749 return true;
6750}
6751
6774
6799{
6800 Q_D(QGraphicsItem);
6801 // binary compatibility workaround between 4.4 and 4.5
6802 if (d->isProxyWidget())
6803 static_cast<QGraphicsProxyWidget*>(this)->dragEnterEvent(event);
6804}
6805
6823{
6824 Q_D(QGraphicsItem);
6825 // binary compatibility workaround between 4.4 and 4.5
6826 if (d->isProxyWidget())
6827 static_cast<QGraphicsProxyWidget*>(this)->dragLeaveEvent(event);
6828}
6829
6850{
6851 Q_D(QGraphicsItem);
6852 // binary compatibility workaround between 4.4 and 4.5
6853 if (d->isProxyWidget())
6854 static_cast<QGraphicsProxyWidget*>(this)->dragMoveEvent(event);
6855}
6856
6872{
6873 Q_D(QGraphicsItem);
6874 // binary compatibility workaround between 4.4 and 4.5
6875 if (d->isProxyWidget())
6876 static_cast<QGraphicsProxyWidget*>(this)->dropEvent(event);
6877}
6878
6891
6903
6918
6931
6946
6960{
6961 event->ignore();
6962}
6963
6977{
6978 event->ignore();
6979}
6980
7015{
7016 if (event->button() == Qt::LeftButton && (flags() & ItemIsSelectable)) {
7017 bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0;
7018 if (!multiSelect) {
7019 if (!d_ptr->selected) {
7020 if (QGraphicsScene *scene = d_ptr->scene) {
7021 ++scene->d_func()->selectionChanging;
7023 --scene->d_func()->selectionChanging;
7024 }
7025 setSelected(true);
7026 }
7027 }
7028 } else if (!(flags() & ItemIsMovable)) {
7029 event->ignore();
7030 }
7031 if (d_ptr->isWidget) {
7032 // Qt::Popup closes when you click outside.
7033 QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
7034 if ((w->windowFlags() & Qt::Popup) == Qt::Popup) {
7035 event->accept();
7036 if (!w->rect().contains(event->pos()))
7037 w->close();
7038 }
7039 }
7040}
7041
7043{
7044 const QGraphicsItem *parent = item->parentItem();
7045 return parent && (((parent->flags() & QGraphicsItem::ItemIsMovable) && parent->isSelected()) || _qt_movableAncestorIsSelected(parent));
7046}
7047
7053
7076{
7077 if ((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) {
7078 // Determine the list of items that need to be moved.
7079 QList<QGraphicsItem *> selectedItems;
7080 QHash<QGraphicsItem *, QPointF> initialPositions;
7081 if (d_ptr->scene) {
7082 selectedItems = d_ptr->scene->selectedItems();
7083 initialPositions = d_ptr->scene->d_func()->movingItemsInitialPositions;
7084 if (initialPositions.isEmpty()) {
7085 for (QGraphicsItem *item : std::as_const(selectedItems))
7086 initialPositions[item] = item->pos();
7087 initialPositions[this] = pos();
7088 }
7089 d_ptr->scene->d_func()->movingItemsInitialPositions = initialPositions;
7090 }
7091
7092 // Find the active view.
7093 QGraphicsView *view = nullptr;
7094 if (event->widget())
7095 view = qobject_cast<QGraphicsView *>(event->widget()->parentWidget());
7096
7097 // Move all selected items
7098 int i = 0;
7099 bool movedMe = false;
7100 while (i <= selectedItems.size()) {
7101 QGraphicsItem *item = nullptr;
7102 if (i < selectedItems.size())
7103 item = selectedItems.at(i);
7104 else
7105 item = this;
7106 if (item == this) {
7107 // Slightly clumsy-looking way to ensure that "this" is part
7108 // of the list of items to move, this is to avoid allocations
7109 // (appending this item to the list of selected items causes a
7110 // detach).
7111 if (movedMe)
7112 break;
7113 movedMe = true;
7114 }
7115
7117 QPointF currentParentPos;
7118 QPointF buttonDownParentPos;
7120 // Items whose ancestors ignore transformations need to
7121 // map screen coordinates to local coordinates, then map
7122 // those to the parent.
7123 QTransform viewToItemTransform = (item->deviceTransform(view->viewportTransform())).inverted();
7124 currentParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->screenPos()))));
7125 buttonDownParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton)))));
7126 } else if (view && (item->flags() & ItemIgnoresTransformations)) {
7127 // Root items that ignore transformations need to
7128 // calculate their diff by mapping viewport coordinates
7129 // directly to parent coordinates.
7130 // COMBINE
7132 if (item->d_ptr->transformData)
7135 QTransform viewToParentTransform = itemTransform
7136 * (item->sceneTransform() * view->viewportTransform()).inverted();
7137 currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos())));
7138 buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))));
7139 } else {
7140 // All other items simply map from the scene.
7141 currentParentPos = item->mapToParent(item->mapFromScene(event->scenePos()));
7142 buttonDownParentPos = item->mapToParent(item->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)));
7143 }
7144
7145 item->setPos(initialPositions.value(item) + currentParentPos - buttonDownParentPos);
7146
7147 if (item->flags() & ItemIsSelectable)
7148 item->setSelected(true);
7149 }
7150 ++i;
7151 }
7152
7153 } else {
7154 event->ignore();
7155 }
7156}
7157
7178{
7179 if (event->button() == Qt::LeftButton && (flags() & ItemIsSelectable)) {
7180 bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0;
7181 if (event->scenePos() == event->buttonDownScenePos(Qt::LeftButton)) {
7182 // The item didn't move
7183 if (multiSelect) {
7185 } else {
7186 bool selectionChanged = false;
7187 if (QGraphicsScene *scene = d_ptr->scene) {
7188 ++scene->d_func()->selectionChanging;
7189 // Clear everything but this item. Bypass
7190 // QGraphicsScene::clearSelection()'s default behavior by
7191 // temporarily removing this item from the selection list.
7192 if (d_ptr->selected) {
7193 scene->d_func()->selectedItems.remove(this);
7194 for (QGraphicsItem *item : std::as_const(scene->d_func()->selectedItems)) {
7195 if (item->isSelected()) {
7196 selectionChanged = true;
7197 break;
7198 }
7199 }
7200 }
7202 if (d_ptr->selected)
7203 scene->d_func()->selectedItems.insert(this);
7204 --scene->d_func()->selectionChanging;
7205 if (selectionChanged)
7207 }
7208 setSelected(true);
7209 }
7210 }
7211 }
7212 if (d_ptr->scene && !event->buttons())
7213 d_ptr->scene->d_func()->movingItemsInitialPositions.clear();
7214}
7215
7244
7260{
7261 event->ignore();
7262}
7263
7272{
7273 event->ignore();
7274}
7275
7290
7305Qt::InputMethodHints QGraphicsItem::inputMethodHints() const
7306{
7307 Q_D(const QGraphicsItem);
7308 return d->imHints;
7309}
7310
7318void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
7319{
7320 Q_D(QGraphicsItem);
7321 d->imHints = hints;
7322 if (!hasFocus())
7323 return;
7324 d->scene->d_func()->updateInputMethodSensitivityInViews();
7326 if (!fw)
7327 return;
7329}
7330
7341
7364{
7365 Q_UNUSED(change);
7366 return value;
7367}
7368
7376{
7378 return false;
7379}
7380
7392
7400{
7402 return QVariant();
7403}
7404
7413{
7416 // ### add to child index only if applicable
7417 return;
7418 }
7419 if (d_ptr->scene)
7420 d_ptr->scene->d_func()->index->addItem(this);
7421}
7422
7431{
7434 // ### remove from child index only if applicable
7435 return;
7436 }
7437 if (d_ptr->scene)
7438 d_ptr->scene->d_func()->index->removeItem(this);
7439}
7440
7455{
7456 if (d_ptr->inDestructor)
7457 return;
7458 if (d_ptr->scene) {
7459 d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true;
7463
7464 QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
7465 scenePrivate->index->prepareBoundingRectChange(this);
7466 scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false,
7467 /*ignoreOpacity=*/ false, /*removingItemFromScene=*/ false,
7468 /*updateBoundingRect=*/true);
7469
7470 // For compatibility reasons, we have to update the item's old geometry
7471 // if someone is connected to the changed signal or the scene has no views.
7472 // Note that this has to be done *after* markDirty to ensure that
7473 // _q_processDirtyItems is called before _q_emitUpdated.
7474 if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex)
7475 || scenePrivate->views.isEmpty()) {
7478 d_ptr->sceneTransform.dy()));
7479 } else {
7481 }
7482 }
7483 }
7484
7485 d_ptr->markParentDirty(/*updateBoundingRect=*/true);
7486}
7487
7495{
7496 const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
7497 if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
7498 return;
7499
7500 const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
7501 if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0))
7502 return;
7503
7504 qreal itemPenWidth;
7505 switch (item->type()) {
7507 itemPenWidth = static_cast<QGraphicsEllipseItem *>(item)->pen().widthF();
7508 break;
7510 itemPenWidth = static_cast<QGraphicsPathItem *>(item)->pen().widthF();
7511 break;
7513 itemPenWidth = static_cast<QGraphicsPolygonItem *>(item)->pen().widthF();
7514 break;
7516 itemPenWidth = static_cast<QGraphicsRectItem *>(item)->pen().widthF();
7517 break;
7519 itemPenWidth = static_cast<QGraphicsSimpleTextItem *>(item)->pen().widthF();
7520 break;
7522 itemPenWidth = static_cast<QGraphicsLineItem *>(item)->pen().widthF();
7523 break;
7524 default:
7525 itemPenWidth = 1.0;
7526 }
7527 const qreal pad = itemPenWidth / 2;
7528
7529 const qreal penWidth = 0; // cosmetic pen
7530
7531 const QColor fgcolor = option->palette.windowText().color();
7532 const QColor bgcolor( // ensure good contrast against fgcolor
7533 fgcolor.red() > 127 ? 0 : 255,
7534 fgcolor.green() > 127 ? 0 : 255,
7535 fgcolor.blue() > 127 ? 0 : 255);
7536
7537 painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine));
7539 painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
7540
7541 painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine));
7543 painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad));
7544}
7545
7582
7587 : QGraphicsItem(dd, parent)
7588{
7590}
7591
7595QGraphicsObject::~QGraphicsObject()
7596{
7597}
7598
7603{
7604 if (ev->type() == QEvent::StyleAnimationUpdate) {
7605 if (isVisible()) {
7606 ev->accept();
7607 update();
7608 }
7609 return true;
7610 }
7611 return QObject::event(ev);
7612}
7613
7614#ifndef QT_NO_GESTURES
7620void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
7621{
7625 QGraphicsItem::d_ptr->scene->d_func()->grabGesture(this, gesture);
7626}
7627
7633void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
7634{
7635 if (QGraphicsItem::d_ptr->gestureContext.remove(gesture) && QGraphicsItem::d_ptr->scene)
7636 QGraphicsItem::d_ptr->scene->d_func()->ungrabGesture(this, gesture);
7637}
7638#endif // QT_NO_GESTURES
7639
7651
7658{
7659 return 0;
7660}
7661
7671
7680
7687{
7688 return 0;
7689}
7690
7700
7709
7950{
7951 Q_DECLARE_PUBLIC(QAbstractGraphicsShapeItem)
7952public:
7953
7956
7957 // Cached bounding rectangle
7959};
7960
7969
7977
7984
7990{
7991 Q_D(const QAbstractGraphicsShapeItem);
7992 return d->pen;
7993}
7994
8003{
8005 if (d->pen == pen)
8006 return;
8008 d->pen = pen;
8009 d->boundingRect = QRectF();
8010 update();
8011}
8012
8019{
8020 Q_D(const QAbstractGraphicsShapeItem);
8021 return d->brush;
8022}
8023
8035{
8037 if (d->brush == brush)
8038 return;
8039 d->brush = brush;
8040 update();
8041}
8042
8050
8055{
8056 Q_D(const QAbstractGraphicsShapeItem);
8057 if (d->brush.isOpaque())
8058 return isClipped() ? clipPath() : shape();
8060}
8061
8088{
8089 Q_DECLARE_PUBLIC(QGraphicsPathItem)
8090public:
8092};
8093
8101 QGraphicsItem *parent)
8103{
8104 if (!path.isEmpty())
8105 setPath(path);
8106}
8107
8118
8125
8133{
8134 Q_D(const QGraphicsPathItem);
8135 return d->path;
8136}
8137
8144{
8145 Q_D(QGraphicsPathItem);
8146 if (d->path == path)
8147 return;
8149 d->path = path;
8150 d->boundingRect = QRectF();
8151 update();
8152}
8153
8158{
8159 Q_D(const QGraphicsPathItem);
8160 if (d->boundingRect.isNull()) {
8161 qreal pw = pen().style() == Qt::NoPen ? qreal(0) : pen().widthF();
8162 if (pw == 0.0)
8163 d->boundingRect = d->path.controlPointRect();
8164 else {
8165 d->boundingRect = shape().controlPointRect();
8166 }
8167 }
8168 return d->boundingRect;
8169}
8170
8175{
8176 Q_D(const QGraphicsPathItem);
8177 return qt_graphicsItem_shapeFromPath(d->path, d->pen);
8178}
8179
8183bool QGraphicsPathItem::contains(const QPointF &point) const
8184{
8186}
8187
8203
8211
8219
8223int QGraphicsPathItem::type() const
8224{
8225 return Type;
8226}
8227
8232{
8234 return false;
8235}
8236
8245
8250{
8252 return QVariant();
8253}
8254
8288{
8289 Q_DECLARE_PUBLIC(QGraphicsRectItem)
8290public:
8292};
8293
8305
8323
8334
8341
8348{
8349 Q_D(const QGraphicsRectItem);
8350 return d->rect;
8351}
8352
8361{
8362 Q_D(QGraphicsRectItem);
8363 if (d->rect == rect)
8364 return;
8366 d->rect = rect;
8367 d->boundingRect = QRectF();
8368 update();
8369}
8370
8388{
8389 Q_D(const QGraphicsRectItem);
8390 if (d->boundingRect.isNull()) {
8391 qreal halfpw = pen().style() == Qt::NoPen ? qreal(0) : pen().widthF() / 2;
8392 d->boundingRect = d->rect;
8393 if (halfpw > 0.0)
8394 d->boundingRect.adjust(-halfpw, -halfpw, halfpw, halfpw);
8395 }
8396 return d->boundingRect;
8397}
8398
8403{
8404 Q_D(const QGraphicsRectItem);
8406 path.addRect(d->rect);
8407 return qt_graphicsItem_shapeFromPath(path, d->pen);
8408}
8409
8413bool QGraphicsRectItem::contains(const QPointF &point) const
8414{
8416}
8417
8433
8441
8449
8454{
8455 return Type;
8456}
8457
8462{
8464 return false;
8465}
8466
8475
8480{
8482 return QVariant();
8483}
8484
8518{
8519 Q_DECLARE_PUBLIC(QGraphicsEllipseItem)
8520public:
8522 : startAngle(0), spanAngle(360 * 16)
8523 { }
8524
8528};
8529
8541
8558
8559
8560
8571
8578
8585{
8586 Q_D(const QGraphicsEllipseItem);
8587 return d->rect;
8588}
8589
8599{
8601 if (d->rect == rect)
8602 return;
8604 d->rect = rect;
8605 d->boundingRect = QRectF();
8606 update();
8607}
8608
8617{
8618 Q_D(const QGraphicsEllipseItem);
8619 return d->startAngle;
8620}
8621
8630{
8632 if (angle != d->startAngle) {
8634 d->boundingRect = QRectF();
8635 d->startAngle = angle;
8636 update();
8637 }
8638}
8639
8649{
8650 Q_D(const QGraphicsEllipseItem);
8651 return d->spanAngle;
8652}
8653
8663{
8665 if (angle != d->spanAngle) {
8667 d->boundingRect = QRectF();
8668 d->spanAngle = angle;
8669 update();
8670 }
8671}
8672
8677{
8678 Q_D(const QGraphicsEllipseItem);
8679 if (d->boundingRect.isNull()) {
8680 qreal pw = pen().style() == Qt::NoPen ? qreal(0) : pen().widthF();
8681 if (pw == 0.0 && d->spanAngle == 360 * 16)
8682 d->boundingRect = d->rect;
8683 else
8684 d->boundingRect = shape().controlPointRect();
8685 }
8686 return d->boundingRect;
8687}
8688
8693{
8694 Q_D(const QGraphicsEllipseItem);
8696 if (d->rect.isNull())
8697 return path;
8698 if (d->spanAngle != 360 * 16) {
8699 path.moveTo(d->rect.center());
8700 path.arcTo(d->rect, d->startAngle / 16.0, d->spanAngle / 16.0);
8701 } else {
8702 path.addEllipse(d->rect);
8703 }
8704
8705 return qt_graphicsItem_shapeFromPath(path, d->pen);
8706}
8707
8712{
8714}
8715
8720 QWidget *widget)
8721{
8724 painter->setPen(d->pen);
8725 painter->setBrush(d->brush);
8726 if ((d->spanAngle != 0) && (qAbs(d->spanAngle) % (360 * 16) == 0))
8727 painter->drawEllipse(d->rect);
8728 else
8729 painter->drawPie(d->rect, d->startAngle, d->spanAngle);
8730
8731 if (option->state & QStyle::State_Selected)
8733}
8734
8742
8750
8755{
8756 return Type;
8757}
8758
8759
8764{
8766 return false;
8767}
8768
8777
8782{
8784 return QVariant();
8785}
8786
8813{
8814 Q_DECLARE_PUBLIC(QGraphicsPolygonItem)
8815public:
8817 : fillRule(Qt::OddEvenFill)
8818 { }
8819
8822};
8823
8835
8846
8853
8861{
8862 Q_D(const QGraphicsPolygonItem);
8863 return d->polygon;
8864}
8865
8872{
8874 if (d->polygon == polygon)
8875 return;
8877 d->polygon = polygon;
8878 d->boundingRect = QRectF();
8879 update();
8880}
8881
8889{
8890 Q_D(const QGraphicsPolygonItem);
8891 return d->fillRule;
8892}
8893
8901{
8903 if (rule != d->fillRule) {
8904 d->fillRule = rule;
8905 update();
8906 }
8907}
8908
8913{
8914 Q_D(const QGraphicsPolygonItem);
8915 if (d->boundingRect.isNull()) {
8916 qreal pw = pen().style() == Qt::NoPen ? qreal(0) : pen().widthF();
8917 if (pw == 0.0)
8918 d->boundingRect = d->polygon.boundingRect();
8919 else
8920 d->boundingRect = shape().controlPointRect();
8921 }
8922 return d->boundingRect;
8923}
8924
8929{
8930 Q_D(const QGraphicsPolygonItem);
8932 path.addPolygon(d->polygon);
8933 return qt_graphicsItem_shapeFromPath(path, d->pen);
8934}
8935
8940{
8942}
8943
8948{
8951 painter->setPen(d->pen);
8952 painter->setBrush(d->brush);
8953 painter->drawPolygon(d->polygon, d->fillRule);
8954
8955 if (option->state & QStyle::State_Selected)
8957}
8958
8966
8974
8979{
8980 return Type;
8981}
8982
8987{
8989 return false;
8990}
8991
9000
9005{
9007 return QVariant();
9008}
9009
9035{
9036 Q_DECLARE_PUBLIC(QGraphicsLineItem)
9037public:
9040};
9041
9053
9066
9067
9068
9079
9086
9094{
9095 Q_D(const QGraphicsLineItem);
9096 return d->pen;
9097}
9098
9106{
9107 Q_D(QGraphicsLineItem);
9108 if (d->pen == pen)
9109 return;
9111 d->pen = pen;
9112 update();
9113}
9114
9121{
9122 Q_D(const QGraphicsLineItem);
9123 return d->line;
9124}
9125
9132{
9133 Q_D(QGraphicsLineItem);
9134 if (d->line == line)
9135 return;
9137 d->line = line;
9138 update();
9139}
9140
9155{
9156 Q_D(const QGraphicsLineItem);
9157 if (d->pen.widthF() == 0.0) {
9158 const qreal x1 = d->line.p1().x();
9159 const qreal x2 = d->line.p2().x();
9160 const qreal y1 = d->line.p1().y();
9161 const qreal y2 = d->line.p2().y();
9162 qreal lx = qMin(x1, x2);
9163 qreal rx = qMax(x1, x2);
9164 qreal ty = qMin(y1, y2);
9165 qreal by = qMax(y1, y2);
9166 return QRectF(lx, ty, rx - lx, by - ty);
9167 }
9168 return shape().controlPointRect();
9169}
9170
9175{
9176 Q_D(const QGraphicsLineItem);
9178 if (d->line == QLineF())
9179 return path;
9180
9181 path.moveTo(d->line.p1());
9182 path.lineTo(d->line.p2());
9183 return qt_graphicsItem_shapeFromPath(path, d->pen);
9184}
9185
9189bool QGraphicsLineItem::contains(const QPointF &point) const
9190{
9191 return QGraphicsItem::contains(point);
9192}
9193
9207
9215
9223
9228{
9229 return Type;
9230}
9231
9236{
9238 return false;
9239}
9240
9249
9254{
9256 return QVariant();
9257}
9258
9313extern QPainterPath qt_regionToPath(const QRegion &region);
9314
9316{
9317 Q_DECLARE_PUBLIC(QGraphicsPixmapItem)
9318public:
9320 : transformationMode(Qt::FastTransformation),
9321 shapeMode(QGraphicsPixmapItem::MaskShape),
9323 {}
9324
9331
9333 {
9334 shape = QPainterPath();
9335 switch (shapeMode) {
9337 QBitmap mask = pixmap.mask();
9338 if (!mask.isNull()) {
9339 shape = qt_regionToPath(QRegion(mask).translated(offset.toPoint()));
9340 break;
9341 }
9342 Q_FALLTHROUGH();
9343 }
9346 break;
9348#ifndef QT_NO_IMAGE_HEURISTIC_MASK
9350#else
9352#endif
9353 break;
9354 }
9355 }
9356};
9357
9369
9380
9387
9394{
9397 d->pixmap = pixmap;
9398 d->hasShape = false;
9399 update();
9400}
9401
9409{
9410 Q_D(const QGraphicsPixmapItem);
9411 return d->pixmap;
9412}
9413
9422{
9423 Q_D(const QGraphicsPixmapItem);
9424 return d->transformationMode;
9425}
9426
9439{
9441 if (mode != d->transformationMode) {
9442 d->transformationMode = mode;
9443 update();
9444 }
9445}
9446
9454{
9455 Q_D(const QGraphicsPixmapItem);
9456 return d->offset;
9457}
9458
9466{
9468 if (d->offset == offset)
9469 return;
9471 d->offset = offset;
9472 d->hasShape = false;
9473 update();
9474}
9475
9487{
9488 Q_D(const QGraphicsPixmapItem);
9489 if (d->pixmap.isNull())
9490 return QRectF();
9491 if (d->flags & ItemIsSelectable) {
9492 qreal pw = 1.0;
9493 return QRectF(d->offset, d->pixmap.deviceIndependentSize()).adjusted(-pw/2, -pw/2, pw/2, pw/2);
9494 } else {
9495 return QRectF(d->offset, d->pixmap.deviceIndependentSize());
9496 }
9497}
9498
9503{
9504 Q_D(const QGraphicsPixmapItem);
9505 if (!d->hasShape) {
9507 thatD->updateShape();
9508 thatD->hasShape = true;
9509 }
9510 return d_func()->shape;
9511}
9512
9517{
9518 return QGraphicsItem::contains(point);
9519}
9520
9538
9546
9551{
9552 return shape();
9553}
9554
9559{
9560 return Type;
9561}
9562
9570{
9571 return d_func()->shapeMode;
9572}
9573
9581{
9583 if (d->shapeMode == mode)
9584 return;
9585 d->shapeMode = mode;
9586 d->hasShape = false;
9587}
9588
9593{
9595 return false;
9596}
9597
9606
9611{
9613 return QVariant();
9614}
9615
9682
9683
9691 : QGraphicsObject(*new QGraphicsItemPrivate, parent),
9693{
9694 dd->qq = this;
9695 if (!text.isEmpty())
9697 setAcceptDrops(true);
9700}
9701
9717
9722{
9723 delete dd;
9724}
9725
9732{
9733#ifndef QT_NO_TEXTHTMLPARSER
9734 if (dd->control)
9735 return dd->control->toHtml();
9736#endif
9737 return QString();
9738}
9739
9748{
9749 dd->textControl()->setHtml(text);
9750}
9751
9758{
9759 if (dd->control)
9760 return dd->control->toPlainText();
9761 return QString();
9762}
9763
9775
9782{
9783 if (!dd->control)
9784 return QFont();
9785 return dd->control->document()->defaultFont();
9786}
9787
9797
9802{
9804 QPalette pal = c->palette();
9805 QColor old = pal.color(QPalette::Text);
9806 pal.setColor(QPalette::Text, col);
9807 c->setPalette(pal);
9808 if (old != col)
9809 update();
9810}
9811
9819
9824{
9825 return dd->boundingRect;
9826}
9827
9832{
9833 if (!dd->control)
9834 return QPainterPath();
9836 path.addRect(dd->boundingRect);
9837 return path;
9838}
9839
9843bool QGraphicsTextItem::contains(const QPointF &point) const
9844{
9845 return dd->boundingRect.contains(point);
9846}
9847
9852 QWidget *widget)
9853{
9855 if (dd->control) {
9856 painter->save();
9857 QRectF r = option->exposedRect;
9859 r.translate(dd->controlOffset());
9860
9861 QTextDocument *doc = dd->control->document();
9862 QTextDocumentLayout *layout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout());
9863
9864 // the layout might need to expand the root frame to
9865 // the viewport if NoWrap is set
9866 if (layout)
9867 layout->setViewport(dd->boundingRect);
9868
9870
9871 if (layout)
9872 layout->setViewport(QRect());
9873
9874 painter->restore();
9875 }
9876
9879}
9880
9888
9896
9901{
9902 return Type;
9903}
9904
9925
9935{
9936 if (!dd->control)
9937 return -1;
9938 return dd->control->textWidth();
9939}
9940
9945{
9946 if (dd->control)
9947 dd->control->adjustSize();
9948}
9949
9958
9963{
9964 return dd->textControl()->document();
9965}
9966
9971{
9972 QEvent::Type t = event->type();
9973 if (!dd->tabChangesFocus && (t == QEvent::KeyPress || t == QEvent::KeyRelease)) {
9974 int k = ((QKeyEvent *)event)->key();
9975 if (k == Qt::Key_Tab || k == Qt::Key_Backtab) {
9977 return true;
9978 }
9979 }
9981
9982 // Ensure input context is updated.
9983 switch (event->type()) {
9985 case QEvent::FocusIn:
9986 case QEvent::FocusOut:
9998 case QEvent::KeyPress:
9999 case QEvent::KeyRelease:
10001 // Reset the focus widget's input context, regardless
10002 // of how this item gained or lost focus.
10003 if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) {
10005 } else {
10007 }
10008 break;
10011 return true;
10012 default:
10013 break;
10014 }
10015
10016 return result;
10017}
10018
10023{
10025 && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
10026 // User left-pressed on edge of selectable/movable item, use
10027 // base impl.
10028 dd->useDefaultImpl = true;
10029 } else if (event->buttons() == event->button()
10031 // User pressed first button on non-interactive item.
10032 dd->useDefaultImpl = true;
10033 }
10034 if (dd->useDefaultImpl) {
10036 if (!event->isAccepted())
10037 dd->useDefaultImpl = false;
10038 return;
10039 }
10040
10042}
10043
10048{
10049 if (dd->useDefaultImpl) {
10051 return;
10052 }
10053
10055}
10056
10061{
10062 if (dd->useDefaultImpl) {
10065 && !event->buttons()) {
10066 // User released last button on non-interactive item.
10067 dd->useDefaultImpl = false;
10068 } else if ((event->buttons() & Qt::LeftButton) == 0) {
10069 // User released the left button on an interactive item.
10070 dd->useDefaultImpl = false;
10071 }
10072 return;
10073 }
10074
10075 QWidget *widget = event->widget();
10077 qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus);
10078 }
10079 dd->clickCausedFocus = 0;
10081}
10082
10087{
10088 if (dd->useDefaultImpl) {
10090 return;
10091 }
10092
10093 if (!hasFocus()) {
10095 return;
10096 }
10097
10099}
10100
10108
10116
10124
10129{
10131 if (event->reason() == Qt::MouseFocusReason) {
10132 dd->clickCausedFocus = 1;
10133 }
10134 update();
10135}
10136
10145
10153
10161
10169
10177
10185
10193
10201
10209
10214{
10215 QVariant v;
10216 if (query == Qt::ImEnabled)
10217 return isEnabled();
10218 else if (query == Qt::ImHints)
10219 v = int(inputMethodHints());
10220 else if (dd->control)
10222 if (dd->control) {
10223 if (v.userType() == QMetaType::QRectF)
10224 v = v.toRectF().translated(-dd->controlOffset());
10225 else if (v.userType() == QMetaType::QPointF)
10226 v = v.toPointF() - dd->controlOffset();
10227 else if (v.userType() == QMetaType::QRect)
10228 v = v.toRect().translated(-dd->controlOffset().toPoint());
10229 else if (v.userType() == QMetaType::QPoint)
10230 v = v.toPoint() - dd->controlOffset().toPoint();
10231 }
10232 return v;
10233}
10234
10239{
10241 return false;
10242}
10243
10252
10257{
10259 return QVariant();
10260}
10261
10266{
10267 if (rect.isValid()) {
10268 rect.translate(-controlOffset());
10269 } else {
10271 }
10272 if (rect.intersects(boundingRect))
10273 qq->update(rect);
10274}
10275
10280{
10281 if (size != boundingRect.size()) {
10284 qq->update();
10285 }
10286}
10287
10292{
10293 if (qq->hasFocus()) {
10294 rect.translate(-controlOffset());
10295 qq->ensureVisible(rect, /*xmargin=*/0, /*ymargin=*/0);
10296 }
10297}
10298
10300{
10301 if (!control) {
10302 QGraphicsTextItem *that = const_cast<QGraphicsTextItem *>(qq);
10303 control = new QWidgetTextControl(that);
10305
10307 [dd = that->dd](const QRectF &rect) { dd->_q_update(rect); });
10309 [dd = that->dd](QSizeF size) { dd->_q_updateBoundingRect(size); });
10311 [dd = that->dd](const QRectF &rect) { dd->_q_ensureVisible(rect); });
10316
10317 const QSizeF pgSize = control->document()->pageSize();
10318 if (pgSize.height() != -1) {
10320 that->dd->boundingRect.setSize(pgSize);
10321 qq->update();
10322 } else {
10323 that->dd->_q_updateBoundingRect(control->size());
10324 }
10325 }
10326 return control;
10327}
10328
10333{
10335 path.addRect(qq->boundingRect());
10336
10337 QPainterPath docPath;
10339 docPath.addRect(
10341 format.leftMargin(),
10342 format.topMargin(),
10343 -format.rightMargin(),
10344 -format.bottomMargin()));
10345
10346 return path.subtracted(docPath).contains(event->pos());
10347}
10348
10389
10395Qt::TextInteractionFlags QGraphicsTextItem::textInteractionFlags() const
10396{
10397 if (!dd->control)
10398 return Qt::NoTextInteraction;
10399 return dd->control->textInteractionFlags();
10400}
10401
10415{
10416 dd->tabChangesFocus = b;
10417}
10418
10430{
10431 return dd->tabChangesFocus;
10432}
10433
10447
10449{
10450 if (!dd->control)
10451 return false;
10452 return dd->control->openExternalLinks();
10453}
10454
10469
10471{
10472 if (!dd->control)
10473 return QTextCursor();
10474 return dd->control->textCursor();
10475}
10476
10491
10493{
10494 layout->setCacheEnabled(true);
10495 layout->beginLayout();
10496 while (layout->createLine().isValid())
10497 ;
10498 layout->endLayout();
10499 qreal maxWidth = 0;
10500 qreal y = 0;
10501 for (int i = 0; i < layout->lineCount(); ++i) {
10502 QTextLine line = layout->lineAt(i);
10503 maxWidth = qMax(maxWidth, line.naturalTextWidth());
10504 line.setPosition(QPointF(0, y));
10505 y += line.height();
10506 }
10507 return QRectF(0, 0, maxWidth, y);
10508}
10509
10511{
10513 QRectF br;
10514 if (text.isEmpty()) {
10515 br = QRectF();
10516 } else {
10517 QString tmp = text;
10518 tmp.replace(u'\n', QChar::LineSeparator);
10521 br = setupTextLayout(&layout);
10522 }
10523 if (br != boundingRect) {
10524 q->prepareGeometryChange();
10525 boundingRect = br;
10526 q->update();
10527 }
10528}
10529
10574
10587
10594
10602{
10604 if (d->text == text)
10605 return;
10606 d->text = text;
10607 d->updateBoundingRect();
10608 update();
10609}
10610
10615{
10616 Q_D(const QGraphicsSimpleTextItem);
10617 return d->text;
10618}
10619
10624{
10626 d->font = font;
10627 d->updateBoundingRect();
10628}
10629
10634{
10635 Q_D(const QGraphicsSimpleTextItem);
10636 return d->font;
10637}
10638
10643{
10644 Q_D(const QGraphicsSimpleTextItem);
10645 return d->boundingRect;
10646}
10647
10652{
10653 Q_D(const QGraphicsSimpleTextItem);
10655 path.addRect(d->boundingRect);
10656 return path;
10657}
10658
10663{
10664 Q_D(const QGraphicsSimpleTextItem);
10665 return d->boundingRect.contains(point);
10666}
10667
10672{
10675
10676 painter->setFont(d->font);
10677
10678 QString tmp = d->text;
10679 tmp.replace(u'\n', QChar::LineSeparator);
10680 QStackTextEngine engine(tmp, d->font);
10682
10683 QPen p;
10684 p.setBrush(d->brush);
10685 painter->setPen(p);
10686 if (d->pen.style() == Qt::NoPen && d->brush.style() == Qt::SolidPattern) {
10688 } else {
10690 range.start = 0;
10691 range.length = layout.text().size();
10692 range.format.setTextOutline(d->pen);
10693 layout.setFormats(QList<QTextLayout::FormatRange>(1, range));
10694 }
10695
10697 layout.draw(painter, QPointF(0, 0));
10698
10701}
10702
10710
10718
10723{
10724 return Type;
10725}
10726
10731{
10733 return false;
10734}
10735
10744
10749{
10751 return QVariant();
10752}
10753
10818
10830
10837
10846{
10847 Q_D(QGraphicsItemGroup);
10848 if (!item) {
10849 qWarning("QGraphicsItemGroup::addToGroup: cannot add null item");
10850 return;
10851 }
10852 if (item == this) {
10853 qWarning("QGraphicsItemGroup::addToGroup: cannot add a group to itself");
10854 return;
10855 }
10856
10857 // COMBINE
10858 bool ok;
10860
10861 if (!ok) {
10862 qWarning("QGraphicsItemGroup::addToGroup: could not find a valid transformation from item to group coordinates");
10863 return;
10864 }
10865
10866 QTransform newItemTransform(itemTransform);
10867 item->setPos(mapFromItem(item, 0, 0));
10868 item->setParentItem(this);
10869
10870 // removing position from translation component of the new transform
10871 if (!item->pos().isNull())
10872 newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
10873
10874 // removing additional transformations properties applied with itemTransform()
10875 QPointF origin = item->transformOriginPoint();
10876 QMatrix4x4 m;
10877 QList<QGraphicsTransform*> transformList = item->transformations();
10878 for (int i = 0; i < transformList.size(); ++i)
10879 transformList.at(i)->applyTo(&m);
10880 newItemTransform *= m.toTransform().inverted();
10881 newItemTransform.translate(origin.x(), origin.y());
10882 newItemTransform.rotate(-item->rotation());
10883 newItemTransform.scale(1/item->scale(), 1/item->scale());
10884 newItemTransform.translate(-origin.x(), -origin.y());
10885
10886 // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
10887
10888 item->setTransform(newItemTransform);
10889 item->d_func()->setIsMemberOfGroup(true);
10891 d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect());
10892 update();
10893}
10894
10904{
10905 Q_D(QGraphicsItemGroup);
10906 if (!item) {
10907 qWarning("QGraphicsItemGroup::removeFromGroup: cannot remove null item");
10908 return;
10909 }
10910
10911 QGraphicsItem *newParent = d_ptr->parent;
10912
10913 // COMBINE
10914 bool ok;
10916 if (newParent)
10917 itemTransform = item->itemTransform(newParent, &ok);
10918 else
10920
10921 QPointF oldPos = item->mapToItem(newParent, 0, 0);
10922 item->setParentItem(newParent);
10923 item->setPos(oldPos);
10924
10925 // removing position from translation component of the new transform
10926 if (!item->pos().isNull())
10928
10929 // removing additional transformations properties applied
10930 // with itemTransform() or sceneTransform()
10931 QPointF origin = item->transformOriginPoint();
10932 QMatrix4x4 m;
10933 QList<QGraphicsTransform*> transformList = item->transformations();
10934 for (int i = 0; i < transformList.size(); ++i)
10935 transformList.at(i)->applyTo(&m);
10936 itemTransform *= m.toTransform().inverted();
10937 itemTransform.translate(origin.x(), origin.y());
10939 itemTransform.scale(1 / item->scale(), 1 / item->scale());
10940 itemTransform.translate(-origin.x(), -origin.y());
10941
10942 // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
10943
10945 item->d_func()->setIsMemberOfGroup(item->group() != nullptr);
10946
10947 // ### Quite expensive. But removeFromGroup() isn't called very often.
10949 d->itemsBoundingRect = childrenBoundingRect();
10950}
10951
10958{
10959 Q_D(const QGraphicsItemGroup);
10960 return d->itemsBoundingRect;
10961}
10962
10967 QWidget *widget)
10968{
10970 if (option->state & QStyle::State_Selected) {
10971 Q_D(QGraphicsItemGroup);
10973 painter->drawRect(d->itemsBoundingRect);
10974 }
10975}
10976
10984
10992
10997{
10998 return Type;
10999}
11000
11001#if QT_CONFIG(graphicseffect)
11002QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
11003{
11004 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
11005 if (!info && deviceCoordinates) {
11006 // Device coordinates without info not yet supported.
11007 qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
11008 return QRectF();
11009 }
11010
11012 if (!item->d_ptr->children.isEmpty())
11014
11015 if (deviceCoordinates) {
11016 Q_ASSERT(info->painter);
11017 rect = info->painter->worldTransform().mapRect(rect);
11018 }
11019
11020 return rect;
11021}
11022
11023void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
11024{
11025 if (!info) {
11026 qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
11027 return;
11028 }
11029
11031 QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
11032 if (painter == info->painter) {
11033 scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
11034 info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform,
11035 info->drawItem);
11036 } else {
11037 QTransform effectTransform = info->painter->worldTransform().inverted();
11038 effectTransform *= painter->worldTransform();
11039 scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
11040 info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
11041 info->drawItem);
11042 }
11043}
11044
11045// sourceRect must be in the given coordinate system
11046QRectF QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
11047{
11048 QRectF effectRectF;
11049
11050 if (unpadded)
11051 *unpadded = false;
11052
11054 if (info) {
11055 QRectF deviceRect = system == Qt::DeviceCoordinates ? sourceRect : info->painter->worldTransform().mapRect(sourceRect);
11056 effectRectF = item->graphicsEffect()->boundingRectFor(deviceRect);
11057 if (unpadded)
11058 *unpadded = (effectRectF.size() == sourceRect.size());
11059 if (info && system == Qt::LogicalCoordinates)
11060 effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF);
11061 } else {
11062 // no choice but to send a logical coordinate bounding rect to boundingRectFor
11063 effectRectF = item->graphicsEffect()->boundingRectFor(sourceRect);
11064 }
11066 // adjust by 1.5 to account for cosmetic pens
11067 effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5);
11068 } else {
11069 effectRectF = sourceRect;
11070 if (unpadded)
11071 *unpadded = true;
11072 }
11073
11074 return effectRectF;
11075}
11076
11077QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
11079{
11080 const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
11081 if (!info && deviceCoordinates) {
11082 // Device coordinates without info not yet supported.
11083 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
11084 return QPixmap();
11085 }
11086 if (!item->d_ptr->scene)
11087 return QPixmap();
11088 QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
11089
11090 bool unpadded;
11091 const QRectF sourceRect = boundingRect(system);
11092 QRectF effectRectF = paddedEffectRect(system, mode, sourceRect, &unpadded);
11093 QRect effectRect = effectRectF.toAlignedRect();
11094
11095 if (offset)
11096 *offset = effectRect.topLeft();
11097
11098 bool untransformed = !deviceCoordinates
11099 || info->painter->worldTransform().type() <= QTransform::TxTranslate;
11100 if (untransformed && unpadded && isPixmap()) {
11101 if (offset)
11102 *offset = boundingRect(system).topLeft().toPoint();
11103 return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
11104 }
11105
11106 if (effectRect.isEmpty())
11107 return QPixmap();
11108
11109 const auto dpr = info ? info->painter->device()->devicePixelRatio() : 1.0;
11110 QPixmap pixmap(QRectF(effectRectF.topLeft(), effectRectF.size() * dpr).toAlignedRect().size());
11111 pixmap.setDevicePixelRatio(dpr);
11112 pixmap.fill(Qt::transparent);
11113 QPainter pixmapPainter(&pixmap);
11114 pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
11115
11116 QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y());
11117 if (deviceCoordinates && info->effectTransform)
11118 effectTransform *= *info->effectTransform;
11119
11120 if (!info) {
11121 // Logical coordinates without info.
11123 QTransform newEffectTransform = sceneTransform.inverted();
11124 newEffectTransform *= effectTransform;
11125 scened->draw(item, &pixmapPainter, nullptr, &sceneTransform, nullptr, nullptr, qreal(1.0),
11126 &newEffectTransform, false, true);
11127 } else if (deviceCoordinates) {
11128 // Device coordinates with info.
11129 scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, nullptr,
11130 info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
11131 info->drawItem);
11132 } else {
11133 // Item coordinates with info.
11134 QTransform newEffectTransform = info->transformPtr->inverted();
11135 newEffectTransform *= effectTransform;
11136 scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, nullptr,
11137 info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
11138 info->drawItem);
11139 }
11140
11141 pixmapPainter.end();
11142
11143 return pixmap;
11144}
11145#endif // QT_CONFIG(graphicseffect)
11146
11147#ifndef QT_NO_DEBUG_STREAM
11149{
11150 if (const QGraphicsItem *parent = item->parentItem())
11151 debug << ", parent=" << static_cast<const void *>(parent);
11152 debug << ", pos=";
11154 if (const qreal z = item->zValue())
11155 debug << ", z=" << z;
11156 if (item->flags())
11157 debug << ", flags=" << item->flags();
11158}
11159
11161{
11162 QDebugStateSaver saver(debug);
11163 debug.nospace();
11164
11165 if (!item) {
11166 debug << "QGraphicsItem(0)";
11167 return debug;
11168 }
11169
11170 if (const QGraphicsObject *o = item->toGraphicsObject())
11171 debug << o->metaObject()->className();
11172 else
11173 debug << "QGraphicsItem";
11174 debug << '(' << static_cast<const void *>(item);
11175 if (const QGraphicsProxyWidget *pw = qgraphicsitem_cast<const QGraphicsProxyWidget *>(item)) {
11176 debug << ", widget=";
11177 if (const QWidget *w = pw->widget()) {
11178 debug << w->metaObject()->className() << '(' << static_cast<const void *>(w);
11179 if (!w->objectName().isEmpty())
11180 debug << ", name=" << w->objectName();
11181 debug << ')';
11182 } else {
11183 debug << "QWidget(0)";
11184 }
11185 }
11187 debug << ')';
11188 return debug;
11189}
11190
11192{
11193 QDebugStateSaver saver(debug);
11194 debug.nospace();
11195
11196 if (!item) {
11197 debug << "QGraphicsObject(0)";
11198 return debug;
11199 }
11200
11201 debug << item->metaObject()->className() << '(' << static_cast<const void *>(item);
11202 if (!item->objectName().isEmpty())
11203 debug << ", name=" << item->objectName();
11205 debug << ')';
11206 return debug;
11207}
11208
11210{
11211 const char *str = "UnknownChange";
11212 switch (change) {
11214 str = "ItemChildAddedChange";
11215 break;
11217 str = "ItemChildRemovedChange";
11218 break;
11220 str = "ItemCursorChange";
11221 break;
11223 str = "ItemCursorHasChanged";
11224 break;
11226 str = "ItemEnabledChange";
11227 break;
11229 str = "ItemEnabledHasChanged";
11230 break;
11232 str = "ItemFlagsChange";
11233 break;
11235 str = "ItemFlagsHaveChanged";
11236 break;
11238 str = "ItemParentChange";
11239 break;
11241 str = "ItemParentHasChanged";
11242 break;
11244 str = "ItemPositionChange";
11245 break;
11247 str = "ItemPositionHasChanged";
11248 break;
11250 str = "ItemSceneChange";
11251 break;
11253 str = "ItemSceneHasChanged";
11254 break;
11256 str = "ItemSelectedChange";
11257 break;
11259 str = "ItemSelectedHasChanged";
11260 break;
11262 str = "ItemToolTipChange";
11263 break;
11265 str = "ItemToolTipHasChanged";
11266 break;
11268 str = "ItemTransformChange";
11269 break;
11271 str = "ItemTransformHasChanged";
11272 break;
11274 str = "ItemVisibleChange";
11275 break;
11277 str = "ItemVisibleHasChanged";
11278 break;
11280 str = "ItemZValueChange";
11281 break;
11283 str = "ItemZValueHasChanged";
11284 break;
11286 str = "ItemOpacityChange";
11287 break;
11289 str = "ItemOpacityHasChanged";
11290 break;
11292 str = "ItemScenePositionHasChanged";
11293 break;
11295 str = "ItemRotationChange";
11296 break;
11298 str = "ItemRotationHasChanged";
11299 break;
11301 str = "ItemScaleChange";
11302 break;
11304 str = "ItemScaleHasChanged";
11305 break;
11307 str = "ItemTransformOriginPointChange";
11308 break;
11310 str = "ItemTransformOriginPointHasChanged";
11311 break;
11312 }
11313 debug << str;
11314 return debug;
11315}
11316
11318{
11319 const char *str = "UnknownFlag";
11320 switch (flag) {
11322 str = "ItemIsMovable";
11323 break;
11325 str = "ItemIsSelectable";
11326 break;
11328 str = "ItemIsFocusable";
11329 break;
11331 str = "ItemClipsToShape";
11332 break;
11334 str = "ItemClipsChildrenToShape";
11335 break;
11337 str = "ItemIgnoresTransformations";
11338 break;
11340 str = "ItemIgnoresParentOpacity";
11341 break;
11343 str = "ItemDoesntPropagateOpacityToChildren";
11344 break;
11346 str = "ItemStacksBehindParent";
11347 break;
11349 str = "ItemUsesExtendedStyleOption";
11350 break;
11352 str = "ItemHasNoContents";
11353 break;
11355 str = "ItemSendsGeometryChanges";
11356 break;
11358 str = "ItemAcceptsInputMethod";
11359 break;
11361 str = "ItemNegativeZStacksBehindParent";
11362 break;
11364 str = "ItemIsPanel";
11365 break;
11367 str = "ItemIsFocusScope";
11368 break;
11370 str = "ItemSendsScenePositionChanges";
11371 break;
11373 str = "ItemStopsClickFocusPropagation";
11374 break;
11376 str = "ItemStopsFocusHandling";
11377 break;
11379 str = "ItemContainsChildrenInShape";
11380 break;
11381 }
11382 debug << str;
11383 return debug;
11384}
11385
11386QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
11387{
11388 debug << '(';
11389 bool f = false;
11390 for (int i = 0; i < 17; ++i) {
11391 if (flags & (1 << i)) {
11392 if (f)
11393 debug << '|';
11394 f = true;
11395 debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i)));
11396 }
11397 }
11398 debug << ')';
11399 return debug;
11400}
11401
11402#endif
11403
11405
11406#include "moc_qgraphicsitem.cpp"
static void(* destroyed)(QAbstractDeclarativeData *, QObject *)
Definition qobject_p.h:66
The QAbstractGraphicsShapeItem class provides a common base for all path items.
void setPen(const QPen &pen)
Sets the pen for this item to pen.
QPen pen() const
Returns the item's pen.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
void setBrush(const QBrush &brush)
Sets the item's brush to brush.
QBrush brush() const
Returns the item's brush, or an empty brush if no brush has been set.
QPainterPath opaqueArea() const override
\reimp
QAbstractGraphicsShapeItem(QGraphicsItem *parent=nullptr)
Constructs a QAbstractGraphicsShapeItem.
~QAbstractGraphicsShapeItem()
Destroys a QAbstractGraphicsShapeItem.
static QWidget * focusWidget()
Returns the application widget that has the keyboard input focus, or \nullptr if no widget in this ap...
\inmodule QtGui
Definition qbitmap.h:16
static QBitmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Returns a copy of the given image converted to a bitmap using the specified image conversion flags.
Definition qbitmap.cpp:170
\inmodule QtGui
Definition qbrush.h:30
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
The QCursor class provides a mouse cursor with an arbitrary shape.
Definition qcursor.h:45
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
Definition qcursor.cpp:188
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qcoreevent.h:45
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ GraphicsSceneDragLeave
Definition qcoreevent.h:200
@ GraphicsSceneMouseMove
Definition qcoreevent.h:189
@ GraphicsSceneContextMenu
Definition qcoreevent.h:193
@ GraphicsSceneMouseRelease
Definition qcoreevent.h:191
@ GraphicsSceneDragEnter
Definition qcoreevent.h:198
@ GraphicsSceneDragMove
Definition qcoreevent.h:199
@ ShortcutOverride
Definition qcoreevent.h:158
@ FocusOut
Definition qcoreevent.h:67
@ InputMethod
Definition qcoreevent.h:120
@ GraphicsSceneMousePress
Definition qcoreevent.h:190
@ DragEnter
Definition qcoreevent.h:101
@ KeyRelease
Definition qcoreevent.h:65
@ KeyPress
Definition qcoreevent.h:64
@ StyleAnimationUpdate
Definition qcoreevent.h:272
@ FocusIn
Definition qcoreevent.h:66
@ HoverLeave
Definition qcoreevent.h:176
@ HoverEnter
Definition qcoreevent.h:175
@ GraphicsSceneHoverLeave
Definition qcoreevent.h:196
@ WindowActivate
Definition qcoreevent.h:83
@ GraphicsSceneMouseDoubleClick
Definition qcoreevent.h:192
@ GraphicsSceneWheel
Definition qcoreevent.h:202
@ DragLeave
Definition qcoreevent.h:103
@ GraphicsSceneDrop
Definition qcoreevent.h:201
@ GraphicsSceneHoverEnter
Definition qcoreevent.h:194
@ GraphicsSceneHoverMove
Definition qcoreevent.h:195
@ WindowDeactivate
Definition qcoreevent.h:84
@ ContextMenu
Definition qcoreevent.h:119
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
\reentrant
Definition qfont.h:22
static QGestureManager * instance(InstanceCreation ic=ForceCreation)
The QGraphicsEffectSource class represents the source on which a QGraphicsEffect is installed on.
The QGraphicsEffect class is the base class for all graphics effects.
PixmapPadMode
This enum describes how the pixmap returned from sourcePixmap should be padded.
QGraphicsEffectSource * source() const
bool isEnabled() const
virtual QRectF boundingRectFor(const QRectF &sourceRect) const
Returns the effective bounding rectangle for this effect, given the provided rect in the device coord...
The QGraphicsEllipseItem class provides an ellipse item that you can add to a QGraphicsScene.
QRectF boundingRect() const override
\reimp
QGraphicsEllipseItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsEllipseItem.
QPainterPath opaqueArea() const override
\reimp
void setExtension(Extension extension, const QVariant &variant) override
~QGraphicsEllipseItem()
Destroys the QGraphicsEllipseItem.
QRectF rect() const
Returns the item's ellipse geometry as a QRectF.
QVariant extension(const QVariant &variant) const override
bool supportsExtension(Extension extension) const override
int spanAngle() const
Returns the span angle of an ellipse segment in 16ths of a degree.
bool contains(const QPointF &point) const override
\reimp
void setStartAngle(int angle)
Sets the start angle for an ellipse segment to angle, which is in 16ths of a degree.
int startAngle() const
Returns the start angle for an ellipse segment in 16ths of a degree.
void setSpanAngle(int angle)
Sets the span angle for an ellipse segment to angle, which is in 16ths of a degree.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
void setRect(const QRectF &rect)
Sets the item's ellipse geometry to rect.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
QPainterPath shape() const override
\reimp
int type() const override
\reimp
QList< QRectF > exposed
QHash< QPaintDevice *, DeviceData > deviceData
QHash< const QGraphicsItem *, QMap< int, QVariant > > data
The QGraphicsItemGroup class provides a container that treats a group of items as a single item.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
QPainterPath opaqueArea() const override
\reimp
QRectF boundingRect() const override
\reimp
int type() const override
\reimp
void addToGroup(QGraphicsItem *item)
Adds the given item and item's child items to this item group.
~QGraphicsItemGroup()
Destroys the QGraphicsItemGroup.
void removeFromGroup(QGraphicsItem *item)
Removes the specified item from this group.
void updateChildWithGraphicsEffectFlagRecursively()
Returns a pointer to this item's effect if it has one; otherwise \nullptr.
QGraphicsItem * subFocusItem
void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide)
void invalidateChildrenSceneTransform()
virtual void setPosHelper(const QPointF &pos)
QVariant extra(Extra type) const
QGraphicsScene * scene
static bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b)
QList< QGraphicsItem ** > focusProxyRefs
QTransform transformToParent() const
void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant, const QVariant *thisPointerVariant)
virtual void focusScopeItemChange(bool isSubFocusItem)
void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, const QRegion &exposedRegion, bool allItems=false) const
QGraphicsEffect * graphicsEffect
QGraphicsItem * focusProxy
virtual qreal height() const
void markParentDirty(bool updateBoundingRect=false)
QGraphicsItem * focusScopeItem
void setEnabledHelper(bool newEnabled, bool explicitly, bool update=true)
void setSubFocus(QGraphicsItem *rootItem=nullptr, QGraphicsItem *stopItem=nullptr)
void combineTransformToParent(QTransform *x, const QTransform *viewTransform=nullptr) const
virtual qreal width() const
QMap< Qt::GestureType, Qt::GestureFlags > gestureContext
bool itemIsUntransformable() const
quint32 mayHaveChildWithGraphicsEffect
void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag=NoFlag, bool enabled=false, bool root=true)
bool discardUpdateRequest(bool ignoreVisibleBit=false, bool ignoreDirtyBit=false, bool ignoreOpacity=false) const
void combineTransformFromParent(QTransform *x, const QTransform *viewTransform=nullptr) const
void setExtra(Extra type, const QVariant &value)
virtual void resetWidth()
QGraphicsItem::PanelModality panelModality
virtual void transformChanged()
bool childrenCombineOpacity() const
void appendGraphicsTransform(QGraphicsTransform *t)
void clearSubFocus(QGraphicsItem *rootItem=nullptr, QGraphicsItem *stopItem=nullptr)
void setTransformHelper(const QTransform &transform)
QList< QGraphicsItem * > children
void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem)
void removeChild(QGraphicsItem *child)
QRectF sceneEffectiveBoundingRect() const
void remapItemPos(QEvent *event, QGraphicsItem *item)
void clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel)
static bool movableAncestorIsSelected(const QGraphicsItem *item)
QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem=nullptr) const
void updatePaintedViewBoundingRects(bool updateChildren)
bool isFullyTransparent() const
virtual void setWidth(qreal)
QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const
virtual void updateSceneTransformFromParent()
QTransform genericMapFromSceneTransform(const QWidget *viewport=nullptr) const
virtual void siblingOrderChange()
quint32 paintedViewBoundingRectsNeedRepaint
QGraphicsItem * parent
void childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem)
virtual void subFocusItemChange()
qreal effectiveOpacity() const
QGraphicsItem * q_ptr
TransformData * transformData
QGraphicsItemCache * maybeExtraItemCache() const
void prependGraphicsTransform(QGraphicsTransform *t)
virtual void resetHeight()
QHash< QWidget *, QRect > paintedViewBoundingRects
QGraphicsItemCache * extraItemCache() const
void unsetExtra(Extra type)
void addChild(QGraphicsItem *child)
void setIsMemberOfGroup(bool enabled)
virtual bool isProxyWidget() const
void setVisibleHelper(bool newVisible, bool explicitly, bool update=true, bool hiddenByPanel=false)
virtual void setHeight(qreal)
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
virtual bool contains(const QPointF &point) const
Returns true if this item contains point, which is in local coordinates; otherwise,...
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event event, can be reimplemented to receive mouse release events for this it...
virtual QVariant extension(const QVariant &variant) const
QRectF mapRectToItem(const QGraphicsItem *item, const QRectF &rect) const
QTransform deviceTransform(const QTransform &viewportTransform) const
QTransform itemTransform(const QGraphicsItem *other, bool *ok=nullptr) const
QPointF scenePos() const
Returns the item's position in scene coordinates.
bool isWidget() const
GraphicsItemChange
This enum describes the state changes that are notified by QGraphicsItem::itemChange().
@ ItemTransformOriginPointChange
@ ItemTransformOriginPointHasChanged
virtual void wheelEvent(QGraphicsSceneWheelEvent *event)
This event handler, for event event, can be reimplemented to receive wheel events for this item.
void setSelected(bool selected)
If selected is true and this item is selectable, this item is selected; otherwise,...
bool acceptDrops() const
Returns true if this item can accept drag and drop events; otherwise, returns false.
QGraphicsWidget * topLevelWidget() const
void setData(int key, const QVariant &value)
Sets this item's custom data for the key key to value.
QPointF mapToItem(const QGraphicsItem *item, const QPointF &point) const
Maps the point point, which is in this item's coordinate system, to item's coordinate system,...
QScopedPointer< QGraphicsItemPrivate > d_ptr
qreal rotation() const
void setX(qreal x)
void ensureVisible(const QRectF &rect=QRectF(), int xmargin=50, int ymargin=50)
If this item is part of a scene that is viewed by a QGraphicsView, this convenience function will att...
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
This event handler, for event event, can be reimplemented to receive hover move events for this item.
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event event, can be reimplemented to receive mouse double-click events for th...
void setScale(qreal scale)
void update(const QRectF &rect=QRectF())
Schedules a redraw of the area covered by rect in this item.
virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented to receive drag enter events for this item.
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event event, can be reimplemented to receive mouse press events for this item...
void setTransformOriginPoint(const QPointF &origin)
QPainterPath clipPath() const
bool isObscured(const QRectF &rect=QRectF()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool handlesChildEvents() const
QGraphicsWidget * parentWidget() const
void setTransform(const QTransform &matrix, bool combine=false)
void setRotation(qreal angle)
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented to receive drop events for this item.
void setOpacity(qreal opacity)
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value)
This virtual function is called by QGraphicsItem to notify custom items that some part of the item's ...
qreal boundingRegionGranularity() const
friend class QGraphicsObject
void setPanelModality(PanelModality panelModality)
bool isWindow() const
void clearFocus()
Takes keyboard input focus from the item.
QGraphicsScene * scene() const
Returns the current scene for the item, or \nullptr if the item is not stored in a scene.
bool isSelected() const
Returns true if this item is selected; otherwise, false is returned.
void setAcceptHoverEvents(bool enabled)
virtual void setExtension(Extension extension, const QVariant &variant)
void setGroup(QGraphicsItemGroup *group)
Adds this item to the item group group.
qreal scale() const
void unsetCursor()
Clears the cursor from this item.
QPointF pos() const
Returns the position of the item in parent coordinates.
QList< QGraphicsItem * > childItems() const
void installSceneEventFilter(QGraphicsItem *filterItem)
Installs an event filter for this item on filterItem, causing all events for this item to first pass ...
qreal y() const
This convenience function is equivalent to calling pos().y().
CacheMode cacheMode() const
virtual bool collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns true if this item collides with other; otherwise returns false.
virtual QPainterPath shape() const
Returns the shape of this item as a QPainterPath in local coordinates.
GraphicsItemFlag
This enum describes different flags that you can set on an item to toggle different features in the i...
@ ItemDoesntPropagateOpacityToChildren
@ ItemContainsChildrenInShape
@ ItemNegativeZStacksBehindParent
@ ItemSendsScenePositionChanges
@ ItemStopsClickFocusPropagation
@ ItemUsesExtendedStyleOption
void setFiltersChildEvents(bool enabled)
void setZValue(qreal z)
Sets the Z-value of the item to z.
virtual void focusInEvent(QFocusEvent *event)
This event handler, for event event, can be reimplemented to receive focus in events for this item.
void stackBefore(const QGraphicsItem *sibling)
virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented to receive drag leave events for this item.
QGraphicsWidget * window() const
QRectF sceneBoundingRect() const
Returns the bounding rect of this item in scene coordinates, by combining sceneTransform() with bound...
virtual QRectF boundingRect() const =0
This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be ...
QCursor cursor() const
Returns the current cursor shape for the item.
QPointF mapFromItem(const QGraphicsItem *item, const QPointF &point) const
Maps the point point, which is in item's coordinate system, to this item's coordinate system,...
void setPos(const QPointF &pos)
Sets the position of the item to pos, which is in parent coordinates.
bool isEnabled() const
Returns true if the item is enabled; otherwise, false is returned.
bool isBlockedByModalPanel(QGraphicsItem **blockingPanel=nullptr) const
friend class QGraphicsItemEffectSourcePrivate
bool acceptHoverEvents() const
QGraphicsObject * toGraphicsObject()
QRectF mapRectToParent(const QRectF &rect) const
virtual void focusOutEvent(QFocusEvent *event)
This event handler, for event event, can be reimplemented to receive focus out events for this item.
bool hasFocus() const
Returns true if this item is active, and it or its \l{focusProxy()}{focus proxy} has keyboard input f...
QGraphicsItem * focusProxy() const
virtual void advance(int phase)
This virtual function is called twice for all items by the QGraphicsScene::advance() slot.
bool isClipped() const
Returns true if this item is clipped.
bool isUnderMouse() const
QGraphicsItemGroup * group() const
Returns a pointer to this item's item group, or \nullptr if this item is not member of a group.
friend class QGraphicsItemGroup
void setHandlesChildEvents(bool enabled)
qreal x() const
This convenience function is equivalent to calling pos().x().
bool hasCursor() const
Returns true if this item has a cursor set; otherwise, false is returned.
void setParentItem(QGraphicsItem *parent)
Sets this item's parent item to newParent.
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
This event handler, for event event, can be reimplemented to receive mouse move events for this item.
qreal zValue() const
Returns the Z-value of the item.
QGraphicsItem * topLevelItem() const
Returns this item's top-level item.
virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
This event handler, for event event, can be reimplemented to receive drag move events for this item.
QPointF mapToScene(const QPointF &point) const
Maps the point point, which is in this item's coordinate system, to the scene's coordinate system,...
QGraphicsItem * focusScopeItem() const
virtual void keyPressEvent(QKeyEvent *event)
This event handler, for event event, can be reimplemented to receive key press events for this item.
QRectF childrenBoundingRect() const
Returns the bounding rect of this item's descendants (i.e., its children, their children,...
QPointF transformOriginPoint() const
void prepareGeometryChange()
Prepares the item for a geometry change.
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
Filters events for the item watched.
Qt::MouseButtons acceptedMouseButtons() const
Returns the mouse buttons that this item accepts mouse events for.
void setFocusProxy(QGraphicsItem *item)
void setFlags(GraphicsItemFlags flags)
Sets the item flags to flags.
void setEnabled(bool enabled)
If enabled is true, the item is enabled; otherwise, it is disabled.
void setCacheMode(CacheMode mode, const QSize &cacheSize=QSize())
QVariant data(int key) const
Returns this item's custom data for the key key as a QVariant.
QList< QGraphicsTransform * > transformations() const
void setFlag(GraphicsItemFlag flag, bool enabled=true)
If enabled is true, the item flag flag is enabled; otherwise, it is disabled.
QRectF mapRectToScene(const QRectF &rect) const
qreal effectiveOpacity() const
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
This event handler can be reimplemented in a subclass to process context menu events.
void scroll(qreal dx, qreal dy, const QRectF &rect=QRectF())
bool isPanel() const
QGraphicsObject * parentObject() const
void setAcceptDrops(bool on)
If on is true, this item will accept drag and drop events; otherwise, it is transparent for drag and ...
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
This event handler, for event event, can be reimplemented to receive hover leave events for this item...
void setActive(bool active)
virtual void inputMethodEvent(QInputMethodEvent *event)
This event handler, for event event, can be reimplemented to receive input method events for this ite...
QGraphicsItem * panel() const
virtual int type() const
Returns the type of an item as an int.
QPointF mapToParent(const QPointF &point) const
Maps the point point, which is in this item's coordinate system, to its parent's coordinate system,...
bool filtersChildEvents() const
QRectF mapRectFromItem(const QGraphicsItem *item, const QRectF &rect) const
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
This method is only relevant for input items.
virtual bool isObscuredBy(const QGraphicsItem *item) const
Returns true if this item's bounding rect is completely obscured by the opaque shape of item.
void updateMicroFocus()
Updates the item's micro focus.
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *)
Returns true if item1 is on top of item2.
QRectF mapRectFromScene(const QRectF &rect) const
QTransform sceneTransform() const
QRegion boundingRegion(const QTransform &itemToDeviceTransform) const
Qt::InputMethodHints inputMethodHints() const
Returns the current input method hints of this item.
void removeSceneEventFilter(QGraphicsItem *filterItem)
Removes an event filter on this item from filterItem.
void setVisible(bool visible)
If visible is true, the item is made visible.
QPointF mapFromParent(const QPointF &point) const
Maps the point point, which is in this item's parent's coordinate system, to this item's coordinate s...
virtual ~QGraphicsItem()
Destroys the QGraphicsItem and all its children.
void setBoundingRegionGranularity(qreal granularity)
QGraphicsItem * commonAncestorItem(const QGraphicsItem *other) const
QRectF mapRectFromParent(const QRectF &rect) const
virtual bool collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns true if this item collides with path.
void setInputMethodHints(Qt::InputMethodHints hints)
Sets the current input method hints of this item to hints.
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
This event handler, for event event, can be reimplemented to receive hover enter events for this item...
void setTransformations(const QList< QGraphicsTransform * > &transformations)
bool isVisible() const
Returns true if the item is visible; otherwise, false is returned.
void setAcceptTouchEvents(bool enabled)
QGraphicsItem * focusItem() const
QGraphicsItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsItem with the given parent item.
QList< QGraphicsItem * > collidingItems(Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns a list of all items that collide with this item.
QTransform transform() const
virtual void keyReleaseEvent(QKeyEvent *event)
This event handler, for event event, can be reimplemented to receive key release events for this item...
PanelModality panelModality() const
virtual bool supportsExtension(Extension extension) const
qreal opacity() const
bool isVisibleTo(const QGraphicsItem *parent) const
void setFocus(Qt::FocusReason focusReason=Qt::OtherFocusReason)
Gives keyboard input focus to this item.
void setAcceptedMouseButtons(Qt::MouseButtons buttons)
Sets the mouse buttons that this item accepts mouse events for.
virtual QPainterPath opaqueArea() const
This virtual function returns a shape representing the area where this item is opaque.
bool isActive() const
void setCursor(const QCursor &cursor)
Sets the current cursor shape for the item to cursor.
GraphicsItemFlags flags() const
Returns this item's flags.
virtual bool sceneEvent(QEvent *event)
This virtual function receives events to this item.
void setY(qreal y)
bool acceptTouchEvents() const
QPointF mapFromScene(const QPointF &point) const
Maps the point point, which is in this item's scene's coordinate system, to this item's coordinate sy...
bool isAncestorOf(const QGraphicsItem *child) const
Returns true if this item is an ancestor of child (i.e., if this item is child's parent,...
The QGraphicsLineItem class provides a line item that you can add to a QGraphicsScene.
~QGraphicsLineItem()
Destroys the QGraphicsLineItem.
QVariant extension(const QVariant &variant) const override
bool contains(const QPointF &point) const override
\reimp
QPainterPath opaqueArea() const override
\reimp
QPainterPath shape() const override
\reimp
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
void setPen(const QPen &pen)
Sets the item's pen to pen.
void setLine(const QLineF &line)
Sets the item's line to be the given line.
QRectF boundingRect() const override
\reimp
int type() const override
\reimp
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
QPen pen() const
Returns the item's pen, or a black solid 0-width pen if no pen has been set.
QLineF line() const
Returns the item's line, or a null line if no line has been set.
bool supportsExtension(Extension extension) const override
QGraphicsLineItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsLineItem.
void setExtension(Extension extension, const QVariant &variant) override
The QGraphicsObject class provides a base class for all graphics items that require signals,...
bool event(QEvent *ev) override
\reimp
void updateMicroFocus()
Updates the item's micro focus.
void setExtension(Extension extension, const QVariant &variant) override
QPainterPath opaqueArea() const override
\reimp
QPainterPath shape() const override
\reimp
QVariant extension(const QVariant &variant) const override
void setPath(const QPainterPath &path)
Sets the item's path to be the given path.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
bool supportsExtension(Extension extension) const override
~QGraphicsPathItem()
Destroys the QGraphicsPathItem.
QPainterPath path() const
Returns the item's path as a QPainterPath.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
bool contains(const QPointF &point) const override
\reimp
QGraphicsPathItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsPath.
QRectF boundingRect() const override
\reimp
QGraphicsPixmapItem::ShapeMode shapeMode
Qt::TransformationMode transformationMode
The QGraphicsPixmapItem class provides a pixmap item that you can add to a QGraphicsScene.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
\reimp
void setExtension(Extension extension, const QVariant &variant) override
QPixmap pixmap() const
Returns the item's pixmap, or an invalid QPixmap if no pixmap has been set.
ShapeMode
This enum describes how QGraphicsPixmapItem calculates its shape and opaque area.
void setPixmap(const QPixmap &pixmap)
Sets the item's pixmap to pixmap.
QVariant extension(const QVariant &variant) const override
void setOffset(const QPointF &offset)
Sets the pixmap item's offset to offset.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
ShapeMode shapeMode() const
Returns the item's shape mode.
bool supportsExtension(Extension extension) const override
Qt::TransformationMode transformationMode() const
Returns the transformation mode of the pixmap.
void setShapeMode(ShapeMode mode)
Sets the item's shape mode to mode.
QGraphicsPixmapItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsPixmapItem.
bool contains(const QPointF &point) const override
\reimp
QPainterPath opaqueArea() const override
\reimp
void setTransformationMode(Qt::TransformationMode mode)
Sets the pixmap item's transformation mode to mode, and toggles an update of the item.
QRectF boundingRect() const override
\reimp
QPainterPath shape() const override
\reimp
int type() const override
\reimp
QPointF offset() const
Returns the pixmap item's offset, which defines the point of the top-left corner of the pixmap,...
~QGraphicsPixmapItem()
Destroys the QGraphicsPixmapItem.
The QGraphicsPolygonItem class provides a polygon item that you can add to a QGraphicsScene.
QGraphicsPolygonItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsPolygonItem.
int type() const override
\reimp
~QGraphicsPolygonItem()
Destroys the QGraphicsPolygonItem.
void setExtension(Extension extension, const QVariant &variant) override
bool supportsExtension(Extension extension) const override
void setPolygon(const QPolygonF &polygon)
Sets the item's polygon to be the given polygon.
QPainterPath shape() const override
\reimp
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
QVariant extension(const QVariant &variant) const override
QRectF boundingRect() const override
\reimp
void setFillRule(Qt::FillRule rule)
Sets the fill rule of the polygon to rule.
QPainterPath opaqueArea() const override
\reimp
QPolygonF polygon() const
Returns the item's polygon, or an empty polygon if no polygon has been set.
bool contains(const QPointF &point) const override
\reimp
Qt::FillRule fillRule() const
Returns the fill rule of the polygon.
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.
int type() const override
\reimp
bool contains(const QPointF &point) const override
\reimp
QPainterPath shape() const override
\reimp
~QGraphicsRectItem()
Destroys the QGraphicsRectItem.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
QVariant extension(const QVariant &variant) const override
QPainterPath opaqueArea() const override
\reimp
bool supportsExtension(Extension extension) const override
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=nullptr) override
\reimp
void setRect(const QRectF &rect)
Sets the item's rectangle to be the given rectangle.
QGraphicsRectItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsRectItem.
QRectF rect() const
Returns the item's rectangle.
void setExtension(Extension extension, const QVariant &variant) override
QRectF boundingRect() const override
\reimp
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...
The QGraphicsSceneHoverEvent class provides hover events in the graphics view framework.
void setPos(const QPointF &pos)
QPointF pos() const
Returns the position of the mouse cursor in item coordinates at the moment the hover event was sent.
The QGraphicsSceneMouseEvent class provides mouse events in the graphics view framework.
QPointF pos() const
Returns the mouse cursor position in item coordinates.
void setButtonDownPos(Qt::MouseButton button, const QPointF &pos)
void setLastPos(const QPointF &pos)
void setPos(const QPointF &pos)
Qt::MouseButtons buttons() const
Returns the combination of mouse buttons that were pressed at the time the event was sent.
QPointF buttonDownPos(Qt::MouseButton button) const
Returns the mouse cursor position in item coordinates where the specified button was clicked.
The QGraphicsSceneWheelEvent class provides wheel events in the graphics view framework.
void setPos(const QPointF &pos)
QPointF pos() const
Returns the position of the cursor in item coordinates when the wheel event occurred.
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.
void removeItem(QGraphicsItem *item)
Removes the item item and all its children from the scene.
void addItem(QGraphicsItem *item)
Adds or moves the item and all its children to this scene.
void clearSelection()
Clears the current selection.
void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason=Qt::OtherFocusReason)
Sets the scene's focus item to item, with the focus reason focusReason, after removing focus from any...
bool sendEvent(QGraphicsItem *item, QEvent *event)
bool isActive() const
void setActivePanel(QGraphicsItem *item)
QList< QGraphicsItem * > selectedItems() const
Returns a list of all currently selected items.
QGraphicsItem * activePanel() const
QList< QGraphicsView * > views() const
Returns a list of all the views that display this scene.
void update(qreal x, qreal y, qreal w, qreal h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void selectionChanged()
virtual bool focusNextPrevChild(bool next)
QList< QGraphicsItem * > collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns a list of all items that collide with item.
QGraphicsItem * focusItem() const
When the scene is active, this functions returns the scene's current focus item, or \nullptr if no it...
QGraphicsItem * mouseGrabberItem() const
Returns the current mouse grabber item, or \nullptr if no item is currently grabbing the mouse.
The QGraphicsSimpleTextItem class provides a simple text path item that you can add to a QGraphicsSce...
bool contains(const QPointF &point) const override
\reimp
void setExtension(Extension extension, const QVariant &variant) override
~QGraphicsSimpleTextItem()
Destroys the QGraphicsSimpleTextItem.
QPainterPath shape() const override
\reimp
QFont font() const
Returns the font that is used to draw the item's text.
QGraphicsSimpleTextItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsSimpleTextItem.
void setText(const QString &text)
Sets the item's text to text.
QVariant extension(const QVariant &variant) const override
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
\reimp
void setFont(const QFont &font)
Sets the font that is used to draw the item's text to font.
QString text() const
Returns the item's text.
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
bool supportsExtension(Extension extension) const override
int type() const override
\reimp
QPainterPath opaqueArea() const override
\reimp
QRectF boundingRect() const override
\reimp
void _q_updateBoundingRect(const QSizeF &)
QWidgetTextControl * control
bool _q_mouseOnEdge(QGraphicsSceneMouseEvent *)
QWidgetTextControl * textControl() const
void sendControlEvent(QEvent *e)
The QGraphicsTextItem class provides a text item that you can add to a QGraphicsScene to display form...
void setDocument(QTextDocument *document)
Sets the text document document on the item.
void linkHovered(const QString &)
This signal is emitted when the user hovers over a link on a text item that enables Qt::LinksAccessib...
bool contains(const QPointF &point) const override
\reimp
void adjustSize()
Adjusts the text item to a reasonable size.
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
Sets the flags flags to specify how the text item should react to user input.
QTextCursor textCursor() const
This property represents the visible text cursor in an editable text item.
void setHtml(const QString &html)
Sets the item's text to text, assuming that text is HTML formatted.
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
\reimp
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) override
\reimp
void linkActivated(const QString &)
This signal is emitted when the user clicks on a link on a text item that enables Qt::LinksAccessible...
void mousePressEvent(QGraphicsSceneMouseEvent *event) override
\reimp
bool isObscuredBy(const QGraphicsItem *item) const override
\reimp
void focusInEvent(QFocusEvent *event) override
\reimp
QVariant extension(const QVariant &variant) const override
bool openExternalLinks() const
Specifies whether QGraphicsTextItem should automatically open links using QDesktopServices::openUrl()...
QGraphicsTextItem(QGraphicsItem *parent=nullptr)
Constructs a QGraphicsTextItem.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
\reimp
void setDefaultTextColor(const QColor &c)
Sets the color for unformatted text to col.
QPainterPath opaqueArea() const override
\reimp
void setTextCursor(const QTextCursor &cursor)
void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override
\reimp
Qt::TextInteractionFlags textInteractionFlags() const
Returns the current text interaction flags.
QVariant inputMethodQuery(Qt::InputMethodQuery query) const override
\reimp
bool tabChangesFocus() const
QColor defaultTextColor() const
Returns the default text color that is used for unformatted text.
void focusOutEvent(QFocusEvent *event) override
\reimp
QRectF boundingRect() const override
\reimp
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override
\reimp
int type() const override
\reimp
void setOpenExternalLinks(bool open)
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override
\reimp
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override
\reimp
void setExtension(Extension extension, const QVariant &variant) override
void dropEvent(QGraphicsSceneDragDropEvent *event) override
\reimp
void inputMethodEvent(QInputMethodEvent *event) override
\reimp
bool sceneEvent(QEvent *event) override
\reimp
QString toHtml() const
Returns the item's text converted to HTML, or an empty QString if no text has been set.
QPainterPath shape() const override
\reimp
void setTextWidth(qreal width)
Sets the preferred width for the item's text.
QFont font() const
Returns the item's font, which is used to render the text.
void setTabChangesFocus(bool b)
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override
\reimp
QString toPlainText() const
Returns the item's text converted to plain text, or an empty QString if no text has been set.
QTextDocument * document() const
Returns the item's text document.
void keyPressEvent(QKeyEvent *event) override
\reimp
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override
\reimp
qreal textWidth() const
Returns the text width.
void keyReleaseEvent(QKeyEvent *event) override
\reimp
void setPlainText(const QString &text)
Sets the item's text to text.
bool supportsExtension(Extension extension) const override
void setFont(const QFont &font)
Sets the font used to render the text item to font.
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override
\reimp
~QGraphicsTextItem()
Destroys the QGraphicsTextItem.
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override
\reimp
The QGraphicsTransform class is an abstract base class for building advanced transformations on QGrap...
virtual void applyTo(QMatrix4x4 *matrix) const =0
This pure virtual method has to be reimplemented in derived classes.
The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene.
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.
bool close()
Call this function to close the widget.
static QInputMethod * inputMethod()
returns the input method.
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1007
T value(const Key &key) const noexcept
Definition qhash.h:1054
\inmodule QtGui
Definition qimage.h:37
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:625
The QKeyEvent class describes a key event.
Definition qevent.h:424
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1468
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
\inmodule QtCore\compares equality \compareswith equality QLine \endcompareswith
Definition qline.h:192
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
T & first()
Definition qlist.h:645
void removeAt(qsizetype i)
Definition qlist.h:590
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
bool removeOne(const AT &t)
Definition qlist.h:598
iterator end()
Definition qlist.h:626
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
void prepend(rvalue_ref t)
Definition qlist.h:473
iterator begin()
Definition qlist.h:625
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
bool contains(const Key &key) const
Definition qmap.h:341
bool isEmpty() const
Definition qmap.h:269
const_iterator constBegin() const
Definition qmap.h:600
const_iterator constEnd() const
Definition qmap.h:604
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
QScopedPointer< QObjectData > d_ptr
Definition qobject.h:373
The QPainterPathStroker class is used to generate fillable outlines for a given painter path.
void setCapStyle(Qt::PenCapStyle style)
Sets the cap style of the generated outlines to style.
void setWidth(qreal width)
Sets the width of the generated outline painter path to width.
QPainterPath createStroke(const QPainterPath &path) const
Generates a new path that is a fillable area representing the outline of the given path.
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style of the generated outlines to style.
void setMiterLimit(qreal length)
Sets the miter limit of the generated outlines to limit.
\inmodule QtGui
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
void addPath(const QPainterPath &path)
Adds the given path to this path as a closed subpath.
QRectF controlPointRect() const
Returns the rectangle containing all the points and control points in this path.
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision.
bool contains(const QPointF &pt) const
Returns true if the given point is inside the path, otherwise returns false.
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
QPainterPath intersected(const QPainterPath &r) const
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition qpainter.h:519
void drawPath(const QPainterPath &path)
Draws the given painter path using the current pen for outline and the current brush for filling.
void drawPie(const QRectF &rect, int a, int alen)
Draws a pie defined by the given rectangle, startAngle and spanAngle.
void setPen(const QColor &color)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void drawLine(const QLineF &line)
Draws a line defined by line.
Definition qpainter.h:442
void restore()
Restores the current painter state (pops a saved state off the stack).
const QTransform & worldTransform() const
Returns the world transformation matrix.
void save()
Saves the current painter state (pushes the state onto a stack).
void setFont(const QFont &f)
Sets the painter's font to the given font.
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device.
void drawEllipse(const QRectF &r)
Draws the ellipse defined by the given rectangle.
void setBrush(const QBrush &brush)
Sets the painter's brush to the given brush.
@ SmoothPixmapTransform
Definition qpainter.h:54
@ Antialiasing
Definition qpainter.h:52
bool end()
Ends painting.
const QTransform & transform() const
Alias for worldTransform().
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule=Qt::OddEvenFill)
Draws the polygon defined by the first pointCount points in the array points using the current pen an...
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
void setRenderHint(RenderHint hint, bool on=true)
Sets the given render hint on the painter if on is true; otherwise clears the render hint.
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
const QColor & color(ColorGroup cg, ColorRole cr) const
Returns the color in the specified color group, used for the given color role.
Definition qpalette.h:67
void setColor(ColorGroup cg, ColorRole cr, const QColor &color)
Sets the color in the specified color group, used for the given color role, to the specified solid co...
Definition qpalette.h:146
\inmodule QtGui
Definition qpen.h:28
qreal widthF() const
Returns the pen width with floating point precision.
Definition qpen.cpp:572
void setStyle(Qt::PenStyle)
[0]
void setBrush(const QBrush &brush)
Sets the brush used to fill strokes generated with this pen to the given brush.
Definition qpen.cpp:726
Qt::PenStyle style() const
Returns the pen style.
Definition qpen.cpp:366
The QPixmapCache::Key class can be used for efficient access to the QPixmapCache.
static bool find(const QString &key, QPixmap *pixmap)
Looks for a cached pixmap associated with the given key in the cache.
static void remove(const QString &key)
Removes the pixmap associated with key from the cache.
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
int height() const
Returns the height of the pixmap.
Definition qpixmap.cpp:480
QBitmap mask() const
Returns true if this pixmap has an alpha channel, or has a mask, otherwise returns false.
int width() const
Returns the width of the pixmap.
Definition qpixmap.cpp:468
QBitmap createHeuristicMask(bool clipTight=true) const
Creates and returns a heuristic mask for this pixmap.
Definition qpixmap.cpp:653
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
bool isNull() const noexcept
Returns true if both the x and y coordinates are set to 0.0 (ignoring the sign); otherwise returns fa...
Definition qpoint.h:338
\inmodule QtCore\reentrant
Definition qpoint.h:25
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
QRectF Q_GUI_EXPORT boundingRect() const
Returns the bounding rectangle of the polygon, or QRectF(0,0,0,0) if the polygon is empty.
Definition qpolygon.cpp:583
\inmodule QtCore\reentrant
Definition qrect.h:484
QRect toAlignedRect() const noexcept
Definition qrect.cpp:2338
constexpr QRectF translated(qreal dx, qreal dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:762
bool contains(const QRectF &r) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:1993
constexpr QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:813
bool intersects(const QRectF &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e.
Definition qrect.cpp:2271
constexpr void setSize(const QSizeF &s) noexcept
Sets the size of the rectangle to the given finite size.
Definition qrect.h:824
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:658
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:859
constexpr void translate(qreal dx, qreal dy) noexcept
Moves the rectangle dx along the x-axis and dy along the y-axis, relative to the current position.
Definition qrect.h:738
\inmodule QtCore\reentrant
Definition qrect.h:30
bool intersects(const QRect &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e., there is at least one pixel...
Definition qrect.cpp:1069
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
Definition qrect.h:245
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:261
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
void translate(int dx, int dy)
Translates (moves) the region dx along the X axis and dy along the Y axis.
QRegion translated(int dx, int dy) const
Definition qregion.cpp:593
T * data() const noexcept
Returns the value of the pointer referenced by this object.
\inmodule QtCore
Definition qsize.h:208
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:335
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3824
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
The QStyleOptionGraphicsItem class is used to describe the parameters needed to draw a QGraphicsItem.
@ State_MouseOver
Definition qstyle.h:80
@ State_Sunken
Definition qstyle.h:69
@ State_HasFocus
Definition qstyle.h:75
@ State_Enabled
Definition qstyle.h:67
@ State_Selected
Definition qstyle.h:82
@ State_None
Definition qstyle.h:66
\reentrant \inmodule QtGui
Definition qtextcursor.h:30
\reentrant \inmodule QtGui
QFont defaultFont
the default font used to display the document's text
QAbstractTextDocumentLayout * documentLayout() const
Returns the document layout for this document.
QSizeF pageSize
the page size that should be used for laying out the document
void setDefaultFont(const QFont &font)
Sets the default font to use in the document layout.
QTextFrame * rootFrame() const
Returns the document's root frame.
QTextFrameFormat frameFormat() const
Returns the frame's format.
Definition qtextobject.h:89
\reentrant
Definition qtextlayout.h:70
\reentrant
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
QTransform & rotate(qreal a, Qt::Axis axis=Qt::ZAxis, qreal distanceToPlane=1024.0f)
static QTransform fromScale(qreal dx, qreal dy)
Creates a matrix which corresponds to a scaling of sx horizontally and sy vertically.
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
qreal dx() const
Returns the horizontal translation factor.
Definition qtransform.h:235
QPoint map(const QPoint &p) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis.
QTransform inverted(bool *invertible=nullptr) const
Returns an inverted copy of this matrix.
TransformationType type() const
Returns the transformation type of this matrix.
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
QRect mapRect(const QRect &) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qreal dy() const
Returns the vertical translation factor.
Definition qtransform.h:239
\inmodule QtCore
Definition qvariant.h:65
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
void setPlainText(const QString &text)
QTextCursor textCursor() const
Qt::TextInteractionFlags textInteractionFlags
void setOpenExternalLinks(bool open)
void setHtml(const QString &text)
void setTextCursor(const QTextCursor &cursor, bool selectionClipboard=false)
void linkActivated(const QString &link)
void updateRequest(const QRectF &rect=QRectF())
void setDocument(QTextDocument *document)
void drawContents(QPainter *painter, const QRectF &rect=QRectF(), QWidget *widget=nullptr)
virtual QVariant inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
virtual void processEvent(QEvent *e, const QTransform &transform, QWidget *contextWidget=nullptr)
void documentSizeChanged(const QSizeF &)
void linkHovered(const QString &)
void visibilityRequest(const QRectF &rect)
QTextDocument * document() const
void setTextWidth(qreal width)
void setTextInteractionFlags(Qt::TextInteractionFlags flags)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
Qt::WindowType windowType() const
Returns the window type of this widget.
Definition qwidget.h:801
void extension()
[6]
Definition dialogs.cpp:230
#define this
Definition dialogs.cpp:9
QOpenGLWidget * widget
[1]
QString str
[2]
QMap< QString, QString > map
[6]
b clear()
QPixmap p2
QPainter paint
QString text
QPushButton * button
[2]
QCursor cursor
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
rect
[4]
Combined button and popup list for selecting options.
static void formatQPoint(QDebug &debug, const Point &point)
Definition qdebug_p.h:33
Definition qcompare.h:63
InputMethodQuery
@ ImHints
@ ImQueryInput
@ ImEnabled
MouseButton
Definition qnamespace.h:56
@ LeftButton
Definition qnamespace.h:58
@ TextEditable
@ NoTextInteraction
TransformationMode
@ SmoothTransformation
@ transparent
Definition qnamespace.h:47
@ SolidLine
@ DashLine
@ NoPen
@ Key_Tab
Definition qnamespace.h:664
@ Key_Backtab
Definition qnamespace.h:665
@ ShiftModifier
@ ControlModifier
@ AltModifier
ItemSelectionMode
@ IntersectsItemShape
@ ContainsItemShape
@ IntersectsItemBoundingRect
@ SolidPattern
@ NoBrush
CoordinateSystem
@ DeviceCoordinates
@ LogicalCoordinates
GestureType
constexpr Initialization Uninitialized
@ Popup
Definition qnamespace.h:211
@ Window
Definition qnamespace.h:207
FocusReason
@ MouseFocusReason
@ OtherFocusReason
Definition brush.cpp:5
#define Q_FALLTHROUGH()
DBusConnection const char * rule
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
bool qIsNaN(qfloat16 f) noexcept
Definition qfloat16.h:284
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static void formatGraphicsItemHelper(QDebug debug, const QGraphicsItem *item)
bool _qt_movableAncestorIsSelected(const QGraphicsItem *item)
static QRectF setupTextLayout(QTextLayout *layout)
static QT_BEGIN_NAMESPACE void _q_adjustRect(QRect *rect)
static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
QDebug operator<<(QDebug debug, const QGraphicsItem *item)
QPainterPath qt_regionToPath(const QRegion &region)
Definition qregion.cpp:1007
static bool qt_QGraphicsItem_isObscured(const QGraphicsItem *item, const QGraphicsItem *other, const QRectF &rect)
void Q_WIDGETS_EXPORT qt_graphicsItem_highlightSelected(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
#define qWarning
Definition qlogging.h:166
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
#define Q_ARG(Type, data)
Definition qobjectdefs.h:63
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLfloat GLfloat GLfloat x1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLfloat GLfloat f
GLsizei range
GLint GLsizei width
GLboolean GLuint group
GLfloat angle
GLbitfield flags
GLenum GLuint GLintptr offset
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
struct _cl_event * event
GLuint GLenum GLenum transform
GLenum query
GLuint res
const GLubyte * c
GLfixed GLfixed GLfixed y2
GLuint GLenum matrix
GLfixed GLfixed x2
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
GLbyte ty
GLbyte by
static const QRectF boundingRect(const QPointF *points, int pointCount)
static QT_BEGIN_NAMESPACE qreal dpr(const QWindow *w)
const QQuickItem * rootItem(const I &item)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
Q_WIDGETS_EXPORT QWidgetPrivate * qt_widget_private(QWidget *widget)
#define enabled
file open(QIODevice::ReadOnly)
QObject::connect nullptr
QVBoxLayout * layout
QVariant variant
[1]
p rx()++
QSharedPointer< T > other(t)
[5]
QGraphicsOpacityEffect * effect
the effect attached to this item
QGraphicsScene scene
[0]
rect sceneTransform().map(QPointF(0
QGraphicsItem * item
view viewport() -> scroll(dx, dy, deviceRect)
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
widget render & pixmap
QPainter painter(this)
[7]
QNetworkAccessManager manager
QHostInfo info
[0]
QQuickView * view
[0]
QJSEngine engine
[0]
QTransform computedFullTransform(QTransform *postmultiplyTransform=nullptr) const
QList< QGraphicsTransform * > graphicsTransforms
bool contains(const AT &t) const noexcept
Definition qlist.h:45
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...