cmake-gui: Add regex explorer window

This commit is contained in:
Gregor Jasny 2015-11-18 22:40:59 +01:00
parent 9cbb8058ca
commit fc656fa4fe
7 changed files with 390 additions and 0 deletions

View File

@ -0,0 +1,6 @@
regex-explorer
--------------
* The Qt base CMake GUI got a Regular Expression Explorer which could be used to
create and evaluate regular expressions in real-time. The explorer window
is available via the ``Tools`` menu.

View File

@ -113,12 +113,15 @@ set(SRCS
QCMakeCacheView.h
QCMakeWidgets.cxx
QCMakeWidgets.h
RegexExplorer.cxx
RegexExplorer.h
)
QT4_WRAP_UI(UI_SRCS
CMakeSetupDialog.ui
Compilers.ui
CrossCompiler.ui
AddCacheEntry.ui
RegexExplorer.ui
)
QT4_WRAP_CPP(MOC_SRCS
AddCacheEntry.h
@ -128,6 +131,7 @@ QT4_WRAP_CPP(MOC_SRCS
QCMake.h
QCMakeCacheView.h
QCMakeWidgets.h
RegexExplorer.h
)
QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)

View File

@ -33,6 +33,7 @@
#include "QCMakeCacheView.h"
#include "AddCacheEntry.h"
#include "FirstConfigure.h"
#include "RegexExplorer.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
@ -125,6 +126,9 @@ CMakeSetupDialog::CMakeSetupDialog()
this, SLOT(doInstallForCommandLine()));
#endif
ToolsMenu->addSeparator();
ToolsMenu->addAction(tr("Regular Expression Explorer..."),
this, SLOT(doRegexExplorerDialog()));
ToolsMenu->addSeparator();
ToolsMenu->addAction(tr("&Find in Output..."),
this, SLOT(doOutputFindDialog()),
QKeySequence::Find);
@ -1272,6 +1276,12 @@ void CMakeSetupDialog::doOutputFindDialog()
}
}
void CMakeSetupDialog::doRegexExplorerDialog()
{
RegexExplorer dialog(this);
dialog.exec();
}
void CMakeSetupDialog::doOutputFindPrev()
{
doOutputFindNext(false);

View File

@ -82,6 +82,7 @@ protected slots:
void doOutputFindNext(bool directionForward = true);
void doOutputFindPrev();
void doOutputErrorNext();
void doRegexExplorerDialog();
protected:

View File

@ -0,0 +1,166 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Kitware, Inc., Gregor Jasny
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "RegexExplorer.h"
RegexExplorer::RegexExplorer(QWidget* p) : QDialog(p), m_matched(false)
{
this->setupUi(this);
for(int i = 1; i < cmsys::RegularExpression::NSUBEXP; ++i)
{
matchNumber->addItem(
QString("Match %1").arg(QString::number(i)),
QVariant(i));
}
matchNumber->setCurrentIndex(0);
}
void RegexExplorer::setStatusColor(QWidget* widget, bool successful)
{
QColor color = successful ? QColor(0, 127, 0) : Qt::red;
QPalette palette = widget->palette();
palette.setColor(QPalette::Foreground, color);
widget->setPalette(palette);
}
void RegexExplorer::on_regularExpression_textChanged(const QString& text)
{
#ifdef QT_NO_STL
m_regex = text.toAscii().constData();
#else
m_regex = text.toStdString();
#endif
bool validExpression =
stripEscapes(m_regex) && m_regexParser.compile(m_regex);
if(!validExpression)
{
m_regexParser.set_invalid();
}
setStatusColor(labelRegexValid, validExpression);
on_inputText_textChanged();
}
void RegexExplorer::on_inputText_textChanged()
{
if(m_regexParser.is_valid())
{
QString plainText = inputText->toPlainText();
#ifdef QT_NO_STL
m_text = plainText.toAscii().constData();
#else
m_text = plainText.toStdString();
#endif
m_matched = m_regexParser.find(m_text);
}
else
{
m_matched = false;
}
setStatusColor(labelRegexMatch, m_matched);
if(!m_matched)
{
clearMatch();
return;
}
#ifdef QT_NO_STL
QString matchText = m_regexParser.match(0).c_str();
#else
QString matchText = QString::fromStdString(m_regexParser.match(0));
#endif
match0->setPlainText(matchText);
on_matchNumber_currentIndexChanged(matchNumber->currentIndex());
}
void RegexExplorer::on_matchNumber_currentIndexChanged(int index)
{
if(!m_matched)
{
return;
}
QVariant itemData = matchNumber->itemData(index);
int idx = itemData.toInt();
if(idx < 1 || idx >= cmsys::RegularExpression::NSUBEXP)
{
return;
}
#ifdef QT_NO_STL
QString match = m_regexParser.match(idx).c_str();
#else
QString match = QString::fromStdString(m_regexParser.match(idx));
#endif
matchN->setPlainText(match);
}
void RegexExplorer::clearMatch()
{
match0->clear();
matchN->clear();
}
bool RegexExplorer::stripEscapes(std::string& source)
{
const char* in = source.c_str();
std::string result;
result.reserve(source.size());
for(char inc = *in; inc != '\0'; inc = *++in)
{
if(inc == '\\')
{
char nextc = in[1];
if(nextc == 't')
{
result.append(1, '\t');
in++;
}
else if(nextc == 'n')
{
result.append(1, '\n');
in++;
}
else if(nextc == 't')
{
result.append(1, '\t');
in++;
}
else if(isalnum(nextc) || nextc == '\0')
{
return false;
}
else
{
result.append(1, nextc);
in++;
}
}
else
{
result.append(1, inc);
}
}
source = result;
return true;
}

View File

@ -0,0 +1,48 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2015 Kitware, Inc., Gregor Jasny
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef RegexExplorer_h
#define RegexExplorer_h
#include <string>
#include <cmsys/RegularExpression.hxx>
#include <QDialog>
#include "ui_RegexExplorer.h"
class QString;
class QWidget;
class RegexExplorer : public QDialog, public Ui::RegexExplorer
{
Q_OBJECT
public:
RegexExplorer(QWidget* p);
private slots:
void on_regularExpression_textChanged(const QString& text);
void on_inputText_textChanged();
void on_matchNumber_currentIndexChanged(int index);
private:
static void setStatusColor(QWidget* widget, bool successful);
static bool stripEscapes(std::string& regex);
void clearMatch();
cmsys::RegularExpression m_regexParser;
std::string m_text;
std::string m_regex;
bool m_matched;
};
#endif

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RegexExplorer</class>
<widget class="QDialog" name="RegexExplorer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>639</width>
<height>555</height>
</rect>
</property>
<property name="windowTitle">
<string>Regular Expression Explorer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Input Text</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="inputText"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Regular Expression</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelRegexValid">
<property name="text">
<string>Valid</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelRegexMatch">
<property name="text">
<string>Match</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLineEdit" name="regularExpression"/>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Complete Match</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="match0">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="matchNumber">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="matchN">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>