Re: [Development] QConfig update.

2014-10-16 Thread André Somers
Thiago Macieira schreef op 15-10-2014 17:34:
 I'm not sure you got my meaning. How is a config editor tool in Qt 
 Creator going to read  write those files?
Why would you need a tool like that for such a format?

 How is the code generator going to read the QTypedSettings source 
 header to genete the equivalent .cpp? 
Exactly the same way moc already parses header files now? My idea was to 
explore if it were possible to build on what moc already can do. You 
might have noticed that this idea looks exactly like how you create 
Q_PROPERTY declarations. I think they should basically _be_ Q_PROPERTY 
declarations, though the options would be extended with keywords such as 
SETTING and DEFAULT.

Note that I would really like it if it were possible at all to not only 
generate .cpp, but also generate a bit of .h that gets included into the 
class declaration in some way, so that there would be real functions to 
call for all settings. That's what I really miss with the Q_PROPERTY 
using the MEMBER keyword.

André

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-16 Thread Thiago Macieira
On Thursday 16 October 2014 08:51:52 André Somers wrote:
 Exactly the same way moc already parses header files now? My idea was to
 explore if it were possible to build on what moc already can do. You
 might have noticed that this idea looks exactly like how you create
 Q_PROPERTY declarations. I think they should basically _be_ Q_PROPERTY
 declarations, though the options would be extended with keywords such as
 SETTING and DEFAULT.

That's abusing moc for something it wasn't intended. Moc creates a meta object 
information for an existing object. That implies:

* the class is a QObject, which this needs not be
* there are no extra methods present in the class, which this needs

We need a code generator that generates a header and possibly a .cpp that can 
be #included for use elsewhere, like uic. That's not moc.

The syntax you proposed does not accomplish that:

class AppSettings: public QTypedConfig
{
Q_SETTINGS(); // Q_OBJECT, but perhaps with some extra's like the 
ability to include generated function declarations for getters and setters

Q_SETTING(int width SETTING dialog/window-width  DEFAULT 800); 
//use generated getter, setter and notify
Q_SETTING(MyCustomType myValue READ myValue  WRITE setMyValue NOTIFY 
myValueChanged); //use custom getter and setter

public:
 AppSettings(QObject* parent = 0);

 MyCustomType myValue() const;
 void setMyValue(const MyCustomType value);
 Q_SIGNAL void myValueChanged(const MyCustomValue value);
};

Given this header, there's no way the preprocessor can turn the Q_SETTING 
macro into a useful declaration. So you can be absolutely sure that the above 
will not be the way to write the setting declarations. The schema will not be 
a C++ source or header file.

Given the above statement, we have two choices:

1) invent our new schema format
2) adopt a format based on something we can read with QtCore

Option 2 implies either XML or JSON.

 Note that I would really like it if it were possible at all to not only
 generate .cpp, but also generate a bit of .h that gets included into the
 class declaration in some way, so that there would be real functions to
 call for all settings. That's what I really miss with the Q_PROPERTY
 using the MEMBER keyword.

Just as I said.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-16 Thread Mathias Hasselmann


Am 14.10.2014 um 18:44 schrieb Tomaz Canabrava:
 On Tue, Oct 14, 2014 at 1:35 PM, Milian Wolff milian.wo...@kdab.com
  mailto:milian.wo...@kdab.com wrote:

 On Tuesday 14 October 2014 13:22:51 Tomaz Canabrava wrote:
 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

I can imagine use cases where I'd like to have this flexibility. The 
best default value for an unspecified setting very much can depend on 
the context.

 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.

I very much agree.

 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 don't think it is wise to unconditionally crash programs for things
that just during normal usage. With this string based API those settings 
schema and the actually accessing code are only losely coupled. So it 
will just happen that applications built for version A of the settings 
schema will access a configuration written with version B of the schema 
in mind. Because of program upgrades. Because the user has two versions 
of the same program installed. Because of human mistakes. Such 
situations must be handled gracefully: Users just don't like their 
programs crashing and maybe never starting again (without deleting 
various files). What's your graceful error handling plan for schema 
mismatches?

