Results 1 to 5 of 5

Thread: PyQt Tree Model: move TreeItems

  1. #1
    Join Date
    Aug 2012
    Posts
    4
    Qt products
    Platforms
    Windows

    Default PyQt Tree Model: move TreeItems

    Hello,

    I have a document class that contains several "Ikwed Objects". Each "Ikwed Object" can have several child "Ikwed Objects".
    The document has a tree model, that is used to show the hierarchy of the "Ikwed Objects" in a tee view.

    I am able to create new "Ikwed Objects" in the document, append or insert childs and also to remove childs in the tree model.

    However, If I try to move a "child tree item" to the root branch, I get errors in the tree view or infite loops that I do not understand.

    For example I want to move the child IkwedObject11 to the start of the root branch:

    -IkwedObject0
    -IkwedObject1
    ++ IkwedObject11
    ++ IkwedObject12

    =>

    -IkwedObject11
    -IkwedObject0
    -IkwedObject1
    ++ IkwedObject12

    Could you please have a look at the function "moveTreeItem" of the attached example and give me hints how to adapt it?
    I wrote the example with Spyder 2.1.9 (PythonXY on Windows Platform, with QT 4.9)

    Qt Code:
    1. def moveTreeItem(self, treeItem, newParentTreeItem, newRow):
    2. oldParentTreeItem = treeItem.parentItem
    3. oldRow = oldParentTreeItem.childItems.index(treeItem)
    4.  
    5. #self.beginMoveRows(self.getIndex(oldParentTreeItem), oldRow, oldRow, self.getIndex(newParentTreeItem), newRow)
    6.  
    7. self.insertTreeItem(treeItem, newParentTreeItem, newRow)
    8. self.removeTreeItemByRow(oldParentTreeItem, oldRow)
    9.  
    10. #self.endMoveRows()
    11.  
    12. def insertTreeItem(self, childItem, parentItem, childRow=0):
    13. #insert a tree item as a new child of a parent item at a given row
    14. #childItem.parentItem = parentItem
    15. if childRow <= parentItem.childCount():
    16. parentIndex = self.getIndex(parentItem)
    17. self.beginInsertRows(parentIndex, childRow, childRow)
    18. parentItem.childItems.insert(childRow, childItem)
    19. self.endInsertRows()
    20. else:
    21. print "Error in insertTreeItem: row is larger row count: " + str(row) + " > " + str(parentItem.childCount())
    22.  
    23. def removeTreeItem(self, treeItem):
    24. parentItem = treeItem.parentItem
    25. row = treeItem.row()
    26. self.removeTreeItemByRow(parentItem, row)
    27.  
    28. def removeTreeItemByRow(self, parentItem, row):
    29. parentIndex = self.getIndex(parentItem)
    30. self.beginRemoveRows(parentIndex, row, row)
    31. del parentItem.childItems[row]
    32. self.endRemoveRows()
    To copy to clipboard, switch view to plain text mode 

    The code creats a default document and displays it. Please comment the line 345

    treeModel.moveTreeItem(treeObj11, rootItem, 0)

    at the end of the init function of TestWidget to see the model without moved items.

    The wrong result I get is:

    -IkwedObject12
    -IkwedObject0
    -IkwedObject1
    ++ IkwedObject12

    Why is the first item "IkwedObject12" instead of "IkwedObject11" ??!!


    Sunny regards,

    Stefan
    Attached Files Attached Files
    Last edited by matameko; 26th November 2012 at 13:14.

  2. #2
    Join Date
    Aug 2012
    Posts
    4
    Qt products
    Platforms
    Windows

    Default Re: PyQt Tree Model: move TreeItems

    One option seems to be to clone the tree item with
    import copy
    copy.deepcopy
    and to use the cloned tree item for the insert command.

  3. #3
    Join Date
    Feb 2010
    Posts
    96
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    4
    Thanked 5 Times in 5 Posts

    Default Re: PyQt Tree Model: move TreeItems

    You can just take the item from the tree instead of cloning it. Either use .takeChild or .takeToplevelItem which takes the item and its children.

    You also run this code on line 227:
    Qt Code:
    1. super(IkwedDocument.TreeModel.TreeItem, self).__init__(parentTreeItem)
    To copy to clipboard, switch view to plain text mode 

    I highly recommended you NEVER run super inside the __init__ method. Super operates with the Method Resolution Order, and if you start basing one class off multiple classes you are going to run into trouble. Also, super returns a proxy. It is best to instantiate the class __init__ method more directly, be it QtCore.QAbstractItemModel.__init__(self) or whatever other class you want to use. Trust me ... I use super every day in my code and the best way to use super is when you reimplement class methods and want to call the original unmodified version.

    To be honest, I am not sure what you are doing wrong. I have a pretty good model for the QTreeWidget. Admittedly it is something of a hacked version of the Qt tree widgets, but it does what you want. The code can be found here: http://tech.madmathlabs.info/index.c...e/tree_dock.py

  4. #4
    Join Date
    Aug 2012
    Posts
    4
    Qt products
    Platforms
    Windows

    Default Re: PyQt Tree Model: move TreeItems

    Thank you for your tips. I am going to have a look at the alternative to super.

    I found out that my over all structure could be more simple.
    My example above uses a "TreeModel" class and the tree has child items of a "TreeItem" class.
    These tree items contain the "IkwedObjects" that I want to manage.

    Now I moved all Functions of the "TreeItem" class to the "TreeModel" class and directly
    use the "IkwedObjects" as tree items. I do not need extra functions in the
    "IkwedObjects". All can be done in the tree model. Without the extra TreeItem class
    my structure is more flat and the errors did somehow disappear.

  5. #5
    Join Date
    Feb 2010
    Posts
    96
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    4
    Thanked 5 Times in 5 Posts

    Default Re: PyQt Tree Model: move TreeItems

    You are welcome. When it comes to super, I will stare down a coder with a college degree and let them know .. they probably don't understand the usage of super. Even in PySide I see super used under the __init__ method in such a manner
    Qt Code:
    1. class Widget(QWidget):
    2.  
    3. def __init__(self):
    4. super(Widget, self).__init__(self)
    To copy to clipboard, switch view to plain text mode 
    and that is a **wrong** usage. Yes ... it is absolutely **wrong** .. even if it appears to work how you want it too.

    Super works by reaching into the Method Resolution Order (MRO). You pass a module that super uses to obtain an index from the MRO, and then it returns a proxy of the index+1. So, for the above example the MRO would look like, [Widget, QWidget, etc ...] and super would return a a proxy of QWidget and then run it's __init__ method pass any arguments you send it.

    The real problem is two fold. First ... you are using a proxy to run methods. The proxy is a module that has already been instantiated, it may have new objects assigned to variable names, and further more the data may have been altered in some other way during run time. Secondly ... you are reaching into the Method Resolution Order. While this has some really cool benefits when you use super correctly, if you don't understand how the MRO is itemized, what methods are in the MRO list, just basically don't understand the MRO, or any other point of misunderstanding ... you are not sure what you are doing .. only that it appears to work.

    Super is an awesome built-in within Python and it has really great uses. I mainly use it so I can modify class defined methods (functions) and then run the original unmodified version if I need too. In Qt, since just about everything is based of QObject or QWidget, or has some other basic class that it inherits, it can provide even more functionality. Say for example you want to create a new QWidget class that all of your widgets will inherit.
    Qt Code:
    1. class MyWidget(QWidget):
    2. def __init__(self):
    3. QWidget.__init__(self)
    To copy to clipboard, switch view to plain text mode 
    You can then use that class in place of QWidget, redifine any of the class methods, and if you still want to use the original QWidget method you can reach into the MRO and obtain it. If I am not mistaken it would look like this.
    Qt Code:
    1. super(MyWidget, self).show()
    To copy to clipboard, switch view to plain text mode 
    And then super would find the MyWidget class and use that as index.

    Here are some blog posts I made about super: http://weblog.madmathlabs.com/?cat=10 (read from the bottom up)

Similar Threads

  1. SQL Tree Model Help
    By MTK358 in forum Newbie
    Replies: 9
    Last Post: 22nd June 2015, 15:02
  2. PyQt Busy progress Bar does not move
    By ilion_007 in forum Qt Programming
    Replies: 0
    Last Post: 10th May 2011, 01:33
  3. Writing a Tree model.
    By kaushal_gaurav in forum Qt Programming
    Replies: 6
    Last Post: 16th January 2009, 11:22
  4. how to move between columns in tree view?
    By Scott Shiff in forum Qt Programming
    Replies: 1
    Last Post: 30th January 2007, 08:01
  5. how to display full tree item name on mouse move ?
    By rajesh in forum Qt Programming
    Replies: 5
    Last Post: 15th November 2006, 08:41

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.