Results 1 to 15 of 15

Thread: QAbstractItemModel newbie question

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Dec 2007
    Posts
    6
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11
    Thanks
    1

    Default Re: QAbstractItemModel newbie question

    Many thanks for replying, wysota.

    > your parent() implementation is invalid - you can't return an index by using
    > ModelIndex:arent() because this method will call the model's parent() method
    > to find the proper parent index

    Okay. The problem then is, how do I get to the parent index when only given the
    child index.
    I resorted to a trick with internalPointer inEnumItemModel::index() :[*] on a top level item, call createIndex() with (void*)0 as the internalPointer[*] on a non toplevel item, call createIndex() with (parent.row() + 1) as the internalPointer

    I would hope that there's a better way to get the parent index but I can't think of one...

    > rowCount() will take an invalid model index for top level items, thus row() will
    > return -1 and your rowCount() method will break

    I'm not sure I understand that comment.
    Here's my modified enumitemmodel.cpp:

    Qt Code:
    1. #include <QtGui>
    2. #include <iostream>
    3.  
    4. #include "enumitemmodel.h"
    5.  
    6. EnumItemModel::EnumItemModel(QObject *parent)
    7. {
    8. setupModelData();
    9. }
    10.  
    11. EnumItemModel::~EnumItemModel()
    12. {
    13. }
    14.  
    15. int EnumItemModel::columnCount(const QModelIndex &parent) const
    16. {
    17. return 1;
    18. }
    19.  
    20. QVariant EnumItemModel::data(const QModelIndex &index, int role) const
    21. {
    22. if (!index.isValid())
    23. return QVariant();
    24.  
    25. if (role != Qt::DisplayRole)
    26. return QVariant();
    27.  
    28. const QModelIndex &parentIndex = index.parent();
    29.  
    30. if (!parentIndex.isValid())
    31. return QVariant(enumTypes[index.row()].first);
    32.  
    33. int parentRow = parentIndex.row();
    34. return QVariant(enumTypes[parentRow].second[index.row()]);
    35. }
    36.  
    37. Qt::ItemFlags EnumItemModel::flags(const QModelIndex &index) const
    38. {
    39. if (!index.isValid())
    40. return 0;
    41.  
    42. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    43. }
    44.  
    45. QModelIndex EnumItemModel::index(int row, int column, const QModelIndex &parent)
    46. const
    47. {
    48. if (!hasIndex(row, column, parent))
    49. return QModelIndex();
    50.  
    51. if (!parent.isValid())
    52. return createIndex(row, column, NULL);
    53.  
    54. long parentRowPlusOne = (long) parent.row() + 1;
    55. return createIndex(row, column, (void*)parentRowPlusOne);
    56. }
    57.  
    58. QModelIndex EnumItemModel::parent(const QModelIndex &index) const
    59. {
    60. if (!index.isValid())
    61. return QModelIndex();
    62.  
    63. long parentRowPlusOne = (long)index.internalPointer();
    64. if (!parentRowPlusOne) // Top level item
    65. return QModelIndex();
    66.  
    67. return createIndex((int)parentRowPlusOne - 1, 0, NULL);
    68. }
    69.  
    70. int EnumItemModel::rowCount(const QModelIndex &parent) const
    71. {
    72. if (!parent.isValid())
    73. return 0;
    74.  
    75. if (parent.column() > 0)
    76. return 0;
    77.  
    78. //return enumTypes[parent.row()].second.count(); // or perhaps:
    79. long parentRowPlusOne = (long)parent.internalPointer();
    80. if (!parentRowPlusOne)
    81. {
    82. std::cerr << "EnumItemModel::rowCount(row=" << parent.row()
    83. << "): parentRowPlusOne is 0 ?!?" << std::endl;
    84. return 0;
    85. }
    86. return enumTypes[parentRowPlusOne - 1].second.count();
    87. }
    88.  
    89. void EnumItemModel::setupModelData()
    90. {
    91. QStringList booleanValues;
    92. booleanValues.append("False");
    93. booleanValues.append("True");
    94. enumTypes.append(EnumDefinition("Boolean", booleanValues));
    95.  
    96. QStringList colorValues;
    97. colorValues.append("Red");
    98. colorValues.append("Green");
    99. colorValues.append("Blue");
    100. enumTypes.append(EnumDefinition("Color", colorValues));
    101. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: QAbstractItemModel newbie question

    Quote Originally Posted by okellogg View Post
    > rowCount() will take an invalid model index for top level items, thus row() will
    > return -1 and your rowCount() method will break

    I'm not sure I understand that comment.
    "model.rowCount()" (or more precisely: "model.rowCount( QModelIndex() )" ) should return the number of top-level items and you have two such items ("Boolean" and "Color").

  3. #3
    Join Date
    Dec 2007
    Posts
    6
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11
    Thanks
    1

    Default Re: QAbstractItemModel newbie question

    Quote Originally Posted by jacek View Post
    "model.rowCount()" (or more precisely: "model.rowCount( QModelIndex() )" ) should return the number of top-level items and you have two such items ("Boolean" and "Color").
    Yippie!
    Qt Code:
    1. int EnumItemModel::rowCount(const QModelIndex &parent) const
    2. {
    3. if (!parent.isValid())
    4. return enumTypes.count();
    5. [...]
    To copy to clipboard, switch view to plain text mode 

    With that change, I now got the top level items displayed:

    - Boolean
    - Color

    And with the following, I got everything displayed:
    Qt Code:
    1. int EnumItemModel::rowCount(const QModelIndex &parent) const
    2. {
    3. if (parent.column() > 0)
    4. return 0;
    5. if (!parent.isValid())
    6. return enumTypes.count();
    7. return enumTypes[parent.row()].second.count();
    8. }
    To copy to clipboard, switch view to plain text mode 

    Last remaining problem: The leaf items ("False", "True", etc.) have a
    "+" symbol and are expandable, and when expanding they show again
    the same leaf items, again with "+" ad infinitum. (I'm sure that's an
    easy one

    Thanks again for your help, jacek and wysota.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: QAbstractItemModel newbie question

    Quote Originally Posted by okellogg View Post
    Last remaining problem: The leaf items ("False", "True", etc.) have a
    "+" symbol and are expandable, and when expanding they show again
    the same leaf items, again with "+" ad infinitum. (I'm sure that's an
    easy one
    Try this: http://labs.trolltech.com/page/Proje...view/Modeltest.

  5. #5
    Join Date
    Dec 2007
    Posts
    6
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11
    Thanks
    1

    Default Re: QAbstractItemModel newbie question

    Just for completeness, the rowCount() was still faulty. Here's the corrected version:
    Qt Code:
    1. int EnumItemModel::rowCount(const QModelIndex &parent) const
    2. {
    3. if (parent.column() > 0)
    4. return 0;
    5. if (!parent.isValid()) // return total top level items
    6. return enumTypes.count();
    7. long parentRowPlusOne = (long)parent.internalPointer();
    8. if (!parentRowPlusOne) // type name, e.g. "Color"
    9. return enumTypes[parent.row()].second.count();
    10. // leaf item, e.g. "Red"
    11. return 0;
    12. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QAbstractItemModel newbie question

    Qt Code:
    1. long parentRowPlusOne = (long)index.internalPointer();
    To copy to clipboard, switch view to plain text mode 
    How about QModelIndex::internalId() instead?

    BTW. a trivial rowCount() implementation:
    Qt Code:
    1. int Model::rowCount(const QModelIndex &parent) const {
    2. // if parent is invalid, return number of top level items
    3. if(!parent.isValid())
    4. return enumTypes.count();
    5. // if parent's parent is invalid, this is level one - return components' count
    6. if(!parent.parent().isValid() && hasIndex(parent))
    7. return enumTypes[parent.row()].second.count();
    8. // otherwise at least level 2 - none in our case
    9. return 0;
    10. }
    To copy to clipboard, switch view to plain text mode 

    No need for internal data and you can continue the descent ad infinitum depending on your needs. (for instance root -> QRect -> QPoint -> (int, int))

  7. #7
    Join Date
    Jan 2006
    Location
    Earth (Terra)
    Posts
    87
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Symbian S60
    Thanks
    4
    Thanked 6 Times in 4 Posts

    Default Re: QAbstractItemModel newbie question

    Quote Originally Posted by wysota View Post
    How about QModelIndex::internalId() instead?

    BTW. a trivial rowCount() implementation:
    Qt Code:
    1. int Model::rowCount(const QModelIndex &parent) const {
    2. // if parent is invalid, return number of top level items
    3. if(!parent.isValid())
    4. return enumTypes.count();
    5. // if parent's parent is invalid, this is level one - return components' count
    6. if(!parent.parent().isValid() && hasIndex(parent))
    7. return enumTypes[parent.row()].second.count();
    8. // otherwise at least level 2 - none in our case
    9. return 0;
    10. }
    To copy to clipboard, switch view to plain text mode 

    No need for internal data and you can continue the descent ad infinitum depending on your needs. (for instance root -> QRect -> QPoint -> (int, int))
    Following along, here - very interesting. Can you explain what the 'hasIndex' call does/verifies in this context?

    thanx,
    rickb

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: QAbstractItemModel newbie question

    Whether parent.row() is within the valid range - [0 - rowCount(parent.parent())-1]. Instead you could use (enumTypes.count()>parent.row() && parent.row()>=0).

  9. #9
    Join Date
    Feb 2008
    Posts
    6
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    2

    Default Re: QAbstractItemModel newbie question

    Can you please post the updated code for this problem?

Similar Threads

  1. Question on QAbstractItemModel vs. QTableView
    By lni in forum Qt Programming
    Replies: 1
    Last Post: 26th April 2007, 08:29
  2. Newbie threading question
    By deepayan in forum Qt Programming
    Replies: 17
    Last Post: 16th April 2007, 01:25
  3. Replies: 1
    Last Post: 15th March 2007, 21:45
  4. newbie question about qtextedit fields
    By otortos in forum Qt Programming
    Replies: 1
    Last Post: 23rd February 2006, 19:21

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
  •  
Qt is a trademark of The Qt Company.