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 
45 GraphicsPoint *GraphicsScene::createPoint (const QString &identifier,
46  const PointStyle &pointStyle,
47  const QPointF &posScreen,
48  GeometryWindow *geometryWindow)
49 {
50  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::createPoint"
51  << " identifier=" << identifier.toLatin1().data();
52 
53  // Ordinal value is initially computed as one plus the max ordinal seen so far. This initial ordinal value will be overridden if the
54  // cordinates determine the ordinal values.
55  //
56  // This is an N-squared algorithm and may be worth replacing later
57  GraphicsPointFactory pointFactory;
58  GraphicsPoint *point = pointFactory.createPoint (*this,
59  identifier,
60  posScreen,
61  pointStyle,
62  geometryWindow);
63 
64  point->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
65 
66  return point;
67 }
68 
69 QString GraphicsScene::dumpCursors () const
70 {
71  QString cursorOverride = (QApplication::overrideCursor () != 0) ?
72  QtCursorToString (QApplication::overrideCursor ()->shape ()) :
73  "<null>";
74  QString cursorImage = QtCursorToString (image()->cursor().shape ());
75 
76  QString dump = QString ("overrideCursor=%1 imageCursor=%2")
77  .arg (cursorOverride)
78  .arg (cursorImage);
79 
80  return dump;
81 }
82 
84 {
85  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::hideAllItemsExceptImage";
86 
87  for (int index = 0; index < QGraphicsScene::items().count(); index++) {
88  QGraphicsItem *item = QGraphicsScene::items().at(index);
89 
90  if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt() == GRAPHICS_ITEM_TYPE_IMAGE) {
91 
92  item->show();
93 
94  } else {
95 
96  item->hide();
97 
98  }
99  }
100 }
101 
102 const QGraphicsPixmapItem *GraphicsScene::image () const
103 {
104  // Loop through items in scene to find the image
105  QList<QGraphicsItem*> items = QGraphicsScene::items();
106  QList<QGraphicsItem*>::iterator itr;
107  for (itr = items.begin(); itr != items.end(); itr++) {
108 
109  QGraphicsItem* item = *itr;
110  if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_IMAGE) {
111 
112  return (QGraphicsPixmapItem *) item;
113  }
114  }
115 
116  return 0;
117 }
118 
120 {
121  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::positionHasChangedPointIdentifiers";
122 
123  QStringList movedIds;
124 
125  const QList<QGraphicsItem*> &items = QGraphicsScene::items();
126  QList<QGraphicsItem*>::const_iterator itr;
127  for (itr = items.begin(); itr != items.end(); itr++) {
128 
129  const QGraphicsItem *item = *itr;
130 
131  // Skip the image and only keep the Points
132  bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
133  if (isPoint) {
134 
135  QString identifier = item->data (DATA_KEY_IDENTIFIER).toString ();
136  bool positionHasChanged = item->data (DATA_KEY_POSITION_HAS_CHANGED).toBool ();
137 
138  LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsScene::positionHasChangedPointIdentifiers"
139  << " identifier=" << identifier.toLatin1().data()
140  << " positionHasChanged=" << (positionHasChanged ? "yes" : "no");
141 
142  if (isPoint && positionHasChanged) {
143 
144  // Add Point to the list
145  movedIds << item->data(DATA_KEY_IDENTIFIER).toString ();
146 
147  }
148  }
149  }
150 
151  return movedIds;
152 }
153 
154 void GraphicsScene::printStream (QString indentation,
155  QTextStream &str)
156 {
157  m_graphicsLinesForCurves.printStream (indentation,
158  str);
159 }
160 
161 void GraphicsScene::removePoint (const QString &identifier)
162 {
163  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removePoint identifier=" << identifier.toLatin1().data();
164 
165  m_graphicsLinesForCurves.removePoint (identifier);
166 }
167 
169 {
170  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removeTemporaryPointIfExists";
171 
172  m_graphicsLinesForCurves.removeTemporaryPointIfExists ();
173 }
174 
176 {
177  // LOG4CPP_INFO_S is below
178 
179  int itemsBefore = items().count();
180 
181  m_graphicsLinesForCurves.resetOnLoad();
182 
183  int itemsAfter = items().count();
184 
185  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::resetOnLoad"
186  << " itemsBefore=" << itemsBefore
187  << " itemsAfter=" << itemsAfter;
188 }
189 
191 {
192  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::resetPositionHasChangedFlags";
193 
194  QList<QGraphicsItem*> itms = items ();
195  QList<QGraphicsItem*>::const_iterator itr;
196  for (itr = itms.begin (); itr != itms.end (); itr++) {
197 
198  QGraphicsItem *item = *itr;
199  item->setData (DATA_KEY_POSITION_HAS_CHANGED, false);
200  }
201 }
202 
204  bool showAll,
205  const QString &curveNameWanted)
206 {
207  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::showCurves"
208  << " show=" << (show ? "true" : "false")
209  << " showAll=" << (showAll ? "true" : "false")
210  << " curve=" << curveNameWanted.toLatin1().data();
211 
212  const QList<QGraphicsItem*> &items = QGraphicsScene::items();
213  QList<QGraphicsItem*>::const_iterator itr;
214  for (itr = items.begin(); itr != items.end(); itr++) {
215 
216  QGraphicsItem* item = *itr;
217 
218  // Skip the image and only process the Points
219  bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
220  bool isCurve = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_LINE);
221 
222  if (isPoint || isCurve) {
223 
224  bool showThis = show;
225  if (show && !showAll) {
226  QString identifier = item->data (DATA_KEY_IDENTIFIER).toString ();
227 
228  if (isPoint) {
229 
230  QString curveNameGot = Point::curveNameFromPointIdentifier (identifier);
231  showThis = (curveNameWanted == curveNameGot);
232 
233  } else {
234 
235  showThis = (curveNameWanted == identifier);
236 
237  }
238  }
239 
240  item->setVisible (showThis);
241 
242  }
243  }
244 }
245 
247  double highlightOpacity,
248  GeometryWindow *geometryWindow)
249 {
250  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateAfterCommand";
251 
252  m_graphicsLinesForCurves.updateHighlightOpacity (highlightOpacity);
253 
254  updateCurves (cmdMediator);
255 
256  // Update the points
257  updatePointMembership (cmdMediator,
258  geometryWindow);
259 }
260 
261 void GraphicsScene::updateCurves (CmdMediator &cmdMediator)
262 {
263  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateCurves";
264 
265  // Desired curve names include both axes and graph curve names
266  QStringList curveNames;
267  curveNames << AXIS_CURVE_NAME;
268  curveNames << cmdMediator.document().curvesGraphsNames();
269 
270  m_graphicsLinesForCurves.addRemoveCurves (*this,
271  curveNames);
272 }
273 
274 void GraphicsScene::updateCurveStyles (const CurveStyles &modelCurveStyles)
275 {
276  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateCurveStyles";
277 
278  m_graphicsLinesForCurves.updateCurveStyles (modelCurveStyles);
279 }
280 
282  const Transformation &transformation)
283 {
284  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateGraphicsLinesToMatchGraphicsPoints";
285 
286  if (transformation.transformIsDefined()) {
287 
288  // Ordinals must be updated to reflect reordering that may have resulted from dragging points
289  m_graphicsLinesForCurves.updatePointOrdinalsAfterDrag (curveStyles,
290  transformation);
291 
292  // Recompute the lines one time for efficiency
293  m_graphicsLinesForCurves.updateGraphicsLinesToMatchGraphicsPoints (curveStyles);
294  }
295 }
296 
297 void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator,
298  GeometryWindow *geometryWindow)
299 {
300  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updatePointMembership";
301 
302  CallbackSceneUpdateAfterCommand ftor (m_graphicsLinesForCurves,
303  *this,
304  cmdMediator.document (),
305  geometryWindow);
306  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
308 
309  // First pass:
310  // 1) Mark all points as Not Wanted (this is done while creating the map)
311  m_graphicsLinesForCurves.lineMembershipReset ();
312 
313  // Next pass:
314  // 1) Existing points that are found in the map are marked as Wanted
315  // 2) Add new points that were just created in the Document. The new points are marked as Wanted
316  cmdMediator.iterateThroughCurvePointsAxes (ftorWithCallback);
317  cmdMediator.iterateThroughCurvesPointsGraphs (ftorWithCallback);
318 
319  // Next pass:
320  // 1) Remove points that were just removed from the Document
321  m_graphicsLinesForCurves.lineMembershipPurge (cmdMediator.document().modelCurveStyles());
322 }
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 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:42
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:672
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:319
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:83