KFileMetaData

formatstrings.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Alexander Stippich <a.stippich@gmx.net>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#include "formatstrings_p.h"
8
9#include <math.h>
10#include <QDateTime>
11#include <KLocalizedString>
12#include <KFormat>
13
14using namespace KFileMetaData;
15
16/*
17 * Calculates and returns the number of digits after the
18 * comma to always show three significant digits for use
19 * with KFormat::formatValue.
20 */
21int threeSignificantDigits(int value)
22{
23 if (value == 0) {
24 return 0;
25 }
26 int before_decimal_point = static_cast<int>(log10(value > 0 ? value : -value)) % 3;
27 return 2 - before_decimal_point;
28}
29
30QString FormatStrings::toStringFunction(const QVariant& value)
31{
32 return value.toString();
33}
34
35QString FormatStrings::formatDouble(const QVariant& value)
36{
37 return QLocale().toString(value.toDouble(),'g',3);
38}
39
40QString FormatStrings::formatDate(const QVariant& value)
41{
42 KFormat form;
43 QDateTime dt;
44 if (value.userType() == QMetaType::QDateTime) {
45 dt = value.toDateTime();
46 } else {
48 }
49 if (dt.isValid()) {
51 }
52 return QString();
53}
54
55QString FormatStrings::formatDuration(const QVariant& value)
56{
57 KFormat form;
58 return form.formatDuration(value.toInt() * 1000);
59}
60
61QString FormatStrings::formatBitRate(const QVariant& value)
62{
63 KFormat form;
64 return i18nc("@label bitrate (per second)", "%1/s", form.formatValue(value.toInt(),
65 KFormat::Unit::Bit, threeSignificantDigits(value.toInt()), KFormat::UnitPrefix::AutoAdjust, KFormat::MetricBinaryDialect));
66}
67
68QString FormatStrings::formatSampleRate(const QVariant& value)
69{
70 KFormat form;
71 return form.formatValue(value.toInt(), KFormat::Unit::Hertz, threeSignificantDigits(value.toInt()), KFormat::UnitPrefix::AutoAdjust, KFormat::MetricBinaryDialect);
72}
73
74QString FormatStrings::formatOrientationValue(const QVariant& value)
75{
76 QString string;
77 switch (value.toInt()) {
78 case 1: string = i18nc("Description of image orientation", "Unchanged"); break;
79 case 2: string = i18nc("Description of image orientation", "Horizontally flipped"); break;
80 case 3: string = i18nc("Description of image orientation", "180° rotated"); break;
81 case 4: string = i18nc("Description of image orientation", "Vertically flipped"); break;
82 case 5: string = i18nc("Description of image orientation", "Transposed"); break;
83 case 6: string = i18nc("Description of image orientation, counter clock-wise rotated", "90° rotated CCW "); break;
84 case 7: string = i18nc("Description of image orientation", "Transversed"); break;
85 case 8: string = i18nc("Description of image orientation, counter clock-wise rotated", "270° rotated CCW"); break;
86 default:
87 break;
88 }
89 return string;
90}
91
92QString FormatStrings::formatPhotoFlashValue(const QVariant& value)
93{
94 // copied from exiv2 tags_int.cpp
95 const QMap<int, QString> flashTranslation = {
96 { 0x00, i18nc("Description of photo flash", "No flash") },
97 { 0x01, i18nc("Description of photo flash", "Fired") },
98 { 0x05, i18nc("Description of photo flash", "Fired, return light not detected") },
99 { 0x07, i18nc("Description of photo flash", "Fired, return light detected") },
100 { 0x08, i18nc("Description of photo flash", "Yes, did not fire") },
101 { 0x09, i18nc("Description of photo flash", "Yes, compulsory") },
102 { 0x0d, i18nc("Description of photo flash", "Yes, compulsory, return light not detected") },
103 { 0x0f, i18nc("Description of photo flash", "Yes, compulsory, return light detected") },
104 { 0x10, i18nc("Description of photo flash", "No, compulsory") },
105 { 0x14, i18nc("Description of photo flash", "No, did not fire, return light not detected") },
106 { 0x18, i18nc("Description of photo flash", "No, auto") },
107 { 0x19, i18nc("Description of photo flash", "Yes, auto") },
108 { 0x1d, i18nc("Description of photo flash", "Yes, auto, return light not detected") },
109 { 0x1f, i18nc("Description of photo flash", "Yes, auto, return light detected") },
110 { 0x20, i18nc("Description of photo flash", "No flash function") },
111 { 0x30, i18nc("Description of photo flash", "No, no flash function") },
112 { 0x41, i18nc("Description of photo flash", "Yes, red-eye reduction") },
113 { 0x45, i18nc("Description of photo flash", "Yes, red-eye reduction, return light not detected") },
114 { 0x47, i18nc("Description of photo flash", "Yes, red-eye reduction, return light detected") },
115 { 0x49, i18nc("Description of photo flash", "Yes, compulsory, red-eye reduction") },
116 { 0x4d, i18nc("Description of photo flash", "Yes, compulsory, red-eye reduction, return light not detected") },
117 { 0x4f, i18nc("Description of photo flash", "Yes, compulsory, red-eye reduction, return light detected") },
118 { 0x50, i18nc("Description of photo flash", "No, red-eye reduction") },
119 { 0x58, i18nc("Description of photo flash", "No, auto, red-eye reduction") },
120 { 0x59, i18nc("Description of photo flash", "Yes, auto, red-eye reduction") },
121 { 0x5d, i18nc("Description of photo flash", "Yes, auto, red-eye reduction, return light not detected") },
122 { 0x5f, i18nc("Description of photo flash", "Yes, auto, red-eye reduction, return light detected") }
123 };
124 if (flashTranslation.contains(value.toInt())) {
125 return flashTranslation.value(value.toInt());
126 } else {
127 return i18n("Unknown");
128 }
129
130}
131
132QString FormatStrings::formatAsDegree(const QVariant& value)
133{
134 return i18nc("Symbol of degree, no space", "%1°", QLocale().toString(value.toDouble()));
135}
136
137QString FormatStrings::formatAsMeter(const QVariant& value)
138{
139 KFormat form;
140 return form.formatValue(value.toDouble(), KFormat::Unit::Meter, 1, KFormat::UnitPrefix::AutoAdjust, KFormat::MetricBinaryDialect);
141}
142
143QString FormatStrings::formatAsMilliMeter(const QVariant& value)
144{
145 return i18nc("Focal length given in mm", "%1 mm", QLocale().toString(value.toDouble(), 'g', 3));
146}
147
148QString FormatStrings::formatAsFrameRate(const QVariant& value)
149{
150 return i18nc("Symbol of frames per second, with space", "%1 fps", QLocale().toString(round(value.toDouble() * 100) / 100));
151}
152
153QString FormatStrings::formatPhotoTime(const QVariant& value)
154{
155 auto val = value.toDouble();
156 if (val < 0.3 && !qFuzzyIsNull(val)) {
157 auto reciprocal = 1.0/val;
158 auto roundedReciprocal = round(reciprocal);
159 if (abs(reciprocal - roundedReciprocal) < 1e-3) {
160 return i18nc("Time period given in seconds as rational number, denominator is given", "1/%1 s", roundedReciprocal);
161 }
162 }
163 return i18nc("Time period given in seconds", "%1 s", QLocale().toString(value.toDouble(), 'g', 3));
164}
165
166QString FormatStrings::formatPhotoExposureBias(const QVariant& value)
167{
168 QLocale locale;
169 auto val = value.toDouble();
170 /*
171 * Exposure values are mostly in steps of one half or third.
172 * Try to construct a rational number from it.
173 * Output as double when it is not possible.
174 */
175 auto sixthParts = val * 6;
176 int roundedSixthParts = static_cast<int>(round(sixthParts));
177 int fractional = roundedSixthParts % 6;
178 if (fractional == 0 || abs(sixthParts - roundedSixthParts) > 1e-3) {
179 return i18nc("Exposure bias/compensation in exposure value (EV)", "%1 EV", locale.toString(val, 'g', 3));
180 }
181 int integral = roundedSixthParts / 6;
182 int nominator = fractional;
183 int denominator = 6;
184 if (nominator % 2 == 0) {
185 nominator = nominator / 2;
186 denominator = denominator / 2;
187 } else if (nominator % 3 == 0) {
188 nominator = nominator / 3;
189 denominator = denominator / 3;
190 }
191 if (integral != 0) {
192 return i18nc("Exposure compensation given as integral with fraction, in exposure value (EV)",
193 "%1 %2/%3 EV", locale.toString(integral), locale.toString(abs(nominator)), locale.toString(denominator));
194 }
195 return i18nc("Exposure compensation given as rational, in exposure value (EV)",
196 "%1/%2 EV", locale.toString(nominator), locale.toString(denominator));
197}
198
199QString FormatStrings::formatAspectRatio(const QVariant& value)
200{
201 return i18nc("Aspect ratio, normalized to one", "%1:1", QLocale().toString(round(value.toDouble() * 100) / 100));
202}
203
204QString FormatStrings::formatAsFNumber(const QVariant& value)
205{
206 return i18nc("F number for photographs", "f/%1", QLocale().toString(value.toDouble(), 'g', 2));
207}
QString formatRelativeDateTime(const QDateTime &dateTime, QLocale::FormatType format) const
QString formatDuration(quint64 msecs, KFormat::DurationFormatOptions options=KFormat::DefaultDuration) const
QString formatValue(double value, const QString &unit, int precision, KFormat::UnitPrefix prefix, KFormat::BinaryUnitDialect dialect) const
MetricBinaryDialect
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
bool isValid() const const
QString toString(QDate date, FormatType format) const const
bool contains(const Key &key) const const
T value(const Key &key, const T &defaultValue) const const
QDateTime toDateTime() const const
double toDouble(bool *ok) const const
int toInt(bool *ok) const const
QString toString() const const
int userType() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:54 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.