Engauge Digitizer  2
GeometryWindow.cpp
1 /******************************************************************************************************
2  * (C) 2016 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 "CallbackGatherXThetaValuesFunctions.h"
8 #include "CmdMediator.h"
9 #include "Curve.h"
10 #include "CurveConnectAs.h"
11 #include "CurveStyle.h"
12 #include "EngaugeAssert.h"
13 #include "GeometryModel.h"
14 #include "GeometryWindow.h"
15 #include "Logger.h"
16 #include "MainWindow.h"
17 #include <QApplication>
18 #include <QClipboard>
19 #include <QItemSelectionModel>
20 #include <QTextStream>
21 #include "WindowTable.h"
22 
24  WindowAbstractBase (mainWindow)
25 {
26  setVisible (false);
27  setAllowedAreas (Qt::AllDockWidgetAreas);
28  setWindowTitle (tr ("Geometry Window")); // Appears in title bar when undocked
29  setStatusTip (tr ("Geometry Window"));
30  setWhatsThis (tr ("Geometry Window\n\n"
31  "This table displays the following geometry data for the currently selected curve:\n\n"
32  "Function area = Area under the curve if it is a function\n\n"
33  "Polygon area = Area inside the curve if it is a relation. This value is only correct "
34  "if none of the curve lines intersect each other\n\n"
35  "X = X coordinate of each point\n\n"
36  "Y = Y coordinate of each point\n\n"
37  "Index = Point number\n\n"
38  "Distance = Distance along the curve in forward or backward direction, in either graph units "
39  "or as a percentage\n\n"
40  "If drag-and-drop is disabled, a rectangular set of cells may be selected by clicking and dragging. Otherwise, if "
41  "drag-and-drop is enabled, a rectangular set of cells may be selected using Click then Shift+Click, since click and drag "
42  "starts the dragging operation. Drag-and-drop mode is set in the Main Window settings"));
43 
44  createWidgets (mainWindow);
45  loadStrategies();
46  initializeHeader ();
47 }
48 
49 GeometryWindow::~GeometryWindow()
50 {
51 }
52 
54 {
55  // Resize table to remove stale body data
56  resizeTable (NUM_HEADER_ROWS);
57 
58  // Clear stale header data values
59  for (int row = 0; row < NUM_HEADER_ROWS - 1; row++) {
60  m_model->setItem (row, COLUMN_HEADER_VALUE, new QStandardItem (""));
61  }
62 }
63 
64 void GeometryWindow::closeEvent(QCloseEvent * /* event */)
65 {
66  LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::closeEvent";
67 
69 }
70 
72 {
73  return COLUMN_BODY_POINT_IDENTIFIERS;
74 }
75 
76 void GeometryWindow::createWidgets (MainWindow *mainWindow)
77 {
78  m_model = new GeometryModel;
79 
80  m_view = new WindowTable (*m_model);
81  connect (m_view, SIGNAL (signalTableStatusChange ()),
82  mainWindow, SLOT (slotTableStatusChange ()));
83 
84  setWidget (m_view);
85 }
86 
88 {
89  LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::doCopy";
90 
91  QString text = m_model->selectionAsText (m_modelExport.delimiter());
92 
93  if (!text.isEmpty ()) {
94 
95  // Save to clipboard
96  QApplication::clipboard ()->setText (text);
97 
98  }
99 }
100 
101 void GeometryWindow::initializeHeader ()
102 {
103  LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::initializeHeader";
104 
105  resizeTable (NUM_HEADER_ROWS);
106 
107  m_model->setItem (HEADER_ROW_NAME, COLUMN_HEADER_LABEL, new QStandardItem (tokenCurveName ()));
108  m_model->setItem (HEADER_ROW_FUNC_AREA, COLUMN_HEADER_LABEL, new QStandardItem (tokenFunctionArea ()));
109  m_model->setItem (HEADER_ROW_POLY_AREA, COLUMN_HEADER_LABEL, new QStandardItem (tokenPolygonArea ()));
110  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_X, new QStandardItem (tokenX ()));
111  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_Y, new QStandardItem (tokenY ()));
112  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_INDEX, new QStandardItem (tokenIndex ()));
113  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_GRAPH_FORWARD, new QStandardItem (tokenDistanceGraph ()));
114  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_PERCENT_FORWARD, new QStandardItem (tokenDistancePercent ()));
115  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_GRAPH_BACKWARD, new QStandardItem (tokenDistanceGraph ()));
116  m_model->setItem (HEADER_ROW_COLUMN_NAMES, COLUMN_BODY_DISTANCE_PERCENT_BACKWARD, new QStandardItem (tokenDistancePercent ()));
117 }
118 
119 void GeometryWindow::loadStrategies ()
120 {
121  LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::loadStrategies";
122 }
123 
124 void GeometryWindow::resizeTable (int rowCount)
125 {
126  LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::resizeTable";
127 
128  unselectAll();
129 
130  m_model->setRowCount (rowCount);
131  m_model->setColumnCount (NUM_BODY_COLUMNS);
132 
133 }
134 
135 void GeometryWindow::slotPointHoverEnter (QString pointIdentifier)
136 {
137  m_model->setCurrentPointIdentifier (pointIdentifier);
138 }
139 
140 void GeometryWindow::slotPointHoverLeave (QString /* pointIdentifier */)
141 {
142  m_model->setCurrentPointIdentifier ("");
143 }
144 
145 QString GeometryWindow::tokenCurveName () const
146 {
147  return QString ("%1:").arg (QObject::tr ("CurveName"));
148 }
149 
150 QString GeometryWindow::tokenDistanceGraph () const
151 {
152  return QObject::tr ("Distance");
153 }
154 
155 QString GeometryWindow::tokenDistancePercent () const
156 {
157  return QObject::tr ("Percent");
158 }
159 
160 QString GeometryWindow::tokenFunctionArea () const
161 {
162  return QString ("%1:").arg (QObject::tr ("FunctionArea"));
163 }
164 
165 QString GeometryWindow::tokenIndex () const
166 {
167  return QObject::tr ("Index");
168 }
169 
170 QString GeometryWindow::tokenPolygonArea () const
171 {
172  return QString ("%1:").arg (QObject::tr ("PolygonArea"));
173 }
174 
175 QString GeometryWindow::tokenX () const
176 {
177  return QObject::tr ("X");
178 }
179 
180 QString GeometryWindow::tokenY () const
181 {
182  return QObject::tr ("Y");
183 }
184 
185 void GeometryWindow::unselectAll ()
186 {
187  QItemSelectionModel *selectionModel = m_view->selectionModel ();
188 
189  selectionModel->clearSelection ();
190 }
191 
192 void GeometryWindow::update (const CmdMediator &cmdMediator,
193  const MainWindowModel &modelMainWindow,
194  const QString &curveSelected,
195  const Transformation &transformation)
196 {
197  LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::update";
198 
199  const int NUM_LEGEND_ROWS_UNSPANNED = 2; // Match with GeometryModel::NUM_LEGEND_ROWS_UNSPANNED
200 
201  // Save inputs
202  m_modelExport = cmdMediator.document().modelExport();
203  m_model->setDelimiter (m_modelExport.delimiter());
204  m_view->setDragEnabled (modelMainWindow.dragDropExport());
205 
206  // Gather and calculate geometry data
207  const Curve *curve = cmdMediator.document().curveForCurveName (curveSelected);
208 
209  ENGAUGE_CHECK_PTR (curve);
210 
211  const Points points = curve->points();
212 
213  QString funcArea, polyArea;
214  QVector<QString> x, y, distanceGraphForward, distancePercentForward, distanceGraphBackward, distancePercentBackward;
215  QVector<bool> isPotentialExportAmbiguity;
216 
217  CurveStyle curveStyle = cmdMediator.document().modelCurveStyles().curveStyle (curveSelected);
218  m_geometryStrategyContext.calculateGeometry (points,
219  cmdMediator.document().modelCoords(),
220  cmdMediator.document().modelGeneral(),
221  modelMainWindow,
222  transformation,
223  curveStyle.lineStyle().curveConnectAs(),
224  funcArea,
225  polyArea,
226  x,
227  y,
228  isPotentialExportAmbiguity,
229  distanceGraphForward,
230  distancePercentForward,
231  distanceGraphBackward,
232  distancePercentBackward);
233 
234  // Was there a potential export ambiguity
235  bool wasAmbiguity = isPotentialExportAmbiguity.contains (true);
236 
237  // Output to table
238  resizeTable (NUM_HEADER_ROWS + points.count() + (wasAmbiguity ? NUM_LEGEND_ROWS_UNSPANNED : 0));
239 
240  m_model->setItem (HEADER_ROW_NAME, COLUMN_HEADER_VALUE, new QStandardItem (curveSelected));
241  m_model->setItem (HEADER_ROW_FUNC_AREA, COLUMN_HEADER_VALUE, new QStandardItem (funcArea));
242  m_model->setItem (HEADER_ROW_POLY_AREA, COLUMN_HEADER_VALUE, new QStandardItem (polyArea));
243 
244  if (transformation.transformIsDefined()) {
245 
246  m_model->setPotentialExportAmbiguity (isPotentialExportAmbiguity);
247 
248  int row = NUM_HEADER_ROWS;
249  int index = 0;
250  for (; index < points.count(); row++, index++) {
251 
252  const Point &point = points.at (index);
253 
254  QPointF posGraph;
255  transformation.transformScreenToRawGraph (point.posScreen (),
256  posGraph);
257 
258  m_model->setItem (row, COLUMN_BODY_X, new QStandardItem (x [index]));
259  m_model->setItem (row, COLUMN_BODY_Y, new QStandardItem (y [index]));
260  m_model->setItem (row, COLUMN_BODY_INDEX, new QStandardItem (QString::number (index + 1)));
261  m_model->setItem (row, COLUMN_BODY_DISTANCE_GRAPH_FORWARD, new QStandardItem (distanceGraphForward [index]));
262  m_model->setItem (row, COLUMN_BODY_DISTANCE_PERCENT_FORWARD, new QStandardItem (distancePercentForward [index]));
263  m_model->setItem (row, COLUMN_BODY_DISTANCE_GRAPH_BACKWARD, new QStandardItem (distanceGraphBackward [index]));
264  m_model->setItem (row, COLUMN_BODY_DISTANCE_PERCENT_BACKWARD, new QStandardItem (distancePercentBackward [index]));
265  m_model->setItem (row, COLUMN_BODY_POINT_IDENTIFIERS, new QStandardItem (point.identifier()));
266  }
267 
268  if (wasAmbiguity) {
269  m_view->setSpan (row, 0, NUM_LEGEND_ROWS_UNSPANNED, NUM_BODY_COLUMNS);
270  m_model->setItem (row, COLUMN_BODY_X,
271  new QStandardItem (tr ("Highlighted segments may have unexpected values when exported due to overlaps. "
272  "Adjust points or change Settings / Curve Properties / Connect As.")));
273  row++;
274  }
275  }
276 
277  // Unselect everything
278  unselectAll ();
279 
280  // Make sure the hidden column stays hidden
281  m_view->setColumnHidden (COLUMN_BODY_POINT_IDENTIFIERS, true);
282 }
283 
284 QTableView *GeometryWindow::view () const
285 {
286  return dynamic_cast<QTableView*> (m_view);
287 }
CurveStyle curveStyle(const QString &curveName) const
CurveStyle in specified curve.
Definition: CurveStyles.cpp:79
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition: LineStyle.cpp:63
void setCurrentPointIdentifier(const QString &pointIdentifier)
Set the point identifier to be highlighted. Value is empty for no highlighting.
virtual void closeEvent(QCloseEvent *event)
Catch close event so corresponding menu item in MainWindow can be updated accordingly.
virtual QTableView * view() const
QTableView-based class used by child class.
Dockable widget abstract base class.
const Curve * curveForCurveName(const QString &curveName) const
See CurvesGraphs::curveForCurveNames, although this also works for AXIS_CURVE_NAME.
Definition: Document.cpp:331
DocumentModelGeneral modelGeneral() const
Get method for DocumentModelGeneral.
Definition: Document.cpp:719
void slotPointHoverEnter(QString)
Highlight the row for the specified point.
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition: Point.h:25
QPointF posScreen() const
Accessor for screen position.
Definition: Point.cpp:404
virtual void update(const CmdMediator &cmdMediator, const MainWindowModel &modelMainWindow, const QString &curveSelected, const Transformation &transformation)
Populate the table with the specified Curve.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
const Points points() const
Return a shallow copy of the Points.
Definition: Curve.cpp:451
void calculateGeometry(const Points &points, const DocumentModelCoords &modelCoords, const DocumentModelGeneral &modelGeneral, const MainWindowModel &modelMainWindow, const Transformation &transformation, CurveConnectAs connectAs, QString &funcArea, QString &polyArea, QVector< QString > &x, QVector< QString > &y, QVector< bool > &isPotentialExportAmbiguity, QVector< QString > &distanceGraphForward, QVector< QString > &distancePercentForward, QVector< QString > &distanceGraphBackward, QVector< QString > &distancePercentBackward) const
Calculate geometry parameters.
QString selectionAsText(ExportDelimiter delimiter) const
Convert the selection into exportable text which is good for text editors.
QString identifier() const
Unique identifier for a specific Point.
Definition: Point.cpp:268
void slotPointHoverLeave(QString)
Unhighlight the row for the specified point.
Affine transformation between screen and graph coordinates, based on digitized axis points.
virtual void doCopy()
Copy the current selection to the clipboard.
void setDelimiter(ExportDelimiter delimiter)
Save output delimiter.
Model for DlgSettingsMainWindow.
LineStyle lineStyle() const
Get method for LineStyle.
Definition: CurveStyle.cpp:26
GeometryWindow(MainWindow *mainWindow)
Single constructor. Parent is needed or else this widget cannot be redocked after being undocked.
ExportDelimiter delimiter() const
Get method for delimiter.
void signalGeometryWindowClosed()
Signal that this QDockWidget was just closed.
static int columnBodyPointIdentifiers()
Hidden column that has the point identifiers.
Container for LineStyle and PointStyle for one Curve.
Definition: CurveStyle.h:18
Table view class with support for both drag-and-drop and copy-and-paste.
Definition: WindowTable.h:17
Container for one set of digitized Points.
Definition: Curve.h:33
void setPotentialExportAmbiguity(const QVector< bool > &isPotentialExportAmbiguity)
Remember which rows could have ambiguities during export - these will be highlighted.
Command queue stack.
Definition: CmdMediator.h:23
bool dragDropExport() const
Get method for drag and drop export.
DocumentModelExportFormat modelExport() const
Get method for DocumentModelExportFormat.
Definition: Document.cpp:712
Model that adds row highlighting according to the currently select point identifier.
Definition: GeometryModel.h:16
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:698
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition: Document.cpp:691
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:91
virtual void clear()
Clear stale information.