QElectroTech 0.200.1-dev
Loading...
Searching...
No Matches
QetShapeItem Class Reference

The QetShapeItem class this class is used to draw a basic shape (line, rectangle, ellipse, polygon or free-form path) into a diagram, that can be saved to a .qet file. Beyond its local geometry, a shape may also carry a rotation/skew/scale (see ShapeTransform) around an arbitrary pivot. More...

#include <qetshapeitem.h>

Inheritance diagram for QetShapeItem:
Inheritance graph
Collaboration diagram for QetShapeItem:
Collaboration graph

Classes

struct  PathNode

Public Types

enum  ShapeType {
  Line =1 , Rectangle =2 , Ellipse =4 , Polygon =8 ,
  Path =16
}
enum  ArcClosure { NoClosure = 0 , Chord = 1 , Pie = 2 }
enum class  NodeKind { Corner , Smooth , Symmetric }
enum class  HandleMode { Size , Corner , NodeEdit , RotateSkew }
enum class  HandleRole {
  Resize , Rotate , SkewEdge , Pivot ,
  CornerRadius , ArcEndpoint , PathAnchor , PathControlIn ,
  PathControlOut
}
enum  { Type = UserType + 1008 }

Signals

void penChanged ()
void brushChanged ()
void closeChanged ()
void XRadiusChanged ()
void YRadiusChanged ()
void transformChanged ()
void arcChanged ()
void geometryChanged ()

Public Member Functions

 QetShapeItem (QPointF, QPointF=QPointF(0, 0), ShapeType=Line, QGraphicsItem *parent=nullptr)
 QetShapeItem::QetShapeItem Constructor of shape item. point 1 and 2 must be in scene coordinate.
 ~QetShapeItem () override
int type () const override
QPen pen () const
 METHODS.
void setPen (const QPen &pen)
 QetShapeItem::setPen Set the pen to use for draw the shape.
QBrush brush () const
void setBrush (const QBrush &brush)
 QetShapeItem::setBrush Set the brush to use for the fill the shape.
ShapeType shapeType () const
virtual bool fromXml (const QDomElement &)
 QetShapeItem::fromXml Build this item from the xml description.
virtual QDomElement toXml (QDomDocument &document) const
 QetShapeItem::toXml Save this item to xml element.
virtual bool toDXF (const QString &filepath, const QPen &pen)
 QetShapeItem::toDXF Draw this element to the dxf document.
void editProperty () override
 QetShapeItem::editProperty Edit the property of this item.
QString name () const override
 QetShapeItem::name.
void setP2 (const QPointF &P2)
 QetShapeItem::setP2 Set the second point of this item. If this item is a polyline, the last point of the polyline is replaced by P2.
QLineF line () const
bool setLine (const QLineF &line)
 QetShapeItem::setLine Set item geometry to line (only available for line shape).
QRectF rect () const
bool setRect (const QRectF &rect)
 QetShapeItem::setRect Set this item geometry to rect (only available if shape is a rectangle or an ellipse).
QPolygonF polygon () const
bool setPolygon (const QPolygonF &polygon)
 QetShapeItem::setPolygon Set this item geometry to polygon (only available if shape is a polyline).
bool isClosed () const
void setClosed (bool close)
 QetShapeItem::setClosed Close this item – has effect for Polygon and Path only (the two shape types with a genuine open/closed distinction at all).
qreal XRadius () const
void setXRadius (qreal X)
qreal YRadius () const
void setYRadius (qreal Y)
const ShapeTransformshapeTransform () const
qreal rotation () const
void setRotation (qreal degrees)
 QetShapeItem::setRotation.
qreal skewX () const
void setSkewX (qreal degrees)
qreal skewY () const
void setSkewY (qreal degrees)
qreal scaleFactorX () const
void setScaleFactorX (qreal factor)
qreal scaleFactorY () const
void setScaleFactorY (qreal factor)
QPointF pivot () const
void setPivot (const QPointF &pivot)
 QetShapeItem::setPivot Move the pivot point. pos() is adjusted at the same time so the shape never visibly jumps – see compensatedPositionForNewPivot() in shapetransform.h for why that adjustment is needed at all.
void resetPivotToBoundingRectCenter ()
void enableNodeEditMode ()
 QetShapeItem::enableNodeEditMode Switches into NodeEdit mode, so every node's control handles (and their tangent guide lines drawn in paint()) become visible – the same visual feedback normal editing already gets via the context menu's node-kind actions, made available to the pen tool too so a node's handles are visible as they're being dragged into existence, not only afterward.
qreal startAngle () const
void setStartAngle (qreal degrees)
qreal endAngle () const
void setEndAngle (qreal degrees)
qreal spanAngle () const
bool isFullEllipse () const
ArcClosure arcClosure () const
void setArcClosure (ArcClosure closure)
const QVector< PathNode > & pathNodes () const
void setPathNodes (const QVector< PathNode > &nodes)
 QetShapeItem::setPathNodes Replace the node list of a Path shape. Interactive editing of anchors and control handles both go through the handle roles built by rebuildHandles() (PathAnchor always visible; PathControlIn/Out for the active node once double-click enters node-edit mode) – this setter itself is just the plain data replacement underneath that.
int pointsCount () const
 QetShapeItem::pointCount.
void setNextPoint (QPointF P)
 QetShapeItem::setNextPoint Add a new point to the current polygon.
void removePoints (int number=1)
 QetShapeItem::removePoints Number of point to remove on the polygon If number is superior to number of polygon points-2, all points of polygon will be removed except the first two (minimum point for the polygon);.
QRectF boundingRect () const override
 QetShapeItem::boundingRect.
QPainterPath shape () const override
 QetShapeItem::shape.
Public Member Functions inherited from QetGraphicsItem
 QetGraphicsItem (QGraphicsItem *parent=nullptr)
 ~QetGraphicsItem () override=0
Diagramdiagram () const
virtual void setPos (const QPointF &p)
virtual void setPos (qreal x, qreal y)
virtual bool isMovable () const
virtual void setMovable (bool movable)
bool isHovered () const
QPointF hoverMousePos () const
QET::GraphicsItemState state () const
 QetGraphicsItem::state.

Protected Member Functions

void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
 QetShapeItem::paint Paint this item.
void hoverEnterEvent (QGraphicsSceneHoverEvent *event) override
 QetShapeItem::hoverEnterEvent Handle hover enter event.
void hoverLeaveEvent (QGraphicsSceneHoverEvent *event) override
 QetShapeItem::hoverLeaveEvent Handle hover leave event.
void mousePressEvent (QGraphicsSceneMouseEvent *event) override
 QetShapeItem::mousePressEvent A left click on an already selected shape (without having dragged) toggles between the Size and RotateSkew handle sets – the same convention LibreOffice Draw and PowerPoint use. A click that performs the selection itself does not toggle, so selecting a shape always starts in Size mode.
void mouseMoveEvent (QGraphicsSceneMouseEvent *event) override
 QetShapeItem::mouseMoveEvent Only ever does something different from the base class while a curve-segment drag (started in mousePressEvent above) is pending or active; otherwise this is exactly QetGraphicsItem's own whole-shape- move handling (grid-snapped drag, multi-selection movement via diagram()->elementsMover()), untouched.
void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override
 QetShapeItem::mouseReleaseEvent If the press in mousePressEvent never turned into a real drag, this was just a plain click – cycle the handle mode, exactly like a click anywhere else on an already-selected shape would. Otherwise commit the curve-drag's undo entry, reusing the same generic before/after XML snapshot mechanism as every other Path edit. With no curve-drag pending at all, this defers entirely to QetGraphicsItem's own release handling (which ends the whole-shape-move gesture via elementsMover()).
QVariant itemChange (GraphicsItemChange change, const QVariant &value) override
 QetShapeItem::itemChange.
bool sceneEventFilter (QGraphicsItem *watched, QEvent *event) override
 QetShapeItem::sceneEventFilter.
void contextMenuEvent (QGraphicsSceneContextMenuEvent *event) override
 QetShapeItem::contextMenuEvent.
