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  {
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::createOptionalSaveDefault (QHBoxLayout * /* layout */)
336 {
337 }
338 
339 void DlgSettingsCoords::createPreview (QGridLayout *layout,
340  int &row)
341 {
342  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createPreview";
343 
344  QLabel *labelPreview = new QLabel ("Preview");
345  layout->addWidget (labelPreview, row++, 0, 1, 4);
346 
347  m_scenePreview = new QGraphicsScene (this);
348  m_viewPreview = new ViewPreview (m_scenePreview,
349  ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
350  this);
351  m_viewPreview->setWhatsThis (tr ("Preview window that shows how current settings affect the coordinate system."));
352  m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
353  m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
354  m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
355 
356  layout->addWidget (m_viewPreview, row++, 0, 1, 4);
357 }
358 
360 {
361  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::createSubPanel";
362 
363  QWidget *subPanel = new QWidget ();
364  QGridLayout *layout = new QGridLayout (subPanel);
365  subPanel->setLayout (layout);
366 
367  layout->setColumnStretch(0, 1); // Empty first column
368  layout->setColumnStretch(1, 0); // Labels
369  layout->setColumnStretch(2, 0); // User controls
370  layout->setColumnStretch(3, 1); // Empty last column
371 
372  int row = 0;
373  createGroupCoordsType(layout, row);
374  createGroupXTheta (layout, row);
375  createGroupYRadius (layout, row);
376  createDateTime (layout, row);
377  createPreview (layout, row);
378 
379  return subPanel;
380 }
381 
382 void DlgSettingsCoords::drawCartesianLinearX ()
383 {
384  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLinearX";
385 
386  bool isAxis = true;
387  for (int step = 0; step < NUM_COORD_STEPS; step++) {
388  double x = CARTESIAN_COORD_MIN + step * CARTESIAN_COORD_STEP;
389  QGraphicsLineItem *line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
390  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
391  line->setPen(QPen (QBrush ((isHighlighted ? Qt::gray : Qt::lightGray)),
392  LINE_WIDTH_THIN,
393  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
394  if (isAxis) {
395  line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
396  line->setPen(QPen (QBrush (Qt::black),
397  LINE_WIDTH_THICK));
398  }
399  isAxis = false;
400  }
401 }
402 
403 void DlgSettingsCoords::drawCartesianLinearY ()
404 {
405  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLinearY";
406 
407  bool isAxis = true;
408  for (int step = NUM_COORD_STEPS - 1; step >= 0; step--) {
409  double y = CARTESIAN_COORD_MIN + step * CARTESIAN_COORD_STEP;
410  QGraphicsLineItem *line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
411  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
412  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
413  LINE_WIDTH_THIN,
414  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
415  if (isAxis) {
416  line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
417  line->setPen(QPen (QBrush (Qt::black),
418  LINE_WIDTH_THICK));
419  }
420  isAxis = false;
421  }
422 }
423 
424 void DlgSettingsCoords::drawCartesianLogX ()
425 {
426  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLogX";
427 
428  bool isAxis = true;
429  for (int step = 0; step < NUM_COORD_STEPS; step++) {
430  double s = (exp (step / (NUM_COORD_STEPS - 1.0)) - 1.0) /
431  (exp (1.0) - 1.0);
432  double x = (1.0 - s) * CARTESIAN_COORD_MIN + s * CARTESIAN_COORD_MAX;
433  QGraphicsLineItem *line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
434  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
435  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
436  LINE_WIDTH_THIN,
437  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
438  if (isAxis) {
439  line = m_scenePreview->addLine (x, CARTESIAN_COORD_MIN, x, CARTESIAN_COORD_MAX);
440  line->setPen(QPen (QBrush (Qt::black),
441  LINE_WIDTH_THICK));
442  }
443  isAxis = false;
444  }
445 }
446 
447 void DlgSettingsCoords::drawCartesianLogY ()
448 {
449  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawCartesianLogY";
450 
451  bool isAxis = true;
452  for (int step = 0; step < NUM_COORD_STEPS; step++) {
453  double s = (pow (POWER_FOR_LOG, step / (NUM_COORD_STEPS - 1.0)) - 1.0) /
454  (pow (POWER_FOR_LOG, 1.0) - 1.0);
455  double y = (1.0 - s) * CARTESIAN_COORD_MAX + s * CARTESIAN_COORD_MIN; // Invert y coordinate (min<->max)
456  QGraphicsLineItem *line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
457  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
458  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
459  LINE_WIDTH_THIN,
460  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
461  if (isAxis) {
462  line = m_scenePreview->addLine (CARTESIAN_COORD_MIN, y, CARTESIAN_COORD_MAX, y);
463  line->setPen(QPen (QBrush (Qt::black),
464  LINE_WIDTH_THICK));
465  }
466  isAxis = false;
467  }
468 }
469 
470 void DlgSettingsCoords::drawPolarLinearRadius ()
471 {
472  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawPolarLinearRadius";
473 
474  for (int step = 0; step < NUM_COORD_STEPS; step++) {
475  double radius = step * POLAR_STEP;
476  QGraphicsEllipseItem *line = m_scenePreview->addEllipse (XCENTER - radius,
477  YCENTER - radius,
478  2.0 * radius,
479  2.0 * radius);
480  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
481  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
482  LINE_WIDTH_THIN,
483  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
484  }
485 }
486 
487 void DlgSettingsCoords::drawPolarLogRadius ()
488 {
489  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawPolarLogRadius";
490 
491  for (int step = 0; step < NUM_COORD_STEPS; step++) {
492  double s = (pow (POWER_FOR_LOG, step / (NUM_COORD_STEPS - 1.0)) - 1.0) /
493  (pow (POWER_FOR_LOG, 1.0) - 1.0);
494  double radius = (s * (NUM_COORD_STEPS - 1.0)) * POLAR_STEP;
495  QGraphicsEllipseItem *line = m_scenePreview->addEllipse (XCENTER - radius,
496  YCENTER - radius,
497  2.0 * radius,
498  2.0 * radius);
499  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
500  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
501  LINE_WIDTH_THIN,
502  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
503  }
504 }
505 
506 void DlgSettingsCoords::drawPolarTheta ()
507 {
508  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::drawPolarTheta";
509 
510  bool isAxis = true;
511  for (int step = 0; step < NUM_COORD_STEPS; step++) {
512  double theta = POLAR_THETA_MIN + step * POLAR_THETA_STEP;
513  double x = POLAR_RADIUS * cos (theta * DEG_2_RAD);
514  double y = POLAR_RADIUS * sin (theta * DEG_2_RAD);
515  QGraphicsLineItem *line = m_scenePreview->addLine (XCENTER, YCENTER, XCENTER + x, YCENTER + y);
516  bool isHighlighted = (step % STEPS_PER_CYCLE == 0);
517  line->setPen(QPen (QBrush (isHighlighted ? Qt::gray : Qt::lightGray),
518  LINE_WIDTH_THIN,
519  (isHighlighted ? Qt::SolidLine : Qt::DashLine)));
520  if (isAxis) {
521  line = m_scenePreview->addLine (XCENTER, YCENTER, XCENTER + x, YCENTER + y);
522  line->setPen(QPen (QBrush (Qt::black),
523  LINE_WIDTH_THICK));
524  }
525  isAxis = false;
526  }
527 }
528 
530 {
531  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::handleOk";
532 
534  cmdMediator ().document(),
535  *m_modelCoordsBefore,
536  *m_modelCoordsAfter);
537  cmdMediator ().push (cmd);
538 
539  hide ();
540 }
541 
543 {
544  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::load";
545 
546  setCmdMediator (cmdMediator);
547 
548  // Remove if coordinates are log so later constraints can be applied
549  bool isEmpty;
550  QRectF rectGraph = boundingRectGraph (cmdMediator,
551  isEmpty);
552  bool xThetaGoesNegative = !isEmpty && (rectGraph.x() <= 0);
553  bool yRGoesNegative = !isEmpty && (rectGraph.y() <= 0);
554  m_xThetaLinear->setEnabled (!xThetaGoesNegative);
555  m_xThetaLog->setEnabled (!xThetaGoesNegative);
556  m_yRadiusLinear->setEnabled (!yRGoesNegative);
557  m_yRadiusLog->setEnabled (!yRGoesNegative);
558 
559  // Flush old data
560  if (m_modelCoordsBefore != 0) {
561  delete m_modelCoordsBefore;
562  }
563  if (m_modelCoordsAfter != 0) {
564  delete m_modelCoordsAfter;
565  }
566 
567  // Save new data
568  m_modelCoordsBefore = new DocumentModelCoords (cmdMediator.document().modelCoords());
569  m_modelCoordsAfter = new DocumentModelCoords (cmdMediator.document().modelCoords());
570 
571  // Populate controls
572  DlgValidatorFactory dlgValidatorFactory;
573  m_validatorOriginRadius = dlgValidatorFactory.createWithNonPolar (m_modelCoordsAfter->coordScaleYRadius(),
574  m_modelCoordsAfter->coordUnitsRadius(),
575  m_modelCoordsAfter->coordUnitsDate(),
576  m_modelCoordsAfter->coordUnitsTime(),
578  m_editOriginRadius->setValidator (m_validatorOriginRadius); // Set before call to setText so validator is defined in updateControls
579  m_editOriginRadius->setText (QString::number (m_modelCoordsAfter->originRadius ()));
580 
581  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
582  m_btnCartesian->setChecked (true);
583  } else {
584  m_btnPolar->setChecked (true);
585  }
586 
587  // X and Y units
588  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
589  loadComboBoxUnitsNonPolar (*m_cmbXThetaUnits,
590  m_modelCoordsAfter->coordUnitsX());
591  loadComboBoxUnitsNonPolar (*m_cmbYRadiusUnits,
592  m_modelCoordsAfter->coordUnitsY());
593  } else {
594  loadComboBoxUnitsPolar (*m_cmbXThetaUnits,
595  m_modelCoordsAfter->coordUnitsTheta());
596  loadComboBoxUnitsNonPolar (*m_cmbYRadiusUnits,
597  m_modelCoordsAfter->coordUnitsRadius());
598  }
599 
600  loadComboBoxDate();
601  loadComboBoxTime ();
602 
603  m_xThetaLinear->setChecked (m_modelCoordsAfter->coordScaleXTheta() == COORD_SCALE_LINEAR);
604  m_xThetaLog->setChecked (m_modelCoordsAfter->coordScaleXTheta() == COORD_SCALE_LOG);
605  m_yRadiusLinear->setChecked (m_modelCoordsAfter->coordScaleYRadius() == COORD_SCALE_LINEAR);
606  m_yRadiusLog->setChecked (m_modelCoordsAfter->coordScaleYRadius() == COORD_SCALE_LOG);
607 
608  updateControls (); // Probably redundant due to the setChecked just above
609  enableOk (false); // Disable Ok button since there not yet any changes
610  updatePreview();
611 }
612 
613 void DlgSettingsCoords::loadComboBoxDate()
614 {
615  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxDate";
616 
617  m_cmbDate->clear ();
618 
619  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_SKIP),
620  QVariant (COORD_UNITS_DATE_SKIP));
621  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_MONTH_DAY_YEAR),
622  QVariant (COORD_UNITS_DATE_MONTH_DAY_YEAR));
623  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_DAY_MONTH_YEAR),
624  QVariant (COORD_UNITS_DATE_DAY_MONTH_YEAR));
625  m_cmbDate->addItem (coordUnitsDateToString (COORD_UNITS_DATE_YEAR_MONTH_DAY),
626  QVariant (COORD_UNITS_DATE_YEAR_MONTH_DAY));
627 
628  ENGAUGE_ASSERT (m_cmbDate->count() == NUM_COORD_UNITS_DATE);
629 
630  int index = m_cmbDate->findData (QVariant (m_modelCoordsAfter->coordUnitsDate()));
631  m_cmbDate->setCurrentIndex (index);
632 }
633 
634 void DlgSettingsCoords::loadComboBoxTime()
635 {
636  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxTime";
637 
638  m_cmbTime->clear ();
639 
640  m_cmbTime->addItem (coordUnitsTimeToString (COORD_UNITS_TIME_SKIP),
641  QVariant (COORD_UNITS_TIME_SKIP));
642  m_cmbTime->addItem (coordUnitsTimeToString (COORD_UNITS_TIME_HOUR_MINUTE),
643  QVariant (COORD_UNITS_TIME_HOUR_MINUTE));
644  m_cmbTime->addItem (coordUnitsTimeToString (COORD_UNITS_TIME_HOUR_MINUTE_SECOND),
645  QVariant (COORD_UNITS_TIME_HOUR_MINUTE_SECOND));
646 
647  ENGAUGE_ASSERT (m_cmbTime->count() == NUM_COORD_UNITS_TIME);
648 
649  int index = m_cmbTime->findData (QVariant (m_modelCoordsAfter->coordUnitsTime()));
650  m_cmbTime->setCurrentIndex (index);
651 }
652 
653 void DlgSettingsCoords::loadComboBoxUnitsNonPolar (QComboBox &cmb,
654  CoordUnitsNonPolarTheta coordUnits)
655 {
656  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxUnitsNonPolar";
657 
658  cmb.clear();
659 
660  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_NUMBER),
661  QVariant (COORD_UNITS_NON_POLAR_THETA_NUMBER));
662  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_DATE_TIME),
663  QVariant (COORD_UNITS_NON_POLAR_THETA_DATE_TIME));
664  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS),
665  QVariant (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS));
666  cmb.addItem (coordUnitsNonPolarThetaToString (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW),
667  QVariant (COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW));
668 
669  ENGAUGE_ASSERT (cmb.count() == NUM_COORD_UNITS_NON_POLAR_THETA);
670 
671  cmb.setWhatsThis (QString (tr ("Numbers have the simplest and most general format.\n\n"
672  "Date and time values have date and/or time components.\n\n"
673  "Degrees Minutes Seconds (DDD MM SS.S) format uses two integer number for degrees and minutes, and a real number for "
674  "seconds. There are 60 seconds per minute. During input, spaces must be inserted between the three numbers.")));
675 
676  int index = cmb.findData (coordUnits);
677  cmb.setCurrentIndex (index);
678 }
679 
680 void DlgSettingsCoords::loadComboBoxUnitsPolar (QComboBox &cmb,
681  CoordUnitsPolarTheta coordUnits)
682 {
683  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::loadComboBoxUnitsPolar";
684 
685  cmb.clear();
686 
687  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES),
688  QVariant (COORD_UNITS_POLAR_THETA_DEGREES));
689  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES),
690  QVariant (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES));
691  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS),
692  QVariant (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS));
693  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW),
694  QVariant (COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW));
695  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_GRADIANS),
696  QVariant (COORD_UNITS_POLAR_THETA_GRADIANS));
697  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_RADIANS),
698  QVariant (COORD_UNITS_POLAR_THETA_RADIANS));
699  cmb.addItem (coordUnitsPolarThetaToString (COORD_UNITS_POLAR_THETA_TURNS),
700  QVariant (COORD_UNITS_POLAR_THETA_TURNS));
701 
702  ENGAUGE_ASSERT (cmb.count() == NUM_COORD_UNITS_POLAR_THETA);
703 
704  cmb.setWhatsThis (QString (tr ("Degrees (DDD.DDDDD) format uses a single real number. One complete revolution is 360 degrees.\n\n"
705  "Degrees Minutes (DDD MM.MMM) format uses one integer number for degrees, and a real number for minutes. There are "
706  "60 minutes per degree. During input, a space must be inserted between the two numbers.\n\n"
707  "Degrees Minutes Seconds (DDD MM SS.S) format uses two integer number for degrees and minutes, and a real number for "
708  "seconds. There are 60 seconds per minute. During input, spaces must be inserted between the three numbers.\n\n"
709  "Gradians format uses a single real number. One complete revolution is 400 gradians.\n\n"
710  "Radians format uses a single real number. One complete revolution is 2*pi radians.\n\n"
711  "Turns format uses a single real number. One complete revolution is one turn.")));
712 
713  int index = cmb.findData (coordUnits);
714  cmb.setCurrentIndex (index);
715 }
716 
717 void DlgSettingsCoords::resetSceneRectangle ()
718 {
719  QRect rect (CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0,
720  CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0,
721  CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP,
722  CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP);
723 
724  QGraphicsRectItem *itemPerimeter = new QGraphicsRectItem(rect);
725  itemPerimeter->setVisible(false);
726  m_scenePreview->addItem (itemPerimeter);
727  m_viewPreview->centerOn (QPointF (0.0, 0.0));
728 }
729 
730 void DlgSettingsCoords::slotCartesianPolar (bool)
731 {
732  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotCartesian";
733 
734  if (m_btnCartesian->isChecked ()) {
735  m_modelCoordsAfter->setCoordsType (COORDS_TYPE_CARTESIAN);
736  } else {
737  m_modelCoordsAfter->setCoordsType(COORDS_TYPE_POLAR);
738  }
739  updateControls();
740  updatePreview();
741 }
742 
743 void DlgSettingsCoords::slotDate(const QString &)
744 {
745  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotDate";
746 
747  CoordUnitsDate coordUnits = (CoordUnitsDate) m_cmbDate->currentData ().toInt();
748  m_modelCoordsAfter->setCoordUnitsDate(coordUnits);
749  updateControls();
750  updatePreview();
751 }
752 
753 void DlgSettingsCoords::slotPolarOriginRadius(const QString &)
754 {
755  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotPolarOriginRadius";
756 
757  QString numberText = m_editOriginRadius->text();
758 
759  m_modelCoordsAfter->setOriginRadius(numberText.toDouble ());
760  updateControls();
761  updatePreview();
762 }
763 
764 void DlgSettingsCoords::slotTime(const QString &)
765 {
766  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotTime";
767 
768  CoordUnitsTime coordUnits = (CoordUnitsTime) m_cmbTime->currentData ().toInt();
769  m_modelCoordsAfter->setCoordUnitsTime(coordUnits);
770  updateControls();
771  updatePreview();
772 }
773 
774 void DlgSettingsCoords::slotUnitsXTheta(const QString &)
775 {
776  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotUnitsXTheta";
777 
778  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
779  CoordUnitsNonPolarTheta coordUnits = (CoordUnitsNonPolarTheta) m_cmbXThetaUnits->currentData ().toInt ();
780  m_modelCoordsAfter->setCoordUnitsX(coordUnits);
781  } else {
782  CoordUnitsPolarTheta coordUnits = (CoordUnitsPolarTheta) m_cmbXThetaUnits->currentData ().toInt ();
783  m_modelCoordsAfter->setCoordUnitsTheta(coordUnits);
784  }
785  updateControls ();
786  updatePreview();
787 }
788 
789 void DlgSettingsCoords::slotUnitsYRadius(const QString &)
790 {
791  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotUnitsYRadius";
792 
793  CoordUnitsNonPolarTheta coordUnits = (CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt ();
794  if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
795  m_modelCoordsAfter->setCoordUnitsY(coordUnits);
796  } else {
797  m_modelCoordsAfter->setCoordUnitsRadius(coordUnits);
798  }
799  updateControls ();
800  updatePreview();
801 }
802 
803 void DlgSettingsCoords::slotXThetaLinear()
804 {
805  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotXThetaLinear";
806 
807  m_modelCoordsAfter->setCoordScaleXTheta(COORD_SCALE_LINEAR);
808  updateControls ();
809  updatePreview();
810 }
811 
812 void DlgSettingsCoords::slotXThetaLog()
813 {
814  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotXThetaLog";
815 
816  m_modelCoordsAfter->setCoordScaleXTheta(COORD_SCALE_LOG);
817  updateControls ();
818  updatePreview();
819 }
820 
821 void DlgSettingsCoords::slotYRadiusLinear()
822 {
823  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotYRadiusLinear";
824 
825  delete m_validatorOriginRadius;
826 
827  DlgValidatorFactory dlgValidatorFactory;
828  m_validatorOriginRadius = dlgValidatorFactory.createWithNonPolar (COORD_SCALE_LINEAR,
829  m_modelCoordsAfter->coordUnitsRadius(),
830  m_modelCoordsAfter->coordUnitsDate(),
831  m_modelCoordsAfter->coordUnitsTime(),
833  m_editOriginRadius->setValidator (m_validatorOriginRadius);
834 
835  m_modelCoordsAfter->setCoordScaleYRadius((COORD_SCALE_LINEAR));
836  updateControls ();
837  updatePreview();
838 }
839 
840 void DlgSettingsCoords::slotYRadiusLog()
841 {
842  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotYRadiusLog";
843 
844  delete m_validatorOriginRadius;
845 
846  DlgValidatorFactory dlgValidatorFactory;
847  m_validatorOriginRadius = dlgValidatorFactory.createWithNonPolar (COORD_SCALE_LOG,
848  m_modelCoordsAfter->coordUnitsRadius(),
849  m_modelCoordsAfter->coordUnitsDate(),
850  m_modelCoordsAfter->coordUnitsTime(),
852  m_editOriginRadius->setValidator (m_validatorOriginRadius);
853 
854  m_modelCoordsAfter->setCoordScaleYRadius(COORD_SCALE_LOG);
855  updateControls ();
856  updatePreview();
857 }
858 
859 void DlgSettingsCoords::updateControls ()
860 {
861  // LOG4CPP_INFO_S is below
862 
863  QString textOriginRadius = m_editOriginRadius->text();
864  int posOriginRadius = 0;
865 
866  bool goodOriginRadius = true; // Cartesian coordinates do not use origin radius
867  if (m_editOriginRadius->isEnabled ()) {
868 
869  // Origin radius must be greater than zero
870  goodOriginRadius = (m_validatorOriginRadius->validate (textOriginRadius,
871  posOriginRadius) == QValidator::Acceptable);
872  }
873 
874  enableOk (goodOriginRadius);
875 
876  m_boxCoordsType->setEnabled (!m_xThetaLog->isChecked ());
877 
878  m_xThetaLinear->setEnabled (!m_btnPolar->isChecked ());
879  m_xThetaLog->setEnabled (!m_btnPolar->isChecked ());
880  if (m_btnCartesian->isChecked()) {
881  m_yRadiusLinear->setEnabled (true);
882  m_yRadiusLog->setEnabled (true);
883  } else {
884 
885  // Use temporary validator to see if current origin radius would be correct in OTHER linear/log mode
886  DlgValidatorFactory dlgValidatorFactory;
887  DlgValidatorAbstract *dlg = dlgValidatorFactory.createWithNonPolar (m_yRadiusLinear->isChecked () ? COORD_SCALE_LOG : COORD_SCALE_LINEAR,
888  m_modelCoordsAfter->coordUnitsRadius(),
889  m_modelCoordsAfter->coordUnitsDate(),
890  m_modelCoordsAfter->coordUnitsTime(),
892  int posOriginRadiusOther;
893  bool goodOriginRadiusOther = (dlg->validate (textOriginRadius, posOriginRadiusOther) == QValidator::Acceptable);
894 
895  delete dlg; // Deallocate
896 
897  m_yRadiusLinear->setEnabled (goodOriginRadius && goodOriginRadiusOther);
898  m_yRadiusLog->setEnabled (goodOriginRadius && goodOriginRadiusOther);
899  }
900  m_editOriginRadius->setEnabled (m_btnPolar->isChecked ());
901 
902  QString captionXTheta = (m_btnCartesian->isChecked () ?
903  QString ("X") :
904  THETA) + QString (" Coordinates");
905  QString captionYRadius = (m_btnCartesian->isChecked () ?
906  QString ("Y") :
907  QString ("R")) + QString (" Coordinates");
908 
909  if (m_boxXTheta->title() != captionXTheta) {
910  m_boxXTheta->setTitle (captionXTheta);
911  }
912 
913  if (m_boxYRadius->title () != captionYRadius) {
914  m_boxYRadius->setTitle (captionYRadius);
915  }
916 
917  bool enableDateTime;
918  if (m_btnCartesian->isChecked()) {
919  enableDateTime = (((CoordUnitsNonPolarTheta) m_cmbXThetaUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME) ||
920  ((CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME));
921  } else {
922  enableDateTime = ((CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME);
923  }
924  m_cmbDate->setEnabled (enableDateTime);
925  m_cmbTime->setEnabled (enableDateTime);
926 
927  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::updateControls"
928  << " textOriginRadius=" << textOriginRadius.toLatin1().data()
929  << " goodOriginRadius=" << (goodOriginRadius ? "true" : "false")
930  << " originRadius=" << posOriginRadius
931  << " btnPolarChecked=" << (m_btnPolar->isChecked() ? "true" : "false")
932  << " enableDateTime=" << (enableDateTime ? "true" : "false");
933 }
934 
935 void DlgSettingsCoords::updatePreview()
936 {
937  m_scenePreview->clear();
938 
939  // General approach
940  // 1) Axis lines are extra thick, but since they sometimes disappear as the preview window is rescaled, we keep the
941  // constant-pixel line under each axis line
942  // 2) Every STEPS_UNHIGHLIGHTED_PER_HIGHLIGHTED out of STEPS_UNHIGHLIGHTED_PER_HIGHLIGHTED+1 lines are dashed to make
943  // them more subtle
944 
945  if (m_btnCartesian->isChecked()) {
946 
947  // Cartesian
948  if (m_xThetaLinear->isChecked()) {
949  drawCartesianLinearX ();
950  } else {
951  drawCartesianLogX ();
952  }
953 
954  if (m_yRadiusLinear->isChecked()) {
955  drawCartesianLinearY ();
956  } else {
957  drawCartesianLogY ();
958  }
959 
960  } else {
961 
962  // Polar
963  drawPolarTheta ();
964  if (m_yRadiusLinear->isChecked()) {
965  drawPolarLinearRadius ();
966  } else {
967  drawPolarLogRadius ();
968  }
969 
970  QFont defaultFont;
971  annotateRadiusAtOrigin (defaultFont);
972  annotateAngles (defaultFont);
973  }
974 
975  resetSceneRectangle();
976 }
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.
virtual QValidator::State validate(QString &input, int &pos) const =0
Validate according to the numeric format specific to the leaf class.
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.
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition: Document.cpp:652
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.
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.
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: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
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:66
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.