File indexing completed on 2025-03-09 03:50:39

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-09-19
0007  * Description : Geolocation data container.
0008  *
0009  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #ifndef DIGIKAM_GEO_DATA_CONTAINER_H
0016 #define DIGIKAM_GEO_DATA_CONTAINER_H
0017 
0018 // Qt includes
0019 
0020 #include <QStringList>
0021 #include <QMetaType>
0022 
0023 namespace DigikamGenericGeolocationEditPlugin
0024 {
0025 
0026 class GeoDataContainer
0027 {
0028 public:
0029 
0030     GeoDataContainer()
0031         : m_interpolated(false),
0032           m_altitude    (0.0),
0033           m_latitude    (0.0),
0034           m_longitude   (0.0)
0035     {
0036     };
0037 
0038     GeoDataContainer(double altitude,
0039                      double latitude,
0040                      double longitude,
0041                      bool interpolated)
0042         : m_interpolated(interpolated),
0043           m_altitude    (altitude),
0044           m_latitude    (latitude),
0045           m_longitude   (longitude)
0046     {
0047     };
0048 
0049     ~GeoDataContainer()
0050     {
0051     };
0052 
0053     GeoDataContainer(const GeoDataContainer& data)
0054     {
0055         m_interpolated = data.isInterpolated();
0056         m_altitude     = data.altitude();
0057         m_latitude     = data.latitude();
0058         m_longitude    = data.longitude();
0059     };
0060 
0061     GeoDataContainer& operator=(const GeoDataContainer& data)
0062     {
0063         m_interpolated = data.isInterpolated();
0064         m_altitude     = data.altitude();
0065         m_latitude     = data.latitude();
0066         m_longitude    = data.longitude();
0067 
0068         return *this;
0069     };
0070 
0071     // use this instead of '==', because '==' implies having the
0072     // same value for m_interpolated
0073 
0074     bool sameCoordinatesAs(const GeoDataContainer& a) const
0075     {
0076         return (
0077                 (a.m_altitude  == m_altitude) &&
0078                 (a.m_latitude  == m_latitude) &&
0079                 (a.m_longitude == m_longitude)
0080                );
0081     }
0082 
0083     void setInterpolated(bool ite)  { m_interpolated = ite; };
0084     void setAltitude(double alt)    { m_altitude     = alt; };
0085     void setLatitude(double lat)    { m_latitude     = lat; };
0086     void setLongitude(double lng)   { m_longitude    = lng; };
0087 
0088     bool   isInterpolated() const   { return m_interpolated; };
0089     double altitude()       const   { return m_altitude;     };
0090     double latitude()       const   { return m_latitude;     };
0091     double longitude()      const   { return m_longitude;    };
0092 
0093     QString altitudeString()  const { return QString::number(m_altitude,  'g', 12); }
0094     QString latitudeString()  const { return QString::number(m_latitude,  'g', 12); }
0095     QString longitudeString() const { return QString::number(m_longitude, 'g', 12); }
0096 
0097     QString geoUrl() const
0098     {
0099         return QString::fromLatin1("geo:%1,%2,%3")
0100                                    .arg(latitudeString())
0101                                    .arg(longitudeString())
0102                                    .arg(altitudeString());
0103     }
0104 
0105     static GeoDataContainer fromGeoUrl(const QString& url, bool* const parsedOkay)
0106     {
0107         // parse geo:-uri according to (only partially implemented):
0108         // https://tools.ietf.org/html/draft-ietf-geopriv-geo-uri-04
0109         // TODO: verify that we follow the spec fully!
0110 
0111         if (!url.startsWith(QLatin1String("geo:")))
0112         {
0113             // TODO: error
0114 
0115             if (parsedOkay)
0116             {
0117                 *parsedOkay = false;
0118             }
0119 
0120             return GeoDataContainer();
0121         }
0122 
0123         const QStringList parts = url.mid(4).split(QLatin1Char(','));
0124 
0125         GeoDataContainer position;
0126 
0127         if ((parts.size() == 3) || (parts.size() == 2))
0128         {
0129             bool okay          = true;
0130             double ptLongitude = 0.0;
0131             double ptAltitude  = 0.0;
0132             double ptLatitude  = parts[0].toDouble(&okay);
0133 
0134             if (okay)
0135             {
0136                 ptLongitude = parts[1].toDouble(&okay);
0137             }
0138 
0139             if (okay && (parts.size() == 3))
0140             {
0141                 ptAltitude = parts[2].toDouble(&okay);
0142             }
0143 
0144             if (!okay)
0145             {
0146                 *parsedOkay = false;
0147 
0148                 return GeoDataContainer();
0149             }
0150 
0151             position = GeoDataContainer(ptAltitude, ptLatitude, ptLongitude, false);
0152         }
0153         else
0154         {
0155             if (parsedOkay)
0156             {
0157                 *parsedOkay = false;
0158             }
0159 
0160             return GeoDataContainer();
0161         }
0162 
0163         if (parsedOkay)
0164         {
0165             *parsedOkay = true;
0166         }
0167 
0168         return position;
0169     }
0170 
0171 private:
0172 
0173     bool   m_interpolated;
0174 
0175     double m_altitude;
0176     double m_latitude;
0177     double m_longitude;
0178 };
0179 
0180 } // namespace DigikamGenericGeolocationEditPlugin
0181 
0182 Q_DECLARE_METATYPE(DigikamGenericGeolocationEditPlugin::GeoDataContainer)
0183 
0184 #endif // DIGIKAM_GEO_DATA_CONTAINER_H