2010-11-18 7 views
1

Ich habe eine QTreeView, in der ich Drag and Drop implementiert habe, um die Neuordnung von Artikeln zu ermöglichen.qt: QTreeView - limit Drag & Drop nur innerhalb eines bestimmten Großelternteils (Vorfahre)

das folgende Beispiel eines Baumes gegeben:

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

Alles markiert als ziehbar kann gezogen werden. Alles, was als Elternteil markiert ist, kann als Kind einen ziehbaren Gegenstand haben. Alles, was als fest markiert ist, ist, gut, behoben.

Meine Frage ist, wie würde ich gehen, um das Ablegen eines Artikels zu begrenzen, um in einem bestimmten Elternteil zu bleiben? Zum Beispiel könnte ich 'bloodOrange' ziehen und es zu einem Kind von 'Apfel' oder 'Orange' machen (oder einfach nur seine Ordinalposition innerhalb von 'Frucht' ändern), aber ich sollte es nicht zu einem Kind von Möhren machen oder Salat usw.

ich habe es geschafft, richtig die Flaggen mit Ausnahme des Teils für alles codieren, die eine Drop-Operation begrenzt innerhalb eines bestimmten Elternteil zu bleiben. Ich weiß nur nicht, wie die zur Zeit gezogen QModelIndex aufzeichnen zu können (von denen ich Eltern bestimmen, Großeltern, etc.)

Dank!

Hier ist mein Code für die Flags-Methode, falls es hilft: Hinweis: Ich beziehe mich auf die obersten Ebene Kinder als Knoten (dh "Essen"), die nächste Ebene als Gruppen (dh "Obst") und das Finale Zwei Ebenen (zB Salat und Eisberg) sind beide 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 

Antwort

1

Wenn Sie die Drag wollen die angezeigt werden „nicht erlaubt“ -Symbol, wenn sie über bestimmte Reihen schweben, ich glaube, Sie können es nicht aus dem Modell. Sie müssten die dragEnter/Move-Ereignisse in der Ansicht Wiedget abfangen.

Allerdings kann dropMimeData() False zurückgeben, um anzuzeigen, dass der Drop zurückgewiesen wurde.

Beachten Sie, dass (in meiner Qt-Version) gibt es einen Fehler in Bezug auf qdnd_win Tropfen ist, die durch das Modell abgelehnt. Hier ist meine Problemumgehung basierend auf einigen Quellentauchgängen; Dies ist eine Methode auf meiner QTreeView Unterklasse definiert:

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) 

(beachten Sie, dass durch „nicht unerhebliche Arbeit“ Ich meine wirklich „Ich will nicht, um die Ereignisse stören Abfangen“

+0

Das war :-) sehr hilfreich, danke, ich habe dieses genaue Problem erlebt. – TrevorB