Protected Member Functions inherited from QetGraphicsItem
void mousePressEvent (QGraphicsSceneMouseEvent *event) override
void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override
void mouseMoveEvent (QGraphicsSceneMouseEvent *event) override
void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override
 QetGraphicsItem::mouseReleaseEvent handle mouse release click.
void hoverEnterEvent (QGraphicsSceneHoverEvent *event) override
void hoverMoveEvent (QGraphicsSceneHoverEvent *event) override
void hoverLeaveEvent (QGraphicsSceneHoverEvent *event) override

Properties

QPen pen
QBrush brush
QRectF rect
QLineF line
QPolygonF polygon
bool close
qreal xRadius
qreal yRadius
qreal rotation
qreal skewX
qreal skewY
qreal scaleFactorX
qreal scaleFactorY
QPointF pivot
qreal startAngle
qreal endAngle

Private Member Functions

void toggleHandleMode ()
HandleMode nextHandleMode () const
 QetShapeItem::toggleHandleMode Cycled by clicking an already-selected shape: Size -> Corner -> RotateSkew -> Size for Rectangle (the only type with a corner-radius concept); Size -> RotateSkew -> Size for everything else, skipping the Corner state entirely rather than showing an empty/meaningless one.
void updateModeHint ()
 QetShapeItem::updateModeHint Keeps the tooltip in sync with what the next click would do – called on selection change (so it appears/disappears with the handles themselves) and after every mode switch. Deliberately short: this is a tooltip, not documentation – the fuller gesture/modifier reference lives in the status bar instead (see currentModeStatusHint(), hoverEnterEvent()), which has room for it without popping up uninvited.
void refreshInteractionHints ()
 QetShapeItem::refreshInteractionHints Keeps the tooltip text current, and – if the shape is already being hovered – immediately re-shows both the tooltip and the status bar hint rather than leaving them stuck on whatever was true before. Needed because Qt only re-evaluates a tooltip, and this class only re-shows the status bar, when the cursor moves: selecting a shape (often clicked while the mouse was already sitting on it) or cycling handle modes (definitely clicked while sitting on it) both change what should be shown without the cursor moving at all, so without this both would appear stale until the user moved away and back.
void showStatusHint (const QString &text) const
void clearStatusHint () const
QString currentModeStatusHint () const
 QetShapeItem::currentModeStatusHint One-line reference for whatever handles are visible right now, shown in the status bar while hovering a selected shape's body (see hoverEnterEvent()) – the modifier keys in particular (Ctrl, Shift, Alt) have no other visible indication that they do anything at all. Also carries the same "next mode" information as the tooltip, since the status bar has room for the full picture in one place rather than needing the tooltip read separately.
QString handleRoleTooltip (HandleRole role, int slot) const
 QetShapeItem::handleRoleTooltip Set natively on each handle item in rebuildHandles() – Qt shows a handle's own tooltip in preference to the shape's when hovering directly over it, so this is what gives each handle its own distinct hint instead of every one of them repeating the shape's general "click: next mode" tooltip regardless of which handle you're actually looking at.
void rebuildHandles ()
 QetShapeItem::rebuildHandles (Re)creates the handler items from scratch, for the current shapeType()/handleMode(). Only called when the set of handles changes – selection, mode toggle, node count change – never during a live drag, since that would delete the very QetGraphicsHandlerItem currently receiving the mouse-move events. See repositionHandles() for the drag-safe alternative.
void repositionHandles ()
 QetShapeItem::repositionHandles Moves the existing handler items to match current geometry, without touching their identity or which one is mid-drag. Safe (and expected) to be called on every frame of a live drag. Falls back to a full rebuild only if the handle count has somehow drifted out of sync – this should not normally happen, since only rebuildHandles() ever changes m_handleRoles/m_handleSlot.
