diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-01-15 08:51:55 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-01-15 08:51:55 (GMT) |
commit | bc1c329c5fd7679023eb69f6d0924e6536fc7b12 (patch) | |
tree | 70181011257d01be39f9d77cdf5b025c55bf0c01 /src/declarative | |
parent | 72480e97f0eb4ef49b380e46899a976cf97e78c4 (diff) | |
download | Qt-bc1c329c5fd7679023eb69f6d0924e6536fc7b12.zip Qt-bc1c329c5fd7679023eb69f6d0924e6536fc7b12.tar.gz Qt-bc1c329c5fd7679023eb69f6d0924e6536fc7b12.tar.bz2 |
Add basic missing stuff (italic, > < & font size) to styledtext.
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/util/qmlstyledtext.cpp | 157 |
1 files changed, 72 insertions, 85 deletions
diff --git a/src/declarative/util/qmlstyledtext.cpp b/src/declarative/util/qmlstyledtext.cpp index ce2b2ea..36b5e49 100644 --- a/src/declarative/util/qmlstyledtext.cpp +++ b/src/declarative/util/qmlstyledtext.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -#include <QXmlStreamReader> #include <QStack> #include <QVector> #include <QPainter> @@ -52,20 +51,22 @@ QmlStyledText supports few tags: <b></b> - bold + <i></i> - italic <br> - new line - <font color="color_name"></font> + <font color="color_name" size="1-7"></font> - The opening and closing tags may be correctly nested. + The opening and closing tags must be correctly nested. */ class QmlStyledTextPrivate { public: - QmlStyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l) {} + QmlStyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l), baseFont(layout.font()) {} void parse(); bool parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format); bool parseCloseTag(const QChar *&ch, const QString &textIn); + void parseEntity(const QChar *&ch, const QString &textIn, QString &textOut); bool parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format); QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn); QStringRef parseValue(const QChar *&ch, const QString &textIn); @@ -77,6 +78,7 @@ public: QString text; QTextLayout &layout; + QFont baseFont; static const QChar lessThan; static const QChar greaterThan; @@ -84,6 +86,7 @@ public: static const QChar singleQuote; static const QChar doubleQuote; static const QChar slash; + static const QChar ampersand; }; const QChar QmlStyledTextPrivate::lessThan(QLatin1Char('<')); @@ -92,6 +95,7 @@ const QChar QmlStyledTextPrivate::equals(QLatin1Char('=')); const QChar QmlStyledTextPrivate::singleQuote(QLatin1Char('\'')); const QChar QmlStyledTextPrivate::doubleQuote(QLatin1Char('\"')); const QChar QmlStyledTextPrivate::slash(QLatin1Char('/')); +const QChar QmlStyledTextPrivate::ampersand(QLatin1Char('&')); QmlStyledText::QmlStyledText(const QString &string, QTextLayout &layout) : d(new QmlStyledTextPrivate(string, layout)) @@ -109,66 +113,6 @@ void QmlStyledText::parse(const QString &string, QTextLayout &layout) styledText.d->parse(); } -#define CUSTOM_PARSER - -#ifndef CUSTOM_PARSER -void QmlStyledTextPrivate::parse() -{ - QList<QTextLayout::FormatRange> ranges; - QStack<QTextCharFormat> formatStack; - - QString drawText; - drawText.reserve(text.count()); - - QXmlStreamReader xml("<html>" + text + "</html>"); - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::StartElement) { - QStringRef name = xml.name(); - if (name == "b") { - QTextCharFormat format; - if (formatStack.count()) - format = formatStack.top(); - else - format.setFont(layout.font()); - format.setFontWeight(QFont::Bold); - formatStack.push(format); - } else if (name == "br") { - drawText.append(QChar(QChar::LineSeparator)); - } else if (name == "font") { - QTextCharFormat format; - if (formatStack.count()) - format = formatStack.top(); - else - format.setFont(layout.font()); - QStringRef col = xml.attributes().value("color"); - if (!col.isEmpty()) { - format.setForeground(QColor(col.toString())); - formatStack.push(format); - } - } - } else if (xml.tokenType() == QXmlStreamReader::EndElement) { - if (formatStack.count() > 1) { - QStringRef name = xml.name(); - if (name == "b" || name == "font" || name == "br") - formatStack.pop(); - } - } else if (xml.tokenType() == QXmlStreamReader::Characters) { - if (formatStack.count() > 1) { - QTextLayout::FormatRange formatRange; - formatRange.format = formatStack.top(); - formatRange.start = drawText.length(); - formatRange.length = xml.text().length(); - ranges.append(formatRange); - } - drawText.append(xml.text()); - } - } - - layout.setText(drawText); - layout.setAdditionalFormats(ranges); -} -#else void QmlStyledTextPrivate::parse() { QList<QTextLayout::FormatRange> ranges; @@ -179,19 +123,20 @@ void QmlStyledTextPrivate::parse() int textStart = 0; int textLength = 0; + int rangeStart = 0; const QChar *ch = text.constData(); while (!ch->isNull()) { if (*ch == lessThan) { - if (textLength) { - if (formatStack.count()) { - QTextLayout::FormatRange formatRange; - formatRange.format = formatStack.top(); - formatRange.start = drawText.length(); - formatRange.length = textLength; - ranges.append(formatRange); - } + if (textLength) drawText.append(QStringRef(&text, textStart, textLength)); + if (rangeStart != drawText.length() && formatStack.count()) { + QTextLayout::FormatRange formatRange; + formatRange.format = formatStack.top(); + formatRange.start = rangeStart; + formatRange.length = drawText.length() - rangeStart; + ranges.append(formatRange); } + rangeStart = drawText.length(); ++ch; if (*ch == slash) { ++ch; @@ -202,33 +147,36 @@ void QmlStyledTextPrivate::parse() if (formatStack.count()) format = formatStack.top(); else - format.setFont(layout.font()); + format.setFont(baseFont); if (parseTag(ch, text, drawText, format)) formatStack.push(format); } textStart = ch - text.constData() + 1; textLength = 0; + } else if (*ch == ampersand) { + ++ch; + drawText.append(QStringRef(&text, textStart, textLength)); + parseEntity(ch, text, drawText); + textStart = ch - text.constData() + 1; + textLength = 0; } else { ++textLength; } ++ch; } - if (textLength) { - if (formatStack.count()) { - QTextLayout::FormatRange formatRange; - formatRange.format = formatStack.top(); - formatRange.start = drawText.length(); - formatRange.length = textLength; - ranges.append(formatRange); - } + if (textLength) drawText.append(QStringRef(&text, textStart, textLength)); + if (rangeStart != drawText.length() && formatStack.count()) { + QTextLayout::FormatRange formatRange; + formatRange.format = formatStack.top(); + formatRange.start = rangeStart; + formatRange.length = drawText.length() - rangeStart; + ranges.append(formatRange); } layout.setText(drawText); layout.setAdditionalFormats(ranges); } -#endif - bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format) { @@ -239,7 +187,8 @@ bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QSt while (!ch->isNull()) { if (*ch == greaterThan) { QStringRef tag(&textIn, tagStart, tagLength); - if (tag.at(0) == QLatin1Char('b')) { + const QChar char0 = tag.at(0); + if (char0 == QLatin1Char('b')) { if (tagLength == 1) { format.setFontWeight(QFont::Bold); return true; @@ -247,6 +196,11 @@ bool QmlStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QSt textOut.append(QChar(QChar::LineSeparator)); return true; } + } else if (char0 == QLatin1Char('i')) { + if (tagLength == 1) { + format.setFontItalic(true); + return true; + } } return false; } else if (ch->isSpace()) { @@ -274,11 +228,15 @@ bool QmlStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn while (!ch->isNull()) { if (*ch == greaterThan) { QStringRef tag(&textIn, tagStart, tagLength); - if (tag.at(0) == QLatin1Char('b')) { + const QChar char0 = tag.at(0); + if (char0 == QLatin1Char('b')) { if (tagLength == 1) return true; else if (tag.at(1) == QLatin1Char('r') && tagLength == 2) return true; + } else if (char0 == QLatin1Char('i')) { + if (tagLength == 1) + return true; } else if (tag == QLatin1String("font")) { return true; } @@ -292,6 +250,26 @@ bool QmlStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn return false; } +void QmlStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textIn, QString &textOut) +{ + int entityStart = ch - textIn.constData(); + int entityLength = 0; + while (!ch->isNull()) { + if (*ch == QLatin1Char(';')) { + QStringRef entity(&textIn, entityStart, entityLength); + if (entity == QLatin1String("gt")) + textOut += QChar(62); + else if (entity == QLatin1String("lt")) + textOut += QChar(60); + else if (entity == QLatin1String("amp")) + textOut += QChar(38); + return; + } + ++entityLength; + ++ch; + } +} + bool QmlStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format) { bool valid = false; @@ -301,6 +279,15 @@ bool QmlStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString & if (attr.first == QLatin1String("color")) { valid = true; format.setForeground(QColor(attr.second.toString())); + } else if (attr.first == QLatin1String("size")) { + valid = true; + int size = attr.second.toString().toInt(); + if (attr.second.at(0) == QLatin1Char('-') || attr.second.at(0) == QLatin1Char('+')) + size += 3; + if (size >= 1 && size <= 7) { + static const qreal scaling[] = { 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 2.4 }; + format.setFontPointSize(baseFont.pointSize() * scaling[size-1]); + } } } while (!ch->isNull() && !attr.first.isEmpty()); |