Cutelee 6.1.0
l10n_filesize.cpp
1/*
2 * This file is part of the Cutelee template system.
3 *
4 * Copyright (c) 2020 Matthias Fehring <mf@huessenbergnetz.de>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "l10n_filesize.h"
21
22#include "abstractlocalizer.h"
23#include "engine.h"
24#include "exception.h"
25#include "parser.h"
26#include "template.h"
27#include "util.h"
28
29#include <limits>
30
31L10nFileSizeNodeFactory::L10nFileSizeNodeFactory() {}
32
34{
35 QStringList parts = smartSplit(tagContent);
36 parts.removeFirst(); // not interested in the name of the tag
37 if (parts.isEmpty()) {
38 throw Exception(TagSyntaxError, QStringLiteral("Error: l10n_filesize requires at least the file size as first parameter"));
39 }
40
41 FilterExpression size(parts.at(0), p);
42
43 FilterExpression unitSystem;
44 if (parts.size() > 1) {
45 unitSystem = FilterExpression(parts.at(1), p);
46 }
47
48 FilterExpression precision;
49 if (parts.size() > 2) {
50 precision = FilterExpression(parts.at(2), p);
51 }
52
53 FilterExpression multiplier;
54 if (parts.size() > 3) {
55 multiplier = FilterExpression(parts.at(3), p);
56 }
57
58 return new L10nFileSizeNode(size, unitSystem, precision, multiplier, p);
59}
60
61L10nFileSizeVarNodeFactory::L10nFileSizeVarNodeFactory() {}
62
64{
65 QStringList parts = smartSplit(tagContent);
66 parts.removeFirst(); // not interested in the name of the tag
67 if (parts.size() < 2) {
68 throw Exception(TagSyntaxError, QStringLiteral("Error: l10n_filesize_var tag takes at least 2 arguments, the file size and the variable name"));
69 }
70
71 FilterExpression size(parts.at(0), p);
72
73 FilterExpression unitSystem;
74 if (parts.size() > 2) {
75 unitSystem = FilterExpression(parts.at(1), p);
76 }
77
78 FilterExpression precision;
79 if (parts.size() > 3) {
80 precision = FilterExpression(parts.at(2), p);
81 }
82
83 FilterExpression multiplier;
84 if (parts.size() > 4) {
85 multiplier = FilterExpression(parts.at(3), p);
86 }
87
88 auto resultName = parts.last();
89
90 return new L10nFileSizeVarNode(size, unitSystem, precision, multiplier, resultName, p);
91}
92
93L10nFileSizeNode::L10nFileSizeNode(const FilterExpression &size,
94 const FilterExpression &unitSystem,
95 const FilterExpression &precision,
96 const FilterExpression &multiplier,
97 QObject *parent)
98 : Node(parent), m_size(size), m_unitSystem(unitSystem), m_precision(precision), m_multiplier(multiplier)
99{
100}
101
103{
104 bool convertNumbers = true;
105
106 qreal size = 0.0f;
107 if (m_size.resolve(c).canConvert<qreal>()) {
108 size = m_size.resolve(c).toReal(&convertNumbers);
109 } else {
110 size = getSafeString(m_size.resolve(c)).get().toDouble(&convertNumbers);
111 }
112 if (!convertNumbers) {
113 qWarning("%s", "Failed to convert input file size into a floating point number.");
114 return;
115 }
116
117 int unitSystem = m_unitSystem.isValid() ? m_unitSystem.resolve(c).toInt(&convertNumbers) : 10;
118 if (!convertNumbers) {
119 qWarning("%s", "Failed to convert unit system for file size into integer value. Using default decimal system as default.");
120 unitSystem = 10;
121 }
122
123 int precision = m_precision.isValid() ? m_precision.resolve(c).toInt(&convertNumbers) : 2;
124 if (!convertNumbers) {
125 qWarning("%s", "Failed to convert decimal precision for file size into an integer value. Using default value 2.");
126 precision = 2;
127 }
128
129 qreal multiplier = m_multiplier.isValid() ? m_multiplier.resolve(c).toReal(&convertNumbers) : 1.0f;
130 if (!convertNumbers) {
131 qWarning("%s", "Failed to convert multiplier file size into a floating point number. Using default value 1.0.");
132 multiplier = 1.0f;
133 }
134
135 if (multiplier == 0.0f) {
136 qWarning("%s", "It makes no sense to multiply the file size by zero. Using default value 1.0.");
137 multiplier = 1.0f;
138 }
139
140 const qreal sizeMult = size * multiplier;
141
142 if (unitSystem == 10) {
143 if ((sizeMult > -1000) && (sizeMult < 1000)) {
144 precision = 0;
145 }
146 } else if (unitSystem == 2) {
147 if ((sizeMult > - 1024) && (sizeMult < 1024)) {
148 precision = 0;
149 }
150 }
151
152 QString resultString;
153
154#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
155 if (sizeMult > static_cast<qreal>(std::numeric_limits<qint64>::min()) && sizeMult < static_cast<qreal>(std::numeric_limits<qint64>::max())) {
156
157 QLocale l(c->localizer()->currentLocale());
158 QLocale::DataSizeFormats format = unitSystem == 10 ? QLocale::DataSizeSIFormat : QLocale::DataSizeIecFormat;
159
160 resultString = l.formattedDataSize(static_cast<qint64>(sizeMult), precision, format);
161
162 } else {
163#endif
164
165 const std::pair<qreal,QString> fspair = calcFileSize(size, unitSystem, multiplier);
166
167 if (precision == 2) {
168 resultString = c->localizer()->localizeNumber(fspair.first) + QChar(QChar::Space) + fspair.second;
169 } else {
170 QLocale l(c->localizer()->currentLocale());
171 resultString = l.toString(fspair.first, 'f', precision) + QChar(QChar::Space) + fspair.second;
172 }
173
174#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
175 }
176#endif
177
178 streamValueInContext(stream, resultString, c);
179}
180
181L10nFileSizeVarNode::L10nFileSizeVarNode(const FilterExpression &size,
182 const FilterExpression &unitSystem,
183 const FilterExpression &precision,
184 const FilterExpression &multiplier,
185 const QString &resultName, QObject *parent)
186 : Node(parent), m_size(size), m_unitSystem(unitSystem), m_precision(precision), m_multiplier(multiplier),
187 m_resultName(resultName)
188{
189}
190
192{
193 Q_UNUSED(stream)
194 bool convertNumbers = true;
195
196 qreal size = 0.0f;
197 if (m_size.resolve(c).canConvert<qreal>()) {
198 size = m_size.resolve(c).toReal(&convertNumbers);
199 } else {
200 size = getSafeString(m_size.resolve(c)).get().toDouble(&convertNumbers);
201 }
202 if (!convertNumbers) {
203 qWarning("%s", "Failed to convert input file size into a floating point number.");
204 return;
205 }
206
207 int unitSystem = m_unitSystem.isValid() ? m_unitSystem.resolve(c).toInt(&convertNumbers) : 10;
208 if (!convertNumbers) {
209 qWarning("%s", "Failed to convert unit system for file size into integer value. Using default decimal system.");
210 unitSystem = 10;
211 }
212
213 int precision = m_precision.isValid() ? m_precision.resolve(c).toInt(&convertNumbers) : 2;
214 if (!convertNumbers) {
215 qWarning("%s", "Failed to convert decimal precision for file size into an integer value. Using default value 2.");
216 precision = 2;
217 }
218
219 qreal multiplier = m_multiplier.isValid() ? m_multiplier.resolve(c).toReal(&convertNumbers) : 1.0f;
220 if (!convertNumbers) {
221 qWarning("%s", "Failed to convert multiplier file size into a floating point number. Using default value 1.0.");
222 multiplier = 1.0f;
223 }
224
225 if (multiplier == 0.0f) {
226 qWarning("%s", "It makes no sense to mulitply the file size by zero. Using default value 1.0.");
227 multiplier = 1.0f;
228 }
229
230 const double sizeMult = size * multiplier;
231
232 if (unitSystem == 10) {
233 if ((sizeMult > -1000) && (sizeMult < 1000)) {
234 precision = 0;
235 }
236 } else if (unitSystem == 2) {
237 if ((sizeMult > - 1024) && (sizeMult < 1024)) {
238 precision = 0;
239 }
240 }
241
242 QString resultString;
243
244#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
245 if (sizeMult > static_cast<qreal>(std::numeric_limits<qint64>::min()) && sizeMult < static_cast<qreal>(std::numeric_limits<qint64>::max())) {
246
247 QLocale l(c->localizer()->currentLocale());
248 QLocale::DataSizeFormats format = unitSystem == 10 ? QLocale::DataSizeSIFormat : QLocale::DataSizeIecFormat;
249
250 resultString = l.formattedDataSize(static_cast<qint64>(sizeMult), precision, format);
251
252 } else {
253#endif
254
255 const std::pair<qreal,QString> fspair = calcFileSize(size, unitSystem, multiplier);
256
257 if (precision == 2) {
258 resultString = c->localizer()->localizeNumber(fspair.first) + QChar(QChar::Space) + fspair.second;
259 } else {
260 QLocale l(c->localizer()->currentLocale());
261 resultString = l.toString(fspair.first, 'f', precision) + QChar(QChar::Space) + fspair.second;
262 }
263
264#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
265 }
266#endif
267
268 c->insert(m_resultName, resultString);
269}
Q_INVOKABLE QStringList smartSplit(const QString &str) const
Definition node.cpp:202
The Context class holds the context to render a Template with.
Definition context.h:119
std::shared_ptr< AbstractLocalizer > localizer() const
Definition context.cpp:230
void insert(const QString &name, QObject *object)
Definition context.cpp:145
An exception for use when implementing template tags.
Definition exception.h:85
A FilterExpression object represents a filter expression in a template.
QVariant resolve(OutputStream *stream, Context *c) const
Base class for all nodes.
Definition node.h:78
void streamValueInContext(OutputStream *stream, const QVariant &input, Cutelee::Context *c) const
Definition node.cpp:88
The OutputStream class is used to render templates to a QTextStream.
The Parser class processes a string template into a tree of nodes.
Definition parser.h:49
const NestedString & get() const
Definition safestring.h:340
Node * getNode(const QString &tagContent, Parser *p) const override
void render(OutputStream *stream, Context *c) const override
Node * getNode(const QString &tagContent, Parser *p) const override
void render(OutputStream *stream, Context *c) const override
std::pair< qreal, QString > calcFileSize(qreal size, int unitSystem=10, qreal multiplier=1.0)
Definition util.cpp:215
Cutelee::SafeString getSafeString(const QVariant &input)
Definition util.cpp:108
Utility functions used throughout Cutelee.