Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. A custom completer behaviour with QLineEdit.
Forum Update on Monday, May 27th 2025

A custom completer behaviour with QLineEdit.

Scheduled Pinned Locked Moved General and Desktop
3 Posts 2 Posters 4.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    pkj__
    wrote on last edited by
    #1

    The default behaviour of QCompleter on QLineEdit set using function QLineEdit::setCompleter() is to take all of the string in QLineEdit::text. So if I want a behaviour where in a QTreeModelCompleter parses parts of QLineEdit::text() [ex: A.B.C && C.D.E] it is not possible with the default behaviour. As A.B.C will work but after it all of the text is given to my Completer and it doesn't work.
    To avoid it I decided to have my own LineEdit inheriting from QLineEdit with this format:
    @
    class LineEdit : public QLineEdit
    {
    Q_OBJECT
    public:
    explicit LineEdit(QWidget parent = 0);
    protected:
    signals:
    private slots:
    void insertCompletion(QString);
    void textEditedSlot(const QString &);
    private:
    QCompleter
    completer;
    QString textUnderCursor();
    };

    LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent)
    {
    completer= new TreeModelCompleter(this);//TreeModelCompleter is my implementation of QCompleter, works ok with qtextedit
    completer->setWidget(this);
    QObject::connect(completer, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
    QObject::connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEditedSlot(QString)));
    }
     
    void LineEdit::insertCompletion(QString completion)
    {
    bool done = false;
    QString rep;
    int initPos = cursorPosition();
    int pos = initPos;
    QString t = text();
    while(!done){
    bool moved=true;
    if(pos == 0) moved = false;
    else { --pos; rep = t.at(pos) + rep; }
    if(!moved) done = true;
    else if(rep.contains(QRegExp("[\\s+-&!,|<>?/ \\(\\) \\{\\} ]")))
    {
    if(!done) rep.remove(0, 1);
    done = true;
    ++pos;
    }
    }
    setText(t.replace(pos, initPos-pos+1, completion));
    }
     
    void LineEdit::textEditedSlot(const QString &text)
    {
     
    QString completionPrefix = textUnderCursor();
    if (completionPrefix != completer->completionPrefix()) {
    completer->setCompletionPrefix(completionPrefix);
    completer->popup()->setCurrentIndex(completer->popup()->model()->index(0,0));
    }
    QRect cr = cursorRect();
    cr.setWidth(completer->popup()->sizeHintForColumn(0)
    + completer->popup()->verticalScrollBar()->sizeHint().width());
    completer->complete(cr); // popup it up!
    }
     
    QString LineEdit::textUnderCursor()
    {
    bool done = false;
    QString rep;
    int initPos = cursorPosition();
    int pos = initPos;
    QString t = text();
    while(!done){
    bool moved=true;
    if(pos == 0) moved = false;
    else {--pos;rep = t.at(pos) + rep; }
    if(!moved) done = true;
    else if(rep.contains(QRegExp("[\\s+-&!,|<>?/ \\(\\) \\{\\} ]")))
    {
    if(!done) rep.remove(0, 1);
    done = true;
    ++pos;
    }
    }
     
    if(!thisString.isEmpty() && rep.contains(QString("this"))){
    rep = rep.replace(QString("this"), thisString);
    }
    return rep;
    }
    

    @

    Now the Problem is after typing in say A no event is taken in by LineEdit. I tried checking with implementing event functions of LineEdit and MyCompleter. So a QKeyEvent of '.' comes to LineEdit but no editchanged signal arrives! LineEdit is rejecting QKeyEvents of '.' For if LineEdit is receiving the event of '.' it should result in text() being changed, leading to fire of textEdited() signal. But is not happening. I don't get it.

    1 Reply Last reply
    0
    • JeroentjehomeJ Offline
      JeroentjehomeJ Offline
      Jeroentjehome
      wrote on last edited by
      #2

      Hmm, doesn't the textEdited() signal only come when done editing? So losing focus (after something else is selected or an enter is given?)

      Greetz, Jeroen

      1 Reply Last reply
      0
      • P Offline
        P Offline
        pkj__
        wrote on last edited by
        #3

        The only difference between textEdited() and textChanged() signals of QLineEdit is that while textEdited() is not fired programmatically. So setText() wouldn't fire textEdited() however, textChanged() does fire.
        Besides, AFAIK, it is a qt bug. QLineEdit even if not subclassed and its setCompleter() function is used, the problem persists. The model and QCompleter subclass I know is good because it works with QTextEdit. And.. it used to work with previous versions(4.7.x).
        The bug is inside qt code. I debugged a little and found that '.' was told to insert in qlineedit_p.cpp file. But didn't updated text(). Didn't had time to debug more.
        Have created a bug too. But you know, with Qt, bugs are rare.. hence the question.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved