ImaginativeThinking.ca


A developers blog

How to resolve C++ Component naming conflicts in QML

By: Brad

In this tutorial I’ll show you how to resolve Naming conflicts between C++ Components within a QML script.

conflict

Lets say your importing two separate models (ca.imaginativethinking.tutorial.objectone and ca.imaginativethinking.tutorial.objecttwo) and lets assume they are from two different third party vendors which you have little control over. Now what happens if they both contain a component which has the same name.

qmlRegisterType<ObjectOne>("ca.imaginativethinking.tutorial.objectone", 1, 0, "MyObject");
qmlRegisterType<ObjectTwo>("ca.imaginativethinking.tutorial.objecttwo", 1, 0, "MyObject");

Lets assume through libraries that your linking against the above code is run which registers two objects (ObjectOne and ObjectTwo) with the same QML keyword name (MyObject) within two separate modules. Now if you never imported these two modules within the same QML script then you don’t have any issues but what if you wanted to use both these objects (or one of these object and another object which is also within one of these two modules) in the same QML script? Your going to have a naming conflict. When you declare MyObject {...} the QML engine won’t know which object you meant to instantiate.

The QML engine can not import two components with the same name into the same namespace.

When the QML engine processes a QML script it reads it line by line going from top to bottom. If your script imports ca.imaginativethinking.tutorial.objectone first then imports ca.imaginativethinking.tutorial.objecttwo the engine will first register ObjectOne with the name MyObject then it will register ObjectTwo with the name MyObject effectively un-registering ObjectOne.

import ca.imaginativethinking.tutorial.objectone 1.0
import ca.imaginativethinking.tutorial.objecttwo 1.0

//Would be ObjectTwo not ObjectOne.
MyObject{ 
    id: objectOne
}

So How can I use both ObjectOne and ObjectTwo in the same QML script?

The good news is that Qt didn’t leave you high and dry they have a built in mechanism to deal with naming conflicts.

When you import modules in your QML script all the components in the module are imported into a non-qualified local namespace. Think of the import statement as something similar to a combination of the #include<> and using statements in C++. In C++ you deal with naming conflicts by putting your classes into different qualified namespaces; when you include a class you need to access the class by qualifying which namespace your intending to use. Of course typing std::string over and over again is a pain so C++ also has a using statement where you can tell the compiler that within this file scope put all the classes into a local non-qualified namespace so that when you see string know to use std::string. Its a nicety to save typing and where C++ made that an opt-in nicety QML made it an opt-out. The import statement in QML by default puts all the imported components into a non-qualified local namespace so that you can access any of the components within the module without qualification.

Most of the time this work without issues and lets you write your QML script with far less typing but in the above case its landed us in a naming conflict problem. To resolve this you can tell the import statement to place the components into a qualified local namespace instead by using the as keyword.

import ca.imaginativethinking.tutorial.objectone 1.0 as ObjectOne
import ca.imaginativethinking.tutorial.objecttwo 1.0 as ObjectTwo

By adding the as keyword and a qualification name to your script you can now explicitly state which module you intend to use.

import ca.imaginativethinking.tutorial.objectone 1.0 as ObjectOne
import ca.imaginativethinking.tutorial.objecttwo 1.0 as ObjectTwo

ObjectOne.MyObject {
    id: objectOne
}
ObjectTwo.MyObject {
    id: objectTwo
}

So there you go that is how you can resolve naming conflicts between C++ Modules.

You can download a sample application which illustrate the above here:
Naming Conflict Sample 1: QML Component Conflicts
Naming Conflict Sample 2: C++ Component Conflicts

Here is where you can find the official Qt documentation on the import statement

Thank you I hope you have enjoyed and found this tutorial helpful. Feel free to leave any comments or questions you might have below and I’ll try to answer them as time permits.

Until next time think imaginatively and design creatively

Brad

My interest in computer programming started back in high school and Software Development has remained a hobby of mine ever since. I graduated as a Computer Engineering Technologist and have been working as a Software Developer for many years. I believe that software is crafted; understanding that how it is done is as important as getting it done. I enjoy the aesthetics in crafting elegant solutions to complex problems and revel in the knowledge that my code is maintainable and thus, will have longevity. I hold the designation Certified Technician (C.Tech.) with the Ontario Association of Computer Engineering Technicians and Technologists (OACETT), have been certified as a Professional Scrum Master level 1 (PSM I) and as a Professional Scrum Developer level 1 (PSD I) by Scrum.org as well as designated as an Officially Certified Qt Developer by the Qt Company. For more on my story check out the about page here

Feel free to write a reply or comment.