NARCISO, Rui wrote:
It worked nicely up to the sorting part.

And if th euser sorts the data himself, then eveything is ok.

It's just when I try to implement default sorting that that fails.

Maybe I can pick up on a signal telling that sorting is in progress to override 
this behaviour in the rowsInserted function...

-----Message d'origine-----
De : Baz Walter [mailto:[email protected]]
Envoyé : vendredi 11 décembre 2009 21:46
À : NARCISO, Rui
Cc : PyQt (E-mail)
Objet : Re: [PyQt] Drag & Drop with QTreeWidget


NARCISO, Rui wrote:
Hi again

Your approach worked nicely but when I tried to enable sorting using:

         self.setSortingEnabled(True)
         self.sortByColumn(0, QtCore.Qt.AscendingOrder)
I get a segmentation fault.

If i disable the sortByColumn then it works.

How then to set the sorting using column 0 by default ?

actually, i now think my approach was too crude. the trouble with using rowsInserted is that it is called every time items are added or moved (or sorted).

what is really needed is a way to add special handling only for dropped items. unfortunately, there does not appear to be an obvious way to detect what items were dropped and where. so i think the only reliable way to get the behaviour you want is to reimplement qtreewidget's drop event handling (which is probably doable, but not easy).

i had another look at reimplementing qtreewidget's drop event handling and it is in fact much easier than i thought. the code below simply reproduces the current behaviour (it's mostly a port of the qt source). hopefully it should not be too difficult to see how to adapt the code in the moveSelection function to get whatever alternate behaviours you want. (note that this example assumes internal moves only).


import sys
from PyQt4 import QtGui, QtCore


class TreeWidget(QtGui.QTreeWidget):
    def __init__(self, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)
        self.header().setHidden(True)
        self.setSelectionMode(self.ExtendedSelection)
        self.setDragDropMode(self.InternalMove)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        def add(num):
            item = QtGui.QTreeWidgetItem(
                    self, QtCore.QStringList('Item(%i)' % num))
            for i in xrange(1, 4):
                QtGui.QTreeWidgetItem(
                    item, QtCore.QStringList('Child(%i,%i)' % (num, i)))
            item.setExpanded(True)
        for i in xrange(1, 3):
            add(i)

    def dropEvent(self, event):
        if event.source() == self:
            QtGui.QAbstractItemView.dropEvent(self, event)

    def dropMimeData(self, parent, row, data, action):
        if action == QtCore.Qt.MoveAction:
            return self.moveSelection(parent, row)
        return False

    def moveSelection(self, parent, position):
        # save the selected items
        selection = [QtCore.QPersistentModelIndex(i)
                     for i in self.selectedIndexes()]
        parent_index = self.indexFromItem(parent)
        if parent_index in selection:
            return False
        # save the drop location in case it gets moved
        target = self.model().index(position, 0, parent_index).row()
        if target < 0:
            target = position
        # remove the selected items
        taken = []
        for index in reversed(selection):
            item = self.itemFromIndex(QtCore.QModelIndex(index))
            if item is None or item.parent() is None:
                taken.append(self.takeTopLevelItem(index.row()))
            else:
                taken.append(item.parent().takeChild(index.row()))
        # insert the selected items at their new positions
        while taken:
            if position == -1:
                # append the items if position not specified
                if parent_index.isValid():
                    parent.insertChild(
                        parent.childCount(), taken.pop(0))
                else:
                    self.insertTopLevelItem(
                        self.topLevelItemCount(), taken.pop(0))
            else:
                # insert the items at the specified position
                if parent_index.isValid():
                    parent.insertChild(min(target,
                        parent.childCount()), taken.pop(0))
                else:
                    self.insertTopLevelItem(min(target,
                        self.topLevelItemCount()), taken.pop(0))
        return True


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    tree = TreeWidget()
    tree.resize(200, 300)
    tree.move(300, 300)
    tree.show()
    sys.exit(app.exec_())


_______________________________________________
PyQt mailing list    [email protected]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to