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 <paul.wicking@qt.io> (cherry picked from commit 6ac77e81aec0b48a76b385092d9050941fa0e257) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
07ff2fcf41
commit
a3b1f4e463
Binary file not shown.
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 73 KiB |
@ -66,12 +66,13 @@
|
|||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QContextMenuEvent>
|
#include <QContextMenuEvent>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QFontDatabase>
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QRegularExpressionMatch>
|
#include <QRegularExpressionMatch>
|
||||||
#include <QRegularExpressionMatchIterator>
|
#include <QRegularExpressionMatchIterator>
|
||||||
|
|
||||||
@ -106,6 +107,20 @@ static QString codeToPattern(QString code)
|
|||||||
return 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
|
class PatternLineEdit : public QLineEdit
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -239,6 +254,7 @@ void RegularExpressionDialog::setResultUiEnabled(bool enabled)
|
|||||||
{
|
{
|
||||||
matchDetailsTreeWidget->setEnabled(enabled);
|
matchDetailsTreeWidget->setEnabled(enabled);
|
||||||
namedGroupsTreeWidget->setEnabled(enabled);
|
namedGroupsTreeWidget->setEnabled(enabled);
|
||||||
|
replacementTextEdit->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setTextColor(QWidget *widget, const QColor &color)
|
static void setTextColor(QWidget *widget, const QColor &color)
|
||||||
@ -264,6 +280,7 @@ void RegularExpressionDialog::refresh()
|
|||||||
matchDetailsTreeWidget->clear();
|
matchDetailsTreeWidget->clear();
|
||||||
namedGroupsTreeWidget->clear();
|
namedGroupsTreeWidget->clear();
|
||||||
regexpStatusLabel->setText(QString());
|
regexpStatusLabel->setText(QString());
|
||||||
|
replacementTextEdit->clear();
|
||||||
|
|
||||||
if (pattern.isEmpty()) {
|
if (pattern.isEmpty()) {
|
||||||
setResultUiEnabled(false);
|
setResultUiEnabled(false);
|
||||||
@ -271,12 +288,12 @@ void RegularExpressionDialog::refresh()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegularExpression rx(pattern);
|
regularExpression.setPattern(pattern);
|
||||||
if (!rx.isValid()) {
|
if (!regularExpression.isValid()) {
|
||||||
setTextColor(patternLineEdit, Qt::red);
|
setTextColor(patternLineEdit, Qt::red);
|
||||||
regexpStatusLabel->setText(tr("Invalid: syntax error at position %1 (%2)")
|
regexpStatusLabel->setText(tr("Invalid: syntax error at position %1 (%2)")
|
||||||
.arg(rx.patternErrorOffset())
|
.arg(regularExpression.patternErrorOffset())
|
||||||
.arg(rx.errorString()));
|
.arg(regularExpression.errorString()));
|
||||||
setResultUiEnabled(false);
|
setResultUiEnabled(false);
|
||||||
setUpdatesEnabled(true);
|
setUpdatesEnabled(true);
|
||||||
return;
|
return;
|
||||||
@ -308,11 +325,13 @@ void RegularExpressionDialog::refresh()
|
|||||||
if (useUnicodePropertiesOptionCheckBox->isChecked())
|
if (useUnicodePropertiesOptionCheckBox->isChecked())
|
||||||
patternOptions |= QRegularExpression::UseUnicodePropertiesOption;
|
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;
|
int i = 0;
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@ -334,7 +353,7 @@ void RegularExpressionDialog::refresh()
|
|||||||
|
|
||||||
regexpStatusLabel->setText(tr("Valid"));
|
regexpStatusLabel->setText(tr("Valid"));
|
||||||
|
|
||||||
const QStringList namedCaptureGroups = rx.namedCaptureGroups();
|
const QStringList namedCaptureGroups = regularExpression.namedCaptureGroups();
|
||||||
for (int i = 0; i < namedCaptureGroups.size(); ++i) {
|
for (int i = 0; i < namedCaptureGroups.size(); ++i) {
|
||||||
const QString currentNamedCaptureGroup = namedCaptureGroups.at(i);
|
const QString currentNamedCaptureGroup = namedCaptureGroups.at(i);
|
||||||
|
|
||||||
@ -343,28 +362,44 @@ void RegularExpressionDialog::refresh()
|
|||||||
namedGroupItem->setText(1, currentNamedCaptureGroup.isNull() ? tr("<no name>") : currentNamedCaptureGroup);
|
namedGroupItem->setText(1, currentNamedCaptureGroup.isNull() ? tr("<no name>") : currentNamedCaptureGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateReplacement();
|
||||||
|
|
||||||
setUpdatesEnabled(true);
|
setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegularExpressionDialog::setupUi()
|
void RegularExpressionDialog::updateReplacement()
|
||||||
{
|
{
|
||||||
QWidget *leftHalfContainer = setupLeftUi();
|
replacementTextEdit->clear();
|
||||||
|
const QString &replacement = replacementLineEdit->text();
|
||||||
|
if (!regularExpression.isValid() || replacement.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
QFrame *verticalSeparator = new QFrame;
|
QString replaced = subjectTextEdit->toPlainText();
|
||||||
verticalSeparator->setFrameStyle(QFrame::VLine | QFrame::Sunken);
|
replaced.replace(regularExpression, replacement);
|
||||||
|
replacementTextEdit->setPlainText(replaced);
|
||||||
QWidget *rightHalfContainer = setupRightUi();
|
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
|
||||||
mainLayout->addWidget(leftHalfContainer);
|
|
||||||
mainLayout->addWidget(verticalSeparator);
|
|
||||||
mainLayout->addWidget(rightHalfContainer);
|
|
||||||
|
|
||||||
setLayout(mainLayout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *RegularExpressionDialog::setupLeftUi()
|
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::setupTextUi()
|
||||||
{
|
{
|
||||||
QWidget *container = new QWidget;
|
QWidget *container = new QWidget;
|
||||||
|
|
||||||
@ -387,6 +422,35 @@ QWidget *RegularExpressionDialog::setupLeftUi()
|
|||||||
subjectTextEdit = new QPlainTextEdit;
|
subjectTextEdit = new QPlainTextEdit;
|
||||||
layout->addRow(tr("&Subject text:"), subjectTextEdit);
|
layout->addRow(tr("&Subject text:"), subjectTextEdit);
|
||||||
|
|
||||||
|
layout->addRow(createHorizontalSeparator());
|
||||||
|
|
||||||
|
QLabel *replaceLabel = new QLabel(tr("<h3>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("<h3>Options</h3>")));
|
||||||
|
|
||||||
caseInsensitiveOptionCheckBox = new QCheckBox(tr("Case insensitive (/i)"));
|
caseInsensitiveOptionCheckBox = new QCheckBox(tr("Case insensitive (/i)"));
|
||||||
dotMatchesEverythingOptionCheckBox = new QCheckBox(tr("Dot matches everything (/s)"));
|
dotMatchesEverythingOptionCheckBox = new QCheckBox(tr("Dot matches everything (/s)"));
|
||||||
multilineOptionCheckBox = new QCheckBox(tr("Multiline (/m)"));
|
multilineOptionCheckBox = new QCheckBox(tr("Multiline (/m)"));
|
||||||
@ -431,7 +495,7 @@ QWidget *RegularExpressionDialog::setupLeftUi()
|
|||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *RegularExpressionDialog::setupRightUi()
|
QWidget *RegularExpressionDialog::setupInfoUi()
|
||||||
{
|
{
|
||||||
QWidget *container = new QWidget;
|
QWidget *container = new QWidget;
|
||||||
|
|
||||||
@ -447,9 +511,7 @@ QWidget *RegularExpressionDialog::setupRightUi()
|
|||||||
matchDetailsTreeWidget->setSizeAdjustPolicy(QTreeWidget::AdjustToContents);
|
matchDetailsTreeWidget->setSizeAdjustPolicy(QTreeWidget::AdjustToContents);
|
||||||
layout->addRow(tr("Match details:"), matchDetailsTreeWidget);
|
layout->addRow(tr("Match details:"), matchDetailsTreeWidget);
|
||||||
|
|
||||||
QFrame *horizontalSeparator = new QFrame;
|
layout->addRow(createHorizontalSeparator());
|
||||||
horizontalSeparator->setFrameStyle(QFrame::HLine | QFrame::Sunken);
|
|
||||||
layout->addRow(horizontalSeparator);
|
|
||||||
|
|
||||||
QLabel *regexpInfoLabel = new QLabel(tr("<h3>Regular expression information</h3>"));
|
QLabel *regexpInfoLabel = new QLabel(tr("<h3>Regular expression information</h3>"));
|
||||||
layout->addRow(regexpInfoLabel);
|
layout->addRow(regexpInfoLabel);
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#define REGULAREXPRESSIONDIALOG_H
|
#define REGULAREXPRESSIONDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
@ -72,18 +73,25 @@ class RegularExpressionDialog : public QDialog
|
|||||||
public:
|
public:
|
||||||
RegularExpressionDialog(QWidget *parent = nullptr);
|
RegularExpressionDialog(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateReplacement();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh();
|
void refresh();
|
||||||
void setupUi();
|
void setupUi();
|
||||||
QWidget *setupLeftUi();
|
QWidget *setupLeftUi();
|
||||||
QWidget *setupRightUi();
|
QWidget *setupTextUi();
|
||||||
|
QWidget *setupOptionsUi();
|
||||||
|
QWidget *setupInfoUi();
|
||||||
void setResultUiEnabled(bool enabled);
|
void setResultUiEnabled(bool enabled);
|
||||||
|
|
||||||
QLineEdit *patternLineEdit;
|
QLineEdit *patternLineEdit;
|
||||||
QLineEdit *rawStringLiteralLineEdit;
|
QLineEdit *rawStringLiteralLineEdit;
|
||||||
QLineEdit *escapedPatternLineEdit;
|
QLineEdit *escapedPatternLineEdit;
|
||||||
|
QLineEdit *replacementLineEdit;
|
||||||
|
|
||||||
QPlainTextEdit *subjectTextEdit;
|
QPlainTextEdit *subjectTextEdit;
|
||||||
|
QPlainTextEdit *replacementTextEdit;
|
||||||
|
|
||||||
QCheckBox *caseInsensitiveOptionCheckBox;
|
QCheckBox *caseInsensitiveOptionCheckBox;
|
||||||
QCheckBox *dotMatchesEverythingOptionCheckBox;
|
QCheckBox *dotMatchesEverythingOptionCheckBox;
|
||||||
@ -104,6 +112,8 @@ private:
|
|||||||
|
|
||||||
QLabel *regexpStatusLabel;
|
QLabel *regexpStatusLabel;
|
||||||
QTreeWidget *namedGroupsTreeWidget;
|
QTreeWidget *namedGroupsTreeWidget;
|
||||||
|
|
||||||
|
QRegularExpression regularExpression;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user