QSqlTableModel primary key to row - c++

I have a QSqlTableModel and I want to insert and update records in it with a special form in a child-window. It's a design choice not to allow "inline editing" which I disabled on purpose.
When the user selects an entry (which can be sorted and filtered through a QSortFilterProxyModel and is presented through a QTableView), he has three options (represented by buttons): delete, edit and add.
My problem is with editing:
The parent-widget emits a signal with a given record and executes a model child-view
The child-widget prepares a form based on the record, waits for user input, validates it, creates a record and sends it back to the parent-widget.
The parent-widget takes the record and puts it into the database.
And right here is the problem! One can get the right record by row quite easily, like so:
void Parent::on_button_edit_record_clicked()
{
// Table could be sorted/filtered!
row = proxyModel->mapToSource(ui->tableView->currentIndex()).row();
QSqlRecord r = model->record(row);
emit editRecordSignal(record);
child->exec();
}
void Parent::editRecord(const QSqlRecord &record)
{
model->setRecord(row, record);
}
As you can see, I manually save the row of the record I want to update. I don't think this is a nice way to handle this. Actually it seems rather hacky to me.
What I missed was an easy way to translate a primary key to a row and vice versa. Like:
void Parent::editRecord(const QSqlRecord &record)
{
model->setRecord(model->primaryKeyToRow(record->value("id")), record);
}
Is there any way to easily do this (without having to extend the QSqlTableModel), so did I miss something or do I really need to save the row manually to achieve what I want?

Related

How to insert programmatically a value in a new row of a QtableView

I'm using a QtableView to display and edit data from a QsqlTableModel.
Everything's fine : data from a postgreSQL table is displayed, and user can edit it and save modifications.
I want to add a row when uses click on a button. I use the insertRecord method from my QslTableModel.
The row is correctly added in the QTableView.
My problem is :
I want to insert a value from a query in the first cell of this new row. (to automatically populate an unique identifier).
This is my code :
def ajoutlgn(self):
query_idNewLine = QtSql.QSqlQuery(self.db)
if query_idNewLine.exec_('SELECT sp_idsuivi+1 FROM bdsuivis.t_suivprev_tablo ORDER BY sp_idsuivi DESC LIMIT 1'):
while query_idNewLine.next():
identifiant = query_idNewLine.value(0)
#print identifiant
record = QtSql.QSqlRecord()
record.setValue(1,identifiant)
self.model.insertRecord(self.model.rowCount(), record)
The value is not inserted in the new row (but if I enter a value by hand, it works perfectly).
Nevertheless, the query is OK (as I can see with the « print identifiant » line, which returns the expected integer).
Do you see what I'm doing wrong ?
Are there other methods to insert programmatically a value in a QTableView cell?
Or do I have to use a QitemDelegate ?
Thanks for advance.
Finally I found the solution :
This line creates a record, but not a record for my QsqlTableModel
record = QtSql.QSqlRecord()
I replaced it with this one, and it works perfectly :
record = self.model.record()

Initialize record on cell enter of XamDataGrid

Assume we have a XamDataGrid with 10 columns.
Column 1 is a XamComboEditor bound to a collection in the model
This can't be changed, the data is coming from a server and the combo's collection is based on different selections within the model so it's very dynamic.
Columns 2 - 10 are just normal alpha numeric fields
The problem:
When you enter a alpha numeric and start typing the model is initialized and everything is fine. However, if you go to the very last row, the non-initialized empty one, and click on the combo editor before entering any data into any of the other fields, the combo editor is empty.
Now I am well aware of why this is happening, it's clear that this is due to the model not being initialized yet. I'm just not sure the best method to fix this.
I would hope there is a property on the XamDataGrid that adjusts when the record is initialized but I've searched the Infragistics documentation and examples and I can't find anything.
There are events for:
EditModeStarting
EditModeStarted
EditModeEnding
EditModeEnded
private void OnCellEditModeStarting(object sender, EditModeStartingEventArgs args)
{
if (args.Cell.Field.Name == "TotalQuantity")
{
DataRecord record = args.Cell.Record;
if (record == null)
return;
MyGridEntry item = record.DataItem as MyGridEntry;
// Do a thing
}
}
You can also respond to the InitializeRecord event. It can fire for multiple reasons, such as cell editing, so check the state of your row model when responding to it. All these events are on the parent grid, not any FieldLayouts or Fields.
<i:XamDataGrid x:Name="myGrid"
InitializeRecord ="OnInitializeRecord"
EditModeStarting ="OnEditModeStarting">

