Marble

EditBookmarkDialog.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2010 Gaurav Gupta <1989.gaurav@googlemail.com>
4// SPDX-FileCopyrightText: 2011 Friedrich W. H. Kossebau <kossebau@kde.org>
5// SPDX-FileCopyrightText: 2012 Thibaut Gridel <tgridel@free.fr>
6//
7
8#include "EditBookmarkDialog.h"
9#include "ui_EditBookmarkDialog.h"
10
11#include "BookmarkManager.h"
12#include "GeoDataCoordinates.h"
13#include "GeoDataData.h"
14#include "GeoDataDocument.h"
15#include "GeoDataExtendedData.h"
16#include "GeoDataFolder.h"
17#include "GeoDataIconStyle.h"
18#include "GeoDataLookAt.h"
19#include "GeoDataPlacemark.h"
20#include "GeoDataPoint.h"
21#include "GeoDataStyle.h"
22#include "MarbleDirs.h"
23#include "MarbleModel.h"
24#include "MarbleWidget.h"
25#include "NewBookmarkFolderDialog.h"
26#include "ReverseGeocodingRunnerManager.h"
27
28#include <QPointer>
29
30namespace Marble
31{
32
33class EditBookmarkDialogPrivate
34{
35public:
36 MarbleWidget *m_widget;
37 ReverseGeocodingRunnerManager *m_manager;
38 BookmarkManager *m_bookmarkManager;
39 GeoDataCoordinates m_bookmarkCoordinates;
40 qreal m_range;
41 Ui::UiEditBookmarkDialog m_ui;
42
43 EditBookmarkDialogPrivate(EditBookmarkDialog *q, BookmarkManager *bookmarkManager);
44
45 void initComboBox(const GeoDataContainer *const container, int level = 0);
46
47 void initialize();
48
49 void setFolderName(const QString &name);
50
51 static QString append(const QString &bookmark, const QString &text);
52
53 void openNewFolderDialog();
54
55 void retrieveGeocodeResult(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark);
56
57 void updateCoordinates();
58
59private:
60 EditBookmarkDialog *const q;
61};
62
63EditBookmarkDialogPrivate::EditBookmarkDialogPrivate(EditBookmarkDialog *q_, BookmarkManager *bookmarkManager)
64 : m_widget(nullptr)
65 , m_manager(nullptr)
66 , m_bookmarkManager(bookmarkManager)
67 , m_range(0)
68 , q(q_)
69{
70 // nothing to do
71}
72
73void EditBookmarkDialogPrivate::initialize()
74{
75 m_ui.setupUi(q);
76 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
77 m_ui.m_header->setPositionVisible(!smallScreen);
78 m_ui.m_header->setIdVisible(false);
79 m_ui.m_header->setIconLink(MarbleDirs::path(QStringLiteral("bitmaps/bookmark.png")));
80 QObject::connect(m_ui.m_newFolderButton, SIGNAL(clicked()), q, SLOT(openNewFolderDialog()));
81 QObject::connect(m_ui.m_header, SIGNAL(valueChanged()), q, SLOT(updateCoordinates()));
82
83 m_ui.m_folders->clear();
84 initComboBox(m_bookmarkManager->document());
85}
86
87void EditBookmarkDialogPrivate::initComboBox(const GeoDataContainer *const container, int level)
88{
89 m_bookmarkManager->ensureDefaultFolder();
90 for (GeoDataFolder *folder : container->folderList()) {
91 QVariant folderVariant;
92 folderVariant.setValue(folder);
93 QString name = QStringLiteral(" ").repeated(4 * level) + folder->name();
94 m_ui.m_folders->addItem(name, folderVariant);
95 if (!folder->folderList().isEmpty()) {
96 initComboBox(folder, level + 1);
97 }
98 }
99}
100
101void EditBookmarkDialogPrivate::setFolderName(const QString &name)
102{
103 for (int i = 0; i < m_ui.m_folders->count(); ++i) {
104 if (m_ui.m_folders->itemText(i) == name) {
105 m_ui.m_folders->setCurrentIndex(i);
106 return;
107 }
108 }
109}
110
111EditBookmarkDialog::EditBookmarkDialog(BookmarkManager *bookmarkManager, QWidget *parent)
112 : QDialog(parent)
113 , d(new EditBookmarkDialogPrivate(this, bookmarkManager))
114{
115 d->initialize();
116}
117
118void EditBookmarkDialog::setCoordinates(const GeoDataCoordinates &coordinates)
119{
120 d->m_bookmarkCoordinates = coordinates;
121 QObject::disconnect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
122
123 if (d->m_ui.m_header->name().isEmpty()) {
124 d->m_ui.m_header->setName(coordinates.toString());
125 }
126
127 d->m_ui.m_header->setLongitude(coordinates.longitude(GeoDataCoordinates::Degree));
128 d->m_ui.m_header->setLatitude(coordinates.latitude(GeoDataCoordinates::Degree));
129 QObject::connect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
130}
131
132void EditBookmarkDialog::setRange(qreal range)
133{
134 d->m_range = range;
135}
136
137void EditBookmarkDialog::setName(const QString &text)
138{
139 QObject::disconnect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
140 d->m_ui.m_header->setName(text);
141 d->m_ui.m_header->selectAll();
142 QObject::connect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
143}
144
145void EditBookmarkDialog::setDescription(const QString &text)
146{
147 QObject::disconnect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
148 d->m_ui.m_description->setText(text);
149 QObject::connect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
150}
151
152void EditBookmarkDialog::setFolderName(const QString &name)
153{
154 d->setFolderName(name);
155}
156
157void EditBookmarkDialog::setIconLink(const QString &iconLink)
158{
159 QObject::disconnect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
160 d->m_ui.m_header->setIconLink(iconLink);
161 QObject::connect(d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()));
162}
163
164void EditBookmarkDialog::setMarbleWidget(MarbleWidget *widget)
165{
166 d->m_widget = widget;
167 const AngleUnit defaultAngleUnit = d->m_widget->defaultAngleUnit();
168 const GeoDataCoordinates::Notation notation = (defaultAngleUnit == DecimalDegree) ? GeoDataCoordinates::Decimal
169 : (defaultAngleUnit == DMSDegree) ? GeoDataCoordinates::DMS
170 :
171 /* else, UTM */ GeoDataCoordinates::UTM;
172 d->m_ui.m_header->setNotation(notation);
173
174 d->m_manager = new ReverseGeocodingRunnerManager(d->m_widget->model(), this);
175 QObject::connect(d->m_manager,
176 SIGNAL(reverseGeocodingFinished(GeoDataCoordinates, GeoDataPlacemark)),
177 this,
178 SLOT(retrieveGeocodeResult(GeoDataCoordinates, GeoDataPlacemark)));
179}
180
181void EditBookmarkDialog::setReverseGeocodeName()
182{
183 if (!d->m_manager) {
184 return;
185 }
186 // reverse geocode the bookmark point for better user experience
187 d->m_manager->reverseGeocoding(d->m_bookmarkCoordinates);
188}
189
190EditBookmarkDialog::~EditBookmarkDialog()
191{
192 delete d;
193}
194
195void EditBookmarkDialogPrivate::retrieveGeocodeResult(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark)
196{
197 Q_UNUSED(coordinates)
198 GeoDataExtendedData data = placemark.extendedData();
199 QString bookmarkName;
200 qreal distance = m_widget->distance() * KM2METER;
201 // FIXME : Optimal logic for suggestion with distance consideration is required
202
203 if (distance >= 3500) {
204 bookmarkName = data.value(QStringLiteral("country")).value().toString();
205 } else if (distance >= 200) {
206 bookmarkName = append(data.value(QStringLiteral("city")).value().toString(), data.value(QStringLiteral("state")).value().toString());
207 bookmarkName = append(bookmarkName, data.value(QStringLiteral("country")).value().toString());
208 } else {
209 bookmarkName = append(data.value(QStringLiteral("road")).value().toString(), data.value(QStringLiteral("city")).value().toString());
210 bookmarkName = append(bookmarkName, data.value(QStringLiteral("country")).value().toString());
211 }
212
213 if (bookmarkName.isEmpty()) {
214 bookmarkName = placemark.address();
215 }
216
217 m_ui.m_header->setName(bookmarkName);
218 m_ui.m_header->selectAll();
219}
220
221QString EditBookmarkDialogPrivate::append(const QString &bookmark, const QString &text)
222{
223 if (bookmark.isEmpty() && text.isEmpty()) {
224 return QString();
225 } else if (bookmark.isEmpty()) {
226 return text;
227 } else if (text.isEmpty()) {
228 return bookmark;
229 }
230 return bookmark + QStringLiteral(", ") + text;
231}
232
233void EditBookmarkDialogPrivate::openNewFolderDialog()
234{
235 QPointer<NewBookmarkFolderDialog> dialog = new NewBookmarkFolderDialog(q);
236 if (dialog->exec() == QDialog::Accepted) {
237 m_bookmarkManager->addNewBookmarkFolder(m_bookmarkManager->document(), dialog->folderName());
238 m_ui.m_folders->clear();
239 initComboBox(m_bookmarkManager->document());
240 setFolderName(dialog->folderName());
241 }
242 delete dialog;
243}
244
245void EditBookmarkDialogPrivate::updateCoordinates()
246{
247 m_bookmarkCoordinates.setLongitude(m_ui.m_header->longitude(), GeoDataCoordinates::Degree);
248 m_bookmarkCoordinates.setLatitude(m_ui.m_header->latitude(), GeoDataCoordinates::Degree);
249}
250
251GeoDataPlacemark EditBookmarkDialog::bookmark() const
252{
253 // Create a bookmark object
254 GeoDataPlacemark bookmark;
255 bookmark.setName(name());
256 bookmark.setDescription(description());
257 GeoDataStyle::Ptr newStyle(new GeoDataStyle(*bookmark.style()));
258 newStyle->iconStyle().setIconPath(iconLink());
259 bookmark.setStyle(newStyle);
260 // allow for HTML in the description
261 bookmark.setDescriptionCDATA(true);
262 bookmark.setCoordinate(coordinates());
263 if (d->m_range) {
264 auto lookat = new GeoDataLookAt;
265 lookat->setCoordinates(coordinates());
266 lookat->setRange(range());
267 bookmark.setAbstractView(lookat);
268 }
269
270 bookmark.extendedData().addValue(GeoDataData(QStringLiteral("isBookmark"), true));
271
272 if (d->m_widget != nullptr) {
273 const QString celestialName = d->m_widget->model()->planetId();
274 if (celestialName != QLatin1StringView("earth")) {
275 bookmark.extendedData().addValue(GeoDataData(QStringLiteral("celestialBody"), celestialName));
276 }
277 }
278
279 return bookmark;
280}
281
282QString EditBookmarkDialog::name() const
283{
284 return d->m_ui.m_header->name();
285}
286
287GeoDataFolder *EditBookmarkDialog::folder() const
288{
289 return qvariant_cast<GeoDataFolder *>(d->m_ui.m_folders->itemData(d->m_ui.m_folders->currentIndex()));
290}
291
292QString EditBookmarkDialog::description() const
293{
294 return d->m_ui.m_description->toPlainText();
295}
296
297GeoDataCoordinates EditBookmarkDialog::coordinates() const
298{
299 return d->m_bookmarkCoordinates;
300}
301
302qreal EditBookmarkDialog::range() const
303{
304 return d->m_range;
305}
306
307QString EditBookmarkDialog::iconLink() const
308{
309 return d->m_ui.m_header->iconLink();
310}
311
312}
313
314#include "moc_EditBookmarkDialog.cpp"
This file contains the headers for MarbleModel.
This file contains the headers for MarbleWidget.
char * toString(const EngineQuery &query)
QString name(GameStandardAction id)
Binds a QML item to a specific geodetic location in screen coordinates.
AngleUnit
This enum is used to choose the unit chosen to measure angles.
@ UTM
UTM.
@ DMSDegree
Degrees in DMS notation.
@ DecimalDegree
Degrees in decimal notation.
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
bool isEmpty() const const
QString repeated(qsizetype times) const const
void setValue(QVariant &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:43 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.