Хорошо, думаю, у меня есть для вас возможное решение.
Имейте в виду, что я неофит в этой области, поэтому нет никаких гарантий, что он а) работает, б) является достойным решением в) не заставит "настоящего" программиста бросить свой обед.
Что я сделал, так это преобразовал все дерево предков определенного элемента в текстовый список пар столбцов строк. (то есть перечислить строку и столбец перетаскиваемого элемента, строку и столбец его родителя, строку и столбец родителя его родителя и т. д., пока мы не получим недопустимый индекс - то есть корень)
Это выглядит примерно так (в этом примере показано, что перетаскиваемый элемент имеет четыре уровня глубины):
2;0,1;0,5;0,1,0
^ ^ ^ ^
| | | |
| | | great grandparent (and child of the root item)
| | |
| | grandparent
| |
| parent
|
item being dragged
Позже, в функции dropMimeData я переворачиваю список (чтобы он читал из корня обратно в перетаскиваемый элемент) и строю индексы по одному, пока не вернусь к первоначально перетаскиваемому элементу.
Вот фрагменты кода, которые заставляют все это работать. Опять же, я не могу гарантировать, что это хорошая идея, просто она работает и не требует сериализации ваших объектов python в ByteArray.
Надеюсь, это поможет.
#---------------------------------------------------------------------------
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