Results 1 to 4 of 4

Thread: QTreeView remove issue

  1. #1
    Join Date
    Mar 2008
    Location
    Houston, Texas, USA
    Posts
    277
    Thanks
    9
    Thanked 17 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Maemo/MeeGo

    Default QTreeView remove issue

    I have my QTreeView basically working like I want. The only issue is that when I remove a row from a leaf in the QTreeView.

    If I have the node expanded when an row is removed it works fine. But when the node is collapsed when I remove the row the arrow next to the leaf is gone until I add a new row or something like that.

    EDIT: It seems to not update the leaf's text and add the item when it is collapsed either.

    Qt Code:
    1. void
    2. NickTreeModel::removeUser(Aki::NickTreeItem *item)
    3. {
    4. int row = -1;
    5. for (int i = 0; i < d->rootItem->childCount(); ++i) {
    6. QModelIndex idx = index(i, 0);
    7. Aki::NickTreeItem *categoryItem = d->rootItem->child(i);
    8. if ((row = categoryItem->indexOfChild(item)) != -1) {
    9. beginRemoveRows(idx, row, row);
    10. delete categoryItem->takeChild(row);
    11. endRemoveRows();
    12. reset();
    13. }
    14. }
    15. }
    16.  
    17. void
    18. NickTreeModel::removeUser(Aki::Irc::User *user)
    19. {
    20. int row = -1;
    21. for (int i = 0; i < d->rootItem->childCount(); ++i) {
    22. QModelIndex idx = index(i, 0);
    23. Aki::NickTreeItem *categoryItem = d->rootItem->child(i);
    24. if ((row = categoryItem->indexOfChild(user)) != -1) {
    25. beginRemoveRows(idx, row, row);
    26. delete categoryItem->takeChild(row);
    27. endRemoveRows();
    28. }
    29. }
    30. }
    To copy to clipboard, switch view to plain text mode 
    Qt-4.7.3 | Gentoo ~amd64 | KDE-4.7
    Aki IRC Client for KDE4 | Qt Documentation

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

    Default Re: QTreeView remove issue

    You meant that the arrow is gone and you have other rows under your leaf, right? It is possible that you have bugs in other parts of your model - index, parent functions.

    The most reliable way to assure that your model does not have obvious bugs is the ModelTest test suite.

    It's hard to say with assurance what is the problem is your case, as we cant see full model implementation

    There are also a few things I noticed (probably not relevant to the problem):
    1) calling reset(); does not make much sense as you are trying to remove the item.
    2) You should probably call break; as soon as you find a mach in your data source to remove. Otherwise you may end up with quite subtle bugs.

    Good luck!

  3. #3
    Join Date
    Mar 2008
    Location
    Houston, Texas, USA
    Posts
    277
    Thanks
    9
    Thanked 17 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Maemo/MeeGo

    Default Re: QTreeView remove issue

    I'm running ModelTest and it doesn't say anything about it when it happens.
    My tree layout is like

    Qt Code:
    1. Root--|
    2. --Operators
    3. |
    4. --Half-Operators
    5. |
    6. --Voices
    7. |
    8. --Users
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. NickTreeModel::NickTreeModel(QObject *parent)
    2. {
    3. d.reset(new Aki::NickTreeModelPrivate(this));
    4.  
    5. d->rootItem = new Aki::NickTreeItem;
    6.  
    7. d->operatorsItem = new Aki::NickTreeItem(d->rootItem, "Operators");
    8. d->operatorsItem->setIcon(KIcon("aki_operator"));
    9. d->rootItem->addChild(d->operatorsItem);
    10.  
    11. d->halfOperatorsItem = new Aki::NickTreeItem(d->rootItem, "Half-Operators");
    12. d->halfOperatorsItem->setIcon(KIcon("aki_halfop"));
    13. d->rootItem->addChild(d->halfOperatorsItem);
    14.  
    15. d->voicesItem = new Aki::NickTreeItem(d->rootItem, "Voices");
    16. d->voicesItem->setIcon(KIcon("aki_voice"));
    17. d->rootItem->addChild(d->voicesItem);
    18.  
    19. d->usersItem = new Aki::NickTreeItem(d->rootItem, "Users");
    20. d->usersItem->setIcon(KIcon("aki_normal"));
    21. d->rootItem->addChild(d->usersItem);
    22.  
    23. sort(0);
    24. }
    25.  
    26. NickTreeModel::~NickTreeModel()
    27. {
    28. delete d->rootItem;
    29. }
    30.  
    31. void
    32. NickTreeModel::addUser(Aki::NickTreeItem *item)
    33. {
    34. int row = -1;
    35. Aki::Irc::User *user = d->user(item);
    36. if (user->isOp()) {
    37. row = d->operatorsItem->childCount();
    38. beginInsertRows(index(0, 0), row, row);
    39. item->setParent(d->operatorsItem);
    40. d->operatorsItem->addChild(item);
    41. endInsertRows();
    42. return;
    43. } else if (user->isHalfOp()) {
    44. row = d->halfOperatorsItem->childCount();
    45. beginInsertRows(index(1, 0), row, row);
    46. item->setParent(d->halfOperatorsItem);
    47. d->halfOperatorsItem->addChild(item);
    48. endInsertRows();
    49. return;
    50. } else if (user->isVoice()) {
    51. row = d->voicesItem->childCount();
    52. beginInsertRows(index(2, 0), row, row);
    53. item->setParent(d->voicesItem);
    54. d->voicesItem->addChild(item);
    55. endInsertRows();
    56. return;
    57. } else if (user->isNormal()){
    58. row = d->usersItem->childCount();
    59. beginInsertRows(index(3, 0), row, row);
    60. item->setParent(d->usersItem);
    61. d->usersItem->addChild(item);
    62. endInsertRows();
    63. return;
    64. }
    65. }
    66.  
    67. void
    68. NickTreeModel::removeUser(Aki::NickTreeItem *item)
    69. {
    70. int row = -1;
    71. for (int i = 0; i < d->rootItem->childCount(); ++i) {
    72. QModelIndex idx = index(i, 0);
    73. Aki::NickTreeItem *categoryItem = d->rootItem->child(i);
    74. if ((row = categoryItem->indexOfChild(item)) != -1) {
    75. beginRemoveRows(idx, row, row);
    76. delete categoryItem->takeChild(row);
    77. endRemoveRows();
    78. return;
    79. }
    80. }
    81. }
    82.  
    83. void
    84. NickTreeModel::removeUser(Aki::Irc::User *user)
    85. {
    86. int row = -1;
    87. for (int i = 0; i < d->rootItem->childCount(); ++i) {
    88. QModelIndex idx = index(i, 0);
    89. Aki::NickTreeItem *categoryItem = d->rootItem->child(i);
    90. if ((row = categoryItem->indexOfChild(user)) != -1) {
    91. beginRemoveRows(idx, row, row);
    92. delete categoryItem->takeChild(row);
    93. endRemoveRows();
    94. return;
    95. }
    96. }
    97. }
    98.  
    99. void
    100. NickTreeModel::changeParents(Aki::NickTreeItem *item)
    101. {
    102. int row = -1;
    103. Aki::NickTreeItem *categoryItem;
    104. for (int i = 0; i < d->rootItem->childCount(); ++i) {
    105. idx = index(i, 0);
    106. categoryItem = d->item(idx);
    107. if (categoryItem->indexOfChild(item) != -1) {
    108. row = categoryItem->indexOfChild(item);
    109. break;
    110. }
    111. }
    112.  
    113. if (!idx.isValid() || row == -1) {
    114. return;
    115. }
    116.  
    117. int newRow = -1;
    118. Aki::Irc::User *user = d->user(item);
    119. if (user->isOp()) {
    120. newRow = d->operatorsItem->childCount();
    121. if (idx == index(0, 0) &&
    122. row == (newRow - 1)) {
    123. return;
    124. }
    125. bool success = beginMoveRows(idx, row, row, index(0, 0), newRow);
    126. if (success) {
    127. Aki::NickTreeItem *old = categoryItem->takeChild(row);
    128. old->setParent(d->operatorsItem);
    129. d->operatorsItem->addChild(old);
    130. endMoveRows();
    131. return;
    132. }
    133.  
    134. } else if (user->isHalfOp()) {
    135. newRow = d->halfOperatorsItem->childCount();
    136. if (idx == index(1, 0) &&
    137. row == (newRow - 1)) {
    138. return;
    139. }
    140. bool success = beginMoveRows(idx, row, row, index(1, 0), newRow);
    141. if (success) {
    142. Aki::NickTreeItem *old = categoryItem->takeChild(row);
    143. old->setParent(d->halfOperatorsItem);
    144. d->halfOperatorsItem->addChild(old);
    145. endMoveRows();
    146. return;
    147. }
    148. } else if (user->isVoice()) {
    149. newRow = d->voicesItem->childCount();
    150. if (idx == index(2, 0) &&
    151. row == (newRow - 1)) {
    152. return;
    153. }
    154. bool success = beginMoveRows(idx, row, row, index(2, 0), newRow);
    155. if (success) {
    156. Aki::NickTreeItem *old = categoryItem->takeChild(row);
    157. old->setParent(d->voicesItem);
    158. d->voicesItem->addChild(old);
    159. endMoveRows();
    160. return;
    161. }
    162. } else if (user->isNormal()){
    163. newRow = d->usersItem->childCount();
    164. if (idx == index(3, 0) &&
    165. row == (newRow - 1)) {
    166. return;
    167. }
    168. bool success = beginMoveRows(idx, row, row, index(3, 0), newRow);
    169. if (success) {
    170. Aki::NickTreeItem *old = categoryItem->takeChild(row);
    171. old->setParent(d->usersItem);
    172. d->usersItem->addChild(old);
    173. endMoveRows();
    174. return;
    175. }
    176. }
    177. }
    178.  
    179. QList<Aki::Irc::User*>
    180. NickTreeModel::users()
    181. {
    182. QList<Aki::Irc::User*> tmp;
    183.  
    184. for (int i = 0; i < d->rootItem->childCount(); ++i) {
    185. Aki::NickTreeItem *item = d->rootItem->child(i);
    186. for (int j = 0; j < item->childCount(); ++j) {
    187. Aki::Irc::User *child =
    188. item->child(j)->data(Aki::NickTreeItem::IrcUserRole).value<Aki::Irc::User*>();
    189. tmp.append(child);
    190. }
    191. }
    192.  
    193. return tmp;
    194. }
    195.  
    196. void
    197. NickTreeModel::clear()
    198. {
    199. beginRemoveRows(QModelIndex(), 0, 3);
    200. delete d->rootItem->takeChild(3);
    201. delete d->rootItem->takeChild(2);
    202. delete d->rootItem->takeChild(1);
    203. delete d->rootItem->takeChild(0);
    204. endRemoveRows();
    205. }
    206.  
    207. void
    208. NickTreeModel::addCategories()
    209. {
    210. beginInsertRows(QModelIndex(), 0, 3);
    211. d->operatorsItem = new Aki::NickTreeItem(d->rootItem, "Operators");
    212. d->operatorsItem->setIcon(KIcon("aki_operator"));
    213. d->rootItem->addChild(d->operatorsItem);
    214.  
    215. d->halfOperatorsItem = new Aki::NickTreeItem(d->rootItem, "Half-Operators");
    216. d->halfOperatorsItem->setIcon(KIcon("aki_halfop"));
    217. d->rootItem->addChild(d->halfOperatorsItem);
    218.  
    219. d->voicesItem = new Aki::NickTreeItem(d->rootItem, "Voices");
    220. d->voicesItem->setIcon(KIcon("aki_voice"));
    221. d->rootItem->addChild(d->voicesItem);
    222.  
    223. d->usersItem = new Aki::NickTreeItem(d->rootItem, "Users");
    224. d->usersItem->setIcon(KIcon("aki_normal"));
    225. d->rootItem->addChild(d->usersItem);
    226. endInsertRows();
    227. }
    228.  
    229. NickTreeModel::data(const QModelIndex &index, int role) const
    230. {
    231. if (!index.isValid()) {
    232. return QVariant();
    233. }
    234.  
    235. Aki::NickTreeItem *item = d->item(index);
    236.  
    237. switch (role) {
    238. case Aki::NickTreeModel::AwayRole: {
    239. return item->data(Aki::NickTreeItem::IrcUserAwayRole);
    240. break;
    241. }
    242. case Qt::DecorationRole: {
    243. return item->data(Qt::DecorationRole);
    244. break;
    245. }
    246. case Qt::DisplayRole: {
    247. return item->data(Qt::DisplayRole);
    248. break;
    249. }
    250. case Aki::NickTreeModel::UserRole: {
    251. return item->data(Aki::NickTreeItem::IrcUserRole);
    252. break;
    253. }
    254. case Qt::ToolTipRole: {
    255. return item->data(Qt::ToolTipRole);
    256. break;
    257. }
    258. default: {
    259. return QVariant();
    260. }
    261. }
    262.  
    263. return QVariant();
    264. }
    265.  
    266. int
    267. NickTreeModel::columnCount(const QModelIndex &parent) const
    268. {
    269. if (parent.isValid()) {
    270. return d->item(parent)->columnCount();
    271. }
    272.  
    273. return d->rootItem->columnCount();
    274. }
    275.  
    276. int
    277. NickTreeModel::rowCount(const QModelIndex &parent) const
    278. {
    279. if (parent.column() > 0) {
    280. return 0;
    281. }
    282.  
    283. if (!parent.isValid()) {
    284. return d->rootItem->childCount();
    285. }
    286.  
    287. return d->item(parent)->childCount();
    288. }
    289.  
    290. NickTreeModel::parent(const QModelIndex &child) const
    291. {
    292. if (!child.isValid()) {
    293. return QModelIndex();
    294. }
    295.  
    296. Aki::NickTreeItem *childItem = d->item(child);
    297. Aki::NickTreeItem *parentItem = childItem->parent();
    298.  
    299. if (parentItem == d->rootItem) {
    300. return QModelIndex();
    301. }
    302.  
    303. return createIndex(parentItem->row(), 0, parentItem);
    304. }
    305.  
    306. NickTreeModel::index(int row, int column, const QModelIndex &parent) const
    307. {
    308. if (!hasIndex(row, column, parent)) {
    309. return QModelIndex();
    310. }
    311.  
    312. Aki::NickTreeItem *parentItem = 0;
    313.  
    314. if (!parent.isValid()) {
    315. parentItem = d->rootItem;
    316. } else {
    317. parentItem = d->item(parent);
    318. }
    319.  
    320. Aki::NickTreeItem *childItem = parentItem->child(row);
    321. if (childItem) {
    322. return createIndex(row, column, childItem);
    323. } else {
    324. return QModelIndex();
    325. }
    326.  
    327. return QModelIndex();
    328. }
    329.  
    330. Qt::ItemFlags
    331. NickTreeModel::flags(const QModelIndex &index) const
    332. {
    333. if (!index.isValid()) {
    334. return 0;
    335. }
    336.  
    337. return d->item(index)->flags();
    338. }
    339.  
    340. bool
    341. NickTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
    342. {
    343. if (!index.isValid()) {
    344. return false;
    345. }
    346.  
    347. if (role != Aki::NickTreeModel::UserRole) {
    348. return false;
    349. }
    350.  
    351. Aki::NickTreeItem *item = d->item(index);
    352. if (item) {
    353. item->setData(0, Aki::NickTreeItem::IrcUserRole, value);
    354. emit dataChanged(index, index);
    355. return true;
    356. }
    357.  
    358. return false;
    359. }
    360. #include "nicktreemodel.moc"
    To copy to clipboard, switch view to plain text mode 
    Qt-4.7.3 | Gentoo ~amd64 | KDE-4.7
    Aki IRC Client for KDE4 | Qt Documentation

  4. #4
    Join Date
    Mar 2008
    Location
    Houston, Texas, USA
    Posts
    277
    Thanks
    9
    Thanked 17 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Maemo/MeeGo

    Default Re: QTreeView remove issue

    I found the problem. It's a bug in Qt that has never been fixed at all in the past 3 years. One of the guys in #qt on freenode told me about it. I can reproduce it in one of the examples in Qt.

    If you compile Qt's EditableTreeModel. Create a toplevel item and create a child in it. Keep the child selected and collapse the leaf and remove the row and the issue appears.
    Qt-4.7.3 | Gentoo ~amd64 | KDE-4.7
    Aki IRC Client for KDE4 | Qt Documentation

Similar Threads

  1. Need help Updating QTreeView model (QAbstractItemModel)
    By iraytrace in forum Qt Programming
    Replies: 1
    Last Post: 26th October 2009, 23:49
  2. One Model, Two Views (QTreeView and QTableView)
    By dgarrett97 in forum Newbie
    Replies: 2
    Last Post: 14th September 2009, 19:10
  3. remove node in xml file
    By mattia in forum Newbie
    Replies: 1
    Last Post: 6th March 2008, 14:25
  4. [QT4 & XP] QTreeView issue with Designer form
    By incapacitant in forum Newbie
    Replies: 3
    Last Post: 2nd March 2006, 18:42
  5. QSettings again ... how to remove array elements
    By Mike in forum Qt Programming
    Replies: 4
    Last Post: 11th January 2006, 09:58

Tags for this Thread

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.