How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?
-
I need to get a signal from a
QTreeWidgetthat its selection has been changed by the user. This includes the user clicking on an item in the widget, or using the keyboard to change the selection.QTreeWidgetdoes provide the signalitemSelectionChangedbut it fires anytime the selection changes for any reason, including it being changed programmatically, so it doesn't fulfill my requirements.How can I accomplish this?
-
I need to get a signal from a
QTreeWidgetthat its selection has been changed by the user. This includes the user clicking on an item in the widget, or using the keyboard to change the selection.QTreeWidgetdoes provide the signalitemSelectionChangedbut it fires anytime the selection changes for any reason, including it being changed programmatically, so it doesn't fulfill my requirements.How can I accomplish this?
@Guy-Gizmo
Qt does not offer to distinguish foritemSelectionChanged().-
Create some state variable during clicks/key presses in a
QTreeWidgetsubclass so that you know it has come from input. MaybeQTreeWidget::itemPressed()helps. Not desirable. -
Could you use
eventFilter()to recognise comes from input? Probably same undesirability.
-
-
@Guy-Gizmo
Qt does not offer to distinguish foritemSelectionChanged().-
Create some state variable during clicks/key presses in a
QTreeWidgetsubclass so that you know it has come from input. MaybeQTreeWidget::itemPressed()helps. Not desirable. -
Could you use
eventFilter()to recognise comes from input? Probably same undesirability.
@JonB I thought about using mouse and key events to set a flag, but I worry that this will catch situations that I don't want it to. Here's one potential example: the user presses Control+Z / Command+Z while the text field is focused. This will trigger code that will programmatically change its selection if that's the last undoable action, but it shouldn't cause this new signal to fire.
I can try to be careful and catch all situations that are triggered by user action, but the truth is that only
QListWidgetreally knows when it's changing the selection via user action as opposed to something else! But I'm trying to find a solution that does not involve basically reimplementingQTreeWidgetfrom scratch. -
-
@JonB I thought about using mouse and key events to set a flag, but I worry that this will catch situations that I don't want it to. Here's one potential example: the user presses Control+Z / Command+Z while the text field is focused. This will trigger code that will programmatically change its selection if that's the last undoable action, but it shouldn't cause this new signal to fire.
I can try to be careful and catch all situations that are triggered by user action, but the truth is that only
QListWidgetreally knows when it's changing the selection via user action as opposed to something else! But I'm trying to find a solution that does not involve basically reimplementingQTreeWidgetfrom scratch.@Guy-Gizmo
I do not disagree with you, but I do not think Qt code offers you a way to distinguish a "user initiated" selection change versus a programmatic one. I think it will be tricky to do, trying to recognise/cover all input cases.If I had to do this --- and if no one else here offers an alternative --- I would have a look through the Qt source code to see if I could spot where the signal is emitted for programmatic versus user invocation and whether I could lever that. If you say
QListWidgetgives you what you want but notQTreeWidget, is there a useful difference you can spot in the code? -
Hi,
Can you explain what differences comes from a user initiated selection and a programmatically made ?
-
I may be completely wrong but wouldn't QSignalBlocker - used in all programmatic changes - be the way to prevent the emission of unwanted signals?
-
Hi,
Can you explain what differences comes from a user initiated selection and a programmatically made ?
@SGaist said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
Hi,
Can you explain what differences comes from a user initiated selection and a programmatically made ?
A user initiated change would come from the user clicking items in the QTreeWidget, or using keystrokes to select items. The change in selection would be handled internally by QTreeWidget.
A programmatic change would be my own code calling a function like
QTreeWidget::clearSelectionorQTreeWidgetItem::setSelected.It is analogous to two signals in QLineEdit, where
QLineEdit::textChangedfires any time its text changes for any reason, andQLineEdit::textEditedfires any time the text is changed due to user action specifically. It's too bad that more widget classes do not include signals like this that explicitly fire only in response to user-driven changes. -
I may be completely wrong but wouldn't QSignalBlocker - used in all programmatic changes - be the way to prevent the emission of unwanted signals?
@DerReisende said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
I may be completely wrong but wouldn't QSignalBlocker - used in all programmatic changes - be the way to prevent the emission of unwanted signals?
This is my current strategy, which works for the time being. But I think it's brittle: I'm not aware of absolutely every function I can call on QTreeWidget that might end up changing its selection somehow, and so this makes it easy for me to write bugs without realizing it.
-
@SGaist said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
Hi,
Can you explain what differences comes from a user initiated selection and a programmatically made ?
A user initiated change would come from the user clicking items in the QTreeWidget, or using keystrokes to select items. The change in selection would be handled internally by QTreeWidget.
A programmatic change would be my own code calling a function like
QTreeWidget::clearSelectionorQTreeWidgetItem::setSelected.It is analogous to two signals in QLineEdit, where
QLineEdit::textChangedfires any time its text changes for any reason, andQLineEdit::textEditedfires any time the text is changed due to user action specifically. It's too bad that more widget classes do not include signals like this that explicitly fire only in response to user-driven changes.@Guy-Gizmo said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
@SGaist said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
Hi,
Can you explain what differences comes from a user initiated selection and a programmatically made ?
A user initiated change would come from the user clicking items in the QTreeWidget, or using keystrokes to select items. The change in selection would be handled internally by QTreeWidget.
A programmatic change would be my own code calling a function like
QTreeWidget::clearSelectionorQTreeWidgetItem::setSelected.It is analogous to two signals in QLineEdit, where
QLineEdit::textChangedfires any time its text changes for any reason, andQLineEdit::textEditedfires any time the text is changed due to user action specifically. It's too bad that more widget classes do not include signals like this that explicitly fire only in response to user-driven changes.I meant with regard to what should happen in your application when the selection comes from the user and when it's done programmatically.
-
@Guy-Gizmo said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
@SGaist said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
Hi,
Can you explain what differences comes from a user initiated selection and a programmatically made ?
A user initiated change would come from the user clicking items in the QTreeWidget, or using keystrokes to select items. The change in selection would be handled internally by QTreeWidget.
A programmatic change would be my own code calling a function like
QTreeWidget::clearSelectionorQTreeWidgetItem::setSelected.It is analogous to two signals in QLineEdit, where
QLineEdit::textChangedfires any time its text changes for any reason, andQLineEdit::textEditedfires any time the text is changed due to user action specifically. It's too bad that more widget classes do not include signals like this that explicitly fire only in response to user-driven changes.I meant with regard to what should happen in your application when the selection comes from the user and when it's done programmatically.
@SGaist said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
I meant with regard to what should happen in your application when the selection comes from the user and when it's done programmatically.
I'm using the tree view to allow the user to select an item from a big categorized list, and I have a custom undo system that needs to make entries in the undo history corresponding to when the user selects something in this list, but avoid making entries of non-user changes.
-
Then it seems sensible to block the selection model's signals when you undo things.
Out of curiosity, are you using Qt's undo framework ?
-
Then it seems sensible to block the selection model's signals when you undo things.
Out of curiosity, are you using Qt's undo framework ?
@SGaist said in How to get a signal from QTreeWidget when its selection is changed by user action, but not programmatically?:
Out of curiosity, are you using Qt's undo framework ?
Not this time. I ended up needing a lot of custom behavior so I made my own.