From ef0f1429aeeecc7f897d102f80a992fc31e327a7 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 27 Mar 2020 13:41:02 +0100 Subject: Remove QRegExp based API and QRegExp usage from QTextDocument Change-Id: Ib5cc2d747f215a483585b703f9b4f6415e0d59f7 Reviewed-by: Samuel Gaist --- src/gui/text/qtextdocument.cpp | 137 ++------------------- src/gui/text/qtextdocument.h | 5 - .../gui/text/qtextdocument/tst_qtextdocument.cpp | 99 ++++----------- 3 files changed, 32 insertions(+), 209 deletions(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index ab18fccee2..2b712c54b0 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -47,7 +47,6 @@ #include "qtexttable.h" #include "qtextlist.h" #include -#include #if QT_CONFIG(regularexpression) #include #endif @@ -1422,130 +1421,6 @@ QTextCursor QTextDocument::find(const QString &subString, const QTextCursor &cur return find(subString, pos, options); } - -#ifndef QT_NO_REGEXP -static bool findInBlock(const QTextBlock &block, const QRegExp &expression, int offset, - QTextDocument::FindFlags options, QTextCursor *cursor) -{ - QRegExp expr(expression); - QString text = block.text(); - text.replace(QChar::Nbsp, QLatin1Char(' ')); - - int idx = -1; - while (offset >=0 && offset <= text.length()) { - idx = (options & QTextDocument::FindBackward) ? - expr.lastIndexIn(text, offset) : expr.indexIn(text, offset); - if (idx == -1) - return false; - - if (options & QTextDocument::FindWholeWords) { - const int start = idx; - const int end = start + expr.matchedLength(); - if ((start != 0 && text.at(start - 1).isLetterOrNumber()) - || (end != text.length() && text.at(end).isLetterOrNumber())) { - //if this is not a whole word, continue the search in the string - offset = (options & QTextDocument::FindBackward) ? idx-1 : end+1; - idx = -1; - continue; - } - } - //we have a hit, return the cursor for that. - *cursor = QTextCursorPrivate::fromPosition(const_cast(QTextDocumentPrivate::get(block)), - block.position() + idx); - cursor->setPosition(cursor->position() + expr.matchedLength(), QTextCursor::KeepAnchor); - return true; - } - return false; -} - -/*! - \overload - - Finds the next occurrence that matches the given regular expression, - \a expr, within the same paragraph in the document. - - The search starts at the given \a from position, and proceeds forwards - through the document unless specified otherwise in the search options. - The \a options control the type of search performed. The FindCaseSensitively - option is ignored for this overload, use QRegExp::caseSensitivity instead. - - Returns a cursor with the match selected if a match was found; otherwise - returns a null cursor. - - If the \a from position is 0 (the default) the search begins from the beginning - of the document; otherwise it begins at the specified position. -*/ -QTextCursor QTextDocument::find(const QRegExp & expr, int from, FindFlags options) const -{ - Q_D(const QTextDocument); - - if (expr.isEmpty()) - return QTextCursor(); - - int pos = from; - //the cursor is positioned between characters, so for a backward search - //do not include the character given in the position. - if (options & FindBackward) { - --pos ; - if(pos < 0) - return QTextCursor(); - } - - QTextCursor cursor; - QTextBlock block = d->blocksFind(pos); - int blockOffset = pos - block.position(); - if (!(options & FindBackward)) { - while (block.isValid()) { - if (findInBlock(block, expr, blockOffset, options, &cursor)) - return cursor; - block = block.next(); - blockOffset = 0; - } - } else { - while (block.isValid()) { - if (findInBlock(block, expr, blockOffset, options, &cursor)) - return cursor; - block = block.previous(); - blockOffset = block.length() - 1; - } - } - - return QTextCursor(); -} - -/*! - \overload - - Finds the next occurrence that matches the given regular expression, - \a expr, within the same paragraph in the document. - - The search starts at the position of the given from \a cursor, and proceeds - forwards through the document unless specified otherwise in the search - options. The \a options control the type of search performed. The FindCaseSensitively - option is ignored for this overload, use QRegExp::caseSensitivity instead. - - Returns a cursor with the match selected if a match was found; otherwise - returns a null cursor. - - If the given \a cursor has a selection, the search begins after the - selection; otherwise it begins at the cursor's position. - - By default the search is case insensitive, and can match text anywhere in the - document. -*/ -QTextCursor QTextDocument::find(const QRegExp &expr, const QTextCursor &cursor, FindFlags options) const -{ - int pos = 0; - if (!cursor.isNull()) { - if (options & QTextDocument::FindBackward) - pos = cursor.selectionStart(); - else - pos = cursor.selectionEnd(); - } - return find(expr, pos, options); -} -#endif // QT_REGEXP - #if QT_CONFIG(regularexpression) static bool findInBlock(const QTextBlock &block, const QRegularExpression &expr, int offset, QTextDocument::FindFlags options, QTextCursor *cursor) @@ -2283,7 +2158,11 @@ static QString colorValue(QColor color) if (color.alpha() == 255) { result = color.name(); } else if (color.alpha()) { - QString alphaValue = QString::number(color.alphaF(), 'f', 6).remove(QRegExp(QLatin1String("\\.?0*$"))); + QString alphaValue = QString::number(color.alphaF(), 'f', 6); + while (alphaValue.length() > 1 && alphaValue.at(alphaValue.size() - 1) == QLatin1Char('0')) + alphaValue.chop(1); + if (alphaValue.at(alphaValue.size() - 1) == QLatin1Char('.')) + alphaValue.chop(1); result = QString::fromLatin1("rgba(%1,%2,%3,%4)").arg(color.red()) .arg(color.green()) .arg(color.blue()) @@ -2786,10 +2665,10 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment) txt = txt.toHtmlEscaped(); // split for [\n{LineSeparator}] - QString forcedLineBreakRegExp = QString::fromLatin1("[\\na]"); - forcedLineBreakRegExp[3] = QChar::LineSeparator; // space in BR on purpose for compatibility with old-fashioned browsers - html += txt.replace(QRegExp(forcedLineBreakRegExp), QLatin1String("
")); + txt.replace(QLatin1Char('\n'), QLatin1String("
")); + txt.replace(QChar::LineSeparator, QLatin1String("
")); + html += txt; } if (attributesEmitted) diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index 1a1a3da8e8..5a165331bf 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -186,11 +186,6 @@ public: QTextCursor find(const QString &subString, int from = 0, FindFlags options = FindFlags()) const; QTextCursor find(const QString &subString, const QTextCursor &cursor, FindFlags options = FindFlags()) const; -#ifndef QT_NO_REGEXP - QTextCursor find(const QRegExp &expr, int from = 0, FindFlags options = FindFlags()) const; - QTextCursor find(const QRegExp &expr, const QTextCursor &cursor, FindFlags options = FindFlags()) const; -#endif - #if QT_CONFIG(regularexpression) QTextCursor find(const QRegularExpression &expr, int from = 0, FindFlags options = FindFlags()) const; QTextCursor find(const QRegularExpression &expr, const QTextCursor &cursor, FindFlags options = FindFlags()) const; diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp index 10a627bb82..71456fbd09 100644 --- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp +++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp @@ -70,8 +70,6 @@ private slots: void find_data(); void find(); void find2(); - void findWithRegExp_data(); - void findWithRegExp(); void findWithRegularExpression_data(); void findWithRegularExpression(); void findMultiple(); @@ -380,39 +378,8 @@ void tst_QTextDocument::find() } //search using a regular expression - QRegExp expr(needle); - expr.setPatternSyntax(QRegExp::FixedString); + QRegularExpression expr(QRegularExpression::escape(needle)); QTextDocument::FindFlags flg(flags); - expr.setCaseSensitivity((flg & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive); - cursor = doc->find(expr, from, flg); - - if (anchor != -1) { - QCOMPARE(cursor.anchor(), anchor); - QCOMPARE(cursor.position(), position); - } else { - QVERIFY(cursor.isNull()); - } -} - -void tst_QTextDocument::findWithRegExp_data() -{ - buildRegExpData(); -} - -void tst_QTextDocument::findWithRegExp() -{ - QFETCH(QString, haystack); - QFETCH(QString, needle); - QFETCH(int, flags); - QFETCH(int, from); - QFETCH(int, anchor); - QFETCH(int, position); - - cursor.insertText(haystack); - //search using a regular expression - QRegExp expr(needle); - QTextDocument::FindFlags flg(flags); - expr.setCaseSensitivity((flg & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive); cursor = doc->find(expr, from, flg); if (anchor != -1) { @@ -482,26 +449,6 @@ void tst_QTextDocument::findMultiple() QCOMPARE(cursor.selectionStart(), text.indexOf("bar")); QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); - - QRegExp expr("bar"); - expr.setPatternSyntax(QRegExp::FixedString); - - cursor.movePosition(QTextCursor::End); - cursor = doc->find(expr, cursor, QTextDocument::FindBackward); - QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar")); - QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); - cursor = doc->find(expr, cursor, QTextDocument::FindBackward); - QCOMPARE(cursor.selectionStart(), text.indexOf("bar")); - QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); - - cursor.movePosition(QTextCursor::Start); - cursor = doc->find(expr, cursor); - QCOMPARE(cursor.selectionStart(), text.indexOf("bar")); - QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); - cursor = doc->find(expr, cursor); - QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar")); - QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3); - QRegularExpression regularExpression("bar"); cursor.movePosition(QTextCursor::End); @@ -1863,7 +1810,7 @@ void tst_QTextDocument::setFragmentMarkersInHtmlExport() QTextDocumentFragment fragment(cursor); QString expected = htmlHead; - expected.replace(QRegExp(""), QString("")); + expected.replace(QRegularExpression(""), QString("")); expected += QString("

