Results 1 to 14 of 14

Thread: Complex data structure upgrade to QAbstractListModel

  1. #1
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Complex data structure upgrade to QAbstractListModel

    Dear Sirs and Madams!

    I am working on Qt/QML with mysql db application I have following situation:
    At startup the user must login into system and this part works ok (QML<==>Qt/C++ interaction). Now, I fetch data from several tables using their models and from this data I would like to make subclassed QAbstractListModel class, which will work with following data structure:
    Qt Code:
    1. typedef QMap<QPair<QString, QString>, QList<UeOrderRecord*>> UeTypeOrders;
    To copy to clipboard, switch view to plain text mode 
    Let me clarify: I have logged user (Id, Name, Image, Password), I have some products (Id, Name, Image, Price, ...) and some positions (Id, Name, ...). Now, for evey logged user, new (empty) model with UeTypeOrders must be created. How do I, for example, handle data in UeTypeOrders in virtual data() method?

    Sincerely yours,
    Marko
    Qt 5.3 Opensource & Creator 3.1.2

  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: Complex data structure upgrade to QAbstractListModel

    The data() method of a list model needs to do two things:

    1) Find the data structure instance for the row as given with index.row()
    2) Return the data field as given by role

    So if you have a list or vector of UeTypeOrders, a simple index access should take care of (1).
    For (2) you specify roles for each of the data fields you'd like to have access to and let a switch() on the role argument handle the access to the respective field.

    Cheers,
    _

  3. #3
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by anda_skoa View Post
    The data() method of a list model needs to do two things:

    1) Find the data structure instance for the row as given with index.row()
    2) Return the data field as given by role

    So if you have a list or vector of UeTypeOrders, a simple index access should take care of (1).
    For (2) you specify roles for each of the data fields you'd like to have access to and let a switch() on the role argument handle the access to the respective field.

    Cheers,
    _
    Here is my data[ method now:
    Qt Code:
    1. QVariant UeOrdersModel::data(const QModelIndex &index,
    2. int role) const
    3. {
    4. switch(role)
    5. {
    6. case ueRoleUserId:
    7. {
    8. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->ueUserId();
    9. } break;
    10.  
    11. case ueRolePlaceId:
    12. {
    13. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->uePlaceId();
    14. } break;
    15.  
    16. case ueRoleProductId:
    17. {
    18. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->ueProductId();
    19. } break;
    20.  
    21. case ueRoleProductName:
    22. {
    23. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->ueProductName();
    24. } break;
    25.  
    26. case ueRoleProductPriceSell:
    27. {
    28. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->ueProductPriceSell();
    29. } break;
    30.  
    31. case ueRoleProductQuantity:
    32. {
    33. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->ueProductQuantity();
    34. } break;
    35.  
    36. case ueRoleOrderAmount:
    37. {
    38. return this->ueOrders()->value(QPair<QString, QString>(this->ueUserName(),this->uePlaceName())).at(index.row())->ueOrderAmount();
    39. } break;
    40.  
    41. default:
    42. {
    43. return QVariant();
    44. } break; // default
    45. } // switch
    46.  
    47. return QVariant();
    48. } // data
    To copy to clipboard, switch view to plain text mode 
    Am I getting close and my next question is if the data structure in the model is updated at runtime (i.e, internal data structure record record is added, changed or deleted), does this mean the model should be implemented as editable or still as read only? And if so (editable), I do not know what to put in, for exameple, method insertRow(s)?
    Qt 5.3 Opensource & Creator 3.1.2

  4. #4
    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: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by MarkoSan View Post
    Here is my data[ method now:
    A lot of code duplication, this could be written much more compact.

    1) no need for "this->"
    2) everything up to the last "->" is equal to all cases. can be done outside the switch
    3) call cases have return. no need to break
    4) no case has local variables. no need to block braces.

    Quote Originally Posted by MarkoSan View Post
    Am I getting close and my next question is if the data structure in the model is updated at runtime (i.e, internal data structure record record is added, changed or deleted), does this mean the model should be implemented as editable or still as read only?
    Can still be read only, the model only needs to signal its changes to the view(s).

    Cheers,
    _

  5. #5
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by anda_skoa View Post
    A lot of code duplication, this could be written much more compact.

    1) no need for "this->"
    2) everything up to the last "->" is equal to all cases. can be done outside the switch
    3) call cases have return. no need to break
    4) no case has local variables. no need to block braces.


    Can still be read only, the model only needs to signal its changes to the view(s).

    Cheers,
    _
    How do I signal changeds to the view, i.e., I have now following method:
    Qt Code:
    1. void UeOrdersModel::ueAddOrder(const QString& userName,
    2. const QString& placeName,
    3. const QImage& productImage,
    4. const QString& productId,
    5. const QString& productName,
    6. const QString& productPriceSell,
    7. const quint64& productQuantity,
    8. const QString& productVAT)
    9. {
    10. QPair<QString, QString> key=QPair<QString, QString>(userName, placeName);
    11. if(this->ueOrders()->contains(key))
    12. {
    13. double priceSell=productPriceSell.toDouble();
    14. double priceVAT=productVAT.toDouble();
    15. double amountWithoutVAT=productQuantity*priceSell;
    16. double amountWithVAT=productQuantity*(priceSell+(priceSell*priceVAT));
    17. this->ueOrders()->value(key)->append(new UeOrderRecord(this,
    18. userName,
    19. placeName,
    20. productImage,
    21. productId,
    22. productName,
    23. productPriceSell,
    24. productQuantity,
    25. QString::number(amountWithoutVAT),
    26. productVAT,
    27. QString::number(amountWithVAT)));
    28. } // if
    29. } // ueAddOrder
    To copy to clipboard, switch view to plain text mode 
    How do I now send dataChanged() signal from this method to update QML ListView?
    Qt 5.3 Opensource & Creator 3.1.2

  6. #6
    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: Complex data structure upgrade to QAbstractListModel

    1) Determine the row to which this entry belongs
    2) get the QModelIndex for that row
    3) emit dataChanged with that index for begin/end and either keep the third parameter empty or add all roles that have changed to the list of roles

    But ueAddOrder sounds like this would add something, are you sure this only changes existing data?

    Cheers,
    _

  7. #7
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Complex data structure upgrade to QAbstractListModel

    With this method I add record to model internal data structure. Do you have some example of your previous post?
    Qt 5.3 Opensource & Creator 3.1.2

  8. #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: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by MarkoSan View Post
    With this method I add record to model internal data structure
    ok, but does that mean new rows in the model or just data in existing rows changing?

    Quote Originally Posted by MarkoSan View Post
    Do you have some example of your previous post?
    Qt Code:
    1. const int affectedRow = ....;
    2.  
    3. const QModelIndex changedIndex = index(affectedRow, 0);
    4.  
    5. emit dataChanged(changedIndex, changedIndex); // if all roles changed or if you don't know which roles
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

  9. #9
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by anda_skoa View Post
    ok, but does that mean new rows in the model or just data in existing rows changing?


    Qt Code:
    1. const int affectedRow = ....;
    2.  
    3. const QModelIndex changedIndex = index(affectedRow, 0);
    4.  
    5. emit dataChanged(changedIndex, changedIndex); // if all roles changed or if you don't know which roles
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _
    I think this:
    1) If I add order to already logged user, that means adding record to model's internal data's QList - QPair and QMap exist.
    2) If already logged user changes target "place", then model's internal data's QPair with empty QList is added to EXISTING QMap
    3) However, if new user logs into system, then new object is created and added to QMap

    So, in number 3 scenario I think new row must be added, or I am wrong?
    Qt 5.3 Opensource & Creator 3.1.2

  10. #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: Complex data structure upgrade to QAbstractListModel

    This is your data, only you know which criteria you used for rowCount().

    Well, we can guess.
    We can guess that the row count is the size/length/count of the QList returned by ueOrders()->value().

    And you append to that.
    So your row count changes.
    So the model has now one row more than it had
    Which means you added a row.
    So you should emit signals for row insertion.
    Which you would do with beginInsertRows() and endInsertRows().

    All just guessing of course, if you are sure you are not adding rows, then just emit the data change signal for the affected row.

    Cheers,
    _

  11. #11
    Join Date
    Jan 2006
    Location
    Ljubljana
    Posts
    687
    Thanks
    111
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by anda_skoa View Post
    This is your data, only you know which criteria you used for rowCount().

    Well, we can guess.
    We can guess that the row count is the size/length/count of the QList returned by ueOrders()->value().

    And you append to that.
    So your row count changes.
    So the model has now one row more than it had
    Which means you added a row.
    So you should emit signals for row insertion.
    Which you would do with beginInsertRows() and endInsertRows().

    All just guessing of course, if you are sure you are not adding rows, then just emit the data change signal for the affected row.

    Cheers,
    _
    Ok, you have a point, but I am verry sorry, I am total confused at the moment. Let's start from the begining. Let say, you and I work in a restaurant with this piece of software of mine. I login into system and at that point the mentioned data structure
    Qt Code:
    1. /*
    2.  * QPair QString1 user name
    3.  * QPair QString2 place name
    4.  * QMap QList list of orders
    5.  */
    6. typedef QMap<QPair<QString, QString>, QList<UeOrderRecord*>*> UeTypeOrders;
    To copy to clipboard, switch view to plain text mode 
    is appended with QMap<QPair<username, placename> empty QList>. That means, I've logged into system using my credentials and I have empty orders QList. Since I need to encapsulate this data structure into model to be used by QML ListView, I "packed" this data structure into subclassed QAbstractListModel. Now, let's say, you come to work and you also login into system, which means another object is appended to UeTypeOrder, with your credentials and empty orders list. Does at this point model changes or not? Or does it only change when I add order to third component, QList? How do I setup my QAbastractListModel, does this means model is readonly or not - should I implement read-only model it editable model? And should I return from model (using data() method, for instance) only QList or whole QMap?

    Sincerely,
    Marko
    Qt 5.3 Opensource & Creator 3.1.2

  12. #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: Complex data structure upgrade to QAbstractListModel

    Quote Originally Posted by MarkoSan View Post
    Now, let's say, you come to work and you also login into system, which means another object is appended to UeTypeOrder, with your credentials and empty orders list. Does at this point model changes or not?
    This depends on what your model does.
    Does it show the logged in people? Does it show the orders of all people? Does it show the combined orders of all logged in people? Does it only show the orders of one logged in person?

    This is your model, you know what aspect of your data your model exposes.

    1) Determine what you want to show in the view
    2) Find out how to get that data from your data structure
    3) Create a model that does that

    At this point it will be obvious which changes to the data structure will change the amount of data exposed by the model and which changes will only change values.

    Cheers,
    _

  13. #13
    Join Date
    Jan 2017
    Posts
    1
    Qt products
    Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Complex data structure upgrade to QAbstractListModel

    I don't understand why you use this way for presenting data.
    In a recent project, I created model as following:
    Qt Code:
    1. class Number {
    2. public:
    3. QString number;
    4. bool isChecked;
    5. };
    6.  
    7. class NumberModel: public QAbstractListModel {
    8. //...
    9. private:
    10. QList<Number *> m_list;
    11. };
    12.  
    13. class Contact {
    14. public:
    15. QString name;
    16. NumberModel numbers;
    17. };
    18.  
    19. class ContactModel : public QAbstractListModel {
    20. //...
    21. private:
    22. QList<Contact *> m_list;
    23. };
    24.  
    25. class Phonebook {
    26. public:
    27. QString title;
    28. QDate creationDate;
    29. ContactModel contacts;
    30. };
    31.  
    32. class PhonebookModel: public QAbstractListModel {
    33. //...
    34. private:
    35. QList<Phonebook *> m_list;
    36. };
    To copy to clipboard, switch view to plain text mode 
    in the data() method you can return your sub-model as a QVariant which is created using QObject *.
    In QML you can use your model as follow:
    Qt Code:
    1. ListView {
    2. model: phonebookModel
    3. delegate: Component{
    4. Text {
    5. model.title
    6. }
    7. MouseArea {
    8. onClicked: { myDialog.model = model.contacts; myDialog.open(); }
    9. }
    10. }
    11. }
    To copy to clipboard, switch view to plain text mode 

  14. #14
    Join Date
    Feb 2017
    Posts
    1
    Qt products
    Platforms
    MacOS X

    Default Re: Complex data structure upgrade to QAbstractListModel

    I am not sure about it.

Similar Threads

  1. Replies: 15
    Last Post: 14th September 2015, 14:42
  2. Show complex cpp data model in QML
    By ms2222 in forum Qt Quick
    Replies: 4
    Last Post: 2nd March 2015, 13:55
  3. Replies: 1
    Last Post: 20th October 2011, 11:08
  4. Printing complex page with changing data
    By marcvanriet in forum Qt Programming
    Replies: 4
    Last Post: 22nd December 2010, 02:15
  5. Data Structure help!
    By darshan in forum Newbie
    Replies: 8
    Last Post: 18th February 2009, 13:47

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.