読者です 読者をやめる 読者になる 読者になる

QCompleterを部分一致補完させる

最近「NavyJS & NavyCreator」というモバイルWebフレームワークとそれ専用の開発環境(簡易IDE)を作ってます。 そのNavyCreatorはC++/Qtを使って実装していて、Qt便利ですごくありがたいなーと思ってます。

QCompleter

NavyCreatorでコンボボックス(ファイル名とかクラス名とかのリスト)にインクルメンタルサーチを実装したいなーと思って、Qtのリファレンスを見てたらQCompleterっていうすごく便利なのを見つけて喜んでました。けどQCompleterが対応してるのは前方一致のみ。オプションで変更できるだろうと思ったんですがそれも無さげ。という訳でQtのコードとか読みながら部分一致を行えるようにQCompleterを拡張できたのでメモとして記事を書いています。

NCompleter

QCompleterを継承したNCompleterで部分一致補完を行います

#ifndef N_COMPLETER_H
#define N_COMPLETER_H

#include <QCompleter>
#include <QComboBox>
#include <QStringListModel>

class NCompleter : public QCompleter
{
    Q_OBJECT
public:
    explicit NCompleter(const QStringList &list, QObject *parent = 0);
    void setStringList(const QStringList &list);

private:
    QStringList mList;
    QStringListModel *mModel;

signals:

private slots:
    void update(const QString &word);
};

#endif // N_COMPLETER_H
#include "n_completer.h"

NCompleter::NCompleter(const QStringList &list, QObject *parent) : QCompleter(parent) {
    mList = list;
    mModel = new QStringListModel();
    mModel->setStringList(list);

    setModel(mModel);
    setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    setModelSorting(QCompleter::CaseInsensitivelySortedModel);
    setCaseSensitivity(Qt::CaseInsensitive);
}

void NCompleter::setStringList(const QStringList &list) {
    mList = list;
    mModel->setStringList(list);
}

void NCompleter::update(const QString &word) {
    if (mList.indexOf(word) == -1) {
        QStringList filtered = mList.filter(word, caseSensitivity());
        if (filtered.length() != 0) {
            mModel->setStringList(filtered);
        }
    }
}
QLineEdit *e = new QLineEdit(this);
NCompleter *c = new NCompleter(e);
QStringList list;
list << "book" << "this is book" << "cook";
c->setStringList(list);
e->setCompleter(c);
connect(e, SIGNAL(textChanged(QString)), c, SLOT(update(QString));

QtCreator上で日本語入力が安定しないのでコメントかけなくて辛い><