у меня есть 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
Мне нужно создать QStringList
прочитав разрешенное sign
а также unit
часть регулярного выражения и вставить это 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
);
Других решений пока нет …