Auto update selection when a QStandardItem is disabled - qt

I use Qt 5.6 and a QStandardItemModel filled with QStandardItem to display a data table.
Some items are enabled, some are not.
Only enabled items can be selected (this is the normal behavior).
But when the data are updated, some items enabled state can change, and this is the source of my problem. Consider the following scenario :
1 an item is enabled
2 the user select it
3 the item is selected
4 the data are updated, the item is now disabled
5 the item remain selected, despite it is disabled
And now, the user can interact with a disabled item : open context menu, edit it...
It there some "update" method in Qt model/view framework that I can call to update the selected state after a flag change ?
Or is there any simple (and generic) way to solve this problem, for all my item views ? (not all are tables, not all are based on QStandardItem)
Thanks

EDIT: This does not seem to work as the enabled property is no data but a flag and editing this should not trigger the named signal. Hang on!
What about connecting the signal
void QStandardItemModel:itemChanged(QStandardItem * item)
with some helper code like
void fixSelection(QStandardItem * item)
{
if (item.isEnabled()) {
// remove item from selection model of view...
}
}
See also here for some information about QItemSelectionModel.
You may also think about clearing the whole selection of the model if the data is modified. This will save you this extra amount of work. I do not know which action might disable some items under selection and which followup action which wants to work on the previously taken selection.

Related

Uncheck a QPushButton with autoExclusive

Ubuntu 22.04, Qt 6.4.0.
I have some QPushButtons that belong to the same parent.
I set all of them with checkable and autoExclusive properties to true.
The doc about the latter states:
If auto-exclusivity is enabled, checkable buttons that belong to the
same parent widget behave as if they were part of the same exclusive
button group. In an exclusive button group, only one button can be
checked at any time;
Emphasis is mine.
From what I understand, they say that only one button "can" be checked. This means that more than one button can never be checked. But it allows to no buttons checked. Otherwise I was expecting something like: "only one button must be checked at any time".
Anyway, my problem is I cannot uncheck a button after it was checked.
It remains checked no matter I click on it.
I also tried programmatically:
ui->myCheckableButton->setChecked(false);
no way.
Disabling the autoExclusive property I can disable them, but of course is not the intended behavior.
What am I missing here?
How to uncheck a button when autoExclusive property is active?
Sadly, you are experiencing the intended behavior of Qt.
The source code for QAbstractButton::setChecked contains lines that makes it clear a button belonging to an exclusive group cannot be unchecked (unless it is the only button in that group).
if (!checked && d->queryCheckedButton() == this) {
// the checked button of an exclusive or autoexclusive group cannot be unchecked
#if QT_CONFIG(buttongroup)
if (d->group ? d->group->d_func()->exclusive : d->autoExclusive)
return;
if (d->group)
d->group->d_func()->detectCheckedButton();
#else
if (d->autoExclusive)
return;
#endif
}
d->queryCheckedButton() returns nullptr if only 1 button belongs to the group. The rest is straight forward:
If Qt was compiled to use button groups and the button group is exclusive, do not uncheck the button (return; instead).
Otherwise, if the button itself is autoexclusive, do not uncheck it.
I checked the exclusive property of QButtonGroup, the description makes the behavior clear:In an exclusive group, the user cannot uncheck the currently checked button by clicking on it; instead, another button in the group must be clicked to set the new checked button for that group..
It is unfortunate the description for QAbstractButton does not contain that sentence too, although I will say it is not incorrect since 0 buttons may initially be checked (then, when 1 is checked, it will never allow to uncheck everything, which is the missing part).
Your modified sentence using must would have a meaning in the lines of:When using the QAbstractButton class, you must make sure not to allow more than 1 button to be checked.There are several instances of sentences built this way and AFAICT, all of them describe things you must do for your implementation to work.
The good news in all of that is that your solution of disabling the autoExclusive property seems no have no impact whatsoever on the signals emitted by the button.You may for instance create a subclass of QPushButton (if that is what you are using), remove the autoExclusive property, first thing in the mousePressEvent and re-enable it last thing in the mouseReleaseEvent.
Alternatively, you can make your button non autoexclusive and connect signals when it is toggled (to true) to unckeck the other buttons.This is probably how I would do it.

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.

Accept edited wigets with QDataWidgetMapper

I'm making a small application that represents a to-do list.
The list is stored in a cusom model (derived from QAbstractItemModel) and is displayed in a QTableView.
I have also a custom widget (TaskDialog) that is used to browse and edit tasks from the list. The children of the TaskDialog are mapped to the model with a QDataWidgetMMapper.
On the task dialog I have also buttons that allow browsing through all the tasks in my to-do list (QDataWidgetMapper::toPrevious() ...).
The problem is that if I'm editing a task in the TaskDialog (e.g. the tasks name) and then browse to another task, the new edited enty isn't set in the model.
But if I edit something in the TaskDialog, then first change the focus to an other child widget of the TaskDialog and then press one of the browsing button, than the changes are written to the model.
How can I achive that widgets that are in a editing mode are accepted and written to the model.
I also tried the example of QDataWidgetMapper from Nokia. There it works perfectly. But they use a QStandardItemModel.
Best regards
Luke
I found a solution:
The submit policy of the QDataWidgetMapper has to be set to QDataWidgetMapper::ManualSubmit.
Then allways when I browse to a new item (i.e. one of the browse buttons is pressed) i submit the changes with QDataWidgetMapper::submit().

QTableView: Best way to change activation-trigger to double-click

In my application, I have one tableview of items, and a side-panel "preview":ing the latest selected item.
I want clicking on an item to change the selection, and double-clicking to cause a "run"-action to be performed. More specifically, I want the "run"-action (including key-navigation and pressing enter) to be bound to the "activation" of the item in the table-row.
My problem is; single-clicks does not only change the selection, but fires the "activated" signal on the item. I would like to tweak it such that:
Navigation Keys, Single Mouse Click: Selection-change, update preview-panel
Enter Key, Double Mouse Click: Activate/run/open action triggered.
Is there a nice clean way to do it, or are overriding the onclick/doubleclick events my best option? Or is there some other tabular list-widget better suiting my needs?
I would connect the slot for the preview action to the currentChanged() signal of the table view's selectionModel(). This covers single clicks and key navigation.
Then there's two options for the double clicks and Enter key presses:
Subclass your tableview, override doubleClickEvent() and keyPressEvent() and fire your custom signal in there, with maybe the model index or something else as an argument. Then just connect your run method to your own signal as you have full control over when it is fired.
If you don't want to subclass, you can use the installEventFilter() mechanism.
Either I'm getting your approach wrong or I'm too tired, but if you want to trigger a run event you should avoid the activated signal completely. Set the signal slot mechanism so that your double click and Enter key press event trigger your run() function, and then the single click/nav buttons should trigger the 'activated' slot which will return your index in the tableview.
I'm pretty certain Qt wants you to be explicit about which signal points to which slot or it'll ignore it or point to a default.

Flex ComboBox user choice reset

To be more descriptive here's a live example:
http://interklub.biz/CTPonLine.html
In last column there's a ComboBox with some values.
When user choose an option in ComboBox from first row and then scroll down the first choice disapears (comes back to default state).
There's something more strange, earlier I've tried to apply a one more ComboBox in additional column, with highly dynamic values (completly different for different rows), but with after same action (scroll down and then scroll down) values dataProviders from different ComboBox were switch.
It looks like you're not initializing your item renderer properly--when the renderer is reused, it's keeping its old value rather than updating from your data.
You should be able to resolve this by doing one of the following:
binding the item renderer's selectedValue to some property of its data element
overriding set data() to update the control for the current data
acting on the dataChange event and updating there
See Adobe's Working with Item Renderers for more.

Resources