基于正则表达式自动完成

时间:2017-06-29 21:49:12

标签: c++ regex qt qcompleter

我有QLineEdit QRegularExpressionValidator,其中允许的输入为:

^(?<sign>[<>=]|>=|<=)(?<value>\d+\.?\d*)(?<unit>[mc]{0,1}m[²2]\/s|St|cSt)$

例如:

"<15m²/s"   // good
">=3.14cSt" // good
"27mm2/s"   // bad

我根据此正则表达式搜索填充QCompleter的方法 因此,如果光标在空QLineEdit上,则完成者建议:
><=>=<=
签名之后,建议不做任何事情,在最后一个号码之后,建议:
mm²/scm²/sm²/sStcSt
我需要通过阅读正则表达式的允许QStringListsign部分来创建unit,并将此QStringList插入QCompleter,因为它基于QAbstractItemModel

1 个答案:

答案 0 :(得分:0)

我通过继承QLineEdit找到了一种解决方法,但它不是最好的解决方案。如果有人有更好的,我会接受 lineeditregexgroup.h

#ifndef LINEEDITREGEXGROUP_H
#define LINEEDITREGEXGROUP_H

#include <QLineEdit>
#include <QMap>

class QCompleter;
class QStringListModel;
class QRegularExpression;
class QRegularExpressionValidator;

class LineEditRegexGroup : public QLineEdit
{
    Q_OBJECT

public:
    LineEditRegexGroup(const QString pattern, QWidget *parent = Q_NULLPTR);
    ~LineEditRegexGroup();
    static QMap<QString, QStringList> mapCompleter;

public slots:
    void checkValidity(const QString &text);

protected:
    virtual void mouseReleaseEvent(QMouseEvent *e);

private:
    QString                     curGroup;
    QCompleter                  *completer;
    QStringListModel            *listCompleter;
    QRegularExpression          *regex;
    QRegularExpressionValidator *validator;

};

#endif // LINEEDITREGEXGROUP_H

lineeditregexgroup.cpp

#include "lineeditregexgroup.h"
#include <QCompleter>
#include <QStringListModel>
#include <QRegularExpression>
#include <QRegularExpressionValidator>
#include <QAbstractItemView>

QMap<QString, QStringList> LineEditRegexGroup::mapCompleter = {    
    { "sign", QStringList() << "<" << ">" << "=" << "<=" << ">=" },
    { "unit", QStringList() << "mm²/s" << "cm²/s" << "m²/s" << "St" << "cSt" }
};

LineEditRegexGroup::LineEditRegexGroup(const QString pattern, QWidget *parent)
    : QLineEdit(parent)
{
    completer = new QCompleter(this);
    listCompleter = new QStringListModel(completer);
    regex = new QRegularExpression(pattern, QRegularExpression::NoPatternOption);
    validator = new QRegularExpressionValidator(*regex, this);

    completer->setModel(listCompleter);
    completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    setCompleter(completer);
    setValidator(validator);
    curGroup = regex->namedCaptureGroups().at(1);

    connect(this, SIGNAL(textEdited(QString)), this, SLOT(checkValidity(QString)));
}

LineEditRegexGroup::~LineEditRegexGroup()
{
    // dtor ...
}

void LineEditRegexGroup::checkValidity(const QString &text)
{
    bool valid = true;
    int nbCapture = 0;
    QRegularExpressionMatch match = regex->match(text);
    for (int i=1; i<=regex->captureCount() && valid; i++){
        /* +1 to check only groups, not the global string */
        valid &= !match.captured(i).isEmpty();
        if (valid)
            nbCapture++;
        curGroup = regex->namedCaptureGroups().at(i);
        if (curGroup == "value")
            curGroup = regex->namedCaptureGroups().at(i-1);
    }
    if (nbCapture < regex->captureCount()){
        QStringList new_model = mapCompleter.value(curGroup);
        if (curGroup == regex->namedCaptureGroups().at(regex->captureCount())){
            new_model.replaceInStrings(QRegularExpression("^(.*)$"), text+"\\1");
        }
        listCompleter->setStringList(new_model);
        completer->complete();
    }
}

void LineEditRegexGroup::mouseReleaseEvent(QMouseEvent *e)
{
    QLineEdit::mouseReleaseEvent(e);
    if (text().isEmpty())
        checkValidity("");
}

并称之为:

new LineEditRegexGroup(
    "^(?:(?<sign>[<>=]|>=|<=|)"
    "(?:(?<value>\\d+\\.?\\d*)"
    "(?:(?<unit>[mc]{0,1}m[²2]\\/s|St|cSt))?)?)?$",
    parent
);

<强>结果
LineEditRegexGroup