regularexpressiondialog.cpp Example File
					 
					
						tools/regularexpression/regularexpressiondialog.cpp
					 
					
/****************************************************************************
**
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/ 
#include "regularexpressiondialog.h" 
#include <QApplication> 
#include <QCheckBox> 
#include <QComboBox> 
#include <QLabel> 
#include <QLineEdit> 
#include <QMenu> 
#include <QSpinBox> 
#include <QPlainTextEdit> 
#include <QTreeWidget> 
#include <QAction> 
#include <QClipboard> 
#include <QContextMenuEvent> 
#include <QHBoxLayout> 
#include <QGridLayout> 
#include <QFormLayout> 
#include <QRegularExpression> 
#include <QRegularExpressionMatch> 
#include <QRegularExpressionMatchIterator> 
Q_DECLARE_METATYPE(QRegularExpression :: MatchType)
static  QString QString . replace(QLatin1String("\\" ),  QLatin1String("\\\\" ));
    pattern. replace(QLatin1String("\"" ),  QLatin1String("\\\"" ));
    pattern. prepend(QLatin1Char('"' ));
    pattern. append(QLatin1Char('"' ));
    return  pattern;
}
static  QString QString for  (int  i =  0 ; i <  code. size(); + + i) {
        if  (code. at(i) = =  QLatin1Char('\\' ))
            code. remove(i,  1 );
    }
    if  (code. startsWith(QLatin1Char('"' )) & &  code. endsWith(QLatin1Char('"' ))) {
        code. chop(1 );
        code. remove(0 ,  1 );
    }
    return  code;
}
class  PatternLineEdit : public  QLineEdit public :
    explicit  PatternLineEdit(QWidget * parent =  nullptr);
private  slots :
    void  copyToCode();
    void  pasteFromCode();
    void  escapeSelection();
protected :
    void  contextMenuEvent(QContextMenuEvent * event) override;
private :
    QAction * escapeSelectionAction;
    QAction * copyToCodeAction;
    QAction * pasteFromCodeAction;
};
PatternLineEdit:: PatternLineEdit(QWidget * parent) :
    QLineEdit , 
    escapeSelectionAction(new  QAction "Escape Selection" ),  this )), 
    copyToCodeAction(new  QAction "Copy to Code" ),  this )), 
    pasteFromCodeAction(new  QAction "Paste from Code" ),  this ))
{
    setClearButtonEnabled(true );
    connect(escapeSelectionAction,  & QAction :: triggered,  this ,  & PatternLineEdit:: escapeSelection);
    connect(copyToCodeAction,  & QAction :: triggered,  this ,  & PatternLineEdit:: copyToCode);
    connect(pasteFromCodeAction,  & QAction :: triggered,  this ,  & PatternLineEdit:: pasteFromCode);
#if !QT_CONFIG(clipboard) 
    copyToCodeAction- > setEnabled(false );
    pasteFromCodeAction- > setEnabled(false );
#endif 
}
void  PatternLineEdit:: escapeSelection()
{
    const  QString =  selectedText();
    const  QString =  QRegularExpression :: escape(selection);
    if  (escapedSelection ! =  selection) {
        QString =  text();
        t. replace(selectionStart(),  selection. size(),  escapedSelection);
        setText(t);
    }
}
void  PatternLineEdit:: copyToCode()
{
#if QT_CONFIG(clipboard) 
    QGuiApplication :: clipboard()- > setText(patternToCode(text()));
#endif 
}
void  PatternLineEdit:: pasteFromCode()
{
#if QT_CONFIG(clipboard) 
    setText(codeToPattern(QGuiApplication :: clipboard()- > text()));
#endif 
}
void  PatternLineEdit:: contextMenuEvent(QContextMenuEvent * event)
{
    QMenu * menu =  createStandardContextMenu();
    menu- > setAttribute(Qt :: WA_DeleteOnClose);
    menu- > addSeparator();
    escapeSelectionAction- > setEnabled(hasSelectedText());
    menu- > addAction(escapeSelectionAction);
    menu- > addSeparator();
    menu- > addAction(copyToCodeAction);
    menu- > addAction(pasteFromCodeAction);
    menu- > popup(event- > globalPos());
}
RegularExpressionDialog:: RegularExpressionDialog(QWidget * parent)
    : QDialog "QRegularExpression Example" ));
    connect(patternLineEdit,  & QLineEdit :: textChanged,  this ,  & RegularExpressionDialog:: refresh);
    connect(subjectTextEdit,  & QPlainTextEdit :: textChanged,  this ,  & RegularExpressionDialog:: refresh);
    connect(caseInsensitiveOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(dotMatchesEverythingOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(multilineOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(extendedPatternSyntaxOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(invertedGreedinessOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(dontCaptureOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(useUnicodePropertiesOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(optimizeOnFirstUsageOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(dontAutomaticallyOptimizeOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(offsetSpinBox,  QOverload < int > :: of(& QSpinBox :: valueChanged), 
            this ,  & RegularExpressionDialog:: refresh);
    connect(matchTypeComboBox,  QOverload < int > :: of(& QComboBox :: currentIndexChanged), 
            this ,  & RegularExpressionDialog:: refresh);
    connect(anchoredMatchOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    connect(dontCheckSubjectStringMatchOptionCheckBox,  & QCheckBox :: toggled,  this ,  & RegularExpressionDialog:: refresh);
    patternLineEdit- > setText(tr("(\\+?\\d+)-(?<prefix>\\d+)-(?<number>\\w+)" ));
    subjectTextEdit- > setPlainText(tr("My office number is +43-152-0123456, my mobile is 001-41-255512 instead." ));
    refresh();
}
void  RegularExpressionDialog:: setResultUiEnabled(bool enabled)
{
    matchDetailsTreeWidget- > setEnabled(enabled);
    namedGroupsTreeWidget- > setEnabled(enabled);
}
static  void  setTextColor(QWidget * widget,  const  QColor & color)
{
    QPalette =  widget- > palette();
    palette. setColor(QPalette :: Text,  color);
    widget- > setPalette(palette);
}
void  RegularExpressionDialog:: refresh()
{
    setUpdatesEnabled(false );
    const  QString =  patternLineEdit- > text();
    const  QString =  subjectTextEdit- > toPlainText();
    offsetSpinBox- > setMaximum(qMax (0 ,  text. length() -  1 ));
    escapedPatternLineEdit- > setText(patternToCode(pattern));
    setTextColor(patternLineEdit,  subjectTextEdit- > palette(). color(QPalette :: Text));
    matchDetailsTreeWidget- > clear();
    namedGroupsTreeWidget- > clear();
    regexpStatusLabel- > setText(QString if  (pattern. isEmpty()) {
        setResultUiEnabled(false );
        setUpdatesEnabled(true );
        return ;
    }
    QRegularExpression if  (! rx. isValid()) {
        setTextColor(patternLineEdit,  Qt :: red);
        regexpStatusLabel- > setText(tr("Invalid: syntax error at position %1 (%2)" )
                                   . arg(rx. patternErrorOffset())
                                   . arg(rx. errorString()));
        setResultUiEnabled(false );
        setUpdatesEnabled(true );
        return ;
    }
    setResultUiEnabled(true );
    QRegularExpression :: MatchType matchType =  matchTypeComboBox- > currentData(). value< QRegularExpression :: MatchType> ();
    QRegularExpression :: PatternOptions patternOptions =  QRegularExpression :: NoPatternOption;
    QRegularExpression :: MatchOptions matchOptions =  QRegularExpression :: NoMatchOption;
    if  (anchoredMatchOptionCheckBox- > isChecked())
        matchOptions | =  QRegularExpression :: AnchoredMatchOption;
    if  (dontCheckSubjectStringMatchOptionCheckBox- > isChecked())
        matchOptions | =  QRegularExpression :: DontCheckSubjectStringMatchOption;
    if  (caseInsensitiveOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: CaseInsensitiveOption;
    if  (dotMatchesEverythingOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: DotMatchesEverythingOption;
    if  (multilineOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: MultilineOption;
    if  (extendedPatternSyntaxOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: ExtendedPatternSyntaxOption;
    if  (invertedGreedinessOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: InvertedGreedinessOption;
    if  (dontCaptureOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: DontCaptureOption;
    if  (useUnicodePropertiesOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: UseUnicodePropertiesOption;
    if  (optimizeOnFirstUsageOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: OptimizeOnFirstUsageOption;
    if  (dontAutomaticallyOptimizeOptionCheckBox- > isChecked())
        patternOptions | =  QRegularExpression :: DontAutomaticallyOptimizeOption;
    rx. setPatternOptions(patternOptions);
    const  int  capturingGroupsCount =  rx. captureCount() +  1 ;
    QRegularExpressionMatchIterator =  rx. globalMatch(text,  offsetSpinBox- > value(),  matchType,  matchOptions);
    int  i =  0 ;
    while  (iterator. hasNext()) {
        QRegularExpressionMatch =  iterator. next();
        QTreeWidgetItem * matchDetailTopItem =  new  QTreeWidgetItem - > setText(0 ,  QString :: number(i));
        for  (int  captureGroupIndex =  0 ; captureGroupIndex <  capturingGroupsCount; + + captureGroupIndex) {
            QTreeWidgetItem * matchDetailItem =  new  QTreeWidgetItem - > setText(1 ,  QString :: number(captureGroupIndex));
            matchDetailItem- > setText(2 ,  match. captured(captureGroupIndex));
        }
        + + i;
    }
    matchDetailsTreeWidget- > expandAll();
    regexpStatusLabel- > setText(tr("Valid" ));
    const  QStringList =  rx. namedCaptureGroups();
    for  (int  i =  0 ; i <  namedCaptureGroups. size(); + + i) {
        const  QString =  namedCaptureGroups. at(i);
        QTreeWidgetItem * namedGroupItem =  new  QTreeWidgetItem - > setText(0 ,  QString :: number(i));
        namedGroupItem- > setText(1 ,  currentNamedCaptureGroup. isNull() ?  tr("<no name>" ) : currentNamedCaptureGroup);
    }
    setUpdatesEnabled(true );
}
void  RegularExpressionDialog:: copyEscapedPatternToClipboard()
{
#if QT_CONFIG(clipboard) 
    QClipboard * clipboard =  QGuiApplication :: clipboard();
    if  (clipboard)
        clipboard- > setText(escapedPatternLineEdit- > text());
#endif 
}
void  RegularExpressionDialog:: setupUi()
{
    QWidget * leftHalfContainer =  setupLeftUi();
    QFrame * verticalSeparator =  new  QFrame - > setFrameStyle(QFrame :: VLine |  QFrame :: Sunken);
    QWidget * rightHalfContainer =  setupRightUi();
    QHBoxLayout * mainLayout =  new  QHBoxLayout - > addWidget(leftHalfContainer);
    mainLayout- > addWidget(verticalSeparator);
    mainLayout- > addWidget(rightHalfContainer);
    setLayout(mainLayout);
}
QWidget * RegularExpressionDialog:: setupLeftUi()
{
    QWidget * container =  new  QWidget QFormLayout * layout =  new  QFormLayout - > setFieldGrowthPolicy(QFormLayout :: AllNonFixedFieldsGrow);
    layout- > setMargin(0 );
    QLabel * regexpAndSubjectLabel =  new  QLabel "<h3>Regular expression and text input</h3>" ));
    layout- > addRow(regexpAndSubjectLabel);
    patternLineEdit =  new  PatternLineEdit;
    patternLineEdit- > setClearButtonEnabled(true );
    layout- > addRow(tr("&Pattern:" ),  patternLineEdit);
    escapedPatternLineEdit =  new  QLineEdit - > setReadOnly(true );
    QPalette =  escapedPatternLineEdit- > palette();
    palette. setBrush(QPalette :: Base,  palette. brush(QPalette :: Disabled,  QPalette :: Base));
    escapedPatternLineEdit- > setPalette(palette);
#if QT_CONFIG(clipboard) 
    QAction * copyEscapedPatternAction =  new  QAction this );
    copyEscapedPatternAction- > setText(tr("Copy to clipboard" ));
    copyEscapedPatternAction- > setIcon(QIcon QStringLiteral ":/images/copy.png" )));
    connect(copyEscapedPatternAction,  & QAction :: triggered,  this ,  & RegularExpressionDialog:: copyEscapedPatternToClipboard);
    escapedPatternLineEdit- > addAction(copyEscapedPatternAction,  QLineEdit :: TrailingPosition);
#endif 
    layout- > addRow(tr("&Escaped pattern:" ),  escapedPatternLineEdit);
    subjectTextEdit =  new  QPlainTextEdit - > addRow(tr("&Subject text:" ),  subjectTextEdit);
    caseInsensitiveOptionCheckBox =  new  QCheckBox "Case insensitive (/i)" ));
    dotMatchesEverythingOptionCheckBox =  new  QCheckBox "Dot matches everything (/s)" ));
    multilineOptionCheckBox =  new  QCheckBox "Multiline (/m)" ));
    extendedPatternSyntaxOptionCheckBox =  new  QCheckBox "Extended pattern (/x)" ));
    invertedGreedinessOptionCheckBox =  new  QCheckBox "Inverted greediness" ));
    dontCaptureOptionCheckBox =  new  QCheckBox "Don't capture" ));
    useUnicodePropertiesOptionCheckBox =  new  QCheckBox "Use unicode properties (/u)" ));
    optimizeOnFirstUsageOptionCheckBox =  new  QCheckBox "Optimize on first usage" ));
    dontAutomaticallyOptimizeOptionCheckBox =  new  QCheckBox "Don't automatically optimize" ));
    QGridLayout * patternOptionsCheckBoxLayout =  new  QGridLayout int  gridRow =  0 ;
    patternOptionsCheckBoxLayout- > addWidget(caseInsensitiveOptionCheckBox,  gridRow,  1 );
    patternOptionsCheckBoxLayout- > addWidget(dotMatchesEverythingOptionCheckBox,  gridRow,  2 );
    + + gridRow;
    patternOptionsCheckBoxLayout- > addWidget(multilineOptionCheckBox,  gridRow,  1 );
    patternOptionsCheckBoxLayout- > addWidget(extendedPatternSyntaxOptionCheckBox,  gridRow,  2 );
    + + gridRow;
    patternOptionsCheckBoxLayout- > addWidget(invertedGreedinessOptionCheckBox,  gridRow,  1 );
    patternOptionsCheckBoxLayout- > addWidget(dontCaptureOptionCheckBox,  gridRow,  2 );
    + + gridRow;
    patternOptionsCheckBoxLayout- > addWidget(useUnicodePropertiesOptionCheckBox,  gridRow,  1 );
    patternOptionsCheckBoxLayout- > addWidget(optimizeOnFirstUsageOptionCheckBox,  gridRow,  2 );
    + + gridRow;
    patternOptionsCheckBoxLayout- > addWidget(dontAutomaticallyOptimizeOptionCheckBox,  gridRow,  1 );
    layout- > addRow(tr("Pattern options:" ),  patternOptionsCheckBoxLayout);
    offsetSpinBox =  new  QSpinBox - > addRow(tr("Match &offset:" ),  offsetSpinBox);
    matchTypeComboBox =  new  QComboBox - > addItem(tr("Normal" ),  QVariant :: fromValue(QRegularExpression :: NormalMatch));
    matchTypeComboBox- > addItem(tr("Partial prefer complete" ),  QVariant :: fromValue(QRegularExpression :: PartialPreferCompleteMatch));
    matchTypeComboBox- > addItem(tr("Partial prefer first" ),  QVariant :: fromValue(QRegularExpression :: PartialPreferFirstMatch));
    matchTypeComboBox- > addItem(tr("No match" ),  QVariant :: fromValue(QRegularExpression :: NoMatch));
    layout- > addRow(tr("Match &type:" ),  matchTypeComboBox);
    dontCheckSubjectStringMatchOptionCheckBox =  new  QCheckBox "Don't check subject string" ));
    anchoredMatchOptionCheckBox =  new  QCheckBox "Anchored match" ));
    QGridLayout * matchOptionsCheckBoxLayout =  new  QGridLayout - > addWidget(dontCheckSubjectStringMatchOptionCheckBox,  0 ,  0 );
    matchOptionsCheckBoxLayout- > addWidget(anchoredMatchOptionCheckBox,  0 ,  1 );
    layout- > addRow(tr("Match options:" ),  matchOptionsCheckBoxLayout);
    return  container;
}
QWidget * RegularExpressionDialog:: setupRightUi()
{
    QWidget * container =  new  QWidget QFormLayout * layout =  new  QFormLayout - > setFieldGrowthPolicy(QFormLayout :: AllNonFixedFieldsGrow);
    layout- > setMargin(0 );
    QLabel * matchInfoLabel =  new  QLabel "<h3>Match information</h3>" ));
    layout- > addRow(matchInfoLabel);
    matchDetailsTreeWidget =  new  QTreeWidget - > setHeaderLabels(QStringList < <  tr("Match index" ) < <  tr("Group index" ) < <  tr("Captured string" ));
    matchDetailsTreeWidget- > setSizeAdjustPolicy(QTreeWidget :: AdjustToContents);
    layout- > addRow(tr("Match details:" ),  matchDetailsTreeWidget);
    QFrame * horizontalSeparator =  new  QFrame - > setFrameStyle(QFrame :: HLine |  QFrame :: Sunken);
    layout- > addRow(horizontalSeparator);
    QLabel * regexpInfoLabel =  new  QLabel "<h3>Regular expression information</h3>" ));
    layout- > addRow(regexpInfoLabel);
    regexpStatusLabel =  new  QLabel "Valid" ));
    regexpStatusLabel- > setWordWrap(true );
    layout- > addRow(tr("Pattern status:" ),  regexpStatusLabel);
    namedGroupsTreeWidget =  new  QTreeWidget - > setHeaderLabels(QStringList < <  tr("Index" ) < <  tr("Named group" ));
    namedGroupsTreeWidget- > setSizeAdjustPolicy(QTreeWidget :: AdjustToContents);
    namedGroupsTreeWidget- > setRootIsDecorated(false );
    layout- > addRow(tr("Named groups:" ),  namedGroupsTreeWidget);
    return  container;
}
#include "regularexpressiondialog.moc"