Russian Qt Forum
Сентябрь 30, 2024, 20:30 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Собственная модель для QCompleter  (Прочитано 6885 раз)
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 ничего не выводит.

В чем проблема ?
Записан
Zmeishe
Гость
« Ответ #1 : Июль 05, 2008, 08:05 »

Попробуй, всё-таки, Q_OBJECT в своём классе прописать.
Похоже от твоей модели ждут сигналов, а они не идут.
Код:
class MyModel : public QAbstractListModel
{
 Q_OBJECT
private:
QStringList * m_pList;
public:
...
А функции data, setData и rowCount - они все в базовом классе virtual объявлены.
Объяви их у себя тоже virtual.
Записан
Red Devil
Гость
« Ответ #2 : Июль 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;
}

};
Записан
ритт
Гость
« Ответ #3 : Июль 05, 2008, 11:39 »

А функции data, setData и rowCount - они все в базовом классе virtual объявлены.
Объяви их у себя тоже virtual.
зачем?
Записан
Zmeishe
Гость
« Ответ #4 : Июль 05, 2008, 11:51 »

Исключительно из уважения к тем, кто будет потом смотреть эти исходники.
Записан
Zmeishe
Гость
« Ответ #5 : Июль 05, 2008, 11:57 »

Все сделал - не помогло  Непонимающий

Единственное, что на ум приходит, попробуй в функции data выдавать данные ещё на Qt::EditRole
Записан
ритт
Гость
« Ответ #6 : Июль 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;
}
Записан
Red Devil
Гость
« Ответ #7 : Июль 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.
Записан
Red Devil
Гость
« Ответ #8 : Июль 05, 2008, 13:29 »

Получилось сделать так как хотел :
Код:
QStringList & List = *m_pStringList;
List<<"hacker"<<"wrapper";
m_pCompleter->setModel(pModel);

Правда я что-то не понимаю, если мы SetModel передаем указатель - почему этот обьект копируется Непонимающий
Ведь если бы он не копировался, то изменения должны были бы сразу в силу вступить.
Или это зависит от внутренней реализации, например Completer узнает кол-во элементов в Model, только при ее установке SetModel, а не во время выполнения ?
Как вы думаете ?
Записан
ритт
Гость
« Ответ #9 : Июль 05, 2008, 13:34 »

я, например, думаю, что стоит читать документацию. а если что-то остаётся непонятным после прочтения документации, всегда можно подглядеть соответствующие сырцы

читать инсертРовз
Записан
Red Devil
Гость
« Ответ #10 : Июль 05, 2008, 13:52 »

Я прочитал и не понял.
Скопировал реализацию из QStringListModel - эта функция вообще никогда не вызывается при работе.
Записан
ритт
Гость
« Ответ #11 : Июль 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 и будешь добавлять значения через неё, комплитер будет адекватно реагировать
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.091 секунд. Запросов: 21.