Engauge Digitizer  2
 All Classes Files Functions Variables Enumerations Enumerator Friends Pages
DlgSettingsCoords.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 "CallbackBoundingRects.h"
8 #include "CmdMediator.h"
9 #include "CmdSettingsCoords.h"
10 #include "CoordUnitsDate.h"
11 #include "CoordUnitsTime.h"
12 #include "DlgSettingsCoords.h"
13 #include "DlgValidatorAbstract.h"
14 #include "DlgValidatorFactory.h"
15 #include "DocumentModelCoords.h"
16 #include "EngaugeAssert.h"
17 #include "Logger.h"
18 #include "MainWindow.h"
19 #include <math.h>
20 #include <QComboBox>
21 #include <QDebug>
22 #include <QDoubleValidator>
23 #include <QGraphicsRectItem>
24 #include <QGridLayout>
25 #include <QGroupBox>
26 #include <QGraphicsScene>
27 #include <QLabel>
28 #include <QLineEdit>
29 #include <QPalette>
30 #include <QRadioButton>
31 #include <QStackedWidget>
32 #include <QVBoxLayout>
33 #include "Transformation.h"
34 #include "ViewPreview.h"
35 
36 const QString OVERRIDDEN_VALUE(""); // Values are overridden in updateControls
37 
38 const int COLUMN_0 = 0;
39 const int COLUMN_1 = 1;
40 
41 const int STEPS_PER_CYCLE = 4; // Repeat STEPS_PER_CYLE-1 unhighlighted steps plus 1 highlighted step in each cycle
42 const int STEPS_CYCLE_COUNT = 4; // Repeat one highlighted step + STEPS_UNHIGHLIGHTED_PER_HIGHLIGHTED steps this many times
43 const int NUM_COORD_STEPS = 1 + STEPS_PER_CYCLE * STEPS_CYCLE_COUNT;
44 
45 const int MAX_WIDTH_EDIT_ORIGIN_RADIUS = 140;
46 
47 const int CARTESIAN_COORD_MAX = 100;
48 const int CARTESIAN_COORD_MIN = -100;
49 const double CARTESIAN_COORD_STEP = (CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN) / (NUM_COORD_STEPS - 1.0);
50 
51 const int POLAR_RADIUS = CARTESIAN_COORD_MAX;
52 const double POLAR_STEP = POLAR_RADIUS / (NUM_COORD_STEPS - 1.0);
53 
54 const int POLAR_THETA_MAX = 360;
55 const int POLAR_THETA_MIN = 0;
56 const double POLAR_THETA_STEP = (POLAR_THETA_MAX - POLAR_THETA_MIN) / (NUM_COORD_STEPS - 1.0);
57 
58 const double XCENTER = (CARTESIAN_COORD_MIN + CARTESIAN_COORD_MAX) / 2.0;
59 const double YCENTER = (CARTESIAN_COORD_MIN + CARTESIAN_COORD_MAX) / 2.0;
60 
61 const double LINE_WIDTH_THIN = 0.0;
62 const double LINE_WIDTH_THICK = 2.0;
63 
64 const double PI = 3.1415926535;
65 const double DEG_2_RAD = PI / 180.0;
66 
67 const int FONT_SIZE = 6;
68 
69 const double POWER_FOR_LOG = 10.0; // Need a larger power (certainly more than e) to make log gradient obvious
70 
71 const int MINIMUM_DIALOG_WIDTH_COORDS = 800;
72 
74  DlgSettingsAbstractBase (tr ("Coordinates"),
75  "DlgSettingsCoords",
76  mainWindow),
77  m_btnCartesian (0),
78  m_btnPolar (0),
79  m_validatorOriginRadius (0),
80  m_cmbDate (0),
81  m_cmbTime (0),
82  m_scenePreview (0),
83  m_viewPreview (0),
84  m_modelCoordsBefore (0),
85  m_modelCoordsAfter (0)
86 {
87  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::DlgSettingsCoords";
88 
89  QWidget *subPanel = createSubPanel ();
90  finishPanel (subPanel,
91  MINIMUM_DIALOG_WIDTH_COORDS);
92 }
93 
94 DlgSettingsCoords::~DlgSettingsCoords()
95 {
96  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::~DlgSettingsCoords";
97 }
98 
99 void DlgSettingsCoords::annotateAngles (const QFont &defaultFont) {
100 
101  // 0=+x, 1=+y, 2=-x, 3=-y
102  for (int direction = 0; direction < 4; direction++) {
103 
104  QString angle;
105  CoordUnitsPolarTheta thetaUnits = (CoordUnitsPolarTheta) m_cmbXThetaUnits->currentData().toInt();
106 
107  switch (thetaUnits) {
108  case COORD_UNITS_POLAR_THETA_DEGREES:
109  case COORD_UNITS_POLAR_THETA_DEGREES_MINUTES:
110  case COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS:
111  angle = QString::number (90.0 * direction);
112  break;
113 
114  case COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW:
115  angle = QString::number (90.0 * direction);
116  if (direction == 1) {
117  angle = "90E";
118  } else if (direction == 3) {
119  angle = "90W";
120  }
121  break;
122 
123  case COORD_UNITS_POLAR_THETA_GRADIANS:
124  angle = QString::number (100.0 * direction);
125  break;
126 
127  case COORD_UNITS_POLAR_THETA_RADIANS:
128  {
129  static QString radiansUnits [] = {"0", "PI / 2", "PI", "3 * PI / 2"};
130  ENGAUGE_ASSERT (direction < 4);
131  angle = radiansUnits [direction];
132  }
133  break;
134 
135  case COORD_UNITS_POLAR_THETA_TURNS:
136  {
137  static QString turnsUnits [] = {"0", "1 / 4", "1 / 2", "3 / 4"};
138  ENGAUGE_ASSERT (direction < 4);
139  angle = turnsUnits [direction];
140  }
141  break;
142 
143  default:
144  break;
145  }
146 
147  QGraphicsTextItem *textAngle = m_scenePreview->addText (angle);
148  textAngle->setFont (QFont (defaultFont.defaultFamily(), FONT_SIZE));
149  double x = 0, y = 0; // Initialized to prevent compiler warning
150  switch (direction) {
151  case 0:
152  x = CARTESIAN_COORD_MAX - textAngle->boundingRect().width ();
153  break;
154  case 1:
155  case 3:
156  x = XCENTER - textAngle->boundingRect().width () / 2.0;
157  break;
158  case 2:
159  x = CARTESIAN_COORD_MIN;
160  break;
161  }
162  switch (direction) {
163  case 0:
164  case 2:
165  y = YCENTER;
166  break;
167  case 1:
168  y = CARTESIAN_COORD_MIN;
169  break;
170  case 3:
171  y = CARTESIAN_COORD_MAX - textAngle->boundingRect().height ();
172  break;
173  }
174 
175  textAngle->setPos (x, y);
176  }
177 }
178 
179 void DlgSettingsCoords::annotateRadiusAtOrigin(const QFont &defaultFont) {
180 
181  QGraphicsTextItem *textRadius = m_scenePreview->addText (m_editOriginRadius->text());
182  textRadius->setFont (QFont (defaultFont.defaultFamily(), FONT_SIZE));
183  textRadius->setPos (XCENTER - textRadius->boundingRect().width () / 2.0,
184  YCENTER);
185 }
186 
187 QRectF DlgSettingsCoords::boundingRectGraph (CmdMediator &cmdMediator,
188  bool &isEmpty) const
189 {
190  CallbackBoundingRects ftor (mainWindow().transformation());
191 
192  Functor2wRet<const QString &, const Point&, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
194 
195  // There may or may one, two or three axis points. Even if all three are not defined (so
196  // transformation is not defined), we can still get coordinates if there are one or two
197  cmdMediator.iterateThroughCurvePointsAxes (ftorWithCallback);
198 
199  // If the transformation is not defined, then there are no graph coordinates to extract
200  // from the graph curves (and probably trigger an assert)
201  if (mainWindow().transformIsDefined()) {
202  cmdMediator.iterateThroughCurvesPointsGraphs (ftorWithCallback);
203  }
204 
205  return ftor.boundingRectGraph(isEmpty);
206 }
207 
208 void DlgSettingsCoords::createDateTime (QGridLayout *layout,
209  int &row)
210 {
211  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createDateTime";
212 
213  QLabel *label = new QLabel(tr ("Date/Time:"));
214  layout->addWidget (label, row, 1);
215 
216  QWidget *widgetCombos = new QWidget;
217  layout->addWidget (widgetCombos, row++, 2);
218  QHBoxLayout *layoutCombos = new QHBoxLayout;
219  widgetCombos->setLayout (layoutCombos);
220 
221  // Put date and time comboboxes into same widget
222  m_cmbDate = new QComboBox;
223  m_cmbDate->setWhatsThis (tr ("Date format to be used for date values, and date portion of mixed date/time values, "
224  "during input and output.\n\n"
225  "Setting the format to an empty value results in just the time portion appearing in output."));
226  connect (m_cmbDate, SIGNAL (activated (const QString &)), this, SLOT (slotDate (const QString &)));
227  layoutCombos->addWidget (m_cmbDate);
228 
229  m_cmbTime = new QComboBox;
230  m_cmbTime->setWhatsThis (tr ("Time format to be used for time values, and time portion of mixed date/time values, "
231  "during input and output.\n\n"
232  "Setting the format to an empty value results in just the date portion appearing in output."));
233  connect (m_cmbTime, SIGNAL (activated (const QString &)), this, SLOT (slotTime (const QString &)));
234  layoutCombos->addWidget (m_cmbTime);
235 }
236 
237 void DlgSettingsCoords::createGroupCoordsType (QGridLayout *layout,
238  int &row)
239 {
240  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createGroupCoordsType";
241 
242  m_boxCoordsType = new QGroupBox(tr ("Coordinates Types"));
243  layout->addWidget (m_boxCoordsType, row++, 1, 1, 2);
244 
245  QVBoxLayout *layoutGroup = new QVBoxLayout (m_boxCoordsType);
246 
247  QString polarButtonText = QString(tr ("Polar") + " (") + THETA + QString(", " + tr ("R") + ")");
248 
249  m_btnCartesian = new QRadioButton (tr ("Cartesian (X, Y)"), m_boxCoordsType);
250  m_btnCartesian->setWhatsThis (QString(tr("Select cartesian coordinates.\n\n"
251  "The X and Y coordinates will be used")));
252  connect (m_btnCartesian, SIGNAL (toggled(bool)), this, SLOT (slotCartesianPolar (bool)));
253  layoutGroup->addWidget (m_btnCartesian);
254 
255  m_btnPolar = new QRadioButton (polarButtonText, m_boxCoordsType);
256  m_btnPolar->setWhatsThis (QString(tr("Select polar coordinates.\n\n"
257  "The Theta and R coordinates will be used.\n\n"
258  "Polar coordinates are not allowed with log scale for Theta")));
259  connect (m_btnPolar, SIGNAL (toggled(bool)), this, SLOT (slotCartesianPolar (bool)));
260  layoutGroup->addWidget (m_btnPolar);
261 }
262 
263 void DlgSettingsCoords::createGroupXTheta (QGridLayout *layout,
264  int &row)
265 {
266  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createGroupXTheta";
267 
268  m_boxXTheta = new QGroupBox(OVERRIDDEN_VALUE);
269  layout->addWidget (m_boxXTheta, row, 1, 1, 1);
270 
271  QGridLayout *layoutXTheta = new QGridLayout (m_boxXTheta);
272  m_boxXTheta->setLayout (layoutXTheta);
273  int rowGroup = 0;
274 
275  QLabel *labelScale = new QLabel (tr ("Scale:"));
276  layoutXTheta->addWidget (labelScale, rowGroup++, COLUMN_0);
277 
278  m_xThetaLinear = new QRadioButton (tr ("Linear"), m_boxXTheta);
279  m_xThetaLinear->setWhatsThis (QString(tr("Specifies linear scale for the X or Theta coordinate")));
280  connect (m_xThetaLinear, SIGNAL (released ()), this, SLOT (slotXThetaLinear()));
281  layoutXTheta->addWidget (m_xThetaLinear, rowGroup++, COLUMN_0);
282 
283  m_xThetaLog = new QRadioButton (tr ("Log"), m_boxXTheta);
284  m_xThetaLog->setWhatsThis (QString(tr("Specifies logarithmic scale for the X or Theta coordinate.\n\n"
285  "Log scale is not allowed if there are negative coordinates.\n\n"
286  "Log scale is not allowed for the Theta coordinate.")));
287  connect (m_xThetaLog, SIGNAL (released ()), this, SLOT (slotXThetaLog()));
288  layoutXTheta->addWidget (m_xThetaLog, rowGroup++, COLUMN_0);
289 
290  QLabel *labelThetaUnits = new QLabel(tr ("Units:"));
291  layoutXTheta->addWidget (labelThetaUnits, rowGroup++, COLUMN_0);
292 
293  m_cmbXThetaUnits = new QComboBox;
294  connect (m_cmbXThetaUnits, SIGNAL (activated (const QString &)), this, SLOT (slotUnitsXTheta(const QString &))); // activated() ignores code changes
295  layoutXTheta->addWidget (m_cmbXThetaUnits, rowGroup++, COLUMN_0, 1, 2);
296 }
297 
298 void DlgSettingsCoords::createGroupYRadius (QGridLayout *layout,
299  int &row)
300 {
301  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createGroupYRadius";
302 
303  m_boxYRadius = new QGroupBox (OVERRIDDEN_VALUE);
304  layout->addWidget (m_boxYRadius, row++, 2, 1, 1);
305 
306  QGridLayout *layoutYRadius = new QGridLayout (m_boxYRadius);
307  m_boxYRadius->setLayout (layoutYRadius);
308  int rowGroup = 0;
309 
310  QLabel *labelScale = new QLabel (tr ("Scale:"));
311  layoutYRadius->addWidget (labelScale, rowGroup++, COLUMN_0);
312 
313  m_yRadiusLinear = new QRadioButton (tr ("Linear"), m_boxYRadius);
314  m_yRadiusLinear->setWhatsThis (QString(tr("Specifies linear scale for the Y or R coordinate")));
315  connect (m_yRadiusLinear, SIGNAL(released()), this, SLOT (slotYRadiusLinear()));
316  layoutYRadius->addWidget (m_yRadiusLinear, rowGroup, COLUMN_0);
317 
318  QLabel *labelOriginRadius = new QLabel(tr ("Origin radius value:"));
319  layoutYRadius->addWidget (labelOriginRadius, rowGroup++, COLUMN_1);
320 
321  m_yRadiusLog = new QRadioButton (tr ("Log"), m_boxYRadius);
322  m_yRadiusLog->setWhatsThis (QString(tr("Specifies logarithmic scale for the Y or R coordinate\n\n"
323  "Log scale is not allowed if there are negative coordinates.")));
324  connect (m_yRadiusLog, SIGNAL(released ()), this, SLOT (slotYRadiusLog ()));
325  layoutYRadius->addWidget (m_yRadiusLog, rowGroup, COLUMN_0);
326 
327  m_editOriginRadius = new QLineEdit (m_boxYRadius);
328  m_editOriginRadius->setMaximumWidth (MAX_WIDTH_EDIT_ORIGIN_RADIUS);
329  m_editOriginRadius->setWhatsThis (QString(tr("Specify radius value at origin.\n\n"
330  "Normally the radius at the origin is 0, but a nonzero value may be applied in other cases "
331  "(like when the radial units are decibels).")));
332  connect (m_editOriginRadius, SIGNAL (textChanged (const QString &)), this, SLOT (slotPolarOriginRadius(const QString &)));
333  layoutYRadius->addWidget (m_editOriginRadius, rowGroup++, COLUMN_1);
334 
335  QLabel *labelUnits = new QLabel(tr ("Units:"));
336  layoutYRadius->addWidget (labelUnits, rowGroup++, COLUMN_0);
337 
338  m_cmbYRadiusUnits = new QComboBox;
339  connect (m_cmbYRadiusUnits, SIGNAL (activated (const QString &)), this, SLOT (slotUnitsYRadius(const QString &))); // activated() ignores code changes
340  layoutYRadius->addWidget (m_cmbYRadiusUnits, rowGroup++, COLUMN_0, 1, 2);
341 }
342 
343 void DlgSettingsCoords::createOptionalSaveDefault (QHBoxLayout * /* layout */)
344 {
345 }
346 
347 void DlgSettingsCoords::createPreview (QGridLayout *layout,
348  int &row)
349 {
350  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createPreview";
351 
352  QLabel *labelPreview = new QLabel (tr ("Preview"));
353  layout->addWidget (labelPreview, row++, 0, 1, 4);
354 
355  m_scenePreview = new QGraphicsScene (this);
356  m_viewPreview = new ViewPreview (m_scenePreview,
357  ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
358  this);
359  m_viewPreview->setWhatsThis (tr ("Preview window that shows how current settings affect the coordinate system."));
360  m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
361  m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
362  m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
363 
364  layout->addWidget (m_viewPreview, row++, 0, 1, 4);
365 }
366 
368 {
369  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createSubPanel";
370 
371  QWidget *subPanel = new QWidget ();
372  QGridLayout *layout = new QGridLayout (subPanel);
373  subPanel->setLayout (layout);
374 
375  layout->setColumnStretch(0, 1); // Empty first column
376  layout->setColumnStretch(1, 0); // Labels
377  layout->setColumnStretch(2, 0); // User controls
378  layout->setColumnStretch(3, 1); // Empty last column
379 
380  int row = 0;
381  createGroupCoordsType(layout, row);
382  createGroupXTheta (layout, row);
383  createGroupYRadius (layout, row);
384  createDateTime (layout, row);
385  createPreview (layout, row);
386 
387  return subPanel;
388 }
389 
390 void DlgSettingsCoords::drawCartesianLinearX ()
391 {
392  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLinearX";
393 
394  bool isAxis = true;
395  for (int step = 0; step < NUM_COORD_STEPS; step++) {
396  double x = CARTESIAN_COORD_MIN + step * CARTESIAN_COORD_STEP;
397  QGraphicsLineItem *line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
398  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
399  line->setPen(QPen (QBrush ((isHighlighted ? Qt::gray : Qt::lightGray)),
400  LINE_WIDTH_THIN,
401  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
402  if (isAxis) {
403  line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
404  line->setPen(QPen (QBrush (Qt::black),
405  LINE_WIDTH_THICK));
406  }
407  isAxis = false;
408  }
409 }
410 
411 void DlgSettingsCoords::drawCartesianLinearY ()
412 {
413  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLinearY";
414 
415  bool isAxis = true;
416  for (int step = NUM_COORD_STEPS - 1; step >= 0; step--) {
417  double y = CARTESIAN_COORD_MIN + step * CARTESIAN_COORD_STEP;
418  QGraphicsLineItem *line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
419  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
420  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
421  LINE_WIDTH_THIN,
422  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
423  if (isAxis) {
424  line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
425  line->setPen(QPen (QBrush (Qt::black),
426  LINE_WIDTH_THICK));
427  }
428  isAxis = false;
429  }
430 }
431 
432 void DlgSettingsCoords::drawCartesianLogX ()
433 {
434  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLogX";
435 
436  bool isAxis = true;
437  for (int step = 0; step < NUM_COORD_STEPS; step++) {
438  double s = (exp (step / (NUM_COORD_STEPS - 1.0)) - 1.0) /
439  (exp (1.0) - 1.0);
440  double x = (1.0 - s) * CARTESIAN_COORD_MIN + s * CARTESIAN_COORD_MAX;
441  QGraphicsLineItem *line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
442  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
443  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
444  LINE_WIDTH_THIN,
445  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
446  if (isAxis) {
447  line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
448  line->setPen(QPen (QBrush (Qt::black),
449  LINE_WIDTH_THICK));
450  }
451  isAxis = false;
452  }
453 }
454 
455 void DlgSettingsCoords::drawCartesianLogY ()
456 {
457  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLogY";
458 
459  bool isAxis = true;
460  for (int step = 0; step < NUM_COORD_STEPS; step++) {
461  double s = (pow (POWER_FOR_LOG, step / (NUM_COORD_STEPS - 1.0)) - 1.0) /
462  (pow (POWER_FOR_LOG, 1.0) - 1.0);
463  double y = (1.0 - s) * CARTESIAN_COORD_MAX + s * CARTESIAN_COORD_MIN; // Invert y coordinate (min<->max)
464  QGraphicsLineItem *line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
465  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
466  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
467  LINE_WIDTH_THIN,
468  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
469  if (isAxis) {
470  line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
471  line->setPen(QPen (QBrush (Qt::black),
472  LINE_WIDTH_THICK));
473  }
474  isAxis = false;
475  }
476 }
477 
478 void DlgSettingsCoords::drawPolarLinearRadius ()
479 {
480  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawPolarLinearRadius";
481 
482  for (int step = 0; step < NUM_COORD_STEPS; step++) {
483  double radius = step * POLAR_STEP;
484  QGraphicsEllipseItem *line = m_scenePreview->addEllipse (XCENTER - radius,
485  YCENTER - radius,
486  2.0 * radius,
487  2.0 * radius);
488  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
489  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
490  LINE_WIDTH_THIN,
491  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
492  }
493 }
494 
495 void DlgSettingsCoords::drawPolarLogRadius ()
496 {
497  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawPolarLogRadius";
498 
499  for (int step = 0; step < NUM_COORD_STEPS; step++) {
500  double s = (pow (POWER_FOR_LOG, step / (NUM_COORD_STEPS - 1.0)) - 1.0) /
501  (pow (POWER_FOR_LOG, 1.0) - 1.0);
502  double radius = (s * (NUM_COORD_STEPS - 1.0)) * POLAR_STEP;
503  QGraphicsEllipseItem *line = m_scenePreview->addEllipse (XCENTER - radius,
504  YCENTER - radius,
505  2.0 * radius,
506  2.0 * radius);
507  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
508  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
509  LINE_WIDTH_THIN,
510  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
511  }
512 }
513 
514 void DlgSettingsCoords::drawPolarTheta ()
515 {
516  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawPolarTheta";
517 
518  bool isAxis = true;
519  for (int step = 0; step < NUM_COORD_STEPS; step++) {
520  double theta = POLAR_THETA_MIN + step * POLAR_THETA_STEP;
521  double x = POLAR_RADIUS * cos (theta * DEG_2_RAD);
522  double y = POLAR_RADIUS * sin (theta * DEG_2_RAD);
523  QGraphicsLineItem *line = m_scenePreview->addLine (XCENTER, YCENTER, XCENTER + x, YCENTER + y);
524  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
525  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
526  LINE_WIDTH_THIN,
527  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
528  if (isAxis) {
529  line = m_scenePreview->addLine (XCENTER, YCENTER, XCENTER + x, YCENTER + y);
530  line->setPen(QPen (QBrush (Qt::black),
531  LINE_WIDTH_THICK));
532  }
533  isAxis = false;
534  }
535 }
536 
538 {
539  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::handleOk";
540 
542  cmdMediator ().document(),
543  *m_modelCoordsBefore,
544  *m_modelCoordsAfter);
545  cmdMediator ().push (cmd);
546 
547  hide ();
548 }
549 
551 {
552  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::load";
553 
554  setCmdMediator (cmdMediator);
555 
556  // Remove if coordinates are log so later constraints can be applied
557  bool isEmpty;
558  QRectF rectGraph = boundingRectGraph (cmdMediator,
559  isEmpty);
560  bool xThetaGoesNegative = !isEmpty && (rectGraph.x() <= 0);
561  bool yRGoesNegative = !isEmpty && (rectGraph.y() <= 0);
562  m_xThetaLinear->setEnabled (!xThetaGoesNegative);
563  m_xThetaLog->setEnabled (!xThetaGoesNegative);
564  m_yRadiusLinear->setEnabled (!yRGoesNegative);
565  m_yRadiusLog->setEnabled (!yRGoesNegative);
566 
567  // Flush old data
568  if (m_modelCoordsBefore != 0) {
569  delete m_modelCoordsBefore;
570  }
571  if (m_modelCoordsAfter != 0) {
572  delete m_modelCoordsAfter;
573  }
574 
575  // Save new data
576  m_modelCoordsBefore = new DocumentModelCoords (cmdMediator.document().modelCoords());
577  m_modelCoordsAfter = new DocumentModelCoords (cmdMediator.document().modelCoords());
578 
579  // Populate controls
580  DlgValidatorFactory dlgValidatorFactory;
581  m_validatorOriginRadius = dlgValidatorFactory.createWithNonPolar (m_modelCoordsAfter->coordScaleYRadius(),
582  m_modelCoordsAfter->coordUnitsRadius(),
583  m_modelCoordsAfter->coordUnitsDate(),
584  m_modelCoordsAfter->coordUnitsTime(),
586  m_editOriginRadius->setValidator (m_validatorOriginRadius); // Set before call to setText so validator is defined in updateControls
587  m_editOriginRadius->setText (QString::number (m_modelCoordsAfter->originRadius ()));
588 
589  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
590  m_btnCartesian->setChecked (true);
591  } else {
592  m_btnPolar->setChecked (true);
593  }
594 
595  updateCoordUnits(); // Call after checking m_btnCartesian or m_btnPolar
596  loadComboBoxDate();
597  loadComboBoxTime ();
598 
599  m_xThetaLinear->setChecked (m_modelCoordsAfter->coordScaleXTheta() == COORD_SCALE_LINEAR);
600  m_xThetaLog->setChecked (m_modelCoordsAfter->coordScaleXTheta() == COORD_SCALE_LOG);
601  m_yRadiusLinear->setChecked (m_modelCoordsAfter->coordScaleYRadius() == COORD_SCALE_LINEAR);
602  m_yRadiusLog->setChecked (m_modelCoordsAfter->coordScaleYRadius() == COORD_SCALE_LOG);
603 
604  updateControls (); // Probably redundant due to the setChecked just above
605  enableOk (false); // Disable Ok button since there not yet any changes
606  updatePreview();
607 }
608 
609 void DlgSettingsCoords::loadComboBoxDate()
610 {
611  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxDate";
612 
613  m_cmbDate->clear ();
614 
615  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_SKIP),
616  QVariant (COORD_UNITS_DATE_SKIP));
617  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_MONTH_DAY_YEAR),
618  QVariant (COORD_UNITS_DATE_MONTH_DAY_YEAR));
619  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_DAY_MONTH_YEAR),
620  QVariant (COORD_UNITS_DATE_DAY_MONTH_YEAR));
621  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_YEAR_MONTH_DAY),
622  QVariant (COORD_UNITS_DATE_YEAR_MONTH_DAY));
623 
624  ENGAUGE_ASSERT (m_cmbDate->count() == NUM_COORD_UNITS_DATE);
625 
626  int index = m_cmbDate->findData (QVariant (m_modelCoordsAfter->coordUnitsDate()));
627  m_cmbDate->setCurrentIndex (index);
628 }
629 
630 void DlgSettingsCoords::loadComboBoxTime()
631 {
632  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxTime";
633 
634  m_cmbTime->clear ();
635 
636  m_cmbTime->addItem (coordUnitsTimeToString (COORD_UNITS_TIME_SKIP),
637  QVariant (COORD_UNITS_TIME_SKIP));
638  m_cmbTime->addItem (coordUnitsTimeToString (COORD_UNITS_TIME_HOUR_MINUTE),
639  QVariant (COORD_UNITS_TIME_HOUR_MINUTE));
640  m_cmbTime->addItem (coordUnitsTimeToString (COORD_UNITS_TIME_HOUR_MINUTE_SECOND),
641  QVariant (COORD_UNITS_TIME_HOUR_MINUTE_SECOND));
642 
643  ENGAUGE_ASSERT (m_cmbTime->count() == NUM_COORD_UNITS_TIME);
644 
645  int index = m_cmbTime->findData (QVariant (m_modelCoordsAfter->coordUnitsTime()));
646  m_cmbTime->setCurrentIndex (index);
647 }
648 
649 void DlgSettingsCoords::loadComboBoxUnitsNonPolar (QComboBox &cmb,
650  CoordUnitsNonPolarTheta coordUnits)
651 {
652  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxUnitsNonPolar";
653 
654  cmb.clear();
655 
656  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_NUMBER),
657  QVariant (COORD_UNITS_NON_POLAR_THETA_NUMBER));
658  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_DATE_TIME),
659  QVariant (COORD_UNITS_NON_POLAR_THETA_DATE_TIME));
660  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS),
661  QVariant (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS));
662  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW),
663  QVariant (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW));
664 
665  ENGAUGE_ASSERT (cmb.count() == NUM_COORD_UNITS_NON_POLAR_THETA);
666 
667  cmb.setWhatsThis (QString (tr ("Numbers have the simplest and most general format.\n\n"
668  "Date and time values have date and/or time components.\n\n"
669  "Degrees Minutes Seconds (DDD MM SS.S) format uses two integer number for degrees and minutes, and a real number for "
670  "seconds. There are 60 seconds per minute. During input, spaces must be inserted between the three numbers.")));
671 
672  int index = cmb.findData (coordUnits);
673  cmb.setCurrentIndex (index);
674 }
675 
676 void DlgSettingsCoords::loadComboBoxUnitsPolar (QComboBox &cmb,
677  CoordUnitsPolarTheta coordUnits)
678 {
679  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxUnitsPolar";
680 
681  cmb.clear();
682 
683  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES),
684  QVariant (COORD_UNITS_POLAR_THETA_DEGREES));
685  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES),
686  QVariant (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES));
687  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS),
688  QVariant (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS));
689  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW),
690  QVariant (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW));
691  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_GRADIANS),
692  QVariant (COORD_UNITS_POLAR_THETA_GRADIANS));
693  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_RADIANS),
694  QVariant (COORD_UNITS_POLAR_THETA_RADIANS));
695  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_TURNS),
696  QVariant (COORD_UNITS_POLAR_THETA_TURNS));
697 
698  ENGAUGE_ASSERT (cmb.count() == NUM_COORD_UNITS_POLAR_THETA);
699 
700  cmb.setWhatsThis (QString (tr ("Degrees (DDD.DDDDD) format uses a single real number. One complete revolution is 360 degrees.\n\n"
701  "Degrees Minutes (DDD MM.MMM) format uses one integer number for degrees, and a real number for minutes. There are "
702  "60 minutes per degree. During input, a space must be inserted between the two numbers.\n\n"
703  "Degrees Minutes Seconds (DDD MM SS.S) format uses two integer number for degrees and minutes, and a real number for "
704  "seconds. There are 60 seconds per minute. During input, spaces must be inserted between the three numbers.\n\n"
705  "Gradians format uses a single real number. One complete revolution is 400 gradians.\n\n"
706  "Radians format uses a single real number. One complete revolution is 2*pi radians.\n\n"
707  "Turns format uses a single real number. One complete revolution is one turn.")));
708 
709  int index = cmb.findData (coordUnits);
710  cmb.setCurrentIndex (index);
711 }
712 
713 void DlgSettingsCoords::resetSceneRectangle ()
714 {
715  QRect rect (CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0,
716  CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0,
717  CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP,
718  CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP);
719 
720  QGraphicsRectItem *itemPerimeter = new QGraphicsRectItem(rect);
721  itemPerimeter->setVisible(false);
722  m_scenePreview->addItem (itemPerimeter);
723  m_viewPreview->centerOn (QPointF (0.0, 0.0));
724 }
725 
726 void DlgSettingsCoords::slotCartesianPolar (bool)
727 {
728  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotCartesian";
729 
730  if (m_btnCartesian->isChecked ()) {
731  m_modelCoordsAfter->setCoordsType (COORDS_TYPE_CARTESIAN);
732  } else {
733  m_modelCoordsAfter->setCoordsType(COORDS_TYPE_POLAR);
734  }
735  updateCoordUnits();
736  updateControls();
737  updatePreview();
738 }
739 
740 void DlgSettingsCoords::slotDate(const QString &)
741 {
742  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotDate";
743 
744  CoordUnitsDate coordUnits = (CoordUnitsDate) m_cmbDate->currentData ().toInt();
745  m_modelCoordsAfter->setCoordUnitsDate(coordUnits);
746  updateControls();
747  updatePreview();
748 }
749 
750 void DlgSettingsCoords::slotPolarOriginRadius(const QString &)
751 {
752  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotPolarOriginRadius";
753 
754  QString numberText = m_editOriginRadius->text();
755 
756  m_modelCoordsAfter->setOriginRadius(numberText.toDouble ());
757  updateControls();
758  updatePreview();
759 }
760 
761 void DlgSettingsCoords::slotTime(const QString &)
762 {
763  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotTime";
764 
765  CoordUnitsTime coordUnits = (CoordUnitsTime) m_cmbTime->currentData ().toInt();
766  m_modelCoordsAfter->setCoordUnitsTime(coordUnits);
767  updateControls();
768  updatePreview();
769 }
770 
771 void DlgSettingsCoords::slotUnitsXTheta(const QString &)
772 {
773  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotUnitsXTheta";
774 
775  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
776  CoordUnitsNonPolarTheta coordUnits = (CoordUnitsNonPolarTheta) m_cmbXThetaUnits->currentData ().toInt ();
777  m_modelCoordsAfter->setCoordUnitsX(coordUnits);
778  } else {
779  CoordUnitsPolarTheta coordUnits = (CoordUnitsPolarTheta) m_cmbXThetaUnits->currentData ().toInt ();
780  m_modelCoordsAfter->setCoordUnitsTheta(coordUnits);
781  }
782  updateControls ();
783  updatePreview();
784 }
785 
786 void DlgSettingsCoords::slotUnitsYRadius(const QString &)
787 {
788  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotUnitsYRadius";
789 
790  CoordUnitsNonPolarTheta coordUnits = (CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt ();
791  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
792  m_modelCoordsAfter->setCoordUnitsY(coordUnits);
793  } else {
794  m_modelCoordsAfter->setCoordUnitsRadius(coordUnits);
795  }
796  updateControls ();
797  updatePreview();
798 }
799 
800 void DlgSettingsCoords::slotXThetaLinear()
801 {
802  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotXThetaLinear";
803 
804  m_modelCoordsAfter->setCoordScaleXTheta(COORD_SCALE_LINEAR);
805  updateControls ();
806  updatePreview();
807 }
808 
809 void DlgSettingsCoords::slotXThetaLog()
810 {
811  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotXThetaLog";
812 
813  m_modelCoordsAfter->setCoordScaleXTheta(COORD_SCALE_LOG);
814  updateControls ();
815  updatePreview();
816 }
817 
818 void DlgSettingsCoords::slotYRadiusLinear()
819 {
820  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotYRadiusLinear";
821 
822  delete m_validatorOriginRadius;
823 
824  DlgValidatorFactory dlgValidatorFactory;
825  m_validatorOriginRadius = dlgValidatorFactory.createWithNonPolar (COORD_SCALE_LINEAR,
826  m_modelCoordsAfter->coordUnitsRadius(),
827  m_modelCoordsAfter->coordUnitsDate(),
828  m_modelCoordsAfter->coordUnitsTime(),
830  m_editOriginRadius->setValidator (m_validatorOriginRadius);
831 
832  m_modelCoordsAfter->setCoordScaleYRadius((COORD_SCALE_LINEAR));
833  updateControls ();
834  updatePreview();
835 }
836 
837 void DlgSettingsCoords::slotYRadiusLog()
838 {
839  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotYRadiusLog";
840 
841  delete m_validatorOriginRadius;
842 
843  DlgValidatorFactory dlgValidatorFactory;
844  m_validatorOriginRadius = dlgValidatorFactory.createWithNonPolar (COORD_SCALE_LOG,
845  m_modelCoordsAfter->coordUnitsRadius(),
846  m_modelCoordsAfter->coordUnitsDate(),
847  m_modelCoordsAfter->coordUnitsTime(),
849  m_editOriginRadius->setValidator (m_validatorOriginRadius);
850 
851  m_modelCoordsAfter->setCoordScaleYRadius(COORD_SCALE_LOG);
852  updateControls ();
853  updatePreview();
854 }
855 
856 void DlgSettingsCoords::updateControls ()
857 {
858  // LOG4CPP_INFO_S is below
859 
860  QString textOriginRadius = m_editOriginRadius->text();
861  int posOriginRadius = 0;
862 
863  bool goodOriginRadius = true; // Cartesian coordinates do not use origin radius
864  if (m_editOriginRadius->isEnabled ()) {
865 
866  // Origin radius must be greater than zero
867  goodOriginRadius = (m_validatorOriginRadius->validate (textOriginRadius,
868  posOriginRadius) == QValidator::Acceptable);
869  }
870 
871  enableOk (goodOriginRadius);
872 
873  m_boxCoordsType->setEnabled (!m_xThetaLog->isChecked ());
874 
875  m_xThetaLinear->setEnabled (!m_btnPolar->isChecked ());
876  m_xThetaLog->setEnabled (!m_btnPolar->isChecked ());
877  if (m_btnCartesian->isChecked()) {
878  m_yRadiusLinear->setEnabled (true);
879  m_yRadiusLog->setEnabled (true);
880  } else {
881 
882  // Use temporary validator to see if current origin radius would be correct in OTHER linear/log mode
883  DlgValidatorFactory dlgValidatorFactory;
884  DlgValidatorAbstract *dlg = dlgValidatorFactory.createWithNonPolar (m_yRadiusLinear->isChecked () ? COORD_SCALE_LOG : COORD_SCALE_LINEAR,
885  m_modelCoordsAfter->coordUnitsRadius(),
886  m_modelCoordsAfter->coordUnitsDate(),
887  m_modelCoordsAfter->coordUnitsTime(),
889  int posOriginRadiusOther;
890  bool goodOriginRadiusOther = (dlg->validate (textOriginRadius, posOriginRadiusOther) == QValidator::Acceptable);
891 
892  delete dlg; // Deallocate
893 
894  m_yRadiusLinear->setEnabled (goodOriginRadius && goodOriginRadiusOther);
895  m_yRadiusLog->setEnabled (goodOriginRadius && goodOriginRadiusOther);
896  }
897  m_editOriginRadius->setEnabled (m_btnPolar->isChecked ());
898 
899  QString captionXTheta = (m_btnCartesian->isChecked () ?
900  QString (tr ("X")) :
901  THETA) + QString (" %1")
902  .arg (tr ("Coordinates"));
903  QString captionYRadius = (m_btnCartesian->isChecked () ?
904  QString (tr ("Y")) :
905  QString (tr ("R"))) + QString (" %1")
906  .arg (tr ("Coordinates"));
907 
908  if (m_boxXTheta->title() != captionXTheta) {
909  m_boxXTheta->setTitle (captionXTheta);
910  }
911 
912  if (m_boxYRadius->title () != captionYRadius) {
913  m_boxYRadius->setTitle (captionYRadius);
914  }
915 
916  bool enableDateTime;
917  if (m_btnCartesian->isChecked()) {
918  enableDateTime = (((CoordUnitsNonPolarTheta) m_cmbXThetaUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME) ||
919  ((CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME));
920  } else {
921  enableDateTime = ((CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME);
922  }
923  m_cmbDate->setEnabled (enableDateTime);
924  m_cmbTime->setEnabled (enableDateTime);
925 
926  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::updateControls"
927  << " textOriginRadius=" << textOriginRadius.toLatin1().data()
928  << " goodOriginRadius=" << (goodOriginRadius ? "true" : "false")
929  << " originRadius=" << posOriginRadius
930  << " btnPolarChecked=" << (m_btnPolar->isChecked() ? "true" : "false")
931  << " enableDateTime=" << (enableDateTime ? "true" : "false");
932 }
933 
934 void DlgSettingsCoords::updateCoordUnits()
935 {
936  // X and Y units
937  if (m_btnCartesian->isChecked()) {
938  loadComboBoxUnitsNonPolar (*m_cmbXThetaUnits,
939  m_modelCoordsAfter->coordUnitsX());
940  loadComboBoxUnitsNonPolar (*m_cmbYRadiusUnits,
941  m_modelCoordsAfter->coordUnitsY());
942  } else {
943  loadComboBoxUnitsPolar (*m_cmbXThetaUnits,
944  m_modelCoordsAfter->coordUnitsTheta());
945  loadComboBoxUnitsNonPolar (*m_cmbYRadiusUnits,
946  m_modelCoordsAfter->coordUnitsRadius());
947  }
948 }
949 
950 void DlgSettingsCoords::updatePreview()
951 {
952  m_scenePreview->clear();
953 
954  // General approach
955  // 1) Axis lines are extra thick, but since they sometimes disappear as the preview window is rescaled, we keep the
956  // constant-pixel line under each axis line
957  // 2) Every STEPS_UNHIGHLIGHTED_PER_HIGHLIGHTED out of STEPS_UNHIGHLIGHTED_PER_HIGHLIGHTED+1 lines are dashed to make
958  // them more subtle
959 
960  if (m_btnCartesian->isChecked()) {
961 
962  // Cartesian
963  if (m_xThetaLinear->isChecked()) {
964  drawCartesianLinearX ();
965  } else {
966  drawCartesianLogX ();
967  }
968 
969  if (m_yRadiusLinear->isChecked()) {
970  drawCartesianLinearY ();
971  } else {
972  drawCartesianLogY ();
973  }
974 
975  } else {
976 
977  // Polar
978  drawPolarTheta ();
979  if (m_yRadiusLinear->isChecked()) {
980  drawPolarLinearRadius ();
981  } else {
982  drawPolarLogRadius ();
983  }
984 
985  QFont defaultFont;
986  annotateRadiusAtOrigin (defaultFont);
987  annotateAngles (defaultFont);
988  }
989 
990  resetSceneRectangle();
991 }
void setCoordUnitsTime(CoordUnitsTime coordUnits)
Set method for time units.
virtual void createOptionalSaveDefault(QHBoxLayout *layout)
Let subclass define an optional Save As Default button.
void setCoordUnitsDate(CoordUnitsDate coordUnits)
Set method for date units.
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void setCoordUnitsY(CoordUnitsNonPolarTheta coordUnits)
Set method for y units.
void setCoordUnitsX(CoordUnitsNonPolarTheta coordUnits)
Set method for x units.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
CoordScale coordScaleYRadius() const
Get method for linear/log scale on y/radius.
double originRadius() const
Get method for origin radius in polar mode.
void setCoordScaleYRadius(CoordScale coordScale)
Set method for linear/log scale on y/radius.
virtual QValidator::State validate(QString &input, int &pos) const =0
Validate according to the numeric format specific to the leaf class.
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition: Document.cpp:665
CoordUnitsNonPolarTheta coordUnitsRadius() const
Get method for radius units.
Abstract validator for all numeric formats.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
CoordUnitsTime coordUnitsTime() const
Get method for time format when used.
Command for DlgSettingsCoords.
virtual QWidget * createSubPanel()
Create dialog-specific panel to which base class will add Ok and Cancel buttons.
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window...
Definition: ViewPreview.h:14
CoordUnitsNonPolarTheta coordUnitsY() const
Get method for x units.
CoordScale coordScaleXTheta() const
Get method for linear/log scale on x/theta.
void setCoordUnitsTheta(CoordUnitsPolarTheta coordUnits)
Set method for theta units.
CoordsType coordsType() const
Get method for coordinates type.
CoordUnitsNonPolarTheta coordUnitsX() const
Get method for x units.
Model for DlgSettingsCoords and CmdSettingsCoords.
void setOriginRadius(double originRadius)
Set method for origin radius in polar mode.
CoordUnitsDate coordUnitsDate() const
Get method for date format when used.
void setCoordUnitsRadius(CoordUnitsNonPolarTheta coordUnits)
Set method for radius units.
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
void finishPanel(QWidget *subPanel, int minimumWidth=MINIMUM_DIALOG_WIDTH)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
DlgValidatorAbstract * createWithNonPolar(CoordScale coordScale, CoordUnitsNonPolarTheta coordUnits, CoordUnitsDate coordUnitsDate, CoordUnitsTime coordUnitsTime, const QLocale &locale) const
Factory method for generating validators when cartesian/polar case handling is handled externally...
Command queue stack.
Definition: CmdMediator.h:23
Abstract base class for all Settings dialogs.
Validator factory.
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
QLocale locale() const
Get method for locale.
Callback for computing the bounding rectangles of the screen and graph coordinates of the points in t...
MainWindow & mainWindow()
Get method for MainWindow.
virtual void handleOk()
Process slotOk.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:83
MainWindowModel modelMainWindow() const
Get method for main window model.
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
void setCoordScaleXTheta(CoordScale coordScale)
Set method for linear/log scale on x/theta.
DlgSettingsCoords(MainWindow &mainWindow)
Single constructor.
CoordUnitsPolarTheta coordUnitsTheta() const
Get method for theta unit.
void setCoordsType(CoordsType coordsType)
Set method for coordinates type.