Engauge Digitizer 2
Loading...
Searching...
No Matches
GraphicsPoint.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5 ******************************************************************************************************/
6
7#include "CurveStyle.h"
8#include "DataKey.h"
9#include "EnumsToQt.h"
10#include "GeometryWindow.h"
11#include "GraphicsItemType.h"
12#include "GraphicsPoint.h"
15#include "Logger.h"
16#include "PointStyle.h"
17#include <QGraphicsEllipseItem>
18#include <QGraphicsPolygonItem>
19#include <QGraphicsScene>
20#include <QGraphicsSceneContextMenuEvent>
21#include <QObject>
22#include <QPen>
23#include <QTextStream>
24#include "QtToString.h"
25#include "ZValues.h"
26
27const double DEFAULT_HIGHLIGHT_OPACITY = 0.35; // 0=transparent to 1=opaque. Values above 0.5 are very hard to notice
28const double MAX_OPACITY = 1.0;
29const double ZERO_WIDTH = 0.0;
30
31GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
32 const QString &identifier,
33 const QPointF &posScreen,
34 const QColor &color,
35 unsigned int radius,
36 double lineWidth,
39 m_scene (scene),
40 m_graphicsItemEllipse (nullptr),
41 m_shadowZeroWidthEllipse (nullptr),
42 m_graphicsItemPolygon (nullptr),
43 m_shadowZeroWidthPolygon (nullptr),
44 m_identifier (identifier),
45 m_posScreen (posScreen),
46 m_color (color),
47 m_lineWidth (lineWidth),
48 m_wanted (true),
49 m_highlightOpacity (DEFAULT_HIGHLIGHT_OPACITY),
50 m_geometryWindow (geometryWindow)
51{
52 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::GraphicsPoint"
53 << " identifier=" << identifier.toLatin1 ().data ();
54
55 createPointEllipse (radius);
56}
57
58GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
59 const QString &identifier,
60 const QPointF &posScreen,
61 const QColor &color,
62 const QPolygonF &polygon,
63 double lineWidth,
66 m_scene (scene),
67 m_graphicsItemEllipse (nullptr),
68 m_shadowZeroWidthEllipse (nullptr),
69 m_graphicsItemPolygon (nullptr),
70 m_shadowZeroWidthPolygon (nullptr),
71 m_identifier (identifier),
72 m_posScreen (posScreen),
73 m_color (color),
74 m_lineWidth (lineWidth),
75 m_wanted (true),
76 m_highlightOpacity (DEFAULT_HIGHLIGHT_OPACITY),
77 m_geometryWindow (geometryWindow)
78{
79 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::GraphicsPoint "
80 << " identifier=" << identifier.toLatin1 ().data ();
81
82 createPointPolygon (polygon);
83}
84
86{
87 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::~GraphicsPoint";
88
89 if (m_graphicsItemEllipse == nullptr) {
90
91 QGraphicsScene *scene = m_graphicsItemPolygon->scene();
92
93 // Since m_shadowZeroWidthPolygon is a child of m_graphicsItemPolygon, removing the parent removes both
94 scene->removeItem (m_graphicsItemPolygon);
95 delete m_graphicsItemPolygon;
96 m_graphicsItemPolygon = nullptr;
97 m_shadowZeroWidthPolygon = nullptr;
98
99
100 } else {
101
102 QGraphicsScene *scene = m_graphicsItemEllipse->scene();
103
104 // Since m_shadowZeroWidthEllipse is a child of m_graphicsItemEllipse, removing the parent removes both
105 scene->removeItem (m_graphicsItemEllipse);
106 delete m_graphicsItemEllipse;
107 m_graphicsItemEllipse = nullptr;
108 m_shadowZeroWidthEllipse = nullptr;
109
110 }
111}
112
114{
115 if (m_graphicsItemEllipse == nullptr) {
116 return m_graphicsItemPolygon->boundingRect ();
117 } else {
118 return m_graphicsItemEllipse->boundingRect ();
119 }
120}
121
122void GraphicsPoint::createPointEllipse (unsigned int radius)
123{
124 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::createPointEllipse";
125
126 const int radiusSigned = signed (radius); // Radius must be signed before multiplying by -1 below, for Visual Studio
127 m_graphicsItemEllipse = new GraphicsPointEllipse (*this,
129 - radiusSigned,
130 2 * radiusSigned + 1,
131 2 * radiusSigned + 1));
132 m_scene.addItem (m_graphicsItemEllipse);
133
134 m_graphicsItemEllipse->setZValue (Z_VALUE_POINT);
135 m_graphicsItemEllipse->setData (DATA_KEY_IDENTIFIER, m_identifier);
136 m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
137 m_graphicsItemEllipse->setPos (m_posScreen.x (),
138 m_posScreen.y ());
139 m_graphicsItemEllipse->setPen (QPen (QBrush (m_color), m_lineWidth));
140 m_graphicsItemEllipse->setEnabled (true);
141 m_graphicsItemEllipse->setFlags (QGraphicsItem::ItemIsSelectable |
142 QGraphicsItem::ItemIsMovable |
143 QGraphicsItem::ItemSendsGeometryChanges);
144 m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
145 if (m_geometryWindow != nullptr) {
146 QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
147 QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
148 }
149
150 // Shadow item is not selectable so it needs no stored data. Do NOT
151 // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
152 m_shadowZeroWidthEllipse = new GraphicsPointEllipse (*this,
154 - radiusSigned,
155 2 * radiusSigned + 1,
156 2 * radiusSigned + 1));
157 m_shadowZeroWidthEllipse->setParentItem(m_graphicsItemPolygon); // Dragging parent also drags child
158
159 m_shadowZeroWidthEllipse->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
160 m_shadowZeroWidthEllipse->setEnabled (true);
161
162 m_graphicsItemEllipse->setShadow (m_shadowZeroWidthEllipse);
163}
164
165void GraphicsPoint::createPointPolygon (const QPolygonF &polygon)
166{
167 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::createPointPolygon";
168
169 m_graphicsItemPolygon = new GraphicsPointPolygon (*this,
170 polygon);
171 m_scene.addItem (m_graphicsItemPolygon);
172
173 m_graphicsItemPolygon->setZValue (Z_VALUE_POINT);
174 m_graphicsItemPolygon->setData (DATA_KEY_IDENTIFIER, m_identifier);
175 m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
176 m_graphicsItemPolygon->setPos (m_posScreen.x (),
177 m_posScreen.y ());
178 m_graphicsItemPolygon->setPen (QPen (QBrush (m_color), m_lineWidth));
179 m_graphicsItemPolygon->setEnabled (true);
180 m_graphicsItemPolygon->setFlags (QGraphicsItem::ItemIsSelectable |
181 QGraphicsItem::ItemIsMovable |
182 QGraphicsItem::ItemSendsGeometryChanges);
183 m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
184 if (m_geometryWindow != nullptr) {
185 QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
186 QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
187 }
188
189 // Shadow item is not selectable so it needs no stored data. Do NOT
190 // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
191 m_shadowZeroWidthPolygon = new GraphicsPointPolygon (*this,
192 polygon);
193 m_shadowZeroWidthPolygon->setParentItem(m_graphicsItemPolygon); // Dragging parent also drags child
194
195 m_shadowZeroWidthPolygon->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
196 m_shadowZeroWidthPolygon->setEnabled (true);
197
198 m_graphicsItemPolygon->setShadow (m_shadowZeroWidthPolygon);
199}
200
202{
203 if (m_graphicsItemEllipse == nullptr) {
204 return m_graphicsItemPolygon->data (key);
205 } else {
206 return m_graphicsItemEllipse->data (key);
207 }
208}
209
211{
212 return m_highlightOpacity;
213}
214
216{
217 if (m_graphicsItemEllipse == nullptr) {
218 return m_graphicsItemPolygon->pos ();
219 } else {
220 return m_graphicsItemEllipse->pos ();
221 }
222}
223
226 double ordinalKey) const
227{
228 str << indentation << "GraphicsPoint\n";
229
231
232 QString identifier;
234 QPointF pos;
235 if (m_graphicsItemEllipse == nullptr) {
236 identifier = m_graphicsItemPolygon->data (DATA_KEY_IDENTIFIER).toString ();
237 pointType = "polygon";
238 pos = m_graphicsItemPolygon->pos();
239 } else {
240 identifier = m_graphicsItemEllipse->data (DATA_KEY_IDENTIFIER).toString ();
241 pointType = "ellipse";
242 pos = m_graphicsItemEllipse->pos();
243 }
244
245 DataKey type = static_cast<DataKey> (data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt());
246
247 str << indentation << identifier
248 << " ordinalKey=" << ordinalKey
249 << " dataIdentifier=" << data (DATA_KEY_IDENTIFIER).toString().toLatin1().data()
250 << " dataType=" << dataKeyToString (type).toLatin1().data()
251 << " " << pointType << "Pos=" << QPointFToString (pos) << "\n";
252}
253
255{
256 m_wanted = false;
257}
258
259void GraphicsPoint::setData (int key, const QVariant &data)
260{
261 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setData"
262 << " key=" << dataKeyToString (static_cast<DataKey> (key)).toLatin1().data()
263 << " data=" << data.toString().toLatin1().data();
264
265 if (m_graphicsItemEllipse == nullptr) {
266 m_graphicsItemPolygon->setData (key, data);
267 } else {
268 m_graphicsItemEllipse->setData (key, data);
269 }
270}
271
272void GraphicsPoint::setHighlightOpacity (double highlightOpacity)
273{
274 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setHighlightOpacity"
275 << " identifier=" << m_identifier.toLatin1().data()
276 << " highlightOpacity=" << highlightOpacity;
277
278 m_highlightOpacity = highlightOpacity;
279}
280
282{
283 if (m_graphicsItemEllipse == nullptr) {
284 m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsFocusable, false);
285 m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsMovable, false);
286 m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsSelectable, false);
287 } else {
288 m_graphicsItemEllipse->setFlag (QGraphicsItem::ItemIsFocusable, false);
289 m_graphicsItemEllipse->setFlag (QGraphicsItem::ItemIsMovable, false);
290 m_graphicsItemEllipse->setFlag (QGraphicsItem::ItemIsSelectable, false);
291 }
292}
293
295{
296 // Setting pen and radius of parent graphics items below also affects the child shadows
297 // (m_shadowItemPolygon and m_shadowItemEllipse)
298 if (m_graphicsItemEllipse == nullptr) {
299 if (pointStyle.shape() == POINT_SHAPE_CIRCLE) {
300
301 // Transition from non-circle to circle. Deleting parent also deletes child shadow
302 delete m_graphicsItemPolygon;
303 m_graphicsItemPolygon = nullptr;
304 m_shadowZeroWidthPolygon = nullptr;
305
306 createPointEllipse (unsigned (pointStyle.radius()));
307
308 } else {
309
310 // Update polygon
311 m_graphicsItemPolygon->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
312 pointStyle.lineWidth()));
313 m_shadowZeroWidthPolygon->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
314 pointStyle.lineWidth()));
315 m_graphicsItemPolygon->setPolygon (pointStyle.polygon());
316 m_shadowZeroWidthPolygon->setPolygon (pointStyle.polygon());
317
318 }
319 } else {
320 if (pointStyle.shape() != POINT_SHAPE_CIRCLE) {
321
322 // Transition from circle to non-circlee. Deleting parent also deletes child shadow
323 delete m_graphicsItemEllipse;
324 m_graphicsItemEllipse = nullptr;
325 m_shadowZeroWidthEllipse = nullptr;
326
327 createPointPolygon (pointStyle.polygon());
328
329 } else {
330
331 // Update circle
332 m_graphicsItemEllipse->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
333 pointStyle.lineWidth()));
334 m_shadowZeroWidthEllipse->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
335 pointStyle.lineWidth()));
336 m_graphicsItemEllipse->setRadius (pointStyle.radius());
337 m_shadowZeroWidthEllipse->setRadius (pointStyle.radius());
338 }
339 }
340}
341
343{
344 if (m_graphicsItemEllipse == nullptr) {
345 m_graphicsItemPolygon->setPos (pos);
346 } else {
347 m_graphicsItemEllipse->setPos (pos);
348 }
349}
350
352{
353 m_wanted = true;
354}
355
357{
358 setPointStyle (curveStyle.pointStyle()); // This point
359}
360
362{
363 return m_wanted;
364}
QString dataKeyToString(DataKey dataKey)
Definition DataKey.cpp:9
DataKey
Index values for storing item details in QGraphicsItem using setData/data.
Definition DataKey.h:13
@ DATA_KEY_GRAPHICS_ITEM_TYPE
‍Unique identifier for QGraphicsItem object
Definition DataKey.h:15
@ DATA_KEY_IDENTIFIER
Definition DataKey.h:14
const int INNER_RADIUS_MIN
QColor ColorPaletteToQColor(ColorPalette color)
Definition EnumsToQt.cpp:15
@ GRAPHICS_ITEM_TYPE_POINT
const double MAX_OPACITY
const double DEFAULT_HIGHLIGHT_OPACITY
const double ZERO_WIDTH
log4cpp::Category * mainCat
Definition Logger.cpp:14
const QString INDENTATION_DELTA
@ POINT_SHAPE_CIRCLE
Definition PointShape.h:13
QString QPointFToString(const QPointF &pos)
const int Z_VALUE_POINT
Definition ZValues.cpp:12
Container for LineStyle and PointStyle for one Curve.
Definition CurveStyle.h:19
PointStyle pointStyle() const
Get method for PointStyle.
Window that displays the geometry information, as a table, for the current curve.
Base class for adding identifiers to graphics items that represent Points.
This class add event handling to QGraphicsEllipseItem.
void setShadow(GraphicsPointEllipse *shadow)
Bind this graphics item to its shadow.
void setRadius(int radius)
Update the radius.
This class add event handling to QGraphicsPolygonItem.
void setShadow(GraphicsPointPolygon *shadow)
Bind this graphics item to its shadow.
QPointF pos() const
Proxy method for QGraphicsItem::pos.
void setWanted()
Mark point as wanted. Marking as unwanted is done by the reset function.
void setData(int key, const QVariant &data)
Proxy method for QGraphicsItem::setData.
void setPointStyle(const PointStyle &pointStyle)
Update the point style.
void updateCurveStyle(const CurveStyle &curveStyle)
Update point and line styles that comprise the curve style.
void setPassive()
Prevent automatic focus on point (=make it passive) for scale bar so drags can be made to work proper...
void reset()
Mark point as unwanted, and unbind any bound lines.
bool wanted() const
Identify point as wanted//unwanted.
GraphicsPoint(QGraphicsScene &scene, const QString &identifier, const QPointF &posScreen, const QColor &color, unsigned int radius, double lineWidth, GeometryWindow *geometryWindow)
Constructor of circular point.
void printStream(QString indentation, QTextStream &str, double ordinalKey) const
Debugging method that supports print method of this class and printStream method of some other class(...
~GraphicsPoint()
Destructor. This remove the graphics item from the scene.
QRectF boundingRect() const
Proxy method for QGraphicsItem::boundingRect.
void setHighlightOpacity(double highlightOpacity)
Set method for highlight opacity.
double highlightOpacity() const
Get method for highlight opacity.
void setPos(const QPointF pos)
Update the position.
QVariant data(int key) const
Proxy method for QGraphicsItem::data.
Details for a specific Point.
Definition PointStyle.h:21
unsigned int radius() const
Radius of point. For a circle this is all that is needed to draw a circle. For a polygon,...
QPolygonF polygon() const
Return the polygon for creating a QGraphicsPolygonItem. The size is determined by the radius.
PointShape shape() const
Get method for point shape.
ColorPalette paletteColor() const
Get method for point color.
int lineWidth() const
Get method for line width.
#define LOG4CPP_DEBUG_S(logger)
Definition convenience.h:20