Python object in QMimeData

I implement a QTreeView drag and drop based on my custom model. Everything works fine, my tree displays data, drag and drop is on, and now the last step ahead of me is to drag and drop data. To do this, I need to implement the mimeTypes, mimeData and dropMimeData methods in my model. And now my question is: is there a simple standard way to pass an arbitrary Python object through QMimeData? I only take an internal step inside a QTreeView that displays the hierarchy of my Python Person classes. And I want to reorder them. No drag and drop outside the application, even out of control. I found only one tutorial: link text . But is this the only way? Cannot be done without encoding a Python object in ByteArray. I need a really simple solution for my only Person class. Thanks.

+1
source share
2 answers

Do not try to implement drag and drop while updating python base object. This will not work if the drag is outside your process; and it will not work for the copy operation (your node objects probably cannot exist in several places in the tree).

Think of dragging and dropping as three operations:

  • serialize data to some byte string
  • deserialize to a new index (or new indexes)
  • (optional: if "move" rather than "copy"), delete the old index (s)

myData () and dropMimeData () are the serialization and deserialization operations that you provide. Python provides some easy ways to implement them - check the documentation for the brine module. If you're lucky, pickle.dumps () and pickle.loads () will work out-of-the-box for you.

Edit: I could not figure out how to embed the code in the comments, so here is the solution that my comment refers to. This is safe, in the sense that it will fail by throwing a KeyError instead of causing failures if you break your rules.

# drag: store off the data in a safe place, and serialize a cooky # that the drop target can use to retrieve the data. self.__tmp_storage_dct = { self.__tmp_storage_cooky: stuff } m.setData(self.rowlistptr_mime_type, QByteArray(pickle.dumps(self.__tmp_storage_cooky))) self.__tmp_storage_cooky += 1 # drop: if mime.hasFormat(self.rowlistptr_mime_type): print "got tmpstorage" cooky = pickle.loads(mime.data(self.rowlistptr_mime_type).data()) nodes = self.__tmp_storage_dct.pop(cooky) 
+2
source

Well, I think I have a possible solution for you.

Keep in mind that I am a complete neophyte in this area, so there is no guarantee that it a) works b) is a worthy solution c) does not make the "real" programmer quit his lunch.

I did the conversion of the entire ancestor tree of a specific item to a text list of pairs of row column pairs. (i.e., list the row and column of the item being dragged, the row and column of its parent, the row and column of the parent, etc.) until we return to the invalid index - that is, the root)

It looks something like this (this example shows that the item being dragged has four depth levels):

 2;0,1;0,5;0,1,0 ^ ^ ^ ^ | | | | | | | great grandparent (and child of the root item) | | | | | grandparent | | | parent | item being dragged 

Later, in the dropMimeData function, I cancel the list (so that it reads from the root as long as it is being dragged) and create indexes each time until I return to the initially dragged item.

Here are the code snippets that make everything work. Again, I cannot guarantee that this is a good idea, it just works and does not require you to serialize your python objects in ByteArray.

Hope this helps.

 #--------------------------------------------------------------------------- def mimeTypes(self): """ Only accept the internal custom drop type which is plain text """ types = QtCore.QStringList() types.append('text/plain') return types #--------------------------------------------------------------------------- def mimeData(self, index): """ Wrap the index up as a list of rows and columns of each parent/grandparent/etc """ rc = "" theIndex = index[0] #<- for testing purposes we only deal with 1st item while theIndex.isValid(): rc = rc + str(theIndex.row()) + ";" + str(theIndex.column()) theIndex = self.parent(theIndex) if theIndex.isValid(): rc = rc + "," mimeData = QtCore.QMimeData() mimeData.setText(rc) return mimeData #--------------------------------------------------------------------------- def dropMimeData(self, data, action, row, column, parentIndex): """ Extract the whole ancestor list of rows and columns and rebuild the index item that was originally dragged """ if action == QtCore.Qt.IgnoreAction: return True if data.hasText(): ancestorL = str(data.text()).split(",") ancestorL.reverse() #<- stored from the child up, we read from ancestor down pIndex = QtCore.QModelIndex() for ancestor in ancestorL: srcRow = int(ancestor.split(";")[0]) srcCol = int(ancestor.split(";")[1]) itemIndex = self.index(srcRow, srcCol, pIndex) pIndex = itemIndex print itemIndex.internalPointer().get_name() return True 
+1
source

Source: https://habr.com/ru/post/951970/


All Articles