Engauge Digitizer  2
DigitizeStateScale.cpp
Go to the documentation of this file.
1 /******************************************************************************************************
2  * (C) 2017 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 "CmdAddScale.h"
8 #include "CmdMediator.h"
9 #include "CursorFactory.h"
10 #include "DigitizeStateScale.h"
11 #include "DigitizeStateContext.h"
12 #include "DlgEditScale.h"
13 #include "Document.h"
14 #include "EngaugeAssert.h"
15 #include "GraphicsPoint.h"
16 #include "GraphicsScene.h"
17 #include "GraphicsView.h"
18 #include "Logger.h"
19 #include "MainWindow.h"
20 #include "PointStyle.h"
21 #include <QCursor>
22 #include <QGraphicsLineItem>
23 #include <QMessageBox>
24 #include "QtToString.h"
25 #include "ZValues.h"
26 
28  DigitizeStateAbstractBase (context),
29  m_temporaryPoint0 (nullptr),
30  m_temporaryPoint1 (nullptr),
31  m_line (nullptr)
32 {
33 }
34 
36 {
37 }
38 
39 QString DigitizeStateScale::activeCurve () const
40 {
41  return AXIS_CURVE_NAME;
42 }
43 
44 void DigitizeStateScale::begin (CmdMediator *cmdMediator,
45  DigitizeState /* previousState */)
46 {
47  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::begin";
48 
49  setCursor(cmdMediator);
50  context().setDragMode(QGraphicsView::NoDrag);
52 }
53 
54 bool DigitizeStateScale::canPaste (const Transformation & /* transformation */,
55  const QSize & /* viewSize */) const
56 {
57  return false;
58 }
59 
60 QCursor DigitizeStateScale::cursor(CmdMediator *cmdMediator) const
61 {
62  LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateScale::cursor";
63 
64  CursorFactory cursorFactory;
65  QCursor cursor = cursorFactory.generate (cmdMediator->document().modelDigitizeCurve());
66 
67  return cursor;
68 }
69 
71 {
72  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::end";
73 }
74 
76  const QString &pointIdentifier)
77 {
78  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleContextMenuEventAxis "
79  << " point=" << pointIdentifier.toLatin1 ().data ();
80 }
81 
83  const QStringList &pointIdentifiers)
84 {
85  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleContextMenuEventGraph "
86  << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
87 }
88 
89 void DigitizeStateScale::handleCurveChange(CmdMediator * /* cmdMediator */)
90 {
91  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleCurveChange";
92 }
93 
94 void DigitizeStateScale::handleKeyPress (CmdMediator * /* cmdMediator */,
95  Qt::Key key,
96  bool /* atLeastOneSelectedItem */)
97 {
98  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleKeyPress"
99  << " key=" << QKeySequence (key).toString ().toLatin1 ().data ();
100 }
101 
102 void DigitizeStateScale::handleMouseMove (CmdMediator * /* cmdMediator */,
103  QPointF posScreen)
104 {
105  if (m_temporaryPoint1 != nullptr) {
106 
107  LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateScale::handleMouseMove"
108  << " oldPos=" << QPointFToString (m_temporaryPoint1->pos ()).toLatin1().data()
109  << " newPos=" << QPointFToString (posScreen).toLatin1().data();
110 
111  m_temporaryPoint1->setPos (posScreen);
112 
113  updateLineGeometry();
114  }
115 }
116 
118  QPointF posScreen)
119 {
120  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleMousePress";
121 
122  GeometryWindow *NULL_GEOMETRY_WINDOW = nullptr;
123 
124  // Create the scale bar to give the user immediate feedback that something was created
125  const Curve &curveAxes = cmdMediator->curveAxes();
126  PointStyle pointStyleAxes = curveAxes.curveStyle().pointStyle();
127  m_pointIdentifier0 = Point::temporaryPointIdentifier();
128  m_pointIdentifier1 = m_pointIdentifier0 + "b";
129  m_temporaryPoint0 = context().mainWindow().scene().createPoint(m_pointIdentifier0,
130  pointStyleAxes,
131  posScreen,
132  NULL_GEOMETRY_WINDOW);
133  m_temporaryPoint1 = context().mainWindow().scene().createPoint(m_pointIdentifier1,
134  pointStyleAxes,
135  posScreen,
136  NULL_GEOMETRY_WINDOW);
137 
138  // Subtle stuff happening here. GraphicsPoints by default can receive focus for clicking/dragging,
139  // but for some reason that was causing the dragged second endpoint to jump to the origin the Nth
140  // time that a scale bar was created, for every N>1. So we make the endpoint passive and update
141  // its position manually in handleMouseMove
142  m_temporaryPoint0->setPassive ();
143  m_temporaryPoint1->setPassive ();
144 
145  context().mainWindow().scene().addTemporaryScaleBar (m_temporaryPoint0,
146  m_temporaryPoint1,
147  m_pointIdentifier0,
148  m_pointIdentifier1);
149 
150  m_line = new QGraphicsLineItem;
151  context().mainWindow().scene().addItem (m_line);
152  m_line->setPen (QColor (Qt::red));
153  m_line->setZValue (Z_VALUE_CURVE);
154  m_line->setVisible (true);
155 
156  updateLineGeometry ();
157 
158  // Attempts to select an endpoint right here, or after an super short timer interval
159  // failed. That would have been nice for having the click create the scale bar and, while
160  // the mouse was still pressed, selecting an endpoint thus allowing a single click-and-drag to
161  // create the scale bar. We fall back to the less elegant solution (which the user will never
162  // notice) of capturing mouse move events and using those to move an endpoint
163 }
164 
166  QPointF /* posScreen */)
167 {
168  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleMouseRelease";
169 
170  if (context().mainWindow().transformIsDefined()) {
171 
172  QMessageBox::warning (nullptr,
173  QObject::tr ("Engauge Digitizer"),
174  QObject::tr ("The scale bar has been defined, and another is not needed or allowed."));
175 
176  removeTemporaryPointsAndLine ();
177 
178  } else {
179 
180  // Ask user for coordinates
181  DlgEditScale *dlg = new DlgEditScale (context ().mainWindow (),
182  cmdMediator->document().modelCoords(),
183  cmdMediator->document().modelGeneral(),
185  int rtn = dlg->exec ();
186 
187  double scaleLength = dlg->scaleLength ();
188  QPointF posScreen0 = m_temporaryPoint0->pos ();
189  QPointF posScreen1 = m_temporaryPoint1->pos ();
190  delete dlg;
191 
192  removeTemporaryPointsAndLine ();
193 
194  if (rtn == QDialog::Accepted) {
195 
196  // User wants to add this scale point. There are no additional sanity checks to run
197 
198  int nextOrdinal0 = cmdMediator->document().nextOrdinalForCurve(AXIS_CURVE_NAME);
199  int nextOrdinal1 = nextOrdinal0 + 1;
200 
201  // Create command to add point
202  Document &document = cmdMediator->document ();
203  QUndoCommand *cmd = new CmdAddScale (context ().mainWindow(),
204  document,
205  posScreen0,
206  posScreen1,
207  scaleLength,
208  nextOrdinal0,
209  nextOrdinal1);
210  context().appendNewCmd(cmdMediator,
211  cmd);
212  }
213  }
214 }
215 
216 void DigitizeStateScale::removeTemporaryPointsAndLine ()
217 {
218  context().mainWindow().scene().removePoint (m_pointIdentifier0); // Deallocates GraphicsPoint automatically
219  context().mainWindow().scene().removePoint (m_pointIdentifier1); // Deallocates GraphicsPoint automaticall
220  context().mainWindow().scene().removeItem (m_line);
221  delete m_line;
222  m_temporaryPoint0 = nullptr;
223  m_temporaryPoint1 = nullptr;
224  m_line = nullptr;
225 }
226 
227 QString DigitizeStateScale::state() const
228 {
229  return "DigitizeStateScale";
230 }
231 
233 {
234  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::updateAfterPointAddition";
235 }
236 
237 void DigitizeStateScale::updateLineGeometry ()
238 {
239  m_line->setLine (m_temporaryPoint0->pos ().x (),
240  m_temporaryPoint0->pos ().y (),
241  m_temporaryPoint1->pos ().x (),
242  m_temporaryPoint1->pos ().y ());
243 }
244 
246  const DocumentModelDigitizeCurve & /*modelDigitizeCurve */)
247 {
248  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::updateModelDigitizeCurve";
249 
250  setCursor(cmdMediator);
251 }
252 
253 void DigitizeStateScale::updateModelSegments(const DocumentModelSegments & /* modelSegments */)
254 {
255  LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::updateModelSegments";
256 }
DigitizeStateScale::handleContextMenuEventAxis
virtual void handleContextMenuEventAxis(CmdMediator *cmdMediator, const QString &pointIdentifier)
Handle a right click, on an axis point, that was intercepted earlier.
Definition: DigitizeStateScale.cpp:74
DigitizeStateScale::handleKeyPress
virtual void handleKeyPress(CmdMediator *cmdMediator, Qt::Key key, bool atLeastOneSelectedItem)
Handle a key press that was intercepted earlier.
Definition: DigitizeStateScale.cpp:93
DigitizeStateContext::setDragMode
void setDragMode(QGraphicsView::DragMode dragMode)
Set QGraphicsView drag mode (in m_view). Called from DigitizeStateAbstractBase subclasses.
Definition: DigitizeStateContext.cpp:211
DigitizeStateContext
Container for all DigitizeStateAbstractBase subclasses. This functions as the context class in a stan...
Definition: DigitizeStateContext.h:26
AXIS_CURVE_NAME
const QString AXIS_CURVE_NAME
DigitizeStateAbstractBase::context
DigitizeStateContext & context()
Reference to the DigitizeStateContext that contains all the DigitizeStateAbstractBase subclasses,...
Definition: DigitizeStateAbstractBase.cpp:41
Document::modelGeneral
DocumentModelGeneral modelGeneral() const
Get method for DocumentModelGeneral.
Definition: Document.cpp:723
GraphicsScene::createPoint
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...
Definition: GraphicsScene.cpp:69
PointStyle.h
CursorFactory.h
DigitizeStateScale::updateAfterPointAddition
virtual void updateAfterPointAddition()
Update graphics attributes after possible new points. This is useful for highlight opacity.
Definition: DigitizeStateScale.cpp:231
DlgEditScale::scaleLength
double scaleLength() const
Return the scale bar length specified by the user. Only applies if dialog was accepted.
Definition: DlgEditScale.cpp:134
DlgEditScale
Dialog box for editing the information of the map scale.
Definition: DlgEditScale.h:21
GraphicsPoint::setPassive
void setPassive()
Prevent automatic focus on point (=make it passive) for scale bar so drags can be made to work proper...
Definition: GraphicsPoint.cpp:281
DigitizeStateContext::mainWindow
MainWindow & mainWindow()
Reference to the MainWindow, without const.
Definition: DigitizeStateContext.cpp:168
CmdMediator.h
CursorFactory
Create standard cross cursor, or custom cursor, according to settings.
Definition: CursorFactory.h:14
Document
Storage of one imported image and the data attached to that image.
Definition: Document.h:40
Transformation
Affine transformation between screen and graph coordinates, based on digitized axis points.
Definition: Transformation.h:30
Document.h
EngaugeAssert.h
DigitizeStateContext.h
DigitizeStateScale::DigitizeStateScale
DigitizeStateScale(DigitizeStateContext &context)
Single constructor.
Definition: DigitizeStateScale.cpp:26
DigitizeStateScale::handleMouseMove
virtual void handleMouseMove(CmdMediator *cmdMediator, QPointF posScreen)
Handle a mouse move. This is part of an experiment to see if augmenting the cursor in Point Match mod...
Definition: DigitizeStateScale.cpp:101
MainWindow::modelMainWindow
MainWindowModel modelMainWindow() const
Get method for main window model.
Definition: MainWindow.cpp:1231
Point::temporaryPointIdentifier
static QString temporaryPointIdentifier()
Point identifier for temporary point that is used by DigitzeStateAxis.
Definition: Point.cpp:519
DigitizeStateScale::end
virtual void end()
Method that is called at the exact moment a state is exited. Typically called just before begin for t...
Definition: DigitizeStateScale.cpp:69
Curve
Container for one set of digitized Points.
Definition: Curve.h:32
Document::modelDigitizeCurve
DocumentModelDigitizeCurve modelDigitizeCurve() const
Get method for DocumentModelDigitizeCurve.
Definition: Document.cpp:709
Document::nextOrdinalForCurve
int nextOrdinalForCurve(const QString &curveName) const
Default next ordinal value for specified curve.
Definition: Document.cpp:765
CursorFactory::generate
QCursor generate(const DocumentModelDigitizeCurve &modelDigitizeCurve) const
Factory method to generate standard or custom cursor.
Definition: CursorFactory.cpp:18
GraphicsScene::addTemporaryScaleBar
void addTemporaryScaleBar(GraphicsPoint *point0, GraphicsPoint *point1, const QString &pointIdentifier0, const QString &pointIdentifier1)
Add temporary scale bar to scene.
Definition: GraphicsScene.cpp:50
DigitizeStateScale::updateModelSegments
virtual void updateModelSegments(const DocumentModelSegments &modelSegments)
Update the segments given the new settings.
Definition: DigitizeStateScale.cpp:252
DigitizeStateContext::appendNewCmd
void appendNewCmd(CmdMediator *cmdMediator, QUndoCommand *cmd)
Append just-created QUndoCommand to command stack. This is called from DigitizeStateAbstractBase subc...
Definition: DigitizeStateContext.cpp:64
DigitizeStateScale::activeCurve
virtual QString activeCurve() const
Name of the active Curve. This can include AXIS_CURVE_NAME.
Definition: DigitizeStateScale.cpp:38
Logger.h
CmdMediator::document
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
DigitizeState
DigitizeState
Set of possible states of Digitize toolbar.
Definition: DigitizeStateAbstractBase.h:23
DigitizeStateScale::handleMousePress
virtual void handleMousePress(CmdMediator *cmdMediator, QPointF posScreen)
Handle a mouse press that was intercepted earlier.
Definition: DigitizeStateScale.cpp:116
GraphicsPoint::setPos
void setPos(const QPointF pos)
Update the position.
Definition: GraphicsPoint.cpp:342
LOG4CPP_INFO_S
#define LOG4CPP_INFO_S(logger)
Definition: convenience.h:18
DigitizeStateScale.h
DigitizeStateScale::~DigitizeStateScale
virtual ~DigitizeStateScale()
Definition: DigitizeStateScale.cpp:34
GraphicsPoint.h
ZValues.h
GraphicsScene::removePoint
void removePoint(const QString &identifier)
Remove specified point. This aborts if the point does not exist.
Definition: GraphicsScene.cpp:185
DocumentModelSegments
Model for DlgSettingsSegments and CmdSettingsSegments.
Definition: DocumentModelSegments.h:16
GraphicsPoint::pos
QPointF pos() const
Proxy method for QGraphicsItem::pos.
Definition: GraphicsPoint.cpp:215
DigitizeStateAbstractBase::setCursor
void setCursor(CmdMediator *cmdMediator)
Update the cursor according to the current state.
Definition: DigitizeStateAbstractBase.cpp:51
Z_VALUE_CURVE
const int Z_VALUE_CURVE
Definition: ZValues.cpp:10
CurveStyle::pointStyle
PointStyle pointStyle() const
Get method for PointStyle.
Definition: CurveStyle.cpp:74
mainCat
log4cpp::Category * mainCat
Definition: Logger.cpp:14
MainWindow.h
GraphicsScene.h
DigitizeStateScale::cursor
virtual QCursor cursor(CmdMediator *cmdMediator) const
Returns the state-specific cursor shape.
Definition: DigitizeStateScale.cpp:59
DocumentModelDigitizeCurve
Model for DlgSettingsDigitizeCurve and CmdSettingsDigitizeCurve.
Definition: DocumentModelDigitizeCurve.h:17
CmdMediator
Command queue stack.
Definition: CmdMediator.h:22
DigitizeStateScale::handleMouseRelease
virtual void handleMouseRelease(CmdMediator *cmdMediator, QPointF posScreen)
Handle a mouse release that was intercepted earlier.
Definition: DigitizeStateScale.cpp:164
PointStyle
Details for a specific Point.
Definition: PointStyle.h:19
DlgEditScale.h
MainWindow::scene
GraphicsScene & scene()
Scene container for the QImage and QGraphicsItems.
Definition: MainWindow.cpp:1458
Document::modelCoords
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition: Document.cpp:695
DigitizeStateScale::handleCurveChange
virtual void handleCurveChange(CmdMediator *cmdMediator)
Handle the selection of a new curve. At a minimum, DigitizeStateSegment will generate a new set of Se...
Definition: DigitizeStateScale.cpp:88
DigitizeStateScale::updateModelDigitizeCurve
virtual void updateModelDigitizeCurve(CmdMediator *cmdMediator, const DocumentModelDigitizeCurve &modelDigitizeCurve)
Update the digitize curve settings.
Definition: DigitizeStateScale.cpp:244
LOG4CPP_DEBUG_S
#define LOG4CPP_DEBUG_S(logger)
Definition: convenience.h:20
CmdAddScale.h
CmdMediator::curveAxes
const Curve & curveAxes() const
See Document::curveAxes.
Definition: CmdMediator.cpp:57
QtToString.h
GeometryWindow
Window that displays the geometry information, as a table, for the current curve.
Definition: GeometryWindow.h:27
DigitizeStateScale::begin
virtual void begin(CmdMediator *cmdMediator, DigitizeState previousState)
Method that is called at the exact moment a state is entered.
Definition: DigitizeStateScale.cpp:43
CmdAddScale
Command for adding one scale point.
Definition: CmdAddScale.h:15
DigitizeStateScale::handleContextMenuEventGraph
virtual void handleContextMenuEventGraph(CmdMediator *cmdMediator, const QStringList &pointIdentifiers)
Handle a right click, on a graph point, that was intercepted earlier.
Definition: DigitizeStateScale.cpp:81
Curve::curveStyle
CurveStyle curveStyle() const
Return the curve style.
Definition: Curve.cpp:149
QPointFToString
QString QPointFToString(const QPointF &pos)
Definition: QtToString.cpp:17
DigitizeStateAbstractBase
Base class for all digitizing states. This serves as an interface to DigitizeStateContext.
Definition: DigitizeStateAbstractBase.h:36
DigitizeStateScale::canPaste
virtual bool canPaste(const Transformation &transformation, const QSize &viewSize) const
Return true if there is good data in the clipboard for pasting, and that is compatible with the curre...
Definition: DigitizeStateScale.cpp:53
DigitizeStateScale::state
virtual QString state() const
State name for debugging.
Definition: DigitizeStateScale.cpp:226
GraphicsView.h
MainWindow::updateViewsOfSettings
void updateViewsOfSettings(const QString &activeCurve)
Update curve-specific view of settings. Private version gets active curve name from DigitizeStateCont...
Definition: MainWindow.cpp:3797