File indexing completed on 2025-02-09 04:28:36
0001 /* 0002 * This file is part of the KTextTemplate library 0003 * 0004 * SPDX-FileCopyrightText: 2020 Matthias Fehring <mf@huessenbergnetz.de> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "l10n_filesize.h" 0010 0011 #include "abstractlocalizer.h" 0012 #include "exception.h" 0013 #include "parser.h" 0014 #include "util.h" 0015 0016 #include <limits> 0017 0018 L10nFileSizeNodeFactory::L10nFileSizeNodeFactory() = default; 0019 0020 Node *L10nFileSizeNodeFactory::getNode(const QString &tagContent, Parser *p) const 0021 { 0022 QStringList parts = smartSplit(tagContent); 0023 parts.removeFirst(); // not interested in the name of the tag 0024 if (parts.isEmpty()) { 0025 throw Exception(TagSyntaxError, 0026 QStringLiteral("Error: l10n_filesize requires at least the " 0027 "file size as first parameter")); 0028 } 0029 0030 FilterExpression size(parts.at(0), p); 0031 0032 FilterExpression unitSystem; 0033 if (parts.size() > 1) { 0034 unitSystem = FilterExpression(parts.at(1), p); 0035 } 0036 0037 FilterExpression precision; 0038 if (parts.size() > 2) { 0039 precision = FilterExpression(parts.at(2), p); 0040 } 0041 0042 FilterExpression multiplier; 0043 if (parts.size() > 3) { 0044 multiplier = FilterExpression(parts.at(3), p); 0045 } 0046 0047 return new L10nFileSizeNode(size, unitSystem, precision, multiplier, p); 0048 } 0049 0050 L10nFileSizeVarNodeFactory::L10nFileSizeVarNodeFactory() = default; 0051 0052 Node *L10nFileSizeVarNodeFactory::getNode(const QString &tagContent, Parser *p) const 0053 { 0054 QStringList parts = smartSplit(tagContent); 0055 parts.removeFirst(); // not interested in the name of the tag 0056 if (parts.size() < 2) { 0057 throw Exception(TagSyntaxError, 0058 QStringLiteral("Error: l10n_filesize_var tag takes at least 2 " 0059 "arguments, the file size and the variable name")); 0060 } 0061 0062 FilterExpression size(parts.at(0), p); 0063 0064 FilterExpression unitSystem; 0065 if (parts.size() > 2) { 0066 unitSystem = FilterExpression(parts.at(1), p); 0067 } 0068 0069 FilterExpression precision; 0070 if (parts.size() > 3) { 0071 precision = FilterExpression(parts.at(2), p); 0072 } 0073 0074 FilterExpression multiplier; 0075 if (parts.size() > 4) { 0076 multiplier = FilterExpression(parts.at(3), p); 0077 } 0078 0079 const auto resultName = parts.last(); 0080 0081 return new L10nFileSizeVarNode(size, unitSystem, precision, multiplier, resultName, p); 0082 } 0083 0084 L10nFileSizeNode::L10nFileSizeNode(const FilterExpression &size, 0085 const FilterExpression &unitSystem, 0086 const FilterExpression &precision, 0087 const FilterExpression &multiplier, 0088 QObject *parent) 0089 : Node(parent) 0090 , m_size(size) 0091 , m_unitSystem(unitSystem) 0092 , m_precision(precision) 0093 , m_multiplier(multiplier) 0094 { 0095 } 0096 0097 void L10nFileSizeNode::render(OutputStream *stream, Context *c) const 0098 { 0099 bool convertNumbers = true; 0100 0101 qreal size = 0.0F; 0102 if (m_size.resolve(c).canConvert<qreal>()) { 0103 size = m_size.resolve(c).toReal(&convertNumbers); 0104 } else { 0105 size = getSafeString(m_size.resolve(c)).get().toDouble(&convertNumbers); 0106 } 0107 if (!convertNumbers) { 0108 qWarning("%s", "Failed to convert input file size into a floating point number."); 0109 return; 0110 } 0111 0112 int unitSystem = m_unitSystem.isValid() ? m_unitSystem.resolve(c).toInt(&convertNumbers) : 10; 0113 if (!convertNumbers) { 0114 qWarning("%s", 0115 "Failed to convert unit system for file size into integer " 0116 "value. Using default decimal system as default."); 0117 unitSystem = 10; 0118 } 0119 0120 int precision = m_precision.isValid() ? m_precision.resolve(c).toInt(&convertNumbers) : 2; 0121 if (!convertNumbers) { 0122 qWarning("%s", 0123 "Failed to convert decimal precision for file size into an " 0124 "integer value. Using default value 2."); 0125 precision = 2; 0126 } 0127 0128 qreal multiplier = m_multiplier.isValid() ? m_multiplier.resolve(c).toReal(&convertNumbers) : 1.0F; 0129 if (!convertNumbers) { 0130 qWarning("%s", 0131 "Failed to convert multiplier file size into a floating " 0132 "point number. Using default value 1.0."); 0133 multiplier = 1.0F; 0134 } 0135 0136 if (multiplier == 0.0F) { 0137 qWarning("%s", 0138 "It makes no sense to multiply the file size by zero. Using " 0139 "default value 1.0."); 0140 multiplier = 1.0F; 0141 } 0142 0143 const qreal sizeMult = size * multiplier; 0144 0145 if (unitSystem == 10) { 0146 if ((sizeMult > -1000) && (sizeMult < 1000)) { 0147 precision = 0; 0148 } 0149 } else if (unitSystem == 2) { 0150 if ((sizeMult > -1024) && (sizeMult < 1024)) { 0151 precision = 0; 0152 } 0153 } 0154 0155 QString resultString; 0156 0157 if (sizeMult > static_cast<qreal>(std::numeric_limits<qint64>::min()) && sizeMult < static_cast<qreal>(std::numeric_limits<qint64>::max())) { 0158 QLocale l(c->localizer()->currentLocale()); 0159 QLocale::DataSizeFormats format = unitSystem == 10 ? QLocale::DataSizeSIFormat : QLocale::DataSizeIecFormat; 0160 0161 resultString = l.formattedDataSize(static_cast<qint64>(sizeMult), precision, format); 0162 0163 } else { 0164 const std::pair<qreal, QString> fspair = calcFileSize(size, unitSystem, multiplier); 0165 0166 if (precision == 2) { 0167 resultString = c->localizer()->localizeNumber(fspair.first) + QChar(QChar::Space) + fspair.second; 0168 } else { 0169 QLocale l(c->localizer()->currentLocale()); 0170 resultString = l.toString(fspair.first, 'f', precision) + QChar(QChar::Space) + fspair.second; 0171 } 0172 } 0173 0174 streamValueInContext(stream, resultString, c); 0175 } 0176 0177 L10nFileSizeVarNode::L10nFileSizeVarNode(const FilterExpression &size, 0178 const FilterExpression &unitSystem, 0179 const FilterExpression &precision, 0180 const FilterExpression &multiplier, 0181 const QString &resultName, 0182 QObject *parent) 0183 : Node(parent) 0184 , m_size(size) 0185 , m_unitSystem(unitSystem) 0186 , m_precision(precision) 0187 , m_multiplier(multiplier) 0188 , m_resultName(resultName) 0189 { 0190 } 0191 0192 void L10nFileSizeVarNode::render(OutputStream *stream, Context *c) const 0193 { 0194 Q_UNUSED(stream) 0195 bool convertNumbers = true; 0196 0197 qreal size = 0.0F; 0198 if (m_size.resolve(c).canConvert<qreal>()) { 0199 size = m_size.resolve(c).toReal(&convertNumbers); 0200 } else { 0201 size = getSafeString(m_size.resolve(c)).get().toDouble(&convertNumbers); 0202 } 0203 if (!convertNumbers) { 0204 qWarning("%s", "Failed to convert input file size into a floating point number."); 0205 return; 0206 } 0207 0208 int unitSystem = m_unitSystem.isValid() ? m_unitSystem.resolve(c).toInt(&convertNumbers) : 10; 0209 if (!convertNumbers) { 0210 qWarning("%s", 0211 "Failed to convert unit system for file size into integer " 0212 "value. Using default decimal system."); 0213 unitSystem = 10; 0214 } 0215 0216 int precision = m_precision.isValid() ? m_precision.resolve(c).toInt(&convertNumbers) : 2; 0217 if (!convertNumbers) { 0218 qWarning("%s", 0219 "Failed to convert decimal precision for file size into an " 0220 "integer value. Using default value 2."); 0221 precision = 2; 0222 } 0223 0224 qreal multiplier = m_multiplier.isValid() ? m_multiplier.resolve(c).toReal(&convertNumbers) : 1.0F; 0225 if (!convertNumbers) { 0226 qWarning("%s", 0227 "Failed to convert multiplier file size into a floating " 0228 "point number. Using default value 1.0."); 0229 multiplier = 1.0F; 0230 } 0231 0232 if (multiplier == 0.0F) { 0233 qWarning("%s", 0234 "It makes no sense to mulitply the file size by zero. Using " 0235 "default value 1.0."); 0236 multiplier = 1.0F; 0237 } 0238 0239 const double sizeMult = size * multiplier; 0240 0241 if (unitSystem == 10) { 0242 if ((sizeMult > -1000) && (sizeMult < 1000)) { 0243 precision = 0; 0244 } 0245 } else if (unitSystem == 2) { 0246 if ((sizeMult > -1024) && (sizeMult < 1024)) { 0247 precision = 0; 0248 } 0249 } 0250 0251 QString resultString; 0252 0253 if (sizeMult > static_cast<qreal>(std::numeric_limits<qint64>::min()) && sizeMult < static_cast<qreal>(std::numeric_limits<qint64>::max())) { 0254 QLocale l(c->localizer()->currentLocale()); 0255 QLocale::DataSizeFormats format = unitSystem == 10 ? QLocale::DataSizeSIFormat : QLocale::DataSizeIecFormat; 0256 0257 resultString = l.formattedDataSize(static_cast<qint64>(sizeMult), precision, format); 0258 0259 } else { 0260 const std::pair<qreal, QString> fspair = calcFileSize(size, unitSystem, multiplier); 0261 0262 if (precision == 2) { 0263 resultString = c->localizer()->localizeNumber(fspair.first) + QChar(QChar::Space) + fspair.second; 0264 } else { 0265 QLocale l(c->localizer()->currentLocale()); 0266 resultString = l.toString(fspair.first, 'f', precision) + QChar(QChar::Space) + fspair.second; 0267 } 0268 } 0269 0270 c->insert(m_resultName, resultString); 0271 } 0272 0273 #include "moc_l10n_filesize.cpp"