📄 qgraphicsitem.cpp
字号:
this notification is delivered; instead, you can return the new scene from itemChange().*//*! \enum QGraphicsItem::Extension \internal Note: This is provided as a hook to avoid future problems related to adding virtual functions. See also extension(), supportsExtension() and setExtension().*/#include "qgraphicsitem.h"#ifndef QT_NO_GRAPHICSVIEW#include "qgraphicsscene.h"#include "qgraphicsscene_p.h"#include "qgraphicssceneevent.h"#include "qgraphicsview.h"#include <QtCore/qbitarray.h>#include <QtCore/qdebug.h>#include <QtCore/qpoint.h>#include <QtCore/qtimer.h>#include <QtCore/qvariant.h>#include <QtGui/qapplication.h>#include <QtGui/qbitmap.h>#include <QtGui/qpainter.h>#include <QtGui/qpainterpath.h>#include <QtGui/qstyleoption.h>#include <QtGui/qevent.h>#include <private/qgraphicsitem_p.h>#include <private/qtextcontrol_p.h>#include <private/qtextengine_p.h>#include <math.h>/* ### Move this into QGraphicsItemPrivate */class QGraphicsItemCustomDataStore{public: QMap<const QGraphicsItem *, QMap<int, QVariant> > data;};Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)/*! \internal Propagates updates to \a item and all its children.*/static void qt_graphicsItem_fullUpdate(QGraphicsItem *item){ item->update(); foreach (QGraphicsItem *child, item->children()) qt_graphicsItem_fullUpdate(child);}/*! \internal Returns a QPainterPath of \a path when stroked with the \a pen. Ignoring dash pattern.*/static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen){ // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 // if we pass a value of 0.0 to QPainterPathStroker::setWidth() const qreal penWidthZero = qreal(0.00000001); if (path == QPainterPath()) return path; QPainterPathStroker ps; ps.setCapStyle(pen.capStyle()); if (pen.widthF() <= 0.0) ps.setWidth(penWidthZero); else ps.setWidth(pen.widthF()); ps.setJoinStyle(pen.joinStyle()); ps.setMiterLimit(pen.miterLimit()); QPainterPath p = ps.createStroke(path); p.addPath(path); return p;}/*! \internal Propagates the ancestor flag \a flag with value \a enabled to all this item's children. If \a root is false, the flag is also set on this item (default is true).*/void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag, bool enabled, bool root){ Q_Q(QGraphicsItem); if (root) { // For root items only. This is the item that has either enabled or // disabled \a childFlag, or has been reparented. switch (int(childFlag)) { case -1: flag = AncestorHandlesChildEvents; enabled = q->handlesChildEvents(); break; case QGraphicsItem::ItemClipsChildrenToShape: flag = AncestorClipsChildren; enabled = flags & QGraphicsItem::ItemClipsChildrenToShape; break; case QGraphicsItem::ItemIgnoresTransformations: flag = AncestorIgnoresTransformations; enabled = flags & QGraphicsItem::ItemIgnoresTransformations; break; default: return; } // Inherit the enabled-state from our parents. if ((parent && ((parent->d_ptr->ancestorFlags & flag) || (int(parent->d_ptr->flags & childFlag) == childFlag) || (childFlag == -1 && parent->d_ptr->handlesChildEvents)))) { enabled = true; ancestorFlags |= flag; } // Top-level root items don't have any ancestors, so there are no // ancestor flags either. if (!parent) ancestorFlags = 0; } else { // Don't set or propagate the ancestor flag if it's already correct. if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled)) return; // Set the flag. if (enabled) ancestorFlags |= flag; else ancestorFlags &= ~flag; // Don't process children if the item has the main flag set on itself. if ((childFlag != -1 && int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents)) return; } foreach (QGraphicsItem *child, children) child->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false);}/*! \internal Propagates item group membership.*/void QGraphicsItemPrivate::setIsMemberOfGroup(bool enabled){ Q_Q(QGraphicsItem); isMemberOfGroup = enabled; if (!qgraphicsitem_cast<QGraphicsItemGroup *>(q)) { foreach (QGraphicsItem *child, children) child->d_func()->setIsMemberOfGroup(enabled); }}/*! \internal Maps any item pos properties of \a event to \a item's coordinate system.*/void QGraphicsItemPrivate::remapItemPos(QEvent *event, QGraphicsItem *item){ Q_Q(QGraphicsItem); switch (event->type()) { case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMousePress: case QEvent::GraphicsSceneMouseRelease: case QEvent::GraphicsSceneMouseDoubleClick: { QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); mouseEvent->setPos(item->mapFromItem(q, mouseEvent->pos())); mouseEvent->setLastPos(item->mapFromItem(q, mouseEvent->pos())); for (int i = 0x1; i <= 0x10; i <<= 1) { if (mouseEvent->buttons() & i) { Qt::MouseButton button = Qt::MouseButton(i); mouseEvent->setButtonDownPos(button, item->mapFromItem(q, mouseEvent->buttonDownPos(button))); } } break; } case QEvent::GraphicsSceneWheel: { QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event); wheelEvent->setPos(item->mapFromItem(q, wheelEvent->pos())); break; } case QEvent::GraphicsSceneContextMenu: { QGraphicsSceneContextMenuEvent *contextEvent = static_cast<QGraphicsSceneContextMenuEvent *>(event); contextEvent->setPos(item->mapFromItem(q, contextEvent->pos())); break; } case QEvent::GraphicsSceneHoverMove: { QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event); hoverEvent->setPos(item->mapFromItem(q, hoverEvent->pos())); break; } default: break; }}/*! \internal Maps the point \a pos from scene to item coordinates. If \a view is passed and the item is untransformable, this function will correctly map \a pos from the scene using the view's transformation.*/QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos, const QWidget *viewport) const{ Q_Q(const QGraphicsItem); if (!itemIsUntransformable()) return q->mapFromScene(pos); QGraphicsView *view = 0; if (viewport) view = qobject_cast<QGraphicsView *>(viewport->parentWidget()); if (!view) return q->mapFromScene(pos); // ### More ping pong than needed. return q->deviceTransform(view->viewportTransform()).inverted().map(view->mapFromScene(pos));}/*! \internal Returns true if this item or any of its ancestors are untransformable.*/bool QGraphicsItemPrivate::itemIsUntransformable() const{ return (flags & QGraphicsItem::ItemIgnoresTransformations) || (ancestorFlags & AncestorIgnoresTransformations);}/*! Constructs a QGraphicsItem with the given \a parent. If \a parent is 0, you can add the item to a scene by calling QGraphicsScene::addItem(). The item will then become a top-level item. \sa QGraphicsScene::addItem(), setParentItem()*/QGraphicsItem::QGraphicsItem(QGraphicsItem *parent#ifndef Q_QDOC // obsolete argument , QGraphicsScene *scene#endif ) : d_ptr(new QGraphicsItemPrivate){ d_ptr->q_ptr = this; setParentItem(parent); if (scene && parent && parent->scene() != scene) { qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is" " different from parent's scene (%p)", scene, parent->scene()); return; } if (scene && !parent) scene->addItem(this);}/*! \internal*/QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene) : d_ptr(&dd){ d_ptr->q_ptr = this; setParentItem(parent); if (scene && parent && parent->scene() != scene) { qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is" " different from parent's scene (%p)", scene, parent->scene()); return; } if (scene && !parent) scene->addItem(this);}/*! Destroys the QGraphicsItem and all its children. If this item is currently associated with a scene, the item will be removed from the scene before it is deleted.*/QGraphicsItem::~QGraphicsItem(){ QVariant variant; foreach (QGraphicsItem *child, d_ptr->children) { if (QGraphicsItem *parent = child->parentItem()) { qVariantSetValue<QGraphicsItem *>(variant, child); parent->itemChange(ItemChildRemovedChange, variant); } delete child; } d_ptr->children.clear(); if (QGraphicsItem *parent = parentItem()) { qVariantSetValue<QGraphicsItem *>(variant, this); parent->itemChange(ItemChildRemovedChange, variant); parent->d_func()->children.removeAll(this); } if (d_ptr->scene) d_ptr->scene->d_func()->_q_removeItemLater(this); delete d_ptr; qt_dataStore()->data.remove(this);}/*! Returns the current scene for the item, or 0 if the item is not stored in a scene. To add or move an item to a scene, call QGraphicsScene::addItem().*/QGraphicsScene *QGraphicsItem::scene() const{ return d_ptr->scene;}/*! Returns a pointer to this item's item group, or 0 if this item is not member of a group. \sa QGraphicsItemGroup, QGraphicsScene::createItemGroup()*/QGraphicsItemGroup *QGraphicsItem::group() const{ if (!d_ptr->isMemberOfGroup) return 0; QGraphicsItem *parent = const_cast<QGraphicsItem *>(this); while ((parent = parent->parentItem())) { if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent)) return group; } // Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this // item is a group item. return 0;}/*! Adds this item to the item group \a group. If \a group is 0, this item is removed from any current group and added as a child of the previous group's parent. \sa group(), QGraphicsScene::createItemGroup()*/void QGraphicsItem::setGroup(QGraphicsItemGroup *group){ if (!group) { if (QGraphicsItemGroup *group = this->group()) group->removeFromGroup(this); } else { group->addToGroup(this); }}/*!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -