Remove QRegExp based API and QRegExp usage from QTextDocument

Change-Id: Ib5cc2d747f215a483585b703f9b4f6415e0d59f7
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
This commit is contained in:
Lars Knoll 2020-03-27 13:41:02 +01:00
parent 70beac08af
commit ef0f1429ae
3 changed files with 32 additions and 209 deletions

View File

@ -47,7 +47,6 @@
#include "qtexttable.h"
#include "qtextlist.h"
#include <qdebug.h>
#include <qregexp.h>
#if QT_CONFIG(regularexpression)
#include <qregularexpression.h>
#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 *>(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("<br />"));
txt.replace(QLatin1Char('\n'), QLatin1String("<br />"));
txt.replace(QChar::LineSeparator, QLatin1String("<br />"));
html += txt;
}
if (attributesEmitted)

View File

@ -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;

View File

@ -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("<body.*>"), QString("<body>"));
expected.replace(QRegularExpression("<body.*>"), QString("<body>"));
expected += QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><!--StartFragment-->Test<span style=\" color:#00ff00;\">Blah</span><!--EndFragment--></p>") + htmlTail;
QCOMPARE(fragment.toHtml(), expected);
}
@ -1883,7 +1830,7 @@ void tst_QTextDocument::setFragmentMarkersInHtmlExport()
QTextDocumentFragment fragment(cursor);
QString expected = htmlHead;
expected.replace(QRegExp("<body.*>"), QString("<body>"));
expected.replace(QRegularExpression("<body.*>"), QString("<body>"));
expected += QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><!--StartFragment-->Test<!--EndFragment--></p>") + 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