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,
37 GeometryWindow *geometryWindow) :
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 createPointEllipse (radius);
53}
54
55GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
56 const QString &identifier,
57 const QPointF &posScreen,
58 const QColor &color,
59 const QPolygonF &polygon,
60 double lineWidth,
61 GeometryWindow *geometryWindow) :
63 m_scene (scene),
64 m_graphicsItemEllipse (nullptr),
65 m_shadowZeroWidthEllipse (nullptr),
66 m_graphicsItemPolygon (nullptr),
67 m_shadowZeroWidthPolygon (nullptr),
68 m_identifier (identifier),
69 m_posScreen (posScreen),
70 m_color (color),
71 m_lineWidth (lineWidth),
72 m_wanted (true),
73 m_highlightOpacity (DEFAULT_HIGHLIGHT_OPACITY),
74 m_geometryWindow (geometryWindow)
75{
76 createPointPolygon (polygon);
77}
78
80{
81 if (m_graphicsItemEllipse == nullptr) {
82
83 QGraphicsScene *scene = m_graphicsItemPolygon->scene();
84
85 // Since m_shadowZeroWidthPolygon is a child of m_graphicsItemPolygon, removing the parent removes both
86 scene->removeItem (m_graphicsItemPolygon);
87 delete m_graphicsItemPolygon;
88 m_graphicsItemPolygon = nullptr;
89 m_shadowZeroWidthPolygon = nullptr;
90
91
92 } else {
93
94 QGraphicsScene *scene = m_graphicsItemEllipse->scene();
95
96 // Since m_shadowZeroWidthEllipse is a child of m_graphicsItemEllipse, removing the parent removes both
97 scene->removeItem (m_graphicsItemEllipse);
98 delete m_graphicsItemEllipse;
99 m_graphicsItemEllipse = nullptr;
100 m_shadowZeroWidthEllipse = nullptr;
101
102 }
103}
104
106{
107 if (m_graphicsItemEllipse == nullptr) {
108 return m_graphicsItemPolygon->boundingRect ();
109 } else {
110 return m_graphicsItemEllipse->boundingRect ();
111 }
112}
113
114void GraphicsPoint::createPointEllipse (unsigned int radius)
115{
116 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::createPointEllipse";
117
118 const int radiusSigned = signed (radius); // Radius must be signed before multiplying by -1 below, for Visual Studio
119 m_graphicsItemEllipse = new GraphicsPointEllipse (*this,
120 QRect (- radiusSigned,
121 - radiusSigned,
122 2 * radiusSigned + 1,
123 2 * radiusSigned + 1));
124 m_scene.addItem (m_graphicsItemEllipse);
125
126 m_graphicsItemEllipse->setZValue (Z_VALUE_POINT);
127 m_graphicsItemEllipse->setData (DATA_KEY_IDENTIFIER, m_identifier);
128 m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
129 m_graphicsItemEllipse->setPos (m_posScreen.x (),
130 m_posScreen.y ());
131 m_graphicsItemEllipse->setPen (QPen (QBrush (m_color), m_lineWidth));
132 m_graphicsItemEllipse->setEnabled (true);
133 m_graphicsItemEllipse->setFlags (QGraphicsItem::ItemIsSelectable |
134 QGraphicsItem::ItemIsMovable |
135 QGraphicsItem::ItemSendsGeometryChanges);
136 m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
137 if (m_geometryWindow != nullptr) {
138 QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
139 QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
140 }
141
142 // Shadow item is not selectable so it needs no stored data. Do NOT
143 // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
144 m_shadowZeroWidthEllipse = new GraphicsPointEllipse (*this,
145 QRect (- radiusSigned,
146 - radiusSigned,
147 2 * radiusSigned + 1,
148 2 * radiusSigned + 1));
149 m_shadowZeroWidthEllipse->setParentItem(m_graphicsItemPolygon); // Dragging parent also drags child
150
151 m_shadowZeroWidthEllipse->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
152 m_shadowZeroWidthEllipse->setEnabled (true);
153
154 m_graphicsItemEllipse->setShadow (m_shadowZeroWidthEllipse);
155}
156
157void GraphicsPoint::createPointPolygon (const QPolygonF &polygon)
158{
159 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::createPointPolygon";
160
161 m_graphicsItemPolygon = new GraphicsPointPolygon (*this,
162 polygon);
163 m_scene.addItem (m_graphicsItemPolygon);
164
165 m_graphicsItemPolygon->setZValue (Z_VALUE_POINT);
166 m_graphicsItemPolygon->setData (DATA_KEY_IDENTIFIER, m_identifier);
167 m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
168 m_graphicsItemPolygon->setPos (m_posScreen.x (),
169 m_posScreen.y ());
170 m_graphicsItemPolygon->setPen (QPen (QBrush (m_color), m_lineWidth));
171 m_graphicsItemPolygon->setEnabled (true);
172 m_graphicsItemPolygon->setFlags (QGraphicsItem::ItemIsSelectable |
173 QGraphicsItem::ItemIsMovable |
174 QGraphicsItem::ItemSendsGeometryChanges);
175 m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
176 if (m_geometryWindow != nullptr) {
177 QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
178 QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
179 }
180
181 // Shadow item is not selectable so it needs no stored data. Do NOT
182 // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
183 m_shadowZeroWidthPolygon = new GraphicsPointPolygon (*this,
184 polygon);
185 m_shadowZeroWidthPolygon->setParentItem(m_graphicsItemPolygon); // Dragging parent also drags child
186
187 m_shadowZeroWidthPolygon->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
188 m_shadowZeroWidthPolygon->setEnabled (true);
189
190 m_graphicsItemPolygon->setShadow (m_shadowZeroWidthPolygon);
191}
192
193QVariant GraphicsPoint::data (int key) const
194{
195 if (m_graphicsItemEllipse == nullptr) {
196 return m_graphicsItemPolygon->data (key);
197 } else {
198 return m_graphicsItemEllipse->data (key);
199 }
200}
201
203{
204 return m_highlightOpacity;
205}
206
207QPointF GraphicsPoint::pos () const
208{
209 if (m_graphicsItemEllipse == nullptr) {
210 return m_graphicsItemPolygon->pos ();
211 } else {
212 return m_graphicsItemEllipse->pos ();
213 }
214}
215
216void GraphicsPoint::printStream (QString indentation,
217 QTextStream &str,
218 double ordinalKey) const
219{
220 str << indentation << "GraphicsPoint\n";
221
222 indentation += INDENTATION_DELTA;
223
224 QString identifier;
225 QString pointType;
226 QPointF pos;
227 if (m_graphicsItemEllipse == nullptr) {
228 identifier = m_graphicsItemPolygon->data (DATA_KEY_IDENTIFIER).toString ();
229 pointType = "polygon";
230 pos = m_graphicsItemPolygon->pos();
231 } else {
232 identifier = m_graphicsItemEllipse->data (DATA_KEY_IDENTIFIER).toString ();
233 pointType = "ellipse";
234 pos = m_graphicsItemEllipse->pos();
235 }
236
237 DataKey type = static_cast<DataKey> (data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt());
238
239 str << indentation << identifier
240 << " ordinalKey=" << ordinalKey
241 << " dataIdentifier=" << data (DATA_KEY_IDENTIFIER).toString().toLatin1().data()
242 << " dataType=" << dataKeyToString (type).toLatin1().data()
243 << " " << pointType << "Pos=" << QPointFToString (pos) << "\n";
244}
245
247{
248 m_wanted = false;
249}
250
251void GraphicsPoint::setData (int key, const QVariant &data)
252{
253 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setData"
254 << " key=" << dataKeyToString (static_cast<DataKey> (key)).toLatin1().data()
255 << " data=" << data.toString().toLatin1().data();
256
257 if (m_graphicsItemEllipse == nullptr) {
258 m_graphicsItemPolygon->setData (key, data);
259 } else {
260 m_graphicsItemEllipse->setData (key, data);
261 }
262}
263
265{
266 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setHighlightOpacity"
267 << " identifier=" << m_identifier.toLatin1().data()
268 << " highlightOpacity=" << highlightOpacity;
269
270 m_highlightOpacity = highlightOpacity;
271}
272
274{
275 if (m_graphicsItemEllipse == nullptr) {
276 m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsFocusable, false);
277 m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsMovable, false);
278 m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsSelectable, false);
279 } else {
280 m_graphicsItemEllipse->setFlag (QGraphicsItem::ItemIsFocusable, false);
281 m_graphicsItemEllipse->setFlag (QGraphicsItem::ItemIsMovable, false);
282 m_graphicsItemEllipse->setFlag (QGraphicsItem::ItemIsSelectable, false);
283 }
284}
285
287{
288 // Setting pen and radius of parent graphics items below also affects the child shadows
289 // (m_shadowItemPolygon and m_shadowItemEllipse)
290 if (m_graphicsItemEllipse == nullptr) {
291 if (pointStyle.shape() == POINT_SHAPE_CIRCLE) {
292
293 // Transition from non-circle to circle. Deleting parent also deletes child shadow
294 delete m_graphicsItemPolygon;
295 m_graphicsItemPolygon = nullptr;
296 m_shadowZeroWidthPolygon = nullptr;
297
298 createPointEllipse (unsigned (pointStyle.radius()));
299
300 } else {
301
302 // Update polygon
303 m_graphicsItemPolygon->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
304 pointStyle.lineWidth()));
305 m_shadowZeroWidthPolygon->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
306 pointStyle.lineWidth()));
307 m_graphicsItemPolygon->setPolygon (pointStyle.polygon());
308 m_shadowZeroWidthPolygon->setPolygon (pointStyle.polygon());
309
310 }
311 } else {
312 if (pointStyle.shape() != POINT_SHAPE_CIRCLE) {
313
314 // Transition from circle to non-circlee. Deleting parent also deletes child shadow
315 delete m_graphicsItemEllipse;
316 m_graphicsItemEllipse = nullptr;
317 m_shadowZeroWidthEllipse = nullptr;
318
319 createPointPolygon (pointStyle.polygon());
320
321 } else {
322
323 // Update circle
324 m_graphicsItemEllipse->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
325 pointStyle.lineWidth()));
326 m_shadowZeroWidthEllipse->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
327 pointStyle.lineWidth()));
328 m_graphicsItemEllipse->setRadius (pointStyle.radius());
329 m_shadowZeroWidthEllipse->setRadius (pointStyle.radius());
330 }
331 }
332}
333
334void GraphicsPoint::setPos (const QPointF pos)
335{
336 if (m_graphicsItemEllipse == nullptr) {
337 m_graphicsItemPolygon->setPos (pos);
338 } else {
339 m_graphicsItemEllipse->setPos (pos);
340 }
341}
342
344{
345 m_wanted = true;
346}
347
349{
350 setPointStyle (curveStyle.pointStyle()); // This point
351}
352
354{
355 return m_wanted;
356}
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
Definition DataKey.h:15
@ DATA_KEY_IDENTIFIER
Definition DataKey.h:14
QColor ColorPaletteToQColor(ColorPalette color)
Definition EnumsToQt.cpp:16
@ GRAPHICS_ITEM_TYPE_POINT
const double MAX_OPACITY
const double DEFAULT_HIGHLIGHT_OPACITY
const double ZERO_WIDTH
const double DEFAULT_HIGHLIGHT_OPACITY
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:16
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.
GraphicsPointAbstractBase()
Single constructor.
This class add event handling to QGraphicsEllipseItem.
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