void insertPoint ()
void removePoint ()
void convertToPathOrPolygon ()
 QetShapeItem::convertToPathOrPolygon Context-menu action, explicitly requested rather than triggered by an Alt+drag (see promoteRectangleOrEllipseToPolygon() for that separate mechanism). A sharp-cornered rectangle converts losslessly to a 4-corner polygon – its 4 corners already are exactly what a rectangle is. Anything else offered here (an ellipse/arc, or a rectangle with rounded corners) used to get the exact same treatment, which is wrong: an ellipse flattened to its bounding rect's 4 corners doesn't resemble an ellipse at all, and rounded corners would be silently squared off. Both instead become a genuine Bezier Path, built from the two verified helper functions below (numerically confirmed against Qt's own arcTo()/addRoundedRect() output – worst-case error a small fraction of a unit on shapes roughly 100-250 units across, i.e. visually indistinguishable, not merely "close enough to eyeball").
void mirror (bool horizontal)
 QetShapeItem::mirror Flips the shape around its own current pivot – horizontal negates scaleFactorX, vertical negates scaleFactorY, composing naturally with whatever rotation/skew are already set rather than needing any shape-specific geometry logic. Verified numerically before building this: the full transform (rotation+skew+scale combined) round-trips exactly under a negative scale just as it does under a positive one, since a negative-scale matrix is just as invertible (non-zero determinant) – and the two interactions that seemed most likely to break under mirroring turned out not to: dragRotateHandle()'s angle-solve isn't hardcoded to assume positive scale (it correctly flips sign for the mirrored case and still tracks the mouse exactly), and dragArcEndpoint() operates entirely in local space via mapFromScene(), which is exactly as exact under a mirror as without one. isResizeCornerSlot() is also unaffected on inspection: it identifies corners by their fixed local index, which mirroring never changes – only where those indices end up on screen.
void setNodeKind (int nodeIndex, NodeKind kind)
 QetShapeItem::setNodeKind Change a Path node's kind, via the context menu rather than a drag. Promoting a Corner node to Smooth or Symmetric synthesizes whichever handles it doesn't already have, from its neighbours – direction toward the far neighbour, length a third of the distance to the near one, the same simple heuristic most vector editors use for a "make smooth" action. Demoting to Corner leaves any existing handles untouched (a Corner node can still have handles – see dragPathControlHandle() – it just stops forcing them to stay linked). Also switches into NodeEdit mode, so the result is immediately visible rather than a change to data you'd otherwise have to click into node-edit mode again to see.
void handlerMousePressEvent (int handlerIndex)
 QetShapeItem::handlerMousePressEvent.
void handlerMouseMoveEvent (int handlerIndex, QGraphicsSceneMouseEvent *event)
 QetShapeItem::handlerMouseMoveEvent.
void handlerMouseReleaseEvent (int handlerIndex)
 QetShapeItem::handlerMouseReleaseEvent.
void dragResize (int index, const QPointF &localPos, Qt::KeyboardModifiers mods)
void dragRotateHandle (int cornerIndex, const QPointF &scenePos, Qt::KeyboardModifiers mods)
void dragSkewHandle (int edgeIndex, const QPointF &scenePos, Qt::KeyboardModifiers mods)
void dragPivotHandle (const QPointF &localPos)
void dragArcEndpoint (int which, const QPointF &localPos, Qt::KeyboardModifiers mods)
void dragCornerRadius (int which, const QPointF &localPos)
void dragPathAnchor (int which, const QPointF &localPos, Qt::KeyboardModifiers mods)
 QetShapeItem::dragPathAnchor Normally just moves the anchor (Polygon vertex, or a Path node's anchor – its in/out handles are relative offsets, so they follow for free). Alt+drag on a Path anchor, in NodeEdit mode, does something different instead: pulls a fresh pair of symmetric handles directly out of that node, letting a bare Corner node be reshaped into a curve without needing the context menu's "make smooth" action first – the anchor itself stays fixed; the drag distance and direction become the outgoing handle, mirrored exactly for the incoming one, matching Illustrator's own "Alt+drag an anchor" convention for this exact gesture. Deliberately scoped to NodeEdit mode: the curve would still bend if allowed in Size mode too (the underlying node data doesn't care what mode is active), but the new handles themselves would be invisible until switching modes anyway, which would just be confusing.
void dragPathControlHandle (bool isOutHandle, int nodeIndex, const QPointF &localPos, Qt::KeyboardModifiers mods)
 QetShapeItem::dragPathControlHandle Dragging a Bezier control handle. Corner nodes have no linked opposite handle to update. Smooth nodes keep the two handles collinear through the anchor but let each keep its own length (tangent-continuous, magnitude-independent). Symmetric nodes mirror both direction and length exactly. Alt always means "break a normally -linked relationship" in this design – here, detaching this handle from its mirror, permanently downgrading the node to Corner, exactly the same convention Alt already has on a rectangle's resize corner (see dragResize()).
void mirrorOppositeHandle (PathNode &node, bool justChangedIsOut)
 QetShapeItem::mirrorOppositeHandle Given a node whose one handle (out, if justChangedIsOut; in, otherwise) was just set directly, updates its other handle to respect the node's kind – Smooth keeps both collinear through the anchor but lets each keep its own prior length (tangent-continuous, magnitude-independent); Symmetric also equalizes the lengths; Corner does nothing, since it has no linked handle to update. If the other handle doesn't exist yet at all, it's created here rather than left missing – matching its own length to whichever handle was just dragged, the only sensible default when there's no prior length of its own to preserve. Shared by dragPathControlHandle() (a handle dragged directly), dragCurveSegment() (both handles moved together, indirectly, by dragging the curve between two nodes), and dragPathAnchor()'s Alt-drag (pulling a fresh pair of handles out of a bare Corner node).
void dragCurveSegment (int segmentIndex, qreal t, const QPointF &localPos)
 QetShapeItem::dragCurveSegment Inkscape-style "grab the curve itself, not a handle" reshaping: moves both of the segment's control points by the same amount, scaled so the curve ends up passing through localPos at the parameter t where the drag started. Verified algebraically and numerically before shipping: for control points P1,P2 shifted by a constant delta, the curve's own point at t shifts by exactly 3*(1-t)*t*delta, which is exactly the factor divided back out below – so the new curve passes through localPos exactly, not approximately. Always measured against the original control points captured when the drag started (m_curveDragOriginalP1/P2), not the current (possibly already-adjusted, this same drag) ones – otherwise each frame's adjustment would compound on top of the last, sending the curve shooting off far past the cursor instead of tracking it. Near either endpoint (t within 5% of 0 or 1) the curve is barely sensitive to its control points at all – the same reason grabbing a suspension bridge's deck right next to a pylon barely moves it – so those clicks are left alone rather than requiring huge, unpredictable handle movements for a small visual change; they're also close enough to an anchor that the user most likely meant to grab that instead.
void promoteRectangleOrEllipseToPolygon (int detachedResizeIndex, const QPointF &newLocalPos)
 QetShapeItem::promoteRectangleOrEllipseToPolygon Alt+drag on a Resize corner detaches that one vertex, at the moment the shape stops being a Rectangle/Ellipse and becomes a Polygon. The prior state (type, geometry, transform, style) is captured by PromoteShapeCommand so a single Undo restores it exactly – this fact never touches the saved .qet file, only the session's undo stack.
std::pair< int, qreal > nearestPathSegment (const QPointF &localPos) const
 QetShapeItem::nearestPathSegment Nearest point on the whole curve to localPos, found by coarse sampling each segment's cubic Bezier (24 samples is plenty for a context-menu pick – this only has to be close enough to feel right, not exact). Returns {-1, 0} if there are fewer than two nodes to form a segment.
void insertPathPoint (int segmentIndex, qreal t)
 QetShapeItem::insertPathPoint Splits the cubic Bezier between node segmentIndex and its successor at parameter t, via De Casteljau's algorithm – the two resulting halves are guaranteed to retrace the original curve exactly (no kink at the seam), which a naive "just add a point at this position and guess new handles" approach cannot promise. When neither side of the segment actually has a handle (a plain straight run between two Corner-ish points), this degrades to a plain linear split with no handles at all on the new node, rather than introducing phantom zero-effect handles on what the user sees as a straight line.
void removePathPoint (int nodeIndex)
 QetShapeItem::removePathPoint Deletes a node outright and lets its two former neighbours connect directly using their own existing handles – no attempt to re-fit a single curve that approximates the old shape through where the point used to be. That's a much harder (and inherently lossy) problem; this is the same plain "just delete it" convention most editors default to.
QDomElement snapshotXml () const
 QetShapeItem::snapshotXml toXml() into a private, throwaway document – used only to hand a self-contained QDomElement to PromoteShapeCommand, which deep-clones it again into its own document anyway (see promoteshapecommand.cpp).
QRectF localRect () const
 QetShapeItem::localRect The rect used for corner/edge handle placement and for arc/radius math. For Polygon and Path this is the vertex bounding box; for everything else it is simply the P1/P2 rect, as before.
QPainterPath outline () const
 QetShapeItem::outline The raw, unstroked path for the current type, in local coordinates. Shared by shape() (which strokes it for hit-testing/selection) and paint() (which draws it directly) so the two can never disagree about what the shape actually looks like.
QVector< QPointF > currentHandlePositions () const
QPointF handlePositionFor (HandleRole role, int slot) const
 QetShapeItem::handlePositionFor Local-coordinate position for one (role, slot) pair, given the shape's current geometry. This is the single source of truth used both to build handles from scratch (rebuildHandles()) and to move existing ones during a live drag (repositionHandles()) – the two can never disagree about where a handle belongs.
QPointF rotateHandleReference (int slot) const
QPointF scaleOnlyOffset (const QPointF &localPoint) const
 QetShapeItem::scaleOnlyOffset / scaleAndShearOffset A local point's offset from the pivot, run through only the parts of the linear transform that are not currently being edited by a drag – i.e. the parts that stay fixed while the user is dragging one specific handle. These are the fixed reference values dragRotateHandle() and dragSkewHandle() solve against, instead of round-tripping through mapFromScene() (which would divide out the very parameter being solved for and turn the drag into a feedback loop – see dragRotateHandle()'s comment for the concrete failure mode this replaces).
QPointF scaleAndShearOffset (const QPointF &localPoint) const

Static Private Member Functions

static QString handleModeLabel (HandleMode mode)
 QetShapeItem::handleModeLabel Short, human name for a HandleMode – used to build both the tooltip ("click: switches to X") and, indirectly, the status bar text.
static bool isResizeCornerSlot (int slot)
static QVector< PathNodebezierNodesForArc (const QRectF &rect, qreal startAngleDeg, qreal spanAngleDeg)
 QetShapeItem::bezierNodesForArc Bezier approximation of an elliptical arc, split into <=90-degree segments (the standard cap for this technique to stay visually exact – a single segment starts drifting noticeably past that). Each segment's handle length is (4/3)*tan(segment_span/4), the general-angle form of the well-known ~0.5523 "kappa" constant for an exact quarter circle. A full 360-degree span is a special case: it produces exactly segments nodes rather than segments+1 (the very last one would just be a duplicate of the first at the same anchor point) and wires the wrap-around segment's own handles explicitly, so the loop closes as a continuous curve rather than the straight "chord" line a generic closed-path wrap-around would otherwise fall back to.
static QVector< PathNodebezierNodesForRoundedRect (const QRectF &rect, qreal xRadius, qreal yRadius)
 QetShapeItem::bezierNodesForRoundedRect Bezier equivalent of QPainterPath::addRoundedRect(): 8 anchors (each edge's two ends), straight lines along the 4 edges, and a Bezier quarter-turn at each of the 4 corners using the same handle-length formula as bezierNodesForArc() (with segSpan fixed at 90 degrees, since a rounded rect's corners always are). xRadius/yRadius are clamped to at most half the rect's own width/height, matching how QPainterPath::addRoundedRect() itself behaves for an over-large radius.
static QColor colorForHandleRole (HandleRole role)
 QetShapeItem::colorForHandleRole Purely cosmetic, but consistent with the existing convention of color-coding what a handle currently does. Mirror-resize used to be its own colored click-cycled mode (green); it is now a Ctrl modifier available on every Resize handle, so only genuinely distinct behaviours get their own color here.
static QRectF lockAspectRatio (const QRectF &oldRect, QRectF newRect, int resizeIndex, bool mirrored)
 QetShapeItem::lockAspectRatio Shift-constrained resize: keep the pre-drag width:height ratio, driven by whichever dimension moved proportionally more, re-anchored the same way the unconstrained result already was.
