File indexing completed on 2025-01-19 03:50:48

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2013-02-25
0007  * Description : Table view column helpers: Geographic columns
0008  *
0009  * SPDX-FileCopyrightText: 2017-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2013      by Michael G. Hansen <mike at mghansen dot de>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "tableview_column_geo.h"
0017 
0018 // Qt includes
0019 
0020 #include <QFormLayout>
0021 #include <QComboBox>
0022 #include <QLocale>
0023 
0024 // KDE includes
0025 
0026 #include <klocalizedstring.h>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 #include "iteminfo.h"
0032 
0033 namespace
0034 {
0035 
0036 QString FormatAltitude(const qreal altitudeInMeters, const QLocale::MeasurementSystem& measureSystem)
0037 {
0038     if (measureSystem == QLocale::MetricSystem)
0039     {
0040         const QString altitudeInMetersString = QLocale().toString(altitudeInMeters);
0041 
0042         return QString::fromUtf8("%1 m").arg(altitudeInMetersString);
0043     }
0044     else
0045     {
0046         const qreal altitudeInFeet         = altitudeInMeters /* m */ / ( 0.3048 /* m/foot */ );
0047         const QString altitudeInFeetString = QLocale().toString(altitudeInFeet, 'g', 2);
0048 
0049         return QString::fromUtf8("%1 ft").arg(altitudeInFeetString);
0050     }
0051 }
0052 
0053 } // namespace
0054 
0055 namespace Digikam
0056 {
0057 
0058 namespace TableViewColumns
0059 {
0060 
0061 ColumnGeoProperties::ColumnGeoProperties(TableViewShared* const tableViewShared,
0062                                          const TableViewColumnConfiguration& pConfiguration,
0063                                          const SubColumn pSubColumn,
0064                                          QObject* const parent)
0065     : TableViewColumn(tableViewShared, pConfiguration, parent),
0066       subColumn      (pSubColumn)
0067 {
0068 }
0069 
0070 ColumnGeoProperties::~ColumnGeoProperties()
0071 {
0072 }
0073 
0074 QStringList ColumnGeoProperties::getSubColumns()
0075 {
0076     QStringList columns;
0077     columns << QLatin1String("geohascoordinates")
0078             << QLatin1String("geocoordinates")
0079             << QLatin1String("geoaltitude");
0080 
0081     return columns;
0082 }
0083 
0084 TableViewColumnDescription ColumnGeoProperties::getDescription()
0085 {
0086     TableViewColumnDescription description(QLatin1String("geo-properties"), i18n("Geo properties"));
0087     description.setIcon(QLatin1String("globe"));
0088     description.addSubColumn(TableViewColumnDescription(QLatin1String("geohascoordinates"), i18n("Geotagged")));
0089     description.addSubColumn(TableViewColumnDescription(QLatin1String("geocoordinates"),    i18n("Coordinates")));
0090     description.addSubColumn(TableViewColumnDescription(QLatin1String("geoaltitude"),       i18n("Altitude")));
0091 
0092     return description;
0093 }
0094 
0095 QString ColumnGeoProperties::getTitle() const
0096 {
0097     switch (subColumn)
0098     {
0099         case SubColumnHasCoordinates:
0100         {
0101             return i18n("Geotagged");
0102         }
0103 
0104         case SubColumnCoordinates:
0105         {
0106             return i18n("Coordinates");
0107         }
0108 
0109         case SubColumnAltitude:
0110         {
0111             return i18n("Altitude");
0112         }
0113     }
0114 
0115     return QString();
0116 }
0117 
0118 TableViewColumn::ColumnFlags ColumnGeoProperties::getColumnFlags() const
0119 {
0120     ColumnFlags flags(ColumnNoFlags);
0121 
0122     if (subColumn == SubColumnAltitude)
0123     {
0124         flags |= (ColumnCustomSorting | ColumnHasConfigurationWidget);
0125     }
0126 
0127     return flags;
0128 }
0129 
0130 QVariant ColumnGeoProperties::data(TableViewModel::Item* const item, const int role) const
0131 {
0132     if (
0133         (role != Qt::DisplayRole) &&
0134         (role != Qt::TextAlignmentRole)
0135        )
0136     {
0137         return QVariant();
0138     }
0139 
0140     if (role == Qt::TextAlignmentRole)
0141     {
0142         switch (subColumn)
0143         {
0144             case SubColumnAltitude:
0145             {
0146                 return QVariant(Qt::Alignment(Qt::AlignRight | Qt::AlignVCenter));
0147             }
0148 
0149             default:
0150             {
0151                 return QVariant();
0152             }
0153         }
0154     }
0155 
0156     const ItemInfo info = s->tableViewModel->infoFromItem(item);
0157 
0158     switch (subColumn)
0159     {
0160         case SubColumnHasCoordinates:
0161         {
0162             return info.hasCoordinates() ? i18nc("@info: tableview", "Yes") : i18nc("@info: tableview", "No");
0163         }
0164 
0165         case SubColumnCoordinates:
0166         {
0167             if (!info.hasCoordinates())
0168             {
0169                 return QString();
0170             }
0171 
0172             return QString::fromUtf8("%1\n%2").arg(QLocale().toString(info.latitudeNumber(),  'g', 7))
0173                                               .arg(QLocale().toString(info.longitudeNumber(), 'g', 7));
0174         }
0175 
0176         case SubColumnAltitude:
0177         {
0178             /// @todo Needs custom sorting
0179 
0180             if ((!info.hasCoordinates()) || (!info.hasAltitude()))
0181             {
0182                 return QString();
0183             }
0184 
0185             /// @todo Use an enum instead to avoid lots of string comparisons
0186 
0187             const QString formatKey                  = configuration.getSetting(QLatin1String("format"), QLatin1String("metric"));
0188             QLocale::MeasurementSystem measureSystem = QLocale().measurementSystem();
0189 
0190             if      (formatKey == QLatin1String("metric"))
0191             {
0192                 measureSystem = QLocale::MetricSystem;
0193             }
0194             else if (formatKey == QLatin1String("imperial"))
0195             {
0196                 measureSystem = QLocale::ImperialSystem;
0197             }
0198 
0199             const QString formattedAltitude = FormatAltitude(info.altitudeNumber(), measureSystem);
0200 
0201             return formattedAltitude;
0202         }
0203     }
0204 
0205     return QVariant();
0206 }
0207 
0208 TableViewColumn::ColumnCompareResult ColumnGeoProperties::compare(TableViewModel::Item* const itemA,
0209                                                                   TableViewModel::Item* const itemB) const
0210 {
0211     const ItemInfo infoA = s->tableViewModel->infoFromItem(itemA);
0212     const ItemInfo infoB = s->tableViewModel->infoFromItem(itemB);
0213 
0214     if (subColumn == SubColumnAltitude)
0215     {
0216         const bool hasAltitudeA = infoA.hasAltitude();
0217         const bool hasAltitudeB = infoB.hasAltitude();
0218 
0219         if (hasAltitudeA && hasAltitudeB)
0220         {
0221             const double altitudeA = infoA.altitudeNumber();
0222             const double altitudeB = infoB.altitudeNumber();
0223 
0224             return (compareHelper<double>(altitudeA, altitudeB));
0225         }
0226 
0227         return (compareHelper<int>(int(hasAltitudeA), int(hasAltitudeB)));
0228     }
0229 
0230     qCWarning(DIGIKAM_GENERAL_LOG) << "geo: unimplemented comparison, subColumn=" << subColumn;
0231 
0232     return CmpEqual;
0233 }
0234 
0235 TableViewColumnConfigurationWidget* ColumnGeoProperties::getConfigurationWidget(QWidget* const parentWidget) const
0236 {
0237     TableViewColumnConfiguration myConfiguration = getConfiguration();
0238 
0239     return (new ColumnGeoConfigurationWidget(s, myConfiguration, parentWidget));
0240 }
0241 
0242 // ----------------------------------------------------------------------------------------------------------------
0243 
0244 ColumnGeoConfigurationWidget::ColumnGeoConfigurationWidget(TableViewShared* const sharedObject,
0245                                                            const TableViewColumnConfiguration& columnConfiguration,
0246                                                            QWidget* const parentWidget)
0247     : TableViewColumnConfigurationWidget(sharedObject, columnConfiguration, parentWidget),
0248       subColumn(ColumnGeoProperties::SubColumnHasCoordinates),
0249       selectorAltitudeUnit(nullptr)
0250 {
0251     ColumnGeoProperties::getSubColumnIndex<ColumnGeoProperties>(configuration.columnId, &subColumn);
0252 
0253     switch (subColumn)
0254     {
0255         case ColumnGeoProperties::SubColumnAltitude:
0256         {
0257             QFormLayout* const box1 = new QFormLayout();
0258             selectorAltitudeUnit    = new QComboBox(this);
0259             selectorAltitudeUnit->addItem(i18n("Metric units"),   QLatin1String("metric"));
0260             selectorAltitudeUnit->addItem(i18n("Imperial units"), QLatin1String("imperial"));
0261             box1->addRow(i18n("Display format"), selectorAltitudeUnit);
0262 
0263             setLayout(box1);
0264 
0265             const int index = selectorAltitudeUnit->findData(configuration.getSetting(QLatin1String("format"), QLatin1String("metric")));
0266             selectorAltitudeUnit->setCurrentIndex((index >= 0) ? index : 0);
0267             break;
0268         }
0269 
0270         default:
0271         {
0272             break;
0273         }
0274     }
0275 }
0276 
0277 ColumnGeoConfigurationWidget::~ColumnGeoConfigurationWidget()
0278 {
0279 }
0280 
0281 TableViewColumnConfiguration ColumnGeoConfigurationWidget::getNewConfiguration()
0282 {
0283     const QString formatKey = selectorAltitudeUnit->itemData(selectorAltitudeUnit->currentIndex()).toString();
0284     configuration.columnSettings.insert(QLatin1String("format"), formatKey);
0285 
0286     return configuration;
0287 }
0288 
0289 void ColumnGeoProperties::setConfiguration(const TableViewColumnConfiguration& newConfiguration)
0290 {
0291     configuration = newConfiguration;
0292 
0293     Q_EMIT signalAllDataChanged();
0294 }
0295 
0296 } // namespace TableViewColumns
0297 
0298 } // namespace Digikam
0299 
0300 #include "moc_tableview_column_geo.cpp"