Ciao,
Mathias
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-16 Thread André Somers
Thiago Macieira schreef op 16-10-2014 09:17:
 On Thursday 16 October 2014 08:51:52 André Somers wrote:
 Exactly the same way moc already parses header files now? My idea was to
 explore if it were possible to build on what moc already can do. You
 might have noticed that this idea looks exactly like how you create
 Q_PROPERTY declarations. I think they should basically _be_ Q_PROPERTY
 declarations, though the options would be extended with keywords such as
 SETTING and DEFAULT.
 That's abusing moc for something it wasn't intended. Moc creates a meta object
 information for an existing object. That implies:

 * the class is a QObject, which this needs not be
It is exactly what I was proposing though. Note that this is *not* 
QConfig/QConfigGroup. I do happen to think that being a QObject for a 
(central) settings object is a very useful quality. For instance, in 
order to signal changes to values.
I know of course that moc was not intended for this. However, you were 
asking how such a format could be parsed, and I was pointing out that Qt 
has been doing exactly that for ages.

 * there are no extra methods present in the class, which this needs
What do you mean by that?

 We need a code generator that generates a header and possibly a .cpp that can
 be #included for use elsewhere, like uic. That's not moc.

 The syntax you proposed does not accomplish that:

 class AppSettings: public QTypedConfig
 {
  Q_SETTINGS(); // Q_OBJECT, but perhaps with some extra's like the
 ability to include generated function declarations for getters and setters

  Q_SETTING(int width SETTING dialog/window-width  DEFAULT 800);
 //use generated getter, setter and notify
  Q_SETTING(MyCustomType myValue READ myValue  WRITE setMyValue NOTIFY
 myValueChanged); //use custom getter and setter

 public:
   AppSettings(QObject* parent = 0);

   MyCustomType myValue() const;
   void setMyValue(const MyCustomType value);
   Q_SIGNAL void myValueChanged(const MyCustomValue value);
 };

 Given this header, there's no way the preprocessor can turn the Q_SETTING
 macro into a useful declaration. So you can be absolutely sure that the above
 will not be the way to write the setting declarations. The schema will not be
 a C++ source or header file.
Given that you know a lot more that I do about what can and what cannot 
be done here... What is blocking doing this _exactly_? Would there be 
any feasible workaround for that? Would it be possible to do if you were 
required to #include the generated .h file inside the class itself for 
instance?

Something like this perhaps?

class AppSettings: public QTypedConfig
{
 Q_SETTINGS(AppSettings); // Q_OBJECT, but perhaps with some extra's
 #include(appsettings_inc.h) //include generated definitions

 Q_SETTING(int width SETTING dialog/window-width  DEFAULT 800);
//use generated getter, setter and notify
 Q_SETTING(MyCustomType myValue READ myValue  WRITE setMyValue NOTIFY
myValueChanged); //use custom getter and setter

(...)
}

where the contents of appsettings_inc.h would be generated by the 
generator, to yield something like:

//generated for setting property width
int width() const; //Q_PROPERTY READ function
void setWidth(int width); // Q_PROPERTY WRITE function
void widthChanged(int width); // Q_PROPERTY SIGNAL function
void resetWidth(); //revert to set default value; Q_PROPERTY RESET function


I don't think it is stretching what moc is already doing conceptually 
all _that_ much. It basically creates properties that are persistent in 
some kind of store for configuration, instead of them depending on 
variables in the object itself. And again: I'd find this (or similar) 
fuctionality also very useful for the Q_PROPERTY MEMBER keyword that we 
already have.

André


___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Albert Astals Cid
Please do not assert on the library, you're going to make everyone's
program crasheable by just editing a file by hand.

