Wrong enum value from QSettings using Qt 6
-
Hello!
I have found an issue with my program using
Qt 6
. For example, I created this method to read theQSettings
ini file.#define APP_SETTINGS_PATH QDir::toNativeSeparators(QString("%1/settings/%2.ini").arg(QApplication::applicationDirPath(), QString(APP_NAME).remove(QRegularExpression("\\s")))) QVariant ManageProgram::loadSettings(QString group, QString property, QVariant defaultValue) { QSettings appSettings(APP_SETTINGS_PATH, QSettings::IniFormat); appSettings.beginGroup(group); QVariant valueVariant = appSettings.value(property, defaultValue); appSettings.endGroup(); return valueVariant; }
Then, I want to get the value from my enum:
Connection::State
Connection::State wlanConnectionState = ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown).value<Connection::State>();
INI file:
[AppSettings] WlanState=2
The stored value is:
2
but it returns as0
onQt 6.3.2
,Qt 6.4.1
,Qt 6.4.2
, which breaks some of the features in my program. OnQt 5
this works well and returns the correct enum value:2
. Any ideas? Thank you. -
Ok, looks like an enum now need Q_ENUM() (even though I think it may be a subtle bug):
struct Connection { Q_GADGET public: enum State { NotConnected = 0, Connecting = 1, Connected = 2, Canceled = 3, Unknown = 4 }; Q_ENUM(State) };
This also allows this in your ini file:
[AppSettings] WlanState=Connected
Will investigate it later on
-
Please print a debug output of your QVariant to see if it's a QVariant conversion problem or QSettings.
qDebug() << ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown);
-
@Cobra91151 said in Wrong enum value from QSettings using Qt 6:
Connection::State
Where is this enum in the docs, please? I can find enum QAbstractSocket::SocketState?
Try reading your saved value as an
int
, do you get the right value? Try converting that to your desired enum, does that work? -
Ok. I have recompiled the program:
qDebug() << ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown);
It returns:QVariant(QString, "2")
So, it seems it's
QVariant
conversion issue. -
@Cobra91151 are you sure the Enum is correctly registered with the meta system ?
I think Variant falls back on that.
Besides that, simply read it as int:
value<int>()
and cast the result to the enum.
-
No, it's my custom enum.
namespace Connection { enum State { NotConnected = 0, Connecting = 1, Connected = 2, Canceled = 3, Unknown = 4 }; }
Yes, it works only when converting using
toInt()
method.int wlanState = ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown).toInt(); wlanConnectionState = static_cast<Connection::State>(wlanState); qDebug() << "wlanConnectionState: " << wlanConnectionState;
wlanConnectionState: 2
Why it fails to convert to enum:
wlanConnectionState = ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown).value<Connection::State>();
? That's the question. -
@Cobra91151 said in Wrong enum value from QSettings using Qt 6:
Why it fails to convert to enum
are you sure the Enum is correctly registered with the meta system ?
-
@J-Hilk
@Christian-Ehrlicher
@JonBI think, it is already registered:
Q_DECLARE_METATYPE(Connection::State)
.
OrQt 6
uses different method of registering types? -
@Cobra91151 did you also use
Q_ENUM_NS
orQ_ENUM
if your declaration is inside a QObject class? -
This enum declaration is in
constants.h
(header file). I use it as a helper file to create some enums/structs/defines there and use it in my program. There is no class in this file.
So, it's outside of aQObject
class. -
I think that I need to use something like this in my program.
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) int wlanState = ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown).toInt(); wlanConnectionState = static_cast<Connection::State>(wlanState); #else wlanConnectionState = ManageProgram::loadSettings("AppSettings", "WlanState", Connection::State::Unknown).value<Connection::State>(); #endif
The output for both cases:
wlanConnectionState: 2
I should use the
.value<Connection::State>();
inQt 5
as always. And use.toInt()
and then cast the result to the enum inQt 6
untilQVariant
conversion problem is fixed. -
Works fine for me with Qt6.head + MSVC
namespace Connection { enum State { NotConnected = 0, Connecting = 1, Connected = 2, Canceled = 3, Unknown = 4 }; } Q_DECLARE_METATYPE(Connection::State); // not even needed for the testcase int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); QVariant v(2); Connection::State s = v.value<Connection::State>(); if (s == Connection::Connected) qDebug() << "Connected"; else qDebug() << "Not connected"; }
-
Yes, it works. So, the enum must be overwritten somewhere in my program which changes the value to 0.
I will check it and fix it. Thank you very much for checking it. -
@Christian-Ehrlicher
@JonB
@J-HilkI have commented all
wlanConnectionState
code in my program where it could be overwritten, recompiled it (clean/run qmake/build) but it still returns as0
. So, I have used @Christian-Ehrlicher example and added my code there.#include <QCoreApplication> #include <QVariant> #include <QSettings> #include <QDir> #include <QRegularExpression> #define APP_NAME "ConsoleApp" #define APP_SETTINGS_PATH QDir::toNativeSeparators(QString("%1/settings/%2.ini").arg(QCoreApplication::applicationDirPath(), QString(APP_NAME).remove(QRegularExpression("\\s")))) namespace Connection { enum State { NotConnected = 0, Connecting = 1, Connected = 2, Canceled = 3, Unknown = 4 }; } Q_DECLARE_METATYPE(Connection::State); // not even needed for the testcase QVariant loadSettings(QString group, QString property, QVariant defaultValue); int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); //QVariant v(2); Connection::State s = loadSettings("AppSettings", "WlanState", Connection::State::Unknown).value<Connection::State>(); //int wlanState = loadSettings("AppSettings", "WlanState", Connection::State::Unknown).toInt(); //Connection::State s = static_cast<Connection::State>(wlanState); if (s == Connection::Connected) { qDebug() << "Connected"; } else { qDebug() << "Not connected"; } qDebug() << "s: " << s; } QVariant loadSettings(QString group, QString property, QVariant defaultValue) { QSettings appSettings(APP_SETTINGS_PATH, QSettings::IniFormat); appSettings.beginGroup(group); QVariant valueVariant = appSettings.value(property, defaultValue); appSettings.endGroup(); return valueVariant; }
It also returns:
Not connected s: 0
When I use this code:
int wlanState = loadSettings("AppSettings", "WlanState", Connection::State::Unknown).toInt(); Connection::State s = static_cast<Connection::State>(wlanState);
The output is the following:
Connected s: 2
So, it seems that issue with
QVariant
conversion still exists.
Can you confirm (reproduce) it using updated code? Also, you will need the settings directory with.ini
file: https://mega.nz/file/EVRwWI5b#4MXbcgqE1aCm_YKEk0leZnMnEGMWw1yuLHL61UlIi54Or create one called ConsoleApp.ini with the following content:
[AppSettings] WlanState=2
Thank you.
-
@Cobra91151 said in Wrong enum value from QSettings using Qt 6:
namespace Connection {
enum State {
NotConnected = 0,
Connecting = 1,
Connected = 2,
Canceled = 3,
Unknown = 4
};
}why not use enum class?
namespace Connection { enum class State { NotConnected = 0, Connecting = 1, Connected = 2, Canceled = 3, Unknown = 4 }; }
-
Hello!
I do not think it will work in my case, since I need to store enum value as integer in the
.ini
file and get it later as enum. OnQt 5
it works as expected. So, I think there is an issue with enum convertion inQt 6
. You can try out my example above to see what the issue is.
Anyway, thank you for your reply :) -
Ok, looks like an enum now need Q_ENUM() (even though I think it may be a subtle bug):
struct Connection { Q_GADGET public: enum State { NotConnected = 0, Connecting = 1, Connected = 2, Canceled = 3, Unknown = 4 }; Q_ENUM(State) };
This also allows this in your ini file:
[AppSettings] WlanState=Connected
Will investigate it later on
-
This post is deleted!
-
@J-Hilk said in Wrong enum value from QSettings using Qt 6:
@Cobra91151 did you also use
Q_ENUM_NS
orQ_ENUM
if your declaration is inside a QObject class?cough 🤓
might be in it since the beginning of Qt6 ? because I don't remember it ever working without the Q_ENUM macro?
-
I see this bug is fixed in
Qt 6.5.0
&Qt 6.6.0
. The issue is resolved.
Thank you. -