Trying to implement drag and drop for QAbstractItemModel

Maurizio Berti maurizio.berti at gmail.com
Tue Apr 20 10:32:06 BST 2021


>
> Then, the problem is that you didn't implement the most important function
>> for drop events in a model: dropMimeData().
>>
>
> Ah, I thought that was required for external drops only.
>

A Qt model doesn't really care about the source of the drag and drop: it's
the view's responsibility to check if the dropped data should be managed by
the model or not, then the model will act accordingly. In this case it's
pretty straightforward that the source is the same, but models should
always provide a generic interface no matter the source. For instance, you
could drop an url from the browser, some text from an editor, or a document
from the file manager.


> Drag and drop always happens (or should happen) through QMimeData in Qt
>> models. Qt views (and their models) use the
>> "application/x-qabstractitemmodeldatalist" format to serialize data, which
>> is created by calling QAbstractItemModel.mimeData (see
>> https://doc.qt.io/qt-5/qabstractitemmodel.html#mimeData), and the
>> structure is the following:
>>
>
> Now, where did you learn about this format specification? I did not see it
> anywhere in the Qt documentation.
>

As far as I know, it's not clearly specified anywhere (there's a generic
description here:
https://doc.qt.io/qt-5/model-view-programming.html#mime-data ), but you can
find it in the sources of QAbstractItemModel:mimeData, which creates a
QDataStream with data encoded using :itemData() in the form:

stream << row << column << itemData(index)

(note that the above syntax is also available on PyQt, while unfortunately
it's not possible with the opposite >> assignment, due to Python dynamic
typing)


> I do have a question, though. Why do we need the condition itemRow < self.rowCount(QModelIndex())
> and itemCol < self.columnCount(QModelIndex()) ? For an internal drop,
> itemRow and itemCol should always satisfy it.
>

Mmmh, I believe I just did that without even thinking (I've been working a
lot with custom models lately). As long as the movement is internal, that's
obviously not required.

Going a bit beyond this particular example, what happens if the method
> mimeData has a list with multiple types? Method mimeData is supposed to
> return a single QMimeData, so there will be a single encoding of the data,
> and if so, for which of the multiple mime types?
>

In theory, you should always ensure that the format is
application/x-qabstractitemmodeldatalist before going on with this
implementation; according to your needs, you could always implement your
own alternatives for other types of mime data.

Also, in case of multiple supported mime types, how can dropMimeData know
> the format in which 'data' is encoded? It does not seem QMimeData provides
> a method indicating its format.
>

By default there is only one supported mime type
(x-qabstractitemmodeldatalist) for models, but QMimeData can theoretically
support any serializable content set using setData(), and you can add that
support by implementing mimeData() (just override it, call the base
implementation and then add more data formats): for instance,
QStandardItemModel also
creates application/x-qstandarditemmodeldatalist (which it uses for itself
when dropping).

Cheers,
Maurizio
-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20210420/83901f4c/attachment.htm>


More information about the PyQt mailing list