On Tue, Oct 14, 2014 at 7:06 PM, Milian Wolff milian.wo...@kdab.com wrote:

 On Tuesday 14 October 2014 13:44:30 Tomaz Canabrava wrote:
  On Tue, Oct 14, 2014 at 1:35 PM, Milian Wolff milian.wo...@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' QHashQString, 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.

 Then provide a QSharedConfig or let the user store the QConfig himself, if
 it
 turns out to be a performance-bottleneck for him. If you add global state
 to
 QConfig, you'll need synchronization or otherwise you are doomed in a
 multithreaded application.

 Also: If you add a cheap JSON cache, is it really worth to optimize at all?

 Furthermore: If you keep the QConfig in memory all the time, you'll
 probably
 end up duplicating the stuff as soon as you add the fancy high-level
 interface
 on-top. QConfig will operate on JSON after all and you'll incur a
 conversion
 penalty whenever you read a value from it. The high-level interface should
 (hopefully) read the values once and store it internally in the proper
 type.
 If you don't do this and always read from QConfig, you'll end up with
 issues
 in this pattern:

 void HighLevelConfig::setFoo(quint64 foo)
 {
   if (foo == m_foo) {
 return;
   }
   m_foo = foo;
   emit fooChanged(foo);
 }

 If this would read from QConfig, instead of directly comparing to the
 quint64
 m_foo member, you'll get rounding errors etc. pp. This, the more I think
 about it, is actually a big issue with a JSON cache in general. .ini does
 not
 have that issue as the byte-array gets interpreted based on the type you
 pass
 along (a kind of duck-typing). It might mean that you'll have to store
 everything as a string in JSON to prevent a loss of data when storing e.g.
 std::limitsquint64::max() (note: JSON only knows double). But storing
 everything as a string looses the difference between

 foo=1

 and

 foo=1

 Afaik this issue has not yet been discussed, has it?

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.

 Most applications, (all KDE applications btw), would then assert.
 Initially,
 no configuration file is available after all.

 And again: Please do not overdesign QConfig. KISS! Add fancy
 schema-validation
 and stuff on-top of that. Don't remove something as essential as reading a
 setting with a default value fallback mechanism!

 Bye
 --
 Milian Wolff | milian.wo...@kdab.com | Software Engineer
 KDAB (Deutschland) GmbHCo KG, a KDAB Group company
 Tel. Germany +49-30-521325470, Sweden (HQ) +46-563-540090
 KDAB - Qt Experts - Platform-independent software solutions

 ___
 

Re: [Development] QConfig update.

2014-10-15 Thread Julien Blanc
On 14/10/2014 19:06, Milian Wolff wrote:
 It might mean that you'll have to store
 everything as a string in JSON to prevent a loss of data when storing e.g.
 std::limitsquint64::max() (note: JSON only knows double).

To be more precise : JSON itself does not assume anything about number 
precision. JavaScript, as well as QJsonValue, do assume that any number 
is a double precision, but nothing in RFC 4627 says that.

libjson (at least) assumes that number values in JSON can be signed 
int64. This specific issue may be better handled in QJsonValue than in a 
QConfig class.

Regards,

Julien Blanc


___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread André Somers
Milian Wolff schreef op 14-10-2014 18:35:

 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.
Indeed. I think default values are vital, even if the issue you (Tomaz) 
point out is valid like I argued yesterday. That is why we only use 
QSettings anymore from within our own type-safe settings class.

 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 }
 }

XML hand-editing is of course not needed. If XML would be used (like it 
is for .ui files and .rcc files in Qt), an editor for this type can be 
added to Creator. That would get rid of the need to hand-edit XML files.

JSON could also work of course. Perhaps it is important however to first 
have a clear goal on use cases the schema has to solve, before going 
into a file format for it. To me, some requirements would be:
1) Easy generation of type-save settings class
2) Management of default values
3) Capable of handling custom types, including enums
4) Makes it easy to avoid writing boilerplate getters and setters, but 
possible to do so if needed
5) Also generates changed signals

Furthermore, I'd like to have the ability to have more than one of 
these. That is: we are in a large project with several libraries. These 
libraries need to access part of the settings. The overall application 
needs to access the whole settings structure of course (for instance for 
showing a settings dialog), preferably in some nice unified way.

I think settings resemble properties to a very large extend. Perhaps it 
would, as an alternative to the XML or JSON schemes already suggested, 
but possible to build on the Qt property system instead for this. It is 
familiar to developers, does not require a special editor, and allows 
for using your own code instead of generated boilerplate quite naturally 
(point 4 above). Perhaps something like:

