1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2007-11-01
7 * Description : Access item position stored in database.
8 *
9 * Copyright (C) 2007-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10 *
11 * This program is free software; you can redistribute it
12 * and/or modify it under the terms of the GNU General
13 * Public License as published by the Free Software Foundation;
14 * either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * ============================================================ */
23
24 #include "itemposition.h"
25
26 // Local includes
27
28 #include "coredbaccess.h"
29 #include "coredb.h"
30 #include "coredbfields.h"
31 #include "dmetadata.h"
32 #include "metadatainfo.h"
33
34 namespace Digikam
35 {
36
37 class Q_DECL_HIDDEN ItemPositionPriv : public QSharedData
38 {
39
40 public:
41
ItemPositionPriv()42 ItemPositionPriv()
43 : empty (true),
44 // NOTE: Do not initialize the QVariants here, they are expected to be null
45 imageId (-1),
46 dirtyFields (DatabaseFields::ItemPositionsNone)
47 {
48 }
49
resetData()50 void resetData()
51 {
52 description.clear();
53 latitude.clear();
54 longitude.clear();
55 latitudeNumber = QVariant();
56 longitudeNumber = QVariant();
57 altitude = QVariant();
58 orientation = QVariant();
59 tilt = QVariant();
60 roll = QVariant();
61 empty = true;
62 dirtyFields = DatabaseFields::ItemPositionsNone;
63 }
64
65 void init(const CoreDbAccess& access, qlonglong imageId);
66
67 public:
68
69 bool empty;
70
71 QVariant latitudeNumber;
72 QVariant longitudeNumber;
73 QVariant altitude;
74 QVariant orientation;
75 QVariant tilt;
76 QVariant roll;
77 QVariant accuracy;
78
79 qlonglong imageId;
80
81 QString description;
82 QString latitude;
83 QString longitude;
84
85 DatabaseFields::ItemPositions dirtyFields;
86 };
87
init(const CoreDbAccess & access,qlonglong id)88 void ItemPositionPriv::init(const CoreDbAccess& access, qlonglong id)
89 {
90 imageId = id;
91 QVariantList values = access.db()->getItemPosition(imageId);
92
93 if (values.size() == 10)
94 {
95 empty = false;
96 latitude = values.at(0).toString();
97 latitudeNumber = values.at(1);
98 longitude = values.at(2).toString();
99 longitudeNumber = values.at(3);
100 altitude = values.at(4);
101 orientation = values.at(5);
102 tilt = values.at(6);
103 roll = values.at(7);
104 accuracy = values.at(8);
105 description = values.at(9).toString();
106 }
107 }
108
109 // ------------------------------------------------------
110
ItemPosition()111 ItemPosition::ItemPosition()
112 {
113 }
114
ItemPosition(qlonglong imageId)115 ItemPosition::ItemPosition(qlonglong imageId)
116 : d(new ItemPositionPriv)
117 {
118 CoreDbAccess access;
119 d->init(access, imageId);
120 }
121
ItemPosition(const CoreDbAccess & access,qlonglong imageId)122 ItemPosition::ItemPosition(const CoreDbAccess& access, qlonglong imageId)
123 : d(new ItemPositionPriv)
124 {
125 d->init(access, imageId);
126 }
127
ItemPosition(const ItemPosition & other)128 ItemPosition::ItemPosition(const ItemPosition& other)
129 : d(other.d)
130 {
131 }
132
~ItemPosition()133 ItemPosition::~ItemPosition()
134 {
135 apply();
136 }
137
operator =(const ItemPosition & other)138 ItemPosition& ItemPosition::operator=(const ItemPosition& other)
139 {
140 d = other.d;
141
142 return *this;
143 }
144
isNull() const145 bool ItemPosition::isNull() const
146 {
147 return !d;
148 }
149
isEmpty() const150 bool ItemPosition::isEmpty() const
151 {
152 return (!d || d->empty);
153 }
154
latitude() const155 QString ItemPosition::latitude() const
156 {
157 if (!d)
158 {
159 return QString();
160 }
161
162 return d->latitude;
163 }
164
longitude() const165 QString ItemPosition::longitude() const
166 {
167 if (!d)
168 {
169 return QString();
170 }
171
172 return d->longitude;
173 }
174
latitudeNumber() const175 double ItemPosition::latitudeNumber() const
176 {
177 if (!d)
178 {
179 return 0;
180 }
181
182 return d->latitudeNumber.toDouble();
183 }
184
longitudeNumber() const185 double ItemPosition::longitudeNumber() const
186 {
187 if (!d)
188 {
189 return 0;
190 }
191
192 return d->longitudeNumber.toDouble();
193 }
194
latitudeFormatted() const195 QString ItemPosition::latitudeFormatted() const
196 {
197 if (!d)
198 {
199 return QString();
200 }
201
202 return DMetadata::valueToString(d->latitude, MetadataInfo::Latitude);
203 }
204
longitudeFormatted() const205 QString ItemPosition::longitudeFormatted() const
206 {
207 if (!d)
208 {
209 return QString();
210 }
211
212 return DMetadata::valueToString(d->longitude, MetadataInfo::Longitude);
213 }
214
latitudeUserPresentableNumbers(int * degrees,int * minutes,double * seconds,char * directionReference)215 bool ItemPosition::latitudeUserPresentableNumbers(int* degrees, int* minutes, double* seconds, char* directionReference)
216 {
217 if (!d)
218 {
219 return false;
220 }
221
222 return DMetadata::convertToUserPresentableNumbers(d->latitude, degrees, minutes, seconds, directionReference);
223 }
224
longitudeUserPresentableNumbers(int * degrees,int * minutes,double * seconds,char * directionReference)225 bool ItemPosition::longitudeUserPresentableNumbers(int* degrees, int* minutes, double* seconds, char* directionReference)
226 {
227 if (!d)
228 {
229 return false;
230 }
231
232 return DMetadata::convertToUserPresentableNumbers(d->longitude, degrees, minutes, seconds, directionReference);
233 }
234
altitude() const235 double ItemPosition::altitude() const
236 {
237 if (!d)
238 {
239 return 0;
240 }
241
242 return d->altitude.toDouble();
243 }
244
altitudeFormatted() const245 QString ItemPosition::altitudeFormatted() const
246 {
247 if (!d)
248 {
249 return QString();
250 }
251
252 return DMetadata::valueToString(d->altitude, MetadataInfo::Altitude);
253 }
254
orientation() const255 double ItemPosition::orientation() const
256 {
257 if (!d)
258 {
259 return 0;
260 }
261
262 return d->orientation.toDouble();
263 }
264
tilt() const265 double ItemPosition::tilt() const
266 {
267 if (!d)
268 {
269 return 0;
270 }
271
272 return d->tilt.toDouble();
273 }
274
roll() const275 double ItemPosition::roll() const
276 {
277 if (!d)
278 {
279 return 0;
280 }
281
282 return d->roll.toDouble();
283 }
284
accuracy() const285 double ItemPosition::accuracy() const
286 {
287 if (!d)
288 {
289 return 0;
290 }
291
292 return d->accuracy.toDouble();
293 }
294
description() const295 QString ItemPosition::description() const
296 {
297 if (!d)
298 {
299 return QString();
300 }
301
302 return d->description;
303 }
304
hasCoordinates() const305 bool ItemPosition::hasCoordinates() const
306 {
307 return (d && !d->latitudeNumber.isNull() && !d->longitudeNumber.isNull());
308 }
309
hasAltitude() const310 bool ItemPosition::hasAltitude() const
311 {
312 return (d && !d->altitude.isNull());
313 }
314
hasOrientation() const315 bool ItemPosition::hasOrientation() const
316 {
317 return (d && !d->orientation.isNull());
318 }
319
hasTilt() const320 bool ItemPosition::hasTilt() const
321 {
322 return (d && !d->tilt.isNull());
323 }
324
hasRoll() const325 bool ItemPosition::hasRoll() const
326 {
327 return (d && !d->roll.isNull());
328 }
329
hasAccuracy() const330 bool ItemPosition::hasAccuracy() const
331 {
332 return (d && !d->accuracy.isNull());
333 }
334
setLatitude(const QString & latitude)335 bool ItemPosition::setLatitude(const QString& latitude)
336 {
337 if (!d)
338 {
339 return false;
340 }
341
342 double number;
343
344 if (!DMetadata::convertFromGPSCoordinateString(latitude, &number))
345 {
346 return false;
347 }
348
349 d->latitude = latitude;
350 d->latitudeNumber = number;
351 d->dirtyFields |= DatabaseFields::Latitude | DatabaseFields::LatitudeNumber;
352
353 return true;
354 }
355
setLongitude(const QString & longitude)356 bool ItemPosition::setLongitude(const QString& longitude)
357 {
358 if (!d)
359 {
360 return false;
361 }
362
363 double number;
364
365 if (!DMetadata::convertFromGPSCoordinateString(longitude, &number))
366 {
367 return false;
368 }
369
370 d->longitude = longitude;
371 d->longitudeNumber = number;
372 d->dirtyFields |= DatabaseFields::Longitude | DatabaseFields::LongitudeNumber;
373
374 return true;
375 }
376
setLatitude(double latitudeNumber)377 bool ItemPosition::setLatitude(double latitudeNumber)
378 {
379 if (!d)
380 {
381 return false;
382 }
383
384 QString string = DMetadata::convertToGPSCoordinateString(true, latitudeNumber);
385
386 if (string.isNull())
387 {
388 return false;
389 }
390
391 d->latitude = string;
392 d->latitudeNumber = latitudeNumber;
393 d->dirtyFields |= DatabaseFields::Latitude | DatabaseFields::LatitudeNumber;
394
395 return true;
396 }
397
setLongitude(double longitudeNumber)398 bool ItemPosition::setLongitude(double longitudeNumber)
399 {
400 if (!d)
401 {
402 return false;
403 }
404
405 QString string = DMetadata::convertToGPSCoordinateString(false, longitudeNumber);
406
407 if (string.isNull())
408 {
409 return false;
410 }
411
412 d->longitude = string;
413 d->longitudeNumber = longitudeNumber;
414 d->dirtyFields |= DatabaseFields::Longitude | DatabaseFields::LongitudeNumber;
415
416 return true;
417 }
418
setAltitude(double altitude)419 void ItemPosition::setAltitude(double altitude)
420 {
421 if (!d)
422 {
423 return;
424 }
425
426 d->altitude = altitude;
427 d->dirtyFields |= DatabaseFields::Altitude;
428 }
429
setOrientation(double orientation)430 void ItemPosition::setOrientation(double orientation)
431 {
432 if (!d)
433 {
434 return;
435 }
436
437 d->orientation = orientation;
438 d->dirtyFields |= DatabaseFields::PositionOrientation;
439 }
440
setTilt(double tilt)441 void ItemPosition::setTilt(double tilt)
442 {
443 if (!d)
444 {
445 return;
446 }
447
448 d->tilt = tilt;
449 d->dirtyFields |= DatabaseFields::PositionTilt;
450 }
451
setRoll(double roll)452 void ItemPosition::setRoll(double roll)
453 {
454 if (!d)
455 {
456 return;
457 }
458
459 d->roll = roll;
460 d->dirtyFields |= DatabaseFields::PositionRoll;
461 }
462
setAccuracy(double accuracy)463 void ItemPosition::setAccuracy(double accuracy)
464 {
465 if (!d)
466 {
467 return;
468 }
469
470 d->accuracy = accuracy;
471 d->dirtyFields |= DatabaseFields::PositionAccuracy;
472 }
473
setDescription(const QString & description)474 void ItemPosition::setDescription(const QString& description)
475 {
476 if (!d)
477 {
478 return;
479 }
480
481 d->description = description;
482 d->dirtyFields |= DatabaseFields::PositionDescription;
483 }
484
apply()485 void ItemPosition::apply()
486 {
487 if (!d)
488 {
489 return;
490 }
491
492 if (d->dirtyFields == DatabaseFields::ItemPositionsNone)
493 {
494 return;
495 }
496
497 QVariantList values;
498
499 if (d->dirtyFields & DatabaseFields::Latitude)
500 {
501 values << d->latitude;
502 }
503
504 if (d->dirtyFields & DatabaseFields::LatitudeNumber)
505 {
506 values << d->latitudeNumber;
507 }
508
509 if (d->dirtyFields & DatabaseFields::Longitude)
510 {
511 values << d->longitude;
512 }
513
514 if (d->dirtyFields & DatabaseFields::LongitudeNumber)
515 {
516 values << d->longitudeNumber;
517 }
518
519 if (d->dirtyFields & DatabaseFields::Altitude)
520 {
521 values << d->altitude;
522 }
523
524 if (d->dirtyFields & DatabaseFields::PositionOrientation)
525 {
526 values << d->orientation;
527 }
528
529 if (d->dirtyFields & DatabaseFields::PositionTilt)
530 {
531 values << d->tilt;
532 }
533
534 if (d->dirtyFields & DatabaseFields::PositionRoll)
535 {
536 values << d->roll;
537 }
538
539 if (d->dirtyFields & DatabaseFields::PositionAccuracy)
540 {
541 values << d->accuracy;
542 }
543
544 if (d->dirtyFields & DatabaseFields::PositionDescription)
545 {
546 values << d->description;
547 }
548
549 if (d->empty)
550 {
551 CoreDbAccess().db()->addItemPosition(d->imageId, values, d->dirtyFields);
552 d->empty = false;
553 }
554 else
555 {
556 CoreDbAccess().db()->changeItemPosition(d->imageId, values, d->dirtyFields);
557 }
558
559 d->dirtyFields = DatabaseFields::ItemPositionsNone;
560 }
561
remove()562 void ItemPosition::remove()
563 {
564 CoreDbAccess().db()->removeItemPosition(d->imageId);
565 d->resetData();
566 }
567
removeAltitude()568 void ItemPosition::removeAltitude()
569 {
570 CoreDbAccess().db()->removeItemPositionAltitude(d->imageId);
571 d->dirtyFields &= ~DatabaseFields::Altitude;
572 d->altitude = QVariant();
573 }
574
575 } // namespace Digikam
576