[Interest] Reading trees from QSettings

BRM bm_witness at yahoo.com
Thu Aug 30 20:22:51 CEST 2012


> From: Sensei <senseiwa at gmail.com>
> Subject: Re: [Interest] Reading trees from QSettings
> On 8/30/12 4:39pm, BRM wrote:
>>  I'm saying to do something like:
>> 
>>  [Root]
>>  item\1\name=New File
>>  item\1\isFile=true
>>  item\2\name=New Folder
>>  item\2\isFile=false
>>  item\size=2
>> 
>>  [New%20Folder]
>>  item\1\name=aaaa
>>  item\1\isFile=false
>>  item\size=1
>> 
>>  No QStringList is required, and it's very straight forward. Your
>>  QSettings values expand, but in a meaningful way.
> I understand. I'd like to avoid extra parameters, if not necessary.
> Your solution works flawlessly, thanks!
 
>>>  and I've found that the problem is in calling QSettings
>>>  with QStringList, as you can see in my reply to my previous post.
>>> 
>>>        QStringList sons = s.childGroups();
>>> 
>>>        // in the loop:
>>>        qWarning("evaluating '%s', child %d %d",
>>>           qPrintable(name),
>>>           s.childGroups().contains(name) == true,
>>>           sons.contains(name) == true);
>>> 
>>> 
>>>  The two comparisons should yield true or false, but I get different 
> results.
>>>  That is weird, to say the least...
>> 
>>  Are you sure 'sons' and 's.childGroups()' are the same thing? If you
>>  don't update 'sons' in the loop, then they're not likely the same
>>  thing. IIRC, 's' is manipulated as you move through the file - thus
>>  when you do a s.beginGroup()/s.endGroup(), then s.childGroups() will
>>  not be the same as that of the "root" (the file in general); it will
>>  only tell you what is below the level you are looking at. You can get
>>  around that by not using s.beginGroup()/s.endGroup() and instead
>>  using "group/group" and "group/value" syntax when looking something
>>  up, but that would carry its own drawbacks (such as dynamically
>>  computing the "group/group" and "group/value" strings yourself
>>  instead of letting QSettings handle them for you).
> 
> Ok, that makes sense. But I am wondering: how could childGroups() 
> differ, in an INI file, since it does not support nested groups?
> 
> In fact, I still wonder that! You are totally right: if print the 
> childgroups, I get an empty string *inside* the loop.
> 
> This is an unexpected behavior, I am using INI, knowing that it is a 
> flat file, so I was expecting that childGroups() would always return the 
> global scope. I was wrong.

I believe you can have nested groups with INI files too; the section 
would just be called something like [primary/secondary/terteriary].
I haven't tested it, but I it should be doable. Even then, I wouldn't recommend it.

So no, it'd be expected behavior. And please note that unless you specifically tell it to use INI, the back-end changes on a per-platform basis.
Even then, you can also register and use your own back-ends.
 
>>  I still suggest adding the extra parameter as I noted above. It fits
>>  with the array method vary easily - you just pull out the two values
>>  in the loop (from within the beginGroup()/endGroup() while processing
>>  the array) and you know what to do - add the file, or add a folder
>>  and look up another group:
>> 
>>  QStringList sons = s.childGroups();
>>  // sons == s.childGroups()
>>  s.beginGroup("root");
>>       // sons != s.childGroups()
>>       arraySize = s.beginReadArray("items");
>>       for (...)
>>           {
>>           bool isGroup = s.value("isFile", false).toBool();
>>           QString name = s.value("name").toString();
>>           if (isGroup) addFolder(name);
>>           else addFile(name);
>>           }
>>  s.endGroup();
>>  // sons == s.childGroups()
> 
> Do you think that caching the global scope could bring other problems? I like zen files...

Doing like I showed above - storing it right before the loop - will tell you what is there at the root level only.

Something else to consider though - namespace conflicts.
That is, do you want to be able to support a tree like the following:

root
+ file1
+ file2
+folderA
|   + file3
|   + file4
|   + folderB
|      + file5
|      + file6    
+ folderB
   + file7
   + file8
   + folderC

Please note that the contents of each level are different files. So folder root/folderA/folderB is not the same as root/folderB.
Under your proposed scheme, only one folder by the name 'folderB' would be able to exist. The caching would cause problems there too.
There are of course numerous solutions (e.g. the INI group name is not the same as the name value but something mapped to the hierarchy, UUIDs, etc.)

Even if you don't think you need it now, then how much of an effort would need to be done to do it later should you?
And how easy would it be to maintain the compatibility?

Forward thinking is usually very good in software as long as one holds the reigns in tight so as not to over-engineer for things that will never happen (like adding audio support to an image file).

>>  $0.02
> Your help is much more valuable that two cents ;)

Here's another $0.02; YMMV on its actual value.

Ben




More information about the Interest mailing list