7 #include "LatLonEdit.h"
8 #include "ui_LatLonEdit.h"
10 #include "MarbleDebug.h"
28 enum { PositiveSphereIndex = 0, NegativeSphereIndex = 1 };
31 class LatLonEditPrivate;
33 class AbstractInputHandler
36 explicit AbstractInputHandler(LatLonEditPrivate *ui) : m_ui(ui) {}
38 virtual ~AbstractInputHandler() {}
41 virtual void setupUi() = 0;
42 virtual void setupMinMax(LatLonEdit::Dimension dimension) = 0;
43 virtual void setValue(qreal value) = 0;
44 virtual void handleIntEditChange() = 0;
45 virtual void handleUIntEditChange() = 0;
46 virtual void handleFloatEditChange() = 0;
47 virtual qreal calculateValue()
const = 0;
50 LatLonEditPrivate *
const m_ui;
53 class DecimalInputHandler :
public AbstractInputHandler
56 explicit DecimalInputHandler(LatLonEditPrivate *ui) : AbstractInputHandler(ui) {}
58 void setupUi()
override;
59 void setupMinMax(LatLonEdit::Dimension dimension)
override;
60 void setValue(qreal value)
override;
61 void handleIntEditChange()
override;
62 void handleUIntEditChange()
override;
63 void handleFloatEditChange()
override;
64 qreal calculateValue()
const override;
67 class DMSInputHandler :
public AbstractInputHandler
70 explicit DMSInputHandler(LatLonEditPrivate *ui) : AbstractInputHandler(ui) {}
72 void setupUi()
override;
73 void setupMinMax(LatLonEdit::Dimension dimension)
override;
74 void setValue(qreal value)
override;
75 void handleIntEditChange()
override;
76 void handleUIntEditChange()
override;
77 void handleFloatEditChange()
override;
78 qreal calculateValue()
const override;
81 class DMInputHandler :
public AbstractInputHandler
84 explicit DMInputHandler(LatLonEditPrivate *ui) : AbstractInputHandler(ui) {}
86 void setupUi()
override;
87 void setupMinMax(LatLonEdit::Dimension dimension)
override;
88 void setValue(qreal value)
override;
89 void handleIntEditChange()
override;
90 void handleUIntEditChange()
override;
91 void handleFloatEditChange()
override;
93 qreal calculateValue()
const override;
96 class LatLonEditPrivate :
public Ui::LatLonEditPrivate
98 friend class DecimalInputHandler;
99 friend class DMSInputHandler;
100 friend class DMInputHandler;
103 LatLonEdit::Dimension m_dimension;
106 AbstractInputHandler *m_inputHandler;
115 ~LatLonEditPrivate();
123 const bool isNegativeSphere = (sign->
currentIndex() == NegativeSphereIndex);
124 sign->
setCurrentIndex( isNegativeSphere ? PositiveSphereIndex : NegativeSphereIndex );
127 void DecimalInputHandler::setupUi()
129 m_ui->m_floatValueEditor->setSuffix(LatLonEdit::tr(
"\xC2\xB0"));
130 m_ui->m_floatValueEditor->setDecimals(5);
132 m_ui->m_intValueEditor->hide();
133 m_ui->m_uintValueEditor->hide();
136 void DecimalInputHandler::setupMinMax(LatLonEdit::Dimension dimension)
138 const qreal maxValue = (dimension == LatLonEdit::Longitude) ? 180.0 : 90.0;
140 m_ui->m_floatValueEditor->setMinimum(-maxValue);
141 m_ui->m_floatValueEditor->setMaximum( maxValue);
144 void DecimalInputHandler::setValue(qreal value)
148 m_ui->m_floatValueEditor->setValue(value);
151 void DecimalInputHandler::handleIntEditChange()
156 void DecimalInputHandler::handleUIntEditChange()
161 void DecimalInputHandler::handleFloatEditChange()
166 qreal DecimalInputHandler::calculateValue()
const
168 qreal value = m_ui->m_floatValueEditor->value();
170 if (m_ui->m_sign->currentIndex() == NegativeSphereIndex) {
177 void DMSInputHandler::setupUi()
179 m_ui->m_uintValueEditor->setSuffix(LatLonEdit::tr(
"'"));
180 m_ui->m_floatValueEditor->setSuffix(LatLonEdit::tr(
"\""));
181 m_ui->m_floatValueEditor->setDecimals(2);
183 m_ui->m_intValueEditor->show();
184 m_ui->m_uintValueEditor->show();
187 void DMSInputHandler::setupMinMax(LatLonEdit::Dimension dimension)
189 const int maxValue = (dimension == LatLonEdit::Longitude) ? 180 : 90;
191 m_ui->m_intValueEditor->setMinimum(-maxValue);
192 m_ui->m_intValueEditor->setMaximum( maxValue);
195 void DMSInputHandler::setValue(qreal value)
197 value = qAbs( value );
199 int degValue = (int) value;
201 qreal minFValue = 60 * (value - degValue);
202 int minValue = (int) minFValue;
203 qreal secFValue = 60 * (minFValue - minValue);
205 int secValue = qRound(secFValue);
215 m_ui->m_intValueEditor->setValue( degValue );
216 m_ui->m_uintValueEditor->setValue( minValue );
217 m_ui->m_floatValueEditor->setValue( secFValue );
220 void DMSInputHandler::handleIntEditChange()
222 const int degValue = m_ui->m_intValueEditor->value();
223 const int minDegValue = m_ui->m_intValueEditor->minimum();
224 const int maxDegValue = m_ui->m_intValueEditor->maximum();
226 if (degValue <= minDegValue || maxDegValue <= degValue) {
227 m_ui->m_uintValueEditor->setValue( 0 );
228 m_ui->m_floatValueEditor->setValue( 0.0 );
232 void DMSInputHandler::handleUIntEditChange()
234 const int degValue = m_ui->m_intValueEditor->value();
235 const int minValue = m_ui->m_uintValueEditor->value();
239 m_ui->m_uintValueEditor->setValue( 59 );
240 const int degDec = (degValue > 0) ? 1 : -1;
241 m_ui->m_intValueEditor->setValue( degValue - degDec );
243 switchSign( m_ui->m_sign );
244 m_ui->m_uintValueEditor->setValue( 1 );
247 const int minDegValue = m_ui->m_intValueEditor->minimum();
248 const int maxDegValue = m_ui->m_intValueEditor->maximum();
250 if (degValue <= minDegValue || maxDegValue <= degValue) {
252 m_ui->m_uintValueEditor->setValue( 0 );
254 }
else if (minValue >= 60) {
255 m_ui->m_uintValueEditor->setValue( 0 );
257 if (minDegValue+1 == degValue || degValue == maxDegValue-1) {
259 m_ui->m_floatValueEditor->setValue( 0.0 );
261 const int degInc = (degValue > 0) ? 1 : -1;
262 m_ui->m_intValueEditor->setValue( degValue + degInc );
267 void DMSInputHandler::handleFloatEditChange()
269 const int degValue = m_ui->m_intValueEditor->value();
270 const int minValue = m_ui->m_uintValueEditor->value();
271 const qreal secValue = m_ui->m_floatValueEditor->value();
273 if (secValue < 0.0) {
274 const qreal secDiff = -secValue;
275 if (degValue == 0 && minValue == 0) {
276 switchSign( m_ui->m_sign );
277 m_ui->m_floatValueEditor->setValue( secDiff );
279 m_ui->m_floatValueEditor->setValue( 60.0 - secDiff );
281 m_ui->m_uintValueEditor->setValue( minValue - 1 );
283 m_ui->m_uintValueEditor->setValue( 59 );
284 const int degDec = (degValue > 0) ? 1 : -1;
285 m_ui->m_intValueEditor->setValue( degValue - degDec );
289 const int minDegValue = m_ui->m_intValueEditor->minimum();
290 const int maxDegValue = m_ui->m_intValueEditor->maximum();
292 if (degValue <= minDegValue || maxDegValue <= degValue) {
294 m_ui->m_floatValueEditor->setValue( 0.0 );
296 }
else if (secValue >= 60.0) {
297 qreal newSec = secValue - 60.0;
299 if (minValue == 59) {
300 m_ui->m_uintValueEditor->setValue( 0 );
302 if (minDegValue+1 == degValue || degValue == maxDegValue-1) {
306 const int degInc = (degValue > 0) ? 1 : -1;
307 m_ui->m_intValueEditor->setValue( degValue + degInc );
309 m_ui->m_uintValueEditor->setValue( minValue + 1 );
311 m_ui->m_floatValueEditor->setValue( newSec );
316 qreal DMSInputHandler::calculateValue()
const
318 const bool isNegativeDeg = ( m_ui->m_intValueEditor->value() < 0 );
320 const qreal deg = (qreal)(qAbs(m_ui->m_intValueEditor->value()));
321 const qreal min = (qreal)(m_ui->m_uintValueEditor->value()) / 60.0;
322 const qreal sec = m_ui->m_floatValueEditor->value() / 3600.0;
324 qreal value = deg + min + sec;
329 if (m_ui->m_sign->currentIndex() == NegativeSphereIndex) {
336 void DMInputHandler::setupUi()
338 m_ui->m_floatValueEditor->setSuffix(LatLonEdit::tr(
"'"));
339 m_ui->m_floatValueEditor->setDecimals(2);
341 m_ui->m_intValueEditor->show();
342 m_ui->m_uintValueEditor->hide();
345 void DMInputHandler::setupMinMax(LatLonEdit::Dimension dimension)
347 const int maxValue = (dimension == LatLonEdit::Longitude) ? 180 : 90;
349 m_ui->m_intValueEditor->setMinimum(-maxValue);
350 m_ui->m_intValueEditor->setMaximum( maxValue);
353 void DMInputHandler::setValue(qreal value)
357 int degValue = (int)value;
359 qreal minFValue = 60 * (value - degValue);
361 int minValue = qRound( minFValue );
367 m_ui->m_intValueEditor->setValue( degValue );
368 m_ui->m_floatValueEditor->setValue( minFValue );
371 void DMInputHandler::handleIntEditChange()
373 const int degValue = m_ui->m_intValueEditor->value();
374 const int minDegValue = m_ui->m_intValueEditor->minimum();
375 const int maxDegValue = m_ui->m_intValueEditor->maximum();
377 if (degValue <= minDegValue || maxDegValue <= degValue) {
378 m_ui->m_floatValueEditor->setValue( 0.0 );
382 void DMInputHandler::handleUIntEditChange()
387 void DMInputHandler::handleFloatEditChange()
389 const int degValue = m_ui->m_intValueEditor->value();
390 const qreal minValue = m_ui->m_floatValueEditor->value();
392 if (minValue < 0.0) {
393 const qreal minDiff = -minValue;
395 switchSign( m_ui->m_sign );
396 m_ui->m_floatValueEditor->setValue( minDiff );
398 m_ui->m_floatValueEditor->setValue( 60.0 - minDiff );
399 m_ui->m_intValueEditor->setValue( degValue - 1 );
402 const int minDegValue = m_ui->m_intValueEditor->minimum();
403 const int maxDegValue = m_ui->m_intValueEditor->maximum();
405 if (degValue <= minDegValue || maxDegValue <= degValue) {
407 m_ui->m_floatValueEditor->setValue( 0.0 );
409 }
else if (minValue >= 60.0) {
410 qreal newMin = minValue - 60.0;
412 if (minDegValue+1 == degValue || degValue == maxDegValue-1) {
416 m_ui->m_intValueEditor->setValue( degValue + 1 );
418 m_ui->m_floatValueEditor->setValue( newMin );
423 qreal DMInputHandler::calculateValue()
const
425 const bool isNegativeDeg = ( m_ui->m_intValueEditor->value() < 0 );
427 const qreal deg = (qreal)(qAbs(m_ui->m_intValueEditor->value()));
428 const qreal min = m_ui->m_floatValueEditor->value() / 60.0;
430 qreal value = deg + min;
435 if (m_ui->m_sign->currentIndex() == NegativeSphereIndex) {
443 LatLonEditPrivate::LatLonEditPrivate()
444 : m_dimension(LatLonEdit::Latitude)
447 , m_inputHandler(new DMSInputHandler(this))
451 LatLonEditPrivate::~LatLonEditPrivate()
453 delete m_inputHandler;
456 void LatLonEditPrivate::init(
QWidget* parent) { setupUi(parent); }
464 :
QWidget( parent ), d(new LatLonEditPrivate())
467 setDimension(dimension);
468 setNotation(notation);
470 connect(d->m_intValueEditor, SIGNAL(valueChanged(
int)),
this, SLOT(checkIntValueOverflow()));
471 connect(d->m_uintValueEditor, SIGNAL(valueChanged(
int)),
this, SLOT(checkUIntValueOverflow()));
472 connect(d->m_floatValueEditor, SIGNAL(valueChanged(
double)),
this, SLOT(checkFloatValueOverflow()));
474 connect(d->m_sign, SIGNAL(currentIndexChanged(
int)),
475 this, SLOT(onSignChanged()));
478 LatLonEdit::~LatLonEdit()
483 qreal LatLonEdit::value()
const
490 return d->m_notation;
493 void LatLonEdit::onSignChanged()
499 if (d->m_sign->currentIndex() == PositiveSphereIndex) {
500 if (d->m_value < 0.0) {
504 if (d->m_value > 0.0) {
509 emit valueChanged( d->m_value );
512 void LatLonEdit::setDimension( Dimension dimension )
514 d->m_dimension = dimension;
516 d->m_updating =
true;
518 d->m_inputHandler->setupMinMax(dimension);
526 d->m_sign->addItem( tr(
"E",
"East, the direction" ) );
527 d->m_sign->addItem( tr(
"W",
"West, the direction" ) );
530 d->m_sign->addItem( tr(
"N",
"North, the direction" ) );
531 d->m_sign->addItem( tr(
"S",
"South, the direction" ) );
536 d->m_updating =
false;
544 delete d->m_inputHandler;
545 d->m_inputHandler =
nullptr;
549 d->m_inputHandler =
new DecimalInputHandler(d);
552 d->m_inputHandler =
new DMSInputHandler(d);
555 d->m_inputHandler =
new DMInputHandler(d);
557 case GeoDataCoordinates::UTM:
565 if (!d->m_inputHandler) {
568 d->m_inputHandler =
new DecimalInputHandler(d);
571 d->m_notation = notation;
572 d->m_inputHandler->setupUi();
573 d->m_inputHandler->setupMinMax(d->m_dimension);
574 d->m_inputHandler->setValue(d->m_value);
577 void LatLonEdit::checkFloatValueOverflow()
582 d->m_updating =
true;
584 d->m_inputHandler->handleFloatEditChange();
586 d->m_updating =
false;
592 void LatLonEdit::checkUIntValueOverflow()
597 d->m_updating =
true;
599 d->m_inputHandler->handleUIntEditChange();
601 d->m_updating =
false;
606 void LatLonEdit::checkIntValueOverflow()
611 d->m_updating =
true;
613 d->m_inputHandler->handleIntEditChange();
615 d->m_updating =
false;
620 void LatLonEdit::setValue( qreal value )
623 const qreal maxValue = (d->m_dimension == Longitude) ? 180.0 : 90.0;
625 if (value > maxValue) {
628 const qreal minValue = -maxValue;
629 if (value < minValue) {
635 if( value == d->m_value ) {
645 d->m_updating =
true;
647 d->m_inputHandler->setValue(value);
649 const bool isNegative = (value < 0.0);
650 d->m_sign->setCurrentIndex( isNegative ? NegativeSphereIndex : PositiveSphereIndex );
652 d->m_updating =
false;
655 void LatLonEdit::recalculate()
657 d->m_value = d->m_inputHandler->calculateValue();
659 emit valueChanged( d->m_value );
663 #include "moc_LatLonEdit.cpp"