[Development] QML engine C++ class renaming

Alan Alpert alan.alpert at nokia.com
Thu Feb 16 12:14:07 CET 2012

On Thu, 16 Feb 2012 20:47:49 ext Olivier Goffart wrote:
> On Thursday 16 February 2012 12:26:50 Alan Alpert wrote:
> > The way QML compatibility is supposed to work is different from C++. Even
> > for a minor version, you don't always just jump to the latest version.
> > Your application continues using the version it was developed for until
> > you choose to update it, deliberately, to a more recent version (note
> > that if the C++ library updates you may get bugfixes transparently, this
> > is primarily about feature additions/changes).
> This is a falacy!
> When you upgrade the runtime, you anyway run into compatibility issues.
> The application has been tested to work with the version QtQuick x.y, its
> bug have been work arounded or avoided.
> Now, you come with a new runtime, that pretends to still be load x.y, but
> still fixes bugs? but often, fixing bugs mean also introducing new ones,
> new bugs against which the application has not been tested.  And the bugs
> you fix have most likely been work arounded.

For bugfixes I meant the ones that were safe in this regard. E.g a bug like 
"calling foo crashes qml" would get fixed but theoretically, a bug like 
"flickable is always 10 too short" would be in a minor version so that you 
could remove your +10 at exactly the right time.

For introducing bugs, I can assure you that we already try not to do that ;) .
> But why in QtQuick x.(y+1) must I change the import statement. Is there so
> many incompatibilities that will make porting so difficult?

Probably not. You'll probably change the import statement and it's perfect. 
But you can check per application. And consider the two major cases:

A) Major version change. Let's be honest, you'll be lucky if nothing broke. 
This is where there are so many incompatibilities that porting needs to be 
taken seriously (even if we try sometimes to keep it from being difficult).

B) Minor version change. This just added some new features. If you don't need 
to use the new features, just keep importing the old version and it's fine. If 
you do need them, you signify that with an updated import at the time that you 
update your code to use new features. Note that because minor versions can add 
new features, it will always have the possibility of adding symbols (suddenly, 
there's a myObject property on this object and it shadows the one you were 
expecting to get from the root object sort of thing).

> The versioning in C++ is much better in that respect:
> void MyApplication::drawSomething(QPainter *p) {
> #if QT_VERSION >= 0x050100
> 	p->drawFastTexture(m_texture);
> #else
> 	//slow path for old version of Qt
> 	p->drawPixmap(m_texture.toPixmap());
> #endif
> }
> void MyApplication::buttonPressed() {
> #if QT_VERSION >= 0x050100
> 	if (qVersion() >= 0x050200) {
> 		QAwsomeFeature::run(m_data);
>     } else {
>        //workaround the bug in QAwsomeFeature with green nodes
>        QAwsomeFeature::run(m_data->removeGreenNodes());
>     }
> #else
> 	showDialog("sorry, not available with this version of Qt");
> #endif
> }
> Then the same source code compiles with different version of Qt and uses
> the newer version of Qt if available. That is usefull for open source
> project for example, where the distribution you target may or may not have
> the newer Qt.

It will be interesting to see how this works out in practice - once there are 
distros that ship a different version of Qt. I may have seen qt 4.8 in a 
fedora somewhere, so this issue is just emerging. QML's approach doesn't seem 
as good for supporting multiple Qt versions "at once", but I'm not convinced 
that's the common case. (FYI: If you're making the app a QML/C++ hybrid like 
you should then you can still use those #ifdefs... but it's less than ideal.)

> Of course, the inconvinient is that C++ is a static compiled language, and
> then it needs to be compiled.
> But with QML you artifitially have this problem because you need to pick
> you version.

We actually do a lot of that sort of thing in QML. JS is an extremely dynamic 
language, and we bolt on QML with static types and a frozen global object. 
Because some restrictions make life a lot easier. This is one of them. If you 
had it left open, sure lots of cases would just work. But you'd also get the 
occasional problem which is a real pain in the ass, like a new symbol being 
added that shadows a variable name of yours. Or a behavioral change to an 
element you weren't expecting. This versioning scheme attempts to mitigate 
those risks by making it an opt-in upgrade, instead of letting the risks fly 
or (even worse) mitigating them by not adding new features at this rate.

Alan Alpert
Senior Engineer
Nokia, Qt Development Frameworks

More information about the Development mailing list