Engauge Digitizer  2
GraphicsScene.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 "CallbackSceneUpdateAfterCommand.h"
8 #include "Curve.h"
9 #include "CurvesGraphs.h"
10 #include "CurveStyles.h"
11 #include "DataKey.h"
12 #include "EngaugeAssert.h"
13 #include "EnumsToQt.h"
14 #include "GeometryWindow.h"
15 #include "GraphicsItemType.h"
16 #include "GraphicsPoint.h"
17 #include "GraphicsPointFactory.h"
18 #include "GraphicsScene.h"
19 #include "Logger.h"
20 #include "MainWindow.h"
21 #include "Point.h"
22 #include "PointStyle.h"
23 #include <QApplication>
24 #include <QGraphicsItem>
25 #include "QtToString.h"
26 #include "Transformation.h"
27 
29  QGraphicsScene(mainWindow)
30 {
31 }
32 
33 void GraphicsScene::addTemporaryPoint (const QString &identifier,
34  GraphicsPoint *point)
35 {
36  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::addTemporaryPoint"
37  << " identifer=" << identifier.toLatin1().data();
38 
39  m_graphicsLinesForCurves.addPoint (AXIS_CURVE_NAME,
40  identifier,
42  *point);
43 }
44 
46  GraphicsPoint *point1,
47  const QString &pointIdentifier0,
48  const QString &pointIdentifier1)
49 {
50  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::addTemporaryScaleBar";
51 
52  const double ORDINAL_0 = 0, ORDINAL_1 = 1;
53 
54  m_graphicsLinesForCurves.addPoint (AXIS_CURVE_NAME,
55  pointIdentifier0,
56  ORDINAL_0,
57  *point0);
58  m_graphicsLinesForCurves.addPoint (AXIS_CURVE_NAME,
59  pointIdentifier1,
60  ORDINAL_1,
61  *point1);
62 }
63 
64 GraphicsPoint *GraphicsScene::createPoint (const QString &identifier,
65  const PointStyle &pointStyle,
66  const QPointF &posScreen,
67  GeometryWindow *geometryWindow)
68 {
69  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::createPoint"
70  << " identifier=" << identifier.toLatin1().data();
71 
72  // Ordinal value is initially computed as one plus the max ordinal seen so far. This initial ordinal value will be overridden if the
73  // cordinates determine the ordinal values.
74  //
75  // This is an N-squared algorithm and may be worth replacing later
76  GraphicsPointFactory pointFactory;
77  GraphicsPoint *point = pointFactory.createPoint (*this,
78  identifier,
79  posScreen,
80  pointStyle,
81  geometryWindow);
82 
83  point->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
84 
85  return point;
86 }
87 
88 QString GraphicsScene::dumpCursors () const
89 {
90  QString cursorOverride = (QApplication::overrideCursor () != 0) ?
91  QtCursorToString (QApplication::overrideCursor ()->shape ()) :
92  "<null>";
93  QString cursorImage = QtCursorToString (image()->cursor().shape ());
94 
95  QString dump = QString ("overrideCursor=%1 imageCursor=%2")
96  .arg (cursorOverride)
97  .arg (cursorImage);
98 
99  return dump;
100 }
101 
103 {
104  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::hideAllItemsExceptImage";
105 
106  for (int index = 0; index < QGraphicsScene::items().count(); index++) {
107  QGraphicsItem *item = QGraphicsScene::items().at(index);
108 
109  if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt() == GRAPHICS_ITEM_TYPE_IMAGE) {
110 
111  item->show();
112 
113  } else {
114 
115  item->hide();
116 
117  }
118  }
119 }
120 
121 const QGraphicsPixmapItem *GraphicsScene::image () const
122 {
123  // Loop through items in scene to find the image
124  QList<QGraphicsItem*> items = QGraphicsScene::items();
125  QList<QGraphicsItem*>::iterator itr;
126  for (itr = items.begin(); itr != items.end(); itr++) {
127 
128  QGraphicsItem* item = *itr;
129  if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_IMAGE) {
130 
131  return (QGraphicsPixmapItem *) item;
132  }
133  }
134 
135  return 0;
136 }
137 
139 {
140  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::positionHasChangedPointIdentifiers";
141 
142  QStringList movedIds;
143 
144  const QList<QGraphicsItem*> &items = QGraphicsScene::items();
145  QList<QGraphicsItem*>::const_iterator itr;
146  for (itr = items.begin(); itr != items.end(); itr++) {
147 
148  const QGraphicsItem *item = *itr;
149 
150  // Skip the image and only keep the Points
151  bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
152  if (isPoint) {
153 
154  QString identifier = item->data (DATA_KEY_IDENTIFIER).toString ();
155  bool positionHasChanged = item->data (DATA_KEY_POSITION_HAS_CHANGED).toBool ();
156 
157  LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsScene::positionHasChangedPointIdentifiers"
158  << " identifier=" << identifier.toLatin1().data()
159  << " positionHasChanged=" << (positionHasChanged ? "yes" : "no");
160 
161  if (isPoint && positionHasChanged) {
162 
163  // Add Point to the list
164  movedIds << item->data(DATA_KEY_IDENTIFIER).toString ();
165 
166  }
167  }
168  }
169 
170  return movedIds;
171 }
172 
173 void GraphicsScene::printStream (QString indentation,
174  QTextStream &str)
175 {
176  m_graphicsLinesForCurves.printStream (indentation,
177  str);
178 }
179 
180 void GraphicsScene::removePoint (const QString &identifier)
181 {
182  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removePoint identifier=" << identifier.toLatin1().data();
183 
184  m_graphicsLinesForCurves.removePoint (identifier);
185 }
186 
188 {
189  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removeTemporaryPointIfExists";
190 
191  m_graphicsLinesForCurves.removeTemporaryPointIfExists ();
192 }
193 
195 {
196  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removeTemporaryScaleBarIfExists";
197 }
198 
200 {
201  // LOG4CPP_INFO_S is below
202 
203  int itemsBefore = items().count();
204 
205  m_graphicsLinesForCurves.resetOnLoad();
206 
207  int itemsAfter = items().count();
208 
209  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::resetOnLoad"
210  << " itemsBefore=" << itemsBefore
211  << " itemsAfter=" << itemsAfter;
212 }
213 
215 {
216  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::resetPositionHasChangedFlags";
217 
218  QList<QGraphicsItem*> itms = items ();
219  QList<QGraphicsItem*>::const_iterator itr;
220  for (itr = itms.begin (); itr != itms.end (); itr++) {
221 
222  QGraphicsItem *item = *itr;
223  item->setData (DATA_KEY_POSITION_HAS_CHANGED, false);
224  }
225 }
226 
228  bool showAll,
229  const QString &curveNameWanted)
230 {
231  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::showCurves"
232  << " show=" << (show ? "true" : "false")
233  << " showAll=" << (showAll ? "true" : "false")
234  << " curve=" << curveNameWanted.toLatin1().data();
235 
236  const QList<QGraphicsItem*> &items = QGraphicsScene::items();
237  QList<QGraphicsItem*>::const_iterator itr;
238  for (itr = items.begin(); itr != items.end(); itr++) {
239 
240  QGraphicsItem* item = *itr;
241 
242  // Skip the image and only process the Points
243  bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
244  bool isCurve = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_LINE);
245 
246  if (isPoint || isCurve) {
247 
248  bool showThis = show;
249  if (show && !showAll) {
250  QString identifier = item->data (DATA_KEY_IDENTIFIER).toString ();
251 
252  if (isPoint) {
253 
254  QString curveNameGot = Point::curveNameFromPointIdentifier (identifier);
255  showThis = (curveNameWanted == curveNameGot);
256 
257  } else {
258 
259  showThis = (curveNameWanted == identifier);
260 
261  }
262  }
263 
264  item->setVisible (showThis);
265 
266  }
267  }
268 }
269 
271  double highlightOpacity,
272  GeometryWindow *geometryWindow)
273 {
274  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateAfterCommand";
275 
276  m_graphicsLinesForCurves.updateHighlightOpacity (highlightOpacity);
277 
278  updateCurves (cmdMediator);
279 
280  // Update the points
281  updatePointMembership (cmdMediator,
282  geometryWindow);
283 }
284 
285 void GraphicsScene::updateCurves (CmdMediator &cmdMediator)
286 {
287  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateCurves";
288 
289  // Desired curve names include both axes and graph curve names
290  QStringList curveNames;
291  curveNames << AXIS_CURVE_NAME;
292  curveNames << cmdMediator.document().curvesGraphsNames();
293 
294  m_graphicsLinesForCurves.addRemoveCurves (*this,
295  curveNames);
296 }
297 
298 void GraphicsScene::updateCurveStyles (const CurveStyles &modelCurveStyles)
299 {
300  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateCurveStyles";
301 
302  m_graphicsLinesForCurves.updateCurveStyles (modelCurveStyles);
303 }
304 
306  const Transformation &transformation)
307 {
308  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateGraphicsLinesToMatchGraphicsPoints";
309 
310  if (transformation.transformIsDefined()) {
311 
312  // Ordinals must be updated to reflect reordering that may have resulted from dragging points
313  m_graphicsLinesForCurves.updatePointOrdinalsAfterDrag (curveStyles,
314  transformation);
315 
316  // Recompute the lines one time for efficiency
317  m_graphicsLinesForCurves.updateGraphicsLinesToMatchGraphicsPoints (curveStyles);
318  }
319 }
320 
321 void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator,
322  GeometryWindow *geometryWindow)
323 {
324  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updatePointMembership";
325 
326  CallbackSceneUpdateAfterCommand ftor (m_graphicsLinesForCurves,
327  *this,
328  cmdMediator.document (),
329  geometryWindow);
330  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
332 
333  // First pass:
334  // 1) Mark all points as Not Wanted (this is done while creating the map)
335  m_graphicsLinesForCurves.lineMembershipReset ();
336 
337  // Next pass:
338  // 1) Existing points that are found in the map are marked as Wanted
339  // 2) Add new points that were just created in the Document. The new points are marked as Wanted
340  cmdMediator.iterateThroughCurvePointsAxes (ftorWithCallback);
341  cmdMediator.iterateThroughCurvesPointsGraphs (ftorWithCallback);
342 
343  // Next pass:
344  // 1) Remove points that were just removed from the Document
345  m_graphicsLinesForCurves.lineMembershipPurge (cmdMediator.document().modelCurveStyles());
346 }
void updateGraphicsLinesToMatchGraphicsPoints(const CurveStyles &modelCurveStyles, const Transformation &transformation)
A mouse move has just occurred so move the selected points, since they were dragged.
void lineMembershipPurge(const CurveStyles &curveStyles)
Mark the end of addPoint calls. Remove stale lines, insert missing lines, and draw the graphics lines...
void removePoint(const QString &identifier)
Remove the specified point. The act of deleting it will automatically remove it from the GraphicsScen...
static QString curveNameFromPointIdentifier(const QString &pointIdentifier)
Parse the curve name from the specified point identifier. This does the opposite of uniqueIdentifierG...
Definition: Point.cpp:227
Factor for generating GraphicsPointAbstractBase class objects.
Callback for updating the QGraphicsItems in the scene after a command may have modified Points in Cur...
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
void printStream(QString indentation, QTextStream &str)
Debugging method that supports print method of this class and printStream method of some other class(...
void removePoint(const QString &identifier)
Remove specified point. This aborts if the point does not exist.
GraphicsScene(MainWindow *mainWindow)
Single constructor.
Model for DlgSettingsCurveProperties and CmdSettingsCurveProperties.
Definition: CurveStyles.h:22
void addPoint(const QString &curveName, const QString &pointIdentifier, double ordinal, GraphicsPoint &point)
Add new point.
void lineMembershipReset()
Mark points as unwanted. Afterwards, lineMembershipPurge gets called.
QVariant data(int key) const
Proxy method for QGraphicsItem::data.
void updateAfterCommand(CmdMediator &cmdMediator, double highlightOpacity, GeometryWindow *geometryWindow)
Update the Points and their Curves after executing a command.
void addTemporaryScaleBar(GraphicsPoint *point0, GraphicsPoint *point1, const QString &pointIdentifier0, const QString &pointIdentifier1)
Add temporary scale bar to scene.
void removeTemporaryScaleBarIfExists()
Remove temporary scale bar, composed of two points and the line between them.
void removeTemporaryPointIfExists()
Remove temporary point if it exists.
Window that displays the geometry information, as a table, for the current curve. ...
QStringList positionHasChangedPointIdentifiers() const
Return a list of identifiers for the points that have moved since the last call to resetPositionHasCh...
void setData(int key, const QVariant &data)
Proxy method for QGraphicsItem::setData.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
CallbackSearchReturn callback(const QString &, const Point &point)
Callback method.
GraphicsPoint * createPoint(QGraphicsScene &scene, const QString &identifier, const QPointF &posScreen, const PointStyle &pointStyle, GeometryWindow *geometryWindow)
Create circle or polygon point according to the PointStyle.
void updatePointOrdinalsAfterDrag(const CurveStyles &curveStyles, const Transformation &transformation)
See GraphicsScene::updateOrdinalsAfterDrag.
GraphicsPoint * createPoint(const QString &identifier, const PointStyle &pointStyle, const QPointF &posScreen, GeometryWindow *geometryWindow)
Create one QGraphicsItem-based object that represents one Point. It is NOT added to m_graphicsLinesFo...
void updateGraphicsLinesToMatchGraphicsPoints(const CurveStyles &curveStyles)
Calls to moveLinesWithDraggedPoint have finished so update the lines correspondingly.
Affine transformation between screen and graph coordinates, based on digitized axis points...
Details for a specific Point.
Definition: PointStyle.h:20
static double UNDEFINED_ORDINAL()
Get method for undefined ordinal constant.
Definition: Point.h:132
void resetPositionHasChangedFlags()
Reset positionHasChanged flag for all items. Typically this is done as part of mousePressEvent.
Graphics item for drawing a circular or polygonal Point.
Definition: GraphicsPoint.h:43
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update curve styles after settings changed.
void removeTemporaryPointIfExists()
Remove temporary point if it exists.
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded...
Command queue stack.
Definition: CmdMediator.h:23
void addTemporaryPoint(const QString &identifier, GraphicsPoint *point)
Add one temporary point to m_graphicsLinesForCurves. Non-temporary points are handled by the updateLi...
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update the curve style for every curve.
void iterateThroughCurvesPointsGraphs(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for all the graphs curves.
Definition: CmdMediator.cpp:97
void iterateThroughCurvePointsAxes(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for the single axes curve.
Definition: CmdMediator.cpp:87
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:696
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded...
void hideAllItemsExceptImage()
Hide all graphics items, except background image, in preparation for preview during IMPORT_TYPE_ADVAN...
void addRemoveCurves(GraphicsScene &scene, const QStringList &curveNames)
Add new curves and remove expired curves to match the specified list.
void showCurves(bool show, bool showAll=false, const QString &curveName="")
Show or hide all Curves (if showAll is true) or just the selected Curve (if showAll is false);...
void updateHighlightOpacity(double highlightOpacity)
Update the highlight opacity value. This may or may not affect the current display immediately depend...
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: Document.cpp:346
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:89