File indexing completed on 2024-04-28 15:39:05
0001 // SPDX-FileCopyrightText: 2020-2022 Tobias Leupold <tl at stonemx dot de> 0002 // 0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 // Local includes 0006 #include "BookmarksList.h" 0007 #include "SharedObjects.h" 0008 #include "Settings.h" 0009 #include "MapWidget.h" 0010 #include "CoordinatesDialog.h" 0011 0012 // KDE includes 0013 #include <KLocalizedString> 0014 0015 // Qt includes 0016 #include <QDebug> 0017 #include <QMenu> 0018 #include <QInputDialog> 0019 #include <QMessageBox> 0020 #include <QListWidgetItem> 0021 #include <QApplication> 0022 0023 BookmarksList::BookmarksList(SharedObjects *sharedObjects, QWidget *parent) 0024 : QListWidget(parent), 0025 m_settings(sharedObjects->settings()), 0026 m_elevationEngine(sharedObjects->elevationEngine()), 0027 m_mapWidget(sharedObjects->mapWidget()) 0028 { 0029 setSortingEnabled(true); 0030 0031 // Load the saved bookmarks 0032 m_bookmarks = m_settings->bookmarks(); 0033 const auto labels = m_bookmarks.keys(); 0034 for (const auto &label : labels) { 0035 auto *item = new QListWidgetItem(label); 0036 addItem(item); 0037 } 0038 0039 // Show the first bookmark's coordinates if we have bookmarks 0040 if (! m_bookmarks.isEmpty()) { 0041 setCurrentItem(0); 0042 } 0043 0044 connect(this, &QListWidget::itemClicked, this, &BookmarksList::centerBookmark); 0045 connect(this, &QListWidget::currentItemChanged, this, &BookmarksList::itemHighlighted); 0046 0047 connect(m_elevationEngine, &ElevationEngine::elevationProcessed, 0048 this, &BookmarksList::elevationProcessed); 0049 connect(m_elevationEngine, &ElevationEngine::lookupFailed, 0050 this, &BookmarksList::restoreAfterElevationLookup); 0051 0052 // Context menu 0053 0054 m_contextMenu = new QMenu(this); 0055 0056 auto *newBookmarkAction = m_contextMenu->addAction(i18n("Add new bookmark for current map " 0057 "center")); 0058 connect(newBookmarkAction, &QAction::triggered, this, &BookmarksList::newBookmark); 0059 0060 auto *newManualBookmarkAction = m_contextMenu->addAction(i18n("Add new manual bookmark")); 0061 connect(newManualBookmarkAction, &QAction::triggered, this, &BookmarksList::newManualBookmark); 0062 0063 m_contextMenu->addSeparator(); 0064 0065 m_renameBookmark = m_contextMenu->addAction(i18n("Rename bookmark")); 0066 connect(m_renameBookmark, &QAction::triggered, this, &BookmarksList::renameBookmark); 0067 0068 m_editCoordinates = m_contextMenu->addAction(i18n("Edit coordinates")); 0069 connect(m_editCoordinates, &QAction::triggered, this, &BookmarksList::editCoordinates); 0070 0071 m_contextMenu->addSeparator(); 0072 0073 m_lookupElevation = m_contextMenu->addAction(i18n("Lookup elevation")); 0074 connect(m_lookupElevation, &QAction::triggered, this, &BookmarksList::lookupElevation); 0075 0076 m_setElevation = m_contextMenu->addAction(i18n("Set elevation manually")); 0077 connect(m_setElevation, &QAction::triggered, this, &BookmarksList::setElevation); 0078 0079 m_contextMenu->addSeparator(); 0080 0081 m_deleteBookmark = m_contextMenu->addAction(i18n("Delete bookmark")); 0082 connect(m_deleteBookmark, &QAction::triggered, this, &BookmarksList::deleteBookmark); 0083 0084 setContextMenuPolicy(Qt::CustomContextMenu); 0085 connect(this, &QWidget::customContextMenuRequested, this, &BookmarksList::showContextMenu); 0086 } 0087 0088 void BookmarksList::showContextMenu(const QPoint &point) 0089 { 0090 m_contextMenuItem = itemAt(point); 0091 0092 const bool itemSelected = m_contextMenuItem != nullptr; 0093 m_renameBookmark->setEnabled(itemSelected); 0094 m_lookupElevation->setEnabled(itemSelected); 0095 m_setElevation->setEnabled(itemSelected); 0096 m_deleteBookmark->setEnabled(itemSelected); 0097 m_editCoordinates->setEnabled(itemSelected); 0098 0099 m_contextMenu->exec(mapToGlobal(point)); 0100 } 0101 0102 void BookmarksList::newBookmark() 0103 { 0104 auto [ label, okay ] = getString(i18n("New Bookmark"), i18n("Label for the new bookmark:")); 0105 if (! okay) { 0106 return; 0107 } 0108 0109 label = label.simplified(); 0110 const auto originalLabel = label; 0111 if (label.isEmpty()) { 0112 label = i18n("Untitled"); 0113 } 0114 0115 saveBookmark(label, m_mapWidget->currentCenter()); 0116 } 0117 0118 void BookmarksList::newManualBookmark() 0119 { 0120 CoordinatesDialog dialog(CoordinatesDialog::Mode::ManualBookmark, 0121 m_settings->lookupElevationAutomatically()); 0122 if (! dialog.exec()) { 0123 return; 0124 } 0125 0126 saveBookmark(dialog.label(), 0127 Coordinates(dialog.lon(), dialog.lat(), dialog.alt(), true)); 0128 } 0129 0130 void BookmarksList::saveBookmark(QString label, const Coordinates &coordinates) 0131 { 0132 const QString originalLabel = label; 0133 QString searchLabel = label; 0134 int addition = 0; 0135 while (! findItems(searchLabel, Qt::MatchExactly).isEmpty()) { 0136 addition++; 0137 searchLabel = i18nc("Adding a consecutive number to a bookmark label to make it unique", 0138 "%1 (%2)", label, addition); 0139 } 0140 label = searchLabel; 0141 0142 m_bookmarks[label] = coordinates; 0143 0144 auto *item = new QListWidgetItem(label); 0145 addItem(item); 0146 setCurrentItem(item); 0147 0148 if (m_settings->lookupElevationAutomatically()) { 0149 requestElevation(label); 0150 } 0151 0152 Q_EMIT bookmarksChanged(); 0153 0154 if (label != originalLabel) { 0155 QMessageBox::warning(this, i18n("Add new bookmark"), 0156 i18n("The bookmark \"%1\" already exists, created \"%2\" instead.", 0157 originalLabel, label)); 0158 } 0159 0160 m_mapWidget->centerCoordinates(coordinates); 0161 } 0162 0163 void BookmarksList::requestElevation(const QString &id) 0164 { 0165 QApplication::setOverrideCursor(Qt::WaitCursor); 0166 setEnabled(false); 0167 m_elevationEngine->request(ElevationEngine::Target::Bookmark, { id }, 0168 { m_bookmarks.value(id) }); 0169 } 0170 0171 void BookmarksList::itemHighlighted(QListWidgetItem *item, QListWidgetItem *) 0172 { 0173 if (item == nullptr) { 0174 Q_EMIT showInfo(Coordinates()); 0175 return; 0176 } 0177 0178 Q_EMIT showInfo(m_bookmarks.value(item->text())); 0179 } 0180 0181 void BookmarksList::centerBookmark(QListWidgetItem *item) 0182 { 0183 m_mapWidget->centerCoordinates(m_bookmarks.value(item->text())); 0184 } 0185 0186 BookmarksList::EnteredString BookmarksList::getString(const QString &title, const QString &label, 0187 const QString &text) 0188 { 0189 bool okay = false; 0190 auto string = QInputDialog::getText(this, title, label, QLineEdit::Normal, text, &okay); 0191 return { string, okay }; 0192 } 0193 0194 void BookmarksList::renameBookmark() 0195 { 0196 const auto currentLabel = m_contextMenuItem->text(); 0197 auto [ newLabel, okay ] = getString(i18n("Rename Bookmark"), 0198 i18n("New label for the new bookmark:"), currentLabel); 0199 if (! okay || newLabel == currentLabel) { 0200 return; 0201 } 0202 0203 newLabel = newLabel.simplified(); 0204 if (! findItems(newLabel, Qt::MatchExactly).isEmpty()) { 0205 QMessageBox::warning(this, i18n("Rename Bookmark"), 0206 i18n("The label \"%1\" is already in use. Please choose another " 0207 "name.", newLabel)); 0208 return; 0209 } 0210 0211 m_bookmarks[newLabel] = m_bookmarks.value(currentLabel); 0212 m_bookmarks.remove(currentLabel); 0213 m_contextMenuItem->setText(newLabel); 0214 0215 Q_EMIT bookmarksChanged(); 0216 } 0217 0218 void BookmarksList::deleteBookmark() 0219 { 0220 if (QMessageBox::question(this, i18n("Delete bookmark"), 0221 i18n("Really delete bookmark \"%1\"?", m_contextMenuItem->text()), 0222 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) { 0223 0224 return; 0225 } 0226 0227 m_bookmarks.remove(m_contextMenuItem->text()); 0228 const auto *item = takeItem(row(m_contextMenuItem)); 0229 delete item; 0230 0231 Q_EMIT bookmarksChanged(); 0232 } 0233 0234 void BookmarksList::elevationProcessed(ElevationEngine::Target target, const QVector<QString> &ids, 0235 const QVector<double> &elevations) 0236 { 0237 if (target != ElevationEngine::Target::Bookmark) { 0238 return; 0239 } 0240 0241 restoreAfterElevationLookup(); 0242 const auto id = ids.at(0); 0243 m_bookmarks[id].setAlt(elevations.at(0)); 0244 Q_EMIT showInfo(m_bookmarks.value(id)); 0245 } 0246 0247 void BookmarksList::restoreAfterElevationLookup() 0248 { 0249 if (! isEnabled()) { 0250 QApplication::restoreOverrideCursor(); 0251 setEnabled(true); 0252 } 0253 } 0254 0255 void BookmarksList::lookupElevation() 0256 { 0257 requestElevation(m_contextMenuItem->text()); 0258 } 0259 0260 void BookmarksList::setElevation() 0261 { 0262 const auto id = m_contextMenuItem->text(); 0263 0264 bool okay = false; 0265 auto elevation = QInputDialog::getDouble(this, i18n("Set elevation"), 0266 i18n("Elevation for \"%1\" (m)", id), 0267 m_bookmarks.value(id).alt(), KGeoTag::minimalAltitude, 0268 KGeoTag::maximalAltitude, 1, &okay); 0269 if (! okay) { 0270 return; 0271 } 0272 0273 elevationProcessed(ElevationEngine::Target::Bookmark, { id }, { elevation }); 0274 } 0275 0276 const QHash<QString, Coordinates> *BookmarksList::bookmarks() const 0277 { 0278 return &m_bookmarks; 0279 } 0280 0281 void BookmarksList::editCoordinates() 0282 { 0283 const auto id = m_contextMenuItem->text(); 0284 auto &coordinates = m_bookmarks[id]; 0285 0286 CoordinatesDialog dialog(CoordinatesDialog::Mode::EditCoordinates, false, coordinates, 0287 i18nc("A quoted bookmark label", "\"%1\"", id)); 0288 if (! dialog.exec()) { 0289 return; 0290 } 0291 0292 coordinates = dialog.coordinates(); 0293 m_mapWidget->centerCoordinates(coordinates); 0294 Q_EMIT showInfo(coordinates); 0295 }