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