Results 1 to 10 of 10

Thread: Removing row from QAbstractItemModel

  1. #1
    Join Date
    Jan 2010
    Posts
    95
    Thanks
    14
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Removing row from QAbstractItemModel

    Hi all,

    I'm using QML treeview with model sub-classed from QAbstractItemModel.
    I'm facing this issue that model indexes aren't updated when user removes a row.

    Here's the code
    Qt Code:
    1. bool TreeModel::removeRows(int row, int count, const QModelIndex &parent)
    2. {
    3. TreeItem *parentItem = getItem(parent);
    4.  
    5. if(parentItem == null) return false;
    6.  
    7. bool success = false;
    8.  
    9. if (count > 0)
    10. {
    11. beginRemoveRows(parent, row, row + count - 1);
    12. success = parentItem->removeChildren(row, count);
    13. endRemoveRows();
    14. }
    15.  
    16. return success;
    17. }
    18.  
    19. bool TreeItem::removeChildren(int position, int count)
    20. {
    21. if (position < 0 || position + count > children_.size())
    22. return false;
    23.  
    24. for (int row = 0; row < count; ++row)
    25. delete children_.takeAt(position);
    26.  
    27. return true;
    28. }
    To copy to clipboard, switch view to plain text mode 

    Could you point what am I missing?
    Last edited by volcano; 28th June 2016 at 13:19.

  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: Removing row from QAbstractItemModel

    Looks ok.

    Does it work with a QTreeView (widget based view)?

    Have you tried the model test framework? https://wiki.qt.io/Model_Test

    Cheers,
    _

  3. #3
    Join Date
    Jan 2010
    Posts
    95
    Thanks
    14
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Removing row from QAbstractItemModel

    Thanks anda_skoa for the suggestion

    I tried to use the test however I can't find the .pri file to add it to the project

  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: Removing row from QAbstractItemModel

    You could write your own one or just add the two files to your .pro

    Cheers,
    _

  5. #5
    Join Date
    Jan 2010
    Posts
    95
    Thanks
    14
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Removing row from QAbstractItemModel

    I added the two files in my project

    Here's my pro file
    Qt Code:
    1. QT += qml quick widgets testlib
    2. CONFIG += c++11
    3.  
    4. SOURCES += main.cpp \
    5. treeviewmodel.cpp \
    6. treeviewitem.cpp \
    7. app.cpp \
    8. modeltest.cpp
    9.  
    10. RESOURCES += qml.qrc
    11.  
    12. HEADERS += \
    13. treeviewmodel.h \
    14. treeviewitem.h \
    15. app.h \
    16. modeltest.h
    To copy to clipboard, switch view to plain text mode 

    However I get the following error
    main.obj : error LNK2019: unresolved external symbol "int __cdecl qInitResources_files(void)" (?qInitResources_files@@YAHXZ) referenced in function main

    Here's my main
    Qt Code:
    1. int main(int argc, char *argv[])
    2. {
    3. QApplication qapp(argc, argv);
    4.  
    5. QQuickView* view = new QQuickView(QUrl(QStringLiteral("qrc:/main.qml")));
    6. view->show();
    7.  
    8. App* app = App::instance();
    9. app->setView(view);
    10.  
    11. return qapp.exec();
    12. }
    To copy to clipboard, switch view to plain text mode 

    Could you point me what am I missing?

  6. #6
    Join Date
    Jan 2010
    Posts
    95
    Thanks
    14
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Removing row from QAbstractItemModel

    Could you point what am I missing?

  7. #7
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Removing row from QAbstractItemModel

    Look carefully at what happens to the internal list in removeChildren() when count is greater than 1. Line 24, 25 of first listing.

    You do not instantiate an instance of ModelTest as in the example on the page provided.

    Regarding the linker error: Run make clean, rerun qmake, and rebuild. Does the problem persist?

  8. #8
    Join Date
    Jan 2010
    Posts
    95
    Thanks
    14
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Removing row from QAbstractItemModel

    Thanks ChrisW67 for your feedback.

    On performing the following operation " Run make clean, rerun qmake, and rebuild", the project build successfully.

    However I'm unable to trace the issue of indexes when a row is removed.
    I refered the Qt example of "editabletreemodel", and I noticed that the model is casted to a QAbstractItemModel and then removeRow is called with the row and the parent
    Qt Code:
    1. void MainWindow::removeRow()
    2. {
    3. QModelIndex index = view->selectionModel()->currentIndex();
    4. QAbstractItemModel *model = view->model();
    5. if (model->removeRow(index.row(), index.parent()))
    6. updateActions();
    7. }
    To copy to clipboard, switch view to plain text mode 

    Here's the removeRow method in that example
    Qt Code:
    1. bool TreeModel::removeRows(int position, int rows, const QModelIndex &parent)
    2. {
    3. TreeItem *parentItem = getItem(parent);
    4. bool success = true;
    5.  
    6. beginRemoveRows(parent, position, position + rows - 1);
    7. success = parentItem->removeChildren(position, rows);
    8. endRemoveRows();
    9.  
    10. return success;
    11. }
    To copy to clipboard, switch view to plain text mode 

    Which is similar to the approach I'm trying to follow.

    Kindly advice what am I missing

  9. #9
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Removing row from QAbstractItemModel

    I have reread your removeChildren() function and it does not suffer from the common mistake I initially thought. My mistake.

  10. #10
    Join Date
    Jan 2010
    Posts
    95
    Thanks
    14
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Removing row from QAbstractItemModel

    I tried to follow the same approach used in the editabletreemodel example i.e, call model->removeRow(index.row(), index.parent())

    However, this is the problem I face..
    If I have 5 items - [0]A, [1]B, [2]C, [3]D, [4]E, where the brackets specify the index and alphabets are the items
    and I remove item C, I am expecting the row index should be [0]A, [1]B, [2]D, [3]E
    However it remains as [0]A, [1]B, [3]D, [4]E

    Here's my treeitem and treemodel
    Qt Code:
    1. TreeItem::TreeItem()
    2. {
    3. }
    4.  
    5. TreeItem::TreeItem(QVariant name, TreeItem *parent)
    6. {
    7. parentItem_ = parent;
    8. itemName_ = name;
    9. }
    10.  
    11. TreeItem::~TreeItem()
    12. {
    13. qDeleteAll(children_);
    14. }
    15.  
    16. void TreeItem::insertChild(int row, TreeItem *item)
    17. {
    18. item->setParent(this);
    19. children_.insert(row, item);
    20. }
    21.  
    22. bool TreeItem::removeChildren(int position, int count)
    23. {
    24. if (position < 0 || position + count > children_.size())
    25. return false;
    26.  
    27. for (int row = 0; row < count; ++row)
    28. delete children_.takeAt(position);
    29.  
    30. return true;
    31. }
    32.  
    33. TreeItem *TreeItem::child(int row) const
    34. {
    35. return children_.at(row);
    36. }
    37.  
    38. TreeItem *TreeItem::parent()
    39. {
    40. return parentItem_;
    41. }
    42.  
    43. void TreeItem::setParent(TreeItem* parent)
    44. {
    45. parentItem_ = parent;
    46. }
    47.  
    48. int TreeItem::childrenCount() const
    49. {
    50. return children_.count();
    51. }
    52.  
    53. int TreeItem::row() const
    54. {
    55. if (parentItem_)
    56. return parentItem_->children_.indexOf(const_cast<TreeItem*>(this));
    57.  
    58. return 0;
    59. }
    60.  
    61. void TreeItem::setItemName(QVariant name)
    62. {
    63. itemName_ = name;
    64. }
    65. QVariant TreeItem::itemName() const
    66. {
    67. return itemName_;
    68. }
    69.  
    70. //////////////////////////////////////////////////////////////////////////
    71. // TreeModel
    72. TreeModel::TreeModel()
    73. {
    74. treeRoot_ = makeShared<TreeItem>();
    75. }
    76.  
    77. TreeModel::~TreeModel()
    78. {
    79. }
    80.  
    81. QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
    82. {
    83. if (!hasIndex(row, column, parent))
    84. return QModelIndex();
    85.  
    86. TreeItem *parentItem = getItem(parent);
    87.  
    88. TreeItem *childItem = parentItem->child(row);
    89. if (childItem)
    90. return createIndex(row, column, childItem);
    91. else
    92. return QModelIndex();
    93. }
    94.  
    95. QModelIndex TreeModel::parent(const QModelIndex &child) const
    96. {
    97. if (!child.isValid())
    98. return QModelIndex();
    99.  
    100. TreeItem *childItem = static_cast<TreeItem*>(child.internalPointer());
    101. TreeItem *parentItem = childItem->parent();
    102.  
    103. if (parentItem == treeRoot_.get())
    104. return QModelIndex();
    105.  
    106. return createIndex(parentItem->row(), 0, parentItem);
    107. }
    108.  
    109. int TreeModel::columnCount(const QModelIndex &parent) const
    110. {
    111. TreeItem* parentItem = getItem(parent);
    112. return parentItem->propertyCount();
    113. }
    114.  
    115. QVariant TreeModel::data(const QModelIndex &index, int role) const
    116. {
    117. if (!index.isValid())
    118. return QVariant();
    119.  
    120. TreeItem* item = getItem(index);
    121.  
    122. switch (role)
    123. {
    124. case NameRole:
    125. return item->itemName();
    126. }
    127. return QVariant();
    128. }
    129.  
    130. bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
    131. {
    132. bool result = true;
    133.  
    134. TreeItem* item = getItem(index);
    135. SP_CNRF(item);
    136.  
    137. switch (role)
    138. {
    139. case NameRole:
    140. item->setItemName(value);
    141. break;
    142.  
    143. default:
    144. result = false;
    145. break;
    146. }
    147.  
    148. if (result)
    149. {
    150. emit dataChanged(index, index);
    151. }
    152.  
    153. return result;
    154. }
    155.  
    156. int TreeModel::rowCount(const QModelIndex &parent) const
    157. {
    158. if (parent.column() > 0)
    159. return 0;
    160.  
    161. TreeItem *parentItem = getItem(parent);
    162. return parentItem->childrenCount();
    163. }
    164.  
    165. bool TreeModel::removeRows(int row, int count, const QModelIndex &parent)
    166. {
    167. TreeItem *parentItem = getItem(parent);
    168.  
    169. if (count > 0)
    170. {
    171. beginRemoveRows(parent, row, row + count - 1);
    172. success = parentItem->removeChildren(row, count);
    173. endRemoveRows();
    174. }
    175.  
    176. return success;
    177. }
    178.  
    179. void TreeModel::insertItem(int position, TreeItem *item, const QModelIndex &parent)
    180. {
    181. TreeItem *parentItem = getItem(parent);
    182.  
    183. beginInsertRows(parent, position, position);
    184. parentItem->insertChild(position, item);
    185. endInsertRows();
    186. }
    187.  
    188. TreeItem* TreeModel::getItem(const QModelIndex &index) const
    189. {
    190. if (index.isValid()) {
    191. TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
    192. if (item)
    193. return item;
    194. }
    195. return treeRoot_.get();
    196. }
    197.  
    198. bool TreeModel::removeItem(const QModelIndex &index)
    199. {
    200. auto treeItem = getItem(index);
    201. if (treeItem)
    202. return removeRows(treeItem->row(), 1, parent(index));
    203. else
    204. return false;
    205. }
    206.  
    207. void TreeModel::init()
    208. {
    209. if (treeRoot_)
    210. {
    211. beginResetModel();
    212. removeRows(0, treeRoot_->childrenCount(), QModelIndex());
    213. endResetModel();
    214. }
    215. }
    216.  
    217. QHash<int, QByteArray> TreeModel::roleNames() const
    218. {
    219. QHash<int, QByteArray> roles;
    220. roles[NameRole] = "name";
    221. return roles;
    222. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. QAbstractItemModel on QGraphicsView
    By wagmare in forum Newbie
    Replies: 0
    Last Post: 24th May 2012, 09:06
  2. qAbstractItemView, QAbstractItemModel...
    By jano_alex_es in forum Newbie
    Replies: 2
    Last Post: 18th May 2009, 10:22
  3. QAbstractItemModel with rowSpan?
    By joeld42 in forum Qt Programming
    Replies: 0
    Last Post: 4th February 2009, 19:53
  4. QAbstractItemModel question
    By awhite1159 in forum Qt Programming
    Replies: 3
    Last Post: 22nd June 2008, 10:11
  5. Help needed with QAbstractItemModel
    By Harvey West in forum Qt Programming
    Replies: 11
    Last Post: 27th November 2006, 13:06

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.