2010-11-18 96 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