class AppSettings: public QTypedConfig
{
Q_SETTINGS(); // Q_OBJECT, but perhaps with some extra's like the 
ability to include generated function declarations for getters and setters

Q_SETTING(int width SETTING dialog/window-width  DEFAULT 800); 
//use generated getter, setter and notify
Q_SETTING(MyCustomType myValue READ myValue  WRITE setMyValue NOTIFY 
myValueChanged); //use custom getter and setter

public:
 AppSettings(QObject* parent = 0);

 MyCustomType myValue() const;
 void setMyValue(const MyCustomType value);
 Q_SIGNAL void myValueChanged(const MyCustomValue value);

}


André

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Oswald Buddenhagen
On Tue, Oct 14, 2014 at 07:06:30PM +0200, Milian Wolff wrote:
 On Tuesday 14 October 2014 13:44:30 Tomaz Canabrava wrote:
  On Tue, Oct 14, 2014 at 1:35 PM, Milian Wolff milian.wo...@kdab.com wrote:
   On Tuesday 14 October 2014 13:22:51 Tomaz Canabrava wrote:
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.
 
 Then provide a QSharedConfig or let the user store the QConfig himself, if it 
 turns out to be a performance-bottleneck for him.

as i previously pointed out, this is one of the things i consider *bad*
about kconfig.
i wouldn't necessarily make a real cache, but the objects should be
automatically shared in the background. that's what happens when you
natively use the windows registry anyway.

 If you add global state to QConfig, you'll need synchronization or
 otherwise you are doomed in a multithreaded application.
 
yes. so what?

 Furthermore: If you keep the QConfig in memory all the time, you'll probably 
 end up duplicating the stuff as soon as you add the fancy high-level 
 interface 
 on-top. QConfig will operate on JSON after all and you'll incur a conversion 
 penalty whenever you read a value from it. The high-level interface should 
 (hopefully) read the values once and store it internally in the proper type. 

you are right with that (that's why i don't think using the json classes
as anything else than backend storage and having an abstraction layer on
top makes sense), but i don't see how that correlates with the config
objects being shared+cached.

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Thiago Macieira
On Tuesday 14 October 2014 13:44:30 Tomaz Canabrava wrote:
 so I don't need to open a config file and parse it every time the user
 created a QConfig object.

I quite frankly don't see this as a problem.

I think this syntax of using QSettings is just plain weird:

QSettings settings;
if (settings.contains(foo))
doSomething();

Applications should just keep a global singleton of theirs for their config.

Clearly, QConfigGroup would need to be thread-safe.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Milian Wolff
On Wednesday 15 October 2014 10:02:59 André Somers wrote:

snip

 I think settings resemble properties to a very large extend. Perhaps it
 would, as an alternative to the XML or JSON schemes already suggested,
 but possible to build on the Qt property system instead for this. It is
 familiar to developers, does not require a special editor, and allows
 for using your own code instead of generated boilerplate quite naturally
 (point 4 above). Perhaps something like:
 
 class AppSettings: public QTypedConfig
 {
 Q_SETTINGS(); // Q_OBJECT, but perhaps with some extra's like the
 ability to include generated function declarations for getters and setters
 
 Q_SETTING(int width SETTING dialog/window-width  DEFAULT 800);
 //use generated getter, setter and notify
 Q_SETTING(MyCustomType myValue READ myValue  WRITE setMyValue NOTIFY
 myValueChanged); //use custom getter and setter
 
 public:
  AppSettings(QObject* parent = 0);
 
  MyCustomType myValue() const;
  void setMyValue(const MyCustomType value);
  Q_SIGNAL void myValueChanged(const MyCustomValue value);
 }

I like the idea!

Bye
-- 
Milian Wolff | milian.wo...@kdab.com | Software Engineer
KDAB (Deutschland) GmbHCo 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@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Rafael Roquetto
On Wed, Oct 15, 2014 at 10:02:59AM +0200, André Somers wrote:
snip
 XML hand-editing is of course not needed. If XML would be used (like it 
 is for .ui files and .rcc files in Qt), an editor for this type can be 
 added to Creator. That would get rid of the need to hand-edit XML files.