static QPointF cornerPoint (const QRectF &rect, int cornerIndex)
static QPointF edgeMidpoint (const QRectF &rect, int edgeIndex)

Private Attributes

ShapeType m_shapeType
 ATTRIBUTES.
QPen m_pen
QBrush m_brush
QPointF m_P1
QPointF m_P2
QPointF m_old_P1
QPointF m_old_P2
QPointF m_context_menu_pos
QPolygonF m_polygon
QPolygonF m_old_polygon
bool m_hovered
int m_vector_index
bool m_closed = false
bool m_modifie_radius_equaly = false
QVector< QetGraphicsHandlerItem * > m_handler_vector
QAction * m_insert_point
QAction * m_remove_point
qreal m_xRadius = 0
qreal m_yRadius = 0
qreal m_old_xRadius
qreal m_old_yRadius
qreal m_old_startAngle
qreal m_old_endAngle
ShapeTransform m_transform
ShapeTransform m_old_transform
HandleMode m_handleMode = HandleMode::Size
QVector< HandleRolem_handleRoles
QVector< int > m_handleSlot
QPointF m_old_pos
qreal m_startAngle = 0
qreal m_endAngle = 360
ArcClosure m_arcClosure = NoClosure
bool m_pivotIsCustom = false
bool m_deferHandleReposition = false
QVector< PathNodem_nodes
QVector< PathNodem_old_nodes
int m_curveDragSegment = -1
qreal m_curveDragT = 0
QPointF m_curveDragOriginalP1
QPointF m_curveDragOriginalP2
QPointF m_curveDragPressPos
bool m_curveDragEngaged = false

Additional Inherited Members

Static Public Member Functions inherited from QetGraphicsItem
static void showItem (QetGraphicsItem *item)
 QetGraphicsItem::QetGraphicsItem Default constructor.
Protected Attributes inherited from QetGraphicsItem
bool is_movable_
bool m_first_move
bool snap_to_grid_
QPointF m_mouse_to_origin_movement
QET::GraphicsItemState m_state = QET:: GIOK

Detailed Description

The QetShapeItem class this class is used to draw a basic shape (line, rectangle, ellipse, polygon or free-form path) into a diagram, that can be saved to a .qet file. Beyond its local geometry, a shape may also carry a rotation/skew/scale (see ShapeTransform) around an arbitrary pivot.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
Type 

◆ ArcClosure

Enumerator
NoClosure 
Chord 
Pie 

◆ HandleMode

enum class QetShapeItem::HandleMode
strong
Enumerator
Size 
Corner 
NodeEdit 
RotateSkew 

◆ HandleRole

enum class QetShapeItem::HandleRole
strong
Enumerator
Resize 
Rotate 
SkewEdge 
Pivot 
CornerRadius 
ArcEndpoint 
PathAnchor 
PathControlIn 
PathControlOut 

◆ NodeKind

enum class QetShapeItem::NodeKind
strong
Enumerator
Corner 
Smooth 
Symmetric 

◆ ShapeType

Enumerator
Line 
Rectangle 
Ellipse 
Polygon 
Path 

Constructor & Destructor Documentation

◆ QetShapeItem()

QetShapeItem::QetShapeItem ( QPointF p1,
QPointF p2 = QPointF(0,0),
ShapeType type = Line,
QGraphicsItem * parent = nullptr )

QetShapeItem::QetShapeItem Constructor of shape item. point 1 and 2 must be in scene coordinate.

Parameters
p1first point
p2second point
typetype of item (line, rectangle, ellipse, polygon, path)
parentparent item
Here is the call graph for this function:

◆ ~QetShapeItem()

QetShapeItem::~QetShapeItem ( )
override

Member Function Documentation

◆ arcChanged

void QetShapeItem::arcChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ arcClosure()

ArcClosure QetShapeItem::arcClosure ( ) const
inline

◆ bezierNodesForArc()

QVector< QetShapeItem::PathNode > QetShapeItem::bezierNodesForArc ( const QRectF & rect,
qreal startAngleDeg,
qreal spanAngleDeg )
staticprivate

QetShapeItem::bezierNodesForArc Bezier approximation of an elliptical arc, split into <=90-degree segments (the standard cap for this technique to stay visually exact – a single segment starts drifting noticeably past that). Each segment's handle length is (4/3)*tan(segment_span/4), the general-angle form of the well-known ~0.5523 "kappa" constant for an exact quarter circle. A full 360-degree span is a special case: it produces exactly segments nodes rather than segments+1 (the very last one would just be a duplicate of the first at the same anchor point) and wires the wrap-around segment's own handles explicitly, so the loop closes as a continuous curve rather than the straight "chord" line a generic closed-path wrap-around would otherwise fall back to.

Parameters
rectthe ellipse's bounding rect
startAngleDegarc start angle, matching QPainterPath::arcTo's own convention
spanAngleDegarc angular span, same convention (may be negative)
Returns
nodes forming the arc; caller sets Path/m_closed and prepends a centre node itself for a Pie-style closure
Here is the caller graph for this function:

◆ bezierNodesForRoundedRect()

QVector< QetShapeItem::PathNode > QetShapeItem::bezierNodesForRoundedRect ( const QRectF & rect,
qreal xRadius,
qreal yRadius )
staticprivate

QetShapeItem::bezierNodesForRoundedRect Bezier equivalent of QPainterPath::addRoundedRect(): 8 anchors (each edge's two ends), straight lines along the 4 edges, and a Bezier quarter-turn at each of the 4 corners using the same handle-length formula as bezierNodesForArc() (with segSpan fixed at 90 degrees, since a rounded rect's corners always are). xRadius/yRadius are clamped to at most half the rect's own width/height, matching how QPainterPath::addRoundedRect() itself behaves for an over-large radius.

Parameters
rectthe rectangle's own corner points, as a QRectF
xRadiuscorner radius along the x axis
yRadiuscorner radius along the y axis
Returns
8 nodes forming the closed rounded-rectangle outline
Here is the caller graph for this function:

◆ boundingRect()

QRectF QetShapeItem::boundingRect ( ) const
override

QetShapeItem::boundingRect.

Returns
the bounding rect of this item
Here is the call graph for this function:

◆ brush()

QBrush QetShapeItem::brush ( ) const
inline

◆ brushChanged

void QetShapeItem::brushChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clearStatusHint()

void QetShapeItem::clearStatusHint ( ) const
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ closeChanged

void QetShapeItem::closeChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ colorForHandleRole()

QColor QetShapeItem::colorForHandleRole ( HandleRole role)
staticprivate

QetShapeItem::colorForHandleRole Purely cosmetic, but consistent with the existing convention of color-coding what a handle currently does. Mirror-resize used to be its own colored click-cycled mode (green); it is now a Ctrl modifier available on every Resize handle, so only genuinely distinct behaviours get their own color here.

Here is the caller graph for this function:

◆ contextMenuEvent()

void QetShapeItem::contextMenuEvent ( QGraphicsSceneContextMenuEvent * event)
overrideprotected

QetShapeItem::contextMenuEvent.

Parameters
event
Here is the call graph for this function:

◆ convertToPathOrPolygon()

void QetShapeItem::convertToPathOrPolygon ( )
private

