Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Red Devil от Июль 04, 2008, 23:53



Название: Собственная модель для QCompleter
Отправлено: Red Devil от Июль 04, 2008, 23:53
Не получается создать свою модель для QCompleter.
Вот, например делаю такой класс :
Код:
class MyModel : public QAbstractListModel
{
QStringList * m_pList;
public:
void SetList(QStringList * pList)
{
m_pList = pList;
}

QVariant data(const QModelIndex &index, int role /* = Qt::DisplayRole */) const
{
if (role == Qt::DisplayRole && index.isValid())
return QVariant(m_pList->at(index.row()));
return QVariant();
}

int rowCount(const QModelIndex &parent) const
{
return m_pList->size();
}

bool setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.row() >= 0 && index.row() < m_pList->size() && (role == Qt::EditRole || role == Qt::DisplayRole))
{
m_pList->replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}
return false;
}
};

Устанавливаю свою модель для QCompleter - и ничего.
Код:
        m_pStringList = new QStringList;
QStringList & List = *m_pStringList;
List<<"hello"<<"world";

m_pEdit = new QLineEdit;
setCentralWidget(m_pEdit);
m_pCompleter = new QCompleter(this);
MyModel * pModel = new MyModel;
        pModel->SetList(m_pStringList);
//QStringListModel * pModel = new QStringListModel;
//pModel->setStringList(List);
m_pCompleter->setModel(pModel);
m_pEdit->setCompleter(m_pCompleter);

Если разкометнировать модель для QStringListModel - то все нормально, StringModel устанавливается. А моя не работает, QCompleter ничего не выводит.

В чем проблема ?


Название: Re: Собственная модель для QCompleter
Отправлено: Zmeishe от Июль 05, 2008, 08:05
Попробуй, всё-таки, Q_OBJECT в своём классе прописать.
Похоже от твоей модели ждут сигналов, а они не идут.
Код:
class MyModel : public QAbstractListModel
{
 Q_OBJECT
private:
QStringList * m_pList;
public:
...
А функции data, setData и rowCount - они все в базовом классе virtual объявлены.
Объяви их у себя тоже virtual.


Название: Re: Собственная модель для QCompleter
Отправлено: Red Devil от Июль 05, 2008, 11:35
Все сделал - не помогло  ???
Код:
class MyModel : public QAbstractListModel
{
Q_OBJECT

QStringList * m_pList;
public:
void SetList(QStringList * pList)
{
m_pList = pList;
}

virtual QVariant data(const QModelIndex &index, int role /* = Qt::DisplayRole */) const
{
if (role == Qt::DisplayRole && index.isValid())
return QVariant(m_pList->at(index.row()));
return QVariant();
}

virtual int rowCount(const QModelIndex &parent) const
{
return m_pList->size();
}

virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.row() >= 0 && index.row() < m_pList->size() && (role == Qt::EditRole || role == Qt::DisplayRole))
{
m_pList->replace(index.row(), value.toString());
emit dataChanged(index, index);
return true;
}
return false;
}

};


Название: Re: Собственная модель для QCompleter
Отправлено: ритт от Июль 05, 2008, 11:39
А функции data, setData и rowCount - они все в базовом классе virtual объявлены.
Объяви их у себя тоже virtual.
зачем?


Название: Re: Собственная модель для QCompleter
Отправлено: Zmeishe от Июль 05, 2008, 11:51
Исключительно из уважения к тем, кто будет потом смотреть эти исходники.


Название: Re: Собственная модель для QCompleter
Отправлено: Zmeishe от Июль 05, 2008, 11:57
Все сделал - не помогло  ???

Единственное, что на ум приходит, попробуй в функции data выдавать данные ещё на Qt::EditRole


Название: Re: Собственная модель для QCompleter
Отправлено: ритт от Июль 05, 2008, 12:25
Код:
QVariant QStringListModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= lst.size())
        return QVariant();

    if (role == Qt::DisplayRole || role == Qt::EditRole)
        return lst.at(index.row());

    return QVariant();
}

bool QStringListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.row() >= 0 && index.row() < lst.size()
        && (role == Qt::EditRole || role == Qt::DisplayRole)) {
        lst.replace(index.row(), value.toString());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}


Название: Re: Собственная модель для QCompleter
Отправлено: Red Devil от Июль 05, 2008, 13:17
Спасибо получилось, правда желаемого эффекта не достиг.
Я хотел чтобы m_pStringList находящийся в MyModel, мог изменятся где-то в другом месте.
Например вот по тому же тесты, что был выше :
Код:
        m_pStringList = new QStringList;
QStringList & List = *m_pStringList;
List<<"hello"<<"world";

QStringListModel ;
m_pEdit = new QLineEdit;
setCentralWidget(m_pEdit);
m_pCompleter = new QCompleter(this);
m_pModel = new MyModel;
m_pModel->SetList(m_pStringList);
m_pCompleter->setModel(m_pModel);
m_pEdit->setCompleter(m_pCompleter);

m_pTestAction = new QAction(tr("Test action"), this);
m_pTestAction->setShortcut(tr("Ctrl+T"));
addAction(m_pTestAction);
connect(m_pTestAction, SIGNAL(triggered()), this, SLOT(Test()));
По сигналу Test, я добавлял еше пару значений в StringList.
Код:
	QStringList & List = *m_pStringList;
List<<"hacker"<<"wrapper";
//m_pModel->SetList(m_pStringList);

И ничего - почему то все равно вижу только hello и world. Если раскометнировать m_pModel->SetList(m_pStringList) - ничего не изменится (проверял по отладчику код в функции Test выполняется).

Мне просто нужно создать эффективную модель распределения памяти, чтобы эти строки никогда не копировались, а только указатели с нужными наборами данных в Model передовались - поэтому я вот так и изращаюсь. Здесь конечно пример сильно упрощен, здесь набора данных нет, просто один QStringList.


Название: Re: Собственная модель для QCompleter
Отправлено: Red Devil от Июль 05, 2008, 13:29
Получилось сделать так как хотел :
Код:
QStringList & List = *m_pStringList;
List<<"hacker"<<"wrapper";
m_pCompleter->setModel(pModel);

Правда я что-то не понимаю, если мы SetModel передаем указатель - почему этот обьект копируется ???
Ведь если бы он не копировался, то изменения должны были бы сразу в силу вступить.
Или это зависит от внутренней реализации, например Completer узнает кол-во элементов в Model, только при ее установке SetModel, а не во время выполнения ?
Как вы думаете ?


Название: Re: Собственная модель для QCompleter
Отправлено: ритт от Июль 05, 2008, 13:34
я, например, думаю, что стоит читать документацию. а если что-то остаётся непонятным после прочтения документации, всегда можно подглядеть соответствующие сырцы

читать инсертРовз


Название: Re: Собственная модель для QCompleter
Отправлено: Red Devil от Июль 05, 2008, 13:52
Я прочитал и не понял.
Скопировал реализацию из QStringListModel - эта функция вообще никогда не вызывается при работе.


Название: Re: Собственная модель для QCompleter
Отправлено: ритт от Июль 05, 2008, 15:20
QCompleterModel::setSourceModel:
Код:
        connect(source, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted()));
        connect(source, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(invalidate()));
rowsInserted зовётся из endInsertRows (если правильно помню)

думаю, если ты (правильно) переопределишь в своей модели insertRows и будешь добавлять значения через неё, комплитер будет адекватно реагировать