我通过子类化找到了一种解决方法,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
);
结果: