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