File indexing completed on 2025-02-09 04:28:40
0001 /* 0002 This file is part of the KTextTemplate library 0003 0004 SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 0008 */ 0009 0010 #include "typeaccessor.h" 0011 0012 #include "metaenumvariable_p.h" 0013 #include "safestring.h" 0014 0015 #include <QRegularExpression> 0016 #include <QStringList> 0017 #include <QVariant> 0018 0019 namespace KTextTemplate 0020 { 0021 0022 static QRegularExpression getIsTitleRE() 0023 { 0024 QRegularExpression titleRe(QStringLiteral("\\b[a-z]"), QRegularExpression::InvertedGreedinessOption); 0025 return titleRe; 0026 } 0027 0028 static QRegularExpression getTitleRE() 0029 { 0030 QRegularExpression titleRe(QStringLiteral("\\b(.)"), QRegularExpression::InvertedGreedinessOption); 0031 return titleRe; 0032 } 0033 0034 template<> 0035 QVariant TypeAccessor<KTextTemplate::SafeString &>::lookUp(const KTextTemplate::SafeString &object, const QString &property) 0036 { 0037 if (property == QStringLiteral("capitalize")) { 0038 const QString &s = object.get(); 0039 return {s.at(0).toUpper() + s.right(s.length() - 1)}; 0040 } 0041 0042 static const QLatin1String falseString("False"); 0043 static const QLatin1String trueString("True"); 0044 0045 if (property == QStringLiteral("isalnum")) { 0046 const QString &s = object.get(); 0047 auto it = s.constBegin(); 0048 while (it != s.constEnd()) { 0049 if (!it->isLetterOrNumber()) 0050 return falseString; 0051 ++it; 0052 } 0053 return trueString; 0054 } 0055 if (property == QStringLiteral("isalpha")) { 0056 const QString &s = object.get(); 0057 auto it = s.constBegin(); 0058 if (it == s.constEnd()) 0059 return falseString; 0060 while (it != s.constEnd()) { 0061 if (!it->isLetter()) 0062 return falseString; 0063 ++it; 0064 } 0065 return trueString; 0066 } 0067 if (property == QStringLiteral("isdigit")) { 0068 const QString &s = object.get(); 0069 auto it = s.constBegin(); 0070 while (it != s.constEnd()) { 0071 if (!it->isNumber()) 0072 return falseString; 0073 ++it; 0074 } 0075 return trueString; 0076 } 0077 if (property == QStringLiteral("islower")) { 0078 const QString s = object.get().toLower(); 0079 return (s == object.get()) ? trueString : falseString; 0080 } 0081 if (property == QStringLiteral("isspace")) { 0082 const QString s = object.get().trimmed(); 0083 return (s.isEmpty()) ? trueString : falseString; 0084 } 0085 if (property == QStringLiteral("istitle")) { 0086 const QString &s = object.get(); 0087 0088 static const auto titleRe = getIsTitleRE(); 0089 return (titleRe.match(s).hasMatch()) ? falseString : trueString; 0090 } 0091 if (property == QStringLiteral("isupper")) { 0092 const QString s = object.get().toUpper(); 0093 return (s == object) ? trueString : falseString; 0094 } 0095 if (property == QStringLiteral("lower")) { 0096 return object.get().toLower(); 0097 } 0098 if (property == QStringLiteral("splitlines")) { 0099 const auto strings = object.get().split(QLatin1Char('\n')); 0100 QVariantList list; 0101 auto it = strings.constBegin(); 0102 const auto end = strings.constEnd(); 0103 for (; it != end; ++it) 0104 list << *it; 0105 return list; 0106 } 0107 if (property == QStringLiteral("strip")) { 0108 return object.get().trimmed(); 0109 } 0110 if (property == QStringLiteral("swapcase")) { 0111 const QString &inputString = object.get(); 0112 QString s; 0113 s.reserve(inputString.size()); 0114 auto it = inputString.constBegin(); 0115 while (it != inputString.constEnd()) { 0116 if (it->isUpper()) 0117 s += it->toLower(); 0118 else if (it->isLower()) 0119 s += it->toUpper(); 0120 else 0121 s += *it; 0122 ++it; 0123 } 0124 return s; 0125 } 0126 if (property == QStringLiteral("title")) { 0127 static const auto titleRe = getTitleRE(); 0128 0129 const QString &s = object.get(); 0130 QString output; 0131 output.reserve(s.size()); 0132 auto pos = 0; 0133 auto nextPos = 0; 0134 int matchedLength; 0135 0136 auto it = titleRe.globalMatch(s); 0137 while (it.hasNext()) { 0138 auto match = it.next(); 0139 pos = match.capturedStart(); 0140 output += match.captured().toUpper(); 0141 matchedLength = match.capturedLength(); 0142 if (it.hasNext()) { 0143 match = it.peekNext(); 0144 nextPos = match.capturedStart(); 0145 output += s.mid(pos + matchedLength, nextPos - pos - 1); 0146 } else { 0147 output += s.right(s.length() - (pos + matchedLength)); 0148 } 0149 } 0150 0151 return output; 0152 } 0153 if (property == QStringLiteral("upper")) { 0154 return object.get().toUpper(); 0155 } 0156 return {}; 0157 } 0158 0159 template<> 0160 QVariant TypeAccessor<MetaEnumVariable &>::lookUp(const MetaEnumVariable &object, const QString &property) 0161 { 0162 if (property == QStringLiteral("name")) 0163 return QLatin1String(object.enumerator.name()); 0164 if (property == QStringLiteral("value")) 0165 return object.value; 0166 if (property == QStringLiteral("key")) 0167 return QLatin1String(object.enumerator.valueToKey(object.value)); 0168 if (property == QStringLiteral("scope")) 0169 return QLatin1String(object.enumerator.scope()); 0170 if (property == QStringLiteral("keyCount")) 0171 return object.enumerator.keyCount(); 0172 0173 auto ok = false; 0174 const auto listIndex = property.toInt(&ok); 0175 if (ok) { 0176 if (listIndex >= object.enumerator.keyCount()) 0177 return {}; 0178 0179 const MetaEnumVariable mev(object.enumerator, object.enumerator.value(listIndex)); 0180 return QVariant::fromValue(mev); 0181 } 0182 0183 return {}; 0184 } 0185 }