From a3b1f4e463da2d80c0d08859b0b9879e83e24e2a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 28 Apr 2021 13:26:35 +0200 Subject: Regular Expression example: Brush up and add a way to preview replacements - Set a fixed font on text edits so that parentheses stand out - Rearrange the layout to have the text at the top be prevent long texts from being wrapped - Add a replacement field where one can exercise replacement with the \1, \2... placeholders. Change-Id: I140a62e1fb2cd1c6bfe02a2f01b7f06a6f3b5eb2 Reviewed-by: Paul Wicking (cherry picked from commit 6ac77e81aec0b48a76b385092d9050941fa0e257) Reviewed-by: Qt Cherry-pick Bot --- .../regularexpression/regularexpressiondialog.cpp | 114 ++++++++++++++++----- .../regularexpression/regularexpressiondialog.h | 12 ++- 2 files changed, 99 insertions(+), 27 deletions(-) (limited to 'examples/widgets/tools') diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp index 51025b7100..36c8695ae9 100644 --- a/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp +++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.cpp @@ -66,12 +66,13 @@ #include #include #include +#include +#include #include #include #include -#include #include #include @@ -106,6 +107,20 @@ static QString codeToPattern(QString code) return code; } +static QFrame *createHorizontalSeparator() +{ + auto *result = new QFrame; + result->setFrameStyle(QFrame::HLine | QFrame::Sunken); + return result; +} + +static QFrame *createVerticalSeparator() +{ + auto *result = new QFrame; + result->setFrameStyle(QFrame::VLine | QFrame::Sunken); + return result; +} + class PatternLineEdit : public QLineEdit { Q_OBJECT @@ -239,6 +254,7 @@ void RegularExpressionDialog::setResultUiEnabled(bool enabled) { matchDetailsTreeWidget->setEnabled(enabled); namedGroupsTreeWidget->setEnabled(enabled); + replacementTextEdit->setEnabled(enabled); } static void setTextColor(QWidget *widget, const QColor &color) @@ -264,6 +280,7 @@ void RegularExpressionDialog::refresh() matchDetailsTreeWidget->clear(); namedGroupsTreeWidget->clear(); regexpStatusLabel->setText(QString()); + replacementTextEdit->clear(); if (pattern.isEmpty()) { setResultUiEnabled(false); @@ -271,12 +288,12 @@ void RegularExpressionDialog::refresh() return; } - QRegularExpression rx(pattern); - if (!rx.isValid()) { + regularExpression.setPattern(pattern); + if (!regularExpression.isValid()) { setTextColor(patternLineEdit, Qt::red); regexpStatusLabel->setText(tr("Invalid: syntax error at position %1 (%2)") - .arg(rx.patternErrorOffset()) - .arg(rx.errorString())); + .arg(regularExpression.patternErrorOffset()) + .arg(regularExpression.errorString())); setResultUiEnabled(false); setUpdatesEnabled(true); return; @@ -308,11 +325,13 @@ void RegularExpressionDialog::refresh() if (useUnicodePropertiesOptionCheckBox->isChecked()) patternOptions |= QRegularExpression::UseUnicodePropertiesOption; - rx.setPatternOptions(patternOptions); + regularExpression.setPatternOptions(patternOptions); - const int capturingGroupsCount = rx.captureCount() + 1; + const int capturingGroupsCount = regularExpression.captureCount() + 1; - QRegularExpressionMatchIterator iterator = rx.globalMatch(text, offsetSpinBox->value(), matchType, matchOptions); + const int offset = offsetSpinBox->value(); + QRegularExpressionMatchIterator iterator = + regularExpression.globalMatch(text, offset, matchType, matchOptions); int i = 0; while (iterator.hasNext()) { @@ -334,7 +353,7 @@ void RegularExpressionDialog::refresh() regexpStatusLabel->setText(tr("Valid")); - const QStringList namedCaptureGroups = rx.namedCaptureGroups(); + const QStringList namedCaptureGroups = regularExpression.namedCaptureGroups(); for (int i = 0; i < namedCaptureGroups.size(); ++i) { const QString currentNamedCaptureGroup = namedCaptureGroups.at(i); @@ -343,28 +362,44 @@ void RegularExpressionDialog::refresh() namedGroupItem->setText(1, currentNamedCaptureGroup.isNull() ? tr("") : currentNamedCaptureGroup); } + updateReplacement(); setUpdatesEnabled(true); } -void RegularExpressionDialog::setupUi() +void RegularExpressionDialog::updateReplacement() { - QWidget *leftHalfContainer = setupLeftUi(); - - QFrame *verticalSeparator = new QFrame; - verticalSeparator->setFrameStyle(QFrame::VLine | QFrame::Sunken); - - QWidget *rightHalfContainer = setupRightUi(); + replacementTextEdit->clear(); + const QString &replacement = replacementLineEdit->text(); + if (!regularExpression.isValid() || replacement.isEmpty()) + return; - QHBoxLayout *mainLayout = new QHBoxLayout; - mainLayout->addWidget(leftHalfContainer); - mainLayout->addWidget(verticalSeparator); - mainLayout->addWidget(rightHalfContainer); + QString replaced = subjectTextEdit->toPlainText(); + replaced.replace(regularExpression, replacement); + replacementTextEdit->setPlainText(replaced); +} - setLayout(mainLayout); +void RegularExpressionDialog::setupUi() +{ + auto *mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(setupTextUi()); + mainLayout->addWidget(createHorizontalSeparator()); + auto *horizontalLayout = new QHBoxLayout(); + mainLayout->addLayout(horizontalLayout); + horizontalLayout->addWidget(setupOptionsUi()); + horizontalLayout->addWidget(createVerticalSeparator()); + horizontalLayout->addWidget(setupInfoUi()); + + auto font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + patternLineEdit->setFont(font); + rawStringLiteralLineEdit->setFont(font); + escapedPatternLineEdit->setFont(font); + replacementLineEdit->setFont(font); + subjectTextEdit->setFont(font); + replacementTextEdit->setFont(font); } -QWidget *RegularExpressionDialog::setupLeftUi() +QWidget *RegularExpressionDialog::setupTextUi() { QWidget *container = new QWidget; @@ -387,6 +422,35 @@ QWidget *RegularExpressionDialog::setupLeftUi() subjectTextEdit = new QPlainTextEdit; layout->addRow(tr("&Subject text:"), subjectTextEdit); + layout->addRow(createHorizontalSeparator()); + + QLabel *replaceLabel = new QLabel(tr("

