Results 1 to 16 of 16

Thread: Populate QTreeView from database

  1. #1
    Join Date
    Dec 2007
    Location
    London
    Posts
    206
    Thanks
    40
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Populate QTreeView from database

    Hi,

    I am trying to fill a Treeview from a database source. I need to be able to manipulate treeview items and sync this with database. As far as i can understand , best (but not easiest) way is to use QAbstractProxyModel and implement maptoSource and mapfromSource functions. But i couldnt find a single example for doing this on a treeview.

    A starting point:

    Qt Code:
    1. QModelIndex TagChannelTreeModel::mapFromSource(const QModelIndex &sourceIndex) const
    2. {
    3. // root
    4. if (!sourceIndex.isValid())
    5. return QModelIndex();
    6.  
    7. //what to do here
    8. int col = sourceIndex.column();
    9.  
    10. return createIndex(sourceIndex.row() , sourceIndex.column());
    11. }
    To copy to clipboard, switch view to plain text mode 

    Here what should i do if column is other than "0"(Top level item) and i want to add this index as a child to parent(column 0 item) ? A small snippet would be appreciated :-)

    Thanks in advance...
    Last edited by yagabey; 22nd November 2014 at 15:07.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Populate QTreeView from database

    You only need a proxy model if you can't do it in the actual model.

    Cheers,
    _

  3. #3
    Join Date
    Dec 2007
    Location
    London
    Posts
    206
    Thanks
    40
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate QTreeView from database

    Hi anda,

    Tha actual model is a sqlquerymodel . It returns a table data. I am not very much familiar with model view framework yet. In the above code "TagChannelTreeModel" is derived from QAbstractProxyModel. Dont you mean that? Here, i couldnt figure out how to build the algorithm to create the tree in proxy model
    Last edited by yagabey; 22nd November 2014 at 17:32.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,229
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Populate QTreeView from database

    How does the table map to a tree structure? Is there a multi-level sort on the columns, where you can have several rows with duplicates in given columns? In other words, something like this:

    Columns
    1 2 3 4 5 ...
    A B C D v ...
    A B D E w ...
    A C D E x ...
    A C E F y ...
    A C E G z ...
    ...

    How would you express your table in tree form? One cell in each of tree nodes at level 1, 2, and 3, and all the rest in the leaf nodes at the lowest level?

    mapToSource() for the tree-shaped model requires you to traverse up the tree (retrieve parent() for each index, until you get to the root - which should be a non-valid index) and count the number of valid parents. This count gives you the column number in the source model. The row number of the topmost valid node in the tree is the same as the row in the table.

    This assumes that your columns in the tree are in the same order as in the source model; if not, you'll have to create a QMap or something like it in your tree model to translate tree column into table column.

    Alternatively, as you build your tree, you can create two QMaps of persistent model indexes - one that maps from source to proxy, the other that maps from proxy to source. Then it is a simple lookup. Depends on how big your table is - you are probably tripling the storage requirement for the indexes if you create these maps. If your tree isn't too deep, then traversing the tree at runtime will be very quick - a few calls to parent() and it is done.

    mapFromSource() goes the other way. The table row() will be the same as the row() of the corresponding top-level table node. You then need to go down the tree hierarchy until you reach the right level (i.e. all of the child nodes in the tree match the initial cells in the table row), then go over the right number of cells at the leaf node in the table. The model index you return will have its parent set to the tree node immediately above the leaf, its row will be set to the row number of the leaf node, and the column number set to the appropriate column for the leaf.

    Does that makes sense?

  5. #5
    Join Date
    Dec 2007
    Location
    London
    Posts
    206
    Thanks
    40
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate QTreeView from database

    Hi, the procedure sounds logical. A small example snipet please. My table is something like that:

    ......ChannelName|TagName |... Frequency

    1....Ch1...............Pomp1..........1000

    2....Ch1...............Pomp2..........3000

    3....Ch2...............Flowmeter.....2000

    ..


    Here Tagname s are unique. TreeView should be something like that...


    ChannelName TagName Frequency

    -Ch1--------------Pomp1..........1000
    | |
    | -----------------Pomp2..........3000
    |
    ---Ch2------------Flowmeter.....2000
    |
    ...

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,229
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Populate QTreeView from database

    -Ch1--------------Pomp1..........1000
    | |
    | -----------------Pomp2..........3000
    |
    ---Ch2------------Flowmeter.....2000
    |
    ...
    Doing that will be harder than this:

    -Ch1
    | |-----------------Pomp1..........1000
    | |-----------------Pomp2..........3000
    |
    -Ch2
    | |-----------------Flowmeter.....2000
    |
    ...

    If you do it your way, the tree structure is a bit hard to keep track of. Each top level item would either have no children or one or more children, but if it has no children, it has more than one column. So the mapping would be hard - if your index is the first child of the channel node, then it is at the same level in the tree, otherwise it is at a level below the channel node.

    If you do it the second way, the code would look something like this:

    Qt Code:
    1. // >> Warning, untested!
    2.  
    3. QModelIndex MyProxy::mapToSource( const QModelIndex & index )
    4. {
    5. QModelIndex sourceIndex;
    6. if ( index.isValid() )
    7. {
    8. int count = 0;
    9. QModelIndex lastValidParent = index;
    10. QModelIndex parentIndex = index.parent();
    11. while ( parentIndex.isValid() )
    12. {
    13. count++;
    14. lastValidParent = parentIndex;
    15. parentIndex = parentIndex.parent();
    16. }
    17.  
    18. // The column in the source table corresponds to the index's column plus the number of times we moved up the tree
    19. int column = index.column() + count;
    20.  
    21. // The row corresponds to the row of the last valid parent (the channel row in the tree) plus the index's row
    22. // (which corresponds to where the index is below the channel node)
    23. int row = lastValidParent.row() + index.row();
    24.  
    25. sourceIndex = sourceModel()->index( row, column, QModelIndex() );
    26. }
    27. return sourceIndex;
    28. }
    To copy to clipboard, switch view to plain text mode 

    I think you can probably figure out how to implement mapFromSource(), since you will need to do this to build the tree in the first place.

  7. The following user says thank you to d_stranz for this useful post:

    yagabey (25th November 2014)

  8. #7
    Join Date
    Dec 2007
    Location
    London
    Posts
    206
    Thanks
    40
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate QTreeView from database

    Hi, i havent touched the mapfromsource() yet, but when i insert the above code into maptosource() function the table messes up as you can see in the attachment. I would expect no change since maptosource() is for tree to table conversion(not table to tree) . Aren't i right? What may be the issue here then? Thanks..
    Attached Images Attached Images

  9. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Populate QTreeView from database

    Are you really sure you want to go with a proxy model?
    Do you have many different models that you need to adapt with it?

    Cheers,
    _

  10. #9
    Join Date
    Dec 2007
    Location
    London
    Posts
    206
    Thanks
    40
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate QTreeView from database

    Actually i just have 1 model. After googling for 3 hours, i saw that i have 2 choises: First is the proxymodel, and the second is standartitemmodel . I ve chosen the first. What do you suggest?

  11. #10
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Populate QTreeView from database

    If you have only one model, then doing a proxy model sounds like way to much overhead.

    A proxy model is a good approach if you have several source models that need this kind of adaption or if you can implement the actual model yourself.
    Neither of which is true in your case.

    For creating your own model you have several options:
    1) as you already said, QStandardItemModel and populate it from the database query
    2) creating your own model on your own tree structure and populate that tree from the database query
    3) creating your own model that queries the database when required to

    Cheers,
    _

  12. The following user says thank you to anda_skoa for this useful post:

    yagabey (25th November 2014)

  13. #11
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,229
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Populate QTreeView from database

    I would expect no change since maptosource() is for tree to table conversion(not table to tree)
    No, I don't see any way that the code I posted would cause any changes at all to the table. The only method it calls on the table is a read-only one (sourceModel()->index()).

    Are you sure you didn't accidentally set the model for your table view to the proxy model, and not to the SQL query model?

    @anda_skoa:

    If the original model is a table model (QSqlQueryModel derives from QAbstractTableModel), then how can you display that in a QTreeView without using a proxy model that maps the table into a tree? Converting the table into QStandardItemModel or any other type of model basically requires turning it into a tree, so why not use a tree-shaped proxy model?

    The disadvantage of using a separate model is that if you want to display the QSqlQueryModel as both a table and a tree, you lose the connection between selections in the tree and table views because the models are independent. With a proxy that uses the original QSqlQueryModel as source, the mapping of selections is easier.

  14. #12
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Populate QTreeView from database

    Quote Originally Posted by d_stranz View Post
    If the original model is a table model (QSqlQueryModel derives from QAbstractTableModel), then how can you display that in a QTreeView without using a proxy model that maps the table into a tree?
    I wouldn't use QSqlQueryModel in such a case. As you said it is a table model.
    Since it is just a convenience wrapper to present the result of an SQL query in a table, it is just doing things that are not needed here.


    Quote Originally Posted by d_stranz View Post
    Converting the table into QStandardItemModel or any other type of model basically requires turning it into a tree, so why not use a tree-shaped proxy model?
    You can, of course, use a proxy for that, but why go through the complexity of a proxy when you can present the data in the way you want to in the first place.

    Quote Originally Posted by d_stranz View Post
    The disadvantage of using a separate model is that if you want to display the QSqlQueryModel as both a table and a tree, you lose the connection between selections in the tree and table views because the models are independent. With a proxy that uses the original QSqlQueryModel as source, the mapping of selections is easier.
    You would still have to synchronize the two selection models since the two views are working with different models.

    Cheers,
    _

  15. #13
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,229
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Populate QTreeView from database

    @anda_skoa:

    Since it is just a convenience wrapper to present the result of an SQL query in a table, it is just doing things that are not needed here.
    True. I suppose it is just a preference. I'd rather let the QSqlQueryModel do all the hard work of converting the query results into a table, and use a proxy to display it the way I want. It puts a layer of indirection between the database query and the display. If the specification for how the data should be displayed changes or if I am asked to display the same data in different formats in different views, then all I need to do is change the proxy or add another proxy rather than having to remap the results at the QSqlQuery level.

    No problem. Cheers!

  16. #14
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Populate QTreeView from database

    Oh, I definitely agree that there can be value in a proxy approach.
    I am just saying that it usually is more complex than making the actual model already do the right thing.

    Cheers,
    _

  17. #15
    Join Date
    Dec 2007
    Location
    London
    Posts
    206
    Thanks
    40
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: Populate QTreeView from database

    Hi guys, thank you all for your help . I simply implemented a standardItemModel and everything is ok now. I think proxymodel is a bir complex for my level.

    Cheers :-)

  18. #16
    Join Date
    Feb 2015
    Posts
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Populate QTreeView from database

    Hello!!!I have exactly the same problem like you had.May I ask you,how exactly did you load the database into the QTreeView??I have already done the tree view without any data and I have already done the database but I don't know how to load it into my gui and how to work with this data!I guess I should use QTreeView, QSqlQuery and QAbstractItemModel like you said but I honestly have no idea how to implement this.I would really appreciate any kind of help!
    Last edited by spokV; 26th March 2015 at 03:19.

Similar Threads

  1. Qtreeview from database(sqlite)
    By cengiz3519 in forum Qt Programming
    Replies: 1
    Last Post: 5th June 2014, 00:42
  2. QTreeView & Sql Database.
    By gcain in forum Qt Programming
    Replies: 1
    Last Post: 18th October 2013, 06:56
  3. Replies: 6
    Last Post: 20th February 2012, 11:59
  4. QTreeView and database
    By langziyang in forum Qt Programming
    Replies: 1
    Last Post: 22nd November 2010, 09:19
  5. using QTreeView with a Database model
    By darksaga in forum Qt Programming
    Replies: 1
    Last Post: 18th January 2007, 00:29

Tags for this Thread

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.