No! Not everyone uses Creator or whatever tool. I strongly dislike the idea of
having to depend on a specific toolset. What is productive to some can be
counter-productive to others. We need to KISS and use a human-readable format
that offers the possibility to be manually edited if desired. And for that XML
is a huge PITA IMHO. Please, please don't go down that road.

-- 
Rafael Roquetto | rafael.roque...@kdab.com | Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel. Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - Qt Experts - Platform-independent software solutions


smime.p7s
Description: S/MIME cryptographic signature
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Rafael Roquetto
On Wed, Oct 15, 2014 at 12:22:32PM +0200, Milian Wolff wrote:
 On Wednesday 15 October 2014 10:02:59 André Somers wrote:
 
 snip
 
  I think settings resemble properties to a very large extend. Perhaps it
  would, as an alternative to the XML or JSON schemes already suggested,
  but possible to build on the Qt property system instead for this. It is
  familiar to developers, does not require a special editor, and allows
  for using your own code instead of generated boilerplate quite naturally
  (point 4 above). Perhaps something like:
  
  class AppSettings: public QTypedConfig
  {
  Q_SETTINGS(); // Q_OBJECT, but perhaps with some extra's like the
  ability to include generated function declarations for getters and setters
  
  Q_SETTING(int width SETTING dialog/window-width  DEFAULT 800);
  //use generated getter, setter and notify
  Q_SETTING(MyCustomType myValue READ myValue  WRITE setMyValue NOTIFY
  myValueChanged); //use custom getter and setter
  
  public:
   AppSettings(QObject* parent = 0);
  
   MyCustomType myValue() const;
   void setMyValue(const MyCustomType value);
   Q_SIGNAL void myValueChanged(const MyCustomValue value);
  }
 
 I like the idea!

+1
-- 
Rafael Roquetto | rafael.roque...@kdab.com | Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel. Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - Qt Experts - Platform-independent software solutions


smime.p7s
Description: S/MIME cryptographic signature
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Rafael Roquetto
On Wed, Oct 15, 2014 at 02:36:51PM +0200, Thiago Macieira wrote:
 On Wednesday 15 October 2014 08:39:27 Rafael Roquetto wrote:
  No! Not everyone uses Creator or whatever tool. I strongly dislike the idea
  of having to depend on a specific toolset. What is productive to some can
  be counter-productive to others. We need to KISS and use a human-readable
  format that offers the possibility to be manually edited if desired. And
  for that XML is a huge PITA IMHO. Please, please don't go down that road.
 
 The only issue is that the more human-editable the source form is, the harder 
 it is to write a parser and toolchain to configure.

Of course, we need to find a compromise in between. In other words, KISS but
no simpler. I am not suggesting something based on natural language,
actually, I am just arguing against an approach which enforces the usage of an
specific tool/editor as an alternative for a better designed textual format.
Specially when it comes to settings or schemas.

The suggested QTypedSettings class is an example of a human-editable source
form which is easy to read (*arguably* easier than condensed XML *IMHO*) being 
at the same
time tool agnostic (any editor will do) and parser/compiler friendly.

-- 
Rafael Roquetto | rafael.roque...@kdab.com | Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel. Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - Qt Experts - Platform-independent software solutions


smime.p7s
Description: S/MIME cryptographic signature
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-15 Thread Thiago Macieira
On Wednesday 15 October 2014 10:09:47 Rafael Roquetto wrote:
 On Wed, Oct 15, 2014 at 02:36:51PM +0200, Thiago Macieira wrote:
  On Wednesday 15 October 2014 08:39:27 Rafael Roquetto wrote:
   No! Not everyone uses Creator or whatever tool. I strongly dislike the
   idea
   of having to depend on a specific toolset. What is productive to some
   can
   be counter-productive to others. We need to KISS and use a
   human-readable
   format that offers the possibility to be manually edited if desired. And
   for that XML is a huge PITA IMHO. Please, please don't go down that
   road.
  
  The only issue is that the more human-editable the source form is, the
  harder it is to write a parser and toolchain to configure.
 
 Of course, we need to find a compromise in between. In other words, KISS but
 no simpler. I am not suggesting something based on natural language,
 actually, I am just arguing against an approach which enforces the usage of
 an specific tool/editor as an alternative for a better designed textual
 format. Specially when it comes to settings or schemas.
 
 The suggested QTypedSettings class is an example of a human-editable source
 form which is easy to read (*arguably* easier than condensed XML *IMHO*)
 being at the same time tool agnostic (any editor will do) and
 parser/compiler friendly.

