I am trying to implement auto-completion for QLineEdit.
Here see my code:
#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() const;
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);
onLineEditTextChanged();
cursorPos_ = curPos + newStr.size() - pre.size();
return part1 + newStr + part2;
}
void Completer::onLineEditTextChanged() const
{
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;
onLineEditTextChanged();
return stringList;
}
#include <completer.h>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ExpressionLineEdit le;
le.show();
return a.exec();
}
For this code ExpressionLineEdit and Completer work properly (as expected).
But when I try to set the to QTreeView and QSyledItemDelegate, the the behavior is changed. I tried to reimplement the eventFilter function of QSyledItemDelegate, but it does not word. I tried to set ExpressionLineEdit to other QWidget and set the QWidget to QTreeView (for QSyledItemDelegate not to work with ExpressionLineEdit directly), but again it did not help.
Here is the code with QTreeView and QSyledItemDelegate.
#include <QTreeView>
#include <QVBoxLayout>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <Completer.h>
class QEvent;
class Delegate:public QStyledItemDelegate
{
public:
Delegate(QObject* parent = 0)
:QStyledItemDelegate(parent){}
bool eventFilter(QObject* editor,QEvent* event){return false;}
virtual bool editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex& index){return false;}
QWidget* createEditor(QWidget* parent,const QStyleOptionViewItem &option,const QModelindex &index) const
{
if(index.column() != 1) return 0;
QWidget* w = new QWidget(parent);
ExpressionLineEdit *le = new ExpressionLineEdit(w);
QVBoxLayout* lay = new QVBoxLayout(w);
lay->setContentsMargins(0, 0, 0, 0);
lay->addWidget(le);
w->setLayout(lay);
return w;
}
};
class Tree:public QTreeView
{
public:
Tree(QWidget* parent = 0)
:QTreeView(parent)
{
QStandardItemModel *model = new QStandardItemModel(this);
model->setRowCount(1);
model->setColumnCount(2);
QStandardItem *item = new QStandardItem("Item");
model->setItem(0,0,item);
setModel(model);
Delegate *d = new Delegate(this);
setItemDelegate(d);
}
void keyPressEvent ( QKeyEvent * event ){}
};
#include <QApplication>
#include <Completer.h>
#include <Tree.h>
int main(int argc, char ** argv)
{
QApplication app(argc,argv);
Tree t;
t.show();
return app.exec();
}
Please help to understand why same code works differently for this 2 cases. Please help to fix the behavior of Completer.