Cutelee 6.2.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 (sizeMult > static_cast<qreal>(std::numeric_limits<qint64>::min()) && sizeMult < static_cast<qreal>(std::numeric_limits<qint64>::max())) {
155
156 QLocale l(c->localizer()->currentLocale());
158
159 resultString = l.formattedDataSize(static_cast<qint64>(sizeMult), precision, format);
160
161 } else {
162 const std::pair<qreal,QString> fspair = calcFileSize(size, unitSystem, multiplier);
163
164 if (precision == 2) {
165 resultString = c->localizer()->localizeNumber(fspair.first) + QChar(QChar::Space) + fspair.second;
166 } else {
167 QLocale l(c->localizer()->currentLocale());
168 resultString = l.toString(fspair.first, 'f', precision) + QChar(QChar::Space) + fspair.second;
169 }
170 }
171
172 streamValueInContext(stream, resultString, c);
173}
174
175L10nFileSizeVarNode::L10nFileSizeVarNode(const FilterExpression &size,
176 const FilterExpression &unitSystem,
177 const FilterExpression &precision,
178 const FilterExpression &multiplier,
179 const QString &resultName, QObject *parent)
180 : Node(parent), m_size(size), m_unitSystem(unitSystem), m_precision(precision), m_multiplier(multiplier),
181 m_resultName(resultName)
182{
183}
184
186{
187 Q_UNUSED(stream)
188 bool convertNumbers = true;
189
190 qreal size = 0.0f;
191 if (m_size.resolve(c).canConvert<qreal>()) {
192 size = m_size.resolve(c).toReal(&convertNumbers);
193 } else {
194 size = getSafeString(m_size.resolve(c)).get().toDouble(&convertNumbers);
195 }
196 if (!convertNumbers) {
197 qWarning("%s", "Failed to convert input file size into a floating point number.");
198 return;
199 }
200
201 int unitSystem = m_unitSystem.isValid() ? m_unitSystem.resolve(c).toInt(&convertNumbers) : 10;
202 if (!convertNumbers) {
203 qWarning("%s", "Failed to convert unit system for file size into integer value. Using default decimal system.");
204 unitSystem = 10;
205 }
206
207 int precision = m_precision.isValid() ? m_precision.resolve(c).toInt(&convertNumbers) : 2;
208 if (!convertNumbers) {
209 qWarning("%s", "Failed to convert decimal precision for file size into an integer value. Using default value 2.");
210 precision = 2;
211 }
212
213 qreal multiplier = m_multiplier.isValid() ? m_multiplier.resolve(c).toReal(&convertNumbers) : 1.0f;
214 if (!convertNumbers) {
215 qWarning("%s", "Failed to convert multiplier file size into a floating point number. Using default value 1.0.");
216 multiplier = 1.0f;
217 }
218
219 if (multiplier == 0.0f) {
220 qWarning("%s", "It makes no sense to mulitply the file size by zero. Using default value 1.0.");
221 multiplier = 1.0f;
222 }
223
224 const double sizeMult = size * multiplier;
225
226 if (unitSystem == 10) {
227 if ((sizeMult > -1000) && (sizeMult < 1000)) {
228 precision = 0;
229 }
230 } else if (unitSystem == 2) {
231 if ((sizeMult > - 1024) && (sizeMult < 1024)) {
232 precision = 0;
233 }
234 }
235
236 QString resultString;
237
238 if (sizeMult > static_cast<qreal>(std::numeric_limits<qint64>::min()) && sizeMult < static_cast<qreal>(std::numeric_limits<qint64>::max())) {
239
240 QLocale l(c->localizer()->currentLocale());
242
243 resultString = l.formattedDataSize(static_cast<qint64>(sizeMult), precision, format);
244
245 } else {
246 const std::pair<qreal,QString> fspair = calcFileSize(size, unitSystem, multiplier);
247
248 if (precision == 2) {
249 resultString = c->localizer()->localizeNumber(fspair.first) + QChar(QChar::Space) + fspair.second;
250 } else {
251 QLocale l(c->localizer()->currentLocale());
252 resultString = l.toString(fspair.first, 'f', precision) + QChar(QChar::Space) + fspair.second;
253 }
254 }
255
256 c->insert(m_resultName, resultString);
257}
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.
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:325
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:196
Cutelee::SafeString getSafeString(const QVariant &input)
Definition util.cpp:111
QList< T >::const_reference at(qsizetype i) const const
bool isEmpty() const const
T & last()
void removeFirst()
qsizetype size() const const
typedef DataSizeFormats
QString formattedDataSize(qint64 bytes, int precision, QLocale::DataSizeFormats format) const const
QString toString(QDate date, QLocale::FormatType format) const const
double toDouble(bool *ok) const const
Utility functions used throughout Cutelee.