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