OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / regexp / regexpwindow.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "regexpwindow.h"
34 #include "settings.h"
35
36 #include <QtGui/QCheckBox>
37 #include <QtGui/QComboBox>
38 #include <QtGui/QLabel>
39 #include <QtGui/QLayout>
40 #include <QtGui/QLineEdit>
41 #include <QtGui/QContextMenuEvent>
42 #include <QtGui/QMenu>
43 #include <QtGui/QInputDialog>
44
45 using namespace RegExp::Internal;
46
47 RegExpWindow::RegExpWindow(QWidget *parent) :
48    QWidget(parent),
49    patternLabel(new QLabel(tr("&Pattern:"))),
50    escapedPatternLabel(new QLabel(tr("&Escaped pattern:"))),
51    syntaxLabel(new QLabel(tr("&Pattern syntax:"))),
52    textLabel(new QLabel(tr("&Text:"))),
53    patternComboBox (new QComboBox),
54    escapedPatternLineEdit(new QLineEdit),
55    textComboBox(new QComboBox),
56    caseSensitiveCheckBox(new QCheckBox(tr("Case &sensitive"))),
57    minimalCheckBox(new QCheckBox(tr("&Minimal"))),
58    syntaxComboBox(new QComboBox),
59    indexLabel(new QLabel(tr("Index of match:"))),
60    matchedLengthLabel(new QLabel(tr("Matched length:"))),
61    indexEdit(new QLineEdit),
62    matchedLengthEdit(new QLineEdit)
63 {
64     QVBoxLayout *vboxLayout = new QVBoxLayout(this);
65     QGridLayout *mainLayout = new QGridLayout;
66
67     patternComboBox->setEditable(true);
68     patternComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
69
70     patternLabel->setBuddy(patternComboBox);
71
72     mainLayout->addWidget(patternLabel, 0, 0);
73     mainLayout->addWidget(patternComboBox, 0, 1);
74
75     escapedPatternLineEdit->setReadOnly(true);
76     QPalette palette = escapedPatternLineEdit->palette();
77     palette.setBrush(QPalette::Base, palette.brush(QPalette::Disabled, QPalette::Base));
78     escapedPatternLineEdit->setPalette(palette);
79
80     escapedPatternLabel->setBuddy(escapedPatternLineEdit);
81
82     mainLayout->addWidget(escapedPatternLabel, 1, 0);
83     mainLayout->addWidget(escapedPatternLineEdit, 1, 1);
84
85     syntaxComboBox->addItem(tr("Regular Expression v1"), QRegExp::RegExp);
86     syntaxComboBox->addItem(tr("Regular Expression v2"), QRegExp::RegExp2);
87     syntaxComboBox->addItem(tr("Wildcard"), QRegExp::Wildcard);
88     syntaxComboBox->addItem(tr("Fixed String"), QRegExp::FixedString);
89
90     syntaxLabel->setBuddy(syntaxComboBox);
91
92     mainLayout->addWidget(syntaxLabel, 2, 0);
93     mainLayout->addWidget(syntaxComboBox, 2, 1);
94
95     QHBoxLayout *checkBoxLayout = new QHBoxLayout;
96
97     caseSensitiveCheckBox->setChecked(true);
98
99     checkBoxLayout->addWidget(caseSensitiveCheckBox);
100     checkBoxLayout->addWidget(minimalCheckBox);
101     checkBoxLayout->addStretch(1);
102
103     mainLayout->addLayout(checkBoxLayout, 3, 0, 1, 2);
104
105     textComboBox->setEditable(true);
106     textComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
107
108     textLabel->setBuddy(textComboBox);
109
110     mainLayout->addWidget(textLabel, 4, 0);
111     mainLayout->addWidget(textComboBox, 4, 1);
112
113     indexEdit->setReadOnly(true);
114
115     mainLayout->addWidget(indexLabel, 5, 0);
116     mainLayout->addWidget(indexEdit, 5, 1);
117
118     matchedLengthEdit->setReadOnly(true);
119
120     mainLayout->addWidget(matchedLengthLabel, 6, 0);
121     mainLayout->addWidget(matchedLengthEdit, 6, 1);
122
123     vboxLayout->addLayout(mainLayout);
124     vboxLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
125
126     for (int i = 0; i < MaxCaptures; ++i) {
127         captureLabels[i] = new QLabel(tr("Capture %1:").arg(i));
128         captureEdits[i] = new QLineEdit;
129         captureEdits[i]->setReadOnly(true);
130     }
131     captureLabels[0]->setText(tr("Match:"));
132
133     for (int j = 0; j < MaxCaptures; ++j) {
134         mainLayout->addWidget(captureLabels[j], 7 + j, 0);
135         mainLayout->addWidget(captureEdits[j], 7 + j, 1);
136     }
137
138     connect(patternComboBox, SIGNAL(editTextChanged(const QString &)), this, SLOT(refresh()));
139     connect(textComboBox, SIGNAL(editTextChanged(const QString &)), this, SLOT(refresh()));
140     connect(caseSensitiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(refresh()));
141     connect(minimalCheckBox, SIGNAL(toggled(bool)), this, SLOT(refresh()));
142     connect(syntaxComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(refresh()));
143
144     setWindowTitle(tr("Regular Expression"));
145     refresh();
146 }
147
148 static const char *escapedBackSlash = "\\\\";
149 static const char *escapedDoubleQuote = "\\\"";
150
151 static QString escapePattern(const QString &pattern)
152 {
153     QString escaped = pattern;
154     escaped.replace(QString(QLatin1Char('\\')) , QLatin1String(escapedBackSlash));
155     const QChar doubleQuote(QLatin1Char('"'));
156     escaped.replace(doubleQuote, QString(QLatin1String(escapedDoubleQuote)));
157     escaped.prepend(doubleQuote);
158     escaped.append(doubleQuote);
159     return escaped;
160 }
161
162 static QString unescapePattern(QString escaped)
163 {
164     // remove quotes
165     const QChar doubleQuote(QLatin1Char('"'));
166     if (escaped.endsWith(doubleQuote))
167         escaped.truncate(escaped.size() - 1);
168     if (escaped.startsWith(doubleQuote))
169         escaped.remove(0, 1);
170
171     const int size = escaped.size();
172     if (!size)
173         return QString();
174
175     // parse out escapes. Do not just replace.
176     QString pattern;
177     const QChar backSlash = QLatin1Char('\\');
178     bool escapeSeen = false;
179     for (int  i = 0; i < size; i++) {
180         const QChar c = escaped.at(i);
181         if (c == backSlash && !escapeSeen)
182             escapeSeen = true;
183         else {
184             pattern.push_back(c);
185             escapeSeen = false;
186         }
187     }
188     return pattern;
189 }
190
191 void RegExpWindow::refresh()
192 {
193     setUpdatesEnabled(false);
194
195     const QString pattern = patternComboBox->currentText();
196     const QString text = textComboBox->currentText();
197
198     escapedPatternLineEdit->setText(escapePattern(pattern));
199
200     QRegExp rx(pattern);
201     const Qt::CaseSensitivity cs = caseSensitiveCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
202     rx.setCaseSensitivity(cs);
203     rx.setMinimal(minimalCheckBox->isChecked());
204     const QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(
205             syntaxComboBox->itemData(syntaxComboBox->currentIndex()).toInt());
206     rx.setPatternSyntax(syntax);
207
208     QPalette palette = patternComboBox->palette();
209     if (rx.isValid()) {
210         palette.setColor(QPalette::Text,
211                          textComboBox->palette().color(QPalette::Text));
212     } else {
213         palette.setColor(QPalette::Text, Qt::red);
214     }
215     patternComboBox->setPalette(palette);
216
217     indexEdit->setText(QString::number(rx.indexIn(text)));
218     matchedLengthEdit->setText(QString::number(rx.matchedLength()));
219     for (int i = 0; i < MaxCaptures; ++i) {
220         const bool enabled = i <= rx.numCaptures();
221         captureLabels[i]->setEnabled(enabled);
222         captureEdits[i]->setEnabled(enabled);
223         captureEdits[i]->setText(rx.cap(i));
224     }
225
226     setUpdatesEnabled(true);
227 }
228
229 static void saveTextCombo(const QComboBox *cb, QString &current, QStringList &items)
230 {
231     current =  cb->currentText();
232     items.clear();
233     if (const int count = cb->count())
234         for (int i = 0;i <  count; i++) {
235             const QString text = cb->itemText(i);
236             if (items.indexOf(text) == -1)
237                 items += text;
238         }
239 }
240
241 Settings RegExpWindow::settings() const
242 {
243     Settings rc;
244     rc.m_patternSyntax = static_cast<QRegExp::PatternSyntax>(syntaxComboBox->itemData(syntaxComboBox->currentIndex()).toInt());
245     rc.m_minimal = minimalCheckBox->checkState() == Qt::Checked;
246     rc.m_caseSensitive = caseSensitiveCheckBox->checkState() == Qt::Checked;
247     saveTextCombo(patternComboBox, rc.m_currentPattern, rc.m_patterns);
248     saveTextCombo(textComboBox,  rc.m_currentMatch, rc.m_matches);
249     return rc;
250 }
251
252 static void restoreTextCombo(const QString &current, const QStringList &items, QComboBox *cb)
253 {
254     cb->clear();
255     cb->addItems(items);
256     cb->lineEdit()->setText(current);
257 }
258
259 void RegExpWindow::setSettings(const Settings &s)
260 {
261     const int patternIndex = syntaxComboBox->findData(QVariant(s.m_patternSyntax));
262     syntaxComboBox->setCurrentIndex(patternIndex);
263     minimalCheckBox->setCheckState(s.m_minimal ? Qt::Checked : Qt::Unchecked);
264     caseSensitiveCheckBox->setCheckState(s.m_caseSensitive ? Qt::Checked : Qt::Unchecked);
265     restoreTextCombo(s.m_currentPattern, s.m_patterns, patternComboBox);
266     restoreTextCombo(s.m_currentMatch, s.m_matches, textComboBox);
267 }
268
269 void RegExpWindow::contextMenuEvent(QContextMenuEvent *event)
270 {
271     QMenu menu(this);
272
273     QAction *enterQuotedAction = menu.addAction(tr("Enter Pattern from Code..."));
274     connect(enterQuotedAction, SIGNAL(triggered()), this, SLOT(enterEscaped()));
275     menu.addSeparator();
276
277     QAction *clearPatternsAction = menu.addAction(tr("Clear Patterns"));
278     connect(clearPatternsAction, SIGNAL(triggered()), patternComboBox, SLOT(clear()));
279
280     QAction *clearTextsAction = menu.addAction(tr("Clear Text"));
281     connect(clearTextsAction, SIGNAL(triggered()), textComboBox, SLOT(clear()));
282
283     event->accept();
284     menu.exec(event->globalPos());
285 }
286
287 void  RegExpWindow::enterEscaped()
288 {
289     const QString escapedPattern = QInputDialog::getText (this, tr("Enter Pattern from Code"), tr("Pattern"));
290     if ( escapedPattern.isEmpty())
291         return;
292     patternComboBox->lineEdit()->setText(unescapePattern(escapedPattern));
293
294 }