Qt 慢慢学

自定义 Qt Creator 向导

2019-12-06  本文已影响0人  AbeirL

我们在使用 Qt Creator 创建项目时,弹出的 New File or Project 对话框,便是创建项目的向导。我们可以自定义自己的向导,使用自己的项目模板,来生成自己的初始项目。

向导

Qt Creator 支持json、xml两种格式的向导描述文件,但是xml格式官方已不推荐使用,以下只介绍json格式。

向导文件存放于 Qt Creator 安装目录中的 share/qtcreator/templates/wizards 目录下,向导文件包含用于生成目标的模板文件和 wizard.json 向导配置文件。开发者还可以将制作的向导文件放置在 $HOME/.config/QtProject/qtcreator/templates/wizards 中,放在此目录下的向导只对当前用户有效。
向导文件中支持使用变量,形如:%\{<variableName>\},在 wizard.json 文件中可以定义 options 区域,用于申明新变量和值。
变量支持JS表达式,形如:%\{JS:<JavaScript expression>\},表达式会被计算并将结果转换成字符串。在表达式中也可以使用定义过的变量,形如:value('<variableName>'),此返回的值可以使字符串、列表、字典或布尔。

另外,除了能使用 wizard.json 中定义的变量以外,Qt Creator 还提供了一些内置的变量。

开发向导时,官方推荐在启动 Qt Creator 时添加 -customwizard-verbose 参数,以便输出更多调试信息。

添加向导

Qt Creator 提供了一个快捷键 Factory.Reset,用于在不重启IDE的情况下重新加载向导。默认情况下,该快捷键没有对应实际的按键,在 工具 > 选项... > 环境 > 键盘 中搜索 Factory.Reset,设置自己习惯的按键即可,方便调试。

下面我们通过官方的C++类创建向导,来分析模板文件的内容。
示例位于 Qt Creator 安装目录下 share/qtcreator/templates/wizards/classes/cpp 中。

C++类创建向导中的模板文件

首先打开 wizard.json 配置文件

