QTreeView / QAbstractItemModel - adding items and using beginInsertRows - qt

I'm implementing my model based on QAbstractItemModel and I'm using it with QTreeView to display hierachical data. Data are stored in sqlite table.
My question is how should I call beginInsertRows when adding subnodes.
Lets say I have some parent node, it contains 10 subnodes. And I want to add new subnode (at the end).
I'm doing it like this:
beginInsertRows(parentIndex, currentNodesCount, currentNodesCount);
// actual inserting
endInsertRows()
currentNodesCount contains value 10 which is the number of rows in this subnode.
The new node will be placed at the 11th position (10th counting from 0).
Is this logic correct ?
Thanks for help.
I'm wondering also about using beginRemoveRows.
Is this correct:
beginRemoveRows(parentIndex, currentRow, currentRow);
// delete record
endRemoveRows();
currentRow contains position in the list of the removed node counting from 0.

Yes that's it.
Was this your only question?

Related

How to find the index of a specific row in QMap based QAbstractListModel?

I have a class derived from QAbstractListModel based on a QMap<QUuid, CustomObject> which I am visualizing with ListView in qml. Some time during my applications running time I am removing some items from this map based on it's QUuid. When I am doing the removing I would like to call beginRemoveRows so the ListView is notified that it's content is changing and needs to redraw itself. How do I find out the right indexes for beginRemoveRows?
Actually using QMap is perfectly fine. You just have to find out the right indexes beginIndexRow, beginRemoveRows etc. For example finding the index for beginIndexRow looks something like this:
int index = std::distance(myQMap.begin(), myQMap.lowerBound(id));
beginInsertRows(QModelIndex(), index, index);
myQMap[id] = myCustomObject;
endInsertRows();

How do I Insert an item at top of QTreeView

In my app I'd like to insert an item at the top of a QTreeView.
What I have so far will insert an item just above the currently selected item. The code (nicked, I think, from the EditableTreeviewDemo):
QModelIndex index = this->selectionModel()->currentIndex();
QAbstractItemModel *model = this->model();
if (!model->insertRow(index.row(), index.parent()))
return;
I guess what I need is the index to the current first row? How do I get this?
As a side question, what happens to the current index when a row is inserted? Does it continue to point to the same item, or the same row?
Well first you have to know that insertRow is a function from QAbstractItemModel and it will call insertRows (with an s). This function must be redefined in your model subclass if you want to allow insertion of data in your model.
http://doc.qt.io/qt-5/qabstractitemmodel.html#insertRows
Also consider that any parent of a topmost index is a invalid QModelIndex. Then the call to do would be :
model->insertRow(0, QModelIndex());
And because this is the default value for the second parameter, simply call :
model->insertRow(0);
Then in your redefinition of insertRows simply check the validity of you parent index to ensure you news underlying data is created where you want it to be.
For you question, inserting data in the model won't affect the current and selected items.

QT: QTableView read cell content

I'm writing a small program with QT creator (QT 5.2.1) under Windows 7 (32 bit) and I'm having problems reading the informations stored in a TableView. My application has 3 elements, a TableView to store text data, a TextBrowser to show info and a buttom.
I modified the TableView properties: when the user selects with the mouse a cell, the full row is selected and multiple row selection is not allowed.
The user select a row and when the buttom is pressed, I would like to read the content of a specific TableView cell and show it in a TextBrowser. In particular, I would like to know the row index of the selected row and read the content of the cell with that row index and a specific column index (example 2).
The pseudo-code is this:
void my_program::on_pushButton_clicked()
{
ui->textBrowser->append("button pressed");
QItemSelectionModel *select = ui->tableView->selectionModel();
int index_row = select->selectedRows();
int index_column = 2;
char cell_data[30] = ??[index_row][index_column]
ui->textBrowser->append(cell_data);
}
The main problem is that select->selectedRows() returns a QModelIndex that is a collection of indexs and I do not know how to convert it to int (since multiple selection are not allowed, it should have only one element).
I would be glad if someone can suggest me a way to proceed.
Thanks
Francesco
edit:
Hi Bogdan, thanks a lot!! I succeed to read the cell content by using
ui->textBrowser->append(ui->tableView->model()->data(ui->tableView->model()->index(2,5)).toString());
this give me the content of the cell in position 2,5.
not sure if this is the best way or not but it works !!.
Can you be a bit more precise about how to iterate the QModeIndexList ? thanks :)
selectedRows() returns QModelIndexList, thus you need to iterate over it and call QModelIndex::data() to get stored data.

QTableView / QStandardItemModel update without losing selection / sort order

Currently I want to update row items in a QStandardItemModel without losing the sort order and row selection in the respective QTableView.
I have tested two approaches:
Clearing the model by clear() and re-adding the rows "destroys" everything including headers.
Removing and re-adding all rows keeps the headers, but still "destroys" selection and sort order.
I could try to manually to a) remove all rows no longer required and then b) update the items of the changed rows. But is there no easier way?
I don't know, how you sorted your data before the update, but please take a look at the QTableView's sortByColumn() function.
As for the selection, if it still keeps disappearing, you can manually put back your selection, where it should be by:
// You access the selected index when the editing starts
QModelIndex index = table->selectionModel()->currentIndex();
//Later when you finished editing, you can select it again
table->selectionModel()->select(index, QItemSelectionModel::Select);
More about this:
QItemSelectionModel
QTableView
You can either remove the rows no longer required and add the new ones or manually remember the sort order and which items were selected before clearing. I.e. assign a unique ID (one can use setData() with a custom role for that), retrieve that before clearing from the selected items, and reapply the selection after recreating the items.

QTableView problems with row

Hello guys i new to QT and i am doing Qtableview to add information in 3 columns to infinite row like
|--1--|--2--|--3--|
|--1--|--2--|--3--|
|--1--|--2--|--3--|
this is how i want to insert/append row but this is how i am getting after insert/append row functions.
|--1--|--2--|--3--|
|-----|-----|-----||--1--|--2--|--3--|
|-----|-----|-----||-----|-----|-----||--1--|--2--|--3--|
i am getting empty gaps and increased column count
i am using QStandardItemmodel for model this is code that creates the model item
void tableview::add_tableview() //this is used to add data to tableview
{
//to get data from line edit in add window
QStandardItem *item_1 = new QStandardItem(QString(enter1_edit->text()));
QStandardItem *item_2 = new QStandardItem(QString(enter2_edit->text()));
QStandardItem *item_3 = new QStandardItem(QString(enter3_edit->text()));
list << item_1 << item_2 << item_3;
model->appendRow(list);
//to set the model
main_tableview->setModel(model);
}
The values in the rows are added using qlineedit enter1_edit,enter2_edit & enter3_edit(its in other function/method)
main_tableview is the object of qtableview
Thanks for helping me!
Ding Ding Ding, I have it.
I tried to reproduce your problem without success unil I tried something...suboptimal :).
Is your list by any chance a global entity? If yes (and I assume it is) you keep adding items to it.
First time you call add_tableview() all is good, list is empty, gets three QStandardItem pointers added and is used to append a row with those three items. So far so god.
You call add_tableview() again, now you create another three QStandardItems and APPEND them to the list (which still contains the three from the last call). Invoking appendRow() actually tries to insert six items, from which the first three allready exist in the model. And as you know you mustn't add the same item pointer to a model twice. Thankfully Qt doesn't crash but inserts three empty columns for the item pointers allready in it.
Solution: At the end of your add_tableview() method call list.clear() or use a local variable for the list. The overhead should be minimal.
Best regards
D

Resources