summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2015-12-19 03:25:39 +0100
committerMarc Mutz <marc.mutz@kdab.com>2015-12-21 09:30:57 +0000
commit92398565fcc3868fb80b6c7c839b2d60bd96a987 (patch)
treeafe5c93dd0bd50cb97befb9920f9ca8bd41a2877 /src/widgets
parent6066af7f09460bbf72d7aaca12836ca002dcea2a (diff)
Remove a use of a QMap in QAccessibleTextWidget::attributes()
The QMap<QByteArray, QString> was only used to hold key/value pairs until they were serialized into a QString at the end of the function. Serialize into QString directly instead, dropping the temporary QMap. The problem is that we'd like to keep the line formatting central while at the same time harnessing the power of QStringBuilder. This is possible with a templated function with an input/output parameter: format_attr(QString &result, const char *key, T &&value) format_attr(result, text-foo, str + str2 + str3); Or with return type deduction: formatted(const char *key, T &&value) -> decltype((expr)) { return expr; } result += formatted(text-foo, str + str2 + str3); I don't like out parameters, and we can't rely on auto return type deduction, yet, so I opted for a miniature expression template solution that can only match the expression attr[key] = value; where 'key' is a const char* and 'value' can be anything that QStringBuilder supports. This allows to keep the syntax of a map while at the same time serializing to QString immediately. The only behavioral difference to the old code is that the attributes are no longer sorted, but order doesn't matter. Saves more than 10KiB in text size on optimized GCC 4.9 Linux AMD64 builds. Change-Id: I7b3bec0466ef24156c693adaa95f0316007e0bfe Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp56
1 files changed, 49 insertions, 7 deletions
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index 9bbc01b5cc..1ecfb43309 100644
--- a/src/widgets/accessible/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -707,6 +707,53 @@ int QAccessibleTextWidget::selectionCount() const
return textCursor().hasSelection() ? 1 : 0;
}
+namespace {
+/*!
+ \internal
+ \brief Helper class for AttributeFormatter
+
+ This class is returned from AttributeFormatter's indexing operator to act
+ as a proxy for the following assignment.
+
+ It uses perfect forwarding in its assignment operator to amend the RHS
+ with the formatting of the key, using QStringBuilder. Consequently, the
+ RHS can be anything that QStringBuilder supports.
+*/
+class AttributeFormatterRef {
+ QString &string;
+ const char *key;
+ friend class AttributeFormatter;
+ AttributeFormatterRef(QString &string, const char *key) : string(string), key(key) {}
+public:
+ template <typename RHS>
+ void operator=(RHS &&rhs)
+ { string += QLatin1String(key) + QLatin1Char(':') + std::forward<RHS>(rhs) + QLatin1Char(';'); }
+};
+
+/*!
+ \internal
+ \brief Small string-builder class that supports a map-like API to serialize key-value pairs.
+ \code
+ AttributeFormatter attrs;
+ attrs["foo"] = QLatinString("hello") + world + QLatin1Char('!');
+ \endcode
+ The key type is always \c{const char*}, and the right-hand-side can
+ be any QStringBuilder expression.
+
+ Breaking it down, this class provides the indexing operator, stores
+ the key in an instance of, and then returns, AttributeFormatterRef,
+ which is the class that provides the assignment part of the operation.
+*/
+class AttributeFormatter {
+ QString string;
+public:
+ AttributeFormatterRef operator[](const char *key)
+ { return AttributeFormatterRef(string, key); }
+
+ QString toFormatted() const { return string; }
+};
+} // unnamed namespace
+
QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *endOffset) const
{
/* The list of attributes can be found at:
@@ -766,7 +813,7 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end
QTextBlockFormat blockFormat = cursor.blockFormat();
- QMap<QByteArray, QString> attrs;
+ AttributeFormatter attrs;
QString family = charFormat.font().family();
if (!family.isEmpty()) {
family = family.replace('\\',QStringLiteral("\\\\"));
@@ -856,12 +903,7 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end
break;
}
- QString result;
- foreach (const QByteArray &attributeName, attrs.keys()) {
- result.append(QString::fromLatin1(attributeName)).append(':').append(attrs[attributeName]).append(';');
- }
-
- return result;
+ return attrs.toFormatted();
}
int QAccessibleTextWidget::cursorPosition() const