-1

I would like to know the best way to achieve the following thing in QML:

I have a ListView with droppable elements and a Grid initialy filled with DropArea. The ListView uses a model derived from QAbstractItemModel. I would like to drop an element on the grid and interact with it (rename it for instance). For now, any modifications in the ListView update the model, but how modifications of the element in the grid could update the model ?

There can be multiple items dropped in the grid corresponding to a subset of ListView's model. I do not know how can I achieve this. The Package can not be used because the Grid is not a GridView and Items must be moved/set at specific positions. So I tried to:

  • create a ListView displayed on the dropped item, using the same model as the source ListView used to drag items,
  • set the same rootIndex, then the same index

I am close to a solution but I think it is not the best way to do this.

Any clue ?

Thanks

Henry Fané
  • 93
  • 2
  • 7
  • A model's item or a view's item? The data part or the visual part? – dtech Apr 22 '16 at 11:17
  • I would like to have different visual representation of the same model item in a ListView and in a component in a Grid. So, a modification of the item in the ListView should update the item in the Grid and vice-versa. – Henry Fané Apr 22 '16 at 11:21

2 Answers2

0

I would like to have different visual representation of the same model item in a ListView and in a component in a Grid. So, a modification of the item in the ListView should update the item in the Grid and vice-versa.

If your model's data is not QObject derived with NOTIFY and properties, notifications of changes can only be made through the model.

And since you won't be using the model for the grid, that means your model has to use underlying QObject instances. A generic model object might come in handy.

When you have that you only need to reference the underlying QObject model item and use bindings to set up your list view delegate. Then when you drag and drop, you only need to pass a reference to the QObject to that other visual representation which you will be creating inside the grid.

Lastly, take care not to be left with dangling references when you remove items from the model, as that will most likely hard-crash your application. Use the onDestruction attached signal to clear elements from the grid as the model item objects are destroyed.

Community
  • 1
  • 1
dtech
  • 47,916
  • 17
  • 112
  • 190
  • Thanks, I am going to watch this. I will also take a closer look at the Package element since the element dropped on the grid hosts a View. – Henry Fané Apr 22 '16 at 12:20
0

I finally found a solution by create a C++ type which inherits from QObject an which can be embedded in a QML object. This type has read/write properties and is initialized with the same model as the ListView. The interesting methods are:

/* writing to a property **from QML** goes here */
void ModelItem::setName(const QString& name)
{
    setModelData(GroupMemberModel::Nom, name);
}
/* then here */
bool ModelItem::setModelData(GroupMemberModel::Role role, const QVariant& value)
{
    return m_model->setData(m_modelIndex, value, role);
}

/* any changes in the model fall here (signals/slots mecanism)*/
void ModelItem::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
{
    if(m_modelIndex.row() < topLeft.row() || m_modelIndex.row() > bottomRight.row())
        return;
    if(m_modelIndex.column() < topLeft.column() || m_modelIndex.column() > bottomRight.column())
        return;
    //Index is modified, emit signal
    foreach(int role, roles) {
        emitDataChanged(role);
    }
}
/* **notify QML** by emit signal on property */
void ModelItem::emitDataChanged(int role) const
{
    if(role < (Qt::UserRole+1))
        role+=Qt::UserRole+1;

    switch(role)
    {
    case GroupMemberModel::Nom:
        emit nameChanged();
        break;
    default:
        qDebug() << "ModelItem::dataChanged, unknown role";
        break;
    }
}

This works as needed and is simplier than what I thought.

Henry Fané
  • 93
  • 2
  • 7