Marble

GeoDataFeature.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2007 Murad Tagirov <tmurad@gmail.com>
4// SPDX-FileCopyrightText: 2009 Patrick Spendrin <ps_ml@gmx.de>
5//
6
7#include "GeoDataFeature.h"
8#include "GeoDataFeature_p.h"
9
10#include <QDataStream>
11#include <QSize>
12
13#include "MarbleDebug.h"
14#include "MarbleDirs.h"
15
16#include "GeoDataStyle.h"
17#include "GeoDataStyleMap.h"
18
19#include "GeoDataCamera.h"
20#include "GeoDataContainer.h"
21#include "GeoDataDocument.h"
22#include "GeoDataFolder.h"
23#include "GeoDataGroundOverlay.h"
24#include "GeoDataNetworkLink.h"
25#include "GeoDataNetworkLinkControl.h"
26#include "GeoDataPhotoOverlay.h"
27#include "GeoDataPlacemark.h"
28#include "GeoDataRegion.h"
29#include "GeoDataScreenOverlay.h"
30#include "GeoDataTour.h"
31
32namespace Marble
33{
34
35GeoDataFeature::GeoDataFeature()
36 : d_ptr(new GeoDataFeaturePrivate())
37{
38}
39
40GeoDataFeature::GeoDataFeature(const GeoDataFeature &other)
41 : GeoDataObject()
42 , d_ptr(new GeoDataFeaturePrivate(*other.d_ptr))
43{
44}
45
46GeoDataFeature::GeoDataFeature(const QString &name)
47 : d_ptr(new GeoDataFeaturePrivate())
48{
49 d_ptr->m_name = name;
50}
51
52GeoDataFeature::GeoDataFeature(GeoDataFeaturePrivate *dd)
54 , d_ptr(dd)
55{
56}
57
58GeoDataFeature::GeoDataFeature(const GeoDataFeature &other, GeoDataFeaturePrivate *dd)
59 : GeoDataObject()
60 , d_ptr(dd)
61{
62 Q_UNUSED(other);
63 // TODO: some classes pass "other" on and thus get duplicated id, also in operator=. Align behaviour
64}
65
66GeoDataFeature::~GeoDataFeature()
67{
68 delete d_ptr;
69}
70
71GeoDataFeature &GeoDataFeature::operator=(const GeoDataFeature &other)
72{
73 if (this != &other) {
74 *d_ptr = *other.d_ptr;
75 }
76
77 return *this;
78}
79
80bool GeoDataFeature::operator==(const GeoDataFeature &other) const
81{
82 if (nodeType() != other.nodeType()) {
83 return false;
84 }
85
86 if (nodeType() == GeoDataTypes::GeoDataDocumentType) {
87 const auto &thisDoc = static_cast<const GeoDataDocument &>(*this);
88 const auto &otherDoc = static_cast<const GeoDataDocument &>(other);
89
90 return thisDoc == otherDoc;
91 } else if (nodeType() == GeoDataTypes::GeoDataFolderType) {
92 const auto &thisFolder = static_cast<const GeoDataFolder &>(*this);
93 const auto &otherFolder = static_cast<const GeoDataFolder &>(other);
94
95 return thisFolder == otherFolder;
96 } else if (nodeType() == GeoDataTypes::GeoDataGroundOverlayType) {
97 const auto &thisGO = static_cast<const GeoDataGroundOverlay &>(*this);
98 const auto &otherGO = static_cast<const GeoDataGroundOverlay &>(other);
99
100 return thisGO == otherGO;
101 } else if (nodeType() == GeoDataTypes::GeoDataNetworkLinkType) {
102 const auto &thisNetLink = static_cast<const GeoDataNetworkLink &>(*this);
103 const auto &otherNetLink = static_cast<const GeoDataNetworkLink &>(other);
104
105 return thisNetLink == otherNetLink;
106 } else if (nodeType() == GeoDataTypes::GeoDataNetworkLinkControlType) {
107 const auto &thisNLC = static_cast<const GeoDataNetworkLinkControl &>(*this);
108 const auto &otherNLC = static_cast<const GeoDataNetworkLinkControl &>(other);
109
110 return thisNLC == otherNLC;
111 } else if (nodeType() == GeoDataTypes::GeoDataPhotoOverlayType) {
112 const auto &thisPO = static_cast<const GeoDataPhotoOverlay &>(*this);
113 const auto &otherPO = static_cast<const GeoDataPhotoOverlay &>(other);
114
115 return thisPO == otherPO;
116 } else if (nodeType() == GeoDataTypes::GeoDataPlacemarkType) {
117 const auto &thisPM = static_cast<const GeoDataPlacemark &>(*this);
118 const auto &otherPM = static_cast<const GeoDataPlacemark &>(other);
119
120 return thisPM == otherPM;
121 } else if (nodeType() == GeoDataTypes::GeoDataScreenOverlayType) {
122 const auto &thisSO = static_cast<const GeoDataScreenOverlay &>(*this);
123 const auto &otherSO = static_cast<const GeoDataScreenOverlay &>(other);
124
125 return thisSO == otherSO;
126 } else if (nodeType() == GeoDataTypes::GeoDataTourType) {
127 const auto &thisTour = static_cast<const GeoDataTour &>(*this);
128 const auto &otherTour = static_cast<const GeoDataTour &>(other);
129
130 return thisTour == otherTour;
131 }
132
133 return false;
134}
135
136bool GeoDataFeature::equals(const GeoDataFeature &other) const
137{
138 Q_D(const GeoDataFeature);
139 const GeoDataFeaturePrivate *const other_d = other.d_func();
140
141 if (!GeoDataObject::equals(other) || d->m_name != other_d->m_name || d->m_styleUrl != other_d->m_styleUrl || d->m_popularity != other_d->m_popularity
142 || d->m_zoomLevel != other_d->m_zoomLevel || d->m_visible != other_d->m_visible || d->m_role != other_d->m_role
143 || d->m_extendedData != other_d->m_extendedData || *style() != *other.style()) {
144 return false;
145 }
146
147 if ((!d->m_styleMap && other_d->m_styleMap) || (d->m_styleMap && !other_d->m_styleMap)) {
148 return false;
149 }
150
151 if ((d->m_styleMap && other_d->m_styleMap) && (*d->m_styleMap != *other_d->m_styleMap)) {
152 return false;
153 }
154
155 if ((!d->m_featureExtendedData && other_d->m_featureExtendedData && other_d->m_featureExtendedData->m_abstractView)
156 || (d->m_featureExtendedData && d->m_featureExtendedData->m_abstractView && !other_d->m_featureExtendedData)) {
157 return false;
158 }
159
160 if ((d->m_featureExtendedData && other_d->m_featureExtendedData) && (*d->m_featureExtendedData != *other_d->m_featureExtendedData)) {
161 return false;
162 }
163
164 return true;
165}
166
167EnumFeatureId GeoDataFeature::featureId() const
168{
169 Q_D(const GeoDataFeature);
170 return d->featureId();
171}
172
174{
175 Q_D(const GeoDataFeature);
176 return d->m_name;
177}
178
180{
182 d->m_name = value;
183}
184
185GeoDataSnippet GeoDataFeature::snippet() const
186{
187 Q_D(const GeoDataFeature);
188 return d->featureExtendedData().m_snippet;
189}
190
191void GeoDataFeature::setSnippet(const GeoDataSnippet &snippet)
192{
194 d->featureExtendedData().m_snippet = snippet;
195}
196
198{
199 Q_D(const GeoDataFeature);
200 if (!d->m_featureExtendedData) {
201 return {};
202 }
203
204 return d->featureExtendedData().m_address;
205}
206
208{
210 if (value.isEmpty() && !d->m_featureExtendedData) {
211 return; // nothing to change
212 }
213
214 d->featureExtendedData().m_address = value;
215}
216
218{
219 Q_D(const GeoDataFeature);
220 if (!d->m_featureExtendedData) {
221 return {};
222 }
223
224 return d->featureExtendedData().m_phoneNumber;
225}
226
228{
230 if (value.isEmpty() && !d->m_featureExtendedData) {
231 return; // nothing to change
232 }
233
234 d->featureExtendedData().m_phoneNumber = value;
235}
236
238{
239 Q_D(const GeoDataFeature);
240 if (!d->m_featureExtendedData) {
241 return {};
242 }
243
244 return d->featureExtendedData().m_description;
245}
246
248{
250 if (value.isEmpty() && !d->m_featureExtendedData) {
251 return; // nothing to change
252 }
253
254 d->featureExtendedData().m_description = value;
255}
256
258{
259 Q_D(const GeoDataFeature);
260 if (!d->m_featureExtendedData) {
261 return false;
262 }
263
264 return d->featureExtendedData().m_descriptionCDATA;
265}
266
268{
270 d->featureExtendedData().m_descriptionCDATA = cdata;
271}
272
274{
275 Q_D(const GeoDataFeature);
276 if (!d->m_featureExtendedData) {
277 return nullptr;
278 }
279
280 return d->featureExtendedData().m_abstractView;
281}
282
284{
285 // FIXME: Calling detach() doesn't help at all because the m_abstractView
286 // object isn't actually copied in the Private class as well.
287 // detach();
288
290 return d->featureExtendedData().m_abstractView;
291}
292
294{
296 if (abstractView == nullptr && !d->m_featureExtendedData) {
297 return; // nothing to change
298 }
299
300 d->featureExtendedData().m_abstractView = abstractView;
301}
302
304{
305 Q_D(const GeoDataFeature);
306 return d->m_styleUrl;
307}
308
310{
312 d->m_styleUrl = value;
313
314 if (value.isEmpty()) {
315 d->m_style = GeoDataStyle::Ptr();
316 return;
317 }
318
319 QString styleUrl = value;
321
322 for (auto object = parent(); object != nullptr; object = object->parent()) {
323 if (auto doc = geodata_cast<GeoDataDocument>(object)) {
324 GeoDataStyleMap &styleMap = doc->styleMap(styleUrl);
325 const QString normalStyleUrl = styleMap.value(QStringLiteral("normal"));
326 if (!normalStyleUrl.isEmpty()) {
327 styleUrl = normalStyleUrl;
329 }
330 // Not calling setStyle here because we don't want
331 // re-parenting of the style
332 d->m_style = doc->style(styleUrl);
333 break;
334 }
335 }
336}
337
339{
340 Q_D(const GeoDataFeature);
341 return d->m_visible;
342}
343
345{
347 d->m_visible = value;
348}
349
351{
352 Q_D(const GeoDataFeature);
353 if (parent() == nullptr) {
354 return d->m_visible;
355 }
356 const auto container = static_cast<const GeoDataContainer *>(parent());
357 return d->m_visible && container->isGloballyVisible();
358}
359
360const GeoDataTimeSpan &GeoDataFeature::timeSpan() const
361{
362 Q_D(const GeoDataFeature);
363 return d->featureExtendedData().m_timeSpan;
364}
365
366GeoDataTimeSpan &GeoDataFeature::timeSpan()
367{
369 return d->featureExtendedData().m_timeSpan;
370}
371
372void GeoDataFeature::setTimeSpan(const GeoDataTimeSpan &timeSpan)
373{
375 d->featureExtendedData().m_timeSpan = timeSpan;
376}
377
378const GeoDataTimeStamp &GeoDataFeature::timeStamp() const
379{
380 Q_D(const GeoDataFeature);
381 return d->featureExtendedData().m_timeStamp;
382}
383
384GeoDataTimeStamp &GeoDataFeature::timeStamp()
385{
387 return d->featureExtendedData().m_timeStamp;
388}
389
390void GeoDataFeature::setTimeStamp(const GeoDataTimeStamp &timeStamp)
391{
393 d->featureExtendedData().m_timeStamp = timeStamp;
394}
395
397{
398 Q_D(const GeoDataFeature);
399 return d->m_extendedData;
400}
401
403{
404 Q_D(const GeoDataFeature);
405 if (d->m_style) {
406 return d->m_style;
407 }
408
409 static const QSharedPointer<const GeoDataStyle> s_defaultStyle(new GeoDataStyle);
410 return s_defaultStyle;
411}
412
414{
415 Q_D(const GeoDataFeature);
416 return d->m_style;
417}
418
420{
422 if (style)
423 style->setParent(this);
424 d->m_style = style;
425}
426
428{
430 return d->m_extendedData;
431}
432
434{
436 d->m_extendedData = extendedData;
437}
438
440{
441 Q_D(const GeoDataFeature);
442 return d->featureExtendedData().m_region;
443}
444
446{
448 return d->featureExtendedData().m_region;
449}
450
452{
454 d->featureExtendedData().m_region = region;
455}
456
458{
459 Q_D(const GeoDataFeature);
460 return d->m_role;
461}
462
464{
466 d->m_role = role;
467}
468
470{
471 Q_D(const GeoDataFeature);
472 return d->m_styleMap;
473}
474
476{
478 d->m_styleMap = styleMap;
479}
480
482{
483 Q_D(const GeoDataFeature);
484 return d->m_zoomLevel;
485}
486
488{
490 d->m_zoomLevel = zoomLevel;
491}
492
494{
495 Q_D(const GeoDataFeature);
496 return d->m_popularity;
497}
498
499void GeoDataFeature::setPopularity(qint64 popularity)
500{
502 d->m_popularity = popularity;
503}
504
506{
507 Q_D(const GeoDataFeature);
508
509 GeoDataObject::pack(stream);
510
511 stream << d->m_name;
512 stream << d->featureExtendedData().m_address;
513 stream << d->featureExtendedData().m_phoneNumber;
514 stream << d->featureExtendedData().m_description;
515 stream << d->m_visible;
516 // stream << d->m_visualCategory;
517 stream << d->m_role;
518 stream << d->m_popularity;
519 stream << d->m_zoomLevel;
520}
521
523{
525 GeoDataObject::unpack(stream);
526
527 stream >> d->m_name;
528 stream >> d->featureExtendedData().m_address;
529 stream >> d->featureExtendedData().m_phoneNumber;
530 stream >> d->featureExtendedData().m_description;
531 stream >> d->m_visible;
532 // stream >> (int)d->m_visualCategory;
533 stream >> d->m_role;
534 stream >> d->m_popularity;
535 stream >> d->m_zoomLevel;
536}
537
538}
A base class that can hold GeoDataFeatures.
a class which allows to add custom data to KML Feature.
A base class for all geodata features.
void setStyle(const QSharedPointer< GeoDataStyle > &style)
Sets the style of the placemark.
void unpack(QDataStream &stream) override
Unserialize the contents of the feature from stream.
QString description() const
Return the text description of the feature.
QString styleUrl() const
Return the styleUrl of the feature.
void setTimeSpan(const GeoDataTimeSpan &timeSpan)
Set the timespan of the feature.
bool descriptionIsCDATA() const
test if the description is CDATA or not CDATA allows for special characters to be included in XML and...
void setStyleUrl(const QString &value)
Set the styleUrl of this feature to value.
const GeoDataTimeSpan & timeSpan() const
Return the timespan of the feature.
bool isGloballyVisible() const
Return whether this feature is visible or not in the context of its parenting.
void setStyleMap(const GeoDataStyleMap *map)
Sets the styleMap of the feature.
int zoomLevel() const
Return the popularity index of the placemark.
void setExtendedData(const GeoDataExtendedData &extendedData)
Sets the ExtendedData of the feature.
void setRegion(const GeoDataRegion &region)
Sets the region of the placemark.
void setRole(const QString &role)
Sets the role of the placemark.
void setPhoneNumber(const QString &value)
Set the phone number of this feature to value.
const GeoDataRegion & region() const
Return the region assigned to the placemark.
QString name() const
The name of the feature.
GeoDataSnippet snippet() const
A short description of the feature.
void setPopularity(qint64 popularity)
Sets the popularity of the feature.
void setDescriptionCDATA(bool cdata)
Set the description to be CDATA See:
const GeoDataAbstractView * abstractView() const
Get the Abstract view of the feature.
qint64 popularity() const
Return the popularity of the feature.
void setZoomLevel(int index)
Sets the popularity index of the placemark.
QSharedPointer< const GeoDataStyle > customStyle() const
Return the style assigned to the placemark with setStyle (can be 0)
void setAddress(const QString &value)
Set the address of this feature to value.
QString address() const
Return the address of the feature.
const GeoDataTimeStamp & timeStamp() const
Return the timestamp of the feature.
const QString role() const
Return the role of the placemark.
QSharedPointer< const GeoDataStyle > style() const
Return the style assigned to the placemark, or a default style if none has been set.
QString phoneNumber() const
Return the phone number of the feature.
GeoDataExtendedData & extendedData()
Return the ExtendedData assigned to the feature.
void setName(const QString &value)
Set a new name for this feature.
void pack(QDataStream &stream) const override
Serialize the contents of the feature to stream.
void setAbstractView(GeoDataAbstractView *abstractView)
Set the abstract view of the feature.
const GeoDataStyleMap * styleMap() const
Return a pointer to a GeoDataStyleMap object which represents the styleMap of this feature.
bool isVisible() const
Return whether this feature is visible or not.
void setVisible(bool value)
Set a new value for visibility.
void setTimeStamp(const GeoDataTimeStamp &timeStamp)
Set the timestamp of the feature.
void setDescription(const QString &value)
Set the description of this feature to value.
void setSnippet(const GeoDataSnippet &value)
Set a new name for this feature.
A base class for all geodata objects.
virtual bool equals(const GeoDataObject &other) const
Compares the value of id and targetId of the two objects.
void pack(QDataStream &stream) const override
Reimplemented from Serializable.
const GeoDataObject * parent() const
Provides the parent of the object in GeoDataContainers.
void unpack(QDataStream &steam) override
Reimplemented from Serializable.
GeoDataRegion describes the visibility and extent of a feature.
a class to map different styles to one style
an addressable style group
virtual const char * nodeType() const =0
Provides type information for downcasting a GeoNode.
Binds a QML item to a specific geodetic location in screen coordinates.
T * geodata_cast(GeoDataObject *node)
Returns the given node cast to type T if the node was instantiated as type T; otherwise returns 0.
T value(const Key &key, const T &defaultValue) const const
bool isEmpty() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:08:52 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.