基于正则表达式的自动完成
Auto completion based on regex
我有一个 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²/s
、cm²/s
、m²/s
、St
或 cSt
我的需要是通过读取正则表达式允许的 sign
和 unit
部分来创建 QStringList
并将此 QStringList
插入 QCompleter
因为它基于QAbstractItemModel
.
我通过子类化 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
);
结果:
我有一个 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²/s
、cm²/s
、m²/s
、St
或 cSt
我的需要是通过读取正则表达式允许的 sign
和 unit
部分来创建 QStringList
并将此 QStringList
插入 QCompleter
因为它基于QAbstractItemModel
.
我通过子类化 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
);
结果: