Stop single QModelIndex from being update - qt

I have a QTreeView with data that changes over time, with a dataChanged signal being emitted in the QAbstractItemModel every second. The items in the QTreeView can be edited as well, but when a editor is opened for a certain item the editor string is updated while I edit is, which is very annoying. Any way to prevent an editor to be updated with the new values?

Do you use your own model with QTreeView? In this case you overwrite it and not return any data for Qt::EditRole. If it is not convenient for you (you want to have the current data in the field when you begin to edit it), then you could create your own QItemDelegate/QStyledItemDelegate and implement some custom logic there: make it so the widget is not updated with new value, when it has focus, for example.
Althought I might be missing something, and there is an easier way to do this.

Related

How did I retrieve changes in the content of all text edit boxs in a widget

Now, I have a widget that used for conguring some parameters, There were some QlineEdit with default value and a save button on this widget. People may change the content of QlineEdit. And click the save button, so that the modified parameters can take effect. Here is my question:
How do retrieve changes in the content of all text line edit in this QWidget?
Once I know which edit content has changed, I can judge whether the modified values is legal, and then let the change take effect.
Can anyone give me some ideas?
OS: Windows10
QT: qt 5.9.0
For this situation, It's better to do one more step before manually validating the user's input. The step is to limit the user to enter invalid settings. If your setting value is a number, use QSpinBox or QDoubleSpinBox for floating-point values. If you want to let the user select from multiple predefined values, like gender(Male, Female), use QComboBox or QRadioButton and so forth. Here is the list of Qt's widgets. So bear in mind, using QLineEdit for all of the inputs is not a good idea.
If your input is something more complex, you can use validators. For getting the idea see this question.
At last, you connect the save button's clicked signal to the slot defined in your widget class using Qt's signals and slots mechanism and get values from all of your inputs and check them, and if everything is OK, apply them to your system.

Add a delete Button to each Item in QListView

Is it somehow possible to add to each Item in a QListview a Button which is deleting the Object onClick? As shown in the following Picture:
EDIT: As I'm new in QT it would be nice to have some example, to understand it better. And as it seems there are three different Ways? What will be the best? Do use a QAbstractItemView?
Yes. You'll need to use:
QAbstractItemView::setIndexWidget ( const QModelIndex & index, QWidget * widget )
QListView inherits QAbstractItemView and when you're trying to customize list/tree views that's usually the place to look. Be careful though, without a delegate this doesn't scale very well. Check out this thread: http://www.qtcentre.org/threads/26916-inserting-custom-Widget-to-listview
You can also go for a generic approach that can work on variety of containers, including the underlying model of your list view.
Each item in the list has a requestRemoval(Item*) signal and a removeMe() slot, connect the X button to the removeMe() slot in each item constructor, in removeMe() you emit the requestRemoval(this) signal, which is connected to a removeHandler(Item*) slot in your "parent" object upon creation of that item, which receives the pointer of the item which has requests deletion, and removes it from the underlying container being used.
Basically, pressing the remove button causes that particular item to send a pointer of itself to the parent's remove handler which removes that entry.
EDIT: Note that this is a generic approach, as noted in the comments below it can be applied without signals and slots as well, and even though it will work it is not the most efficient solution in your particular case.

QListView losing selection on edit

I have a QListView pulling data from a QSQLTableModel.
Upon a user clicking an 'Add' button, I add a new item and open it for editing:
QSqlTableModel *tblModel= qobject_cast<QSqlTableModel *>(ui->listView->model());
if(tblModel->insertRow(tblModel->rowCount()))
ui->listView->edit(tblModel->index(tblModel->rowCount()-1, 1));
But once the user is done editing the new value, the selection of listView is lost. I can't find a signal on QListView or QSQLTableModel to handle when and edit has finished for me to 'restore' the selection.
Is there a way I can make sure the selection is kept?
An excerpt from edit() function documentation:
Note that this function does not change the current index. Since the
current index defines the next and previous items to edit, users may
find that keyboard navigation does not work as expected. To provide
consistent navigation behavior, call setCurrentIndex() before this
function with the same model index.