{
    "version": 1,
    "supportedProjectTypes": [ ],
    "id": "A.Class",
    "category": "O.C++",
    "trDescription": "Creates a C++ header and a source file for a new class that you can add to a C++ project.",
    "trDisplayName": "C++ Class",
    "trDisplayCategory": "C++",
    "iconText": "h/cpp",
    "enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",

    "options":
    [
        { "key": "TargetPath", "value": "%{Path}" },
        { "key": "HdrPath", "value": "%{Path}/%{HdrFileName}" },
        { "key": "SrcPath", "value": "%{Path}/%{SrcFileName}" },
        { "key": "CN", "value": "%{JS: Cpp.className(value('Class'))}" },
        { "key": "Base", "value": "%{JS: value('BaseCB') === '' ? value('BaseEdit') : value('BaseCB')}" },
        { "key": "isQObject", "value": "%{JS: [ 'QObject', 'QWidget', 'QMainWindow', 'QDeclarativeItem', 'QQuickItem'].indexOf(value('Base')) >= 0 }" },
        { "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard(value('Class'), Util.suffix(value('HdrFileName')))}" },
        { "key": "SharedDataInit", "value": "%{JS: (value('IncludeQSharedData')) ? 'data(new %{CN}Data)' : '' }" }
    ],

    "pages":
    [
        {
            "trDisplayName": "Define Class",
            "trShortTitle": "Details",
            "typeId": "Fields",
            "data" :
            [
                {
                    "name": "Class",
                    "trDisplayName": "Class name:",
                    "mandatory": true,
                    "type": "LineEdit",
                    "data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*|)" }
                },
                {
                    "name": "BaseCB",
                    "trDisplayName": "Base class:",
                    "type": "ComboBox",
                    "data":
                    {
                        "items": [ { "trKey": "<Custom>", "value": "" },
                                   "QObject", "QWidget", "QMainWindow", "QDeclarativeItem", "QQuickItem" ]
                    }
                },
                {
                    "name": "BaseEdit",
                    "type": "LineEdit",
                    "enabled": "%{JS: value('BaseCB') === ''}",
                    "mandatory": false,
                    "data":
                    {
                        "trText": "%{BaseCB}",
                        "trDisabledText": "%{BaseCB}"
                    }
                },

                {
                    "name": "Sp1",
                    "type": "Spacer",
                    "data": { "factor": 2 }
                },
                {
                    "name": "IncludeQObject",
                    "trDisplayName": "Include QObject",
                    "type": "CheckBox",
                    "data":
                    {
                        "checkedValue": "QObject",
                        "uncheckedValue": "",
                        "checked": "%{JS: value('BaseCB') === 'QObject'}"
                    }
                },
                {
                    "name": "IncludeQWidget",
                    "trDisplayName": "Include QWidget",
                    "type": "CheckBox",
                    "data":
                    {
                        "checkedValue": "QWidget",
                        "uncheckedValue": "",
                        "checked": "%{JS: value('BaseCB') === 'QWidget'}"
                    }
                },
                {
                    "name": "IncludeQMainWindow",
                    "trDisplayName": "Include QMainWindow",
                    "type": "CheckBox",
                    "data":
                    {
                        "checkedValue": "QMainWindow",
                        "uncheckedValue": "",
                        "checked": "%{JS: value('BaseCB') === 'QMainWindow'}"
                    }
                },
                {
                    "name": "IncludeQDeclarativeItem",
                    "trDisplayName": "Include QDeclarativeItem - Qt Quick 1",
                    "type": "CheckBox",
                    "data":
                    {
                        "checkedValue": "QDeclarativeItem",
                        "uncheckedValue": "",
                        "checked": "%{JS: value('BaseCB') === 'QDeclarativeItem'}"
                    }
                },
                {
                    "name": "IncludeQQuickItem",
                    "trDisplayName": "Include QQuickItem - Qt Quick 2",
                    "type": "CheckBox",
                    "data":
                    {
                        "checkedValue": "QQuickItem",
                        "uncheckedValue": "",
                        "checked": "%{JS: value('BaseCB') === 'QQuickItem'}"
                    }
                },
                {
                    "name": "IncludeQSharedData",
                    "trDisplayName": "Include QSharedData",
                    "type": "CheckBox",
                    "data":
                    {
                        "checkedValue": "QSharedData",
                        "uncheckedValue": "",
                        "checked": false
                    }
                },
                {
                    "name": "Sp2",
                    "type": "Spacer"
                },

                {
                    "name": "HdrFileName",
                    "type": "LineEdit",
                    "trDisplayName": "Header file:",
                    "mandatory": true,
                    "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++hdr'))}" }
                },
                {
                    "name": "SrcFileName",
                    "type": "LineEdit",
                    "trDisplayName": "Source file:",
                    "mandatory": true,
                    "data": { "trText": "%{JS: Cpp.classToFileName(value('Class'), Util.preferredSuffix('text/x-c++src'))}" }
                },
                {
                    "name": "Path",
                    "type": "PathChooser",
                    "trDisplayName": "Path:",
                    "mandatory": true,
                    "data":
                    {
                        "kind": "directory",
                        "basePath": "%{InitialPath}",
                        "path": "%{InitialPath}"
                    }
                }
            ]
        },
        {
            "trDisplayName": "Project Management",
            "trShortTitle": "Summary",
            "typeId": "Summary"
        }
    ],

    "generators":
    [
        {
            "typeId": "File",
            "data":
            [
                {
                    "source": "file.h",
                    "target": "%{HdrPath}",
                    "openInEditor": true,
                    "options": [
                        { "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
                        { "key": "Cpp:License:ClassName", "value": "%{CN}" }
                    ]
                },
                {
                    "source": "file.cpp",
                    "target": "%{SrcPath}",
                    "openInEditor": true,
                    "options": [
                        { "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
                        { "key": "Cpp:License:ClassName", "value": "%{CN}" }
                    ]
                }
            ]
        }
    ]
}

页面

配置在 wizard.json 文件的 pages 区域中

Field

字段页。使用指定的组件定义页面,组件的说明详见【组件】部分

{
        "trDisplayName": "Define Class",
        "trShortTitle": "Details",
        "typeId": "Fields",
        "data" :
        [
            {
                "name": "Class",
                "trDisplayName": "Class name:",
                "mandatory": true,
                "type": "LineEdit",
                "data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)+[a-zA-Z_][a-zA-Z_0-9]*|)" }
            },
            ...
        ]
}

File

文件页。可以省略 data 项或设置 data 为空对象

{
    "trDisplayName": "Location",
    "trShortTitle": "Location",
    "typeId": "File"
}

Form

表单页。可以省略 data 项或设置 data 为空对象

