Page 1 of 2 12 LastLast
Results 1 to 20 of 34

Thread: Map table to tree through model/view possible?

  1. #1
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Map table to tree through model/view possible?

    I am trying to convert a table into a tree, hereby making use of the aforementioned model and view. I can create/order the table anyhow I want. Currently, every row in the table represents a path of the tree, which means that for some row an element in the "column-1" is the parent of the element of "column".

    I have tried reimplementing the index() and parent() of the QSqlTableModel. I have tried using the proxy model. I have studied numerous examples, read Qt's “view/model programming”, and various other docs. I didn't even get close to a tree. I am constantly getting errors/crashes/etc..

    I know I could use the “treeitem” and “treemodel” from Qt's source snippets, but it seems a whole way round something that seems so simple.

    So, how do I make an index point to some other index?

    Kind regards,
    Davor

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

    Default Re: Map table to tree through model/view possible?

    You need to have a proxy model and implement mapToSource() and mapFromSource() there (apart from the rest of the required methods, of course).
    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.


  3. #3
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by wysota View Post
    You need to have a proxy model and implement mapToSource() and mapFromSource() there (apart from the rest of the required methods, of course).
    I already tried that, but I do not know how to implement mapFromSource() and mapToSource() to make the index point to the index with the same row, but with column-1,

  4. #4
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Have you tried index method?

  5. #5
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by fatjuicymole View Post
    Have you tried index method?
    Yes! I think I was very explicit about that in my first post...

    How can I return a createIndex() pointing to some other index?

  6. #6
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Well, index takes row, column and parent, so it should be easy. Thats what you wanted, right?

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

    Default Re: Map table to tree through model/view possible?

    I don't think this would be enough. You would only gain as much that your data would be shifted one column to the left.

    But just for the sake of an example:
    Qt Code:
    1. QModelIndex Proxy::mapToSource(const QModelIndex &proxyIndex){
    2. if(proxyIndex.column()==0) return QModelIndex();
    3. return sourceModel()->index(proxyIndex.row(), proxyIndex.column()-1, <something has to go here>);
    4. }
    5.  
    6. QModelIndex Proxy::mapFromSource(const QModelIndex &sourceIndex){
    7. return createIndex(sourceIndex.row(), sourceIndex.column()+1, <something has to go here>);
    8. }
    To copy to clipboard, switch view to plain text mode 
    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.


  8. #8
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by fatjuicymole View Post
    Well, index takes row, column and parent, so it should be easy. Thats what you wanted, right?
    That is exactly what I thought... until I started coding.

    I don't understand the index() method: the arguments over-determine the subject. Whats the meaning of row, column AND parent. Either row/column OR parent is more than enough to devise the index. I don't understand the logic.

    The following example does nothing more than QSortFilterProxyModel does with the table. I haven't tried reimplementing AbstractProxyModel yet with this code.

    Qt Code:
    1. #ifndef TABLETOTREEPROXYMODEL_H
    2. #define TABLETOTREEPROXYMODEL_H
    3.  
    4. //#include <QAbstractProxyModel>
    5. #include <QSortFilterProxyModel>
    6. #include <QModelIndex>
    7.  
    8. class TableToTreeProxyModel : public QSortFilterProxyModel
    9. {
    10. public:
    11. TableToTreeProxyModel(QObject * parent = 0);
    12.  
    13. QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex())
    14. {
    15. if (!parent.isValid()) return createIndex(row, 0);
    16. else return index(parent.row(),parent.column()+1);
    17. return createIndex(row,column);
    18. }
    19. QModelIndex parent(const QModelIndex &child)
    20. {
    21. if (!child.isValid()) return QModelIndex();
    22. if (child.column()==0) return QModelIndex();
    23. return index(child.row(),child.column()-1);
    24. }
    25. };
    26.  
    27. #endif // TABLETOTREEPROXYMODEL_H
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by wysota View Post
    I don't think this would be enough. You would only gain as much that your data would be shifted one column to the left.

    But just for the sake of an example:
    Qt Code:
    1. QModelIndex Proxy::mapToSource(const QModelIndex &proxyIndex){
    2. if(proxyIndex.column()==0) return QModelIndex();
    3. return sourceModel()->index(proxyIndex.row(), proxyIndex.column()-1, <something has to go here>);
    4. }
    5.  
    6. QModelIndex Proxy::mapFromSource(const QModelIndex &sourceIndex){
    7. return createIndex(sourceIndex.row(), sourceIndex.column()+1, <something has to go here>);
    8. }
    To copy to clipboard, switch view to plain text mode 
    This also has completely no effect:

    Qt Code:
    1. #ifndef TABLETOTREEPROXYMODEL_H
    2. #define TABLETOTREEPROXYMODEL_H
    3.  
    4. //#include <QAbstractProxyModel>
    5. #include <QSortFilterProxyModel>
    6. #include <QModelIndex>
    7.  
    8. class TableToTreeProxyModel : public QSortFilterProxyModel
    9. {
    10. public:
    11. TableToTreeProxyModel(QObject * parent = 0) : QSortFilterProxyModel(parent){};
    12.  
    13. QModelIndex mapToSource(const QModelIndex &proxyIndex)
    14. {
    15. if(proxyIndex.column()==0) return QModelIndex();
    16. return sourceModel()->index(proxyIndex.row(), proxyIndex.column()-1, parent(proxyIndex));
    17. }
    18.  
    19. QModelIndex mapFromSource(const QModelIndex &sourceIndex)
    20. {
    21. return createIndex(sourceIndex.row(), sourceIndex.column()+1);
    22. }
    23.  
    24. QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex())
    25. {
    26. if (!parent.isValid()) return createIndex(row, column);
    27. else return index(parent.row(),parent.column()+1);
    28. return createIndex(row,column);
    29. }
    30. QModelIndex parent(const QModelIndex &child)
    31. {
    32. if (!child.isValid()) return QModelIndex();
    33. if (child.column()==0) return QModelIndex();
    34. return index(child.row(),child.column()-1);
    35. }
    36. };
    37.  
    38. #endif // TABLETOTREEPROXYMODEL_H
    To copy to clipboard, switch view to plain text mode 
    Last edited by Davor; 2nd December 2009 at 11:21.

  10. #10
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    This seems logical, but has completely no effect:

    Qt Code:
    1. #ifndef TABLETOTREEPROXYMODEL_H
    2. #define TABLETOTREEPROXYMODEL_H
    3.  
    4. //#include <QAbstractProxyModel>
    5. #include <QSortFilterProxyModel>
    6. #include <QModelIndex>
    7.  
    8. class TableToTreeProxyModel : public QSortFilterProxyModel
    9. {
    10. public:
    11. TableToTreeProxyModel(QObject * parent = 0) : QSortFilterProxyModel(parent){};
    12.  
    13. QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex())
    14. {
    15. if (!parent.isValid()) return sourceModel()->index(row, column);
    16. if (parent.isValid()) return sourceModel()->index(parent.row(),parent.column()+1);
    17. return sourceModel()->index(row,column);
    18. }
    19. QModelIndex parent(const QModelIndex &child)
    20. {
    21. if (!child.isValid()) return QModelIndex();
    22. if (child.column()==0) return QModelIndex();
    23. return sourceModel()->index(child.row(),child.column()-1);
    24. }
    25. };
    26.  
    27. #endif // TABLETOTREEPROXYMODEL_H
    To copy to clipboard, switch view to plain text mode 

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

    Default Re: Map table to tree through model/view possible?

    If you ignore the parent, you will never receive a tree model. You also have to return indexes from the proxy model and not from the source model. The only method that can and has to return indexes from the proxy model is mapToSource().

    I still fail to grasp what is the effect you want to obtain. Maybe a very simple practical example would clear things up?
    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.


  12. #12
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by wysota View Post
    If you ignore the parent, you will never receive a tree model. You also have to return indexes from the proxy model and not from the source model. The only method that can and has to return indexes from the proxy model is mapToSource().

    I still fail to grasp what is the effect you want to obtain. Maybe a very simple practical example would clear things up?
    Take a table with two columns and two rows and following data:
    1,2
    3,4

    I want to be able to click on “1” so it expands to “2”,
    I want to be able to click on “3” so it expands to “4”,

    In other words as already stated: each record represents the path of a tree.

  13. #13
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by Davor View Post
    That is exactly what I thought... until I started coding.

    I don't understand the index() method: the arguments over-determine the subject. Whats the meaning of row, column AND parent. Either row/column OR parent is more than enough to devise the index. I don't understand the logic.
    Imagine a treeview like so:
    #root
    #-first tree
    #---first tree subitem
    #-second tree
    #---second tree subitem

    So 'first tree' and 'second tree' will require a parent of 'root', whilst the subitems will request the first/second tree as parents as appropriate. Once you have that, THEN you can use the row and column. Without the parent, the row and column are meaningless.

  14. #14
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by fatjuicymole View Post
    Imagine a treeview like so:
    #root
    #-first tree
    #---first tree subitem
    #-second tree
    #---second tree subitem

    So 'first tree' and 'second tree' will require a parent of 'root', whilst the subitems will request the first/second tree as parents as appropriate. Once you have that, THEN you can use the row and column. Without the parent, the row and column are meaningless.
    Ok, so what should I return then from index() if parent is invalid? QModelIndex()?

  15. #15
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Here is something interesting: from QAbstractItemModel Class Reference for “parent()”:

    […] A common convention used in models that expose tree data structures is that only items in the first column have children. For that case, when reimplementing this function in a subclass the column of the returned QModelIndex would be 0.[...]

    The meaning of “conventions” is left open: which implications has it on the model? Same with “would be”: is it an option or a necessity to make it 0?


    In the end, I really feel like wasting time. In the meantime I could have written 50 classic trees, so to speak. The Qt Model/View documentation doesn't say anything about Model-View interaction. It just says what you should implement for certain thing to occur, and let the magic work, and if magic fails, then one's only option is to delve into the sourcecode and try to figure out the internal workings.

    Up till now, I tried many things. They outcomes/debuggings all lack logic to me. And in the end, I don't even see why one would need pointers to make trees. It seems an unnecessary complication. Why? Because the underlying Model/View structure is represented in tables in the first place, and because trees are representable as graphs (with constraints), and the two structures (one could probably argue) are completely isomorphic, given the constraints. (There are books written about this, mainly for the practical purpose of translating the (old) hierarchical databases into the relational ones.)

    I'll just use the TreeItem and TreeModel for my implementation, of simply the QTreeWidget..

    Thanks for your help anyway.

  16. #16
    Join Date
    Oct 2009
    Posts
    151
    Thanks
    6
    Thanked 13 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Map table to tree through model/view possible?

    As I understand it, you have

    Table(row, column) is the parent of Table(row, column+1)

    It would seem to me that all you need to do is iterate through your table, adding items to the tree, in pseudo code this would be:

    For row
    insert parent

    For column
    insert child
    next column

    next row

    the number of rows and colums can be obtained from your tableModel:

    TableModel->row count();
    TableModel->columncount();

    the methods for inserting nodes are included in the QTreeWidgetItem class.

  17. #17
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by Davor View Post
    Ok, so what should I return then from index() if parent is invalid? QModelIndex()?
    Yes, the same as you would if row or column was invalid.

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

    Default Re: Map table to tree through model/view possible?

    Your mapping is very complex (contrary to how it might look). I can't find a mathematical function to map between the two models. I know how the proxy can be implemented to work but it's not trivial. I'm unable to find a trivial solution to the problem and I've been trying for half an hour now. I'm close to coming to a conclusion that there is no deterministic function to map between the two models in Qt's model-view architecture - you always lack one piece of information - the row, column and parent are not enough to do the mapping.
    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.


  19. #19
    Join Date
    Dec 2009
    Posts
    24
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    Quote Originally Posted by JD2000 View Post
    As I understand it, you have

    Table(row, column) is the parent of Table(row, column+1)

    It would seem to me that all you need to do is iterate through your table, adding items to the tree, in pseudo code this would be:

    For row
    insert parent

    For column
    insert child
    next column

    next row

    the number of rows and colums can be obtained from your tableModel:

    TableModel->row count();
    TableModel->columncount();

    the methods for inserting nodes are included in the QTreeWidgetItem class.
    Indeed, it’s funny considering the fact that that the model/view was made for easy programming. Or maybe it’s just my bad luck having this problem...

    PS: wysota, you have no idea how much I would love to share just a fraction of your insight in this model/view thing! Thanks for trying to solve it.

  20. #20
    Join Date
    Nov 2009
    Posts
    129
    Thanks
    4
    Thanked 29 Times in 29 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Map table to tree through model/view possible?

    The row and column of a QModelIndex are relative to the item’s parent. To create the tree structure you describe, the row and column mapping from source to target is easy: the column of every item in the tree is 0; the row of every item from column 0 of the source is the same as its row in the source, and the row of every item from any column other than 0 is 0.

    So nearly all the row/column information from the table is thrown away when you map to the row/column values for the tree. Obviously, you must have some way to recover this information to make the QModelIndexes into the tree meaningful.

    The QAbstractItemModel::createIndex functions do not take the parent as an argument; though there is a QModelIndex::parent() function, this just delegates the operation to QAbstractItemModel::parent. Tree structure information is not stored in a QModelIndex, but must be provided by the model.

    What you do have in a QModelIndex is an “opaque” value — either a void* or a quint32 (not both) — in which a model can store information it needs to identify the item. You would need to use this field in some way that will allow you to implement QAbstractItemModel::index, QAbstractItemModel::parent, QSortFilterProxyModel::mapFromSource and QSortFilterProxyModel::mapToSource consistently.

    If it happens that the ranges of source row and column numbers are limited such that you can squeeze both values into a total of 32 bits, the job is easy — just save the source row and column in the opaque field of each tree QModelIndex, and you’ll have all the information you need to implement the required functions.

    If you cannot pack the source row and column into a 32-bit field, it gets messy; you might use a hash table containing row/column pairs, locating or adding each distinct pair as needed and passing the address of the pair as the third argument to createIndex.

Similar Threads

  1. Postgresql QSqlRelationalTableModel empty table
    By RolandHughes in forum Qt Programming
    Replies: 0
    Last Post: 12th November 2008, 17:18
  2. Replies: 3
    Last Post: 5th October 2008, 23:41
  3. Questions regarding setting up a Qt SQL Model/View
    By Methedrine in forum Qt Programming
    Replies: 3
    Last Post: 26th November 2007, 09:26
  4. Replies: 4
    Last Post: 11th September 2006, 14:13
  5. creating table plugin
    By mgurbuz in forum Qt Programming
    Replies: 3
    Last Post: 28th April 2006, 13:50

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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.