Results 1 to 16 of 16

Thread: Questions about models

  1. #1
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Question Questions about models

    I have a few questions about the models.

    Say i have the following classes:
    Qt Code:
    1. class SubItem {
    2. // some properties...
    3. };
    4.  
    5. class Item {
    6. // some properties...
    7. QList<SubItem> subitems;
    8. };
    To copy to clipboard, switch view to plain text mode 

    Now, i have a UI which displays those items. It is an MDI, where each window has a form layout which displays the properties of the Item.

    Most of the properties can just be displayed on a QLabel, but for the list of subitems i need a list-based widget (QListWidget/QListView or QTableWidget/View).

    Currently, i am just using the Q*Widget classes. But i would like to use proper model/view programming and use a Q*View.
    The problem is that i am not sure how to use a list model in this case. I started to think about the class definitions and realised i have no idea how it will work:
    Qt Code:
    1. class SubItem...
    2.  
    3. class Item {
    4. SubItemListModel getSubItemListModel();
    5. }
    6.  
    7. class SubItemListModel {
    8. Item* item; // A reference to the object which contains the list.
    9.  
    10. QList<SubItem> getItems() { item->getSubItems(); }
    11. }
    To copy to clipboard, switch view to plain text mode 

    Should the SubItemListModel work with the data in the Item's list, or should the Item have it's list data in a SubItemListModel?


    Also another minor question - i have my UI classes defined in .cpp files in one folder, and my "model" (or data) classes (Item, SubItem, etc) defined in another folder. This is separation of data and ui. But if i were to start using Qt's model classes (derived from QAbstractItemModel), where would they be defined? With my data classes, or the UI classes? Because as i see it, Q*Models are more about providing data to the UI, rather than actually storing data themselves.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  2. #2
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Any response?

    One of the things i don't understand about Qt's model classes is that they are models of lists of items. What do i do when i want to model a single item? Obviously, such a model wouldn't be used with any list views (tree, table), but it seems that Qt's model/view is build only around this concept of lists.

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

    Default Re: Questions about models

    Should the SubItemListModel work with the data in the Item's list, or should the Item have it's list data in a SubItemListModel?
    The better way is to have a Model (Say MyModel)

    Qt Code:
    1. class MyModel : public QAbstractItemModel
    2. {
    3. public:
    4. class SubItem {
    5. // some properties...
    6. };
    7.  
    8. class Item {
    9. // some properties...
    10. QList<SubItem> subitems;
    11. };
    12.  
    13. SubItem mainItem;
    14. };
    To copy to clipboard, switch view to plain text mode 

    now MyModel has all the knowledge of Item and SubItem class, it can act as model to any type view, just implement the virtual calls properly.

    Also another minor question - i have my UI classes defined in .cpp files in one folder, and my "model" (or data) classes (Item, SubItem, etc) defined in another folder. This is separation of data and ui. But if i were to start using Qt's model classes (derived from QAbstractItemModel), where would they be defined? With my data classes, or the UI classes? Because as i see it, Q*Models are more about providing data to the UI, rather than actually storing data themselves.
    I will say the model classes will go with the data.

    One of the things i don't understand about Qt's model classes is that they are models of lists of items. What do i do when i want to model a single item? Obviously, such a model wouldn't be used with any list views (tree, table), but it seems that Qt's model/view is build only around this concept of lists.
    If you closely observe the interface calls, they are not restricting you to have list as a model, you can have any variety of data structure as your data container, or even get the data from internet or dynamically create data based on state and return to the view.

  4. #4
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Ok, take the following example:

    An application needs to store and display information about people and their job history. Each person has details such as name, address, D.O.B, etc, as well as a list of previous employment. Items in this list contains details such the job name/title, date started, date finished, etc.

    Here we have a case where information is nested. There will be a list of people, and each person item will have a list of jobs.

    Now, this application will display information about a person in a property page (e.g. MDI window). This window will have name, address, etc as QLabels in a QFormLayout, and the employment history will be in a table view below the QFormLayout.

    C++ being an object-oriented language, a Person and Job class is created:
    Qt Code:
    1. class Job {
    2. QString name;
    3. QDate startDate;
    4. //...
    5. };
    6.  
    7. class Person {
    8. QString name;
    9. QString address;
    10. QList<Job> employmentHistory;
    11. //...
    12. };
    To copy to clipboard, switch view to plain text mode 
    The application maintains a list of Person objects. The person and job data is not stored in a database, let's just say that it is obtained some other way.


    So, how would i do this using Qt's model/view classes? Do i need to scrap the Job and Person classes in favour of QAbstractItemModel subclasses, which return the properties (name, address, etc) as columns? And how do i handle the nesting?

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

    Default Re: Questions about models

    So good you already have container for data list of persons, and list of jobs for each person, you just need to give this data to the view using QAbstractItemModel. Here I will give a heads up

    Qt Code:
    1. class Job {
    2. QString name;
    3. QDate startDate;
    4. };
    5.  
    6. class Person {
    7. QString name;
    8. QString address;
    9. QList<Job> employmentHistory;
    10. };
    11.  
    12. class MyModel : public QAbstractItemModel
    13. {
    14. public:
    15. int rowCount(QModelIndex index)
    16. {
    17. if(!index.isValid())
    18. return p.count();
    19. return 0;
    20. }
    21.  
    22. int columnCount(QModelIndex index)
    23. {
    24. return 2; // say 2 columns, name & address (or name & start date)
    25. }
    26.  
    27. QVariant data(QModelIndex index, int role)
    28. {
    29. if(role == Qt::DataRole)
    30. {
    31. if(index.column() == 0)
    32. return p.at(index.row()).name;
    33. if(index.column() == 1)
    34. return p.at(index.row()).address;
    35. }
    36. return QVariant();
    37. }
    38.  
    39. // implement other required interface calls also.
    40. private:
    41. QList<Person> p; // have your list of persons in here, or a pointer to point to the actual data
    42. };
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Right, that much i got. Basically, the model returns the data's members as columns.
    But that still doesn't help me, you have not mentioned how to model the Job list within each Person object.

  7. #7
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Anyone?

    Surely others must have this problem, or at least understand the problem i have.

  8. #8
    Join Date
    Jan 2009
    Location
    The Netherlands and Spain
    Posts
    150
    Thanks
    6
    Thanked 18 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Questions about models

    You could create a second Model, like Santosh showed you, serving Job info (the Jobs Model).
    Now there are two ways you can go:
    1. Make some kind of selection possible in the Jobs Model to select only jobs for a selected person, or
    2. Give every person an instance of the Jobs model class.

    If you do 1), you only have to connect one Jobs Model to the View. It will be updated with the correct values when scrolling through Persons, because Persons updates the Jobs selection.
    If you go for 2), you have to connect (setModel) the right Jobs Model to the View when a new Person is selected.

    I don't know what's best. And maybe there are better ways...

  9. #9
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Quote Originally Posted by boudie View Post
    You could create a second Model, like Santosh showed you, serving Job info (the Jobs Model).
    Santosh never mentioned a second Model. He only ever showed me how to create a single model (which i already know how to do).

    As for your ideas, it seems like Qt's models just aren't built for this kind of thing. For now i guess i will stick to using QTableWidgets for this.

  10. #10
    Join Date
    Jan 2009
    Location
    The Netherlands and Spain
    Posts
    150
    Thanks
    6
    Thanked 18 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Questions about models

    What I meant was: you create a second model in the same way you created the first one.
    I think Qt can handle this very well; I described two options to implement it. It's up to you to decide which option you think is best.
    Once you've tried, feel free to ask for detailed help.

  11. #11
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    As for your ideas, it seems like Qt's models just aren't built for this kind of thing. For now i guess i will stick to using QTableWidgets for this.
    Models are build for this kind of things, but a model can be only for 1 kind of data : it cannot be a model both for persons, and also for jobs.

    Compare it with a simple relational database : you have a table with persons, and a table with jobs, and they are linked together using some sort of index field. In this case, each record in the 'jobs' table will have a field to say whose job this is or was. If you make a GUI around this, you would make an instance of a 'PersonsModel' class, and an instance of a 'JobsModel' class. Then when a different person is selected in the PersonsModel, you could set a filter in the JobsModel to show only the job history of this person.

    One of the things i don't understand about Qt's model classes is that they are models of lists of items. What do i do when i want to model a single item?
    It is also my understanding that models are only for lists of items (persons, jobs, ...). In your example you want to keep the information about more than 1 person, don't you ? If you want to keep information about just 1 item (although I can't really think of a practical example of such a case), then you can can create a model which has just 1 entry in it - like a database table with just 1 record in it.

    I'm really not very familiar with model/view programming, so I don't think I can be of any futher help. Maybe you can check out the Master-Detail example.

    Regards,
    Marc

  12. #12
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Quote Originally Posted by marcvanriet View Post
    Models are build for this kind of things, but a model can be only for 1 kind of data : it cannot be a model both for persons, and also for jobs.

    Compare it with a simple relational database : you have a table with persons, and a table with jobs, and they are linked together using some sort of index field. In this case, each record in the 'jobs' table will have a field to say whose job this is or was. If you make a GUI around this, you would make an instance of a 'PersonsModel' class, and an instance of a 'JobsModel' class. Then when a different person is selected in the PersonsModel, you could set a filter in the JobsModel to show only the job history of this person.
    Yeah, i guess. The difference with me is that i am not using a database, i am simply storing data in C++ objects. So i am not storing Person and Job data in separate lists/tables, but rather each Person contains a list of Jobs.


    Quote Originally Posted by marcvanriet
    It is also my understanding that models are only for lists of items (persons, jobs, ...). In your example you want to keep the information about more than 1 person, don't you ? If you want to keep information about just 1 item (although I can't really think of a practical example of such a case), then you can can create a model which has just 1 entry in it - like a database table with just 1 record in it.
    Yes, I am storing information about more than one person*, but i am only displaying one at a time in the view.

    I just wanted a simple way of modelling this, but i already have it working with QTableWidget and that way at least makes a lot more sense to me. I guess it would be possible in some way to use Qt's models here, but it seems like more trouble than it's worth.


    * The person/job classes i posted is just an example, but they demonstrate what i have in my actual application.

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

    Default Re: Questions about models

    Ok, I somehow came to a conclusion that I may not able to explain you further without help of a working example.

    So here we look at an example, which should be very similar to what you explained. Please make a BIG NOTE that this is just an example, and shows one of the ways to implement a model.

    The key feature here is to relate the Person to the Job, and at run-time able to refer them from one another. In the example below i use a simple row & and type encoding which make it easy to relate job to a person. One could use any type of technique to relate Job & Person, simple pointers / run time type determination / holding pointer to each others etc.


    Qt Code:
    1. //PersonJobModel.h
    2. #ifndef PERSONJOBMODEL_H
    3. #define PERSONJOBMODEL_H
    4.  
    5. #include <QList>
    6. #include <QDate>
    7. #include <QAbstractItemModel>
    8.  
    9. struct Job {
    10. QString name;
    11. QDate startDate;
    12. };
    13.  
    14. struct Person {
    15. QString name;
    16. QString address;
    17. QList<Job*> employmentHistory;
    18. };
    19.  
    20. class PersonJobModel : public QAbstractItemModel
    21. {
    22. Q_OBJECT
    23. public:
    24. explicit PersonJobModel(QObject *parent = 0);
    25. ~PersonJobModel();
    26.  
    27. QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
    28. QModelIndex parent(const QModelIndex &child) const ;
    29. int rowCount(const QModelIndex &parent = QModelIndex()) const;
    30. int columnCount(const QModelIndex &parent = QModelIndex()) const;
    31. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    32.  
    33. signals:
    34.  
    35. private:
    36. enum RowType {
    37. TypePerson = 0x00000000,
    38. TypeJob = 0x01000000,
    39. TypeMask = 0xFF000000
    40. };
    41.  
    42. QList<Person*> persons;
    43.  
    44. inline quint32 encodeTypeRow(RowType type, int row) const
    45. { return type | ( ~TypeMask & row); }
    46.  
    47. inline int decodeRow(const QModelIndex& index) const
    48. { return static_cast<quint32>(index.internalId()) & ~TypeMask; }
    49.  
    50. inline RowType decodeType(const QModelIndex& index) const
    51. { return static_cast<RowType>(index.internalId() & TypeMask); }
    52.  
    53. inline bool isPerson(const QModelIndex& index) const
    54. { return decodeType(index) == TypePerson; }
    55.  
    56. inline bool isJob(const QModelIndex& index) const
    57. { return decodeType(index) == TypeJob; }
    58. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. //PersonJobModel.cpp
    2. #include "PersonJobModel.h"
    3.  
    4. PersonJobModel::PersonJobModel(QObject *parent)
    5. {
    6. //Create some sample data, 4 Persons, 5 Jobs per person
    7. for(int i = 0; i < 4; i++)
    8. {
    9. Person* person = new Person;
    10. person->name = QString("Person %1").arg(i+1);
    11. person->address = QString("Address of Person %1").arg(i+1);
    12. for(int j = 0; j < 5; j++)
    13. {
    14. Job* job = new Job;
    15. job->name = QString("Person %1, Job %2").arg(i+1).arg((i+1)*(j+1));
    16. job->startDate = QDate(i+1, j+1, (i+1)*(j+1));
    17. person->employmentHistory.append(job);
    18. }
    19. persons.append(person);
    20. }
    21. }
    22.  
    23. PersonJobModel::~PersonJobModel()
    24. {
    25. while(persons.count())
    26. {
    27. while(persons.at(0)->employmentHistory.count())
    28. delete persons.at(0)->employmentHistory.takeFirst();
    29. delete persons.takeFirst();
    30. }
    31. }
    32.  
    33. QModelIndex PersonJobModel::index(int row, int column, const QModelIndex &parent) const
    34. {
    35. if(!parent.isValid())
    36. return createIndex(row, column, encodeTypeRow(TypePerson, 0));
    37. else if(isPerson(parent))
    38. return createIndex(row, column, encodeTypeRow(TypeJob, parent.row()));
    39. return QModelIndex();
    40. }
    41.  
    42. QModelIndex PersonJobModel::parent(const QModelIndex& child) const
    43. {
    44. if(child.isValid())
    45. if(isJob(child))
    46. return createIndex(decodeRow(child), 0, encodeTypeRow(TypePerson, 0));
    47. return QModelIndex();
    48. }
    49.  
    50. int PersonJobModel::rowCount(const QModelIndex& parent) const
    51. {
    52. if(!parent.isValid())
    53. return persons.count();
    54. else if(isPerson(parent))
    55. return persons.at(parent.row())->employmentHistory.count();
    56. return 0;
    57. }
    58.  
    59. int PersonJobModel::columnCount(const QModelIndex& parent) const
    60. {
    61. return 2;
    62. }
    63.  
    64. QVariant PersonJobModel::data(const QModelIndex& index, int role) const
    65. {
    66. if(role == Qt::DisplayRole)
    67. {
    68. if(isPerson(index))
    69. {
    70. if(index.column() == 0)
    71. return persons.at(index.row())->name;
    72. else if(index.column() == 1)
    73. return persons.at(index.row())->address;
    74. }
    75. else if(isJob(index))
    76. {
    77. if(index.column() == 0)
    78. return persons.at(decodeRow(index))->employmentHistory.at(index.row())->name;
    79. else if(index.column() == 1)
    80. return persons.at(decodeRow(index))->employmentHistory.at(index.row())->startDate.toString();
    81. }
    82. }
    83. return QVariant();
    84. }
    85.  
    86. #endif // PERSONJOBMODEL_H
    To copy to clipboard, switch view to plain text mode 

    and here is the output view
    Attached Images Attached Images

  14. #14
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    The difference with me is that i am not using a database, i am simply storing data in C++ objects. So i am not storing Person and Job data in separate lists/tables, but rather each Person contains a list of Jobs.
    Well, a database is also just a way of storing data. You can store the same data in C++ objects. It doesn't matter for the GUI. You must only have different models for accessing the data. The advantage of the model/view approach is that it is more generic and works with a lot of built-in widgets. For your C++ objects, you have to implement everything yourself.

    Regards,
    Marc

  15. #15
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Questions about models

    Santosh, that code seems awful complicated compared to the few lines it takes to create QTableWidgetItems.
    For example:
    Qt Code:
    1. int row = 0;
    2. jobsTable->setRowCount(person.jobs().size());
    3. jobsTable->setColumnCount(2);
    4. for (i = person.jobs().begin(); i != person.jobs().end(); i++) {
    5. QTableWidgetItem* jobNameItem = new QTableWidgetItem((*i).name());
    6. QTableWidgetItem* jobDateItem = new QTableWidgetItem((*i).startDate());
    7.  
    8. jobsTable->setItem(row, 0, jobNameItem);
    9. jobsTable->setItem(row, 1, jobDateItem);
    10. row++;
    11. }
    To copy to clipboard, switch view to plain text mode 

    Also, your screenshot is a little different to what i want. I know the view can be changed independent of the model, but here is an example of what my "view" (UI) looks like:
    form.png
    [Window Detective] - Windows UI spy utility
    [War Thunder]

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

    Default Re: Questions about models

    As always you can use QTableWidget to keep things simple

Similar Threads

  1. Viewer for 3D Models
    By bts in forum Newbie
    Replies: 2
    Last Post: 3rd March 2011, 14:45
  2. sql models
    By damiano19902 in forum Newbie
    Replies: 1
    Last Post: 4th June 2009, 07:18
  3. Proxy models and slection models
    By amunitz in forum The Model-View Framework
    Replies: 1
    Last Post: 23rd September 2008, 14:35
  4. Models in cascade
    By thrantir in forum Qt Programming
    Replies: 6
    Last Post: 18th January 2007, 14:05

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.