File indexing completed on 2025-01-19 03:53:38

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2007-11-01
0007  * Description : Access item position stored in database.
0008  *
0009  * SPDX-FileCopyrightText: 2007-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "itemposition.h"
0016 
0017 // Local includes
0018 
0019 #include "coredbaccess.h"
0020 #include "coredb.h"
0021 #include "dmetadata.h"
0022 #include "metadatainfo.h"
0023 
0024 namespace Digikam
0025 {
0026 
0027 class Q_DECL_HIDDEN ItemPositionPriv : public QSharedData
0028 {
0029 
0030 public:
0031 
0032     ItemPositionPriv()
0033       : empty       (true),
0034         // NOTE: Do not initialize the QVariants here, they are expected to be null
0035         imageId     (-1),
0036         dirtyFields (DatabaseFields::ItemPositionsNone)
0037     {
0038     }
0039 
0040     void resetData()
0041     {
0042         description.clear();
0043         latitude.clear();
0044         longitude.clear();
0045         latitudeNumber  = QVariant();
0046         longitudeNumber = QVariant();
0047         altitude        = QVariant();
0048         orientation     = QVariant();
0049         tilt            = QVariant();
0050         roll            = QVariant();
0051         empty           = true;
0052         dirtyFields     = DatabaseFields::ItemPositionsNone;
0053     }
0054 
0055     void init(const CoreDbAccess& access, qlonglong imageId);
0056 
0057 public:
0058 
0059     bool                           empty;
0060 
0061     QVariant                       latitudeNumber;
0062     QVariant                       longitudeNumber;
0063     QVariant                       altitude;
0064     QVariant                       orientation;
0065     QVariant                       tilt;
0066     QVariant                       roll;
0067     QVariant                       accuracy;
0068 
0069     qlonglong                      imageId;
0070 
0071     QString                        description;
0072     QString                        latitude;
0073     QString                        longitude;
0074 
0075     DatabaseFields::ItemPositions  dirtyFields;
0076 };
0077 
0078 void ItemPositionPriv::init(const CoreDbAccess& access, qlonglong id)
0079 {
0080     imageId             = id;
0081     QVariantList values = access.db()->getItemPosition(imageId);
0082 
0083     if (values.size() == 10)
0084     {
0085         empty           = false;
0086         latitude        = values.at(0).toString();
0087         latitudeNumber  = values.at(1);
0088         longitude       = values.at(2).toString();
0089         longitudeNumber = values.at(3);
0090         altitude        = values.at(4);
0091         orientation     = values.at(5);
0092         tilt            = values.at(6);
0093         roll            = values.at(7);
0094         accuracy        = values.at(8);
0095         description     = values.at(9).toString();
0096     }
0097 }
0098 
0099 // ------------------------------------------------------
0100 
0101 ItemPosition::ItemPosition()
0102 {
0103 }
0104 
0105 ItemPosition::ItemPosition(qlonglong imageId)
0106     : d(new ItemPositionPriv)
0107 {
0108     CoreDbAccess access;
0109     d->init(access, imageId);
0110 }
0111 
0112 ItemPosition::ItemPosition(const CoreDbAccess& access, qlonglong imageId)
0113     : d(new ItemPositionPriv)
0114 {
0115     d->init(access, imageId);
0116 }
0117 
0118 ItemPosition::ItemPosition(const ItemPosition& other)
0119     : d(other.d)
0120 {
0121 }
0122 
0123 ItemPosition::~ItemPosition()
0124 {
0125     apply();
0126 }
0127 
0128 ItemPosition& ItemPosition::operator=(const ItemPosition& other)
0129 {
0130     d = other.d;
0131 
0132     return *this;
0133 }
0134 
0135 bool ItemPosition::isNull() const
0136 {
0137     return !d;
0138 }
0139 
0140 bool ItemPosition::isEmpty() const
0141 {
0142     return (!d || d->empty);
0143 }
0144 
0145 QString ItemPosition::latitude() const
0146 {
0147     if (!d)
0148     {
0149         return QString();
0150     }
0151 
0152     return d->latitude;
0153 }
0154 
0155 QString ItemPosition::longitude() const
0156 {
0157     if (!d)
0158     {
0159         return QString();
0160     }
0161 
0162     return d->longitude;
0163 }
0164 
0165 double ItemPosition::latitudeNumber() const
0166 {
0167     if (!d)
0168     {
0169         return 0;
0170     }
0171 
0172     return d->latitudeNumber.toDouble();
0173 }
0174 
0175 double ItemPosition::longitudeNumber() const
0176 {
0177     if (!d)
0178     {
0179         return 0;
0180     }
0181 
0182     return d->longitudeNumber.toDouble();
0183 }
0184 
0185 QString ItemPosition::latitudeFormatted() const
0186 {
0187     if (!d)
0188     {
0189         return QString();
0190     }
0191 
0192     return DMetadata::valueToString(d->latitude, MetadataInfo::Latitude);
0193 }
0194 
0195 QString ItemPosition::longitudeFormatted() const
0196 {
0197     if (!d)
0198     {
0199         return QString();
0200     }
0201 
0202     return DMetadata::valueToString(d->longitude, MetadataInfo::Longitude);
0203 }
0204 
0205 bool ItemPosition::latitudeUserPresentableNumbers(int* degrees, int* minutes, double* seconds, char* directionReference)
0206 {
0207     if (!d)
0208     {
0209         return false;
0210     }
0211 
0212     return DMetadata::convertToUserPresentableNumbers(d->latitude, degrees, minutes, seconds, directionReference);
0213 }
0214 
0215 bool ItemPosition::longitudeUserPresentableNumbers(int* degrees, int* minutes, double* seconds, char* directionReference)
0216 {
0217     if (!d)
0218     {
0219         return false;
0220     }
0221 
0222     return DMetadata::convertToUserPresentableNumbers(d->longitude, degrees, minutes, seconds, directionReference);
0223 }
0224 
0225 double ItemPosition::altitude() const
0226 {
0227     if (!d)
0228     {
0229         return 0;
0230     }
0231 
0232     return d->altitude.toDouble();
0233 }
0234 
0235 QString ItemPosition::altitudeFormatted() const
0236 {
0237     if (!d)
0238     {
0239         return QString();
0240     }
0241 
0242     return DMetadata::valueToString(d->altitude, MetadataInfo::Altitude);
0243 }
0244 
0245 double ItemPosition::orientation() const
0246 {
0247     if (!d)
0248     {
0249         return 0;
0250     }
0251 
0252     return d->orientation.toDouble();
0253 }
0254 
0255 double ItemPosition::tilt() const
0256 {
0257     if (!d)
0258     {
0259         return 0;
0260     }
0261 
0262     return d->tilt.toDouble();
0263 }
0264 
0265 double ItemPosition::roll() const
0266 {
0267     if (!d)
0268     {
0269         return 0;
0270     }
0271 
0272     return d->roll.toDouble();
0273 }
0274 
0275 double ItemPosition::accuracy() const
0276 {
0277     if (!d)
0278     {
0279         return 0;
0280     }
0281 
0282     return d->accuracy.toDouble();
0283 }
0284 
0285 QString ItemPosition::description() const
0286 {
0287     if (!d)
0288     {
0289         return QString();
0290     }
0291 
0292     return d->description;
0293 }
0294 
0295 bool ItemPosition::hasCoordinates() const
0296 {
0297     return (d && !d->latitudeNumber.isNull() && !d->longitudeNumber.isNull());
0298 }
0299 
0300 bool ItemPosition::hasAltitude() const
0301 {
0302     return (d && !d->altitude.isNull());
0303 }
0304 
0305 bool ItemPosition::hasOrientation() const
0306 {
0307     return (d && !d->orientation.isNull());
0308 }
0309 
0310 bool ItemPosition::hasTilt() const
0311 {
0312     return (d && !d->tilt.isNull());
0313 }
0314 
0315 bool ItemPosition::hasRoll() const
0316 {
0317     return (d && !d->roll.isNull());
0318 }
0319 
0320 bool ItemPosition::hasAccuracy() const
0321 {
0322     return (d && !d->accuracy.isNull());
0323 }
0324 
0325 bool ItemPosition::setLatitude(const QString& latitude)
0326 {
0327     if (!d)
0328     {
0329         return false;
0330     }
0331 
0332     double number;
0333 
0334     if (!DMetadata::convertFromGPSCoordinateString(latitude, &number))
0335     {
0336         return false;
0337     }
0338 
0339     d->latitude       = latitude;
0340     d->latitudeNumber = number;
0341     d->dirtyFields   |= DatabaseFields::Latitude | DatabaseFields::LatitudeNumber;
0342 
0343     return true;
0344 }
0345 
0346 bool ItemPosition::setLongitude(const QString& longitude)
0347 {
0348     if (!d)
0349     {
0350         return false;
0351     }
0352 
0353     double number;
0354 
0355     if (!DMetadata::convertFromGPSCoordinateString(longitude, &number))
0356     {
0357         return false;
0358     }
0359 
0360     d->longitude       = longitude;
0361     d->longitudeNumber = number;
0362     d->dirtyFields    |= DatabaseFields::Longitude | DatabaseFields::LongitudeNumber;
0363 
0364     return true;
0365 }
0366 
0367 bool ItemPosition::setLatitude(double latitudeNumber)
0368 {
0369     if (!d)
0370     {
0371         return false;
0372     }
0373 
0374     QString string = DMetadata::convertToGPSCoordinateString(true, latitudeNumber);
0375 
0376     if (string.isNull())
0377     {
0378         return false;
0379     }
0380 
0381     d->latitude       = string;
0382     d->latitudeNumber = latitudeNumber;
0383     d->dirtyFields   |= DatabaseFields::Latitude | DatabaseFields::LatitudeNumber;
0384 
0385     return true;
0386 }
0387 
0388 bool ItemPosition::setLongitude(double longitudeNumber)
0389 {
0390     if (!d)
0391     {
0392         return false;
0393     }
0394 
0395     QString string = DMetadata::convertToGPSCoordinateString(false, longitudeNumber);
0396 
0397     if (string.isNull())
0398     {
0399         return false;
0400     }
0401 
0402     d->longitude       = string;
0403     d->longitudeNumber = longitudeNumber;
0404     d->dirtyFields    |= DatabaseFields::Longitude | DatabaseFields::LongitudeNumber;
0405 
0406     return true;
0407 }
0408 
0409 void ItemPosition::setAltitude(double altitude)
0410 {
0411     if (!d)
0412     {
0413         return;
0414     }
0415 
0416     d->altitude     = altitude;
0417     d->dirtyFields |= DatabaseFields::Altitude;
0418 }
0419 
0420 void ItemPosition::setOrientation(double orientation)
0421 {
0422     if (!d)
0423     {
0424         return;
0425     }
0426 
0427     d->orientation  = orientation;
0428     d->dirtyFields |= DatabaseFields::PositionOrientation;
0429 }
0430 
0431 void ItemPosition::setTilt(double tilt)
0432 {
0433     if (!d)
0434     {
0435         return;
0436     }
0437 
0438     d->tilt         = tilt;
0439     d->dirtyFields |= DatabaseFields::PositionTilt;
0440 }
0441 
0442 void ItemPosition::setRoll(double roll)
0443 {
0444     if (!d)
0445     {
0446         return;
0447     }
0448 
0449     d->roll         = roll;
0450     d->dirtyFields |= DatabaseFields::PositionRoll;
0451 }
0452 
0453 void ItemPosition::setAccuracy(double accuracy)
0454 {
0455     if (!d)
0456     {
0457         return;
0458     }
0459 
0460     d->accuracy     = accuracy;
0461     d->dirtyFields |= DatabaseFields::PositionAccuracy;
0462 }
0463 
0464 void ItemPosition::setDescription(const QString& description)
0465 {
0466     if (!d)
0467     {
0468         return;
0469     }
0470 
0471     d->description  = description;
0472     d->dirtyFields |= DatabaseFields::PositionDescription;
0473 }
0474 
0475 void ItemPosition::apply()
0476 {
0477     if (!d)
0478     {
0479         return;
0480     }
0481 
0482     if (d->dirtyFields == DatabaseFields::ItemPositionsNone)
0483     {
0484         return;
0485     }
0486 
0487     QVariantList values;
0488 
0489     if (d->dirtyFields & DatabaseFields::Latitude)
0490     {
0491         values << d->latitude;
0492     }
0493 
0494     if (d->dirtyFields & DatabaseFields::LatitudeNumber)
0495     {
0496         values << d->latitudeNumber;
0497     }
0498 
0499     if (d->dirtyFields & DatabaseFields::Longitude)
0500     {
0501         values << d->longitude;
0502     }
0503 
0504     if (d->dirtyFields & DatabaseFields::LongitudeNumber)
0505     {
0506         values << d->longitudeNumber;
0507     }
0508 
0509     if (d->dirtyFields & DatabaseFields::Altitude)
0510     {
0511         values << d->altitude;
0512     }
0513 
0514     if (d->dirtyFields & DatabaseFields::PositionOrientation)
0515     {
0516         values << d->orientation;
0517     }
0518 
0519     if (d->dirtyFields & DatabaseFields::PositionTilt)
0520     {
0521         values << d->tilt;
0522     }
0523 
0524     if (d->dirtyFields & DatabaseFields::PositionRoll)
0525     {
0526         values << d->roll;
0527     }
0528 
0529     if (d->dirtyFields & DatabaseFields::PositionAccuracy)
0530     {
0531         values << d->accuracy;
0532     }
0533 
0534     if (d->dirtyFields & DatabaseFields::PositionDescription)
0535     {
0536         values << d->description;
0537     }
0538 
0539     if (d->empty)
0540     {
0541         CoreDbAccess().db()->addItemPosition(d->imageId, values, d->dirtyFields);
0542         d->empty = false;
0543     }
0544     else
0545     {
0546         CoreDbAccess().db()->changeItemPosition(d->imageId, values, d->dirtyFields);
0547     }
0548 
0549     d->dirtyFields = DatabaseFields::ItemPositionsNone;
0550 }
0551 
0552 void ItemPosition::remove()
0553 {
0554     CoreDbAccess().db()->removeItemPosition(d->imageId);
0555     d->resetData();
0556 }
0557 
0558 void ItemPosition::removeAltitude()
0559 {
0560     CoreDbAccess().db()->removeItemPositionAltitude(d->imageId);
0561     d->dirtyFields &= ~DatabaseFields::Altitude;
0562     d->altitude     = QVariant();
0563 }
0564 
0565 } // namespace Digikam