Engauge Digitizer  2
 All Classes Files Functions Variables Enumerations Enumerator Friends Pages
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 "GraphicsItemType.h"
15 #include "GraphicsPoint.h"
16 #include "GraphicsPointFactory.h"
17 #include "GraphicsScene.h"
18 #include "Logger.h"
19 #include "MainWindow.h"
20 #include "Point.h"
21 #include "PointStyle.h"
22 #include <QApplication>
23 #include <QGraphicsItem>
24 #include "QtToString.h"
25 #include "Transformation.h"
26 
28  QGraphicsScene(mainWindow)
29 {
30 }
31 
32 void GraphicsScene::addTemporaryPoint (const QString &identifier,
33  GraphicsPoint *point)
34 {
35  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::addTemporaryPoint"
36  << " identifer=" << identifier.toLatin1().data();
37 
38  m_graphicsLinesForCurves.addPoint (AXIS_CURVE_NAME,
39  identifier,
41  *point);
42 }
43 
44 GraphicsPoint *GraphicsScene::createPoint (const QString &identifier,
45  const PointStyle &pointStyle,
46  const QPointF &posScreen)
47 {
48  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::createPoint"
49  << " identifier=" << identifier.toLatin1().data();
50 
51  // Ordinal value is initially computed as one plus the max ordinal seen so far. This initial ordinal value will be overridden if the
52  // cordinates determine the ordinal values.
53  //
54  // This is an N-squared algorithm and may be worth replacing later
55  GraphicsPointFactory pointFactory;
56  GraphicsPoint *point = pointFactory.createPoint (*this,
57  identifier,
58  posScreen,
59  pointStyle);
60 
61  point->setToolTip (identifier);
62  point->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
63 
64  return point;
65 }
66 
67 QString GraphicsScene::dumpCursors () const
68 {
69  QString cursorOverride = (QApplication::overrideCursor () != 0) ?
70  QtCursorToString (QApplication::overrideCursor ()->shape ()) :
71  "<null>";
72  QString cursorImage = QtCursorToString (image()->cursor().shape ());
73 
74  QString dump = QString ("overrideCursor=%1 imageCursor=%2")
75  .arg (cursorOverride)
76  .arg (cursorImage);
77 
78  return dump;
79 }
80 
82 {
83  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::hideAllItemsExceptImage";
84 
85  for (int index = 0; index < QGraphicsScene::items().count(); index++) {
86  QGraphicsItem *item = QGraphicsScene::items().at(index);
87 
88  if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt() == GRAPHICS_ITEM_TYPE_IMAGE) {
89 
90  item->show();
91 
92  } else {
93 
94  item->hide();
95 
96  }
97  }
98 }
99 
100 const QGraphicsPixmapItem *GraphicsScene::image () const
101 {
102  // Loop through items in scene to find the image
103  QList<QGraphicsItem*> items = QGraphicsScene::items();
104  QList<QGraphicsItem*>::iterator itr;
105  for (itr = items.begin(); itr != items.end(); itr++) {
106 
107  QGraphicsItem* item = *itr;
108  if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_IMAGE) {
109 
110  return (QGraphicsPixmapItem *) item;
111  }
112  }
113 
114  return 0;
115 }
116 
118 {
119  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::positionHasChangedPointIdentifiers";
120 
121  QStringList movedIds;
122 
123  const QList<QGraphicsItem*> &items = QGraphicsScene::items();
124  QList<QGraphicsItem*>::const_iterator itr;
125  for (itr = items.begin(); itr != items.end(); itr++) {
126 
127  const QGraphicsItem *item = *itr;
128 
129  // Skip the image and only keep the Points
130  bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
131  if (isPoint) {
132 
133  QString identifier = item->data (DATA_KEY_IDENTIFIER).toString ();
134  bool positionHasChanged = item->data (DATA_KEY_POSITION_HAS_CHANGED).toBool ();
135 
136  LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsScene::positionHasChangedPointIdentifiers"
137  << " identifier=" << identifier.toLatin1().data()
138  << " positionHasChanged=" << (positionHasChanged ? "yes" : "no");
139 
140  if (isPoint && positionHasChanged) {
141 
142  // Add Point to the list
143  movedIds << item->data(DATA_KEY_IDENTIFIER).toString ();
144 
145  }
146  }
147  }
148 
149  return movedIds;
150 }
151 
152 void GraphicsScene::printStream (QString indentation,
153  QTextStream &str)
154 {
155  m_graphicsLinesForCurves.printStream (indentation,
156  str);
157 }
158 
159 void GraphicsScene::removePoint (const QString &identifier)
160 {
161  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removePoint identifier=" << identifier.toLatin1().data();
162 
163  m_graphicsLinesForCurves.removePoint (identifier);
164 }
165 
167 {
168  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::removeTemporaryPointIfExists";
169 
170  m_graphicsLinesForCurves.removeTemporaryPointIfExists ();
171 }
172 
174 {
175  // LOG4CPP_INFO_S is below
176 
177  int itemsBefore = items().count();
178 
179  m_graphicsLinesForCurves.resetOnLoad();
180 
181  int itemsAfter = items().count();
182 
183  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::resetOnLoad"
184  << " itemsBefore=" << itemsBefore
185  << " itemsAfter=" << itemsAfter;
186 }
187 
189 {
190  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::resetPositionHasChangedFlags";
191 
192  QList<QGraphicsItem*> itms = items ();
193  QList<QGraphicsItem*>::const_iterator itr;
194  for (itr = itms.begin (); itr != itms.end (); itr++) {
195 
196  QGraphicsItem *item = *itr;
197  item->setData (DATA_KEY_POSITION_HAS_CHANGED, false);
198  }
199 }
200 
202 {
203  const QList<QGraphicsItem*> &items = QGraphicsScene::selectedItems();
204 
205  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::selectedPointIdentifiers"
206  << " selectedItems=" << items.count();
207 
208  QStringList selectedIds;
209  QList<QGraphicsItem*>::const_iterator itr;
210  for (itr = items.begin(); itr != items.end(); itr++) {
211 
212  const QGraphicsItem* item = *itr;
213 
214  // Skip the image and only keep the Points
215  bool isPoint = (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_POINT);
216  if (isPoint) {
217 
218  // Add Point to the list
219  selectedIds << item->data(DATA_KEY_IDENTIFIER).toString ();
220 
221  }
222  }
223 
224  return selectedIds;
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 {
272  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateAfterCommand";
273 
274  updateCurves (cmdMediator);
275 
276  // Update the points
277  updatePointMembership (cmdMediator);
278 }
279 
280 void GraphicsScene::updateCurves (CmdMediator &cmdMediator)
281 {
282  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateCurves";
283 
284  // Desired curve names include both axes and graph curve names
285  QStringList curveNames;
286  curveNames << AXIS_CURVE_NAME;
287  curveNames << cmdMediator.document().curvesGraphsNames();
288 
289  m_graphicsLinesForCurves.addRemoveCurves (*this,
290  curveNames);
291 }
292 
293 void GraphicsScene::updateCurveStyles (const CurveStyles &modelCurveStyles)
294 {
295  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateCurveStyles";
296 
297  m_graphicsLinesForCurves.updateCurveStyles (modelCurveStyles);
298 }
299 
301  const Transformation &transformation)
302 {
303  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateGraphicsLinesToMatchGraphicsPoints";
304 
305  if (transformation.transformIsDefined()) {
306 
307  // Ordinals must be updated to reflect reordering that may have resulted from dragging points
308  m_graphicsLinesForCurves.updatePointOrdinalsAfterDrag (curveStyles,
309  transformation);
310 
311  // Recompute the lines one time for efficiency
312  m_graphicsLinesForCurves.updateGraphicsLinesToMatchGraphicsPoints (curveStyles);
313  }
314 }
315 
316 void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator)
317 {
318  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updatePointMembership";
319 
320  CallbackSceneUpdateAfterCommand ftor (m_graphicsLinesForCurves,
321  *this,
322  cmdMediator.document ());
323  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
325 
326  // First pass:
327  // 1) Mark all points as Not Wanted (this is done while creating the map)
328  m_graphicsLinesForCurves.lineMembershipReset ();
329 
330  // Next pass:
331  // 1) Existing points that are found in the map are marked as Wanted
332  // 2) Add new points that were just created in the Document. The new points are marked as Wanted
333  cmdMediator.iterateThroughCurvePointsAxes (ftorWithCallback);
334  cmdMediator.iterateThroughCurvesPointsGraphs (ftorWithCallback);
335 
336  // Next pass:
337  // 1) Remove points that were just removed from the Document
338  m_graphicsLinesForCurves.lineMembershipPurge (cmdMediator.document().modelCurveStyles());
339 }
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 updateAfterCommand(CmdMediator &cmdMediator)
Update the Points and their Curves after executing a command.
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.
QStringList selectedPointIdentifiers() const
Return a list of identifiers for the currently selected points.
GraphicsPoint * createPoint(QGraphicsScene &scene, const QString &identifier, const QPointF &posScreen, const PointStyle &pointStyle)
Create circle or polygon point according to the PointStyle.
void removeTemporaryPointIfExists()
Remove temporary point if it exists.
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.
void updatePointOrdinalsAfterDrag(const CurveStyles &curveStyles, const Transformation &transformation)
See GraphicsScene::updateOrdinalsAfterDrag.
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
QStringList positionHasChangedPointIdentifiers() const
Return a list of identifiers for the points that have moved since the last call to resetPositionHasCh...
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:618
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.
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
Graphics item for drawing a circular or polygonal Point.
Definition: GraphicsPoint.h:39
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update curve styles after settings changed.
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: Document.cpp:312
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.
GraphicsPoint * createPoint(const QString &identifier, const PointStyle &pointStyle, const QPointF &posScreen)
Create one QGraphicsItem-based object that represents one Point. It is NOT added to m_graphicsLinesFo...
QVariant data(int key) const
Proxy method for QGraphicsItem::data.
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
void setToolTip(const QString &toolTip)
Proxy method for QGraphicsItem::setToolTip.
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);...
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:77