{
    "trDisplayName": "Choose a Form Template",
    "trShortTitle": "Form Template",
    "typeId": "Form"
}

Kits

工具页。data 项如下:

{
    "trDisplayName": "Kit Selection",
    "trShortTitle": "Kits",
    "typeId": "Kits",
    "enabled": "%{IsTopLevelProject}",
    "data": { "projectFilePath": "%{ProFileName}" }
}

Project

项目页。不包含 data 项或者 data 项是一个对象,对象仅有一个 trDescription 属性,在生成的页面中显示

{
    "trDisplayName": "Project Location",
    "trShortTitle": "Location",
    "typeId": "Project",
    "data": { "trDescription": "A description of the wizard" }
}

Summary

摘要页。不包含 data 项
如果创建的是顶级项目,则设置变量 IsSubproject 为空字符串,否则设置为 yes,并设置 VersionControl 变量为正在使用的版本控制系统的ID

{
    "trDisplayName": "Project Management",
    "trShortTitle": "Summary",
    "typeId": "Summary"
}

VcsCommand

版本控制页。设置版本控制并显示结果。data 项为对象,属性如下:

VcsConfiguration

版本控制配置页。提供用户配置版本控制系统。data 项为对象,属性如下:

组件

Field 页面中可使用的组件,包含:

通用的组件的配置如下:

以下为各个组件和组件特有的配置

CheckBox

多选框

{
    "name": "IncludeQObject",
    "trDisplayName": "Include QObject",
    "type": "CheckBox",
    "data":
    {
        "checkedValue": "QObject",
        "uncheckedValue": "",
        "checked": "%{JS: value('BaseCB') === 'QObject' ? 'true' : 'false'}"
    }
}

ComboBox

下拉列表

{
    "name": "BaseCB",
    "trDisplayName": "Base class:",
    "type": "ComboBox",
    "data":
    {
        "items": [ { "trKey": "<Custom>", "value": "" },
                   "QObject", "QWidget", "QMainWindow", "QDeclarativeItem", "QQuickItem" ]
    }
}

IconList

带有图标的下拉列表

{
    "name": "ChosenBuildSystem",
    "trDisplayName": "Choose your build system:",
    "type": "IconList",
    "data":
    {
        "items": [
            { "trKey": "Qbs", "value": "qbs", "icon": "qbs_icon.png", "trToolTip": "Building with Qbs." },
            { "trKey": "QMake", "value": "qmake", "icon": "qmake_icon.png", "trToolTip": "Building with QMake." }
        ]
    }
}

Label

标签。直接显示文本

{
    "name": "LabelQQC_2_0",
    "type": "Label",
    "span": true,
    "visible": "%{JS: value('CS') === 'QQC_2_0'}",
    "data":
    {
        "wordWrap": true,
        "trText": "Creates a deployable Qt Quick 2 application using Qt Quick Controls.",
    }
}

LineEdit

单行文本编辑框。占用一行,包含了标签和输入框

{
    "name": "Class",
    "trDisplayName": "Class name:",
    "mandatory": true,
    "type": "LineEdit",
    "data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)+[a-zA-Z_][a-zA-Z_0-9]*|)" }
}
{
    "name": "BaseEdit",
    "type": "LineEdit",
    "enabled": "%{JS: value('BaseCB') === '' ? 'true' : 'false'}",
    "mandatory": false,
    "data":
    {
        "trText": "%{BaseCB}",
        "trDisabledText": "%{BaseCB}"
    }
}

PathChooser

路径选择器

{
    "name": "Path",
    "type": "PathChooser",
    "trDisplayName": "Path:",
    "mandatory": true,
    "data":
    {
        "kind": "existingDirectory",
        "basePath": "%{InitialPath}",
        "path": "%{InitialPath}"
    }
}

Spacer

空行间隔

{
    "name": "Sp1",
    "type": "Spacer",
    "data":
    {
        "factor": 2
    }
}

TextEdit

多行文件编辑框

{
    "name": "TextField",
    "type": "TextEdit",
    "data" :
    {
        "trText": "This is some text",
        "richText": true
    }
}

生成器

File

使用定义好的模板文件生成项目文件。提供 data 区域,配置每一个模板文件。
data 是一个对象,属性如下:

Scanner

扫描 %\{TargetPath\} 路径,生成所有此路径中找到的文件。提供 data 区域,配置筛选条件。
data 是一个对象,属性如下:

上一篇 下一篇

猜你喜欢

热点阅读