Show Editors for All Cells in Row in QTableView

I would like to display editors for all cells in a row when a user begins editing any cell in a QTableView. I have made several attempts but I cannot obtain the correct behaviour.
The only way to open multiple editors is by QAbstractItemView::openPersistentEditor() - attempts to successively call QAbstractItemView::edit() results in only one editor.
I cannot use signals such as clicked() and doubleClicked() from QAbstractItemView to invoke editing, because then it would not respect the edit triggers of the view.
There appears to be no "editing complete" signal. I would like to connect this signal to a slot that calls closePersistentEditor() for cells in the editing row.
Any suggestions would be appreciated.
Thanks!
I hate to be the bearer of bad news, but I can't think of any easy way to do what you want. I can think of a couple of options, each more painful than the last:
You could create a delegate that always shows the editors, and when the user changes the selected row, set that delegate for the newly selected row, and the original delegate for the deselected row.
You could try inheriting from the table view, and overriding the behavior for drawing the appropriate items for everything in the given row. I have no idea how hard this would be, but I doubt it would be trivial.
You could create your own view to display the model. I've never done this, and I'd hate to think about all that would be required to "complete" support the models. However, to match with one specific model, you might be able to get away with it.

How can I tell a QTableWidget to end editing a cell?

I'm showing a popup menu to select some values in a QTableWidget. The lowest item is a "Modify list" entry, when I select it a new window should automatically appear and the QComboBox should vanish and the cell return to a Qt::DisplayRole state.
Now Qt has all those nice API-calls like QTableWidget.edit() and QTableWidget.editItem(), what I'm really looking for is a QTableWidget.endEditing(), preferably without specifying the index of the cell, though I could get that using this call:
table.currentIndex()
… but I don't know if I can guarantee that the current cell is the cell being edited at all times.
Is there an API to close those kind of editors?
QTableWidget inherits 19 public slots from QWidget. One of those is setDisabled(), which should disable input events for that widget and all of its children.
I would try:
table.setDisabled( true );
table.setDisabled( false );
Although you said it does not work for you, there is an alternative method:
If you don't like that (the table loses focus, I believe), you can try using EditTriggers. For example:
table.setEditTriggers( QAbstractItemView::NoEditTriggers );
table.setCurrentItem(None) is what worked for me. (Don’t forget to block signals if you use some cellChanged/itemChanged slot function.)
This is with PyQt. For C++ I think replace None with NULL.
You may be able to use QTableWidget.closePersistentEditor() to close the editor. However, QAbstractItemView.closeEditor() may be closer to what you want, especially since you seem to be comfortable with the QModelIndex-based API and are already using a custom editor widget.
In my case, none of the options worked properly. So, I figured: I need to send the key press event to the line edit itself. The following works with QTreeView but probably does work with any other view or widget that opens a line edit to edit cells.
QWidget* editingWidget = treeView->findChild<QLineEdit*>();
if(editingWidget)
{
QKeyEvent keyPressEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
QApplication::sendEvent(editingWidget, &keyPressEvent);
QApplication::processEvents(); // see note below
}
In my case, I wanted to start editing another field directly when having finished editing one item. That is why I put processEvents there, in most cases you can probably remove that line.
PS: yeah, it's C++, but should be easily adaptable to Python. I found this thread when I searched for the C++ solution, so maybe it helps anyone else, too.
I can't speak for list widgets. But, I got here trying to do something similar.
I was double-clicking a cell, and based on the column, bringing up a sub-form with a list, then when that was closed move to the next appropriate column based on the value selected.
My problem was I could get the value in the cell and "select" the next appropriate cell, but the original cell stayed selected in edit mode!
It finally dawned on me that my double-click was selecting the cell, ie. editing.
A single-click selects the cell but doesn't open an edit mode.
Side note: Never could get that sub-form to act truly modal, so I created a loop in the calling form: while the sub form was visible, with the only code being app.processEvents()

Resources