2010-11-18 24 views
1

J'ai un QTreeView dans lequel j'ai implémenté le glisser-déposer pour permettre le réordonnancement des articles.qt: QTreeView - limiter le glisser-déposer pour n'être possible qu'avec un grand-parent (ancêtre) particulier

suivant donné l'exemple d'un arbre:

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

marqué quelque chose comme draggable peut être traîné. Tout élément marqué comme parentable peut contenir un élément déplaçable en tant qu'enfant. Tout ce qui est marqué fixe est, bien, corrigé.

Ma question est, comment pourrais-je faire pour limiter la chute d'un élément pour rester dans un parent particulier? Par exemple, je pourrais glisser 'bloodOrange' et en faire un enfant de 'pomme' ou 'orange' (ou même simplement changer sa position ordinale à l'intérieur de 'Fruit'), mais je ne devrais pas pouvoir en faire un enfant de carottes ou laitue etc.

J'ai réussi à coder correctement les drapeaux pour tout sauf la partie qui limite une opération de dépôt pour rester dans un parent particulier. Je ne sais pas comment capturer le QModelIndex actuellement traîné (à partir de laquelle je peux déterminer parent, grand-parent, etc.)

Merci!

Voici mon code pour la méthode des drapeaux au cas où cela aiderait: Note: Je me réfère aux enfants de niveau supérieur comme Nodes (ie 'Food'), le prochain niveau comme Groupes (ie 'Fruit'), et le final deux niveaux (ie laitue et IcebergLettuce) sont tous deux des 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 

Répondre

1

Si vous voulez la faire glisser pour afficher l'icône « non autorisés » lors du survol de certaines lignes, je crois que vous ne pouvez pas le faire à partir du modèle. Vous devez intercepter les événements dragEnter/Move sur le wiedget View. Toutefois, dropMimeData() peut renvoyer False pour indiquer que la suppression est rejetée.

Notez que (dans ma version de Qt) il y a un bogue dans qdnd_win concernant les gouttes qui sont rejetées par le modèle. Voici ma solution de contournement basée sur une source de plongée; c'est une méthode définie sur ma sous-classe 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) 

(Notez que, par « travail non négligeable » Je veux dire vraiment « Je ne veux pas déranger intercepter les événements » :-)

+0

C'était très utile merci, je connaissais ce problème. – TrevorB