diff --git a/gui/gmapdlg.cc b/gui/gmapdlg.cc index 2a7d570b8..ee17d8da5 100644 --- a/gui/gmapdlg.cc +++ b/gui/gmapdlg.cc @@ -22,20 +22,20 @@ //------------------------------------------------------------------------ #include "gmapdlg.h" -#include // for QAbstractButton #include // for QAbstractItemView #include // for QDateTime, operator<, operator> +#include // for QDebug #include // for QFrame #include // for QHBoxLayout #include // for QHeaderView #include // for QItemSelectionModel +#include // for QList #include // for QMenu -#include // for QPushButton +#include // for QModelIndexList #include // for QStandardItemModel #include // for QTreeView -#include // for QVariant #include // for CheckState, ContextMenuPolicy -#include // for QForeachContainer, qMakeForeachContainer, foreach +#include // for qDebug #include "appname.h" // for appName #include "gpx.h" // for GpxWaypoint, GpxTrack, GpxRoute, Gpx, GpxItem, GpxTrackPoint, GpxTrackSegment #include "latlng.h" // for LatLn @@ -101,8 +101,8 @@ void GMapDialog::appendTrackInfo(QStandardItem* it, const GpxTrack& trk) QDateTime stopTime; bool first = true; int count = 0; - foreach (const GpxTrackSegment& seg, trk.getTrackSegments()) { - foreach (const GpxTrackPoint& pt, seg.getTrackPoints()) { + for (const GpxTrackSegment& seg : trk.getTrackSegments()) { + for (const GpxTrackPoint& pt : seg.getTrackPoints()) { count++; QDateTime t = pt.getDateTime(); if (!t.isValid()) { @@ -141,11 +141,10 @@ void GMapDialog::appendRouteInfo(QStandardItem* it, const GpxRoute& rte) } //------------------------------------------------------------------------ -GMapDialog::GMapDialog(QWidget* parent, const QString& gpxFileName, QPlainTextEdit* te): QDialog(parent) +GMapDialog::GMapDialog(QWidget* parent, const Gpx& mapData, QPlainTextEdit* te): QDialog(parent), gpx_(mapData) { ui_.setupUi(this); this->setWindowTitle(QString(appName) + " " + QString("Google Maps")); - gpx_.read(gpxFileName); mapWidget_ = new Map(this, gpx_, te); auto* lay = new QHBoxLayout(ui_.frame); @@ -153,61 +152,57 @@ GMapDialog::GMapDialog(QWidget* parent, const QString& gpxFileName, QPlainTextEd lay->addWidget(mapWidget_); model_ = new QStandardItemModel(this); - menuIndex_ = -1; // Actually set for real in showContextMenu(). wptItem_ = new StandardItem(tr("Waypoints")); wptItem_->setCheckable(true); wptItem_->setCheckState(Qt::Checked); model_->appendRow(wptItem_); - for (int i=0; iappendRow(it); it->setCheckable(true); it->setCheckState(Qt::Checked); - it->setData(QVariant::fromValue((void*)&wpt)); appendWaypointInfo(it, wpt); - wptList_ << it; } trkItem_ = new StandardItem(tr("Tracks")); trkItem_->setCheckable(true); trkItem_->setCheckState(Qt::Checked); model_->appendRow(trkItem_); - for (int i=0; iappendRow(it); it->setCheckable(true); it->setCheckState(Qt::Checked); - it->setData(QVariant::fromValue((void*)&trk)); appendTrackInfo(it, trk); - trkList_ << it; } rteItem_ = new StandardItem(tr("Routes")); rteItem_->setCheckable(true); rteItem_->setCheckState(Qt::Checked); model_->appendRow(rteItem_); - for (int i=0; iappendRow(it); it->setCheckable(true); it->setCheckState(Qt::Checked); - it->setData(QVariant::fromValue((void*)&rte)); appendRouteInfo(it, rte); - rteList_ << it; } ui_.treeView->header()->hide(); ui_.treeView->setModel(model_); ui_.treeView->setExpandsOnDoubleClick(false); connect(model_, &QStandardItemModel::itemChanged, - this, &GMapDialog::itemChangedX); - connect(mapWidget_, &Map::waypointClicked, this, &GMapDialog::waypointClickedX); - connect(mapWidget_, &Map::routeClicked, this, &GMapDialog::routeClickedX); - connect(mapWidget_, &Map::trackClicked, this, &GMapDialog::trackClickedX); + this, &GMapDialog::itemChangedX); + connect(mapWidget_, &Map::waypointClicked, this, [this](int i)->void { + itemClickedX(wptItem_->child(i)); + }); + connect(mapWidget_, &Map::routeClicked, this, [this](int i)->void { + itemClickedX(rteItem_->child(i)); + }); + connect(mapWidget_, &Map::trackClicked, this, [this](int i)->void { + itemClickedX(trkItem_->child(i)); + }); connect(ui_.treeView, &QAbstractItemView::doubleClicked, this, &GMapDialog::treeDoubleClicked); connect(ui_.treeView->selectionModel(), &QItemSelectionModel::selectionChanged, @@ -218,136 +213,93 @@ GMapDialog::GMapDialog(QWidget* parent, const QString& gpxFileName, QPlainTextEd this, &GMapDialog::showContextMenu); } -//------------------------------------------------------------------------- -void GMapDialog::itemChangedX(QStandardItem* it) -{ - bool show = (it->checkState() == Qt::Checked); - if (it == trkItem_) { - if (show) { - mapWidget_->showTracks(gpx_.getTracks()); - } else { - mapWidget_->hideAllTracks(); - } - } - - else if (it == wptItem_) { - if (show) { - mapWidget_->showWaypoints(gpx_.getWaypoints()); - } else { - mapWidget_->hideAllWaypoints(); - } - } - - else if (it == rteItem_) { - if (show) { - mapWidget_->showRoutes(gpx_.getRoutes()); +//------------------------------------------------------------------------ +void GMapDialog::trace(const QString& label, const QStandardItem* it) +{ + if constexpr(debug_) { + QDebug qdb(QtDebugMsg); + qdb.nospace().noquote() << label + ": "; + qdb.quote(); + if (it == nullptr) { + qdb << "null item"; } else { - mapWidget_->hideAllRoutes(); - } - } - - else { - // Individual items, find the right one. - GpxItem* git = static_cast(it->data().value()); - if (git != nullptr) { - git->setVisible(show); - for (int i=0; isetWaypointVisibility(i, show); - } - } - for (int i=0; isetTrackVisibility(i, show); - } - } - for (int i=0; isetRouteVisibility(i, show); - } + QStandardItem* parent = it->parent(); + if (parent == nullptr) { + qdb << "parent: none"; + } else { + qdb << "parent: " << parent->text(); } + qdb << " item: " << it->text() << " (row: " << it->row() << ")"; } } } - -//------------------------------------------------------------------------- -int GMapDialog::waypointIndex(QStandardItem* it) + +//------------------------------------------------------------------------ +void GMapDialog::showHideChild(const QStandardItem* child) { - for (int j=0; jparent(); + bool showTop = (top->checkState() == Qt::Checked); + bool show = showTop && (child->checkState() == Qt::Checked); + int row = child->row(); + if (top == wptItem_) { + mapWidget_->setWaypointVisibility(row, show); + } else if (top == trkItem_) { + mapWidget_->setTrackVisibility(row, show); + } else if (top == rteItem_) { + mapWidget_->setRouteVisibility(row, show); } - return -1; } -//------------------------------------------------------------------------- -int GMapDialog::trackIndex(QStandardItem* it) +//------------------------------------------------------------------------ +void GMapDialog::showHideChildren(const QStandardItem* top) { - for (int j=0; jrowCount(); ++row) { + const QStandardItem* child = top->child(row); + showHideChild(child); } - return -1; } //------------------------------------------------------------------------- -int GMapDialog::routeIndex(QStandardItem* it) +void GMapDialog::itemChangedX(QStandardItem* it) { - for (int j=0; jparent(); + if ((parent == wptItem_) || (parent == trkItem_) || (parent == rteItem_)) { + showHideChild(it); } } - return -1; } //------------------------------------------------------------------------- void GMapDialog::treeDoubleClicked(const QModelIndex& idx) { QStandardItem* it = model_->itemFromIndex(idx); - int i = waypointIndex(it); - if (i >= 0) { + trace("treeDoubleClicked", it); + QStandardItem* parent = it->parent(); + int row = it->row(); + if (parent == wptItem_) { + parent->setCheckState(Qt::Checked); it->setCheckState(Qt::Checked); - gpx_.getWaypoints()[i].setVisible(true); - mapWidget_->panTo(gpx_.getWaypoints()[i].getLocation()); - mapWidget_->setWaypointVisibility(i, true); - return; - } - i = trackIndex(it); - if (i >= 0) { - mapWidget_->frameTrack(i); + mapWidget_->panTo(gpx_.getWaypoints().at(row).getLocation()); + } else if (parent == trkItem_) { + parent->setCheckState(Qt::Checked); it->setCheckState(Qt::Checked); - gpx_.getTracks()[i].setVisible(true); - mapWidget_->setTrackVisibility(i, true); - return; - } - i = routeIndex(it); - if (i >= 0) { - mapWidget_->frameRoute(i); + mapWidget_->frameTrack(row); + } else if (parent == rteItem_) { + parent->setCheckState(Qt::Checked); it->setCheckState(Qt::Checked); - gpx_.getRoutes()[i].setVisible(true); - mapWidget_->setRouteVisibility(i, true); - return; + mapWidget_->frameRoute(row); } } //------------------------------------------------------------------------- -void GMapDialog::waypointClickedX(int i) -{ - if (i>=0 && i < wptList_.size()) { - QStandardItem* it = wptList_[i]; - QModelIndex idx = model_->indexFromItem(it); - ui_.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter); - ui_.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect); - } -} -//------------------------------------------------------------------------- -void GMapDialog::trackClickedX(int i) +void GMapDialog::itemClickedX(const QStandardItem* it) { - if (i>=0 && i indexFromItem(it); ui_.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter); ui_.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect); @@ -355,221 +307,139 @@ void GMapDialog::trackClickedX(int i) } //------------------------------------------------------------------------- -void GMapDialog::routeClickedX(int i) +void GMapDialog::selectionChangedX(const QItemSelection& sel, const QItemSelection& desel) { - if (i>=0 && i indexFromItem(it); - ui_.treeView->scrollTo(idx, QAbstractItemView::PositionAtCenter); - ui_.treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect); + if constexpr(debug_) { + qDebug() << "selectionChangedX"; } -} - -//------------------------------------------------------------------------- -void GMapDialog::selectionChangedX(const QItemSelection& sel, const QItemSelection& desel) -{ - int k=0; - foreach (QStandardItem* w, wptList_) { - QModelIndex idx = model_->indexFromItem(w); - if (desel.contains(idx)) { - mapWidget_->setWaypointColorBlue(k); + for (const QModelIndexList idxs = desel.indexes(); const auto& idx : idxs) { + const QStandardItem* it = model_->itemFromIndex(idx); + const QStandardItem* parent = it->parent(); + if (parent == wptItem_) { + int row = it->row(); + mapWidget_->setWaypointColorBlue(row); } - if (sel.contains(idx)) { - mapWidget_->setWaypointColorRed(k); + } + for (const QModelIndexList idxs = sel.indexes(); const auto& idx : idxs) { + const QStandardItem* it = model_->itemFromIndex(idx); + const QStandardItem* parent = it->parent(); + if (parent == wptItem_) { + int row = it->row(); + mapWidget_->setWaypointColorRed(row); } - k++; } } //------------------------------------------------------------------------ -void GMapDialog::expandCollapseAll(const QList& li, - QStandardItem* top, bool exp) +void GMapDialog::expandCollapseAll(QStandardItem* top, bool exp) { ui_.treeView->setExpanded(model_->indexFromItem(top), exp); - foreach (QStandardItem* it, li) { - QModelIndex idx = model_->indexFromItem(it); - ui_.treeView->setExpanded(idx, exp); + for (int row = 0; row < top->rowCount(); ++row) { + const QStandardItem* child = top->child(row); + ui_.treeView->setExpanded(model_->indexFromItem(child), exp); } } //------------------------------------------------------------------------ -void GMapDialog::expandAllWaypoints() -{ - expandCollapseAll(wptList_, wptItem_, true); -} -//------------------------------------------------------------------------ -void GMapDialog::expandAllTracks() -{ - expandCollapseAll(trkList_, trkItem_, true); -} -//------------------------------------------------------------------------ -void GMapDialog::expandAllRoutes() -{ - expandCollapseAll(rteList_, rteItem_, true); -} - -//------------------------------------------------------------------------ -void GMapDialog::collapseAllWaypoints() -{ - expandCollapseAll(wptList_, wptItem_,false); -} -//------------------------------------------------------------------------ -void GMapDialog::collapseAllTracks() -{ - expandCollapseAll(trkList_, trkItem_,false); -} -//------------------------------------------------------------------------ -void GMapDialog::collapseAllRoutes() -{ - expandCollapseAll(rteList_, rteItem_,false); -} - -//------------------------------------------------------------------------ -void GMapDialog::checkUncheckAll(const QList& li, - QStandardItem* top, bool ck) +void GMapDialog::showHideAll(QStandardItem* top, bool ck) { - top->setCheckState(ck ? Qt::Checked: Qt::Unchecked); - foreach (QStandardItem* it, li) { - it->setCheckState(ck ? Qt::Checked: Qt::Unchecked); + trace("showHideAll", top); + if (ck) { + mapWidget_->resetBounds(); } -} -//------------------------------------------------------------------------ -void GMapDialog::showAllWaypoints() -{ - foreach (GpxWaypoint wpt, gpx_.getWaypoints()) { - wpt.setVisible(true); - } - checkUncheckAll(wptList_, wptItem_, true); - mapWidget_->showWaypoints(gpx_.getWaypoints()); -} -//------------------------------------------------------------------------ -void GMapDialog::showAllTracks() -{ - foreach (GpxTrack trk, gpx_.getTracks()) { - trk.setVisible(true); - } - checkUncheckAll(trkList_, trkItem_, true); - mapWidget_->showTracks(gpx_.getTracks()); -} - -//------------------------------------------------------------------------ -void GMapDialog::showAllRoutes() -{ - foreach (GpxRoute rte, gpx_.getRoutes()) { - rte.setVisible(true); + top->setCheckState(ck ? Qt::Checked: Qt::Unchecked); + for (int row = 0; row < top->rowCount(); ++row) { + QStandardItem* child = top->child(row); + child->setCheckState(ck ? Qt::Checked: Qt::Unchecked); } - checkUncheckAll(rteList_, rteItem_, true); - mapWidget_->showRoutes(gpx_.getRoutes()); } //------------------------------------------------------------------------ -void GMapDialog::hideAllWaypoints() +void GMapDialog::showOnlyThis(QStandardItem* top, int menuRow) { - foreach (GpxWaypoint wpt, gpx_.getWaypoints()) { - wpt.setVisible(false); + trace("showOnlyThis", top->child(menuRow)); + if (top == wptItem_) { + mapWidget_->panTo(gpx_.getWaypoints().at(menuRow).getLocation()); + } else if (top == trkItem_) { + mapWidget_->frameTrack(menuRow); + } else if (top = rteItem_) { + mapWidget_->frameRoute(menuRow); } - checkUncheckAll(wptList_, wptItem_, false); - mapWidget_->showWaypoints(gpx_.getWaypoints()); -} -//------------------------------------------------------------------------ -void GMapDialog::hideAllTracks() -{ - foreach (GpxTrack trk, gpx_.getTracks()) { - trk.setVisible(false); - } - checkUncheckAll(trkList_, trkItem_, false); - mapWidget_->showTracks(gpx_.getTracks()); - -} -//------------------------------------------------------------------------ -void GMapDialog::hideAllRoutes() -{ - foreach (GpxRoute rte, gpx_.getRoutes()) { - rte.setVisible(false); + for (int row = 0; row < top->rowCount(); ++row) { + QStandardItem* child = top->child(row); + child->setCheckState(row == menuRow? Qt::Checked: Qt::Unchecked); } - checkUncheckAll(rteList_, rteItem_, false); - mapWidget_->showRoutes(gpx_.getRoutes()); - + top->setCheckState(Qt::Checked); } -//------------------------------------------------------------------------ -void GMapDialog::showOnlyThisWaypoint() +void GMapDialog::showTopContextMenu(const QStringList& text, QStandardItem* top, const QPoint& pt) { - QList & wlist = gpx_.getWaypoints(); - for (int i=0; isetCheckState(i==menuIndex_? Qt::Checked: Qt::Unchecked); - } - wptItem_->setCheckState(Qt::Checked); - mapWidget_->showWaypoints(gpx_.getWaypoints()); + QMenu menu(this); + menu.addAction(text.at(0), this, [this, &top]()->void { + showHideAll(top, true); + }); + menu.addAction(text.at(1), this, [this, &top]()->void { + showHideAll(top, false); + }); + menu.addAction(text.at(2), this, [this, &top]()->void { + expandCollapseAll(top, true); + }); + menu.addAction(text.at(3), this, [this, &top]()->void { + expandCollapseAll(top, false); + }); + menu.exec(ui_.treeView->mapToGlobal(pt)); } -//------------------------------------------------------------------------ -void GMapDialog::showOnlyThisTrack() -{ - QList & tlist = gpx_.getTracks(); - for (int i=0; isetCheckState(i==menuIndex_? Qt::Checked: Qt::Unchecked); - } - trkItem_->setCheckState(Qt::Checked); - mapWidget_->showTracks(gpx_.getTracks()); -} -//------------------------------------------------------------------------ -void GMapDialog::showOnlyThisRoute() +void GMapDialog::showChildContextMenu(const QString& text, const QStandardItem* child, const QPoint& pt) { - QList & rlist = gpx_.getRoutes(); - for (int i=0; isetCheckState(i==menuIndex_? Qt::Checked: Qt::Unchecked); - } - rteItem_->setCheckState(Qt::Checked); - mapWidget_->showRoutes(gpx_.getRoutes()); - + QStandardItem* parent = child->parent(); + int row = child->row(); + QMenu menu(this); + menu.addAction(text, this, [this, &row, &parent]()->void { + showOnlyThis(parent, row); + }); + menu.exec(ui_.treeView->mapToGlobal(pt)); } //------------------------------------------------------------------------ void GMapDialog::showContextMenu(const QPoint& pt) { + if constexpr(debug_) { + qDebug() << "showContextMenu"; + } QModelIndex idx = ui_.treeView->indexAt(pt); - QStandardItem* it = model_->itemFromIndex(idx); - int j; - if (model_->indexFromItem(wptItem_) == idx) { - QMenu menu(this); - menu.addAction(tr("Show All Waypoints"), this, &GMapDialog::showAllWaypoints); - menu.addAction(tr("Hide All Waypoints"), this, &GMapDialog::hideAllWaypoints); - menu.addAction(tr("Expand All"), this, &GMapDialog::expandAllWaypoints); - menu.addAction(tr("Collapse All"), this, &GMapDialog::collapseAllWaypoints); - menu.exec(ui_.treeView->mapToGlobal(pt)); - } else if (model_->indexFromItem(rteItem_) == idx) { - QMenu menu(this); - menu.addAction(tr("Show All Routes"), this, &GMapDialog::showAllRoutes); - menu.addAction(tr("Hide All Routes"), this, &GMapDialog::hideAllRoutes); - menu.addAction(tr("Expand All"), this, &GMapDialog::expandAllRoutes); - menu.addAction(tr("Collapse All"), this, &GMapDialog::collapseAllRoutes); - menu.exec(ui_.treeView->mapToGlobal(pt)); - } else if (model_->indexFromItem(trkItem_) == idx) { - QMenu menu(this); - menu.addAction(tr("Show All Tracks"), this, &GMapDialog::showAllTracks); - menu.addAction(tr("Hide All Tracks"), this, &GMapDialog::hideAllTracks); - menu.addAction(tr("Expand All"), this, &GMapDialog::expandAllTracks); - menu.addAction(tr("Collapse All"), this, &GMapDialog::collapseAllTracks); - menu.exec(ui_.treeView->mapToGlobal(pt)); - } else if ((j = waypointIndex(it)) >=0) { - QMenu menu(this); - menu.addAction(tr("Show Only This Waypoint"), this, &GMapDialog::showOnlyThisWaypoint); - menuIndex_ = j; - menu.exec(ui_.treeView->mapToGlobal(pt)); - } else if ((j = trackIndex(it)) >=0) { - QMenu menu(this); - menu.addAction(tr("Show Only This Track"), this, &GMapDialog::showOnlyThisTrack); - menuIndex_ = j; - menu.exec(ui_.treeView->mapToGlobal(pt)); - } else if ((j = routeIndex(it)) >=0) { - QMenu menu(this); - menu.addAction(tr("Show Only This Route"), this, &GMapDialog::showOnlyThisRoute); - menuIndex_ = j; - menu.exec(ui_.treeView->mapToGlobal(pt)); - } else { + if (idx.isValid()) { + QStandardItem* it = model_->itemFromIndex(idx); + if (it == wptItem_) { + const QStringList labels = {tr("Show All Waypoints"), + tr("Hide All Waypoints"), + tr("Expand All"), + tr("Collapse All") + }; + showTopContextMenu(labels, it, pt); + } else if (it == rteItem_) { + const QStringList labels = {tr("Show All Routes"), + tr("Hide All Routes"), + tr("Expand All"), + tr("Collapse All") + }; + showTopContextMenu(labels, it, pt); + } else if (it == trkItem_) { + const QStringList labels = {tr("Show All Tracks"), + tr("Hide All Tracks"), + tr("Expand All"), + tr("Collapse All") + }; + showTopContextMenu(labels, it, pt); + } else if (it != nullptr) { + QStandardItem* parent = it->parent(); + if (parent == wptItem_) { + showChildContextMenu(tr("Show Only This Waypoint"), it, pt); + } else if (parent == trkItem_) { + showChildContextMenu(tr("Show Only This Track"), it, pt); + } else if (parent == rteItem_) { + showChildContextMenu(tr("Show Only This Route"), it, pt); + } + } } } diff --git a/gui/gmapdlg.h b/gui/gmapdlg.h index 43a49d89e..e4dbd1822 100644 --- a/gui/gmapdlg.h +++ b/gui/gmapdlg.h @@ -25,7 +25,6 @@ #include // for QDialog #include // for QItemSelection -#include // for QList #include // for QModelIndex #include // for Q_OBJECT, slots #include // for QPlainTextEdit @@ -42,60 +41,40 @@ class GMapDialog: public QDialog { Q_OBJECT public: - GMapDialog(QWidget* parent, const QString& gpxFileName, QPlainTextEdit* te); + GMapDialog(QWidget* parent, const Gpx& mapData, QPlainTextEdit* te); private: + static constexpr bool debug_ = false; + Ui_GMapDlg ui_; Map* mapWidget_; QStandardItemModel* model_; - QStandardItem* wptItem_, *trkItem_, *rteItem_; - QList wptList_, trkList_, rteList_; - Gpx gpx_; - int menuIndex_; + QStandardItem* wptItem_; + QStandardItem* trkItem_; + QStandardItem* rteItem_; + const Gpx& gpx_; + + static void appendWaypointInfo(QStandardItem* it, const GpxWaypoint& wpt); + static void appendTrackInfo(QStandardItem* it, const GpxTrack& trk); + static void appendRouteInfo(QStandardItem* it, const GpxRoute& rte); - void appendWaypointInfo(QStandardItem* it, const GpxWaypoint& wpt); - void appendTrackInfo(QStandardItem* it, const GpxTrack& trk); - void appendRouteInfo(QStandardItem* it, const GpxRoute& rte); + static QString formatLength(double l); - int waypointIndex(QStandardItem* it); - int trackIndex(QStandardItem* it); - int routeIndex(QStandardItem* it); - QString formatLength(double l); + static void trace(const QString& label, const QStandardItem* it); + void expandCollapseAll(QStandardItem* top, bool exp); + void showHideAll(QStandardItem* top, bool ck); + void showHideChild(const QStandardItem* child); + void showHideChildren(const QStandardItem* top); + void itemClickedX(const QStandardItem* it); + void showOnlyThis(QStandardItem* top, int menuRow); + void showTopContextMenu(const QStringList& text, QStandardItem* top, const QPoint& pt); + void showChildContextMenu(const QString& text, const QStandardItem* child, const QPoint& pt); // private slots: - void itemChangedX(QStandardItem*); - void waypointClickedX(int i); - void trackClickedX(int i); - void routeClickedX(int i); + void itemChangedX(QStandardItem* it); void treeDoubleClicked(const QModelIndex& idx); - void selectionChangedX(const QItemSelection&, const QItemSelection&); - void showContextMenu(const QPoint&); - - - void expandCollapseAll(const QList& li, - QStandardItem* it, bool exp); - void checkUncheckAll(const QList& li, - QStandardItem* it, bool exp); - void expandAllWaypoints(); - void expandAllTracks(); - void expandAllRoutes(); - - void collapseAllWaypoints(); - void collapseAllTracks(); - void collapseAllRoutes(); - - void hideAllWaypoints(); - void hideAllTracks(); - void hideAllRoutes(); - - void showAllWaypoints(); - void showAllTracks(); - void showAllRoutes(); - - void showOnlyThisWaypoint(); - void showOnlyThisTrack(); - void showOnlyThisRoute(); + void selectionChangedX(const QItemSelection& sel, const QItemSelection& desel); + void showContextMenu(const QPoint& pt); }; - #endif diff --git a/gui/gpx.cc b/gui/gpx.cc index ba2ce2c08..f725f253c 100644 --- a/gui/gpx.cc +++ b/gui/gpx.cc @@ -47,30 +47,7 @@ static bool trackIsEmpty(const GpxTrack& trk) class GpxHandler { public: - GpxHandler() - - { - state = e_noop; - } - - enum elementState {e_noop, e_wpt, e_trk, - e_trkpt, e_trkseg, e_rte, e_rtept - }; - QString textChars; - GpxWaypoint currentWpt; - QList wptList; - - QList trkList; - GpxTrack currentTrk; - GpxTrackPoint currentTrkPt; - GpxTrackSegment currentTrkSeg; - - QList rteList; - GpxRoute currentRte; - GpxRoutePoint currentRtePt; - - elementState state; - QList stateStack; + /* Member Functions */ void startElement(QStringView localName, const QXmlStreamAttributes& atts) @@ -204,22 +181,50 @@ class GpxHandler { textChars = x; } + + /* Data Members */ + + QList wptList; + QList trkList; + QList rteList; + +private: + /* Types */ + + enum elementState {e_noop, e_wpt, e_trk, + e_trkpt, e_trkseg, e_rte, e_rtept + }; + + /* Data Memebers */ + + QString textChars; + GpxWaypoint currentWpt; + + GpxTrack currentTrk; + GpxTrackPoint currentTrkPt; + GpxTrackSegment currentTrkSeg; + + GpxRoute currentRte; + GpxRoutePoint currentRtePt; + + elementState state{e_noop}; + QList stateStack; }; //------------------------------------------------------------------------ -bool Gpx::read(const QString& fileName) +QString Gpx::read(const QString& fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { - return false; + return QStringLiteral("Error opening file %1").arg(fileName); } QXmlStreamReader reader(&file); GpxHandler gpxHandler; - for (bool atEnd = false; !reader.atEnd() && !atEnd;) { + for (bool atEnd = false; !reader.atEnd() && !atEnd;) { reader.readNext(); // do processing switch (reader.tokenType()) { @@ -249,8 +254,8 @@ bool Gpx::read(const QString& fileName) wayPoints = gpxHandler.wptList; tracks = gpxHandler.trkList; routes = gpxHandler.rteList; - return true; + return {}; } - return false; + return QStringLiteral("Error parsing map file: %1").arg(reader.errorString()); } diff --git a/gui/gpx.h b/gui/gpx.h index 473cf178b..da6a33412 100644 --- a/gui/gpx.h +++ b/gui/gpx.h @@ -26,39 +26,13 @@ #include // for QDateTime #include // for QList #include // for QString -#include // for QForeachContainer, qMakeForeachContainer, foreach #include "latlng.h" // for LatLng //------------------------------------------------------------------------ -class GpxItem +class GpxRoutePoint { public: - GpxItem(): visible(true) {} - GpxItem(bool visible): visible(visible) {} - - void setVisible(bool b) - { - visible = b; - } - - bool getVisible() const - { - return visible; - } - -protected: - bool visible; -}; - -//------------------------------------------------------------------------ -class GpxRoutePoint: public GpxItem -{ -public: - GpxRoutePoint(): location(LatLng()), name(QString()) - { - } - void setLocation(const LatLng& pt) { location = pt; @@ -85,32 +59,9 @@ class GpxRoutePoint: public GpxItem }; //------------------------------------------------------------------------ -class GpxRoute: public GpxItem +class GpxRoute { public: - GpxRoute(): name(QString()), cachedLength(-1) {} - - GpxRoute(const GpxRoute& c) - :GpxItem(c.visible), - name(c.name), cachedLength(c.cachedLength) - { - routePoints.clear(); - foreach (GpxRoutePoint sg, c.routePoints) { - routePoints << sg; - } - } - GpxRoute& operator = (const GpxRoute& c) - { - visible = c.visible; - name = c.name; - cachedLength = c.cachedLength; - routePoints.clear(); - foreach (GpxRoutePoint sg, c.routePoints) { - routePoints << sg; - } - return *this; - } - double length() const { if (cachedLength >=0.0) { @@ -119,7 +70,7 @@ class GpxRoute: public GpxItem LatLng prevPt; bool first = true; double dist = 0.0; - foreach (GpxRoutePoint pt, routePoints) { + for (const GpxRoutePoint& pt : routePoints) { if (first) { prevPt = pt.getLocation(); first = false; @@ -160,17 +111,13 @@ class GpxRoute: public GpxItem private: QString name; QList routePoints; - double cachedLength; + double cachedLength{-1.0}; }; //------------------------------------------------------------------------ -class GpxTrackPoint: public GpxItem +class GpxTrackPoint { public: - GpxTrackPoint(): location(LatLng()), elevation(0), dateTime(QDateTime()) - { - } - void setLocation(const LatLng& pt) { location = pt; @@ -203,32 +150,14 @@ class GpxTrackPoint: public GpxItem private: LatLng location; - double elevation; + double elevation{0.0}; QDateTime dateTime; }; //------------------------------------------------------------------------ -class GpxTrackSegment: public GpxItem +class GpxTrackSegment { public: - GpxTrackSegment() {} - - GpxTrackSegment(const GpxTrackSegment& c): GpxItem(c.visible) - { - trackPoints.clear(); - foreach (GpxTrackPoint pt, c.trackPoints) { - trackPoints << pt; - } - } - GpxTrackSegment& operator = (const GpxTrackSegment& c) - { - visible = c.visible; - trackPoints.clear(); - foreach (GpxTrackPoint pt, c.trackPoints) { - trackPoints << pt; - } - return *this; - } void addPoint(const GpxTrackPoint& pt) { trackPoints << pt; @@ -247,39 +176,9 @@ class GpxTrackSegment: public GpxItem QList trackPoints; }; //------------------------------------------------------------------------ -class GpxTrack: public GpxItem +class GpxTrack { public: - GpxTrack(): number(1), name(QString()), comment(QString()), description(QString()), cachedLength(-1.0) {} - - GpxTrack(const GpxTrack& c) - :GpxItem(c.visible), - number(c.number), - name(c.name), - comment(c.comment), - description(c.description), - cachedLength(c.cachedLength) - { - trackSegments.clear(); - foreach (GpxTrackSegment sg, c.trackSegments) { - trackSegments << sg; - } - } - GpxTrack& operator = (const GpxTrack& c) - { - visible = c.visible; - number = c.number; - name = c.name; - comment = c.comment; - description = c.description; - cachedLength = c.cachedLength; - trackSegments.clear(); - foreach (GpxTrackSegment sg, c.trackSegments) { - trackSegments << sg; - } - return *this; - } - void setNumber(int n) { number = n; @@ -342,8 +241,8 @@ class GpxTrack: public GpxItem LatLng prevPt; bool first = true; double dist = 0.0; - foreach (GpxTrackSegment seg, trackSegments) { - foreach (GpxTrackPoint pt, seg.getTrackPoints()) { + for (const GpxTrackSegment& seg : trackSegments) { + for (const GpxTrackPoint& pt : seg.getTrackPoints()) { if (first) { prevPt = pt.getLocation(); first = false; @@ -359,27 +258,18 @@ class GpxTrack: public GpxItem } private: - int number; + int number{1}; QString name; QString comment; QString description; QList trackSegments; - double cachedLength; + double cachedLength{-1.0}; }; //------------------------------------------------------------------------ -class GpxWaypoint: public GpxItem +class GpxWaypoint { public: - GpxWaypoint(): - location_(LatLng(0, 0)), - elevation_(-1.0E-100), - name_(QString()), - comment_(QString()), - description_(QString()), - symbol_(QString()) - {} - void setLocation(const LatLng& pt) { location_ = pt; @@ -442,7 +332,7 @@ class GpxWaypoint: public GpxItem private: LatLng location_; - double elevation_; + double elevation_{-1.0E-100}; QString name_; QString comment_; QString description_; @@ -453,44 +343,26 @@ class GpxWaypoint: public GpxItem class Gpx { public: - Gpx() {} - bool read(const QString& fileName); + QString read(const QString& fileName); - QList & getWaypoints() + const QList& getWaypoints() const { return wayPoints; - } // nonconst - - QList & getTracks() - { - return tracks; } - QList & getRoutes() - { - return routes; - } - - const QList & getWaypoints() const - { - return wayPoints; - } - - const QList & getTracks() const + const QList& getTracks() const { return tracks; } - const QList & getRoutes() const + const QList& getRoutes() const { return routes; } private: QList wayPoints; - QList tracks; - QList routes; + QList tracks; + QList routes; }; - - #endif diff --git a/gui/latlng.h b/gui/latlng.h index 44c390108..bfff8718c 100644 --- a/gui/latlng.h +++ b/gui/latlng.h @@ -28,7 +28,7 @@ class LatLng { public: - LatLng(): _lat(0), _lng(0) {} + LatLng() = default; LatLng(double lat, double lng): _lat(lat), _lng(lng) {} double lat() const { @@ -41,8 +41,8 @@ class LatLng double haversineDistance(const LatLng& other) const; private: - double _lat; - double _lng; + double _lat{0.0}; + double _lng{0.0}; }; diff --git a/gui/mainwindow.cc b/gui/mainwindow.cc index 643ca9bcb..0f10d5c77 100644 --- a/gui/mainwindow.cc +++ b/gui/mainwindow.cc @@ -66,6 +66,7 @@ #include "formatload.h" // for FormatLoad #include "gbversion.h" // for VERSION, kVersionDate, kVersionSHA #ifndef DISABLE_MAPPREVIEW +#include "gpx.h" // for Gpx #include "gmapdlg.h" // for GMapDialog #endif #include "help.h" // for ShowHelp @@ -968,12 +969,25 @@ void MainWindow::applyActionX() ui_.outputWindow->appendPlainText(tr("Translation successful")); #ifndef DISABLE_MAPPREVIEW if (babelData_.previewGmap_) { - this->hide(); - GMapDialog dlg(nullptr, tempName, babelData_.debugLevel_ >=1 ? ui_.outputWindow : nullptr); - dlg.show(); - dlg.exec(); + Gpx mapData; + QString mapStatus = mapData.read(tempName); QFile(tempName).remove(); - this->show(); + if (!mapStatus.isNull()) { + QTextCharFormat defaultFormat = ui_.outputWindow->currentCharFormat(); + QTextCharFormat errorFormat = defaultFormat; + errorFormat.setForeground(Qt::red); + errorFormat.setFontItalic(true); + + ui_.outputWindow->setCurrentCharFormat(errorFormat); + ui_.outputWindow->appendPlainText(tr("Error preparing map: %1\n").arg(mapStatus)); + ui_.outputWindow->setCurrentCharFormat(defaultFormat); + } else { + this->hide(); + GMapDialog dlg(nullptr, mapData, babelData_.debugLevel_ >=1 ? ui_.outputWindow : nullptr); + dlg.show(); + dlg.exec(); + this->show(); + } } #endif } else { diff --git a/gui/map.cc b/gui/map.cc index 547a3f571..b70792194 100644 --- a/gui/map.cc +++ b/gui/map.cc @@ -28,6 +28,7 @@ #include // for QFile #include // for QIODevice #include // for QLatin1String +#include // for QList #include // for QMessageBox #include // for QNetworkAccessManager #include // for qMakeStringPrivate, QStringLiteral @@ -37,7 +38,6 @@ #include // for QWebEngineSettings #include // for QWebEngineView #include // for CursorShape -#include // for QForeachContainer, qMakeForeachContainer, foreach #include // for string #include // for vector @@ -53,22 +53,15 @@ using std::vector; //------------------------------------------------------------------------ static QString stripDoubleQuotes(const QString& s) { - QString out; - foreach (QChar c, s) { - if (c != QChar('"')) { - out += c; - } - } - return out; + QString out = s; + return out.remove('"'); } //------------------------------------------------------------------------ Map::Map(QWidget* parent, - const Gpx& gpx, QPlainTextEdit* te): + const Gpx& gpx, QPlainTextEdit* te): QWebEngineView(parent), gpx_(gpx), - mapPresent_(false), - busyCursor_(false), textEdit_(te) { busyCursor_ = true; @@ -90,7 +83,7 @@ Map::Map(QWidget* parent, // 1. In the file system in the same directory as the executable. // 2. In the Qt resource system. This is useful if the resource was compiled // into the executable. - QString baseFile = QApplication::applicationDirPath() + "/gmapbase.html"; + QString baseFile = QApplication::applicationDirPath() + "/gmapbase.html"; QString fileName; QUrl baseUrl; if (QFile(baseFile).exists()) { @@ -193,7 +186,7 @@ void Map::loadFinishedX(bool f) //------------------------------------------------------------------------ static QString fmtLatLng(const LatLng& l) { - return QString("{lat: %1, lng: %3}").arg(l.lat(), 0, 'f', 5) .arg(l.lng(), 0, 'f', 5); + return QString("{lat: %1, lng: %3}").arg(l.lat(), 0, 'f', 5) .arg(l.lng(), 0, 'f', 5); } //------------------------------------------------------------------------ @@ -239,7 +232,7 @@ void Map::showGpxData() // Waypoints. int num=0; - foreach (const GpxWaypoint& pt, gpx_.getWaypoints()) { + for (const GpxWaypoint& pt : gpx_.getWaypoints()) { scriptStr << QString("waypts[%1] = new google.maps.Marker({map: map, position: %2, " "title: \"%3\", icon: blueIcon});") @@ -258,10 +251,10 @@ void Map::showGpxData() // Tracks num = 0; - foreach (const GpxTrack& trk, gpx_.getTracks()) { + for (const GpxTrack& trk : gpx_.getTracks()) { vector pts; - foreach (const GpxTrackSegment seg, trk.getTrackSegments()) { - foreach (const GpxTrackPoint pt, seg.getTrackPoints()) { + for (const GpxTrackSegment& seg : trk.getTrackSegments()) { + for (const GpxTrackPoint& pt : seg.getTrackPoints()) { pts.push_back(pt.getLocation()); } } @@ -287,9 +280,9 @@ void Map::showGpxData() // Routes num = 0; - foreach (const GpxRoute& rte, gpx_.getRoutes()) { + for (const GpxRoute& rte : gpx_.getRoutes()) { vector pts; - foreach (const GpxRoutePoint& pt, rte.getRoutePoints()) { + for (const GpxRoutePoint& pt : rte.getRoutePoints()) { pts.push_back(pt.getLocation()); } QString path = makePath(pts); @@ -333,7 +326,6 @@ void Map::markerClicked(int t, int i) } else if (t == 2) { emit routeClicked(i); } - } //------------------------------------------------------------------------ @@ -346,75 +338,6 @@ void Map::logTime(const QString& s) stopWatch_.start(); } //------------------------------------------------------------------------ -void Map::showTracks(const QList& tracks) -{ - QStringList scriptStr; - int i=0; - foreach (const GpxTrack& trk, tracks) { - scriptStr << QString("trks[%1].%2();").arg(i).arg(trk.getVisible()?"show":"hide"); - i++; - } - evaluateJS(scriptStr); -} - -//------------------------------------------------------------------------ -void Map::hideAllTracks() -{ - QStringList scriptStr; - scriptStr - << "for (idx = 0; idx < trks.length; idx += 1) {" - << " trks[idx].hide();" - << "}" - ; - evaluateJS(scriptStr); -} - -//------------------------------------------------------------------------ -// TACKY: we assume the waypoints list and JS waypts[] are parallel. -void Map::showWaypoints(const QList& waypoints) -{ - QStringList scriptStr; - int i=0; - foreach (const GpxWaypoint& pt, waypoints) { - scriptStr << QString("waypts[%1].setVisible(%2);").arg(i++).arg(pt.getVisible()?"true":"false"); - } - evaluateJS(scriptStr); -} -//------------------------------------------------------------------------ -void Map::hideAllWaypoints() -{ - QStringList scriptStr; - scriptStr - << "for (idx = 0; idx < waypts.length; idx += 1) {" - << " waypts[idx].setVisible(false);" - << "}" - ; - evaluateJS(scriptStr); -} - -//------------------------------------------------------------------------ -void Map::showRoutes(const QList& routes) -{ - QStringList scriptStr; - int i=0; - foreach (const GpxRoute& rt, routes) { - scriptStr << QString("rtes[%1].%2();").arg(i).arg(rt.getVisible()?"show":"hide"); - i++; - } - evaluateJS(scriptStr); -} -//------------------------------------------------------------------------ -void Map::hideAllRoutes() -{ - QStringList scriptStr; - scriptStr - << "for (idx = 0; idx < rtes.length; idx += 1) {" - << " rtes[idx].hide();" - << "}" - ; - evaluateJS(scriptStr); -} -//------------------------------------------------------------------------ void Map::setWaypointVisibility(int i, bool show) { evaluateJS(QString("waypts[%1].setVisible(%2);") @@ -433,6 +356,15 @@ void Map::setRouteVisibility(int i, bool show) evaluateJS(QString("rtes[%1].%2();").arg(i).arg(show?"show": "hide")); } +//------------------------------------------------------------------------ +void Map::resetBounds() +{ + evaluateJS(QStringList{ + "map.setCenter(bounds.getCenter());", + "map.fitBounds(bounds);", + }); +} + //------------------------------------------------------------------------ void Map::panTo(const LatLng& loc) { @@ -463,29 +395,21 @@ void Map::setWaypointColorBlue(int i) //------------------------------------------------------------------------ void Map::frameTrack(int i) { - QStringList scriptStr; - - scriptStr - << QString("map.setCenter(trks[%1].getBounds().getCenter());").arg(i) - << QString("map.fitBounds(trks[%1].getBounds());").arg(i) - - ; - evaluateJS(scriptStr); + evaluateJS(QStringList{ + QString("map.setCenter(trks[%1].getBounds().getCenter());").arg(i), + QString("map.fitBounds(trks[%1].getBounds());").arg(i), + }); } - //------------------------------------------------------------------------ void Map::frameRoute(int i) { - QStringList scriptStr; - scriptStr - << QString("map.setCenter(rtes[%1].getBounds().getCenter());").arg(i) - << QString("map.fitBounds(rtes[%1].getBounds());").arg(i) - ; - evaluateJS(scriptStr); + evaluateJS(QStringList{ + QString("map.setCenter(rtes[%1].getBounds().getCenter());").arg(i), + QString("map.fitBounds(rtes[%1].getBounds());").arg(i), + }); } - //------------------------------------------------------------------------ void Map::evaluateJS(const QString& s, bool upd) { diff --git a/gui/map.h b/gui/map.h index bf1d7b19f..26aa9a7f8 100644 --- a/gui/map.h +++ b/gui/map.h @@ -25,7 +25,6 @@ #include // for QByteArray #include // for QElapsedTimer -#include // for QList #include // for QNetworkAccessManager #include // for QObject, emit, Q_OBJECT, signals, slots #include // for QPlainTextEdit @@ -70,43 +69,33 @@ public slots: }; - class Map : public QWebEngineView { Q_OBJECT public: Map(QWidget* parent, - const Gpx& gpx_, QPlainTextEdit* textEdit_); + const Gpx& gpx_, QPlainTextEdit* textEdit_); ~Map(); -public slots: void showGpxData(); - - void showTracks(const QList& tracks); - void hideAllTracks(); void setTrackVisibility(int i, bool show); - - void showWaypoints(const QList& waypoints); - void hideAllWaypoints(); void setWaypointVisibility(int i, bool show); - - void showRoutes(const QList& routes); - void hideAllRoutes(); void setRouteVisibility(int i, bool show); - - void loadFinishedX(bool); - void markerClicked(int t, int i); + void resetBounds(); void panTo(const LatLng& loc); void setWaypointColorRed(int i); void setWaypointColorBlue(int i); void frameTrack(int i); void frameRoute(int i); - void logTime(const QString&); +public slots: + void loadFinishedX(bool f); + void markerClicked(int t, int i); + void logTime(const QString& s); private: - QByteArray encodeKey(const QByteArray& key); - QByteArray decodeKey(const QByteArray& key); + static QByteArray encodeKey(const QByteArray& key); + static QByteArray decodeKey(const QByteArray& key); signals: void waypointClicked(int i); @@ -115,24 +104,20 @@ public slots: private: #ifdef DEBUG_JS_GENERATION - QFile* dbgdata_; - QTextStream* dbgout_; + QFile* dbgdata_{nullptr}; + QTextStream* dbgout_{nullptr}; #endif - QNetworkAccessManager* manager_; + QNetworkAccessManager* manager_{nullptr}; const Gpx& gpx_; - bool mapPresent_; - bool busyCursor_; + bool mapPresent_{false}; + bool busyCursor_{false}; QElapsedTimer stopWatch_; - QPlainTextEdit* textEdit_; + QPlainTextEdit* textEdit_{nullptr}; void evaluateJS(const QString& s, bool update = true); void evaluateJS(const QStringList& s, bool update = true); - protected: void resizeEvent(QResizeEvent* event) override; - }; - - #endif // HEADER_H