TestBlah

") + htmlTail; QCOMPARE(fragment.toHtml(), expected); } @@ -1883,7 +1830,7 @@ void tst_QTextDocument::setFragmentMarkersInHtmlExport() QTextDocumentFragment fragment(cursor); QString expected = htmlHead; - expected.replace(QRegExp(""), QString("")); + expected.replace(QRegularExpression(""), QString("")); expected += QString("

Test

") + htmlTail; QCOMPARE(fragment.toHtml(), expected); } @@ -2024,8 +1971,9 @@ void tst_QTextDocument::capitalizationHtmlInExport() { doc->setPlainText("Test"); - QRegExp re(".*span style=\"(.*)\">Test.*"); - QVERIFY(re.exactMatch(doc->toHtml()) == false); // no span + QRegularExpression re(".*span style=\"(.*)\">Test.*"); + QCOMPARE(re.captureCount(), 1); + QVERIFY(!re.match(doc->toHtml()).hasMatch()); // no span QTextCursor cursor(doc); cursor.setPosition(4, QTextCursor::KeepAnchor); @@ -2034,23 +1982,23 @@ void tst_QTextDocument::capitalizationHtmlInExport() cursor.mergeCharFormat(cf); const QString smallcaps = doc->toHtml(); - QVERIFY(re.exactMatch(doc->toHtml())); - QCOMPARE(re.captureCount(), 1); - QCOMPARE(re.cap(1).trimmed(), QString("font-variant:small-caps;")); + auto match = re.match(doc->toHtml()); + QVERIFY(match.hasMatch()); + QCOMPARE(match.captured(1).trimmed(), QString("font-variant:small-caps;")); cf.setFontCapitalization(QFont::AllUppercase); cursor.mergeCharFormat(cf); const QString uppercase = doc->toHtml(); - QVERIFY(re.exactMatch(doc->toHtml())); - QCOMPARE(re.captureCount(), 1); - QCOMPARE(re.cap(1).trimmed(), QString("text-transform:uppercase;")); + match = re.match(doc->toHtml()); + QVERIFY(match.hasMatch()); + QCOMPARE(match.captured(1).trimmed(), QString("text-transform:uppercase;")); cf.setFontCapitalization(QFont::AllLowercase); cursor.mergeCharFormat(cf); const QString lowercase = doc->toHtml(); - QVERIFY(re.exactMatch(doc->toHtml())); - QCOMPARE(re.captureCount(), 1); - QCOMPARE(re.cap(1).trimmed(), QString("text-transform:lowercase;")); + match = re.match(doc->toHtml()); + QVERIFY(match.hasMatch()); + QCOMPARE(match.captured(1).trimmed(), QString("text-transform:lowercase;")); doc->setHtml(smallcaps); cursor.setPosition(1); @@ -2065,8 +2013,9 @@ void tst_QTextDocument::wordspacingHtmlExport() { doc->setPlainText("Test"); - QRegExp re(".*span style=\"(.*)\">Test.*"); - QVERIFY(re.exactMatch(doc->toHtml()) == false); // no span + QRegularExpression re(".*span style=\"(.*)\">Test.*"); + QCOMPARE(re.captureCount(), 1); + QVERIFY(!re.match(doc->toHtml()).hasMatch()); // no span QTextCursor cursor(doc); cursor.setPosition(4, QTextCursor::KeepAnchor); @@ -2074,16 +2023,16 @@ void tst_QTextDocument::wordspacingHtmlExport() cf.setFontWordSpacing(4); cursor.mergeCharFormat(cf); - QVERIFY(re.exactMatch(doc->toHtml())); - QCOMPARE(re.captureCount(), 1); - QCOMPARE(re.cap(1).trimmed(), QString("word-spacing:4px;")); + auto match = re.match(doc->toHtml()); + QVERIFY(match.hasMatch()); + QCOMPARE(match.captured(1).trimmed(), QString("word-spacing:4px;")); cf.setFontWordSpacing(-8.5); cursor.mergeCharFormat(cf); - QVERIFY(re.exactMatch(doc->toHtml())); - QCOMPARE(re.captureCount(), 1); - QCOMPARE(re.cap(1).trimmed(), QString("word-spacing:-8.5px;")); + match = re.match(doc->toHtml()); + QVERIFY(match.hasMatch()); + QCOMPARE(match.captured(1).trimmed(), QString("word-spacing:-8.5px;")); } class CursorPosSignalSpy : public QObject -- cgit v1.2.3