1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "regexpwindow.h"
37 #include <QtGui/QCheckBox>
38 #include <QtGui/QComboBox>
39 #include <QtGui/QLabel>
40 #include <QtGui/QLayout>
41 #include <QtGui/QLineEdit>
42 #include <QtGui/QContextMenuEvent>
43 #include <QtGui/QMenu>
44 #include <QtGui/QInputDialog>
46 using namespace RegExp::Internal;
48 RegExpWindow::RegExpWindow(QWidget *parent) :
50 patternLabel(new QLabel(tr("&Pattern:"))),
51 escapedPatternLabel(new QLabel(tr("&Escaped pattern:"))),
52 syntaxLabel(new QLabel(tr("&Pattern syntax:"))),
53 textLabel(new QLabel(tr("&Text:"))),
54 patternComboBox (new QComboBox),
55 escapedPatternLineEdit(new QLineEdit),
56 textComboBox(new QComboBox),
57 caseSensitiveCheckBox(new QCheckBox(tr("Case &sensitive"))),
58 minimalCheckBox(new QCheckBox(tr("&Minimal"))),
59 syntaxComboBox(new QComboBox),
60 indexLabel(new QLabel(tr("Index of match:"))),
61 matchedLengthLabel(new QLabel(tr("Matched length:"))),
62 indexEdit(new QLineEdit),
63 matchedLengthEdit(new QLineEdit)
65 QVBoxLayout *vboxLayout = new QVBoxLayout(this);
66 QGridLayout *mainLayout = new QGridLayout;
68 patternComboBox->setEditable(true);
69 patternComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
71 patternLabel->setBuddy(patternComboBox);
73 mainLayout->addWidget(patternLabel, 0, 0);
74 mainLayout->addWidget(patternComboBox, 0, 1);
76 escapedPatternLineEdit->setReadOnly(true);
77 QPalette palette = escapedPatternLineEdit->palette();
78 palette.setBrush(QPalette::Base, palette.brush(QPalette::Disabled, QPalette::Base));
79 escapedPatternLineEdit->setPalette(palette);
81 escapedPatternLabel->setBuddy(escapedPatternLineEdit);
83 mainLayout->addWidget(escapedPatternLabel, 1, 0);
84 mainLayout->addWidget(escapedPatternLineEdit, 1, 1);
86 syntaxComboBox->addItem(tr("Regular Expression v1"), QRegExp::RegExp);
87 syntaxComboBox->addItem(tr("Regular Expression v2"), QRegExp::RegExp2);
88 syntaxComboBox->addItem(tr("Wildcard"), QRegExp::Wildcard);
89 syntaxComboBox->addItem(tr("Fixed String"), QRegExp::FixedString);
91 syntaxLabel->setBuddy(syntaxComboBox);
93 mainLayout->addWidget(syntaxLabel, 2, 0);
94 mainLayout->addWidget(syntaxComboBox, 2, 1);
96 QHBoxLayout *checkBoxLayout = new QHBoxLayout;
98 caseSensitiveCheckBox->setChecked(true);
100 checkBoxLayout->addWidget(caseSensitiveCheckBox);
101 checkBoxLayout->addWidget(minimalCheckBox);
102 checkBoxLayout->addStretch(1);
104 mainLayout->addLayout(checkBoxLayout, 3, 0, 1, 2);
106 textComboBox->setEditable(true);
107 textComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
109 textLabel->setBuddy(textComboBox);
111 mainLayout->addWidget(textLabel, 4, 0);
112 mainLayout->addWidget(textComboBox, 4, 1);
114 indexEdit->setReadOnly(true);
116 mainLayout->addWidget(indexLabel, 5, 0);
117 mainLayout->addWidget(indexEdit, 5, 1);
119 matchedLengthEdit->setReadOnly(true);
121 mainLayout->addWidget(matchedLengthLabel, 6, 0);
122 mainLayout->addWidget(matchedLengthEdit, 6, 1);
124 vboxLayout->addLayout(mainLayout);
125 vboxLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
127 for (int i = 0; i < MaxCaptures; ++i) {
128 captureLabels[i] = new QLabel(tr("Capture %1:").arg(i));
129 captureEdits[i] = new QLineEdit;
130 captureEdits[i]->setReadOnly(true);
132 captureLabels[0]->setText(tr("Match:"));
134 for (int j = 0; j < MaxCaptures; ++j) {
135 mainLayout->addWidget(captureLabels[j], 7 + j, 0);
136 mainLayout->addWidget(captureEdits[j], 7 + j, 1);
139 connect(patternComboBox, SIGNAL(editTextChanged(const QString &)), this, SLOT(refresh()));
140 connect(textComboBox, SIGNAL(editTextChanged(const QString &)), this, SLOT(refresh()));
141 connect(caseSensitiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(refresh()));
142 connect(minimalCheckBox, SIGNAL(toggled(bool)), this, SLOT(refresh()));
143 connect(syntaxComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(refresh()));
145 setWindowTitle(tr("Regular Expression"));
149 static const char *escapedBackSlash = "\\\\";
150 static const char *escapedDoubleQuote = "\\\"";
152 static QString escapePattern(const QString &pattern)
154 QString escaped = pattern;
155 escaped.replace(QString(QLatin1Char('\\')) , QLatin1String(escapedBackSlash));
156 const QChar doubleQuote(QLatin1Char('"'));
157 escaped.replace(doubleQuote, QString(QLatin1String(escapedDoubleQuote)));
158 escaped.prepend(doubleQuote);
159 escaped.append(doubleQuote);
163 static QString unescapePattern(QString escaped)
166 const QChar doubleQuote(QLatin1Char('"'));
167 if (escaped.endsWith(doubleQuote))
168 escaped.truncate(escaped.size() - 1);
169 if (escaped.startsWith(doubleQuote))
170 escaped.remove(0, 1);
172 const int size = escaped.size();
176 // parse out escapes. Do not just replace.
178 const QChar backSlash = QLatin1Char('\\');
179 bool escapeSeen = false;
180 for (int i = 0; i < size; i++) {
181 const QChar c = escaped.at(i);
182 if (c == backSlash && !escapeSeen)
185 pattern.push_back(c);
192 void RegExpWindow::refresh()
194 setUpdatesEnabled(false);
196 const QString pattern = patternComboBox->currentText();
197 const QString text = textComboBox->currentText();
199 escapedPatternLineEdit->setText(escapePattern(pattern));
202 const Qt::CaseSensitivity cs = caseSensitiveCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
203 rx.setCaseSensitivity(cs);
204 rx.setMinimal(minimalCheckBox->isChecked());
205 const QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(
206 syntaxComboBox->itemData(syntaxComboBox->currentIndex()).toInt());
207 rx.setPatternSyntax(syntax);
209 QPalette palette = patternComboBox->palette();
211 palette.setColor(QPalette::Text,
212 textComboBox->palette().color(QPalette::Text));
214 palette.setColor(QPalette::Text, Qt::red);
216 patternComboBox->setPalette(palette);
218 indexEdit->setText(QString::number(rx.indexIn(text)));
219 matchedLengthEdit->setText(QString::number(rx.matchedLength()));
220 for (int i = 0; i < MaxCaptures; ++i) {
221 const bool enabled = i <= rx.numCaptures();
222 captureLabels[i]->setEnabled(enabled);
223 captureEdits[i]->setEnabled(enabled);
224 captureEdits[i]->setText(rx.cap(i));
227 setUpdatesEnabled(true);
230 static void saveTextCombo(const QComboBox *cb, QString ¤t, QStringList &items)
232 current = cb->currentText();
234 if (const int count = cb->count())
235 for (int i = 0;i < count; i++) {
236 const QString text = cb->itemText(i);
237 if (items.indexOf(text) == -1)
242 Settings RegExpWindow::settings() const
245 rc.m_patternSyntax = static_cast<QRegExp::PatternSyntax>(syntaxComboBox->itemData(syntaxComboBox->currentIndex()).toInt());
246 rc.m_minimal = minimalCheckBox->checkState() == Qt::Checked;
247 rc.m_caseSensitive = caseSensitiveCheckBox->checkState() == Qt::Checked;
248 saveTextCombo(patternComboBox, rc.m_currentPattern, rc.m_patterns);
249 saveTextCombo(textComboBox, rc.m_currentMatch, rc.m_matches);
253 static void restoreTextCombo(const QString ¤t, const QStringList &items, QComboBox *cb)
257 cb->lineEdit()->setText(current);
260 void RegExpWindow::setSettings(const Settings &s)
262 const int patternIndex = syntaxComboBox->findData(QVariant(s.m_patternSyntax));
263 syntaxComboBox->setCurrentIndex(patternIndex);
264 minimalCheckBox->setCheckState(s.m_minimal ? Qt::Checked : Qt::Unchecked);
265 caseSensitiveCheckBox->setCheckState(s.m_caseSensitive ? Qt::Checked : Qt::Unchecked);
266 restoreTextCombo(s.m_currentPattern, s.m_patterns, patternComboBox);
267 restoreTextCombo(s.m_currentMatch, s.m_matches, textComboBox);
270 void RegExpWindow::contextMenuEvent(QContextMenuEvent *event)
274 QAction *enterQuotedAction = menu.addAction(tr("Enter Pattern from Code..."));
275 connect(enterQuotedAction, SIGNAL(triggered()), this, SLOT(enterEscaped()));
278 QAction *clearPatternsAction = menu.addAction(tr("Clear Patterns"));
279 connect(clearPatternsAction, SIGNAL(triggered()), patternComboBox, SLOT(clear()));
281 QAction *clearTextsAction = menu.addAction(tr("Clear Text"));
282 connect(clearTextsAction, SIGNAL(triggered()), textComboBox, SLOT(clear()));
285 menu.exec(event->globalPos());
288 void RegExpWindow::enterEscaped()
290 const QString escapedPattern = QInputDialog::getText (this, tr("Enter Pattern from Code"), tr("Pattern"));
291 if ( escapedPattern.isEmpty())
293 patternComboBox->lineEdit()->setText(unescapePattern(escapedPattern));