Qt Quick Designer plug-in
-
This is a bit more complicated. ;)
You could register a new type of Widget to QML in your plugin. The property editor "sheets" are written in QML an can use the widget then.
The QML code for the existing property sheets can be found here:
creator\share\qtcreator\qmldesigner\propertyeditor
-
This is what I was afraid of :(
And can this be done as a plug-in and installed in officially released Creator or I need to build it with Creator source code?
How to make a connection between new property type and property editor "sheet"?
-
is it possible to add a context menu plugin instead? This would work for me as well. I have found an example how to do this in Qt Designer ("link":http://doc-snapshot.qt-project.org/4.8/designer-creating-custom-widgets-extensions.html) but can this be done in Qt Quick Designer?
-
Do you want to add edit functionality for a new property to any Item or just a new one?
The first would be impossible, but the second is possible by adding a new sheet in QML for the new Item and providing a custom widget as a plugin.
The connection would be that you use a new specific widget in the sheet that you register to QML in your plugin.
The plugin has to be build source compatible to the Qt Creator release which is possible.The concept of a menu plugin instead does not exist, yet. There is of course the possibility to contribute a nice interface to Qt Creator/Qt Quick Designer via Qt Project.
In an ideal world there would exist interfaces for extending context menus, delegates in the form editor and of course customizing the property editor (which is already possible but there are known issues limits. For example we currently do not export the classes for accessing the internal model. We could do this but this would mean longer loading times for everybody.).
All of this comes with a definite maintenance burden and atm we just do not have the resources.
Currently we focus on Qt Quick 2.0/Qt5 support.
Contributions are of course welcome.
-
Can you provide an example or a link to something similar? I'm new in the subject so its hard to figure it out :(
-
I have made some progress but stuck now.
I have created sample project Qt Quick Application, and my new type for properties:
@
class MyType : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(string name READ getName WRITE setName)public:
MyType(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent) { }string getName() const { return m_name; } void setName(const string &name) { m_name = name; }
private:
string m_name;
};
@and registered it in main()
@
qmlRegisterType<MyType>("MyUri", 1, 0, "myType");
@I have found a place in QmlDesigner plugin for Qt Creator where it generates templates for properties types and added there my template, reusing available ComboBox component: templateGeneration() src\plugins\qmldesigner\components\propertyeditor\propertyeditor.cpp:
@
if (typeName == "myType") {
qmlTemplate += QString(QLatin1String(
"QWidget {\nlayout: HorizontalLayout {\nLabel {\ntext: "%1"\ntoolTip: "%1"\n}\nComboBox {\nbackendValue: backendValues.%2\nbaseStateFlag: isBaseState\nitems : { ["test value 1", "test value 2"] }\n}\n}\n}\n"
)).arg(name).arg(properName);
emptyTemplate = false;
}
@And it works, when I create a QML Component that has a property of this type:
@
import QtQuick 1.1
import MyUri 1.0Rectangle
{
property myType myVariable: myType {
name: ""
}
width: 59
height: 36
}
@And use it in a different component:
@
TestComponent
{width: 71 height: 68 radius: 1
}
@I see a nice combo box in property editor displaying my two hard coded values.
But I do not know how to make the QmlDesigner to put selected value from combo box into the name property of myType.
@
TestComponent
{width: 71 height: 68 radius: 1 myVariable: myType { name: "test value 1" <---------------------------- }
}
@I know that the value assignment is in changeValue() src\plugins\qmldesigner\components\propertyeditor\propertyeditor.cpp:~450
@
if (castedValue.isValid() && !castedValue.isNull()) {
m_locked = true;
fxObjectNode.setVariantProperty(propertyName, castedValue);
m_locked = false;
}
@but castedValue.isNull() is true and nothing happens.
Any idea where to go now?
-
What you are trying to do is quite sophisticated.
Means that we did not anticipate people would try this ;)qmlRegisterType<MyType>("MyUri", 1, 0, "myType");
This registers your type in the code model, so we know about it. This is not sufficient to render your component (Which is not your question). If you also want to see your component in the Designer you have to make it a plugin and install it in the imports directory like the official plug-ins coming with Qt.
What you do is creating a generic ComboBox for your custom item. But the generic ComoBox does not know how to handle a property of type MyType.
What we did for cases like this (e.g. Gradient) is writing custom controls in C++ and expose those to .qml. You would have to create: MyTypeCustomControl and expose it like our Gradient editing.
Actually we are revisiting extending the property editor and hopefully it will be a lot easier in the future.
One Idea would be to automatically expose myVariable in the property editor as a subsection.
Then the user would get a "mini" property editor for MyType inside the property editor for TestComponent.One immediate problem I see is that a property like myVariable is super flexible.
In practice one could even subclass from MyType and assign the subclass. This is properly even a use case. And then it gets too complicated in the ui.
We have to find the line between usefulness and complexity.For now I would suggest creating property aliases in TestComponent for all the relevant properties of
MyType.We definitely have to find a solution for types like font.
But even now you can write a custom control in C++ put it in a QtQuick Designer Plugin and register it as qmlRegisterType<T>("Bauhaus",1,0,"T");
Then it is available in the property editor.
And we probably should make templateGeneration() expendable (without patching).
Already you could write a property pane for TestComponent by hand (.qml). This is also an area we will clean up, polish and then document.
-
Just to clarify, I do not want to write property pane for TestComponent or any other componet. I want to have my new custom, special type (myType) for properties that can be used in many QML components.
The MyType is complex, it will have more that one property, and I want them to be filled in automatically based on single user action - selecting one value from ComboBox - one selection results in setting complex property to value. I imagine that QMLDesigner create an instance of myType, assign it to myVariable property and generates this:
@
myVariable: myType {
name: "test value 1"
}
@I will try to check the Gradient.
But the starndard ComboBox.qml has something like this
@
QComboBox {
id: box
property variant backendValue: comboBox.backendValue
onCurrentTextChanged: { backendValue.value = currentText; evaluate(); }
@here a value from QComboBox is assigned to backendValue.value on change. I would expect that I get this value as castedValue in changeValue() src\plugins\qmldesigner\components\propertyeditor\propertyeditor.cpp:~450. The castedValue is even QString which is what I expected by why it is empty? I must be missing something...
At the end I will probably create MyComboBox.qml that will do more - load items dinamically based on project configuration. But at this point I wanted to figure out how all this value passing from property editor to QML file works.
By the way, how to add custom entries to .qmlproject and access it from propertyeditor.cpp or QML?
-
ComboBox is written for enums.
I understand what you want to achieve. Right now the only way is to write the special ComboBox you need in C++ and expose this like the gradient editor for example.
-
And how about accessing .qmlproject or .pro files? Let say that I would like to add there a list of items that should be placed in MyComboBox. So, MyComboBox C++ implementation needs to obtain reference to the project.
-
Did you find a solution? I've an analog problem with a string property named sscName that I want to be set using a combobox. I found a dirty trick that works in my situation (the property name is known) but I'd like to find a clean approach to the problem.
My dirty solution it was to modify :
share/qtcreator/qmldesigner/propertyeditor/PropertyTemplates/StringEditorTemplate.templateQWidget {
layout: HorizontalLayout {
Label {
text: "%1"
toolTip: "%1"
}
LineEdit {
backendValue: backendValues.%2
baseStateFlag: isBaseStateComponent.onCompleted : { if (backendValues.%2.name != "sscName") visible = true; else visible = false; } }
ComboBox {
baseStateFlag: isBaseState
minimumHeight: 22;
items : { ["Pompa", "Elica", "Porta"] }
backendValue : backendValues.%2Component.onCompleted : { if (backendValues.%2.name == "sscName") visible = true; else visible = false; } currentText: backendValues.%2.value; onItemsChanged: { currentText = backendValues.%2.value; } } }
}
A cleaner approach I attempted it was to define a new custom type
for SscName:Item
{
default property string value;
}(for testing purpose defined directly inside the project)
to add a new property template called SscNameEditorTemplate.template:
QWidget {
layout: HorizontalLayout {
Label {
text: "%1"
toolTip: "%1"
}ComboBox
{
baseStateFlag: isBaseState
minimumHeight: 22;
items : { ["Pompa", "Elica", "Porta", "Ciccio"] }
backendValue : backendValues.%2currentText: backendValues.%2.value; onItemsChanged: { currentText = backendValues.%2.value; }
}
}
}
But as happens to spaluc, backendValues.%2.value is not valid while the editor setup the property editor. If Iive understood a c++ plugin to implement the type SscName is needed. Any suggestion on how to implement it and on where tu put the library to be loaded by qt creator?
-
No, I have not moved any further.