Объект Python в QMimeData - PullRequest
       16

Объект Python в QMimeData

2 голосов
/ 18 ноября 2010

Я реализую перетаскивание QTreeView на основе моей пользовательской модели.Все работает нормально, мое дерево отображает данные, перетаскивание включено, и теперь передо мной последний шаг - отбрасывать и передавать перетаскиваемые данные.Для этого мне нужно реализовать методы mimeTypes, mimeData и dropMimeData в моей модели.А теперь мой вопрос: есть ли простой стандартный способ передачи произвольного объекта Python через QMimeData?Я делаю только внутреннее перемещение в QTreeView, которое отображает иерархию моих классов Python Person.И я хочу изменить их порядок.Нет перетаскивания за пределы приложения, даже вне контроля.Я нашел только один учебник: текст ссылки .Но так ли это?Это не может быть сделано без кодирования объекта Python в ByteArray.Мне нужно действительно простое решение для моего единственного человека в классе.Спасибо.

Ответы [ 2 ]

2 голосов
/ 11 декабря 2010

Не пытайтесь реализовать перетаскивание путем переопределения базового объекта python.Это не сработает, если перетаскивание происходит извне вашего процесса;и при этом это не будет работать для операции копирования (ваши объекты-узлы, вероятно, не могут существовать в нескольких местах дерева).

Думайте о перетаскивании «перемещение» как о трех операциях:

  1. сериализовать данные в некоторую байтовую строку
  2. десериализовать в новый индекс (или новые индексы)
  3. (необязательно: если "переместить", а не "скопировать") удалить старый индекс (ы)

mineData () и dropMimeData () - это предоставляемые вами операции сериализации и десериализации.Python предоставляет несколько простых способов их реализации - проверьте документацию для модуля pickle.Если вам повезет, pickle.dumps () и pickle.loads () будут работать для вас из коробки.

Редактировать: я не мог понять, как вставить код в комментарии,так вот решение, к которому относится мой комментарий.Это безопасно, в том смысле, что он потерпит неудачу, выдав KeyError вместо того, чтобы вызвать сбои, если вы нарушите свои правила.

# 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)
1 голос
/ 23 ноября 2010

Хорошо, думаю, у меня есть для вас возможное решение.

Имейте в виду, что я неофит в этой области, поэтому нет никаких гарантий, что он а) работает, б) является достойным решением в) не заставит "настоящего" программиста бросить свой обед.

Что я сделал, так это преобразовал все дерево предков определенного элемента в текстовый список пар столбцов строк. (то есть перечислить строку и столбец перетаскиваемого элемента, строку и столбец его родителя, строку и столбец родителя его родителя и т. д., пока мы не получим недопустимый индекс - то есть корень)

Это выглядит примерно так (в этом примере показано, что перетаскиваемый элемент имеет четыре уровня глубины):

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...