2010-11-18 98 views
1

我有一个QTreeView,我已经在其中实现拖放以允许重新排序项目。qt: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... 

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

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

我已经设法正确编码除了限制放置操作,留在一个特定的父母的部分的标志。我只是不知道如何捕获当前拖动的QModelIndex(从中我可以确定父母,祖父母等)

谢谢!

这里是我的代码为旗帜的方法,如果它有帮助:注:我指的顶级儿童节点(即'食品'),下一级作为组(即'水果'),和最后两个级别(即生菜和冰山生菜)都是Params。

#--------------------------------------------------------------------------- 
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 

回答

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) 

(请注意,我真正的意思是:“我不希望打扰拦截事件” :-)

+0

这是非常有帮助的感谢,我遇到了这个确切的问题。 – TrevorB 2014-03-12 16:23:50