PDA

View Full Version : Qsettings does not differentiate between string and int values



yaronkle
14th October 2013, 09:00
Hi,

I am writing and reading string and int values using QSettings to an Ini file.
When I try to read the values from a different process later on, the values are read as strings instead of int.

This is the code I am using to write values:

QSettings settings("TestQSettings.ini", QSettings::IniFormat);
settings.setValue("AAA",QString("111"));
settings.setValue("BBB",222);

This is the INI file created

[General]
AAA=111
BBB=222

This is the code I am using to read values:

QVariant qvar = settings.value("AAA");
std::cout << "AAA type " << qvar.type() << std::endl;
qvar = settings.value("BBB");
std::cout << "BBB type " << qvar.type() << std::endl;

If I run this code from the same process

AAA type 10
BBB type 2

If I run this code from a different process:

AAA type 10
BBB type 10

Have this problem with Ubuntu 12 and Qt 4.8.1 64 bit.

Thanks!

Santosh Reddy
14th October 2013, 09:17
Don't worry how the values are stored in INI file, just read the value and convert to the type which was used during writing using toString() /toInt() functions.
also try this for more insight


qDebug() << settings.value("AAA") << settings.value("BBB");
qDebug() << settings.value("AAA").toString() << settings.value("BBB").toInt();

yaronkle
14th October 2013, 09:23
Thanks, but if it were only that simple...

I am porting Windows legacy code to Linux.
It's doable but a lot of work.

I was hoping that QT will is able to save the strings with quotes "" thus allowing it to read the value types correctly.

Santosh Reddy
14th October 2013, 09:33
I am porting Windows legacy code to Linux.
How does that matter?
Do mean to say the INI file is created using legacy APIs, and now you want to read using Qt APIs.

I was hoping that QT will is able to save the strings with quotes "" thus allowing it to read the value types correctly
Why do you want know the types from INI file, you are supposed to know them upfront.

yaronkle
14th October 2013, 09:49
OK, let me explain.

I am porting Windows code that calls RegQueryValueEx (for example, there are other API's).
RegQueryValueEx returns the correct type to the user, since that type is written correctly in Windows Registry (also in QSettings as long as you run it without stopping the process).

I have written a Linux implementation of RegQueryValueEx.

I can modify all the calls to RegQueryValueEx (which is a hassle).
Because this is a multiplatform project, I can't guarantee that another developer won't call RegQueryValueEx and rely on it to return the correct type.

Santosh Reddy
14th October 2013, 10:45
Don't mix up APIs. Either stick to Qt APIs on all platforms or use your custom (or legacy) on all platform.

anda_skoa
14th October 2013, 12:32
So if I understand correctly you are not actually creating a Qt API for something but you are backing a compatibility shim of sorts by Qt code, right?
And you shim function has to return a typed value or at least a type on request?

While that sounds very painful to maintain long term, you probably have reasons not to do a clean port.

As far as I can see you have to options:
1) use a backend that contains the type information just like the original API's backend does
2) use a type-less backend and try to find the closest type by trying potental conversion

Cheers,
_

yaronkle
14th October 2013, 12:44
That is correct for both questions!

What is a backend?
Are you referring to QSettings::SetIniCodec?

I have an idea, I have seen QT add quotes at one time to. I think it was when I played with QSringList.
Thinking of storing strings as QStringList of length 0. QVariant::type() will probably return the correct value.

anda_skoa
14th October 2013, 17:33
What is a backend?
Are you referring to QSettings::SetIniCodec?

No, QSettings would be one possible backend for storing values.

Other alternatives would be JSON, XML or some custom storage format, e.g. using QDataStream.
Even with QSettings as the backend, you could store the type as a subkey of the value.

Cheers,
_

yaronkle
15th October 2013, 07:59
I have a working solution which was simpler than expected.

When writing string values to the INI file, I append "\"STRING" to the string
When reading generic values. If the QVariant is a string without the above prefix I assume it's an int.
Works like a charm.

Many thanks to all of you!