Results 1 to 2 of 2

Thread: QStandardItemModel insertRow crashing

  1. #1
    Join Date
    Jan 2006
    Posts
    667
    Thanks
    10
    Thanked 80 Times in 74 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default QStandardItemModel insertRow crashing

    Hi,

    I have a treeview for which I am creating the model (QStandardItemModel) after reading values from a DB. The treeview is inside a tab and everytime a user moves to another tab and comes back I have to query the DB again and rebuild the model.

    Now, the problem is that when a node a tree is opened something like below

    |__+Node1
    |__Node2
    | |__Leaf1
    | |__Leaf2
    |__+Node3

    and we navigate to some other tab and come back to this one, my application crashes when insertRow is called. But when the tree is like the following

    |__+Node1
    |__+Node2
    |__+Node3

    Everything works fine.

    Qt Code:
    1. #include <FooTab.h>
    2. #include <DeleteDBValueOp.h>
    3. #include <NewAccountOp.h>
    4. #include <SessionSingleton.h>
    5. #include <UpdateDBValuesOp.h>
    6. #include <MainWindow.h>
    7.  
    8. #define DEFAULT_NUMBER_VALUE 1
    9. #define DEFAULT_DATETIME_VALUE "'2000-01-01 00:00:00'"
    10.  
    11. FooTab::FooTab( QWidget* )
    12. {
    13. qDebug() << "Inside Constructor";
    14. ui = MainWindow::instance()->UI();
    15. connect( ui.FooRefreshBtn, SIGNAL( clicked() ), this, SLOT( doRefreshFooTree() ) );
    16. connect( ui.FooDeleteBtn, SIGNAL( clicked() ), this, SLOT( doFooDeleteBtnClicked() ) );
    17. connect( ui.FooNewAccountBtn, SIGNAL( clicked() ), this, SLOT( FooNewAccountBtnClicked() ) );
    18. connect( ui.FooUnlockBtn, SIGNAL( clicked() ), this, SLOT( FooUnlockBtnClicked() ) );
    19. connect( ui.FooUpdateBtn, SIGNAL( clicked() ), this, SLOT( FooUpdateBtnClicked() ) );
    20. connect( ui.FooDescriptionLE, SIGNAL( textEdited( const QString & ) ), this, SLOT( FooInfoEdited( const QString & ) ) );
    21. connect( ui.FooNumberLE, SIGNAL( textEdited( const QString & ) ), this, SLOT( FooInfoEdited( const QString & ) ) );
    22. connect( ui.FooInactivateBtn, SIGNAL( clicked() ), this, SLOT( FooInactivateBtnClicked() ) );
    23.  
    24. ui.FooNumberLE->setReadOnly( true );
    25. ui.FooNewAccountBtn->setEnabled( false );
    26. }
    27.  
    28. FooTab::~FooTab ()
    29. {
    30.  
    31. }
    32.  
    33. /*!
    34. * The function is called when user changed tab or
    35. * another case, when we need to put tab in initial state for
    36. * user to start manipulationd with accounts.
    37. */
    38.  
    39. void FooTab::updateClientFooTab()
    40. {
    41. qDebug() << "\nupdating Foo tab";
    42.  
    43. ui.FooNumberLE->setVisible( true );
    44. ui.FooNumberL->setVisible( true );
    45.  
    46. QAbstractItemModel* model = ui.FooTree->model();
    47.  
    48. // create model if it not exists
    49. if( model == NULL )
    50. {
    51. model = new QStandardItemModel;
    52. ui.FooTree->setModel( model );
    53.  
    54. model->insertColumn( 0 );
    55.  
    56. // set names to horizontal labels
    57. model->setHeaderData(0, Qt::Horizontal, tr("Some Header"));
    58. }
    59. qDebug() << model->rowCount();
    60. if ( model->rowCount() > 0 )//When the tree is built for the first time this condition will be false.
    61. {
    62. model->removeRows( 0, model->rowCount());
    63. }
    64.  
    65. // Create first level of nodes, if empty
    66. if ( model->rowCount() == 0 )
    67. {
    68. qDebug() << "Empty tab. Updating...";
    69. QSqlQuery query( ... );
    70. QString account_names_query = QString( "SOME QUERY");
    71.  
    72. qDebug() << account_names_query;
    73. query.exec( account_names_query );
    74.  
    75. // insert root element
    76. model->insertRow( 0 ); //CRASHES HERE. BOOM!!!
    77. QModelIndex root = model->index( 0, 0 );
    78.  
    79. model->insertColumn( 0, root );
    80.  
    81. Q_ASSERT( root.isValid() );
    82. model->setData( root, "Root" );
    83. FooTreeNodeData node_data;
    84. node_data.was_expanded = true;
    85. node_data.id = -1;
    86. node_data.is_type = true;
    87. v.setValue( node_data );
    88. model->setData( root, v, Qt::UserRole );
    89.  
    90. ui.FooTree->setRootIndex( root );
    91. // set root as current element
    92. ui.FooTree->setCurrentIndex( root );
    93.  
    94. // Insert zero level at TreeView, as expandable nodes
    95. doAddNewSubnodes( root, query, model );
    96. }
    97.  
    98. qDebug() << "Foo Tab updated";
    99. ui.FooTree->setCurrentIndex( model->index( 0, 0 ) );
    100.  
    101. connect( ui.FooTree, SIGNAL( expanded( const QModelIndex &) ), this, SLOT( doExpandFooTreeNode( const QModelIndex &) ) );
    102.  
    103. QItemSelectionModel* selectionModel = ui.FooTree->selectionModel();
    104. connect( selectionModel,
    105. SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
    106. this,
    107. SLOT( FooTreeCurrentChanged( const QModelIndex& , const QModelIndex& ))) ;
    108. }
    109.  
    110. /*!
    111.  * The slot is run, when user expands Tree node.
    112.  * If node is expanded first time, then it selects from DB subnodes.
    113.  * else just expands.
    114.  * \param index clicked node
    115.  */
    116. void FooTab::doExpandFooTreeNode( const QModelIndex &index)
    117. {
    118. qDebug() << "expanded Foo node";
    119. QSqlQuery query( SessionSingleton::instance()->database() );
    120.  
    121. QAbstractItemModel *model = ui.FooTree->model();
    122. // If wasn't expanded yet
    123. FooTreeNodeData node_data = model->data( index, Qt::UserRole ).value<FooTreeNodeData>();
    124. if ( !node_data.was_expanded )
    125. {
    126. qDebug() << "Wasn't expanded yet. Read data from DB";
    127. // Now expanded
    128. node_data.was_expanded = true;
    129. v.setValue( node_data );
    130. model->setData( index, v, Qt::UserRole );
    131.  
    132. // Delete fictiuous subnode
    133. model->removeRow( 0, index );
    134.  
    135. QString accounts_query_string = QString( "SOME OTHER QUERY");
    136.  
    137. qDebug() << accounts_query_string;
    138. query.exec( accounts_query_string );
    139.  
    140. while( query.next() )
    141. {
    142. int id = query.value( 0 ).toInt();
    143. QString description = query.value( 1 ).toString();
    144. int number = query.value( 2 ).toInt();
    145.  
    146. qDebug() << id << description << number;
    147.  
    148. if( description.isEmpty() )
    149. {
    150. description = QString( "%1" ).arg( number );
    151. }
    152.  
    153. FooTreeNodeData node_data;
    154. node_data.is_type = false;
    155. node_data.was_expanded = true;
    156. node_data.id = id;
    157.  
    158. model->insertRow( model->rowCount( index ), index );
    159. QModelIndex subindex = model->index( model->rowCount( index ) - 1, 0, index );
    160.  
    161. model->setData( subindex, description );
    162. v.setValue( node_data );
    163. model->setData( subindex, v, Qt::UserRole );
    164.  
    165. model->insertColumn( 0, subindex );
    166.  
    167. // adding sub node
    168. QSqlQuery query_subnode( DATABASECONNECTION );
    169. QString qry_accounts_subtypes = QString( "THE THIRD QUERY");
    170. qDebug() << qry_accounts_subtypes;
    171. query_subnode.exec( qry_accounts_subtypes );
    172. if (query_subnode.size() > 0)
    173. {
    174. while ( query_subnode.next() )
    175. {
    176. QString name = query_subnode.value( 0 ).toString();
    177. int id = query_subnode.value( 1 ).toInt();
    178.  
    179. //Q_ASSERT( !name.isEmpty() );
    180. if ( name.isEmpty() )
    181. {
    182. name = "<EMPTY>";
    183. }
    184.  
    185. qDebug() << "Insert node: " << name;
    186. // Insert node
    187. int model_row_count = model->rowCount( subindex );
    188. model->insertRow( model_row_count, subindex );
    189. QModelIndex sub_subindex = model->index( model->rowCount( subindex ) - 1, 0, subindex );
    190. model->setData( sub_subindex, name );
    191.  
    192. FooTreeNodeData node_data;
    193. node_data.id = id;
    194. node_data.was_expanded = true;
    195. node_data.is_type = false;
    196. v.setValue( node_data );
    197.  
    198. model->setData( sub_subindex, v, Qt::UserRole );
    199. node_data = model->data( sub_subindex, Qt::UserRole ).value<FooTreeNodeData>();
    200. qDebug() << "Node type ID: " << node_data.id;
    201.  
    202. // Insert subnode
    203. model->insertColumn( 0, sub_subindex );
    204. }
    205. }
    206. }
    207. }
    208. }
    209.  
    210.  
    211. /*!
    212.  * \brief Add new subnodes to \c index from \c query
    213.  *
    214.  * \note Also, added fictuous subnode to subnodes be expandable
    215.  * \param index node where insert subnodes
    216.  * \param query from get subnode names
    217.  * \param model model to add subnodes to
    218.  */
    219. void FooTab::doAddNewSubnodes( const QModelIndex &index, QSqlQuery &query, QAbstractItemModel *model)
    220. {
    221. while ( query.next() )
    222. {
    223. QString name = query.value( 0 ).toString();
    224. int id = query.value( 1 ).toInt();
    225.  
    226. Q_ASSERT( !name.isEmpty() );
    227. if ( name.isEmpty() )
    228. {
    229. name = "<EMPTY>";
    230. }
    231.  
    232. qDebug() << "Insert node: " << name;
    233. // Insert node
    234. int model_row_count = model->rowCount( index );
    235. model->insertRow( model_row_count, index );
    236. QModelIndex subindex = model->index( model->rowCount( index ) - 1, 0, index );
    237. model->setData( subindex, name );
    238.  
    239. FooTreeNodeData node_data;
    240. node_data.id = id;
    241. node_data.was_expanded = false;
    242. node_data.is_type = true;
    243. v.setValue( node_data );
    244.  
    245. model->setData( subindex, v, Qt::UserRole );
    246. node_data = model->data( subindex, Qt::UserRole ).value<FooTreeNodeData>();
    247. qDebug() << "Node type ID: " << node_data.id;
    248.  
    249. // Insert subnode
    250. model->insertColumn( 0, subindex );
    251. model->insertRow( 0, subindex );
    252. }
    253. }
    To copy to clipboard, switch view to plain text mode 

    Can someone please tell me what wrong with the code above?

    Thanks a lot
    Last edited by munna; 27th June 2008 at 07:34. Reason: Clearing up unwanted code.

  2. #2
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: QStandardItemModel insertRow crashing

    I didn't see the fault in your code, but here's mine.
    I'm using a QAbstractTableModel, maybe you can use it for your program.

    Qt Code:
    1. #include "articlesTableModel.h"
    2. #include <QtGui>
    3.  
    4.  
    5. ArticlesTableModel::ArticlesTableModel(const QList<QStringList> &data, const QStringList &header, QObject *parent)
    6. {
    7. qDebug("ArticlesTableModel::ArticlesTableModel(): Constructing the table model");
    8. this->articles = data;
    9. this->header = header;
    10. }
    11.  
    12.  
    13. int ArticlesTableModel::rowCount( const QModelIndex& parent) const
    14. {
    15. Q_UNUSED(parent);
    16. return articles.count();
    17. }
    18.  
    19. int ArticlesTableModel::columnCount( const QModelIndex& parent) const
    20. {
    21. Q_UNUSED(parent);
    22. return header.count();
    23. }
    24.  
    25. QVariant ArticlesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
    26. {
    27. if( Qt::Horizontal == orientation)
    28. {
    29. if(Qt::DisplayRole == role)
    30. {
    31. return header.at(section);
    32. }
    33. }
    34.  
    35. return QAbstractTableModel::headerData(section, orientation, role);
    36. }
    37.  
    38. QVariant ArticlesTableModel::data(const QModelIndex &index, int role) const
    39. {
    40.  
    41. if(!index.isValid())
    42. return QVariant();
    43.  
    44. QStringList record = this->articles.at(index.row());
    45.  
    46. if(role == Qt::DisplayRole || role == Qt::EditRole){
    47.  
    48. return record.at(index.column());
    49.  
    50. }
    51.  
    52. return QVariant();
    53.  
    54. }
    55.  
    56. Qt::ItemFlags ArticlesTableModel::flags(const QModelIndex &index) const
    57. {
    58. if(!index.isValid())
    59. return 0;
    60.  
    61. return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
    62. }
    63.  
    64.  
    65. bool ArticlesTableModel::setData(const QModelIndex& index, const QVariant& value, int role)
    66. {
    67. if(index.isValid() && (role == Qt::DisplayRole || role == Qt::EditRole)){
    68. this->articles[index.row()][index.column()] = value.toString();
    69. emit dataChanged(index, index);
    70. return true;
    71. }
    72.  
    73. return false;
    74. }
    75.  
    76. bool ArticlesTableModel::insertRows(int row, int count, const QModelIndex &parent)
    77. {
    78. Q_UNUSED(parent);
    79. QStringList emptyRecord;
    80. for(int i = 0; i < columnCount(QModelIndex()); i++)
    81. emptyRecord.append(QString());
    82. beginInsertRows(QModelIndex(), row, row+count-1);
    83. for(int i = 0; i < count; i++){
    84. this->articles.insert(row, emptyRecord);
    85. }
    86. endInsertRows();
    87.  
    88. return true;
    89. }
    90.  
    91. bool ArticlesTableModel::removeRows(int row, int count, const QModelIndex &parent)
    92. {
    93. Q_UNUSED(parent);
    94. if(row-count-1 > this->articles.count() -1) return false;
    95. beginRemoveRows(QModelIndex(), row, row+count-1);
    96. for(int i=0; i<count; i++)
    97. this->articles.removeAt(row);
    98. endRemoveRows();
    99. return true;
    100.  
    101. }
    To copy to clipboard, switch view to plain text mode 

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.