QetShapeItem::convertToPathOrPolygon Context-menu action, explicitly requested rather than triggered by an Alt+drag (see promoteRectangleOrEllipseToPolygon() for that separate mechanism). A sharp-cornered rectangle converts losslessly to a 4-corner polygon – its 4 corners already are exactly what a rectangle is. Anything else offered here (an ellipse/arc, or a rectangle with rounded corners) used to get the exact same treatment, which is wrong: an ellipse flattened to its bounding rect's 4 corners doesn't resemble an ellipse at all, and rounded corners would be silently squared off. Both instead become a genuine Bezier Path, built from the two verified helper functions below (numerically confirmed against Qt's own arcTo()/addRoundedRect() output – worst-case error a small fraction of a unit on shapes roughly 100-250 units across, i.e. visually indistinguishable, not merely "close enough to eyeball").

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cornerPoint()

QPointF QetShapeItem::cornerPoint ( const QRectF & rect,
int cornerIndex )
staticprivate
Here is the caller graph for this function:

◆ currentHandlePositions()

QVector< QPointF > QetShapeItem::currentHandlePositions ( ) const
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ currentModeStatusHint()

QString QetShapeItem::currentModeStatusHint ( ) const
private

QetShapeItem::currentModeStatusHint One-line reference for whatever handles are visible right now, shown in the status bar while hovering a selected shape's body (see hoverEnterEvent()) – the modifier keys in particular (Ctrl, Shift, Alt) have no other visible indication that they do anything at all. Also carries the same "next mode" information as the tooltip, since the status bar has room for the full picture in one place rather than needing the tooltip read separately.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragArcEndpoint()

void QetShapeItem::dragArcEndpoint ( int which,
const QPointF & localPos,
Qt::KeyboardModifiers mods )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragCornerRadius()

void QetShapeItem::dragCornerRadius ( int which,
const QPointF & localPos )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragCurveSegment()

void QetShapeItem::dragCurveSegment ( int segmentIndex,
qreal t,
const QPointF & localPos )
private

QetShapeItem::dragCurveSegment Inkscape-style "grab the curve itself, not a handle" reshaping: moves both of the segment's control points by the same amount, scaled so the curve ends up passing through localPos at the parameter t where the drag started. Verified algebraically and numerically before shipping: for control points P1,P2 shifted by a constant delta, the curve's own point at t shifts by exactly 3*(1-t)*t*delta, which is exactly the factor divided back out below – so the new curve passes through localPos exactly, not approximately. Always measured against the original control points captured when the drag started (m_curveDragOriginalP1/P2), not the current (possibly already-adjusted, this same drag) ones – otherwise each frame's adjustment would compound on top of the last, sending the curve shooting off far past the cursor instead of tracking it. Near either endpoint (t within 5% of 0 or 1) the curve is barely sensitive to its control points at all – the same reason grabbing a suspension bridge's deck right next to a pylon barely moves it – so those clicks are left alone rather than requiring huge, unpredictable handle movements for a small visual change; they're also close enough to an anchor that the user most likely meant to grab that instead.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragPathAnchor()

void QetShapeItem::dragPathAnchor ( int which,
const QPointF & localPos,
Qt::KeyboardModifiers mods )
private

QetShapeItem::dragPathAnchor Normally just moves the anchor (Polygon vertex, or a Path node's anchor – its in/out handles are relative offsets, so they follow for free). Alt+drag on a Path anchor, in NodeEdit mode, does something different instead: pulls a fresh pair of symmetric handles directly out of that node, letting a bare Corner node be reshaped into a curve without needing the context menu's "make smooth" action first – the anchor itself stays fixed; the drag distance and direction become the outgoing handle, mirrored exactly for the incoming one, matching Illustrator's own "Alt+drag an anchor" convention for this exact gesture. Deliberately scoped to NodeEdit mode: the curve would still bend if allowed in Size mode too (the underlying node data doesn't care what mode is active), but the new handles themselves would be invisible until switching modes anyway, which would just be confusing.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragPathControlHandle()

void QetShapeItem::dragPathControlHandle ( bool isOutHandle,
int nodeIndex,
const QPointF & localPos,
Qt::KeyboardModifiers mods )
private

QetShapeItem::dragPathControlHandle Dragging a Bezier control handle. Corner nodes have no linked opposite handle to update. Smooth nodes keep the two handles collinear through the anchor but let each keep its own length (tangent-continuous, magnitude-independent). Symmetric nodes mirror both direction and length exactly. Alt always means "break a normally -linked relationship" in this design – here, detaching this handle from its mirror, permanently downgrading the node to Corner, exactly the same convention Alt already has on a rectangle's resize corner (see dragResize()).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragPivotHandle()

void QetShapeItem::dragPivotHandle ( const QPointF & localPos)
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragResize()

void QetShapeItem::dragResize ( int index,
const QPointF & localPos,
Qt::KeyboardModifiers mods )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragRotateHandle()

void QetShapeItem::dragRotateHandle ( int cornerIndex,
const QPointF & scenePos,
Qt::KeyboardModifiers mods )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dragSkewHandle()

void QetShapeItem::dragSkewHandle ( int edgeIndex,
const QPointF & scenePos,
Qt::KeyboardModifiers mods )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ edgeMidpoint()

QPointF QetShapeItem::edgeMidpoint ( const QRectF & rect,
int edgeIndex )
staticprivate
Here is the caller graph for this function:

◆ editProperty()

void QetShapeItem::editProperty ( )
overridevirtual

QetShapeItem::editProperty Edit the property of this item.

Reimplemented from QetGraphicsItem.

Here is the call graph for this function:

◆ enableNodeEditMode()

void QetShapeItem::enableNodeEditMode ( )

QetShapeItem::enableNodeEditMode Switches into NodeEdit mode, so every node's control handles (and their tangent guide lines drawn in paint()) become visible – the same visual feedback normal editing already gets via the context menu's node-kind actions, made available to the pen tool too so a node's handles are visible as they're being dragged into existence, not only afterward.

Here is the call graph for this function:

◆ endAngle()

qreal QetShapeItem::endAngle ( ) const
inline

◆ fromXml()

bool QetShapeItem::fromXml ( const QDomElement & e)
virtual

QetShapeItem::fromXml Build this item from the xml description.

Parameters
eelement where is stored this item
Returns
true if load success
Here is the call graph for this function:

◆ geometryChanged

void QetShapeItem::geometryChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleModeLabel()

QString QetShapeItem::handleModeLabel ( HandleMode mode)
staticprivate

QetShapeItem::handleModeLabel Short, human name for a HandleMode – used to build both the tooltip ("click: switches to X") and, indirectly, the status bar text.

Here is the caller graph for this function:

◆ handlePositionFor()

QPointF QetShapeItem::handlePositionFor ( HandleRole role,
int slot ) const
private

QetShapeItem::handlePositionFor Local-coordinate position for one (role, slot) pair, given the shape's current geometry. This is the single source of truth used both to build handles from scratch (rebuildHandles()) and to move existing ones during a live drag (repositionHandles()) – the two can never disagree about where a handle belongs.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handlerMouseMoveEvent()

void QetShapeItem::handlerMouseMoveEvent ( int handlerIndex,
QGraphicsSceneMouseEvent * event )
private

QetShapeItem::handlerMouseMoveEvent.

Parameters
handlerIndex
event
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handlerMousePressEvent()

void QetShapeItem::handlerMousePressEvent ( int handlerIndex)
private

QetShapeItem::handlerMousePressEvent.

Parameters
handlerIndex
Here is the caller graph for this function:

◆ handlerMouseReleaseEvent()

void QetShapeItem::handlerMouseReleaseEvent ( int handlerIndex)
private

QetShapeItem::handlerMouseReleaseEvent.

Parameters
handlerIndex
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleRoleTooltip()

QString QetShapeItem::handleRoleTooltip ( HandleRole role,
int slot ) const
private

QetShapeItem::handleRoleTooltip Set natively on each handle item in rebuildHandles() – Qt shows a handle's own tooltip in preference to the shape's when hovering directly over it, so this is what gives each handle its own distinct hint instead of every one of them repeating the shape's general "click: next mode" tooltip regardless of which handle you're actually looking at.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hoverEnterEvent()

void QetShapeItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event)
overrideprotected

QetShapeItem::hoverEnterEvent Handle hover enter event.

Parameters
event
Here is the call graph for this function:

◆ hoverLeaveEvent()

void QetShapeItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event)
overrideprotected

QetShapeItem::hoverLeaveEvent Handle hover leave event.

Parameters
event
Here is the call graph for this function:

◆ insertPathPoint()

void QetShapeItem::insertPathPoint ( int segmentIndex,
qreal t )
private

QetShapeItem::insertPathPoint Splits the cubic Bezier between node segmentIndex and its successor at parameter t, via De Casteljau's algorithm – the two resulting halves are guaranteed to retrace the original curve exactly (no kink at the seam), which a naive "just add a point at this position and guess new handles" approach cannot promise. When neither side of the segment actually has a handle (a plain straight run between two Corner-ish points), this degrades to a plain linear split with no handles at all on the new node, rather than introducing phantom zero-effect handles on what the user sees as a straight line.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ insertPoint()

