Engauge Digitizer  2
GraphicsPoint.cpp
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 "GraphicsItemType.h"
11 #include "GraphicsPoint.h"
12 #include "GraphicsPointEllipse.h"
13 #include "GraphicsPointPolygon.h"
14 #include "Logger.h"
15 #include "PointStyle.h"
16 #include <QGraphicsEllipseItem>
17 #include <QGraphicsPolygonItem>
18 #include <QGraphicsScene>
19 #include <QGraphicsSceneContextMenuEvent>
20 #include <QPen>
21 #include <QTextStream>
22 #include "QtToString.h"
23 
24 const double ZERO_WIDTH = 0.0;
25 const double Z_VALUE = 100.0; // Put on top of Segments in DlgSettingsSegments
26 
27 GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
28  const QString &identifier,
29  const QPointF &posScreen,
30  const QColor &color,
31  unsigned int radius,
32  double lineWidth) :
34  m_scene (scene),
35  m_graphicsItemEllipse (0),
36  m_shadowZeroWidthEllipse (0),
37  m_graphicsItemPolygon (0),
38  m_shadowZeroWidthPolygon (0),
39  m_identifier (identifier),
40  m_posScreen (posScreen),
41  m_color (color),
42  m_lineWidth (lineWidth),
43  m_wanted (true)
44 {
45  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPoint::GraphicsPoint"
46  << " identifier=" << identifier.toLatin1 ().data ();
47 
48  createPointEllipse (radius);
49 }
50 
51 GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
52  const QString &identifier,
53  const QPointF &posScreen,
54  const QColor &color,
55  const QPolygonF &polygon,
56  double lineWidth) :
58  m_scene (scene),
59  m_graphicsItemEllipse (0),
60  m_shadowZeroWidthEllipse (0),
61  m_graphicsItemPolygon (0),
62  m_shadowZeroWidthPolygon (0),
63  m_identifier (identifier),
64  m_posScreen (posScreen),
65  m_color (color),
66  m_lineWidth (lineWidth),
67  m_wanted (true)
68 {
69  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPoint::GraphicsPoint "
70  << " identifier=" << identifier.toLatin1 ().data ();
71 
72  createPointPolygon (polygon);
73 }
74 
76 {
77  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPoint::~GraphicsPoint";
78 
79  if (m_graphicsItemEllipse == 0) {
80 
81  QGraphicsScene *scene = m_graphicsItemPolygon->scene();
82 
83  // Since m_shadowZeroWidthPolygon is a child of m_graphicsItemPolygon, removing the parent removes both
84  scene->removeItem (m_graphicsItemPolygon);
85  delete m_graphicsItemPolygon;
86  m_graphicsItemPolygon = 0;
87  m_shadowZeroWidthPolygon = 0;
88 
89 
90  } else {
91 
92  QGraphicsScene *scene = m_graphicsItemEllipse->scene();
93 
94  // Since m_shadowZeroWidthEllipse is a child of m_graphicsItemEllipse, removing the parent removes both
95  scene->removeItem (m_graphicsItemEllipse);
96  delete m_graphicsItemEllipse;
97  m_graphicsItemEllipse = 0;
98  m_shadowZeroWidthEllipse = 0;
99 
100  }
101 }
102 
103 void GraphicsPoint::createPointEllipse (unsigned int radius)
104 {
105  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPoint::createPointEllipse";
106 
107  const int radiusSigned = radius; // Radius must be signed before multiplying by -1 below, for Visual Studio
108  m_graphicsItemEllipse = new GraphicsPointEllipse (*this,
109  QRect (- radiusSigned,
110  - radiusSigned,
111  2 * radiusSigned + 1,
112  2 * radiusSigned + 1));
113  m_scene.addItem (m_graphicsItemEllipse);
114 
115  m_graphicsItemEllipse->setZValue (Z_VALUE);
116  m_graphicsItemEllipse->setData (DATA_KEY_IDENTIFIER, m_identifier);
117  m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
118  m_graphicsItemEllipse->setPos (m_posScreen.x (),
119  m_posScreen.y ());
120  m_graphicsItemEllipse->setPen (QPen (QBrush (m_color), m_lineWidth));
121  m_graphicsItemEllipse->setEnabled (true);
122  m_graphicsItemEllipse->setFlags (QGraphicsItem::ItemIsSelectable |
123  QGraphicsItem::ItemIsMovable |
124  QGraphicsItem::ItemSendsGeometryChanges);
125 
126  m_graphicsItemEllipse->setToolTip (m_identifier);
127  m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
128 
129  // Shadow item is not selectable so it needs no stored data. Do NOT
130  // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
131  m_shadowZeroWidthEllipse = new GraphicsPointEllipse (*this,
132  QRect (- radiusSigned,
133  - radiusSigned,
134  2 * radiusSigned + 1,
135  2 * radiusSigned + 1));
136  m_shadowZeroWidthEllipse->setParentItem(m_graphicsItemPolygon); // Dragging parent also drags child
137 
138  m_shadowZeroWidthEllipse->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
139  m_shadowZeroWidthEllipse->setEnabled (true);
140 }
141 
142 void GraphicsPoint::createPointPolygon (const QPolygonF &polygon)
143 {
144  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPoint::createPointPolygon";
145 
146  m_graphicsItemPolygon = new GraphicsPointPolygon (*this,
147  polygon);
148  m_scene.addItem (m_graphicsItemPolygon);
149 
150  m_graphicsItemPolygon->setZValue (Z_VALUE);
151  m_graphicsItemPolygon->setData (DATA_KEY_IDENTIFIER, m_identifier);
152  m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
153  m_graphicsItemPolygon->setPos (m_posScreen.x (),
154  m_posScreen.y ());
155  m_graphicsItemPolygon->setPen (QPen (QBrush (m_color), m_lineWidth));
156  m_graphicsItemPolygon->setEnabled (true);
157  m_graphicsItemPolygon->setFlags (QGraphicsItem::ItemIsSelectable |
158  QGraphicsItem::ItemIsMovable |
159  QGraphicsItem::ItemSendsGeometryChanges);
160 
161  m_graphicsItemPolygon->setToolTip (m_identifier);
162  m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
163 
164  // Shadow item is not selectable so it needs no stored data. Do NOT
165  // call QGraphicsScene::addItem since the QGraphicsItem::setParentItem call adds the item
166  m_shadowZeroWidthPolygon = new GraphicsPointPolygon (*this,
167  polygon);
168  m_shadowZeroWidthPolygon->setParentItem(m_graphicsItemPolygon); // Dragging parent also drags child
169 
170  m_shadowZeroWidthPolygon->setPen (QPen (QBrush (m_color), ZERO_WIDTH));
171  m_shadowZeroWidthPolygon->setEnabled (true);
172 }
173 
174 QVariant GraphicsPoint::data (int key) const
175 {
176  if (m_graphicsItemEllipse == 0) {
177  return m_graphicsItemPolygon->data (key);
178  } else {
179  return m_graphicsItemEllipse->data (key);
180  }
181 }
182 
183 QPointF GraphicsPoint::pos () const
184 {
185  if (m_graphicsItemEllipse == 0) {
186  return m_graphicsItemPolygon->pos ();
187  } else {
188  return m_graphicsItemEllipse->pos ();
189  }
190 }
191 
192 void GraphicsPoint::printStream (QString indentation,
193  QTextStream &str,
194  double ordinalKey) const
195 {
196  str << indentation << "GraphicsPoint\n";
197 
198  indentation += INDENTATION_DELTA;
199 
200  QString identifier;
201  QString pointType;
202  QPointF pos;
203  if (m_graphicsItemEllipse == 0) {
204  identifier = m_graphicsItemPolygon->data (DATA_KEY_IDENTIFIER).toString ();
205  pointType = "polygon";
206  pos = m_graphicsItemPolygon->pos();
207  } else {
208  identifier = m_graphicsItemEllipse->data (DATA_KEY_IDENTIFIER).toString ();
209  pointType = "ellipse";
210  pos = m_graphicsItemEllipse->pos();
211  }
212 
213  DataKey type = (DataKey) data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt();
214 
215  str << indentation << identifier
216  << " ordinalKey=" << ordinalKey
217  << " dataIdentifier=" << data (DATA_KEY_IDENTIFIER).toString().toLatin1().data()
218  << " dataType=" << dataKeyToString (type).toLatin1().data()
219  << " " << pointType << "Pos=" << QPointFToString (pos) << "\n";
220 }
221 
223 {
224  m_wanted = false;
225 }
226 
227 void GraphicsPoint::setData (int key, const QVariant &data)
228 {
229  LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setData"
230  << " key=" << dataKeyToString ((DataKey) key).toLatin1().data()
231  << " data=" << data.toString().toLatin1().data();
232 
233  if (m_graphicsItemEllipse == 0) {
234  m_graphicsItemPolygon->setData (key, data);
235  } else {
236  m_graphicsItemEllipse->setData (key, data);
237  }
238 }
239 
241 {
242  // Setting pen and radius of parent graphics items below also affects the child shadows
243  // (m_shadowItemPolygon and m_shadowItemEllipse)
244  if (m_graphicsItemEllipse == 0) {
245  if (pointStyle.shape() == POINT_SHAPE_CIRCLE) {
246 
247  // Transition from non-circle to circle. Deleting parent also deletes child shadow
248  delete m_graphicsItemPolygon;
249  m_graphicsItemPolygon = 0;
250  m_shadowZeroWidthPolygon = 0;
251 
252  createPointEllipse (pointStyle.radius());
253 
254  } else {
255 
256  // Update polygon
257  m_graphicsItemPolygon->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
258  pointStyle.lineWidth()));
259  m_shadowZeroWidthPolygon->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
260  pointStyle.lineWidth()));
261  m_graphicsItemPolygon->setPolygon (pointStyle.polygon());
262  m_shadowZeroWidthPolygon->setPolygon (pointStyle.polygon());
263 
264  }
265  } else {
266  if (pointStyle.shape() != POINT_SHAPE_CIRCLE) {
267 
268  // Transition from circle to non-circlee. Deleting parent also deletes child shadow
269  delete m_graphicsItemEllipse;
270  m_graphicsItemEllipse = 0;
271  m_shadowZeroWidthEllipse = 0;
272 
273  createPointPolygon (pointStyle.polygon());
274 
275  } else {
276 
277  // Update circle
278  m_graphicsItemEllipse->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
279  pointStyle.lineWidth()));
280  m_shadowZeroWidthEllipse->setPen (QPen (ColorPaletteToQColor(pointStyle.paletteColor()),
281  pointStyle.lineWidth()));
282  m_graphicsItemEllipse->setRadius (pointStyle.radius());
283  m_shadowZeroWidthEllipse->setRadius (pointStyle.radius());
284  }
285  }
286 }
287 
288 void GraphicsPoint::setPos (const QPointF pos)
289 {
290  if (m_graphicsItemEllipse == 0) {
291  return m_graphicsItemPolygon->setPos (pos);
292  } else {
293  return m_graphicsItemEllipse->setPos (pos);
294  }
295 }
296 
297 void GraphicsPoint::setToolTip (const QString &toolTip)
298 {
299  if (m_graphicsItemEllipse == 0) {
300  m_graphicsItemPolygon->setToolTip (toolTip);
301  } else {
302  m_graphicsItemEllipse->setToolTip (toolTip);
303  }
304 }
305 
307 {
308  m_wanted = true;
309 }
310 
312 {
313  setPointStyle (curveStyle.pointStyle()); // This point
314 }
315 
317 {
318  return m_wanted;
319 }
void setWanted()
Mark point as wanted. Marking as unwanted is done by the reset function.
int lineWidth() const
Get method for line width.
Definition: PointStyle.cpp:119
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(...
QPolygonF polygon() const
Return the polygon for creating a QGraphicsPolygonItem. The size is determined by the radius...
Definition: PointStyle.cpp:155
Base class for adding identifiers to graphics items that represent Points.
PointStyle pointStyle() const
Get method for PointStyle.
Definition: CurveStyle.cpp:75
void setData(int key, const QVariant &data)
Proxy method for QGraphicsItem::setData.
void setPos(const QPointF pos)
Update the position.
bool wanted() const
Identify point as wanted//unwanted.
void setPointStyle(const PointStyle &pointStyle)
Update the point style.
void updateCurveStyle(const CurveStyle &curveStyle)
Update point and line styles that comprise the curve style.
This class add event handling to QGraphicsEllipseItem.
Details for a specific Point.
Definition: PointStyle.h:20
~GraphicsPoint()
Destructor. This remove the graphics item from the scene.
ColorPalette paletteColor() const
Get method for point color.
Definition: PointStyle.cpp:150
Container for LineStyle and PointStyle for one Curve.
Definition: CurveStyle.h:18
int radius() const
Radius of point. For a circle this is all that is needed to draw a circle. For a polygon, the radius determines the size of the polygon.
Definition: PointStyle.cpp:253
This class add event handling to QGraphicsPolygonItem.
QPointF pos() const
Proxy method for QGraphicsItem::pos.
GraphicsPoint(QGraphicsScene &scene, const QString &identifier, const QPointF &posScreen, const QColor &color, unsigned int radius, double lineWidth)
Constructor of circular point.
QVariant data(int key) const
Proxy method for QGraphicsItem::data.
void setToolTip(const QString &toolTip)
Proxy method for QGraphicsItem::setToolTip.
PointShape shape() const
Get method for point shape.
Definition: PointStyle.cpp:292
void setRadius(int radius)
Update the radius.
void reset()
Mark point as unwanted, and unbind any bound lines.