1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2013-02-25
7 * Description : Table view column helpers: Geographic columns
8 *
9 * Copyright (C) 2017-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2013 by Michael G. Hansen <mike at mghansen dot de>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option) 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 "tableview_column_geo.h"
25
26 // Qt includes
27
28 #include <QFormLayout>
29 #include <QComboBox>
30 #include <QLocale>
31
32 // KDE includes
33
34 #include <klocalizedstring.h>
35
36 // Local includes
37
38 #include "digikam_debug.h"
39 #include "iteminfo.h"
40
41 namespace
42 {
43
FormatAltitude(const qreal altitudeInMeters,const QLocale::MeasurementSystem & measureSystem)44 QString FormatAltitude(const qreal altitudeInMeters, const QLocale::MeasurementSystem& measureSystem)
45 {
46 if (measureSystem == QLocale::MetricSystem)
47 {
48 const QString altitudeInMetersString = QLocale().toString(altitudeInMeters);
49
50 return QString::fromUtf8("%1 m").arg(altitudeInMetersString);
51 }
52 else
53 {
54 const qreal altitudeInFeet = altitudeInMeters /* m */ / ( 0.3048 /* m/foot */ );
55 const QString altitudeInFeetString = QLocale().toString(altitudeInFeet, 'g', 2);
56
57 return QString::fromUtf8("%1 ft").arg(altitudeInFeetString);
58 }
59 }
60
61 } // namespace
62
63 namespace Digikam
64 {
65
66 namespace TableViewColumns
67 {
68
ColumnGeoProperties(TableViewShared * const tableViewShared,const TableViewColumnConfiguration & pConfiguration,const SubColumn pSubColumn,QObject * const parent)69 ColumnGeoProperties::ColumnGeoProperties(TableViewShared* const tableViewShared,
70 const TableViewColumnConfiguration& pConfiguration,
71 const SubColumn pSubColumn,
72 QObject* const parent)
73 : TableViewColumn(tableViewShared, pConfiguration, parent),
74 subColumn (pSubColumn)
75 {
76 }
77
~ColumnGeoProperties()78 ColumnGeoProperties::~ColumnGeoProperties()
79 {
80 }
81
getSubColumns()82 QStringList ColumnGeoProperties::getSubColumns()
83 {
84 QStringList columns;
85 columns << QLatin1String("geohascoordinates")
86 << QLatin1String("geocoordinates")
87 << QLatin1String("geoaltitude");
88
89 return columns;
90 }
91
getDescription()92 TableViewColumnDescription ColumnGeoProperties::getDescription()
93 {
94 TableViewColumnDescription description(QLatin1String("geo-properties"), i18n("Geo properties"));
95 description.setIcon(QLatin1String("globe"));
96 description.addSubColumn(TableViewColumnDescription(QLatin1String("geohascoordinates"), i18n("Geotagged")));
97 description.addSubColumn(TableViewColumnDescription(QLatin1String("geocoordinates"), i18n("Coordinates")));
98 description.addSubColumn(TableViewColumnDescription(QLatin1String("geoaltitude"), i18n("Altitude")));
99
100 return description;
101 }
102
getTitle() const103 QString ColumnGeoProperties::getTitle() const
104 {
105 switch (subColumn)
106 {
107 case SubColumnHasCoordinates:
108 {
109 return i18n("Geotagged");
110 }
111
112 case SubColumnCoordinates:
113 {
114 return i18n("Coordinates");
115 }
116
117 case SubColumnAltitude:
118 {
119 return i18n("Altitude");
120 }
121 }
122
123 return QString();
124 }
125
getColumnFlags() const126 TableViewColumn::ColumnFlags ColumnGeoProperties::getColumnFlags() const
127 {
128 ColumnFlags flags(ColumnNoFlags);
129
130 if (subColumn == SubColumnAltitude)
131 {
132 flags |= (ColumnCustomSorting | ColumnHasConfigurationWidget);
133 }
134
135 return flags;
136 }
137
data(TableViewModel::Item * const item,const int role) const138 QVariant ColumnGeoProperties::data(TableViewModel::Item* const item, const int role) const
139 {
140 if (
141 (role != Qt::DisplayRole) &&
142 (role != Qt::TextAlignmentRole)
143 )
144 {
145 return QVariant();
146 }
147
148 if (role == Qt::TextAlignmentRole)
149 {
150 switch (subColumn)
151 {
152 case SubColumnAltitude:
153 {
154 return QVariant(Qt::Alignment(Qt::AlignRight | Qt::AlignVCenter));
155 }
156
157 default:
158 {
159 return QVariant();
160 }
161 }
162 }
163
164 const ItemInfo info = s->tableViewModel->infoFromItem(item);
165
166 switch (subColumn)
167 {
168 case SubColumnHasCoordinates:
169 {
170 return info.hasCoordinates() ? i18nc("@info: tableview", "Yes") : i18nc("@info: tableview", "No");
171 }
172
173 case SubColumnCoordinates:
174 {
175 if (!info.hasCoordinates())
176 {
177 return QString();
178 }
179
180 return QString::fromUtf8("%1\n%2").arg(QLocale().toString(info.latitudeNumber(), 'g', 7))
181 .arg(QLocale().toString(info.longitudeNumber(), 'g', 7));
182 }
183
184 case SubColumnAltitude:
185 {
186 /// @todo Needs custom sorting
187
188 if ((!info.hasCoordinates()) || (!info.hasAltitude()))
189 {
190 return QString();
191 }
192
193 /// @todo Use an enum instead to avoid lots of string comparisons
194
195 const QString formatKey = configuration.getSetting(QLatin1String("format"), QLatin1String("metric"));
196 QLocale::MeasurementSystem measureSystem = QLocale().measurementSystem();
197
198 if (formatKey == QLatin1String("metric"))
199 {
200 measureSystem = QLocale::MetricSystem;
201 }
202 else if (formatKey == QLatin1String("imperial"))
203 {
204 measureSystem = QLocale::ImperialSystem;
205 }
206
207 const QString formattedAltitude = FormatAltitude(info.altitudeNumber(), measureSystem);
208
209 return formattedAltitude;
210 }
211 }
212
213 return QVariant();
214 }
215
compare(TableViewModel::Item * const itemA,TableViewModel::Item * const itemB) const216 TableViewColumn::ColumnCompareResult ColumnGeoProperties::compare(TableViewModel::Item* const itemA,
217 TableViewModel::Item* const itemB) const
218 {
219 const ItemInfo infoA = s->tableViewModel->infoFromItem(itemA);
220 const ItemInfo infoB = s->tableViewModel->infoFromItem(itemB);
221
222 if (subColumn == SubColumnAltitude)
223 {
224 const bool hasAltitudeA = infoA.hasAltitude();
225 const bool hasAltitudeB = infoB.hasAltitude();
226
227 if (hasAltitudeA && hasAltitudeB)
228 {
229 const double altitudeA = infoA.altitudeNumber();
230 const double altitudeB = infoB.altitudeNumber();
231
232 return (compareHelper<double>(altitudeA, altitudeB));
233 }
234
235 return (compareHelper<int>(int(hasAltitudeA), int(hasAltitudeB)));
236 }
237
238 qCWarning(DIGIKAM_GENERAL_LOG) << "geo: unimplemented comparison, subColumn=" << subColumn;
239
240 return CmpEqual;
241 }
242
getConfigurationWidget(QWidget * const parentWidget) const243 TableViewColumnConfigurationWidget* ColumnGeoProperties::getConfigurationWidget(QWidget* const parentWidget) const
244 {
245 TableViewColumnConfiguration myConfiguration = getConfiguration();
246
247 return (new ColumnGeoConfigurationWidget(s, myConfiguration, parentWidget));
248 }
249
250 // ----------------------------------------------------------------------------------------------------------------
251
ColumnGeoConfigurationWidget(TableViewShared * const sharedObject,const TableViewColumnConfiguration & columnConfiguration,QWidget * const parentWidget)252 ColumnGeoConfigurationWidget::ColumnGeoConfigurationWidget(TableViewShared* const sharedObject,
253 const TableViewColumnConfiguration& columnConfiguration,
254 QWidget* const parentWidget)
255 : TableViewColumnConfigurationWidget(sharedObject, columnConfiguration, parentWidget),
256 subColumn(ColumnGeoProperties::SubColumnHasCoordinates),
257 selectorAltitudeUnit(nullptr)
258 {
259 ColumnGeoProperties::getSubColumnIndex<ColumnGeoProperties>(configuration.columnId, &subColumn);
260
261 switch (subColumn)
262 {
263 case ColumnGeoProperties::SubColumnAltitude:
264 {
265 QFormLayout* const box1 = new QFormLayout();
266 selectorAltitudeUnit = new QComboBox(this);
267 selectorAltitudeUnit->addItem(i18n("Metric units"), QLatin1String("metric"));
268 selectorAltitudeUnit->addItem(i18n("Imperial units"), QLatin1String("imperial"));
269 box1->addRow(i18n("Display format"), selectorAltitudeUnit);
270
271 setLayout(box1);
272
273 const int index = selectorAltitudeUnit->findData(configuration.getSetting(QLatin1String("format"), QLatin1String("metric")));
274 selectorAltitudeUnit->setCurrentIndex((index >= 0) ? index : 0);
275 break;
276 }
277
278 default:
279 {
280 break;
281 }
282 }
283 }
284
~ColumnGeoConfigurationWidget()285 ColumnGeoConfigurationWidget::~ColumnGeoConfigurationWidget()
286 {
287 }
288
getNewConfiguration()289 TableViewColumnConfiguration ColumnGeoConfigurationWidget::getNewConfiguration()
290 {
291 const QString formatKey = selectorAltitudeUnit->itemData(selectorAltitudeUnit->currentIndex()).toString();
292 configuration.columnSettings.insert(QLatin1String("format"), formatKey);
293
294 return configuration;
295 }
296
setConfiguration(const TableViewColumnConfiguration & newConfiguration)297 void ColumnGeoProperties::setConfiguration(const TableViewColumnConfiguration& newConfiguration)
298 {
299 configuration = newConfiguration;
300
301 emit signalAllDataChanged();
302 }
303
304 } // namespace TableViewColumns
305
306 } // namespace Digikam
307