void QetShapeItem::insertPoint ( )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isClosed()

bool QetShapeItem::isClosed ( ) const
inline

◆ isFullEllipse()

bool QetShapeItem::isFullEllipse ( ) const
inline
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isResizeCornerSlot()

bool QetShapeItem::isResizeCornerSlot ( int slot)
staticprivate
Here is the caller graph for this function:

◆ itemChange()

QVariant QetShapeItem::itemChange ( GraphicsItemChange change,
const QVariant & value )
overrideprotected

QetShapeItem::itemChange.

Parameters
change
value
Returns
Here is the call graph for this function:

◆ line()

QLineF QetShapeItem::line ( ) const
inline

◆ localRect()

QRectF QetShapeItem::localRect ( ) const
private

QetShapeItem::localRect The rect used for corner/edge handle placement and for arc/radius math. For Polygon and Path this is the vertex bounding box; for everything else it is simply the P1/P2 rect, as before.

Here is the caller graph for this function:

◆ lockAspectRatio()

QRectF QetShapeItem::lockAspectRatio ( const QRectF & oldRect,
QRectF newRect,
int resizeIndex,
bool mirrored )
staticprivate

QetShapeItem::lockAspectRatio Shift-constrained resize: keep the pre-drag width:height ratio, driven by whichever dimension moved proportionally more, re-anchored the same way the unconstrained result already was.

Here is the caller graph for this function:

◆ mirror()

void QetShapeItem::mirror ( bool horizontal)
private

QetShapeItem::mirror Flips the shape around its own current pivot – horizontal negates scaleFactorX, vertical negates scaleFactorY, composing naturally with whatever rotation/skew are already set rather than needing any shape-specific geometry logic. Verified numerically before building this: the full transform (rotation+skew+scale combined) round-trips exactly under a negative scale just as it does under a positive one, since a negative-scale matrix is just as invertible (non-zero determinant) – and the two interactions that seemed most likely to break under mirroring turned out not to: dragRotateHandle()'s angle-solve isn't hardcoded to assume positive scale (it correctly flips sign for the mirrored case and still tracks the mouse exactly), and dragArcEndpoint() operates entirely in local space via mapFromScene(), which is exactly as exact under a mirror as without one. isResizeCornerSlot() is also unaffected on inspection: it identifies corners by their fixed local index, which mirroring never changes – only where those indices end up on screen.

QetShapeItem::mirror Flips the shape around its own current pivot.

The first version of this just negated scaleFactorX/Y directly, leaving rotation and skew untouched – correct only when both happen to already be zero. Reflection doesn't commute with rotation (reflect . rotate(t) = rotate(-t) . reflect) or with shear, so on anything already rotated or skewed that version silently reflected the shape's original, pre-transform geometry and then re-applied the same rotation on top – visibly changing a line's inclination instead of mirroring it, exactly as reported.

Fixed by building the reflection as an actual matrix applied to the CURRENT linear transform (reflecting the shape's current on-screen appearance, not its original geometry), then decomposing the result back into the five scalar fields via decomposeLinear() – the same function already used for importing a foreign matrix, applied here to a structurally identical problem: a matrix exists, scalars that reproduce it are needed. Verified against the real QTransform and decomposeLinear() on a shape that was both rotated and skewed before relying on it here, not just reasoned about abstractly.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mirrorOppositeHandle()

void QetShapeItem::mirrorOppositeHandle ( PathNode & node,
bool justChangedIsOut )
private

QetShapeItem::mirrorOppositeHandle Given a node whose one handle (out, if justChangedIsOut; in, otherwise) was just set directly, updates its other handle to respect the node's kind – Smooth keeps both collinear through the anchor but lets each keep its own prior length (tangent-continuous, magnitude-independent); Symmetric also equalizes the lengths; Corner does nothing, since it has no linked handle to update. If the other handle doesn't exist yet at all, it's created here rather than left missing – matching its own length to whichever handle was just dragged, the only sensible default when there's no prior length of its own to preserve. Shared by dragPathControlHandle() (a handle dragged directly), dragCurveSegment() (both handles moved together, indirectly, by dragging the curve between two nodes), and dragPathAnchor()'s Alt-drag (pulling a fresh pair of handles out of a bare Corner node).

Here is the caller graph for this function:

◆ mouseMoveEvent()

void QetShapeItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event)
overrideprotected

QetShapeItem::mouseMoveEvent Only ever does something different from the base class while a curve-segment drag (started in mousePressEvent above) is pending or active; otherwise this is exactly QetGraphicsItem's own whole-shape- move handling (grid-snapped drag, multi-selection movement via diagram()->elementsMover()), untouched.

Here is the call graph for this function:

◆ mousePressEvent()

void QetShapeItem::mousePressEvent ( QGraphicsSceneMouseEvent * event)
overrideprotected

QetShapeItem::mousePressEvent A left click on an already selected shape (without having dragged) toggles between the Size and RotateSkew handle sets – the same convention LibreOffice Draw and PowerPoint use. A click that performs the selection itself does not toggle, so selecting a shape always starts in Size mode.

Here is the call graph for this function:

◆ mouseReleaseEvent()

void QetShapeItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event)
overrideprotected

QetShapeItem::mouseReleaseEvent If the press in mousePressEvent never turned into a real drag, this was just a plain click – cycle the handle mode, exactly like a click anywhere else on an already-selected shape would. Otherwise commit the curve-drag's undo entry, reusing the same generic before/after XML snapshot mechanism as every other Path edit. With no curve-drag pending at all, this defers entirely to QetGraphicsItem's own release handling (which ends the whole-shape-move gesture via elementsMover()).

Here is the call graph for this function:

◆ name()

QString QetShapeItem::name ( ) const
overridevirtual

QetShapeItem::name.

Returns
the name of the current shape.

Reimplemented from QetGraphicsItem.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nearestPathSegment()

std::pair< int, qreal > QetShapeItem::nearestPathSegment ( const QPointF & localPos) const
private

QetShapeItem::nearestPathSegment Nearest point on the whole curve to localPos, found by coarse sampling each segment's cubic Bezier (24 samples is plenty for a context-menu pick – this only has to be close enough to feel right, not exact). Returns {-1, 0} if there are fewer than two nodes to form a segment.

Here is the caller graph for this function:

◆ nextHandleMode()

QetShapeItem::HandleMode QetShapeItem::nextHandleMode ( ) const
private

QetShapeItem::toggleHandleMode Cycled by clicking an already-selected shape: Size -> Corner -> RotateSkew -> Size for Rectangle (the only type with a corner-radius concept); Size -> RotateSkew -> Size for everything else, skipping the Corner state entirely rather than showing an empty/meaningless one.

QetShapeItem::nextHandleMode What clicking an already-selected shape switches to from the current mode – the single source of truth for the cycle order, shared by toggleHandleMode() (which acts on it) and updateModeHint() (which just describes it).

Here is the caller graph for this function:

◆ outline()

QPainterPath QetShapeItem::outline ( ) const
private

QetShapeItem::outline The raw, unstroked path for the current type, in local coordinates. Shared by shape() (which strokes it for hit-testing/selection) and paint() (which draws it directly) so the two can never disagree about what the shape actually looks like.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ paint()

void QetShapeItem::paint ( QPainter * painter,
const QStyleOptionGraphicsItem * option,
QWidget * widget )
overrideprotected

QetShapeItem::paint Paint this item.

Parameters
painter
option
widget
Here is the call graph for this function:

◆ pathNodes()

const QVector< PathNode > & QetShapeItem::pathNodes ( ) const
inline

◆ pen()

QPen QetShapeItem::pen ( ) const
inline

METHODS.

◆ penChanged

void QetShapeItem::penChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pivot()

QPointF QetShapeItem::pivot ( ) const
inline

◆ pointsCount()

int QetShapeItem::pointsCount ( ) const

QetShapeItem::pointCount.

Returns
the number of point in the polygon
Here is the caller graph for this function:

◆ polygon()

QPolygonF QetShapeItem::polygon ( ) const
inline

◆ promoteRectangleOrEllipseToPolygon()

