How to add QComboBox and TextField inside TreeView with delegate QML? - qt

I had implement TreeView following this tutorial, But I had implement with Qt Quick Control (does not has .ui file). tutorial here. With load text and show on TreeView, it work fine. But I had another problem:
I know that a row is a TreeItem and the model is TreeModel extend from QAbstractItemModel.
- My TreeView has four columns and I set data for TreeItem with its itemData, each itemData has 4 element.
On Value Column (column 2) I want to add dynamic component (QComboBox and TextField), it depend on value of TreeItem the TreeModel. The figure below.
I set data for TreeItem and TreeModel from .cpp file, and set model for TreeView in .qml file.
I have a objectA with 8 element (name, value, data to assign component for column 2, current index of Combobox if have Combobox, data1,...) with second element maybe QStringList or QString. My TreeItem get data from objectA with TreeItem (name,value,data1,data2).
I have 3 problems need to be solve:
First problem, I had delegate the column 2 to all ComboBox or all TextField ok, But I cannot mix them together. When the value of TreeItem is a QStringList, I want delegate for Combobox, and when it is QString I want delegate for TextField. But I cannot access to the return data, I dont know that I need to define it on .cpp file or .qml file. I know that "styleData.value" is the value for a cell data, access from .qml file. But I cant to know data Type of "styleData.value" .
Second problem, Another problem that I dont know how to set current index for Combobox on load data. For example: the value(second element) of TreeItem is: [item1, item2, item3] and the current Index is at item 2.
Third problem, when data is loaded, I change data for ComboBox. How to get current Data of the TreeItem, current Index of Combobox.
Sorry for long question, and a lot of problems.
Please help me if you know any my problem.
Thank in advance.

Related

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.

How to update selection in the QTableView after drag row

I have custom QTableView class that shows content of custom model based on QAbstractItemModel. In the model I've implemented all needed methods to support changing rows order by DragAndDrop ( using dropMimeData()).
But I do not know how to update selection in the view after model (and view) changed.
For example:
user clicks on the row, it becomes 'selected';
user drags this row to other place;
rows are swaps in the model and view;
BUT selection stays on the first selected row.
How model can notify view to change selection?
NOTE: I cant to create additional signals and slots because don't use MOC.
The solution is:
In function dropMimeData() need to use beginMoveRows() and andMoveRows() around place where data changed.
Need to process signal QAbstractItemModel::rowsMoved of the model, where we can retrieve index of the target row.

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.

Remove item by text from QStandardItemModel in QT

How can I remove an item with text "something" from a QStandardItemModel that filled with QStandardItem items and shown in a QListView in pyqt.
I made my QStandardItemModel like code shown below:
item = QtGui.QStandardItem("something")
QStandardItemModel.appendRow(item)
You will first need to find the items with the matching text, and then remove them from the model:
model = listview.model()
for item in model.findItems('something'):
model.removeRow(item.row())
I believe the solution given only works when findItems returns a single item.
Otherwise the first call to removeRow will invalidate the next items...

flex datagrid - item renderers and skipping rows

HI,
I have a datagrid with 6 columns, each with its own item renderer. In the first column i want to be able do a check and see if the column contains some valid data, if not then i want to skip this row and go to the next. In other words i want a way to tell my datagrid to stop processing the rest of the item renderers for the current data object and skip to the next. Any ideas?
I'd say your best bet is to use the filterFunction property on ListCollectionView objects (such as ArrayCollection). This allows you to filter out the objects you don't want to show in your DataGrid before they're displayed in the grid, and should avoid any itemRenderers being processed altogether.
If you still want the "skipped" object to display in the data grid and just change how the item renderers respond to it, then you'll need to write code for that in the renderers.
Inside of the item renderer, you can access the data values of the previous columns. You should examine the listData property available in the item renderer and use your findings to configure how the item renderer should display.
You can find information about the listData here: http://livedocs.adobe.com/flex/3/langref/mx/controls/dataGridClasses/DataGridListData.html
To examine previous values, you might code something like this:
var dgListData:DataGridListData = DataGridListData( listData );
// Process all columns before the current one.
for ( var i:int = 0; i < dgListData.columnIndex; i++)
{
// Do something here to examine previous data
// If we should stop processing based on previous values
// then hide everything inside of this renderer (perhaps
// move to a state name 'empty' that has no children), else
// move to the state that renders something.
currentState = shouldSkipObject ? 'empty' : 'normal';
}
If you want more specific help writing the code inside of the item renderer, please include a sample of what the data looks like inside of the data grid as well as a description of what the item renderer should actually do.

Resources