[Qt-interest] if i use QAbstractItemModel::beginMoveRows willselection track moved rows?

Stephen Kelly steveire at gmail.com
Wed Jun 15 13:34:42 CEST 2011


On Wed, Jun 15, 2011 at 9:06 AM, Ross Bencina
<rossb-lists at audiomulch.com> wrote:
> Stephen Kelly wrote:
>>
>> Ross Bencina wrote:
>>
>>> <snip>
>>>
>>> My problem is that after the drag and drop operation, item A is no longer
>>> selected because I am using emit dataChanged() in my model to invalidate
>>> the rows. Question: if I instead used beginMoveRows()/endMoveRows() then
>>> would the selection update correctly?
>>
>> Yes. The begin/endMoveRows methods update the QPersistentIndexes, which is
>> what the QItemSelection uses to keep the selection up to date. I think I
>> saw
>> that use of dataChanged to handle moves in a book last year, but it is
>> completely wrong for the reason you just hit. In the model, data changes
>> and
>> structural changes are entirely separate.
>
> Thanks for clarifying that Stephen. It makes sense now. (but gee, porting
> from a Widget implementation to a ItemView implementation is like having
> your head turned inside out).

Yep, I think there's definitely room for high level documentation
about concepts in itemviews.

>
>
>>> In any case, the above example is not a contiguous move since
>>> source={1,2,3,4} and destination={4,1,2,3}. How can I deal with this? or
>>> should I just hack my model to directly modify the selection after a
>>> drag-and-drop operation?
>>
>> if (!beginMoveRows(0, 0, QModelIndex(), 4, QModelIndex()))
>>  return; // Invalid move attempted.
>>
>> Node *n = myVector.takeFirst();
>> myVector.append(n);
>>
>> endMoveRows();
>
>
> Hmm, well those parameters to beginMoveRows() don't look quite right to me.
> The docs say:
> bool QAbstractItemModel::beginMoveRows ( const QModelIndex & sourceParent,
> int sourceFirst, int sourceLast, const QModelIndex & destinationParent, int
> destinationChild )

Right. I guess I didn't look at the docs :).

should be:

if (!beginMoveRows(QModelIndex(), 0, 0, QModelIndex(), 4))
 return; // Invalid move attempted.

>
> I remain unconvinced that beginMoveRows/endMoveRows can actually do what I
> asked since the beginMoveRows docs seems to imply that it is used for moving
> a contiguous selection from one place in the model to another only.

Indeed it is for contiguous selections. If you have non-contiguous
selections you can break them up into non-contiguous ones. See the
implementation here for example where I create multiple command
objects in the non-contiguous case and then execute them (they notify
the move internally):

https://projects.kde.org/projects/kde/kdelibs/repository/revisions/master/entry/kdeui/tests/proxymodeltestsuite/dynamictreemodel.cpp

>
> What I have worked out in the mean time is:
> emit layoutAboutToBeChanged();
>
> QModelIndexList from, to;
>
> // code to insert the appropriate index mappings into from -> to
>
> changePersistentIndexList( from, to );
>
> emit layoutChanged();
>
> This supports non-contiguous source and/or destination row sets, and seems
> to work correctly (selection is correct after move).

Yes, that's what begin/endMoveRows does too pretty much.

>
> I still don't understand what a persistent index is though.
>

The persistent index corrects 'automatically' when the model structure changes:

#include <QtGui>

int main(int argc, char **argv)
{

  QStringListModel model(QStringList() << "Monday"
                                       << "Tuesday"
                                       << "Wednesday"
                                       << "Thursday"
                                       << "Friday"
  );

  QModelIndex nonPersistent = model.index(2, 0);

  qDebug() << "The index is " << nonPersistent
           << ", the data is " << nonPersistent.data();

  QPersistentModelIndex persistentIndex(nonPersistent);

  qDebug() << "Removing a row";
  model.removeRow(0);

  qDebug() << "Persistent: " << persistentIndex << persistentIndex.data();
  qDebug() << "Non-Persistent: " << nonPersistent << nonPersistent.data();

}

$ ./stringmodel
The index is  QModelIndex(2,0,0x0,QStringListModel(0xbfae4404) )  ,
the data is  QVariant(QString, "Wednesday")
Removing a row
Persistent:  QModelIndex(1,0,0x0,QStringListModel(0xbfae4404) )
QVariant(QString, "Wednesday")
Non-Persistent:  QModelIndex(2,0,0x0,QStringListModel(0xbfae4404) )
QVariant(QString, "Thursday")



More information about the Qt-interest-old mailing list