void QetShapeItem::promoteRectangleOrEllipseToPolygon ( int detachedResizeIndex,
const QPointF & newLocalPos )
private

QetShapeItem::promoteRectangleOrEllipseToPolygon Alt+drag on a Resize corner detaches that one vertex, at the moment the shape stops being a Rectangle/Ellipse and becomes a Polygon. The prior state (type, geometry, transform, style) is captured by PromoteShapeCommand so a single Undo restores it exactly – this fact never touches the saved .qet file, only the session's undo stack.

Parameters
detachedResizeIndexthe Resize-role slot (0,2,5,7 = corners in QetGraphicsHandlerUtility::pointsForRect's own ordering) being dragged
newLocalPoswhere that corner is being dragged to
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rebuildHandles()

void QetShapeItem::rebuildHandles ( )
private

QetShapeItem::rebuildHandles (Re)creates the handler items from scratch, for the current shapeType()/handleMode(). Only called when the set of handles changes – selection, mode toggle, node count change – never during a live drag, since that would delete the very QetGraphicsHandlerItem currently receiving the mouse-move events. See repositionHandles() for the drag-safe alternative.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rect()

QRectF QetShapeItem::rect ( ) const
inline

◆ refreshInteractionHints()

void QetShapeItem::refreshInteractionHints ( )
private

QetShapeItem::refreshInteractionHints Keeps the tooltip text current, and – if the shape is already being hovered – immediately re-shows both the tooltip and the status bar hint rather than leaving them stuck on whatever was true before. Needed because Qt only re-evaluates a tooltip, and this class only re-shows the status bar, when the cursor moves: selecting a shape (often clicked while the mouse was already sitting on it) or cycling handle modes (definitely clicked while sitting on it) both change what should be shown without the cursor moving at all, so without this both would appear stale until the user moved away and back.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ removePathPoint()

void QetShapeItem::removePathPoint ( int nodeIndex)
private

QetShapeItem::removePathPoint Deletes a node outright and lets its two former neighbours connect directly using their own existing handles – no attempt to re-fit a single curve that approximates the old shape through where the point used to be. That's a much harder (and inherently lossy) problem; this is the same plain "just delete it" convention most editors default to.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ removePoint()

void QetShapeItem::removePoint ( )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ removePoints()

void QetShapeItem::removePoints ( int number = 1)

QetShapeItem::removePoints Number of point to remove on the polygon If number is superior to number of polygon points-2, all points of polygon will be removed except the first two (minimum point for the polygon);.

Here is the call graph for this function:

◆ repositionHandles()

void QetShapeItem::repositionHandles ( )
private

QetShapeItem::repositionHandles Moves the existing handler items to match current geometry, without touching their identity or which one is mid-drag. Safe (and expected) to be called on every frame of a live drag. Falls back to a full rebuild only if the handle count has somehow drifted out of sync – this should not normally happen, since only rebuildHandles() ever changes m_handleRoles/m_handleSlot.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resetPivotToBoundingRectCenter()

void QetShapeItem::resetPivotToBoundingRectCenter ( )
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rotateHandleReference()

QPointF QetShapeItem::rotateHandleReference ( int slot) const
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ rotation()

qreal QetShapeItem::rotation ( ) const
inline

◆ scaleAndShearOffset()

QPointF QetShapeItem::scaleAndShearOffset ( const QPointF & localPoint) const
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ scaleFactorX()

qreal QetShapeItem::scaleFactorX ( ) const
inline

◆ scaleFactorY()

qreal QetShapeItem::scaleFactorY ( ) const
inline

◆ scaleOnlyOffset()

QPointF QetShapeItem::scaleOnlyOffset ( const QPointF & localPoint) const
private

QetShapeItem::scaleOnlyOffset / scaleAndShearOffset A local point's offset from the pivot, run through only the parts of the linear transform that are not currently being edited by a drag – i.e. the parts that stay fixed while the user is dragging one specific handle. These are the fixed reference values dragRotateHandle() and dragSkewHandle() solve against, instead of round-tripping through mapFromScene() (which would divide out the very parameter being solved for and turn the drag into a feedback loop – see dragRotateHandle()'s comment for the concrete failure mode this replaces).

Here is the caller graph for this function:

◆ sceneEventFilter()

bool QetShapeItem::sceneEventFilter ( QGraphicsItem * watched,
QEvent * event )
overrideprotected

QetShapeItem::sceneEventFilter.

Parameters
watched
event
Returns
Here is the call graph for this function:

◆ setArcClosure()

void QetShapeItem::setArcClosure ( ArcClosure closure)
Here is the call graph for this function:

◆ setBrush()

void QetShapeItem::setBrush ( const QBrush & brush)

QetShapeItem::setBrush Set the brush to use for the fill the shape.

Parameters
brush
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setClosed()

void QetShapeItem::setClosed ( bool close)

QetShapeItem::setClosed Close this item – has effect for Polygon and Path only (the two shape types with a genuine open/closed distinction at all).

Parameters
close
Here is the call graph for this function:

◆ setEndAngle()

void QetShapeItem::setEndAngle ( qreal degrees)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setLine()

bool QetShapeItem::setLine ( const QLineF & line)

QetShapeItem::setLine Set item geometry to line (only available for line shape).

Parameters
line
Returns
: true when shape is a Line, else false
Here is the call graph for this function:

◆ setNextPoint()

void QetShapeItem::setNextPoint ( QPointF P)

QetShapeItem::setNextPoint Add a new point to the current polygon.

Parameters
Pthe new point.
Here is the call graph for this function:

◆ setNodeKind()

void QetShapeItem::setNodeKind ( int nodeIndex,
NodeKind kind )
private

QetShapeItem::setNodeKind Change a Path node's kind, via the context menu rather than a drag. Promoting a Corner node to Smooth or Symmetric synthesizes whichever handles it doesn't already have, from its neighbours – direction toward the far neighbour, length a third of the distance to the near one, the same simple heuristic most vector editors use for a "make smooth" action. Demoting to Corner leaves any existing handles untouched (a Corner node can still have handles – see dragPathControlHandle() – it just stops forcing them to stay linked). Also switches into NodeEdit mode, so the result is immediately visible rather than a change to data you'd otherwise have to click into node-edit mode again to see.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setP2()

void QetShapeItem::setP2 ( const QPointF & P2)

QetShapeItem::setP2 Set the second point of this item. If this item is a polyline, the last point of the polyline is replaced by P2.

Parameters
P2
Here is the call graph for this function:

◆ setPathNodes()

void QetShapeItem::setPathNodes ( const QVector< PathNode > & nodes)

QetShapeItem::setPathNodes Replace the node list of a Path shape. Interactive editing of anchors and control handles both go through the handle roles built by rebuildHandles() (PathAnchor always visible; PathControlIn/Out for the active node once double-click enters node-edit mode) – this setter itself is just the plain data replacement underneath that.

Here is the call graph for this function:

◆ setPen()

void QetShapeItem::setPen ( const QPen & pen)

QetShapeItem::setPen Set the pen to use for draw the shape.

Parameters
pen
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setPivot()

void QetShapeItem::setPivot ( const QPointF & newPivot)

QetShapeItem::setPivot Move the pivot point. pos() is adjusted at the same time so the shape never visibly jumps – see compensatedPositionForNewPivot() in shapetransform.h for why that adjustment is needed at all.

Parameters
newPivotin local coordinates
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setPolygon()

bool QetShapeItem::setPolygon ( const QPolygonF & polygon)

QetShapeItem::setPolygon Set this item geometry to polygon (only available if shape is a polyline).

Parameters
polygon: new polygon
Returns
true if item is polygon, else false
Here is the call graph for this function:

◆ setRect()

bool QetShapeItem::setRect ( const QRectF & rect)

QetShapeItem::setRect Set this item geometry to rect (only available if shape is a rectangle or an ellipse).

Parameters
rect: new rect
Returns
: true when shape is rectangle or ellipse, else false
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setRotation()

void QetShapeItem::setRotation ( qreal degrees)

QetShapeItem::setRotation.

Parameters
degreesOne property per ShapeTransform scalar: every handle (and the properties panel) touches exactly one of these, never the matrix directly. See shapetransform.h for why the matrix itself is only ever built from these, never mutated by hand.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setScaleFactorX()

