Engauge Digitizer 2
Loading...
Searching...
No Matches
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
32void 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
44GraphicsPoint *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
67QString 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
100const 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
152void GraphicsScene::printStream (QString indentation,
153 QTextStream &str)
154{
155 m_graphicsLinesForCurves.printStream (indentation,
156 str);
157}
158
159void 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
280void 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
293void 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
316void 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}
Callback for updating the QGraphicsItems in the scene after a command may have modified Points in Cur...
CallbackSearchReturn callback(const QString &, const Point &point)
Callback method.
Command queue stack.
Definition CmdMediator.h:24
void iterateThroughCurvesPointsGraphs(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for all the graphs curves.
void iterateThroughCurvePointsAxes(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for the single axes curve.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Model for DlgSettingsCurveProperties and CmdSettingsCurveProperties.
Definition CurveStyles.h:23
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition Document.cpp:312
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition Document.cpp:618
void updatePointOrdinalsAfterDrag(const CurveStyles &curveStyles, const Transformation &transformation)
See GraphicsScene::updateOrdinalsAfterDrag.
void removePoint(const QString &identifier)
Remove the specified point. The act of deleting it will automatically remove it from the GraphicsScen...
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update the curve style for every curve.
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded.
void removeTemporaryPointIfExists()
Remove temporary point if it exists.
void updateGraphicsLinesToMatchGraphicsPoints(const CurveStyles &curveStyles)
Calls to moveLinesWithDraggedPoint have finished so update the lines correspondingly.
void addRemoveCurves(GraphicsScene &scene, const QStringList &curveNames)
Add new curves and remove expired curves to match the specified list.
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.
void lineMembershipPurge(const CurveStyles &curveStyles)
Mark the end of addPoint calls. Remove stale lines, insert missing lines, and draw the graphics lines...
Factor for generating GraphicsPointAbstractBase class objects.
GraphicsPoint * createPoint(QGraphicsScene &scene, const QString &identifier, const QPointF &posScreen, const PointStyle &pointStyle)
Create circle or polygon point according to the PointStyle.
Graphics item for drawing a circular or polygonal Point.
void setData(int key, const QVariant &data)
Proxy method for QGraphicsItem::setData.
void setToolTip(const QString &toolTip)
Proxy method for QGraphicsItem::setToolTip.
QVariant data(int key) const
Proxy method for QGraphicsItem::data.
void updateGraphicsLinesToMatchGraphicsPoints(const CurveStyles &modelCurveStyles, const Transformation &transformation)
A mouse move has just occurred so move the selected points, since they were dragged.
void resetOnLoad()
Reset, when loading a document after the first, to same state that first document was at when loaded.
void updateAfterCommand(CmdMediator &cmdMediator)
Update the Points and their Curves after executing a command.
QStringList selectedPointIdentifiers() const
Return a list of identifiers for the currently selected points.
GraphicsScene(MainWindow *mainWindow)
Single constructor.
void hideAllItemsExceptImage()
Hide all graphics items, except background image, in preparation for preview during IMPORT_TYPE_ADVAN...
void addTemporaryPoint(const QString &identifier, GraphicsPoint *point)
Add one temporary point to m_graphicsLinesForCurves. Non-temporary points are handled by the updateLi...
QStringList positionHasChangedPointIdentifiers() const
Return a list of identifiers for the points that have moved since the last call to resetPositionHasCh...
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 resetPositionHasChangedFlags()
Reset positionHasChanged flag for all items. Typically this is done as part of mousePressEvent.
void printStream(QString indentation, QTextStream &str)
Debugging method that supports print method of this class and printStream method of some other class(...
void removeTemporaryPointIfExists()
Remove temporary point if it exists.
void removePoint(const QString &identifier)
Remove specified point. This aborts if the point does not exist.
void updateCurveStyles(const CurveStyles &modelCurveStyles)
Update curve styles after settings changed.
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...
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition MainWindow.h:78
Details for a specific Point.
Definition PointStyle.h:21
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
static double UNDEFINED_ORDINAL()
Get method for undefined ordinal constant.
Definition Point.h:132
Affine transformation between screen and graph coordinates, based on digitized axis points.
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.