I'm not sure you got my meaning.

How is a config editor tool in Qt Creator going to read  write those files? 
How 
is the code generator going to read the QTypedSettings source header to genete 
the equivalent .cpp?

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


[Development] QConfig update.

2014-10-14 Thread Tomaz Canabrava
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' QHashQString, 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

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);

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?

QConfigWatcher: created automatically via the .watcher() method on QConfig
and QConfigGroup

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();

TODO, but only after this part gets perfect, KconfigXT like automatic
creation of classes and structures based on a schema file.
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-14 Thread Milian Wolff
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' QHashQString, 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). 

 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.

 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 }
}

 QConfigWatcher: created automatically via the .watcher() method on QConfig
 and QConfigGroup

It should be the other way around, imo. Also see below.

 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?

 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.

Bye

-- 
Milian Wolff | milian.wo...@kdab.com | Software Engineer
KDAB (Deutschland) GmbHCo 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@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] QConfig update.

2014-10-14 Thread Tomaz Canabrava
On Tue, Oct 14, 2014 at 1:35 PM, Milian Wolff milian.wo...@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' QHashQString, 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.wo...@kdab.com | Software Engineer
 KDAB (Deutschland) GmbHCo KG, a KDAB Group company
 Tel. Germany +49-30-521325470, Sweden (HQ) +46-563-540090
 KDAB - Qt Experts - Platform-independent software solutions

 

Re: [Development] QConfig update.

2014-10-14 Thread Milian Wolff
On Tuesday 14 October 2014 13:44:30 Tomaz Canabrava wrote:
 On Tue, Oct 14, 2014 at 1:35 PM, Milian Wolff milian.wo...@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' QHashQString, 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.

Then provide a QSharedConfig or let the user store the QConfig himself, if it 
turns out to be a performance-bottleneck for him. If you add global state to 
QConfig, you'll need synchronization or otherwise you are doomed in a 
multithreaded application.

Also: If you add a cheap JSON cache, is it really worth to optimize at all?

Furthermore: If you keep the QConfig in memory all the time, you'll probably 
end up duplicating the stuff as soon as you add the fancy high-level interface 
on-top. QConfig will operate on JSON after all and you'll incur a conversion 
penalty whenever you read a value from it. The high-level interface should 
(hopefully) read the values once and store it internally in the proper type. 
If you don't do this and always read from QConfig, you'll end up with issues 
in this pattern:

void HighLevelConfig::setFoo(quint64 foo)
{
  if (foo == m_foo) {
return;
  }
  m_foo = foo;
  emit fooChanged(foo);
}

If this would read from QConfig, instead of directly comparing to the quint64 
m_foo member, you'll get rounding errors etc. pp. This, the more I think 
about it, is actually a big issue with a JSON cache in general. .ini does not 
have that issue as the byte-array gets interpreted based on the type you pass 
along (a kind of duck-typing). It might mean that you'll have to store 
everything as a string in JSON to prevent a loss of data when storing e.g. 
std::limitsquint64::max() (note: JSON only knows double). But storing 
everything as a string looses the difference between

foo=1

and

foo=1

Afaik this issue has not yet been discussed, has it?

   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.

Most applications, (all KDE applications btw), would then assert. Initially, 
no configuration file is available after all.

And again: Please do not overdesign QConfig. KISS! Add fancy schema-validation 
and stuff on-top of that. Don't remove something as essential as reading a 
setting with a default value fallback mechanism!

Bye
-- 
Milian Wolff | milian.wo...@kdab.com | Software Engineer
KDAB (Deutschland) GmbHCo 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@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development