Unable to change bools in C++ struct
-
Hi all -
Just ran across weird behavior -- my attempts to set boolean members of a C++ struct don't work in my app.
struct Schedule { Q_GADGET QML_VALUE_TYPE(schedule) QML_STRUCTURED_VALUE Q_PROPERTY(QString name MEMBER m_name) Q_PROPERTY(bool maintenance MEMBER m_maintenance) public: QString m_name = QString(); bool m_maintenance = false; ...
and
ColumnLayout { id: scheduleScreen property schedule newSchedule: ({}) Component.onCompleted: { newSchedule.maintenance = true console.log("ScheduleScreen.qml: newSchedule.maintenance is " + newSchedule.maintenance) } ...
produces this output:
qml: ScheduleScreen.qml: newSchedule.maintenance is false
Same behavior with another bool value in my struct, but changing other values (such as name) works.
I also tried reducing this to a minimal example, but that worked (ugh).
Any ideas where I went wrong with this? Qt 6.5.3, Windows.
Thanks...
@mzimmers said in Unable to change bools in C++ struct:
I also tried reducing this to a minimal example, but that worked (ugh).
This really means you need to start from such a good situation, or from a bad situation, and work towards the other. Till you can produce a "this works, and with this tiny change that does not work".
-
@mzimmers said in Unable to change bools in C++ struct:
I also tried reducing this to a minimal example, but that worked (ugh).
This really means you need to start from such a good situation, or from a bad situation, and work towards the other. Till you can produce a "this works, and with this tiny change that does not work".
-
@mzimmers
Do a copy of your schedule before modifying it and assign it back when you are done.@GrecKo this:
Component.onCompleted: { var tempSchedule = newSchedule console.log("ScheduleScreen.qml: newSchedule is " + newSchedule) tempSchedule.name = "xxx" tempSchedule.m_maintenance = true tempSchedule.timeOffset = 55 tempSchedule.timeFrame = ScheduleEnums.TIMEFRAME_DAILY; newSchedule = tempSchedule console.log("ScheduleScreen.qml: tempSchedule is " + tempSchedule) console.log("ScheduleScreen.qml: newSchedule is " + newSchedule) }
Produces this:
qml: ScheduleScreen.qml: newSchedule is Schedule({00000000-0000-0000-0000-000000000000}, , {00000000-0000-0000-0000-000000000000}, false, false, , START_ACTION_TURN_ON, END_ACTION_TURN_OFF, START_WHEN_TIME_OF_DAY, END_WHEN_TIME_OF_DAY, 09:00:00.000, 17:00:00.000, TIMEFRAME_WEEKLY, REPEAT_EVERY_WEEK, , , , 0, ) qml: ScheduleScreen.qml: tempSchedule is Schedule({00000000-0000-0000-0000-000000000000}, xxx, {00000000-0000-0000-0000-000000000000}, false, false, , START_ACTION_TURN_ON, END_ACTION_TURN_OFF, START_WHEN_TIME_OF_DAY, END_WHEN_TIME_OF_DAY, 09:00:00.000, 17:00:00.000, TIMEFRAME_DAILY, REPEAT_EVERY_WEEK, , , , 55, ) qml: ScheduleScreen.qml: newSchedule is Schedule({00000000-0000-0000-0000-000000000000}, xxx, {00000000-0000-0000-0000-000000000000}, false, false, , START_ACTION_TURN_ON, END_ACTION_TURN_OFF, START_WHEN_TIME_OF_DAY, END_WHEN_TIME_OF_DAY, 09:00:00.000, 17:00:00.000, TIMEFRAME_DAILY, REPEAT_EVERY_WEEK, , , , 55, )
So...no change. Really odd, isn't it?
-
@mzimmers said in Unable to change bools in C++ struct:
I also tried reducing this to a minimal example, but that worked (ugh).
This really means you need to start from such a good situation, or from a bad situation, and work towards the other. Till you can produce a "this works, and with this tiny change that does not work".
-
@JonB agree completely, though I'm not sure what the next step is, given how "close to the top" this code is. It probably has something to do with how I coded my struct, but I sure can't see what might be doing this.
-
@mzimmers when I get strange stuff not working I do a clean, run qmake, build. Sometimes it is just a moc issue. Not sure how that works with cmake though.
-
OK, so I discovered something, but I don't understand it. I stepped through this in the debugger, and confirmed the problem is in the C++ side:
Then, for lack of anything else to try, I removed the initializer in my struct:
// bool m_maintenance = false; // before bool m_maintenance; // now
and...
For another test, I added this line to my c'tor:bool m_maintenance = false;
And got the original (bad) result.
I also "changed polarity" (initialize to true; try to set to false) with the same (bad) result.
So...this problem just got a little bigger. I'm not willing to release code to the field that creates structs with uninitialized values; I need to figure out what's going on here.
EDIT: this occurs on 6.6 as well as 6.5.3.
ANY ideas, no matter how far-fetched, are welcome. Thanks...
-
OK, so I discovered something, but I don't understand it. I stepped through this in the debugger, and confirmed the problem is in the C++ side:
Then, for lack of anything else to try, I removed the initializer in my struct:
// bool m_maintenance = false; // before bool m_maintenance; // now
and...
For another test, I added this line to my c'tor:bool m_maintenance = false;
And got the original (bad) result.
I also "changed polarity" (initialize to true; try to set to false) with the same (bad) result.
So...this problem just got a little bigger. I'm not willing to release code to the field that creates structs with uninitialized values; I need to figure out what's going on here.
EDIT: this occurs on 6.6 as well as 6.5.3.
ANY ideas, no matter how far-fetched, are welcome. Thanks...
Check this out.
https://stackoverflow.com/questions/1069621/are-members-of-a-c-struct-initialized-to-0-by-default
It may not be a C++ problem. Instead it is a C problem. Struct is very C style. I even avoid using it. -
Check this out.
https://stackoverflow.com/questions/1069621/are-members-of-a-c-struct-initialized-to-0-by-default
It may not be a C++ problem. Instead it is a C problem. Struct is very C style. I even avoid using it. -
@JoeCFD interesting article, though my issue is with modification, not initialization.
Regarding the use of structs: I suppose I could use a class, but I'd be astonished if that made a difference. I'm deliberately avoiding using QObject here, too.
-
@mzimmers bool m_maintenance; // now
is undefined.can you try:
bool m_maintenance{ false };
I do not know if it will make a difference.@JoeCFD said in Unable to change bools in C++ struct:
@mzimmers bool m_maintenance; // now
is undefined.I realize that, and that's not acceptable. But currently I have the options of leaving it undefined, or initializing it and (somehow) making it QML-immutable in the process.
I can't even modify it if I initialize it in QML, like this:
property schedule newSchedule: ({ "maintenance": false })
-
@mzimmers bool m_maintenance; // now
is undefined.can you try:
bool m_maintenance{ false };
I do not know if it will make a difference. -
@JoeCFD said in Unable to change bools in C++ struct:
can you try:
bool m_maintenance{ false };Same (bad) result. Thanks for the suggestion, though.
-
@GrecKo this:
Component.onCompleted: { var tempSchedule = newSchedule console.log("ScheduleScreen.qml: newSchedule is " + newSchedule) tempSchedule.name = "xxx" tempSchedule.m_maintenance = true tempSchedule.timeOffset = 55 tempSchedule.timeFrame = ScheduleEnums.TIMEFRAME_DAILY; newSchedule = tempSchedule console.log("ScheduleScreen.qml: tempSchedule is " + tempSchedule) console.log("ScheduleScreen.qml: newSchedule is " + newSchedule) }
Produces this:
qml: ScheduleScreen.qml: newSchedule is Schedule({00000000-0000-0000-0000-000000000000}, , {00000000-0000-0000-0000-000000000000}, false, false, , START_ACTION_TURN_ON, END_ACTION_TURN_OFF, START_WHEN_TIME_OF_DAY, END_WHEN_TIME_OF_DAY, 09:00:00.000, 17:00:00.000, TIMEFRAME_WEEKLY, REPEAT_EVERY_WEEK, , , , 0, ) qml: ScheduleScreen.qml: tempSchedule is Schedule({00000000-0000-0000-0000-000000000000}, xxx, {00000000-0000-0000-0000-000000000000}, false, false, , START_ACTION_TURN_ON, END_ACTION_TURN_OFF, START_WHEN_TIME_OF_DAY, END_WHEN_TIME_OF_DAY, 09:00:00.000, 17:00:00.000, TIMEFRAME_DAILY, REPEAT_EVERY_WEEK, , , , 55, ) qml: ScheduleScreen.qml: newSchedule is Schedule({00000000-0000-0000-0000-000000000000}, xxx, {00000000-0000-0000-0000-000000000000}, false, false, , START_ACTION_TURN_ON, END_ACTION_TURN_OFF, START_WHEN_TIME_OF_DAY, END_WHEN_TIME_OF_DAY, 09:00:00.000, 17:00:00.000, TIMEFRAME_DAILY, REPEAT_EVERY_WEEK, , , , 55, )
So...no change. Really odd, isn't it?
-
@mzimmers what's the issue on this output? We don't know which field is which. Also why are you using m_maintenance in QML? That's not the name of your property.
-
OK, guys - here's a minimal repeatable example:
// schedule.h #pragma once #include <QObject> #include <QMetaType> #include <QtQml/qqmlregistration.h> #include <QtQmlIntegration/QtQmlIntegration> struct Schedule { Q_GADGET QML_VALUE_TYPE(schedule) QML_STRUCTURED_VALUE Q_PROPERTY(bool maintenance MEMBER m_maintenance) public: bool m_maintenance; Q_INVOKABLE Schedule() {} bool operator ==(const Schedule &rhs) const {return true;} };
// Main.qml import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Window Window { id: mainWindow width: 640 height: 480 visible: true property schedule newSchedule: ({ }) Switch { onClicked: { console.log("switch is " + checked) newSchedule.maintenance = checked console.log("newSchedule.maintenance is " + newSchedule.maintenance) } } }
Output:
qml: switch is true qml: newSchedule.maintenance is false qml: switch is false qml: newSchedule.maintenance is false qml: switch is true qml: newSchedule.maintenance is false qml: switch is false qml: newSchedule.maintenance is false
I can provide the cmake file as well if desired, but it doesn't contain anything unusual.
-
OK, guys - here's a minimal repeatable example:
// schedule.h #pragma once #include <QObject> #include <QMetaType> #include <QtQml/qqmlregistration.h> #include <QtQmlIntegration/QtQmlIntegration> struct Schedule { Q_GADGET QML_VALUE_TYPE(schedule) QML_STRUCTURED_VALUE Q_PROPERTY(bool maintenance MEMBER m_maintenance) public: bool m_maintenance; Q_INVOKABLE Schedule() {} bool operator ==(const Schedule &rhs) const {return true;} };
// Main.qml import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Window Window { id: mainWindow width: 640 height: 480 visible: true property schedule newSchedule: ({ }) Switch { onClicked: { console.log("switch is " + checked) newSchedule.maintenance = checked console.log("newSchedule.maintenance is " + newSchedule.maintenance) } } }
Output:
qml: switch is true qml: newSchedule.maintenance is false qml: switch is false qml: newSchedule.maintenance is false qml: switch is true qml: newSchedule.maintenance is false qml: switch is false qml: newSchedule.maintenance is false
I can provide the cmake file as well if desired, but it doesn't contain anything unusual.
@mzimmers said in Unable to change bools in C++ struct:
bool operator ==(const Schedule &rhs) const {return true;}
If you remove this non-sensical
operator==
your code works as expected.My guess is that the engine modifies a temp Schedule internally, checks the equality and assign it only if it's different. As it's always equal it won't modify it.
-
@mzimmers said in Unable to change bools in C++ struct:
bool operator ==(const Schedule &rhs) const {return true;}
If you remove this non-sensical
operator==
your code works as expected.My guess is that the engine modifies a temp Schedule internally, checks the equality and assign it only if it's different. As it's always equal it won't modify it.
@GrecKo bingo!
I'd just stubbed out that comparison function to satisfy the compiler, but you were absolutely right. In my app, I'd neglected to include the maintenance member in my comparison function. Seems to work fine now.
Kind of has me wondering -- if I set my compiler options to no optimization, I wonder if it would have worked...
Anyway, thanks to EVERYONE for the help on this.
-
M mzimmers has marked this topic as solved on