1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> |
4 | ** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch> |
5 | ** Copyright (C) 2016 The Qt Company Ltd. |
6 | ** Contact: https://www.qt.io/licensing/ |
7 | ** |
8 | ** This file is part of the examples of the Qt Toolkit. |
9 | ** |
10 | ** $QT_BEGIN_LICENSE:BSD$ |
11 | ** Commercial License Usage |
12 | ** Licensees holding valid commercial Qt licenses may use this file in |
13 | ** accordance with the commercial license agreement provided with the |
14 | ** Software or, alternatively, in accordance with the terms contained in |
15 | ** a written agreement between you and The Qt Company. For licensing terms |
16 | ** and conditions see https://www.qt.io/terms-conditions. For further |
17 | ** information use the contact form at https://www.qt.io/contact-us. |
18 | ** |
19 | ** BSD License Usage |
20 | ** Alternatively, you may use this file under the terms of the BSD license |
21 | ** as follows: |
22 | ** |
23 | ** "Redistribution and use in source and binary forms, with or without |
24 | ** modification, are permitted provided that the following conditions are |
25 | ** met: |
26 | ** * Redistributions of source code must retain the above copyright |
27 | ** notice, this list of conditions and the following disclaimer. |
28 | ** * Redistributions in binary form must reproduce the above copyright |
29 | ** notice, this list of conditions and the following disclaimer in |
30 | ** the documentation and/or other materials provided with the |
31 | ** distribution. |
32 | ** * Neither the name of The Qt Company Ltd nor the names of its |
33 | ** contributors may be used to endorse or promote products derived |
34 | ** from this software without specific prior written permission. |
35 | ** |
36 | ** |
37 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
38 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
39 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
40 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
41 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
42 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
43 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
44 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
45 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
46 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
47 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
48 | ** |
49 | ** $QT_END_LICENSE$ |
50 | ** |
51 | ****************************************************************************/ |
52 | |
53 | #include "regularexpressiondialog.h" |
54 | |
55 | #include <QApplication> |
56 | |
57 | #include <QCheckBox> |
58 | #include <QComboBox> |
59 | #include <QLabel> |
60 | #include <QLineEdit> |
61 | #include <QMenu> |
62 | #include <QSpinBox> |
63 | #include <QPlainTextEdit> |
64 | #include <QTreeWidget> |
65 | |
66 | #include <QAction> |
67 | #include <QClipboard> |
68 | #include <QContextMenuEvent> |
69 | |
70 | #include <QHBoxLayout> |
71 | #include <QGridLayout> |
72 | #include <QFormLayout> |
73 | |
74 | #include <QRegularExpression> |
75 | #include <QRegularExpressionMatch> |
76 | #include <QRegularExpressionMatchIterator> |
77 | |
78 | Q_DECLARE_METATYPE(QRegularExpression::MatchType) |
79 | |
80 | static QString rawStringLiteral(QString pattern) |
81 | { |
82 | pattern.prepend(QLatin1String("R\"RX(" )); |
83 | pattern.append(QLatin1String(")RX\"" )); |
84 | return pattern; |
85 | } |
86 | |
87 | static QString patternToCode(QString pattern) |
88 | { |
89 | pattern.replace(QLatin1String("\\" ), QLatin1String("\\\\" )); |
90 | pattern.replace(QLatin1String("\"" ), QLatin1String("\\\"" )); |
91 | pattern.prepend(QLatin1Char('"')); |
92 | pattern.append(QLatin1Char('"')); |
93 | return pattern; |
94 | } |
95 | |
96 | static QString codeToPattern(QString code) |
97 | { |
98 | for (int i = 0; i < code.size(); ++i) { |
99 | if (code.at(i) == QLatin1Char('\\')) |
100 | code.remove(i, 1); |
101 | } |
102 | if (code.startsWith(QLatin1Char('"')) && code.endsWith(QLatin1Char('"'))) { |
103 | code.chop(1); |
104 | code.remove(0, 1); |
105 | } |
106 | return code; |
107 | } |
108 | |
109 | class PatternLineEdit : public QLineEdit |
110 | { |
111 | Q_OBJECT |
112 | public: |
113 | explicit PatternLineEdit(QWidget *parent = nullptr); |
114 | |
115 | private slots: |
116 | void copyToCode(); |
117 | void pasteFromCode(); |
118 | void escapeSelection(); |
119 | |
120 | protected: |
121 | void contextMenuEvent(QContextMenuEvent *event) override; |
122 | |
123 | private: |
124 | QAction *escapeSelectionAction; |
125 | QAction *copyToCodeAction; |
126 | QAction *pasteFromCodeAction; |
127 | }; |
128 | |
129 | PatternLineEdit::PatternLineEdit(QWidget *parent) : |
130 | QLineEdit(parent), |
131 | escapeSelectionAction(new QAction(tr("Escape Selection" ), this)), |
132 | copyToCodeAction(new QAction(tr("Copy to Code" ), this)), |
133 | pasteFromCodeAction(new QAction(tr("Paste from Code" ), this)) |
134 | { |
135 | setClearButtonEnabled(true); |
136 | connect(escapeSelectionAction, &QAction::triggered, this, &PatternLineEdit::escapeSelection); |
137 | connect(copyToCodeAction, &QAction::triggered, this, &PatternLineEdit::copyToCode); |
138 | connect(pasteFromCodeAction, &QAction::triggered, this, &PatternLineEdit::pasteFromCode); |
139 | #if !QT_CONFIG(clipboard) |
140 | copyToCodeAction->setEnabled(false); |
141 | pasteFromCodeAction->setEnabled(false); |
142 | #endif |
143 | } |
144 | |
145 | void PatternLineEdit::escapeSelection() |
146 | { |
147 | const QString selection = selectedText(); |
148 | const QString escapedSelection = QRegularExpression::escape(selection); |
149 | if (escapedSelection != selection) { |
150 | QString t = text(); |
151 | t.replace(selectionStart(), selection.size(), escapedSelection); |
152 | setText(t); |
153 | } |
154 | } |
155 | |
156 | void PatternLineEdit::copyToCode() |
157 | { |
158 | #if QT_CONFIG(clipboard) |
159 | QGuiApplication::clipboard()->setText(patternToCode(text())); |
160 | #endif |
161 | } |
162 | |
163 | void PatternLineEdit::pasteFromCode() |
164 | { |
165 | #if QT_CONFIG(clipboard) |
166 | setText(codeToPattern(QGuiApplication::clipboard()->text())); |
167 | #endif |
168 | } |
169 | |
170 | void PatternLineEdit::(QContextMenuEvent *event) |
171 | { |
172 | QMenu * = createStandardContextMenu(); |
173 | menu->setAttribute(Qt::WA_DeleteOnClose); |
174 | menu->addSeparator(); |
175 | escapeSelectionAction->setEnabled(hasSelectedText()); |
176 | menu->addAction(escapeSelectionAction); |
177 | menu->addSeparator(); |
178 | menu->addAction(copyToCodeAction); |
179 | menu->addAction(pasteFromCodeAction); |
180 | menu->popup(event->globalPos()); |
181 | } |
182 | |
183 | class DisplayLineEdit : public QLineEdit |
184 | { |
185 | public: |
186 | explicit DisplayLineEdit(QWidget *parent = nullptr); |
187 | }; |
188 | |
189 | DisplayLineEdit::DisplayLineEdit(QWidget *parent) : QLineEdit(parent) |
190 | { |
191 | setReadOnly(true); |
192 | QPalette disabledPalette = palette(); |
193 | disabledPalette.setBrush(QPalette::Base, disabledPalette.brush(QPalette::Disabled, QPalette::Base)); |
194 | setPalette(disabledPalette); |
195 | |
196 | #if QT_CONFIG(clipboard) |
197 | QAction *copyAction = new QAction(this); |
198 | copyAction->setText(RegularExpressionDialog::tr("Copy to clipboard" )); |
199 | copyAction->setIcon(QIcon(QStringLiteral(":/images/copy.png" ))); |
200 | connect(copyAction, &QAction::triggered, this, |
201 | [this] () { QGuiApplication::clipboard()->setText(text()); }); |
202 | addAction(copyAction, QLineEdit::TrailingPosition); |
203 | #endif |
204 | } |
205 | |
206 | RegularExpressionDialog::RegularExpressionDialog(QWidget *parent) |
207 | : QDialog(parent) |
208 | { |
209 | setupUi(); |
210 | setWindowTitle(tr("QRegularExpression Example" )); |
211 | |
212 | connect(patternLineEdit, &QLineEdit::textChanged, this, &RegularExpressionDialog::refresh); |
213 | connect(subjectTextEdit, &QPlainTextEdit::textChanged, this, &RegularExpressionDialog::refresh); |
214 | |
215 | connect(caseInsensitiveOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
216 | connect(dotMatchesEverythingOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
217 | connect(multilineOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
218 | connect(extendedPatternSyntaxOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
219 | connect(invertedGreedinessOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
220 | connect(dontCaptureOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
221 | connect(useUnicodePropertiesOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
222 | |
223 | connect(offsetSpinBox, &QSpinBox::valueChanged, |
224 | this, &RegularExpressionDialog::refresh); |
225 | |
226 | connect(matchTypeComboBox, &QComboBox::currentIndexChanged, |
227 | this, &RegularExpressionDialog::refresh); |
228 | |
229 | connect(anchoredMatchOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
230 | connect(dontCheckSubjectStringMatchOptionCheckBox, &QCheckBox::toggled, this, &RegularExpressionDialog::refresh); |
231 | |
232 | patternLineEdit->setText(tr("(\\+?\\d+)-(?<prefix>\\d+)-(?<number>\\w+)" )); |
233 | subjectTextEdit->setPlainText(tr("My office number is +43-152-0123456, my mobile is 001-41-255512 instead." )); |
234 | |
235 | refresh(); |
236 | } |
237 | |
238 | void RegularExpressionDialog::setResultUiEnabled(bool enabled) |
239 | { |
240 | matchDetailsTreeWidget->setEnabled(enabled); |
241 | namedGroupsTreeWidget->setEnabled(enabled); |
242 | } |
243 | |
244 | static void setTextColor(QWidget *widget, const QColor &color) |
245 | { |
246 | QPalette palette = widget->palette(); |
247 | palette.setColor(QPalette::Text, color); |
248 | widget->setPalette(palette); |
249 | } |
250 | |
251 | void RegularExpressionDialog::refresh() |
252 | { |
253 | setUpdatesEnabled(false); |
254 | |
255 | const QString pattern = patternLineEdit->text(); |
256 | const QString text = subjectTextEdit->toPlainText(); |
257 | |
258 | offsetSpinBox->setMaximum(qMax(0, text.length() - 1)); |
259 | |
260 | escapedPatternLineEdit->setText(patternToCode(pattern)); |
261 | rawStringLiteralLineEdit->setText(rawStringLiteral(pattern)); |
262 | |
263 | setTextColor(patternLineEdit, subjectTextEdit->palette().color(QPalette::Text)); |
264 | matchDetailsTreeWidget->clear(); |
265 | namedGroupsTreeWidget->clear(); |
266 | regexpStatusLabel->setText(QString()); |
267 | |
268 | if (pattern.isEmpty()) { |
269 | setResultUiEnabled(false); |
270 | setUpdatesEnabled(true); |
271 | return; |
272 | } |
273 | |
274 | QRegularExpression rx(pattern); |
275 | if (!rx.isValid()) { |
276 | setTextColor(patternLineEdit, Qt::red); |
277 | regexpStatusLabel->setText(tr("Invalid: syntax error at position %1 (%2)" ) |
278 | .arg(rx.patternErrorOffset()) |
279 | .arg(rx.errorString())); |
280 | setResultUiEnabled(false); |
281 | setUpdatesEnabled(true); |
282 | return; |
283 | } |
284 | |
285 | setResultUiEnabled(true); |
286 | |
287 | QRegularExpression::MatchType matchType = qvariant_cast<QRegularExpression::MatchType>(matchTypeComboBox->currentData()); |
288 | QRegularExpression::PatternOptions patternOptions = QRegularExpression::NoPatternOption; |
289 | QRegularExpression::MatchOptions matchOptions = QRegularExpression::NoMatchOption; |
290 | |
291 | if (anchoredMatchOptionCheckBox->isChecked()) |
292 | matchOptions |= QRegularExpression::AnchorAtOffsetMatchOption; |
293 | if (dontCheckSubjectStringMatchOptionCheckBox->isChecked()) |
294 | matchOptions |= QRegularExpression::DontCheckSubjectStringMatchOption; |
295 | |
296 | if (caseInsensitiveOptionCheckBox->isChecked()) |
297 | patternOptions |= QRegularExpression::CaseInsensitiveOption; |
298 | if (dotMatchesEverythingOptionCheckBox->isChecked()) |
299 | patternOptions |= QRegularExpression::DotMatchesEverythingOption; |
300 | if (multilineOptionCheckBox->isChecked()) |
301 | patternOptions |= QRegularExpression::MultilineOption; |
302 | if (extendedPatternSyntaxOptionCheckBox->isChecked()) |
303 | patternOptions |= QRegularExpression::ExtendedPatternSyntaxOption; |
304 | if (invertedGreedinessOptionCheckBox->isChecked()) |
305 | patternOptions |= QRegularExpression::InvertedGreedinessOption; |
306 | if (dontCaptureOptionCheckBox->isChecked()) |
307 | patternOptions |= QRegularExpression::DontCaptureOption; |
308 | if (useUnicodePropertiesOptionCheckBox->isChecked()) |
309 | patternOptions |= QRegularExpression::UseUnicodePropertiesOption; |
310 | |
311 | rx.setPatternOptions(patternOptions); |
312 | |
313 | const int capturingGroupsCount = rx.captureCount() + 1; |
314 | |
315 | QRegularExpressionMatchIterator iterator = rx.globalMatch(text, offsetSpinBox->value(), matchType, matchOptions); |
316 | int i = 0; |
317 | |
318 | while (iterator.hasNext()) { |
319 | QRegularExpressionMatch match = iterator.next(); |
320 | |
321 | QTreeWidgetItem *matchDetailTopItem = new QTreeWidgetItem(matchDetailsTreeWidget); |
322 | matchDetailTopItem->setText(0, QString::number(i)); |
323 | |
324 | for (int captureGroupIndex = 0; captureGroupIndex < capturingGroupsCount; ++captureGroupIndex) { |
325 | QTreeWidgetItem *matchDetailItem = new QTreeWidgetItem(matchDetailTopItem); |
326 | matchDetailItem->setText(1, QString::number(captureGroupIndex)); |
327 | matchDetailItem->setText(2, match.captured(captureGroupIndex)); |
328 | } |
329 | |
330 | ++i; |
331 | } |
332 | |
333 | matchDetailsTreeWidget->expandAll(); |
334 | |
335 | regexpStatusLabel->setText(tr("Valid" )); |
336 | |
337 | const QStringList namedCaptureGroups = rx.namedCaptureGroups(); |
338 | for (int i = 0; i < namedCaptureGroups.size(); ++i) { |
339 | const QString currentNamedCaptureGroup = namedCaptureGroups.at(i); |
340 | |
341 | QTreeWidgetItem *namedGroupItem = new QTreeWidgetItem(namedGroupsTreeWidget); |
342 | namedGroupItem->setText(0, QString::number(i)); |
343 | namedGroupItem->setText(1, currentNamedCaptureGroup.isNull() ? tr("<no name>" ) : currentNamedCaptureGroup); |
344 | } |
345 | |
346 | |
347 | setUpdatesEnabled(true); |
348 | } |
349 | |
350 | void RegularExpressionDialog::setupUi() |
351 | { |
352 | QWidget *leftHalfContainer = setupLeftUi(); |
353 | |
354 | QFrame *verticalSeparator = new QFrame; |
355 | verticalSeparator->setFrameStyle(QFrame::VLine | QFrame::Sunken); |
356 | |
357 | QWidget *rightHalfContainer = setupRightUi(); |
358 | |
359 | QHBoxLayout *mainLayout = new QHBoxLayout; |
360 | mainLayout->addWidget(leftHalfContainer); |
361 | mainLayout->addWidget(verticalSeparator); |
362 | mainLayout->addWidget(rightHalfContainer); |
363 | |
364 | setLayout(mainLayout); |
365 | } |
366 | |
367 | QWidget *RegularExpressionDialog::setupLeftUi() |
368 | { |
369 | QWidget *container = new QWidget; |
370 | |
371 | QFormLayout *layout = new QFormLayout(container); |
372 | layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); |
373 | layout->setContentsMargins(QMargins()); |
374 | |
375 | QLabel *regexpAndSubjectLabel = new QLabel(tr("<h3>Regular expression and text input</h3>" )); |
376 | layout->addRow(regexpAndSubjectLabel); |
377 | |
378 | patternLineEdit = new PatternLineEdit; |
379 | patternLineEdit->setClearButtonEnabled(true); |
380 | layout->addRow(tr("&Pattern:" ), patternLineEdit); |
381 | |
382 | rawStringLiteralLineEdit = new DisplayLineEdit; |
383 | layout->addRow(tr("&Raw string literal:" ), rawStringLiteralLineEdit); |
384 | escapedPatternLineEdit = new DisplayLineEdit; |
385 | layout->addRow(tr("&Escaped pattern:" ), escapedPatternLineEdit); |
386 | |
387 | subjectTextEdit = new QPlainTextEdit; |
388 | layout->addRow(tr("&Subject text:" ), subjectTextEdit); |
389 | |
390 | caseInsensitiveOptionCheckBox = new QCheckBox(tr("Case insensitive (/i)" )); |
391 | dotMatchesEverythingOptionCheckBox = new QCheckBox(tr("Dot matches everything (/s)" )); |
392 | multilineOptionCheckBox = new QCheckBox(tr("Multiline (/m)" )); |
393 | extendedPatternSyntaxOptionCheckBox = new QCheckBox(tr("Extended pattern (/x)" )); |
394 | invertedGreedinessOptionCheckBox = new QCheckBox(tr("Inverted greediness" )); |
395 | dontCaptureOptionCheckBox = new QCheckBox(tr("Don't capture" )); |
396 | useUnicodePropertiesOptionCheckBox = new QCheckBox(tr("Use unicode properties (/u)" )); |
397 | |
398 | QGridLayout *patternOptionsCheckBoxLayout = new QGridLayout; |
399 | int gridRow = 0; |
400 | patternOptionsCheckBoxLayout->addWidget(caseInsensitiveOptionCheckBox, gridRow, 1); |
401 | patternOptionsCheckBoxLayout->addWidget(dotMatchesEverythingOptionCheckBox, gridRow, 2); |
402 | ++gridRow; |
403 | patternOptionsCheckBoxLayout->addWidget(multilineOptionCheckBox, gridRow, 1); |
404 | patternOptionsCheckBoxLayout->addWidget(extendedPatternSyntaxOptionCheckBox, gridRow, 2); |
405 | ++gridRow; |
406 | patternOptionsCheckBoxLayout->addWidget(invertedGreedinessOptionCheckBox, gridRow, 1); |
407 | patternOptionsCheckBoxLayout->addWidget(dontCaptureOptionCheckBox, gridRow, 2); |
408 | ++gridRow; |
409 | patternOptionsCheckBoxLayout->addWidget(useUnicodePropertiesOptionCheckBox, gridRow, 1); |
410 | |
411 | layout->addRow(tr("Pattern options:" ), patternOptionsCheckBoxLayout); |
412 | |
413 | offsetSpinBox = new QSpinBox; |
414 | layout->addRow(tr("Match &offset:" ), offsetSpinBox); |
415 | |
416 | matchTypeComboBox = new QComboBox; |
417 | matchTypeComboBox->addItem(tr("Normal" ), QVariant::fromValue(QRegularExpression::NormalMatch)); |
418 | matchTypeComboBox->addItem(tr("Partial prefer complete" ), QVariant::fromValue(QRegularExpression::PartialPreferCompleteMatch)); |
419 | matchTypeComboBox->addItem(tr("Partial prefer first" ), QVariant::fromValue(QRegularExpression::PartialPreferFirstMatch)); |
420 | matchTypeComboBox->addItem(tr("No match" ), QVariant::fromValue(QRegularExpression::NoMatch)); |
421 | layout->addRow(tr("Match &type:" ), matchTypeComboBox); |
422 | |
423 | dontCheckSubjectStringMatchOptionCheckBox = new QCheckBox(tr("Don't check subject string" )); |
424 | anchoredMatchOptionCheckBox = new QCheckBox(tr("Anchored match" )); |
425 | |
426 | QGridLayout *matchOptionsCheckBoxLayout = new QGridLayout; |
427 | matchOptionsCheckBoxLayout->addWidget(dontCheckSubjectStringMatchOptionCheckBox, 0, 0); |
428 | matchOptionsCheckBoxLayout->addWidget(anchoredMatchOptionCheckBox, 0, 1); |
429 | layout->addRow(tr("Match options:" ), matchOptionsCheckBoxLayout); |
430 | |
431 | return container; |
432 | } |
433 | |
434 | QWidget *RegularExpressionDialog::setupRightUi() |
435 | { |
436 | QWidget *container = new QWidget; |
437 | |
438 | QFormLayout *layout = new QFormLayout(container); |
439 | layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); |
440 | layout->setContentsMargins(QMargins()); |
441 | |
442 | QLabel *matchInfoLabel = new QLabel(tr("<h3>Match information</h3>" )); |
443 | layout->addRow(matchInfoLabel); |
444 | |
445 | matchDetailsTreeWidget = new QTreeWidget; |
446 | matchDetailsTreeWidget->setHeaderLabels(QStringList() << tr("Match index" ) << tr("Group index" ) << tr("Captured string" )); |
447 | matchDetailsTreeWidget->setSizeAdjustPolicy(QTreeWidget::AdjustToContents); |
448 | layout->addRow(tr("Match details:" ), matchDetailsTreeWidget); |
449 | |
450 | QFrame *horizontalSeparator = new QFrame; |
451 | horizontalSeparator->setFrameStyle(QFrame::HLine | QFrame::Sunken); |
452 | layout->addRow(horizontalSeparator); |
453 | |
454 | QLabel *regexpInfoLabel = new QLabel(tr("<h3>Regular expression information</h3>" )); |
455 | layout->addRow(regexpInfoLabel); |
456 | |
457 | regexpStatusLabel = new QLabel(tr("Valid" )); |
458 | regexpStatusLabel->setWordWrap(true); |
459 | layout->addRow(tr("Pattern status:" ), regexpStatusLabel); |
460 | |
461 | namedGroupsTreeWidget = new QTreeWidget; |
462 | namedGroupsTreeWidget->setHeaderLabels(QStringList() << tr("Index" ) << tr("Named group" )); |
463 | namedGroupsTreeWidget->setSizeAdjustPolicy(QTreeWidget::AdjustToContents); |
464 | namedGroupsTreeWidget->setRootIsDecorated(false); |
465 | layout->addRow(tr("Named groups:" ), namedGroupsTreeWidget); |
466 | |
467 | return container; |
468 | } |
469 | |
470 | #include "regularexpressiondialog.moc" |
471 | |