Wizard: Improve QtQuick2 extension plugin

- Added options for Kit version
- Added CMake support for Qt6.2
- Added options for creating example project,
which uses the plugin

Task-number: QTCREATORBUG-26982
Change-Id: I808c01bce6e4015a679f2fd69767c13179a25ee5
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Artem Sokolovskii
2022-03-09 16:27:06 +01:00
parent 6f520f8783
commit b06db48869
8 changed files with 264 additions and 11 deletions

View File

@@ -0,0 +1,44 @@
cmake_minimum_required(VERSION 3.16)
project(%{ProjectName} VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
qt_add_library(%{ProjectName} STATIC)
qt_add_qml_module(%{ProjectName}
URI %{ProjectName}
VERSION 1.0
QML_FILES %{ObjectQml}
SOURCES %{ObjectSrc} %{ObjectHdr}
)
set_target_properties(%{ProjectName} PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_compile_definitions(%{ProjectName}
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(%{ProjectName}
PRIVATE Qt6::Quick)
target_include_directories(%{ProjectName} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
@if %{CreateExampleProject}
# Example Project
qt_add_executable(ExampleProject example/example.cpp)
qt_add_qml_module(ExampleProject
URI ExampleProjectApp
VERSION 1.0
QML_FILES example/example.qml
)
target_link_libraries(ExampleProject PRIVATE Qt6::Quick %{ProjectName}plugin)
target_compile_definitions(ExampleProject PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
@endif

View File

@@ -0,0 +1,23 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml/qqmlextensionplugin.h>
Q_IMPORT_QML_PLUGIN(%{ProjectName}Plugin)
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// The first subfolder is the libraryName followed by the regular
// folder structure: LibararyName/Subfolder
const QUrl url(u"qrc:/ExampleProjectApp/example/example.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

View File

@@ -0,0 +1,29 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Controls.Material
import %{ProjectName}
Window {
width: 640
height: 400
visible: true
title: qsTr("Example Project")
%{ObjectName}Controls {
id: controls
anchors.left: parent.left
anchors.top: parent.top
anchors.margins: 20
width: 100
height: 100
}
%{ObjectName} {
id: rect
anchors.left: controls.right
anchors.top: parent.top
anchors.margins: 20
width: 100
height: 100
}
}

View File

@@ -1,7 +1,9 @@
#include "%{ObjectHdr}" #include "%{ObjectHdr}"
#include <QPainter>
%{ObjectName}::%{ObjectName}(QQuickItem *parent) %{ObjectName}::%{ObjectName}(QQuickItem *parent)
: QQuickItem(parent) : QQuickPaintedItem(parent)
{ {
// By default, QQuickItem does not draw anything. If you subclass // By default, QQuickItem does not draw anything. If you subclass
// QQuickItem to create a visual item, you will need to uncomment the // QQuickItem to create a visual item, you will need to uncomment the
@@ -10,6 +12,16 @@
// setFlag(ItemHasContents, true); // setFlag(ItemHasContents, true);
} }
void %{ObjectName}::paint(QPainter *painter)
{
QPen pen(QColorConstants::Red, 2);
QBrush brush(QColorConstants::Red);
painter->setPen(pen);
painter->setBrush(brush);
painter->drawRect(0, 0, 100, 100);
}
%{ObjectName}::~%{ObjectName}() %{ObjectName}::~%{ObjectName}()
{ {
} }

View File

@@ -6,15 +6,16 @@
#define %{OBJECTGUARD} #define %{OBJECTGUARD}
@endif @endif
#include <QQuickItem> #include <QtQuick/QQuickPaintedItem>
class %{ObjectName} : public QQuickItem class %{ObjectName} : public QQuickPaintedItem
{ {
Q_OBJECT Q_OBJECT
QML_ELEMENT
Q_DISABLE_COPY(%{ObjectName}) Q_DISABLE_COPY(%{ObjectName})
public: public:
explicit %{ObjectName}(QQuickItem *parent = nullptr); explicit %{ObjectName}(QQuickItem *parent = nullptr);
void paint(QPainter *painter) override;
~%{ObjectName}() override; ~%{ObjectName}() override;
}; };

View File

@@ -0,0 +1,10 @@
import QtQuick %{QtQuickVersion}
Item {
id: root
Rectangle {
anchors.fill: root
color: "green"
}
}

View File

@@ -13,16 +13,23 @@
"options": "options":
[ [
{ "key": "ProjectFile", "value": "%{ProFile}" }, { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') === 'qmake' ? value('ProFile') : value('CMakeFile')}" },
{ "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" }, { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" },
{ "key": "CMakeFile", "value": "%{ProjectDirectory}/CMakeLists.txt" },
{ "key": "PluginBaseFileName", "value": "%{JS: value('ProjectName') + '_plugin'}" }, { "key": "PluginBaseFileName", "value": "%{JS: value('ProjectName') + '_plugin'}" },
{ "key": "PluginSrc", "value": "%{JS: Cpp.classToFileName(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++src'))}" }, { "key": "PluginSrc", "value": "%{JS: Cpp.classToFileName(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++src'))}" },
{ "key": "PluginHdr", "value": "%{JS: Cpp.classToFileName(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++hdr'))}" }, { "key": "PluginHdr", "value": "%{JS: Cpp.classToFileName(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++hdr'))}" },
{ "key": "ObjectSrc", "value": "%{JS: Cpp.classToFileName(value('ObjectName'), Util.preferredSuffix('text/x-c++src'))}" }, { "key": "ObjectSrc", "value": "%{JS: Cpp.classToFileName(value('ObjectName'), Util.preferredSuffix('text/x-c++src'))}" },
{ "key": "ObjectHdr", "value": "%{JS: Cpp.classToFileName(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" }, { "key": "ObjectHdr", "value": "%{JS: Cpp.classToFileName(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" },
{ "key": "ObjectQml", "value": "%{JS: Util.fileName(value('ObjectName') + 'Controls', 'qml')}" },
{ "key": "PluginName", "value": "%{JS: value('ProjectName').charAt(0).toUpperCase() + value('ProjectName').slice(1) + 'Plugin' }" }, { "key": "PluginName", "value": "%{JS: value('ProjectName').charAt(0).toUpperCase() + value('ProjectName').slice(1) + 'Plugin' }" },
{ "key": "PLUGINGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++hdr'))}" }, { "key": "PLUGINGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('PluginBaseFileName'), Util.preferredSuffix('text/x-c++hdr'))}" },
{ "key": "OBJECTGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" } { "key": "OBJECTGUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('ObjectName'), Util.preferredSuffix('text/x-c++hdr'))}" },
{ "key": "IsQt6", "value": "%{JS: value('QtVersion').IsQt6}" },
{ "key": "QtQuickVersion", "value": "%{JS: value('QtVersion').QtQuickVersion}" },
{ "key": "QtQuickFeature", "value": "%{JS: (value('QtQuickVersion')=='') ? 'QtSupport.Wizards.FeatureQt.6.2' : 'QtSupport.Wizards.FeatureQtQuick.%{QtQuickVersion}'}" },
{ "key": "CreateExampleProjectDefault", "value": false },
{ "key": "TargetName", "value": "%{JS: 'lib' + value('ProjectName')}" }
], ],
"pages": "pages":
@@ -32,12 +39,102 @@
"trShortTitle": "Location", "trShortTitle": "Location",
"typeId": "Project" "typeId": "Project"
}, },
{
"trDisplayName": "Define Build System",
"trShortTitle": "Build System",
"typeId": "Fields",
"enabled": "%{JS: !value('IsSubproject')}",
"data":
[
{
"name": "BuildSystem",
"trDisplayName": "Build system:",
"type": "ComboBox",
"persistenceKey": "BuildSystemType",
"data":
{
"index": 0,
"items":
[
{
"trKey": "CMake",
"value": "cmake",
"condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
},
{
"trKey": "qmake",
"value": "qmake",
"condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}"
}
]
}
}
]
},
{ {
"trDisplayName": "Custom Parameters", "trDisplayName": "Custom Parameters",
"trShortTitle": "Details", "trShortTitle": "Details",
"typeId": "Fields", "typeId": "Fields",
"data": "data":
[ [
{
"name": "QtVersion",
"trDisplayName": "Minimal required Qt version:",
"type": "ComboBox",
"persistenceKey": "QtQuick.minimumQtVersion",
"data":
{
"index": 0,
"items":
[
{
"trKey": "Qt 6.2",
"value":
{
"QtQuickVersion": "",
"IsQt6": true
}
},
{
"trKey": "Qt 5.15",
"condition": "%{JS: value('BuildSystem') === 'qmake'}",
"value":
{
"QtQuickVersion": "2.15",
"IsQt6": false
}
},
{
"trKey": "Qt 5.14",
"condition": "%{JS: value('BuildSystem') === 'qmake'}",
"value":
{
"QtQuickVersion": "2.14",
"IsQt6": false
}
},
{
"trKey": "Qt 5.13",
"condition": "%{JS: value('BuildSystem') === 'qmake'}",
"value":
{
"QtQuickVersion": "2.13",
"IsQt6": false
}
},
{
"trKey": "Qt 5.12",
"condition": "%{JS: value('BuildSystem') === 'qmake'}",
"value":
{
"QtQuickVersion": "2.12",
"IsQt6": false
}
}
]
}
},
{ {
"name": "ObjectName", "name": "ObjectName",
"trDisplayName": "Object class-name:", "trDisplayName": "Object class-name:",
@@ -59,6 +156,16 @@
"validator": "^[A-Za-z0-9]+([A-Za-z0-9-]*[A-Za-z0-9]+)?(\\.[A-Za-z0-9]+([-A-Za-z0-9]*[A-Za-z0-9]+)?)*$", "validator": "^[A-Za-z0-9]+([A-Za-z0-9-]*[A-Za-z0-9]+)?(\\.[A-Za-z0-9]+([-A-Za-z0-9]*[A-Za-z0-9]+)?)*$",
"trText": "com.mycompany.qmlcomponents" "trText": "com.mycompany.qmlcomponents"
} }
},
{
"name": "CreateExampleProject",
"trDisplayName": "Create example project",
"visible": "%{JS: value('BuildSystem') === 'cmake'}",
"type": "CheckBox",
"data":
{
"checked": "%{CreateExampleProjectDefault}"
}
} }
] ]
}, },
@@ -69,7 +176,7 @@
"enabled": "%{JS: !value('IsSubproject')}", "enabled": "%{JS: !value('IsSubproject')}",
"data": { "data": {
"projectFilePath": "%{ProjectFile}", "projectFilePath": "%{ProjectFile}",
"requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuick", "QtSupport.Wizards.FeatureQtQuick.2" ] "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuick", "%{QtQuickFeature}" ]
} }
}, },
{ {
@@ -87,7 +194,14 @@
{ {
"source": "project.pro", "source": "project.pro",
"target": "%{ProFile}", "target": "%{ProFile}",
"openAsProject": true "openAsProject": true,
"condition": "%{JS: value('BuildSystem') === 'qmake'}"
},
{
"source": "CMakeLists.6.x.txt",
"target": "CMakeLists.txt",
"openAsProject": true,
"condition": "%{JS: value('BuildSystem') === 'cmake'}"
}, },
{ {
"source": "qmldir", "source": "qmldir",
@@ -96,11 +210,13 @@
{ {
"source": "plugin.cpp", "source": "plugin.cpp",
"target": "%{PluginSrc}", "target": "%{PluginSrc}",
"openInEditor": true "openInEditor": true,
"condition": "%{JS: value('BuildSystem') === 'qmake'}"
}, },
{ {
"source": "plugin.h", "source": "plugin.h",
"target": "%{PluginHdr}" "target": "%{PluginHdr}",
"condition": "%{JS: value('BuildSystem') === 'qmake'}"
}, },
{ {
"source": "object.cpp", "source": "object.cpp",
@@ -110,6 +226,20 @@
"source": "object.h", "source": "object.h",
"target": "%{ObjectHdr}" "target": "%{ObjectHdr}"
}, },
{
"source": "object.qml",
"target": "%{ObjectQml}"
},
{
"source": "example/example.cpp",
"target": "example/example.cpp",
"condition": "%{JS: value('CreateExampleProject')}"
},
{
"source": "example/example.qml",
"target": "example/example.qml",
"condition": "%{JS: value('CreateExampleProject')}"
},
{ {
"source": "../git.ignore", "source": "../git.ignore",
"target": ".gitignore", "target": ".gitignore",

View File

@@ -1265,7 +1265,11 @@ void ComboBoxField::initializeData(MacroExpander *expander)
ListField::initializeData(expander); ListField::initializeData(expander);
// refresh also the current text of the combobox // refresh also the current text of the combobox
auto w = qobject_cast<QComboBox *>(widget()); auto w = qobject_cast<QComboBox *>(widget());
w->setCurrentIndex(selectionModel()->currentIndex().row()); const int row = selectionModel()->currentIndex().row();
if (row < w->count() && row > 0)
w->setCurrentIndex(row);
else
w->setCurrentIndex(0);
} }
QVariant ComboBoxField::toSettings() const QVariant ComboBoxField::toSettings() const