void QetShapeItem::setScaleFactorX ( qreal factor)
Here is the call graph for this function:

◆ setScaleFactorY()

void QetShapeItem::setScaleFactorY ( qreal factor)
Here is the call graph for this function:

◆ setSkewX()

void QetShapeItem::setSkewX ( qreal degrees)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setSkewY()

void QetShapeItem::setSkewY ( qreal degrees)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setStartAngle()

void QetShapeItem::setStartAngle ( qreal degrees)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setXRadius()

void QetShapeItem::setXRadius ( qreal X)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setYRadius()

void QetShapeItem::setYRadius ( qreal Y)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shape()

QPainterPath QetShapeItem::shape ( ) const
override

QetShapeItem::shape.

Returns
the shape of this item
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shapeTransform()

const ShapeTransform & QetShapeItem::shapeTransform ( ) const
inline

◆ shapeType()

ShapeType QetShapeItem::shapeType ( ) const
inline

◆ showStatusHint()

void QetShapeItem::showStatusHint ( const QString & text) const
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ skewX()

qreal QetShapeItem::skewX ( ) const
inline

◆ skewY()

qreal QetShapeItem::skewY ( ) const
inline

◆ snapshotXml()

QDomElement QetShapeItem::snapshotXml ( ) const
private

QetShapeItem::snapshotXml toXml() into a private, throwaway document – used only to hand a self-contained QDomElement to PromoteShapeCommand, which deep-clones it again into its own document anyway (see promoteshapecommand.cpp).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ spanAngle()

qreal QetShapeItem::spanAngle ( ) const
inline
Here is the caller graph for this function:

◆ startAngle()

qreal QetShapeItem::startAngle ( ) const
inline

◆ toDXF()

bool QetShapeItem::toDXF ( const QString & filepath,
const QPen & pen )
virtual

QetShapeItem::toDXF Draw this element to the dxf document.

Parameters
filepathfile path of the the dxf document
pen
Returns
true if draw success
Here is the call graph for this function:
Here is the caller graph for this function:

◆ toggleHandleMode()

void QetShapeItem::toggleHandleMode ( )
private
Here is the call graph for this function:
Here is the caller graph for this function:

◆ toXml()

QDomElement QetShapeItem::toXml ( QDomDocument & document) const
virtual

QetShapeItem::toXml Save this item to xml element.

Parameters
documentparent document xml
Returns
element xml where is write this item
Here is the call graph for this function:
Here is the caller graph for this function:

◆ transformChanged

void QetShapeItem::transformChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ type()

int QetShapeItem::type ( ) const
inlineoverride
Here is the caller graph for this function:

◆ updateModeHint()

void QetShapeItem::updateModeHint ( )
private

QetShapeItem::updateModeHint Keeps the tooltip in sync with what the next click would do – called on selection change (so it appears/disappears with the handles themselves) and after every mode switch. Deliberately short: this is a tooltip, not documentation – the fuller gesture/modifier reference lives in the status bar instead (see currentModeStatusHint(), hoverEnterEvent()), which has room for it without popping up uninvited.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ XRadius()

qreal QetShapeItem::XRadius ( ) const
inline

◆ XRadiusChanged

void QetShapeItem::XRadiusChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

◆ YRadius()

qreal QetShapeItem::YRadius ( ) const
inline

◆ YRadiusChanged

void QetShapeItem::YRadiusChanged ( )
signal
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_arcClosure

ArcClosure QetShapeItem::m_arcClosure = NoClosure
private

◆ m_brush

QBrush QetShapeItem::m_brush
private

◆ m_closed

bool QetShapeItem::m_closed = false
private

◆ m_context_menu_pos

QPointF QetShapeItem::m_context_menu_pos
private

◆ m_curveDragEngaged

bool QetShapeItem::m_curveDragEngaged = false
private

◆ m_curveDragOriginalP1

QPointF QetShapeItem::m_curveDragOriginalP1
private

◆ m_curveDragOriginalP2

QPointF QetShapeItem::m_curveDragOriginalP2
private

◆ m_curveDragPressPos

QPointF QetShapeItem::m_curveDragPressPos
private

◆ m_curveDragSegment

int QetShapeItem::m_curveDragSegment = -1
private

◆ m_curveDragT

qreal QetShapeItem::m_curveDragT = 0
private

◆ m_deferHandleReposition

bool QetShapeItem::m_deferHandleReposition = false
private

◆ m_endAngle

qreal QetShapeItem::m_endAngle = 360
private

◆ m_handleMode

HandleMode QetShapeItem::m_handleMode = HandleMode::Size
private

◆ m_handler_vector

QVector<QetGraphicsHandlerItem *> QetShapeItem::m_handler_vector
private

◆ m_handleRoles

QVector<HandleRole> QetShapeItem::m_handleRoles
private

◆ m_handleSlot

QVector<int> QetShapeItem::m_handleSlot
private

◆ m_hovered

bool QetShapeItem::m_hovered
private

◆ m_insert_point

QAction* QetShapeItem::m_insert_point
private

◆ m_modifie_radius_equaly

bool QetShapeItem::m_modifie_radius_equaly = false
private

◆ m_nodes

QVector<PathNode> QetShapeItem::m_nodes
private

◆ m_old_endAngle

qreal QetShapeItem::m_old_endAngle
private

◆ m_old_nodes

QVector<PathNode> QetShapeItem::m_old_nodes
private

◆ m_old_P1

QPointF QetShapeItem::m_old_P1
private

◆ m_old_P2

QPointF QetShapeItem::m_old_P2
private

◆ m_old_polygon

QPolygonF QetShapeItem::m_old_polygon
private

◆ m_old_pos

QPointF QetShapeItem::m_old_pos
private

◆ m_old_startAngle

qreal QetShapeItem::m_old_startAngle
private

◆ m_old_transform

ShapeTransform QetShapeItem::m_old_transform
private

◆ m_old_xRadius

qreal QetShapeItem::m_old_xRadius
private

◆ m_old_yRadius

qreal QetShapeItem::m_old_yRadius
private

◆ m_P1

QPointF QetShapeItem::m_P1
private

◆ m_P2

QPointF QetShapeItem::m_P2
private

◆ m_pen

QPen QetShapeItem::m_pen
private

◆ m_pivotIsCustom

bool QetShapeItem::m_pivotIsCustom = false
private

◆ m_polygon

QPolygonF QetShapeItem::m_polygon
private

◆ m_remove_point

QAction * QetShapeItem::m_remove_point
private

◆ m_shapeType

ShapeType QetShapeItem::m_shapeType
private

ATTRIBUTES.

◆ m_startAngle

qreal QetShapeItem::m_startAngle = 0
private

◆ m_transform

ShapeTransform QetShapeItem::m_transform
private

◆ m_vector_index

int QetShapeItem::m_vector_index
private

◆ m_xRadius

qreal QetShapeItem::m_xRadius = 0
private

◆ m_yRadius

qreal QetShapeItem::m_yRadius = 0
private

Property Documentation

◆ brush

QBrush QetShapeItem::brush
readwrite

◆ close

bool QetShapeItem::close
readwrite

◆ endAngle

qreal QetShapeItem::endAngle
readwrite

◆ line

QLineF QetShapeItem::line
readwrite

◆ pen

QPen QetShapeItem::pen
readwrite

◆ pivot

QPointF QetShapeItem::pivot
readwrite

◆ polygon

QPolygonF QetShapeItem::polygon
readwrite

◆ rect

QRectF QetShapeItem::rect
readwrite

◆ rotation

qreal QetShapeItem::rotation
readwrite

◆ scaleFactorX

qreal QetShapeItem::scaleFactorX
readwrite

◆ scaleFactorY

qreal QetShapeItem::scaleFactorY
readwrite

◆ skewX

qreal QetShapeItem::skewX
readwrite

◆ skewY

qreal QetShapeItem::skewY
readwrite

◆ startAngle

qreal QetShapeItem::startAngle
readwrite

◆ xRadius

qreal QetShapeItem::xRadius
readwrite

◆ yRadius

qreal QetShapeItem::yRadius
readwrite

The documentation for this class was generated from the following files: