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