Russian Qt Forum

Qt => Qt Quick => Тема начата: qt_newer от Январь 19, 2015, 19:17



Название: Работа с ЛистВью и делегатами
Отправлено: qt_newer от Январь 19, 2015, 19:17
Есть список (id, name получаемый из базы данных), по нажатию на элемент которого должно открываться диалоговое окно с вопросом удалить ли текущую строку, если да, то в записи с соответствующим id изменяется поле deleted, и она перестает отображаться в списке.
Я могу передать index спп слоту, но не знаю, как передать  id. После апдейта таблицы есть 2 возможности: обновить модель в спп- в ContextProperty (что я сейчас делаю), либо убрать тек. запись внутри qml.
Таким образом, у меня 2 вопроса:
1) как удалить запись из модели внутри qml?
2) как получить id текущей записи в диалоговом окне?
Пример ниже: ???
ListView {
     id: mylist
     model: mymodel
     delegate:
         Rectangle
         {
                 Text {
                     text: id + '  ' +name
                 }
         }
         ...
         MouseArea
         {
             anchors.fill: parent
             onClicked:
             {
                 mylist.currentIndex = index;
                 mydialog.popupVisible = true

             }
         }
}
CustomDialog {

    id: mydialog
    popupVisible: false
    
    
    Button {
        ...
        onClicked: {
            mydialog.popupVisible = false
            // call cpp slot with id as parameter
        }
    }    
}


Название: Re: Работа с ЛистВью и делегатами
Отправлено: carrygun от Январь 20, 2015, 05:24
mylist.model.get(mylist.currentIndex).id


Название: Re: Работа с ЛистВью и делегатами
Отправлено: qt_newer от Январь 20, 2015, 12:55
Спасибо, но у меня модель наследуется от QSqlQueryModel и там нет метода get(), т.е. при попытке использовать mylist.model.get(mylist.currentIndex).id, получаю "Property 'get' of object is not a function"

В спп такой код выдает корректный ответ:
QModelIndex ind = mymodel.index(1, 0,QModelIndex());
qDebug() << "just test ID: " << mymodel.data(ind, Qt::UserRole).toInt();

Но использовать его в qml пока не получается:
console.log("current ID: " + mylist.model.data(mylist.currentIndex, mylist.model.UserRole )) выдает current ID: undefined

Вероятно, что-то не так с ролью, либо с определением модели:

class myModel : public QSqlQueryModel
{
    Q_OBJECT
public:
    myModel(QObject* parent = 0)
        : QSqlQueryModel(parent)
    {
        roleNamesHash.insert(Qt::UserRole,      QByteArray("id"));
        roleNamesHash.insert(Qt::UserRole + 1,  QByteArray("name"));
    }

    Q_INVOKABLE QVariant data(const QModelIndex& index, int role) const
    {
        if(role < Qt::UserRole) {
            return QSqlQueryModel::data(index, role);
        }

        QSqlRecord r = record(index.row());
        return r.value(role - Qt::UserRole);
    }

    QHash<int, QByteArray> roleNames() const { return roleNamesHash; }



private:
    QHash<int, QByteArray> roleNamesHash;
};

Если я дополнительно определяю в модели:
    Q_INVOKABLE QVariant get(const QModelIndex& index) const
    {
        QSqlRecord r = record(index.row());
        return r.value(0);
    }
то это опять работает в спп:
    qDebug() << "2nd test ID: " << mymodel.get(ind).toInt();
и не работает в qml:
console.log( "2nd test ID:" + mylist.model.get(mylist.currentIndex)) - возвращает 0


PS Код должен работать в Qt 5.0


Название: Re: Работа с ЛистВью и делегатами
Отправлено: carrygun от Январь 20, 2015, 13:07
У вас функция ожидает QModelIndex, а вы передаете int.


Название: Re: Работа с ЛистВью и делегатами
Отправлено: qt_newer от Январь 20, 2015, 13:17
да, похоже на то :-\
Я передаю mylist.currentIndex, а как передавать индекс модели ?

ListView {
     id: mylist
     model: mymodel
     delegate:
         ...
         MouseArea
         {
             anchors.fill: parent
             onClicked:
             {
                 mylist.currentIndex = index;
                 mydialog.popupVisible = true

             }
         }
}


Название: Re: Работа с ЛистВью и делегатами
Отправлено: qt_newer от Январь 20, 2015, 13:31
PS получилось только в спп функцию get() переделать, чтобы она int принимала, тогда все работает


Название: Re: Работа с ЛистВью и делегатами
Отправлено: qt_newer от Январь 20, 2015, 19:53
Спасибо с первой частью удалось разобраться, но теперь не знаю, как обновить листвью после изменения таблицы в спп слоте.
Если я делаю в спп слоте:

    QSqlQuery q;
    QString s= "UPDATE mytable SET deleted = 1 WHERE id ="+ id;
    if (!q.exec(s))
        qDebug() << q.lastError() << "in " << s;

    myModel mymodel;
    mymodel.setQuery("select * from mytable where deleted=0);

    view->rootContext()->setContextProperty("mymodel", &mymodel);

то это даже срабатывает для первой удаленной записи, но при попытке удалить еще одну- приложение вылетает

Также я пробую вместо обновления контекста сделать рефреш модели:
        QModelIndex ind = this->index(0, 0,QModelIndex());
        QModelIndex ind2 = this->index(rowCount()-1, columnCount()-1,QModelIndex());

        QVector<int> v;

        v << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 ...
        emit dataChanged(ind, ind2, v);

но в этом случае записи c делетед = 1 продолжают отображаться в листвью.

Заранее спасибо за любые советы!


Название: Re: Работа с ЛистВью и делегатами
Отправлено: qt_newer от Январь 22, 2015, 11:28
Удалось разобраться самостоятельно, проблема была в том, что при начальной установке и в спп слоте использовались разные объекты модели- введение синглтона решило проблему, и стало достаточно использовать в слоте:
    myModel *myModel = myModel::getInstance();
    myModel->setQuery(sql);