QTreeView update column number

I'm currently working on a customization of QAbstractItemModel an I encountered a problem. The model itself works fine so far, but I have problems, if i try to display it with QTreeView.
The Model itself is able to change its column number on its own, depending on it's data. But the view will never update the number of columns shown, only their content.
I did overload insertColumns:
bool MyModel::insertColumns(int column, int count, const QModelIndex &parent)
{
bool success;
beginInsertColumns(parent, column, column + count - 1);
success = this->getItem(parent)->insertColumns(column, count);
endInsertColumns();
return success;
}
I experimented a little bit and found out, that if I reset and set the View each time, it will display the right number of columns:
connect(this->model, SIGNAL(columnsChanged()), this->ui->treeView, SLOT(reset()));
But there has to be another way to do this. I'm looking for a function, that will just tell the View that the column-count has changed. But the only one i found (QTreeView::columnCountChanged(int oldCount, int newCount)) is protected...
here are some other signals that treeview's mode can give out these should all be triggered if your inserting a column so just use the appropriate one and connect to update on your table view, although i would have thought that if your changing the underlying model the view should update, and if it doesnt reset the model
ui->treeView->model()->layoutChanged();
ui->treeView->model()->dataChanged();
ui->treeView->model()->columnsInserted();
ui->treeView->model()->columnsMoved();

Hide text in column as password dots in QtTableWidget

I have table (created by QTableWidget).
My table has 3 columns
# | user | pass
Text in user and in password is visible i.e "user", "password"
I want to hide text in pass like:
"********" < means "password"
In QLineEdit is good option called "echomode" but it is only for QLineEdit.
I can manually replace text for *, but how can i read this text later from a table (in class) ?
Better than ** will be dots. (like echomode -> password)
Regards
I would set the table item text to "*****", and store the real password as an item data with specific role. For example:
// Get the password item of first row
QTableWidgetItem *passwordItem = tableWidget->item(0, 2);
passwordItem->setText("*****");
passwordItem->setData(Qt::UserRole, "the_actual_password");
Extracting the actual password could be made in the similar way:
QString actualPassword = passwordItem->data(Qt::UserRole).toString();
You create a QStyledItemDelegate that you set on the column of passwords in the view (not the model, setItemDelegateForColumn()). When asked to create the editor (createEditor()) it should create a QLineEdit set to obscure the echo. You can have the delegate look at the value in another column before deciding whether to obscure the password.
http://www.qtcentre.org/threads/55315-How-can-i-have-echomode-in-QtableView-for-password-column
It's a bit old but I would like to warm it up, because it wasn't working that easily for me with Qt5.
The proper way to do this is to use a QStyledItemDelegate and override the paint method. But it seems so, that you've to paint on the widget stored in the option view (I looked into Qt's source).
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
opt.widget->style()->drawItemText(painter, opt.rect, Qt::AlignLeft, opt.palette, true, "*****");
When I do not do it in this way I get a lot of strange side effects when table cell's selection changes.

list of SelectedRows in QTableWidget

I have problem getting selected rows from QTableWidget. I have table like this:
[id] [ key ]
0 test
1 pass
I want to get every row's key values. I tried QTableWidget->selectedIndexes(); but it says it's protected and I can't access that. When I tried QTableWidget->SelectionModel->selectedIndexes, I don't know how to loop through list and get the key values. Do anyone know better way how can I do it?
Regards.
I'm assuming that you set the selection behavior of your table widget to select rows.
You can always access the so-called "selection model" of any item view/widget. QTableWidget inherits from QAbstractItemView, which gives you access to this special model. This model can tell you the selected rows as a list of QModelIndex, which can then tell you the row. Once you've got them, you can access the table content, in your case the text in the column with index 1 (key column).
static const KEY_COLUMN = 1;
QList<QString> selectedKeys;
QItemSelectionModel *selectionModel = ui->tableWidget->selectionModel();
foreach(QModelIndex index, selectionModel->selectedRows())
selectedIDs << ui->tableWidget->item(index->row(), KEY_COLUMN)->text();
Because you are using QTableWidget, you probably want to be calling selectedItems(). Your results will be based on what you have set the selection behavior to, via setSelectionBehavior()
When you have a list of items, you can specifically get the second column item (if it wasn't selected already):
QTableWigetItem *keyItem = table->item(anItem->row(), 1);
QString val = keyItem->text();