#include "lts_coord_widget_p.h" namespace LtsCoordWidget { void LtsCoordInputWidgetHandler::onCoordinateDataChanged() { const QPointF coord(coordinate()); if (coord.isNull()) { emit invalidCoordinate(); return; } emit coordinateChanged(coord); } MgrsEdit::MgrsEdit(int precision, QWidget *widget) : LtsCoordInputWidgetHandler(widget) , m_precision(precision) , m_ui(new Ui::Mgrs) { m_ui->setupUi(widget); if (m_precision < 0) m_precision = 0; if (m_precision > 11) m_precision = 11; const int upperLimit = pow(10, m_precision) - 1; m_ui->leEast->setValidator(new QIntValidator(0, upperLimit, m_ui->leEast)); m_ui->leNorth->setValidator(new QIntValidator(0, upperLimit, m_ui->leNorth)); setDefaultMgrsSquares(); connect(m_ui->cbxZone, QOverload::of(&QComboBox::currentIndexChanged), this, &MgrsEdit::onCoordinateDataChanged); connect(m_ui->leEast, &QLineEdit::editingFinished, this, &MgrsEdit::onCoordinateDataChanged); connect(m_ui->leNorth, &QLineEdit::editingFinished, this, &MgrsEdit::onCoordinateDataChanged); } MgrsEdit::~MgrsEdit() { delete m_ui; } bool MgrsEdit::isValid() { const QString &east = m_ui->leEast->text(); if (east.size() != m_precision) return false; const QString &north = m_ui->leNorth->text(); if (north.size() != m_precision) return false; if (m_ui->cbxZone->currentIndex() < 0) return false; if (m_ui->cbxZone->currentText().isEmpty()) return false; return true; } void MgrsEdit::setCoordinate(const QPointF &geoCoord) { const QString mgrsString = LtsCoordTrans::mgrsFromGeographic(geoCoord.x(), geoCoord.y(), m_precision, false); if (mgrsString.isEmpty()) { m_ui->leEast->clear(); m_ui->leNorth->clear(); return; } m_ui->leEast->setText(QString()); m_ui->leNorth->setText(QString()); const QString mgrsSquare = mgrsString.left(3) + QLatin1Char(' ') + mgrsString.mid(3, 2); QString east = mgrsString.mid(5, m_precision); QString north = mgrsString.mid(5 + m_precision, m_precision); int idx = m_ui->cbxZone->findText(mgrsSquare); if (idx < 0) { addMgrsSquare(mgrsSquare); idx = m_ui->cbxZone->findText(mgrsSquare); } m_ui->cbxZone->setCurrentIndex(idx); m_ui->leEast->setText(east); m_ui->leNorth->setText(north); } static inline QString getMgrsCoord(QLineEdit *le, int prec) { QString ret = le->text(); if (ret.isEmpty()) return ret; while (ret.size() < prec) ret += QLatin1Char('0'); le->setText(ret); return ret; } QPointF MgrsEdit::coordinate() const { const QString east = getMgrsCoord(m_ui->leEast, m_precision); const QString north = getMgrsCoord(m_ui->leNorth, m_precision); if (east.isEmpty() || north.isEmpty() || m_ui->cbxZone->currentIndex() < 0) return QPointF(); const QString mgrsString(m_ui->cbxZone->currentText() + east + north); return LtsCoordTrans::geographicFromMgrs(mgrsString); } QToolButton *MgrsEdit::resetButton() { return m_ui->tbReset; } void MgrsEdit::cleanup() { delete m_ui->horizontalLayout; delete m_ui->cbxZone; delete m_ui->leEast; delete m_ui->leNorth; delete m_ui->tbReset; } void MgrsEdit::clear() { m_ui->cbxZone->clear(); m_ui->leEast->clear(); m_ui->leNorth->clear(); setDefaultMgrsSquares(); } void MgrsEdit::setSquaresEditable(bool bEditable) { m_ui->cbxZone->setEditable(bEditable); } void MgrsEdit::setWithSurroundingSquare(bool bEnabled) { m_withMgrsSquareOffset = bEnabled; } static QStringList defaultMgrsSquares() { const QVector squares(LtsCoordTrans::defaultMgrsSquares()); QStringList sl; sl.reserve(squares.size()); for (const LtsCoordTrans::UtmCoordinate &c : squares) sl += c.mgrs(0); std::sort(sl.begin(), sl.end()); return sl; } static QString preferedMgrsSquare() { const LtsCoordTrans::UtmCoordinate c(LtsCoordTrans::preferedMgrsSquare()); return c.mgrs(0); } void MgrsEdit::setDefaultMgrsSquares() { m_ui->cbxZone->addItems(defaultMgrsSquares()); m_ui->cbxZone->setCurrentIndex(m_ui->cbxZone->findText(preferedMgrsSquare())); } void MgrsEdit::addMgrsSquare(const QString &newMgrsSquare) { QStringList sl = defaultMgrsSquares(); sl += newMgrsSquare; if (m_withMgrsSquareOffset) { QStringList squares = utmCoordsToList(LtsCoordTrans::defaultMgrsSquareWithOffsets()); for (const auto &sq : qAsConst(squares)) if (!sl.contains(sq)) sl.append(sq); } std::sort(sl.begin(), sl.end()); m_ui->cbxZone->clear(); m_ui->cbxZone->addItems(sl); } QStringList MgrsEdit::utmCoordsToList(const QVector &coords) { QStringList list; list.reserve(coords.count()); for (const auto &utm : coords) list.append(utm.mgrs(0)); return list; } void MgrsEdit::setMgrsSquares(const QVector &geoCoords) { QStringList sl = utmCoordsToList(geoCoords); if (sl.isEmpty()) return; std::sort(sl.begin(), sl.end()); m_ui->cbxZone->clear(); m_ui->cbxZone->addItems(sl); } Wgs84Edit::Wgs84Edit(QWidget *widget) : LtsCoordInputWidgetHandler(widget) , m_ui(new Ui::Wgs84) { m_ui->setupUi(widget); DoubleValidator *v = new DoubleValidator(-180, 180, 9, m_ui->leLon); v->setNotation(QDoubleValidator::StandardNotation); m_ui->leLon->setValidator(v); v = new DoubleValidator(-180, 180, 9, m_ui->leLat); v->setNotation(QDoubleValidator::StandardNotation); m_ui->leLat->setValidator(v); connect(m_ui->leLon, &QLineEdit::editingFinished, this, &Wgs84Edit::onCoordinateDataChanged); connect(m_ui->leLat, &QLineEdit::editingFinished, this, &Wgs84Edit::onCoordinateDataChanged); } Wgs84Edit::~Wgs84Edit() { delete m_ui; } bool Wgs84Edit::isValid() { return (!m_ui->leLon->text().isEmpty()) && (!m_ui->leLat->text().isEmpty()); } void Wgs84Edit::setCoordinate(const QPointF &geoCoord) { const QPointF coord(geoCoord * LtsCoordTrans::rad2deg()); const QLocale l; m_ui->leLon->setText(l.toString(coord.x(), 'f', 9)); m_ui->leLat->setText(l.toString(coord.y(), 'f', 9)); } QPointF Wgs84Edit::coordinate() const { QPointF ret; const QLocale l; const QString lonStr = m_ui->leLon->text().remove(l.groupSeparator()); const QString latStr = m_ui->leLat->text().remove(l.groupSeparator()); if (lonStr.isEmpty() || latStr.isEmpty()) return ret; ret.rx() = l.toDouble(lonStr); ret.ry() = l.toDouble(latStr); return ret * LtsCoordTrans::deg2rad(); } QToolButton *Wgs84Edit::resetButton() { return m_ui->tbReset; } void Wgs84Edit::cleanup() { delete m_ui->horizontalLayout; delete m_ui->leLon; delete m_ui->leLat; delete m_ui->tbReset; delete m_ui->lblLon; delete m_ui->lblLat; } void Wgs84Edit::clear() { m_ui->leLon->clear(); m_ui->leLat->clear(); } DoubleValidator::DoubleValidator(double bottom, double top, int decimals, QObject *parent) : QDoubleValidator(bottom, top, decimals, parent) {} QValidator::State DoubleValidator::validate(QString &input, int &pos) const { const QValidator::State ret = QDoubleValidator::validate(input, pos); if (ret != QValidator::Acceptable) return ret; QLocale l; const QChar gs(l.groupSeparator()); if (gs.isNull()) return ret; if (input.contains(gs)) return QValidator::Invalid; return ret; } }