Struggling with completer example



  • HI,

    I am currently struggling to understand the completer example. What I do not understand is how the function modelFromFile() works. A txt file is read and the content is put in a QStandardItemModel

    QStandardItemModel *m = new QStandardItemModel(words.count(), 2, completer);
    for (int i = 0; i < words.count(); ++i) {
            QModelIndex countryIdx = m->index(i, 0);
            QModelIndex symbolIdx = m->index(i, 1);
            QString country = words[i].mid(0, words[i].length() - 2).trimmed();
            QString symbol = words[i].right(2);
            m->setData(countryIdx, country);
            m->setData(symbolIdx, symbol);
     }
    
    return m;
    

    So the country name is put in row one in the 2D matrix and the country short cut in row two. But nowhere in the rest of the code the completer is told to use row one and not row two. What if I wanted to use row two for completion? Or in my case I would like to show some extra information on the completion. In the example here I would like to display in light grey the country short cut at the end of the completer box and it should not be inserted.
    To get the data displayed I probably need a custom delegate, which I can set by completer->setPopup() but I do not get from the example how the completer knows which data to use.

    Thanks for all suggestions.



  • @Sikarjan
    First of all, I guess you mean column one/ column two instead of row one/row two.
    http://doc.qt.io/qt-5/qcompleter.html says,
    To set the model on which QCompleter should operate, call setModel(). By default, QCompleter will attempt to match the completion prefix (i.e., the word that the user has started typing) against the Qt::EditRole data stored in column 0 in the model case sensitively. This can be changed using setCompletionRole(), setCompletionColumn(), and setCaseSensitivity().

    So by default the column 0 is the column for completion and if you want to use column two for completion, you can change by setCompletionColumn().



  • @samdol
    Thanks for pointing that out. Don't know why I did not see that.

    Unfortunately this does not help me creating the completer I want. I managed to have a custom delegate:

    #ifndef COMPLETERDELEGATE_H
    #define COMPLETERDELEGATE_H
    
    #include <QObject>
    #include <QApplication>
    #include <QStyledItemDelegate>
    #include <QPainter>
    #include <QStyle>
    #include <QTextDocument>
    #include <QAbstractTextDocumentLayout>
    #include <QStyleOption>
    
    class CompleterDelegate : public QStyledItemDelegate
    {
    public:
        CompleterDelegate();
    
    protected:
        void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
        QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    };
    
    #endif // COMPLETERDELEGATE_H
    
    #include "completerdelegate.h"
    
    CompleterDelegate::CompleterDelegate()
    {
    
    }
    
    void CompleterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QStyleOptionViewItemV4 optionV4 = option;
        initStyleOption(&optionV4, index);
    
        QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();
    
        QTextDocument doc;
        doc.setHtml(optionV4.text);
    
        // Painting item without text
        optionV4.text = QString();
        style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);
    
        QAbstractTextDocumentLayout::PaintContext ctx;
    
        // Highlighting text if item is selected
        if (optionV4.state & QStyle::State_Selected)
            ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));
    
        QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
        painter->save();
        painter->translate(textRect.topLeft());
        painter->setClipRect(textRect.translated(-textRect.topLeft()));
        doc.documentLayout()->draw(painter, ctx);
        painter->restore();
    }
    
    QSize CompleterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QStyleOptionViewItemV4 optionV4 = option;
        initStyleOption(&optionV4, index);
    
        QTextDocument doc;
        doc.setHtml(optionV4.text);
        doc.setTextWidth(optionV4.rect.width());
        return QSize(doc.idealWidth(), doc.size().height());
    }
    

    And I set the delegate like this

        cDeligate = new CompleterDelegate;
        completer = new QCompleter(compList, this);
        completer->popup()->setItemDelegate(cDeligate);
    

    So how could I access the data from my models second column?


  • Lifetime Qt Champion

    Hi,

    You can use QModelIndex::sibling.



  • @SGaist Thanks again for helping me out.

    In CompleterDelegate I added:

    QStyleOptionViewItem hint = option;
    initStyleOption(&hint, index.sibling(index.row(),1));
    

    Which gave me

    hint.text
    

    to access the content of the second column.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.