Results 1 to 13 of 13

Thread: QTreeView display of graph (multiple parents of item)

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QTreeView display of graph (multiple parents of item)

    Unfortunately this is impossible to express using QAbstractItemModel. One can assume the "first" parent is the "real" parent but then again the structure becomes:

    Qt Code:
    1. struct Item {
    2. Item *parent;
    3. QList<Item*> otherParents;
    4. QList<Item*> children;
    5. };
    To copy to clipboard, switch view to plain text mode 

    The only way I see happening to represent a graph as a tree is to "snapshot" a subgraph that actually forms a tree and represent only this snapshot in the model. The data structure itself may contain other members (including pointers to items) however they are not relevant to the tree hierarchy of the model. You may look at it like on a genealogy tree. It is not really a tree but a graph but at a particular moment one is only looking only at its subgraph that is a regular tree.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  2. #2
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    3
    Thanked 453 Times in 435 Posts
    Wiki edits
    15

    Default Re: QTreeView display of graph (multiple parents of item)

    Quote Originally Posted by wysota
    Unfortunately this is impossible to express using QAbstractItemModel.
    Somehow I still believe that it is possible using QAbstractItemModel and QTreeView, but it not possible using the QModelIndex. As QTreeView uses QModelIndex to reference items in QAbstractItemModel, I would say it not possible using QModelIndex

    If we manage to have a CustomModelIndex (enhances QModelIndex) with information required to reference items in the graph (both downlinks and uplinks) it should be possible. But Again the problem is how do we make QTreeView use CustomModelIndex

    If somehow we are able to store two internalId / internalPointers in QModelIndex it should be possible. I would use the first internalPointer to store the item reference and the second internalPointer to store the item's parent (the parent under which the item is displayed in the QTreeView) reference.

    So it boils down to one question. Is it possible to store two internalPointers in QModelIndex?

    Quote Originally Posted by iraytrace
    At the moment, I am thinking of sub-classing QModelIndex (ugh) to extend it with the full path to the object.
    IMO OP tried to sub-class QModelIndex for same reason as above. Again here we have the same problem as above QTreeView is not able to understand sub-classed QModelIndex.

  3. The following user says thank you to Santosh Reddy for this useful post:

    fleebness (15th November 2011)

  4. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QTreeView display of graph (multiple parents of item)

    Quote Originally Posted by Santosh Reddy View Post
    Somehow I still believe that it is possible using QAbstractItemModel and QTreeView, but it not possible using the QModelIndex.
    Of course, if you reimplement the whole architecture to do something totally different then it will be possible. The same way as it will be possible to launch a rocket into space using QAbstractItemModel. However this will have little to do with the architecture of QAbstractItemModel.

    As QTreeView uses QModelIndex to reference items in QAbstractItemModel, I would say it not possible using QModelIndex
    It's not the fault of QTreeView. QAbstractItemModel has a parent() method that returns a SINGLE index. All views rely on that (if not for other things then at least for the root index of the view).


    If we manage to have a CustomModelIndex (enhances QModelIndex) with information required to reference items in the graph (both downlinks and uplinks) it should be possible. But Again the problem is how do we make QTreeView use CustomModelIndex
    You can put a custom pointer into the index but this will not teach QAbstractItemView to manipulate the graph.


    A side note: it IS possible to express a graph in QAbstractItemModel because it is possible to express a graph using a plain two dimensional array. However you need a custom view for that and you lose almost all benefits of having a QAbstractItemModel. it will be much simpler to do without the burden of QAbstractItemModel.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. The following user says thank you to wysota for this useful post:

    fleebness (15th November 2011)

  6. #4
    Join Date
    Nov 2011
    Location
    Maryland, USA
    Posts
    2
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    3

    Default Re: QTreeView display of graph (multiple parents of item)

    Thanks, everyone, for continuing the discussion.

    I think wysota has it right, that it could be expressed, but it isn't practical. To do this, it seems you have to build a tree first, then model the tree. That negates the point of using a model, so I may as well use QTreeWidget instead of QTreeView, if I'm going to show this as a tree. The more I think about this, the more I see it as impossible, and probably impractical, to use the view, so I probably shouldn't bother.

    Alternatively, I suppose, I could try creating a QGraphWidget and QGraphView (with associated QAbstractGraphModel, if I want to make this extensible, etc). That seems like an aggressive lot of code to write for someone new to Qt, though.

  7. #5
    Join Date
    May 2014
    Posts
    1
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Thanked 1 Time in 1 Post

    Default Re: QTreeView display of graph (multiple parents of item)

    I know this thread is too old, but maybe my findings will be useful.

    I also wanted to have multiple parents for my qtreeview entities (items) and came up with the following solution.

    I have an IndexData structure that contains information about current item and it's parent:
    Qt Code:
    1. struct IndexData{
    2. IndexData *parentIndex;
    3. Entity *parent;
    4. Entity *item;
    5. int row;
    6. };
    To copy to clipboard, switch view to plain text mode 

    When QAbstractItemModel::createIndex() function is called, I pass a pointer to IndexData structure as the third parameter.

    Full item model class is the following (Please note that it is a quick and dirty solution with memory leaks that was not well tested):
    Qt Code:
    1. #include "entitymodel.h"
    2. #include <QDebug>
    3.  
    4. EntityModel::EntityModel(Entity *root, QObject *parent) :
    5. {
    6. m_root = root;
    7. m_rootIndexData = new IndexData;
    8. m_rootIndexData->parent = 0;
    9. m_rootIndexData->parentIndex = 0;
    10. m_rootIndexData->row = 0;
    11. m_rootIndexData->item = root;
    12. }
    13.  
    14. QModelIndex EntityModel::index(int row, int column, const QModelIndex &parent) const
    15. {
    16. if (!hasIndex(row, column, parent)) {
    17. return QModelIndex();
    18. }
    19.  
    20. IndexData *parentData = indexData(parent);
    21. Entity *child = parentData->item->child(row);
    22.  
    23. if (child)
    24. return createIndex(row, column, createIndexData(parentData, child, row));
    25.  
    26. return QModelIndex();
    27. }
    28.  
    29. QModelIndex EntityModel::parent(const QModelIndex &child) const
    30. {
    31. if (!child.isValid())
    32. return QModelIndex();
    33.  
    34. IndexData *data = indexData(child);
    35. if (data->parent == m_root) {
    36. return QModelIndex();
    37. }
    38.  
    39. if (data->parentIndex == 0)
    40. return QModelIndex();
    41.  
    42. return createIndex(data->parentIndex->row, 0, data->parentIndex);
    43. }
    44.  
    45. int EntityModel::rowCount(const QModelIndex &parent) const
    46. {
    47. IndexData *data = indexData(parent);
    48. return data->item->childrenCount();
    49. }
    50.  
    51. int EntityModel::columnCount(const QModelIndex &parent) const
    52. {
    53. return 2;
    54. }
    55.  
    56. QVariant EntityModel::data(const QModelIndex &index, int role) const
    57. {
    58. if (!index.isValid())
    59. return QVariant();
    60.  
    61. if (role != Qt::DisplayRole)
    62. return QVariant();
    63.  
    64. Entity *item = indexData(index)->item;
    65.  
    66. if (index.column() == 0) {
    67. return item->name();
    68. } else if (index.column() == 1) {
    69. return "Entity";
    70. } else {
    71. qCritical() << "Invalid column";
    72. return "";
    73. }
    74. }
    75.  
    76. EntityModel::IndexData *EntityModel::indexData(const QModelIndex &index) const
    77. {
    78. if (index.isValid()) {
    79. IndexData *data = static_cast<IndexData*>(index.internalPointer());
    80. if (data)
    81. return data;
    82. }
    83.  
    84. return m_rootIndexData;
    85. }
    86.  
    87. EntityModel::IndexData *EntityModel::createIndexData(IndexData *parent, Entity *item, int row) const
    88. {
    89. if (!m_indexData.contains(quintptr(parent->item))) {
    90. QHash<quintptr, IndexData*>* hash = new QHash<quintptr, IndexData*>();
    91. m_indexData.insert(quintptr(parent->item), hash);
    92. }
    93.  
    94. if (!m_indexData[quintptr(parent->item)]->contains(quintptr(item))) {
    95. IndexData *data = new IndexData;
    96. data->parent = parent->item;
    97. data->item = item;
    98. data->parentIndex = parent;
    99. data->row = row;
    100. m_indexData[quintptr(parent->item)]->insert(quintptr(item), data);
    101. }
    102.  
    103. return m_indexData[quintptr(parent->item)]->value(quintptr(item));
    104. }
    To copy to clipboard, switch view to plain text mode 

  8. The following user says thank you to Petro Svintsitskyi for this useful post:

    d_stranz (16th May 2014)

  9. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,346
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    318
    Thanked 872 Times in 859 Posts

    Default Re: QTreeView display of graph (multiple parents of item)

    Thanks for this. Now I need to figure out how to implement a model that will handle an undirected cyclic graph which may contain disjoint subgraphs :-) I might have to save that for another lifetime.

Similar Threads

  1. QTreeWidget item with multiple parents
    By di_zou in forum Newbie
    Replies: 0
    Last Post: 16th November 2009, 16:32
  2. Can't change the text display of a QTreeview item.
    By johnny_sparx in forum Qt Programming
    Replies: 3
    Last Post: 2nd June 2006, 02:03

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.