3

我有一个 QTreeView,我在其中实现了拖放以允许重新排序项目。

给定以下树的示例:

Food                        <--fixed
|--Vegetables               <--fixed
|  |--carrots            <-- draggable/parentable
|  |--lettuce            <-- draggable/parentable
|  |  |--icebergLettuce  <-- draggable but NOT parentable
|--Fruit                    <-- fixed
|  |--apple              <-- draggable/parentable
|  |--orange             <-- draggable/parentable
|  |--bloodOrange        <-- draggable/parentable
etc...

任何标记为可拖动的东西都可以被拖动。任何标记为 parentable 的东西都可能有一个可拖动的项作为子项。任何标记为固定的东西都是固定的。

我的问题是,我将如何限制物品的丢弃以留在特定的父母中?例如,我可以拖动 'bloodOrange' 并使其成为 'apple' 或 'orange' 的孩子(或者甚至只是更改其在 'Fruit' 中的序号位置),但我不应该让它成为胡萝卜的孩子或生菜等

我已经成功地为除了限制放置操作以保持在特定父级中的部分之外的所有内容正确编码了标志。我只是不知道如何捕获当前拖动的 QModelIndex (从中我可以确定父母、祖父母等)

谢谢!

这是我的 flags 方法的代码,以防它有帮助: 注意:我将顶级子级称为节点(即“食物”),下一个级别称为组(即“水果”),最后两个级别(即lettuce 和 icebergLettuce) 都是参数。

#---------------------------------------------------------------------------
def flags(self, index):
    """
    Returns whether or not the current item is editable/selectable/etc. 
    """

    if not index.isValid():
        return QtCore.Qt.ItemIsEnabled

    #by default, you can't do anything
    enabled = QtCore.Qt.NoItemFlags
    selectable = QtCore.Qt.NoItemFlags
    editable = QtCore.Qt.NoItemFlags
    draggable = QtCore.Qt.NoItemFlags
    droppable = QtCore.Qt.NoItemFlags

    #get a pointer to the referenced object
    item = index.internalPointer()

    #only 'valid' cells may be manipulated ('valid' is defined by the obj)
    if item.column_is_valid(index.column()):

        #all valid cells are selectable and enabled
        selectable = QtCore.Qt.ItemIsSelectable
        enabled = QtCore.Qt.ItemIsEnabled

        #column 0 cells may occasionally be dragged and dropped
        if index.column() == 0:

            #drag/drop is only possible if it is a param...
            if item.get_obj_type() == 'param':

                #...and then only child-less params may be dragged...
                if item.get_child_count() == 0:
                    draggable = QtCore.Qt.ItemIsDragEnabled

                #...and only params with a group as parent may be dropped on
                if item.get_parent().get_obj_type() == "group":
                    droppable = QtCore.Qt.ItemIsDropEnabled

        #all other valid columns > 0 may be edited (no drag or drop)
        else:                
            editable = QtCore.Qt.ItemIsEditable

    #return our flags.
    return enabled | selectable| editable| draggable| droppable 
4

1 回答 1

1

如果您希望拖动在某些行上悬停时显示“不允许”图标,我相信您无法从模型中执行此操作。您必须拦截 View wiedget 上的 dragEnter/Move 事件。

但是,dropMimeData() 可以返回 False 以指示丢弃被拒绝。

请注意(在我的 Qt 版本中)在 qdnd_win 中存在一个错误,该错误与模型拒绝的丢弃有关。这是我基于一些来源潜水的解决方法;这是在我的 QTreeView 子类上定义的方法:

def dropEvent(self, evt):
    QTreeView.dropEvent(self, evt)
    if not evt.isAccepted():
        # qdnd_win.cpp has weird behavior -- even if the event isn't accepted
        # by target widget, it sets accept() to true, which causes the executed
        # action to be reported as "move", which causes the view to remove the
        # source rows even though the target widget didn't like the drop.
        # Maybe it's better for the model to check drop-okay-ness during the
        # drag rather than only on drop; but the check involves not-insignificant work.
        evt.setDropAction(Qt.IgnoreAction)

(请注意,“不重要的工作”我的意思是“我不想打扰拦截事件”:-)

于 2011-02-15T03:21:52.320 回答