Автозаполнение на основе регулярных выражений

у меня есть 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,

1

Решение

Я нашел обходной путь путем подклассов 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

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]