Replacement")); + layout->addRow(replaceLabel); + + replacementLineEdit = new QLineEdit; + replacementLineEdit->setClearButtonEnabled(true); + connect(replacementLineEdit, &QLineEdit::textChanged, this, + &RegularExpressionDialog::updateReplacement); + layout->addRow(tr("&Replace by:"), replacementLineEdit); + replacementLineEdit->setToolTip(tr("Use \\1, \\2... as placeholders for the captured groups.")); + + replacementTextEdit = new QPlainTextEdit; + replacementTextEdit->setReadOnly(true); + layout->addRow(tr("Result:"), replacementTextEdit); + + return container; +} + +QWidget *RegularExpressionDialog::setupOptionsUi() +{ + QWidget *container = new QWidget; + + QFormLayout *layout = new QFormLayout(container); + layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + layout->setContentsMargins(QMargins()); + + layout->addRow(new QLabel(tr("

Options

"))); + caseInsensitiveOptionCheckBox = new QCheckBox(tr("Case insensitive (/i)")); dotMatchesEverythingOptionCheckBox = new QCheckBox(tr("Dot matches everything (/s)")); multilineOptionCheckBox = new QCheckBox(tr("Multiline (/m)")); @@ -431,7 +495,7 @@ QWidget *RegularExpressionDialog::setupLeftUi() return container; } -QWidget *RegularExpressionDialog::setupRightUi() +QWidget *RegularExpressionDialog::setupInfoUi() { QWidget *container = new QWidget; @@ -447,9 +511,7 @@ QWidget *RegularExpressionDialog::setupRightUi() matchDetailsTreeWidget->setSizeAdjustPolicy(QTreeWidget::AdjustToContents); layout->addRow(tr("Match details:"), matchDetailsTreeWidget); - QFrame *horizontalSeparator = new QFrame; - horizontalSeparator->setFrameStyle(QFrame::HLine | QFrame::Sunken); - layout->addRow(horizontalSeparator); + layout->addRow(createHorizontalSeparator()); QLabel *regexpInfoLabel = new QLabel(tr("

Regular expression information

")); layout->addRow(regexpInfoLabel); diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.h b/examples/widgets/tools/regularexpression/regularexpressiondialog.h index b0db4d884c..b5d592c3c2 100644 --- a/examples/widgets/tools/regularexpression/regularexpressiondialog.h +++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.h @@ -54,6 +54,7 @@ #define REGULAREXPRESSIONDIALOG_H #include +#include QT_BEGIN_NAMESPACE class QCheckBox; @@ -72,18 +73,25 @@ class RegularExpressionDialog : public QDialog public: RegularExpressionDialog(QWidget *parent = nullptr); +private slots: + void updateReplacement(); + private: void refresh(); void setupUi(); QWidget *setupLeftUi(); - QWidget *setupRightUi(); + QWidget *setupTextUi(); + QWidget *setupOptionsUi(); + QWidget *setupInfoUi(); void setResultUiEnabled(bool enabled); QLineEdit *patternLineEdit; QLineEdit *rawStringLiteralLineEdit; QLineEdit *escapedPatternLineEdit; + QLineEdit *replacementLineEdit; QPlainTextEdit *subjectTextEdit; + QPlainTextEdit *replacementTextEdit; QCheckBox *caseInsensitiveOptionCheckBox; QCheckBox *dotMatchesEverythingOptionCheckBox; @@ -104,6 +112,8 @@ private: QLabel *regexpStatusLabel; QTreeWidget *namedGroupsTreeWidget; + + QRegularExpression regularExpression; }; #endif -- cgit v1.2.3