1 /*
2     SPDX-FileCopyrightText: 2012 Jan Grulich <grulja@gmail.com>
3 
4     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "staticmapurl.h"
8 
9 #include <QUrlQuery>
10 
11 using namespace KGAPI2;
12 
13 
14 class Q_DECL_HIDDEN StaticMapUrl::Private
15 {
16 public:
17     Private();
18     Private(const Private& other);
19 
20     void init(const Private &other);
21 
22     StaticMapUrl::LocationType locationType;
23     StaticMapUrl::ImageFormat format;
24 
25     QString locationString;
26     KContacts::Address locationAddress;
27     KContacts::Geo locationGeo;
28 
29     StaticMapUrl::MapType maptype;
30     QList<StaticMapMarker> markers;
31     QList<StaticMapPath> paths;
32     StaticMapUrl::Scale scale;
33     bool sensor;
34     QSize size;
35 
36     QString visibleString;
37     KContacts::Address visibleAddress;
38     KContacts::Geo visibleGeo;
39     StaticMapUrl::LocationType visibleLocationType;
40 
41     qint32 zoom;
42 };
43 
Private()44 StaticMapUrl::Private::Private():
45     locationType(StaticMapUrl::Undefined),
46     format(StaticMapUrl::PNG),
47     maptype(StaticMapUrl::Roadmap),
48     scale(StaticMapUrl::Normal),
49     sensor(false),
50     visibleLocationType(StaticMapUrl::Undefined),
51     zoom(-1)
52 {
53 }
54 
Private(const Private & other)55 StaticMapUrl::Private::Private(const Private & other)
56 {
57     init(other);
58 }
59 
init(const StaticMapUrl::Private & other)60 void StaticMapUrl::Private::init(const StaticMapUrl::Private& other)
61 {
62     locationType = other.locationType;
63     format = other.format;
64     locationString = other.locationString;
65     locationAddress = other.locationAddress;
66     locationGeo = other.locationGeo;
67     maptype = other.maptype;
68     markers = other.markers;
69     paths = other.paths;
70     scale = other.scale;
71     sensor = other.sensor;
72     size = other.size;
73     visibleString = other.visibleString;
74     visibleAddress = other.visibleAddress;
75     visibleGeo = other.visibleGeo;
76     visibleLocationType = other.visibleLocationType;
77     zoom = other.zoom;
78 }
79 
StaticMapUrl()80 StaticMapUrl::StaticMapUrl():
81     d(new Private)
82 {
83 }
84 
StaticMapUrl(const StaticMapUrl & other)85 StaticMapUrl::StaticMapUrl(const StaticMapUrl& other):
86     d(new Private(*(other.d)))
87 {
88 }
89 
~StaticMapUrl()90 StaticMapUrl::~StaticMapUrl()
91 {
92     delete d;
93 }
94 
95 
operator =(const StaticMapUrl & other)96 StaticMapUrl& StaticMapUrl::operator=(const StaticMapUrl& other)
97 {
98     if (&other == this) {
99         return *this;
100     }
101 
102     d->init(*(other.d));
103     return *this;
104 }
105 
StaticMapUrl(const QString & location,const QSize & size,quint32 zoom,bool sensor)106 StaticMapUrl::StaticMapUrl(const QString &location, const QSize &size,
107                            quint32 zoom, bool sensor):
108     d(new Private)
109 {
110     setLocation(location);
111     setSize(size);
112     setZoomLevel(zoom);
113     setSensorUsed(sensor);
114 }
115 
StaticMapUrl(const KContacts::Address & address,const QSize & size,quint32 zoom,bool sensor)116 StaticMapUrl::StaticMapUrl(const KContacts::Address &address, const QSize &size,
117                            quint32 zoom, bool sensor):
118     d(new Private)
119 {
120     setLocation(address);
121     setSize(size);
122     setZoomLevel(zoom);
123     setSensorUsed(sensor);
124 }
125 
StaticMapUrl(const KContacts::Geo & geo,const QSize & size,quint32 zoom,bool sensor)126 StaticMapUrl::StaticMapUrl(const KContacts::Geo &geo, const QSize &size,
127                            quint32 zoom, bool sensor):
128     d(new Private)
129 {
130     setLocation(geo);
131     setSize(size);
132     setZoomLevel(zoom);
133     setSensorUsed(sensor);
134 }
135 
locationType() const136 StaticMapUrl::LocationType StaticMapUrl::locationType() const
137 {
138     return d->locationType;
139 }
140 
format() const141 StaticMapUrl::ImageFormat StaticMapUrl::format() const
142 {
143     return d->format;
144 }
145 
setFormat(const StaticMapUrl::ImageFormat format)146 void StaticMapUrl::setFormat(const StaticMapUrl::ImageFormat format)
147 {
148     d->format = format;
149 }
150 
isValid() const151 bool StaticMapUrl::isValid() const
152 {
153     bool maOrPa = true;
154 
155     if (d->markers.isEmpty()) {
156         for (const StaticMapPath & path : std::as_const(d->paths)) {
157             if (!path.isValid()) {
158                 maOrPa = false;
159             }
160         }
161     } else {
162 
163         for (const StaticMapMarker & marker : std::as_const(d->markers)) {
164             if (!marker.isValid()) {
165                 maOrPa = false;
166             }
167         }
168 
169     }
170 
171     if (maOrPa) {
172         if ((d->locationType == Undefined || d->zoom == -1) && (d->visibleLocationType == Undefined)) {
173             return false;
174         }
175     }
176 
177     return !(d->size.isEmpty());
178 }
179 
locationString() const180 QString StaticMapUrl::locationString() const
181 {
182     return d->locationString;
183 }
184 
setLocation(const QString & location)185 void StaticMapUrl::setLocation(const QString& location)
186 {
187     d->locationString = location;
188     d->locationType = String;
189     d->locationAddress.clear();
190     d->locationGeo.setLatitude(91);
191     d->locationGeo.setLongitude(181);
192 }
193 
locationAddress() const194 KContacts::Address StaticMapUrl::locationAddress() const
195 {
196     return d->locationAddress;
197 }
198 
setLocation(const KContacts::Address & address)199 void StaticMapUrl::setLocation(const KContacts::Address& address)
200 {
201     d->locationAddress = address;
202     d->locationType = KABCAddress;
203     d->locationString.clear();
204     d->locationGeo.setLatitude(91);
205     d->locationGeo.setLongitude(181);
206 }
207 
locationGeo() const208 KContacts::Geo StaticMapUrl::locationGeo() const
209 {
210     return d->locationGeo;
211 }
212 
setLocation(const KContacts::Geo & geo)213 void StaticMapUrl::setLocation(const KContacts::Geo& geo)
214 {
215     d->locationGeo = geo;
216     d->locationType = KABCGeo;
217     d->locationString.clear();
218     d->locationAddress.clear();
219 }
220 
mapType() const221 StaticMapUrl::MapType StaticMapUrl::mapType() const
222 {
223     return d->maptype;
224 }
225 
setMapType(const StaticMapUrl::MapType type)226 void StaticMapUrl::setMapType(const StaticMapUrl::MapType type)
227 {
228     d->maptype = type;
229 }
230 
markers() const231 QList< StaticMapMarker > StaticMapUrl::markers() const
232 {
233     return d->markers;
234 }
235 
setMarker(const StaticMapMarker & marker)236 void StaticMapUrl::setMarker(const StaticMapMarker& marker)
237 {
238     QList<StaticMapMarker> markers;
239     markers << marker;
240     d->markers = markers;
241 }
242 
setMarkers(const QList<StaticMapMarker> & markers)243 void StaticMapUrl::setMarkers(const QList< StaticMapMarker >& markers)
244 {
245     d->markers = markers;
246 }
247 
paths() const248 QList<StaticMapPath> StaticMapUrl::paths() const
249 {
250     return d->paths;
251 }
252 
setPath(const StaticMapPath & path)253 void StaticMapUrl::setPath(const StaticMapPath & path)
254 {
255     QList<StaticMapPath> paths;
256     paths << path;
257     d->paths = paths;
258 }
259 
setPaths(const QList<StaticMapPath> & paths)260 void StaticMapUrl::setPaths(const QList< StaticMapPath >& paths)
261 {
262     d->paths = paths;
263 }
264 
size() const265 QSize StaticMapUrl::size() const
266 {
267     return d->size;
268 }
269 
setSize(const QSize & size)270 void StaticMapUrl::setSize(const QSize& size)
271 {
272     d->size = size;
273 }
274 
scale() const275 StaticMapUrl::Scale StaticMapUrl::scale() const
276 {
277     return d->scale;
278 }
279 
setScale(const Scale scale)280 void StaticMapUrl::setScale(const Scale scale)
281 {
282     d->scale = scale;
283 }
284 
sensorUsed() const285 bool StaticMapUrl::sensorUsed() const
286 {
287     return d->sensor;
288 }
289 
setSensorUsed(const bool sensor)290 void StaticMapUrl::setSensorUsed(const bool sensor)
291 {
292     d->sensor = sensor;
293 }
294 
visibleLocationString() const295 QString StaticMapUrl::visibleLocationString() const
296 {
297     return d->visibleString;
298 }
299 
setVisibleLocation(const QString & location)300 void StaticMapUrl::setVisibleLocation(const QString & location)
301 {
302     d->visibleString = location;
303     d->visibleLocationType = String;
304     d->visibleAddress.clear();
305     d->visibleGeo.setLatitude(911);
306     d->visibleGeo.setLongitude(181);
307 }
308 
visibleLocationAddress() const309 KContacts::Address StaticMapUrl::visibleLocationAddress() const
310 {
311     return d->locationAddress;
312 }
313 
setVisibleLocation(const KContacts::Address & address)314 void StaticMapUrl::setVisibleLocation(const KContacts::Address & address)
315 {
316     d->visibleAddress = address;
317     d->visibleLocationType = KABCAddress;
318     d->visibleString.clear();
319     d->visibleGeo.setLatitude(911);
320     d->visibleGeo.setLongitude(181);
321 }
322 
visibleLocationGeo() const323 KContacts::Geo StaticMapUrl::visibleLocationGeo() const
324 {
325     return d->locationGeo;
326 }
327 
setVisibleLocation(const KContacts::Geo & geo)328 void StaticMapUrl::setVisibleLocation(const KContacts::Geo & geo)
329 {
330     d->visibleGeo = geo;
331     d->visibleLocationType = KABCGeo;
332     d->visibleString.clear();
333     d->visibleAddress.clear();
334 }
335 
visibleLocationType() const336 StaticMapUrl::LocationType StaticMapUrl::visibleLocationType() const
337 {
338     return d->visibleLocationType;
339 }
340 
zoomLevel() const341 qint8 StaticMapUrl::zoomLevel() const
342 {
343     return d->zoom;
344 }
345 
setZoomLevel(const quint32 zoom)346 void StaticMapUrl::setZoomLevel(const quint32 zoom)
347 {
348     d->zoom = zoom;
349 }
350 
url() const351 QUrl StaticMapUrl::url() const
352 {
353     QUrl url(QStringLiteral("http://maps.googleapis.com/maps/api/staticmap"));
354     QUrlQuery query(url);
355 
356     if (d->locationType != Undefined) {
357         QString param;
358 
359         switch (d->locationType) {
360         case Undefined:
361         case String:
362             param = d->locationString;
363             param.replace(QLatin1String(", "), QLatin1String(","));
364             param.replace(QLatin1String(". "), QLatin1String("."));
365             param.replace(QLatin1Char(' '), QLatin1Char('+'));
366             query.addQueryItem(QStringLiteral("center"), param);
367             break;
368         case KABCAddress:
369             param = d->locationAddress.formattedAddress();
370             param.replace(QLatin1String(", "), QLatin1String(","));
371             param.replace(QLatin1String(". "), QLatin1String("."));
372             param.replace(QLatin1Char(' '), QLatin1Char('+'));
373             param.replace(QLatin1Char('\n'), QLatin1Char(','));
374             query.addQueryItem(QStringLiteral("center"), param);
375             break;
376         case KABCGeo:
377             param = QString::number(d->locationGeo.latitude()) + QLatin1Char(',') +
378                     QString::number(d->locationGeo.longitude());
379             query.addQueryItem(QStringLiteral("center"), param);
380             break;
381         }
382     }
383 
384     if (d->zoom != -1) {
385         query.addQueryItem(QStringLiteral("zoom"), QString::number(d->zoom));
386     }
387 
388     if (!d->size.isEmpty()) {
389         QString size = QString::number(d->size.width()) + QLatin1Char('x') +
390                        QString::number(d->size.height());
391         query.addQueryItem(QStringLiteral("size"), size);
392     }
393 
394     if (d->scale != Normal) {
395         query.addQueryItem(QStringLiteral("scale"), QString::number(2));
396     }
397     if (d->format != PNG) {
398         QString format;
399 
400         switch (d->format) {
401         case PNG:
402         case PNG32:
403             format = QStringLiteral("png32");
404             break;
405         case GIF:
406             format = QStringLiteral("gif");
407             break;
408         case JPG:
409             format = QStringLiteral("jpg");
410             break;
411         case JPGBaseline:
412             format = QStringLiteral("jpg-baseline");
413             break;
414         }
415 
416         query.addQueryItem(QStringLiteral("format"), format);
417     }
418 
419     if (d->maptype != Roadmap) {
420         QString maptype;
421 
422         switch (d->maptype) {
423         case Roadmap:
424         case Satellite:
425             maptype = QStringLiteral("satellite");
426             break;
427         case Terrain:
428             maptype = QStringLiteral("terrain");
429             break;
430         case Hybrid:
431             maptype = QStringLiteral("hybrid");
432             break;
433         }
434 
435         query.addQueryItem(QStringLiteral("maptype"), maptype);
436     }
437 
438     for (const StaticMapMarker & marker : std::as_const(d->markers)) {
439         if (marker.isValid()) {
440             query.addQueryItem(QStringLiteral("markers"), marker.toString());
441         }
442     }
443 
444     for (const StaticMapPath & path : std::as_const(d->paths)) {
445         if (path.isValid()) {
446             query.addQueryItem(QStringLiteral("path"), path.toString());
447         }
448     }
449 
450     if (d->visibleLocationType != Undefined) {
451 
452         QString param;
453 
454         switch (d->visibleLocationType) {
455         case Undefined:
456         case String:
457             param = d->visibleString;
458             param.replace(QLatin1String(", "), QLatin1String(","));
459             param.replace(QLatin1String(". "), QLatin1String("."));
460             param.replace(QLatin1Char(' '), QLatin1Char('+'));
461             query.addQueryItem(QStringLiteral("visible"), param);
462             break;
463         case KABCAddress:
464             param = d->visibleAddress.formattedAddress();
465             param.replace(QLatin1String(", "), QLatin1String(","));
466             param.replace(QLatin1String(". "), QLatin1String("."));
467             param.replace(QLatin1Char(' '), QLatin1Char('+'));
468             param.replace(QLatin1Char('\n'), QLatin1Char(','));
469             query.addQueryItem(QStringLiteral("visible"), param);
470             break;
471         case KABCGeo:
472             param = QString::number(d->visibleGeo.latitude()) + QLatin1Char(',') +
473                     QString::number(d->visibleGeo.longitude());
474             query.addQueryItem(QStringLiteral("visible"), param);
475             break;
476         }
477     }
478 
479     if (d->sensor) {
480         query.addQueryItem(QStringLiteral("sensor"), QStringLiteral("true"));
481     } else {
482         query.addQueryItem(QStringLiteral("sensor"), QStringLiteral("false"));
483     }
484 
485     url.setQuery(query);
486     return url;
487 }
488