[solved] Newbie is confused.How to add dynamic data to TableView and parse through it send data to c++
-
@p3c0
Any hint or example on how to update the data? Thanks a lot -
@vishnu Make use rowsInserted of rowsRemoved signals. Connect them to their respective slots as shown previously for
dataChanged
. -
@p3c0
I have already added 3 rows with default value. when ever I change default value to someother value. I am not getting the updated value to c++ side.
QObject::connect(model,SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), &myclass,SLOT(onDataChanged(QModelIndex,QModelIndex,QVector<int>)));
This is not working? As you said since I am not updating the model, just appending and removing the rows.I feel like there has to be done more in my QML part.May I know what is wrong or missing in my Model and View (QML) ?Thanks -
I have already added 3 rows with default value. when ever I change default value to someother value. I am not getting the updated value to c++ side.
how are you changing the default value ?
-
@p3c0
I can change my default values because my delegate is a TextInput.TableViewColumn { role: "tool" title: "Tool" width: 80 delegate: TextInput { anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter renderType: Text.NativeRendering validator: IntValidator {bottom: 0; top: 1;} text: styleData.value } }
-
@vishnu Im asking how do you change the items added in
ListModel
? That signal will only be updated only when you update the existing items in the model.
For eg:ListModel { id: myModel ListElement { name: "abc" age: 12 } onDataChanged: console.log("Changed") } //updating the list model myModel.set(0, { "name" : "xyz" } )
So here the signal dataChanged will be triggered and hence the slot onDataChanged in QML will be invoked. Same will work for C++ slot too.
Now in your earlier code you are just adding and removing the rows so those signals (mentioned earlier) will be triggered.
-
@p3c0
I am no where doing that kind of updating. I am assuming that ListModel.append method does updating the model as well as view.Button{ id:addNewRowButton text: "ADD" onClicked: { setTableModel.append({"x_position": 0, "y_position":0, "z_position":0, "velocity":0, "acceleration":0, "deceleration":0, "tool":0, "tracking_x":0, "tracking_y":0, "tracking_z":0} ) } }
-
@vishnu No that is not updating. That wont invoke the data changed signal.
As said earlier if you useappend
orremove
use rowsInserted or rowsRemoved signals repectively. -
@p3c0
you are right. This works perfect. I can see the data in c++ when ever a new row is added.QObject::connect(model,SIGNAL(rowsInserted(QModelIndex,int,int)), &tcpCommunicationPort,SLOT(onRowsInserted(QModelIndex,int,int)));
But when one of item in the Row is changed I can't see the new data in c++.So that means only Set/setproperty of ListModel will invoke the data changed signal. That mean My qml code is wrong if i want dataChangedsignal.
I changed my TableView like this:TableView{ id:setTableView objectName: "setTableView" model: { setTableModel.set(0,{"x_position": 0, "y_position":300, "z_position":500, "velocity":0, "acceleration":0, "deceleration":0, "tool":0, "tracking_x":0, "tracking_y":0, "tracking_z":0}); setTableModel.set(1,{"x_position": 0, "y_position":400, "z_position":800, "velocity":0, "acceleration":0, "deceleration":0, "tool":0, "tracking_x":0, "tracking_y":0, "tracking_z":0}) }
Now the entire view if gone. I cannot add anymore rows.That means what I have done is wrong.But don't know what to do.
Also If the user changes some value in any of the times.how can i know which value is changed? TableView has onClicked signal I can get the current row ,and delegate has access to the properties styleData.row - the index of the row ; styleData.column - the index of the column. Don't know how to make use of them.
Can you please tell me what exactly have to be done on my QML side. Should i change my delegate or View or Model code?Thanks. -
@vishnu Keep your code with
append
andremove
as it is. It just adds and removes the rows. Now to update the already added elements inListModel
useset
.
So,append -> rowsInserted remove -> rowsRemoved update i.e set -> dataChanged
-
@p3c0
I got the meaning what your saying but Where and how exactly I should do that set.
For eg: should I do like thisButton{ id:addNewRowButton text: "ADD" onClicked: { setTableModel.append({"x_position": 0, "y_position":0, "z_position":0, "velocity":0, "acceleration":0, "deceleration":0, "tool":0, "tracking_x":0, "tracking_y":0, "tracking_z":0} ) //ofcourse index is not defined, May be I make a property and increment it when even I add new row. setTableModel.set(index,{"x_position": 0, "y_position":0, "z_position":0, "velocity":0, "acceleration":0, "deceleration":0, "tool":0, "tracking_x":0, "tracking_y":0, "tracking_z":0}) }
How about defalut values where should i set them?
Is It in Tableview:this went totally wrong.id:setTableView objectName: "setTableView" model: { setTableModel.set(0,{"x_position": 0, "y_position":300, "z_position":500, "velocity":0, "acceleration":0, "deceleration":0, "tool":0, "tracking_x":0, "tracking_y":0, "tracking_z":0});
-
@vishnu See
set
is used to update theListModel
- since you have used
TextInput
to allow user to update the data you need a way to update the model from this. This can be done inonAccepted
handler ofTextInput
So to sum up, for eg:
delegate: TextInput { anchors.fill: parent text: styleData.value onAccepted: { myModel.set( styleData.row, { title: text } ) //updates the role name "title" with updated text of TextInput } }
-
@p3c0
Thanks for the explanation.Now I am not able to know which role is changed.
As you said I did like this in QML.TableViewColumn { role: "tracking_z" title: "Tz mm" delegate: TextInput { validator: IntValidator {} text: styleData.value onAccepted: { setTableModel.set(styleData.row,{"tracking_z":parseInt(text)}) } }
For each column view I have a separate delegate because the IntValidator differs for each role.When ever there is datachanged this SLOT is called successfully.
void TCPCommunicationPort::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { qDebug() << "row changed"<<topLeft.row();//getting the row number qDebug() << "column changed"<<topLeft.column();//this is always zero.I don't know why. QVariant newValue = topLeft.data(roles[0]); qDebug() << "Data Changed in cpp"<<newValue.toInt();//Getting the value where ever i change in the tableView. //How to get the role name for which corresponding value is changed. }
Main problem is how to go the position where I have saved the tabledata to a position in Qbytearray.Can I access this model in onDataChanged SLOT?
QAbstractListModel *model = qvariant_cast<QAbstractListModel *>(qmlmodel); //convert to QAbstractListModel
Atleast I will try to read the whole new data(ofcourse it is insufficient) but my purpose is served. -
-
Can I access this model in onDataChanged SLOT?
-Yes. TheQModelIndex
also returns the model. UsetopLeft.model()
-
How to get the role name for which corresponding value is changed.
-Once you get the model using above method useroleNames()
.
topLeft.model()->roleNames()[roles[0]]
. This will give exact role name. -
Atleast I will try to read the whole new data(ofcourse it is insufficient) but my purpose is served.
-Ok. Would't that be unnecessary ?
-
-
@p3c0
perfect.served my purpose :) but inefficient solution :(.- Atleast I will try to read the whole new data(ofcourse it is insufficient) but my purpose is served.
-Ok. Would't that be unnecessary ?
because I have to send the data by array of char and I have saved the data from Tableview to char array like this:
char m_senddataBuffer[3256]={0};//I know the max size char *positionValue; positionValue = &m_senddataBuffer[56];//created a pointer to a particular position. int count=0; for (int i = 0; i<rows; i++) { for(int j = model->roleNames().count()-1; j>=0; j--) { //get the roles count QVariant rowData= model->index(i, 0).data(j); //get the actual data using roles QString rolename = model->roleNames()[j]; int value =rowData.toInt(); //qDebug()<<" row"<<i << "role name"<<rolename<< "value "<<value; if(!QString::compare(rolename,"x_position",Qt::CaseInsensitive)) { qDebug()<<"x_position is running"<<++count; value=value*1000; //int to char array *(positionValue++) = (value) & 0xFF; *(positionValue++) = (value >> 8) & 0xFF; *(positionValue++) = (value >> 16) & 0xFF; *(positionValue++) = (value >> 24) & 0xFF; } //and so on...
I just copy pasted the same code in onDataChanged SLOT. I thought of writing a function readModel(QAbstractItemModel model). but the typecased model is of type QAbstractListModel.So I have done like this. Any improvements can be done. Please let me know.
- Atleast I will try to read the whole new data(ofcourse it is insufficient) but my purpose is served.
-
-
@p3c0
reading the whole model when there is just one data has to be changed. -
@vishnu Right that is why we have
dataChanged
:)