is a Switch appropriate here...?
-
Hi all -
I'm implementing a control system. Several pieces of equipment have on/off switches in their display. At first, it seemed like a (customized) Switch was ideal for this, but now I'm not so sure. When the user clicks one of these controls, I'd like the series of events to occur:
- an on/off message is formed and delivered to the controller via a HTTP POST command.
- If get a reply to this command that it was successful, I would then (and ONLY then) update the display to show the "on" status, and I would change the checked property of the switch.
- If my POST was not successful, I get a 403 response, and I can display an error message. The switch's checked property (and display) should remain unchanged.
The more I've been experimenting, the more I question whether I really want to use a switch (or, really, any AbstractButton) here. It seems like the automatic interplay between a clicked() and the checked state is different from what I want.
So...is there some way to partially disable the automatic updating of the checked property (and ensuing display change), or should I just implement my own control with a few rectangles?
Thanks...
-
@GrecKo said in is a Switch appropriate here...?:
Calling your c++ switchIsOn function will prevent the checked property from being updated if the powerState changes.
OK, maybe I didn't understand your solution as well as I thought.
My switchIsOn() function doesn't really do anything; it just returns a bool. If I use the binding you posted, what do you expect the toggleOrder() to do?
To reiterate the data flow:
- user clicks the switch
- app sends a message to the controller
- controller sends a response (either OK or error)
- upon receiving this response, client sends a GET request
- upon getting the GET response, client updates the model, including the power state
It seemed to be working the way I had it, but maybe there's a hidden glitch I can't see. So, do I still need a toggleOrder/switchIsOn function?
Thanks...
@mzimmers don't underestimate you, you got most of it the first time!
You correctly replaced my vague toggleOrder with your actual message sending (
sendSwitchChange
).
But I don't think you needed to introduce yourswitchIsOn
function.
What I had in mind is:Toggle { id: cardSwitch checked: vspCard.powerState === EquipmentNS.POWER_ON onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(() => vspCard.powerState === EquipmentNS.POWER_ON) } }
Or to factorize it a little:
Toggle { id: cardSwitch function switchIsOn() { vspCard.powerState === EquipmentNS.POWER_ON } checked: switchIsOn() onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(switchIsOn) } }
Having the function in QML allows the binding to keep being updated if the powerState changes. In c++ your function won't be called again if the NOTIFY signal of the powerState property is emitted.
-
Hi all -
I'm implementing a control system. Several pieces of equipment have on/off switches in their display. At first, it seemed like a (customized) Switch was ideal for this, but now I'm not so sure. When the user clicks one of these controls, I'd like the series of events to occur:
- an on/off message is formed and delivered to the controller via a HTTP POST command.
- If get a reply to this command that it was successful, I would then (and ONLY then) update the display to show the "on" status, and I would change the checked property of the switch.
- If my POST was not successful, I get a 403 response, and I can display an error message. The switch's checked property (and display) should remain unchanged.
The more I've been experimenting, the more I question whether I really want to use a switch (or, really, any AbstractButton) here. It seems like the automatic interplay between a clicked() and the checked state is different from what I want.
So...is there some way to partially disable the automatic updating of the checked property (and ensuing display change), or should I just implement my own control with a few rectangles?
Thanks...
@mzimmers said in is a Switch appropriate here...?:
should I just implement my own control with a few rectangles?
I'd vote for this solution.
-
@mzimmers said in is a Switch appropriate here...?:
should I just implement my own control with a few rectangles?
I'd vote for this solution.
Not that pretty but I feel that is still ok: you can reset the
checked
binding in theonToggled
signal handler:Switch { checked: backend.checked onToggled: { checked = Qt.binding(() => backend.checked) backend.toggleOrder() } }
Note that
CheckBox
has anextCheckState
function property that can make it somewhat more elegant:CheckBox { checked: backend.checked onReleased: backend.toggleOrder() nextCheckState: () => checkState }
You can try it with:
Timer { id: backend property bool checked: false function toggleOrder() { start(); } interval: 500 onTriggered: checked = !checked }
-
Not that pretty but I feel that is still ok: you can reset the
checked
binding in theonToggled
signal handler:Switch { checked: backend.checked onToggled: { checked = Qt.binding(() => backend.checked) backend.toggleOrder() } }
Note that
CheckBox
has anextCheckState
function property that can make it somewhat more elegant:CheckBox { checked: backend.checked onReleased: backend.toggleOrder() nextCheckState: () => checkState }
You can try it with:
Timer { id: backend property bool checked: false function toggleOrder() { start(); } interval: 500 onTriggered: checked = !checked }
@GrecKo thanks for the suggestion; besides being helpful, it introduced a couple new QML constructs to me.
I think I understand most of what you're proposing. Here's what I've put together:
// QML Toggle { id: cardSwitch checked: vspCard.powerState === EquipmentNS.POWER_ON onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(() => equipmentModel.switchIsOn(vspCard.uuid)) } } // C++ model bool EquipmentModel::switchIsOn(QUuid uuid) { bool rc = false; int index = getIndex(uuid); if (index != NOT_IN_LIST) { Vsp *vsp = static_cast<Vsp *>(m_list->at(index).get()); rc = vsp->m_powerState; } return rc; }
(You can ignore all the static_cast stuff; I have to do this because my model's list contains items of different subclasses of Equipment, which is its own headache.)
Is this what you had in mind? I'm not sure what you wanted me to do with the toggleOrder() call.
Thanks...
-
@GrecKo thanks for the suggestion; besides being helpful, it introduced a couple new QML constructs to me.
I think I understand most of what you're proposing. Here's what I've put together:
// QML Toggle { id: cardSwitch checked: vspCard.powerState === EquipmentNS.POWER_ON onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(() => equipmentModel.switchIsOn(vspCard.uuid)) } } // C++ model bool EquipmentModel::switchIsOn(QUuid uuid) { bool rc = false; int index = getIndex(uuid); if (index != NOT_IN_LIST) { Vsp *vsp = static_cast<Vsp *>(m_list->at(index).get()); rc = vsp->m_powerState; } return rc; }
(You can ignore all the static_cast stuff; I have to do this because my model's list contains items of different subclasses of Equipment, which is its own headache.)
Is this what you had in mind? I'm not sure what you wanted me to do with the toggleOrder() call.
Thanks...
@mzimmers That's what I had in mind for the toggleOrder (you replacing it with actual backend logic call). But not for the switchIsOn.
Can't you use the same binding here ?checked = Qt.binding(() => vspCard.powerState === EquipmentNS.POWER_ON)
Calling your c++
switchIsOn
function will prevent thechecked
property from being updated if thepowerState
changes. -
@mzimmers That's what I had in mind for the toggleOrder (you replacing it with actual backend logic call). But not for the switchIsOn.
Can't you use the same binding here ?checked = Qt.binding(() => vspCard.powerState === EquipmentNS.POWER_ON)
Calling your c++
switchIsOn
function will prevent thechecked
property from being updated if thepowerState
changes.@GrecKo said in is a Switch appropriate here...?:
Calling your c++ switchIsOn function will prevent the checked property from being updated if the powerState changes.
OK, maybe I didn't understand your solution as well as I thought.
My switchIsOn() function doesn't really do anything; it just returns a bool. If I use the binding you posted, what do you expect the toggleOrder() to do?
To reiterate the data flow:
- user clicks the switch
- app sends a message to the controller
- controller sends a response (either OK or error)
- upon receiving this response, client sends a GET request
- upon getting the GET response, client updates the model, including the power state
It seemed to be working the way I had it, but maybe there's a hidden glitch I can't see. So, do I still need a toggleOrder/switchIsOn function?
Thanks...
-
@GrecKo said in is a Switch appropriate here...?:
Calling your c++ switchIsOn function will prevent the checked property from being updated if the powerState changes.
OK, maybe I didn't understand your solution as well as I thought.
My switchIsOn() function doesn't really do anything; it just returns a bool. If I use the binding you posted, what do you expect the toggleOrder() to do?
To reiterate the data flow:
- user clicks the switch
- app sends a message to the controller
- controller sends a response (either OK or error)
- upon receiving this response, client sends a GET request
- upon getting the GET response, client updates the model, including the power state
It seemed to be working the way I had it, but maybe there's a hidden glitch I can't see. So, do I still need a toggleOrder/switchIsOn function?
Thanks...
@mzimmers don't underestimate you, you got most of it the first time!
You correctly replaced my vague toggleOrder with your actual message sending (
sendSwitchChange
).
But I don't think you needed to introduce yourswitchIsOn
function.
What I had in mind is:Toggle { id: cardSwitch checked: vspCard.powerState === EquipmentNS.POWER_ON onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(() => vspCard.powerState === EquipmentNS.POWER_ON) } }
Or to factorize it a little:
Toggle { id: cardSwitch function switchIsOn() { vspCard.powerState === EquipmentNS.POWER_ON } checked: switchIsOn() onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(switchIsOn) } }
Having the function in QML allows the binding to keep being updated if the powerState changes. In c++ your function won't be called again if the NOTIFY signal of the powerState property is emitted.
-
M mzimmers has marked this topic as solved on
-
@mzimmers don't underestimate you, you got most of it the first time!
You correctly replaced my vague toggleOrder with your actual message sending (
sendSwitchChange
).
But I don't think you needed to introduce yourswitchIsOn
function.
What I had in mind is:Toggle { id: cardSwitch checked: vspCard.powerState === EquipmentNS.POWER_ON onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(() => vspCard.powerState === EquipmentNS.POWER_ON) } }
Or to factorize it a little:
Toggle { id: cardSwitch function switchIsOn() { vspCard.powerState === EquipmentNS.POWER_ON } checked: switchIsOn() onToggled: { equipmentModel.sendSwitchChange(id, cardSwitch.checked ? EquipmentNS.POWER_ON : EquipmentNS.POWER_OFF) checked = Qt.binding(switchIsOn) } }
Having the function in QML allows the binding to keep being updated if the powerState changes. In c++ your function won't be called again if the NOTIFY signal of the powerState property is emitted.
@GrecKo thanks for the clarification. I've implemented your approach and verified that it works. (It actually helped me uncover a minor bug where power state was kept as an enum, but received from the core as a bool, causing the "===" to fail. Took me a few minutes to find that one!)