Results 1 to 9 of 9

Thread: Master/detail presentation

  1. #1
    Join Date
    Oct 2009
    Posts
    65
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Master/detail presentation

    Merry XMas to everybody,
    probably I'm alone on this forum at 26th December, but, I've a problem, and I hope to solve it as soon as possibile.
    This is my problem: I have a two table in a MYSQL database, that show a master/detail relation. I'd like to show these data on my form with a single widget (perhaps treeview), but, I'm a newbie of QT and I don't know from where I must start.
    I'd like to obtain a widget like a tree view, in which every master elemet is a treeview element and, opening this, it show a table (with different headers too) where are shown the details element. Something Like the MS Hierarchical FlexGrid of Microsoft Visual Studio 6.

    Have you got any ideas?

    Thanks for your help

    Michele

  2. #2
    Join Date
    Oct 2008
    Posts
    71
    Thanks
    6
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Master/detail presentation

    As far as I know there is no easy way to do this with a single liner - you will probably have to develop your own model to present the data from your database in a hierarchical manner.

    There are two classes that could have helped if a table-like solution was OK: QSqlTableModel and QSqlQueryModel. These two will let you to present the data from your DB in a QTableView widget with little effort. You also mentioned that the headers in the tables are different. If they are completely different, then you could actually present the data with QSqlQueryModel in a single table.

    Otherwise you will probably have to take a look at model development and work out your own model. You could inherit from QSqlQueryModel and extend the model to make it hierarchical. If you are completely new to model development, then it will probably take some time...

  3. #3
    Join Date
    Oct 2009
    Posts
    65
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Master/detail presentation

    As I said, I'm a newbie of c++ & QT programming, so, it I don't know if this is the correct way but, I could use an hierarchical model (perhaps a QSqlRelationalModel or a QTreeModel) and build a different view or delegates. I thought this: for my uses it's enought that the child items of a single parent could be added to a QTableWidget; in this way, I take the items from the hierarchical model but I add to an inner table (all the child items of each parent are shown bye an inner table below the parent intem, with the same indentation of the child). However, I don't know how obtain this, i should create an inner table for each parent item of QTreeWidget for example; fill this control is possible in some way. I should build a custom delegate? or I should build only a custom Widget?
    Have you got any ideas or example that I can follow?

    Thanks a lot for your time.

    Michele
    PS. I've see also the QSqlRelationalModel example of qt (relative to artist/album/tracks managing, but in that case it uses 3 different controls on the form)

  4. #4
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Master/detail presentation

    This is my little attempt to create a master/detail control with Qt by embedding a QTreeView inside a QTreeView. Inspired by the frozen column example. Enjoy.
    mainwindow.h
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QtGui/QMainWindow>
    5.  
    6. class MainWindow : public QMainWindow
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11. MainWindow(QWidget *parent = 0);
    12. ~MainWindow();
    13. };
    14.  
    15.  
    16. #include <QAbstractItemDelegate>
    17. #include <QFontMetrics>
    18. #include <QModelIndex>
    19. #include <QSize>
    20. #include <QTreeView>
    21. #include <QStyledItemDelegate>
    22. #include <QResizeEvent>
    23.  
    24. class QObject;
    25. class QPainter;
    26.  
    27.  
    28. class HGrid : public QTreeView
    29. {
    30. Q_OBJECT
    31. public:
    32. HGrid(QWidget * parent = 0);
    33. public slots:
    34. void expanding(const QModelIndex & index);
    35. void collapsing(const QModelIndex & index);
    36. private:
    37. QTreeView * tv;
    38. void collapseOthers(QAbstractItemModel * m, QModelIndex sp);
    39. };
    40.  
    41.  
    42. class TableDelegate : public QStyledItemDelegate
    43. {
    44. Q_OBJECT
    45.  
    46. public:
    47. TableDelegate(QObject *parent, QTreeView* child);
    48.  
    49. void paint(QPainter *painter, const QStyleOptionViewItem &option,
    50. const QModelIndex &index) const;
    51.  
    52. QSize sizeHint(const QStyleOptionViewItem &option,
    53. const QModelIndex &index ) const;
    54.  
    55. private:
    56. QTreeView * tv;
    57. };
    58.  
    59. #endif // MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 
    and mainwindow.cpp
    Qt Code:
    1. #include "mainwindow.h"
    2. #include <QTreeView>
    3. #include <QStandardItemModel>
    4. #include <QString>
    5. #include <QPainter>
    6. #include <QDebug>
    7. #include <QScrollBar>
    8. #include <QtGui/QApplication>
    9.  
    10. const int margin = 12;
    11. const int sMargin = 3;
    12. const int ChildModelRole = Qt::UserRole + 1;
    13. Q_DECLARE_METATYPE( QAbstractItemModel * );
    14.  
    15. HGrid::HGrid(QWidget * parent) :
    16. QTreeView(parent), tv(0)
    17. {
    18. /* Register QAbstractItemModel* so we can store it in a QVariant. */
    19. qRegisterMetaType<QAbstractItemModel*>("QAbstractItemModel*");
    20. tv = new QTreeView(this->viewport());
    21. tv->hide();
    22. TableDelegate * td = new TableDelegate(this, tv);
    23. connect(this, SIGNAL(expanded(QModelIndex)), SLOT(expanding(const QModelIndex)));
    24. connect(this, SIGNAL(collapsed(QModelIndex)), SLOT(collapsing(const QModelIndex)));
    25. setItemDelegate(td);
    26. setIndentation(12);
    27. setHorizontalScrollMode(ScrollPerPixel);
    28. setVerticalScrollMode(ScrollPerPixel);
    29. }
    30.  
    31. void HGrid::collapseOthers(QAbstractItemModel * m, QModelIndex sp)
    32. {
    33. for (int i = 0; i < m->rowCount(); i++)
    34. if (isExpanded(m->index(i, 0)))
    35. if (m->index(i, 0) != sp)
    36. setExpanded(m->index(i, 0), false);
    37. }
    38.  
    39. void HGrid::expanding(const QModelIndex &index)
    40. {
    41. /* Hide all the other expanded sections. This way we only need one child tree-view. */
    42. collapseOthers(model(), index);
    43.  
    44. if (index.model()->data(index.child(0,0), ChildModelRole).isValid())
    45. {
    46. /* Retrieve our child model. */
    47. tv->setModel(qVariantValue<QAbstractItemModel*>(index.model()->data(index.child(0,0), ChildModelRole)));
    48. setFirstColumnSpanned(0, index, true);
    49. viewport()->stackUnder(tv);
    50. tv->show();
    51. }
    52. }
    53.  
    54. void HGrid::collapsing(const QModelIndex &index)
    55. {
    56. tv->hide();
    57. }
    58.  
    59. TableDelegate::TableDelegate(QObject *parent, QTreeView *child)
    60. : QStyledItemDelegate(parent), tv(child)
    61. { }
    62.  
    63. void TableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    64. const QModelIndex &index) const
    65. {
    66. if (index.model()->data(index, ChildModelRole).isValid())
    67. {
    68. QRect rc = option.rect;
    69. painter->save();
    70. painter->setBrush(Qt::gray);
    71. painter->setPen(Qt::NoPen);
    72. painter->drawRoundedRect(rc.left() + sMargin, rc.top() + sMargin,
    73. rc.width() - (sMargin * 2), rc.height() - (sMargin * 2),
    74. 3.5, 3.5);
    75. painter->restore();
    76. tv->resize(rc.width() - (margin * 2), rc.height() - (margin * 2));
    77. tv->move(rc.left() + margin, rc.top() + margin);
    78. }
    79. else
    80. {
    81. QStyledItemDelegate::paint(painter, option, index);
    82. }
    83. }
    84.  
    85. QSize TableDelegate::sizeHint(const QStyleOptionViewItem & option,
    86. const QModelIndex & index) const
    87. {
    88. if (index.model()->data(index, ChildModelRole).isValid())
    89. return QSize(option.rect.width(), 200);
    90. else
    91. return QStyledItemDelegate::sizeHint(option, index);
    92. }
    93.  
    94. MainWindow::MainWindow(QWidget *parent)
    95. : QMainWindow(parent)
    96. {
    97. HGrid * hgrid = new HGrid(this);
    98.  
    99.  
    100. /* Our master can have any number of columns. */
    101. QStandardItem *parentItem = m->invisibleRootItem();
    102.  
    103. for (int i = 0; i < 10; ++i) {
    104. QStandardItem *item = new QStandardItem(QString("Parent %0").arg(i));
    105. parentItem->appendRow(item);
    106.  
    107. QStandardItem * ph = new QStandardItem("Placeholder");
    108. item->appendRow(ph);
    109. ph->setFlags(Qt::NoItemFlags);
    110.  
    111. /* Now make a child model to fill our child tree view. */
    112. for (int j = 0; j < 10; j++)
    113. {
    114. QList<QStandardItem*> items;
    115. for (int column = 0; column < 6; ++column)
    116. {
    117. items.push_back(new QStandardItem(QString("Item %0").arg(column)));
    118. }
    119. m2->invisibleRootItem()->appendRow(items);
    120. }
    121.  
    122. /* And store a pointer to our child model in the master model. */
    123. m->setData(ph->index(), QVariant(QMetaType::type("QAbstractItemModel*"), &m2), ChildModelRole);
    124. }
    125.  
    126. hgrid->setModel(m);
    127. setCentralWidget(hgrid);
    128. }
    129.  
    130. MainWindow::~MainWindow()
    131. { }
    132.  
    133.  
    134. int main(int argc, char *argv[])
    135. {
    136. QApplication a(argc, argv);
    137. MainWindow w;
    138. w.show();
    139. return a.exec();
    140. }
    To copy to clipboard, switch view to plain text mode 
    Attached Images Attached Images

  5. #5
    Join Date
    Sep 2008
    Location
    Portugal
    Posts
    171
    Thanks
    57
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Master/detail presentation

    Hi,

    I'm looking at the "Implementing Master-Detail Forms" in the "C++ GUI Programming with C++".

    Does anyone know other examples like this available in the Internet?

    I tried some googling but i ended up in the example above.

    Thanks

  6. #6
    Join Date
    Oct 2009
    Posts
    65
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Master/detail presentation

    Happy new Year to everybody!
    Thanks a lot Numbat for your solution! It's exactly what I want obtain. But I've yet a question: I see in this example it is used some for loop and strings to fill the columns... how I can link the view to a gerarchical model? (I think to QSQLRelationalModel)
    By this, I'll have an indipendent widget that I can simply put on my form ad use it simply passing on it the model of my data.

    Thanks for your help!

    I'll show you, if you want how I'll use this.

    Michele

  7. #7
    Join Date
    Oct 2009
    Posts
    65
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Master/detail presentation

    Goodmorning to all.
    I'm working with the example of numbat (thanks a lot for this!) it's exaclty what I need!! But... working on it I've see this example use string constants to populate two level grid and all the sistem of "frozen column" is based over a single model.

    I've this problem now: I'd like to use this view with an SQL model. The most simple way is read all row and column of two QSqlTableModel (one for the first level and one for the second level) and set the strings into the treeview (using the tecnic showed by numbat), but i'd like to make something better.

    I'd like to create an SQL model then inglobe the two different Role and in which every item has different parent if need. I'd like to create ad QSqlTreeModel or something like this.

    I try to do this but my experience on QT is non enought and I loose myself.

    Does anybody any ideas of how can I create a model the can populate the grid? I thought to pass two tables and two fields to something like "select()" method of QSqlTableModel and use it as base... but I don't know which this cause.

    Have you got any ideas and some time to try to create it togheter?

    Thanks a lot for your time!

    Michele

  8. #8
    Join Date
    Oct 2009
    Posts
    65
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Master/detail presentation

    I've resolve the question adding a method that implements the code of the numbat's example:
    Qt Code:
    1. void HGrid::setMasterSlaveModel(QSqlTableModel *master, QSqlTableModel *slave, QString fieldmaster, QString fieldslave)
    2. {
    3. // Our master can have any number of columns.
    4. QStandardItem *parentItem = m->invisibleRootItem();
    5.  
    6. //Scorro il model principale per riga
    7. for (int i=0; i< master->rowCount();i++){
    8.  
    9. //Leggo il record corrente del model
    10. QSqlRecord rec = master->record(i);
    11. //Creo una lista di colonne
    12. QList<QStandardItem*> colsFatt;
    13.  
    14. //Scorro tutte le colonne
    15. for (int j=0; j<master->columnCount();++j){
    16.  
    17. //Aggiungo i dati delle colonne alla lista
    18. colsFatt.push_back(new QStandardItem(rec.value(j).toString()));
    19. }
    20.  
    21. //Aggiungo la lista dei dati delle colonne al model
    22. parentItem->appendRow(colsFatt);
    23.  
    24. //Creo un elemento fittizio per aggiungere i dati di secondo livello
    25. QStandardItem * ph = new QStandardItem( "Placeholder");
    26. colsFatt.at(0)->appendRow(ph);
    27. ph->setFlags(Qt::NoItemFlags);
    28.  
    29. slave->setFilter(QString("%1=%2").arg(fieldslave).arg(rec.value(fieldmaster).toInt()));
    30. for (int k = 0; k < slave->rowCount(); k++)
    31. {
    32. QList<QStandardItem*> colsDett;
    33. QSqlRecord recDett = slave->record(k);
    34. for (int x = 0; x < slave->columnCount(); ++x)
    35. {
    36. colsDett.push_back(new QStandardItem(recDett.value(x).toString()));
    37. }
    38. m2->invisibleRootItem()->appendRow(colsDett);
    39. }
    40. m->setData(ph->index(), QVariant(QMetaType::type("QAbstractItemModel*"), &m2), ChildModelRole);
    41. }
    42.  
    43. this->setModel(m);
    44. }
    To copy to clipboard, switch view to plain text mode 

    But I don't like it so much. Is there any smarter solution? Have you got any ideas?

    Thanks a lot for your time.

    Michele

  9. #9
    Join Date
    Oct 2009
    Posts
    65
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Master/detail presentation

    And, with this structure, how can I show images on the first column (of both the QTreeView). One image for the items of firts level (first QTreeview) and an other for the items of internal QTreeview (second level).

    Have you got any idea?

    Thank a lot for your time

    Michele

Similar Threads

  1. Graphics View Presentation
    By Brandybuck in forum The GraphicsView Framework
    Replies: 0
    Last Post: 29th May 2008, 01:44
  2. Welcome to the ICSNetwork presentation of Introduction to Qt
    By glebovitz in forum Introduction to Qt
    Replies: 0
    Last Post: 22nd April 2008, 17:01
  3. Widget for chat presentation
    By krivenok in forum Qt Programming
    Replies: 8
    Last Post: 24th January 2006, 13:37

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.