I have a feature to implement a textbox with auto completion. I have found a code which uses QLineEdit and QCompleter.
Hence I have my string values, "one" , "two" , "three" ect.
Once I type "on" the completer suggests me every word in the list with prefix "on". But after I select "one" from the list and try to type the second word, completer does not work.
Is there a functionality in QCompleter or overall in Qt, which provides such functionality. I haven found it in documentation.
See my found code:
#include <QApplication>
#include<QStringList>
#include<QLineEdit>
#include<QCompleter>
#include<QHBoxLayout>
#include<QWidget>
#include<QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *win=new QWidget();
QHBoxLayout *lay=new QHBoxLayout();
QStringList wordList;
wordList << "alpha" << "omega" << "omicron" << "zeta"<<"america"<<"orion"<<"amit"<<"Odssey";
QLabel *lbl=new QLabel("Select");
QLineEdit *lineEdit = new QLineEdit();
lbl->setBuddy(lineEdit);
QCompleter *completer = new QCompleter(wordList);
completer->setCaseSensitivity(Qt::CaseInsensitive); //Make caseInsensitive selectio
lineEdit->setCompleter(completer);
lay->addWidget(lbl);
lay->addWidget(lineEdit);
win->setLayout(lay);
win->showMaximized();
return a.exec();
}
I think you need override several methods in QLineEdit. My version of code:
mclineedit.h
#ifndef MCLINEEDIT_H
#define MCLINEEDIT_H
#include <QLineEdit>
class MCLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit MCLineEdit(QWidget *parent = 0);
void setMultipleCompleter(QCompleter*);
protected:
void keyPressEvent(QKeyEvent *e);
private:
QString cursorWord(const QString& sentence) const;
private slots:
void insertCompletion(QString);
private:
QCompleter* c;
};
#endif // MCLINEEDIT_H
mclineedit.cpp
#include "mclineedit.h"
#include <QCompleter>
#include <QTextCursor>
#include <QAbstractItemView>
#include <QScrollBar>
MCLineEdit::MCLineEdit(QWidget *parent) :
QLineEdit(parent)
{
}
void MCLineEdit::keyPressEvent(QKeyEvent *e)
{
QLineEdit::keyPressEvent(e);
if (!c)
return;
c->setCompletionPrefix(cursorWord(this->text()));
if (c->completionPrefix().length() < 1)
{
c->popup()->hide();
return;
}
QRect cr = cursorRect();
cr.setWidth(c->popup()->sizeHintForColumn(0)
+ c->popup()->verticalScrollBar()->sizeHint().width());
c->complete(cr);
}
QString MCLineEdit::cursorWord(const QString &sentence) const
{
return sentence.mid(sentence.left(cursorPosition()).lastIndexOf(" ") + 1,
cursorPosition() -
sentence.left(cursorPosition()).lastIndexOf(" ") - 1);
}
void MCLineEdit::insertCompletion(QString arg)
{
setText(text().replace(text().left(cursorPosition()).lastIndexOf(" ") + 1,
cursorPosition() -
text().left(cursorPosition()).lastIndexOf(" ") - 1,
arg));
}
void MCLineEdit::setMultipleCompleter(QCompleter* completer)
{
c = completer;
c->setWidget(this);
connect(c, SIGNAL(activated(QString)),
this, SLOT(insertCompletion(QString)));
}
To learn more visit http://qt-project.org/doc/qt-4.8/tools-customcompleter.html (with QTextEdit).
Here I have found a solution.
#ifndef COMPLETER_H
#define COMPLETER_H
#include <QCompleter>
#include <QString>
#include <QStringList>
#include <QLineEdit>
class Completer:public QCompleter
{
Q_OBJECT
public:
explicit Completer(QStringList stringList, QObject *parent=0);
virtual QString pathFromIndex(const QModelIndex &index)const;
virtual QStringList splitPath(const QString&)const;
public slots:
void onLineEditTextChanged();
private:
mutable int cursorPos_;
};
class ExpressionLineEdit: public QLineEdit
{
Q_OBJECT
public:
explicit ExpressionLineEdit(QWidget *parent=0);
private:
QStringList stringList;
Completer *completer_;
};
#endif // COMPLETER_H
#include <completer.h>
#include <QDebug>
Completer::Completer(QStringList stringList, QObject *parent)
: QCompleter(stringList,parent)
, cursorPos_(-1)
{
}
ExpressionLineEdit::ExpressionLineEdit(QWidget* parent)
: QLineEdit(parent)
{
stringList << "minRoute" << "minPitch" << "minSpacing";
completer_ = new Completer(stringList, this);
setCompleter(completer_);
QObject::connect(this, SIGNAL(textChanged(const QString&)),
completer_, SLOT(onLineEditTextChanged()));
QObject::connect(this, SIGNAL(cursorPositionChanged(int, int)),
completer_, SLOT(onLineEditTextChanged()));
}
QString Completer::pathFromIndex(const QModelIndex &index) const
{
QString newStr = index.data(Qt::EditRole).toString();
ExpressionLineEdit *lineEdit = qobject_cast<ExpressionLineEdit*>(parent());
QString str = lineEdit->text();
int prevSpacePos = str.mid(0, lineEdit->cursorPosition()).lastIndexOf(' ');
int curPos = lineEdit->cursorPosition();
int nextSpacePos = str.indexOf(' ', curPos);
if (nextSpacePos == -1) {
nextSpacePos = str.size();
}
QString part1 = str.mid(0, prevSpacePos + 1);
QString pre = str.mid(prevSpacePos + 1, curPos - prevSpacePos - 1);
QString post = str.mid(curPos, nextSpacePos - curPos);
QString part2 = str.mid(nextSpacePos);
cursorPos_ = curPos + newStr.size() - pre.size();
return part1 + newStr + part2;
}
void Completer::onLineEditTextChanged()
{
qDebug() << "Completer::onLineEditTextChanged()" << cursorPos_;
if (cursorPos_ != -1) {
ExpressionLineEdit *lineEdit = qobject_cast<ExpressionLineEdit*>(parent());
lineEdit->setCursorPosition(cursorPos_);
cursorPos_ = -1;
}
}
QStringList Completer::splitPath(const QString &path) const
{
cursorPos_ = -1;
ExpressionLineEdit *lineEdit = qobject_cast<ExpressionLineEdit*>(parent());
QString text = lineEdit->text();
QStringList stringList;
QString str;
int index = text.mid(0,lineEdit->cursorPosition()).lastIndexOf(' ');
str = text.mid(index, lineEdit->cursorPosition()-index);
str.trimmed();
str.replace(" ", "");
stringList << str;
return stringList;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With