PDA

View Full Version : QCompleter and a UnionModel query internal submodels



momesana
29th May 2008, 12:54
Hi,
I am trying to create a lineedit with a completer that queries different models based on the length of the lineedit's input. In the test example below, the completer should match against one model if the input has a length less or equal three characters. with 4-6 charachters, the completer should match against the other model and with more characters match against both. It doesn not work however :(. If I modify the code to start out in UnionModel::MatchAll mode and change onTextChanged to return immediately without applying changes to the match mode the completer can match against both models, so I think the code works to some extent, thus it may be some QCompleter internals that keep this from working ...
Can anybody tell me what I am doing wrong?




#include <QtGui>

class Model : public QAbstractListModel
{
Q_OBJECT
public:
Model(QStringList& list, QObject* parent = 0)
: QAbstractListModel(parent), m_list(list) {}

int rowCount(const QModelIndex& parent = QModelIndex()) const {
return m_list.count();
}

QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const {
if (!index.isValid()) return QVariant();
if (role == Qt::DisplayRole) {
return m_list.at(index.row());
}
return QVariant();
}

private:
QStringList m_list;
};

class UnionModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(MatchMode matchMode READ matchMode WRITE setMatchMode)
public:
UnionModel(QObject* parent = 0)
: QAbstractListModel(parent),
m_matchMode(UnionModel::MatchInput) {
m_applicationModel = new Model(QStringList() << "oneoneoneone" << "twotwotwotwo", this);
m_inputModel = new Model(QStringList() << "oneoneone" << "twotwotwo", this);
}

enum MatchMode { MatchApplications, MatchInput, MatchAll };

int rowCount(const QModelIndex& parent = QModelIndex()) const {
Q_UNUSED(parent)
switch (m_matchMode) {
case UnionModel::MatchInput:
return m_inputModel->rowCount();
case UnionModel::MatchApplications:
return m_applicationModel->rowCount();
case UnionModel::MatchAll:
return (m_inputModel->rowCount() + m_applicationModel->rowCount());
}
return 0;
}

QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const {
if (!index.isValid())
return QVariant();

if (role == Qt::DisplayRole) {
if (m_matchMode == MatchInput) {
return m_inputModel->data(index);
}

else if (m_matchMode == MatchApplications) {
return m_applicationModel->data(index);
}

if (index.row() < m_inputModel->rowCount()) {
return m_inputModel->data(index);
}

QModelIndex idx = m_applicationModel->index(qAbs(index.row() - m_inputModel->rowCount()));
return m_applicationModel->data(idx);
}

return QVariant();
}
MatchMode matchMode() const {
return m_matchMode;
}

public slots:
void setMatchMode(UnionModel::MatchMode mode) {
if (m_matchMode != mode) {
m_matchMode = mode;
emit matchModeChanged(mode);
}
}

private:
MatchMode m_matchMode;
Model* m_applicationModel;
Model* m_inputModel;

signals:
void matchModeChanged(UnionModel::MatchMode mode);
};

class LineEdit : public QLineEdit
{
Q_OBJECT
public:
LineEdit(QWidget* parent = 0) : QLineEdit(parent) {
QCompleter* c = new QCompleter(this);
UnionModel* model = new UnionModel(c);
c->setModel(model);
c->setCompletionRole(Qt::DisplayRole);
setCompleter(c);
QObject::connect(this, SIGNAL(changeModeRequest(UnionModel::MatchMode)),
model, SLOT(setMatchMode(UnionModel::MatchMode)));

connect(this, SIGNAL(textChanged(const QString&)),
this, SLOT(onTextChanged(const QString&)));
}
private slots:
void onTextChanged(const QString& text) {
if (text.trimmed().isEmpty()) return;

UnionModel::MatchMode mode;
int len = text.length();

if (len < 3) {
mode = UnionModel::MatchInput;
}

else if (len >= 3 && len <= 6) {
mode = UnionModel::MatchApplications;
}

else {
mode = UnionModel::MatchAll;
}

emit changeModeRequest(mode);
}
signals:
void changeModeRequest(UnionModel::MatchMode mode);
};

int main(int argc, char** argv)
{
QApplication app(argc, argv);
LineEdit le;
le.show();
return app.exec();
}

#include "main.moc"


p.s. Maybe I have to call a function to tell the view/completer etc. that the rowCount() has changed ...

momesana
29th May 2008, 14:43
emitting layoutAboutToBeChanged and layoutChanged solved it. Thanks nonetheless.