[Development] QConfig update.

Tomaz Canabrava tcanabrava at kde.org
Tue Oct 14 18:44:30 CEST 2014


On Tue, Oct 14, 2014 at 1:35 PM, Milian Wolff <milian.wolff at kdab.com> wrote:

> On Tuesday 14 October 2014 13:22:51 Tomaz Canabrava wrote:
> > People, I'v read everything on the other two e-mails and I'v changed
> quite
> > a few things here and again I ask for some advice.
> >
> > What I'v done:
> >
> > QConfig / QConfigGroup / QConfigWatcher combo classes, to be used from
> the
> > user
> > QConfigIniBackend, to be used internally.
> >
> > QConfig:
> >
> >    uses a 'global' QHash<QString, QConfigIniBackend> for different files
> in
> > a way that we don't destruct the info when the object is destroyed, but
> > reuses the JSON information stored, and parse it to the config object.
> >
> > it has a QConfigGroup 'global' value that can be acced directly via
> > .setValue and .value
>
> Why the global state? A QConfig should be valid for a single file and
> constructed on-demand. If you want to share stuff and keep it open, adding
> something like a KSharedConfig might be a good idea. But again, that is
> something that could/should be built on-top of QConfig (imo).
>

so I don't need to open a config file and parse it every time the user
created a QConfig object.


>
> > QConfig and QConfigGroup *does not* support setting a default value on
> the
> > getter, I know that this is used in a lot of places but this can cause
> > inconsistencies:
> >
> > Main.cpp
> >
> > QConfig c;
> > c.value("window-width", 800);
> >
> > MainWindow.cpp
> > c.value("window-width", 1200);
> >
> > so we must create a better way for that. for now, I simply removed the
> > possibility for that, we can only do
> >
> > c.value("window-width");
>
> And how do you check whether window-width was read or not? What do you
> return
> on error? A default-constructed value? What type does the value have for
> that
> matter?
>
> Imo, this makes this API extremely inconvenient. Yes it's possible to do an
> error, but that is life. You should only add such error-prevention stuff
> into
> the high-level schema stuff, not into QConfig itself.
>
> Without the ability to provide a default value, one can never figure out
> whether `c.value("some-int") == 0` means the value could not be read and a
> default should be used, or whether the value is 0.
>

Since I wanted to add schema-validation on the low level stuff, this
wouldn't be an issue,
'value couldn't be read' would cause an assert.
but I can postpone this for later.

> I plan to set the defaults via a schema-based file ( could be the
> KConfigXt
> > based, but I dislike having to edit XML by hand, so something more
> similar
> > to QML would be best ).
> > Any tougths on that?
>
> If you store JSON, maybe use JSON? The mapping will give you the default
> value
> and from there you get a type.
>
> {
> "foo" : 1,
> "bar" : { "lala": "string" }
> }
>

Yup - and I'm already working on a schema format conversor for json.


> > QConfigWatcher: created automatically via the .watcher() method on
> QConfig
> > and QConfigGroup
>
> It should be the other way around, imo. Also see below.
>

you are right. :)


>
> > Removed the need for pointers and references, implemented via DPointer
> and
> > move-semantics.
> >
> > Example usage:
> >
> >     QConfig config;
> >
> >     QConfigGroup window = config.group("window");
> >     window.setValue("width", 800);
> >     window.setValue("height", 600);
> >     window.setValue("x", 100);
> >     window.setValue("y",100);
> >     window.setValue("opacity", 55);
> >
> >     QConfigGroup font = config.group("fonts");
> >     font.setValue("family", "san-serif");
> >     font.setValue("pointSize", 9);
> >     font.setValue("bold", true);
> >     font.setValue("italic", true);
> >
> >     QConfigGroup plasmoids = config.group("plasmoids");
> >     for(int i = 0; i < 5; i++){
> >         QConfigGroup plasmoid = plasmoids.group(QString::number(i));
> >         plasmoid.setValue("name", "name_" + QString::number(i));
> >         plasmoid.setValue("width", rand() % 100 + 100);
> >         plasmoid.setValue("value", rand() % 100 + 100);
> >     }
> >
> >     connect(plasmoids.watcher(), SIGNAL(changed(QConfigGroup)), this,
> > SLOT(plasmoidsChanged(QConfigGroup)));
> >     config.sync();
>
> When the context is left, QConfig is destroyed. What happens to the
> watcher?
> It stays alive/is leaked? How can the connect work otherwise?
>

Right now, it's not leaked but reused every time the same group is created,
but I can see it was a bad design decision.
Redoing that. :)


>
> > TODO, but only after this part gets perfect, KconfigXT like automatic
> > creation of classes and structures based on a schema file.
>
> I hope, again, that you reconsider more API from the KConfig world. You
> decisions with the global state inside QConfig as well as the removal of
> default-values for reading from the config are very bad imo, and much
> better
> handled in K{,Shared}Config.
>

Okay - will take a look at K{,Shared}Config to see what the api looks like.


>
> Bye
>
> --
> Milian Wolff | milian.wolff at kdab.com | Software Engineer
> KDAB (Deutschland) GmbH&Co KG, a KDAB Group company
> Tel. Germany +49-30-521325470, Sweden (HQ) +46-563-540090
> KDAB - Qt Experts - Platform-independent software solutions
>
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20141014/ca80d243/attachment.html>


More information about the Development mailing list