QT CREATOR 插件开发:添加新的工程类型(上)

2023-10-30

Qt Creator 中,新的工程类型将出现在“文件 -> 新建”菜单项中;我们可以通过打开的选择工程类型的对话框来找到所需要的工程:

Qt Creator 新建工程

在本章中,我们将学习如何向上面所示的对话框中添加新的工程类型。

Core::IWizard接口

Qt Creator 提供了Core::IWizard接口,用于实现添加新的工程类型。该接口在 src/plugins/coreplugin/dialogs/iwizard.h 中声明:

class CORE_EXPORT IWizard
    : public QObject
{
    Q_OBJECT
public:
    enum WizardKind {
        FileWizard = 0x01,
        ClassWizard = 0x02,
        ProjectWizard = 0x04
    };
    Q_DECLARE_FLAGS(WizardKinds, WizardKind)

    IWizard(QObject *parent = 0) : QObject(parent) {}
    virtual ~IWizard() {}

    virtual WizardKind kind() const = 0;
    virtual QIcon icon() const = 0;
    virtual QString description() const = 0;
    virtual QString displayName() const = 0;
    virtual QString id() const = 0;

    virtual QString category() const = 0;
    virtual QString displayCategory() const = 0;

    virtual void runWizard(const QString &path, QWidget *parent) = 0;

    // Utility to find all registered wizards
    static QList allWizards();
    // Utility to find all registered wizards of a certain kind
    static QList wizardsOfKind(WizardKind kind);
};

可以看出,Qt Creator 支持一下类型的向导:

  • File
  • Class
  • Project

Core::IWizard就是实现以上向导所必须实现的接口。

简单实现Core::IWizard

下面,我们自己实现IWizard接口,来添加一个新的工程类型“Custom Project”,目的是让我们的新的工程类型能够显示在“新建工程”对话框中。

实现Core::IWizard接口

首先,新建一个类CustomProjectWizard,实现Core::IWizard:

#ifndef CUSTOMPROJECTWIZARD_H
#define CUSTOMPROJECTWIZARD_H

#include <coreplugin/dialogs/iwizard.h>

class QIcon;
class QString;
class QWidget;

class CustomProjectWizard : public Core::IWizard
{
public:
    CustomProjectWizard() { }
    ~CustomProjectWizard() { }

    Core::IWizard::WizardKind kind() const;
    QIcon icon() const;
    QString description() const;
    QString displayName() const;
    QString id() const;

    QString category() const;
    QString displayCategory() const;

    void runWizard(const QString &path, QWidget *parent);
};

#endif // CUSTOMPROJECTWIZARD_H

下面,我们将讨论每一个函数的实现。

函数kind()用于告诉 Qt Creator,我们实现的IWizard接口是哪种类型的。它的合法值就是前面所说的IWizard::WizardKind枚举。在我们的例子中,我们返回ProjectWizard:

Core::IWizard::WizardKind CustomProjectWizard::kind() const
{
    return IWizard::ProjectWizard;
}

函数icon()返回一个图标,这个图标代表该工程,将会出现在新建对话框列表的左侧。在我们的例子中,我们直接返回 Qt Creator 的图标:

QIcon CustomProjectWizard::icon() const
{
    return qApp->windowIcon();
}

函数description()、displayName()、category()、displayCategory()和id()用于返回我们提供的新的工程类型的元数据,比如显示的名字、分类等。其中,以 display 开头的几个函数则用于在界面上显示的字符串,因此我们需要将其用tr()函数返回。

QString CustomProjectWizard::description() const
{
    return "A custom project";
}

QString CustomProjectWizard::displayName() const
{
    return tr("Custom Project");
}

QString CustomProjectWizard::id() const
{
    return "CustomProjectID";
}

QString CustomProjectWizard::category() const
{
    return "GalaxyWorld";
}

QString CustomProjectWizard::displayCategory() const
{
    return tr("GalaxyWorld");
}

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

当用户选择了“CustomProject”分类的时候,runWizard()函数将被调用。这个函数必须显示一个对话框,或者一个QWizard对象,用于向用户询问创建新的工程、文件或者类所必须的那些信息。在我们的示例中,这个函数仅仅显示一个对话框:

void CustomProjectWizard::runWizard(const QString &path, QWidget *parent)
{
    Q_UNUSED(path);
    Q_UNUSED(parent);

    QMessageBox::information(parent, "Custom Wizard Dialog", "Hi there!");
}

提供插件

至此我们已经完成自定义工程所需要的代码,下面就需要和前面一样,提供一个插件的封装:

bool CustomProjectWizardPlugin::initialize(const QStringList& args, QString *errMsg)
{
    Q_UNUSED(args);
    Q_UNUSED(errMsg);

    addAutoReleasedObject(new CustomProjectWizard);

    return true;
}

下面运行测试一下,就可以在新建对话框中发现我们增加的 Custom Project 类型:

Qt Creator 自定义工程

附件下载:CustomProjectWizardPlugin 文件

预定义的IWizard实现:Core::BaseFileWizard

Qt Creator 已经提供了一个默认的IWizard接口的实现,也就是Core::BaseFileWizard类。这个类提供了
IWizard接口的所有函数的默认实现,并且增加了自己特有的虚函数。为了利用这个类,我们需要继承它,并且重写其中的一个或多个函数。

Core::GeneratedFile和Core::GeneratedFiles

通常说,一个新的向导(IWizard的实现)能够提供用户多种提示,并且最终生成一个或者多个文件。Core::GeneratedFile类帮助我们对将要生成的文件进行抽象。很快,我们就可以了解到,在Core::BaseFileWizard的子类中,我们可以为每一个自动生成的文件创建Core::GeneratedFile类的实例。Core::GeneratedFile在 coreplugin/basefilewizard.h 中声明:

class CORE_EXPORT GeneratedFile
{
public:
    enum Attribute { // Open this file in editor
                     OpenEditorAttribute = 0x01,
                     // Open project
                     OpenProjectAttribute = 0x02,
                     /* File is generated by external scripts, do not write out,
                      * see BaseFileWizard::writeFiles() */
                     CustomGeneratorAttribute = 0x4
                   };
    Q_DECLARE_FLAGS(Attributes, Attribute)

    GeneratedFile();
    explicit GeneratedFile(const QString &path);
    GeneratedFile(const GeneratedFile &);
    GeneratedFile &operator=(const GeneratedFile &);
    ~GeneratedFile();

    // Full path of the file should be created, or the suggested file name
    QString path() const;
    void setPath(const QString &p);

    // Contents of the file (UTF8)
    QString contents() const;
    void setContents(const QString &c);

    QByteArray binaryContents() const;
    void setBinaryContents(const QByteArray &c);

    // Defaults to false (Text file).
    bool isBinary() const;
    void setBinary(bool b);

    // Id of editor to open the file with
    QString editorId() const;
    void setEditorId(const QString &k);

    bool write(QString *errorMessage) const;

    Attributes attributes() const;
    void setAttributes(Attributes a);

private:
    QSharedDataPointer m_d;
};

typedef QList GeneratedFiles;

需要由Core::BaseFileWizard子类生成的文件由Core::GeneratedFile类对象表示。这个类包含了需要生成的文件的三个关键属性:

  1. 文件名(及绝对路径)
  2. 用于编辑文件所需要的编辑器类型,合法值为:CppEditor::Constants::CPPEDITOR_KINDGenericProjectManager::Constants::PROJECT_KINDGit::Constants:: GIT_COMMAND_LOG_EDITOR_KINDGit::Constants:: C_GIT_COMMAND_LOG_EDITOR
  3. 文件内容

假设我们需要生成如下内容的 C++ 文件:

#include <iostream>

int main()
{
    cout << "Hello World\n";

    return 0;
}

我们按照下述代码使用Core::GeneratedFile:

#include <coreplugin/basefilewizard.h>
#include <cppeditor/cppeditorconstants.h>

Core::GeneratedFile genFile("C:/Path/To/Source.cpp");
genFile.setEditorId(CppEditor::Constants::CPPEDITOR_ID);
genFile.setContents(
                     "#include <iostream>\n"
                     "\n"
                     "int main()\n"
                     "{\n"
                     "    cout << \"Hello World\n\";\n"
                     "    \n"
                     "    return 0;\n"
                     "}"
                    );
genFile.write(NULL);

Item Model 类向导

假设我们希望提供一个新的类向导,来帮助我们自动生成一个数据项模型的文件。这个文件将基于如下几个数据:

  • 模型类名称;
  • 父类名称(可以是QAbstractItemModel、QAbstractListModel或者QAbstractTableModel中的一个);
  • 头文件名;
  • 源代码文件名。

下面,我们就来为 Qt Creator 提供这个“数据项模型”类向导。

第一步:设计类向导界面

首先,我们需要使用 Qt Designer 设计一个简单的界面,目的是向用户搜集我们上面提到的所需要的各个数据:

ModelClassPage UI

这个界面被命名为 ModelNamePage.ui。

第二步:实现类向导页面

现在,我们将这个 UI 界面导入 Qt 类,从而可以获取到界面数据。首先,我们需要设计一个结构体,来保存所需数据:

struct ModelClassParameters
{
    QString className;
    QString headerFile;
    QString sourceFile;
    QString baseClass;
    QString path;
};

下一步,我们声明表示向导页的类,用于将前面我们做出的 UI 类加载进来,以便用户能够使用我们设计的界面来输入需要的内容:

#ifndef MODELNAMEPAGE_H
#define MODELNAMEPAGE_H

#include <QWizardPage>

struct ModelClassParameters
{
    QString className;
    QString headerFile;
    QString sourceFile;
    QString baseClass;
    QString path;
};

namespace Ui {
class ModelNamePage;
}

class ModelNamePage : public QWizardPage
{
    Q_OBJECT

public:
    explicit ModelNamePage(QWidget *parent = 0);
    ~ModelNamePage();

    void setPath(const QString& path);
    ModelClassParameters parameters() const;

private slots:
    void onClassNameChange(const QString & name);

private:
    Ui::ModelNamePage *ui;
    QString path;
};

#endif // MODELNAMEPAGE_H

构造函数和析构函数都是很简单的:

ModelNamePage::ModelNamePage(QWidget *parent) :
    QWizardPage(parent),
    ui(new Ui::ModelNamePage)
{
    ui->setupUi(this);
}

ModelNamePage::~ModelNamePage()
{
    delete ui;
}

函数setPath()用于将文件路径存储下来:

void ModelNamePage::setPath(const QString& path)
{
    this->path = path;
}

槽函数onClassNameChange()根据用户填写的类名,自动生成对应的头文件和源代码文件的名字:

void ModelNamePage::onClassNameChange(const QString &name)
{
    ui->headerEdit->setText(name + ".h");
    ui->implEdit->setText(name + ".cpp");
}

最后, 函数parameters()用于返回ModelClassParameters实例,实际就是返回用户填写的数据:

ModelClassParameters ModelNamePage::parameters() const
{
    ModelClassParameters params;
    params.className = ui->classNameEdit->text();
    params.headerFile = ui->headerEdit->text();
    params.sourceFile = ui->implEdit->text();
    params.baseClass = ui->baseClassBox->currentText();
    params.path = path;
    return params;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT CREATOR 插件开发:添加新的工程类型(上) 的相关文章

  • 进程何时获得 SIGABRT(信号 6)?

    C 中进程获得 SIGABRT 的场景有哪些 该信号是否始终来自进程内部 或者该信号可以从一个进程发送到另一个进程吗 有没有办法识别哪个进程正在发送该信号 abort 向调用进程发送SIGABRT信号 就是这样abort 基本上有效 abo
  • 使用具有现有访问令牌的 Google API .NET 客户端

    用例如下 移动应用程序正在通过 Google 对用户进行身份验证 并且在某些时候 我们需要将用户的视频发布到他的 YouTube 帐户 出于实际原因 实际发布应该由后端完成 已经存储在那里的大文件 由于用户已经通过应用程序的身份验证 因此应
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 32 位应用程序的特征最大矩阵大小

    所以 我正在寻找Eigen http eigen tuxfamily org index php title Main Page当我尝试声明大于 10000x10000 的矩阵时 包崩溃 我需要声明一个像这样的矩阵 可靠地大约有 13000
  • 从 MVC 迁移到 ASP.NET Core 3.1 中的端点路由时,具有角色的 AuthorizeAttribute 不起作用

    我正在尝试将我的项目从 UseMVC asp net core 2 2 兼容样式 升级到 UseEndpoint Routing 并且我的所有请求都被重定向到我的验证失败页面 它与声明有关 如果我删除 Authorize Roles Adm
  • 对齐 GridView 中的行值

    我需要在 asp net 3 5 中右对齐 gridview 列中的值 我怎样才能做到这一点
  • 显示异常时的自定义错误消息:从客户端检测到潜在危险的 Request.Form 值

    我在我的 Web 应用程序中使用 ASP NET 的登录控件 当发生此异常时 我想在标签上显示一种有趣的错误类型System Web HttpRequestValidationException A potentially dangerou
  • JSON 数组到 C# 列表

    如何将这个简单的 JSON 字符串反序列化为 C 中的列表 on4ThnU7 n71YZYVKD CVfSpM2W 10kQotV 这样 List
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • 暂停下载线程

    我正在用 C 编写一个非常简单的批量下载程序 该程序读取要下载的 URL 的 txt 文件 我已经设置了一个全局线程和委托来更新 GUI 按下 开始 按钮即可创建并启动该线程 我想要做的是有一个 暂停 按钮 使我能够暂停下载 直到点击 恢复
  • 即使手动设置显示环境变量后,WSL Ubuntu 也会显示“错误:无法打开显示”

    我在 WSL Ubuntu 上使用 g 我使用 git 克隆了 GLFW 存储库 使用了ccmake命令配置并生成二进制文件 然后使用make在 build 目录中最终创建 a文件 我安装了所有OpenGL相关的库 usr ld 我不记得我
  • 基于xsd模式生成xml(使用.NET)

    我想根据我的 xsd 架构 cap xsd 生成 xml 文件 我找到了这篇文章并按照说明进行操作 使用 XSD 文件生成 XML 文件 https stackoverflow com questions 6530424 generatin
  • 无法将类型“System.IO.Stream”隐式转换为“Java.IO.InputStream”

    我提到了一些类似的问题 但没有一个涉及IO 当我使用时 我在java中使用了相同的代码Eclipse 那次就成功了 但现在我尝试在中使用这段代码Mono for Android C 它不起作用 我正在尝试运行此代码来创建一个InputStr
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 当模板类不包含可用的成员函数时,如何在编译时验证模板参数?

    我有以下模板struct template
  • 当前的 x86 架构是否支持非临时加载(来自“正常”内存)?

    我知道有关此主题的多个问题 但是 我没有看到任何明确的答案或任何基准测量 因此 我创建了一个处理两个整数数组的简单程序 第一个数组a非常大 64 MB 第二个数组b很小 无法放入 L1 缓存 程序迭代a并将其元素添加到相应的元素中b在模块化
  • 转到定义:“无法导航到插入符号下的符号。”

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我今天突然开始在我的项目中遇到一个问题 单击 转到定义 会出现一个奇怪的错误 无法导航到
  • WinRT 定时注销

    我正在开发一个 WinRT 应用程序 要求之一是应用程序应具有 定时注销 功能 这意味着在任何屏幕上 如果应用程序空闲了 10 分钟 应用程序应该注销并导航回主屏幕 显然 执行此操作的强力方法是在每个页面的每个网格上连接指针按下事件 并在触
  • 实例化 Microsoft.Office.Interop.Excel.Application 对象时出现错误:800700c1

    实例化 Microsoft Office Interop Excel Application 以从 winforms 应用程序生成 Excel 时 出现以下错误 这之前是有效的 但突然间它停止工作了 尽管代码和 Excel 版本没有变化 我
  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder

随机推荐

  • C51_PID 水温控制系统

    前言 通过C语言程序写入51单片机实现水的温度的采集 并通过控制器控制加热器给水体加热 对水体的温进行PID控制 保证温度在设定值范围内波动 最终包括C51的视频的内容以及部分参考资料都可以在 百度分享链接内下载 链接 https pan
  • STM32中文参考手册下载地址

    STM32中文参考手册下载地址 进入官网后点击 设计资源 选择你要下载的芯片的手册 然后找到有 完整的存储器和外设信息 字眼的文档进行下载 很多人下载的下面这种 这种只介绍电气性能和简单介绍外设资源 并不告诉你寄存器啥的 编程比较困难 vo
  • 电脑键盘指法的正确练习步骤

    电脑键盘指法的正确练习步骤 转载 http www jb51 net softjc 39858 html 如果您觉得不合适请联系QQ 2453419889 我会及时删除本博文 电脑键盘指法练习学习目的 一 正确的指法 二 熟悉字母位置 电脑
  • base64、utf-8、二进制有什么关系?

    一 引言 在开发过程中我们经常会用到GBK utf 8等编码规范 本文为大家介绍了他们的起源 差别以及应用 二 ASCII GBK Unicode Utf 8编码区别 1 文本编码的诞生背景 计算机只能处理数字 如果要处理文本文件就必须先把
  • React Native Map遍历问题

    code for let room of rooms values console log room error TypeError undefined is not a function evaluating iterator typeo
  • 【100%通过率 】【华为OD机试真题c++/java/python】开心消消乐【2022 Q4

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 给定一个N行M列的二维矩阵 矩阵中每个位置的数字取值为0或1 矩阵示例如 1100 0001 0011 1111 现需要将矩阵中所有的1进行反转
  • Linux线程学习(三):pthread常见线程函数

    在任何一个时间点上 线程是可结合的 joinable 或者是分离的 detached 一个可结合的线程能够被其他线程收回其资源和杀死 在被其他线程回收之前 它的存储器资源 例如栈 是不释放的 相反 一个分离的线程是不能被其他线程回收或杀死的
  • 如何使用FastReport .NET 从 JetBrains Rider 中创建PDF报告?

    Fastreport是目前世界上主流的图表控件 具有超高性价比 以更具成本优势的价格 便能提供功能齐全的报表解决方案 连续三年蝉联全球文档创建组件和库的 Top 50 Publishers 奖 FastReport NET官方版下载 qun
  • android开发系列:Android Studio项目添加依赖时下载的jar包在哪

    参考 参考 https blog csdn net wudinaniya article details 75258077 结论 c盘 用户 用户名 gradle caches modules 2 files 2 1
  • python模拟登录网站_Python模拟登录的几种方法

    目录 正文 方法一 直接使用已知的cookie访问 特点 简单 但需要先在浏览器登录 原理 简单地说 cookie保存在发起请求的客户端中 服务器利用cookie来区分不同的客户端 因为http是一种无状态的连接 当服务器一下子收到好几个请
  • 【error】Doubbo 服务启动异常:java.lang.RuntimeException: [source error] getPropertyValue,问题分析,解决方案

    目录 1 报错信息 2 原因分析 3 解决方案 4 提示 1 报错信息 java lang RuntimeException source error getPropertyValue Ljava lang Object Ljava lan
  • R语言—向量

    向量 vector R 语言最基本的数据结构是向量 类似于数学上的集合的概念 由一个或多个元素构成 向量其实是用于存储数值型 字符型 或逻辑型数据的一维数组 创建向量 c 函数 gt a lt 1 给a赋值1 gt a 显示a的值 1 1
  • 解密企业级PPPoE:部署、配置和管理的最佳实践

    亲爱的读者朋友们 今天 我将带你一起探索企业级PPPoE 这个让你畅快玩转互联网的神奇协议 首先 让我们来了解一下什么是PPPoE 它代表着 点对点协议以太网 是一种强大而灵活的网络连接协议 对于企业来说 部署PPPoE意味着你可以轻松实现
  • Java实现实现简单算法之最长对称字符串

    题目 已知一字符串 求其内包含的最长对称字符串 例 已知字符串 google 输出最长对称字符串 goog 已知abada 输出aba 已知sdghjdgzzgdah 输出 dgzzgd 看到题目时 大家第一反应都是模棱两可的 好像可以这样
  • Selenium+Python3之:多线程进行跨浏览器测试

    python多线程跨浏览器测试 1 引言 2 跨浏览器操作及定义 2 1 啥是跨浏览器测试 2 2 为啥要进行跨浏览器测试 2 3 跨浏览器测试执行 3 代码编写实战 1 引言 在WebUI自动化方面的博文 我也是有好一段时间没有更新了 这
  • 什么是期货交易的技术分析(期货交易市场技术分析)

    什么是期货买卖的本领领会 拓展材料 1 期货本领领会规则 期货本领领会的规则是伴随趋向 期货本领领会的表面普通 期货本领领会的表面普通是创造在三个有理的假如之上的 商场动作具备容纳性和容纳性 价钱以一种趋向的办法兴盛 汗青将重演 在这三个假
  • 如何利用Python爬虫在网上接单,一周赚7800元,一天只要两小时 !

    1 兼职处理数据 互联网时代下 越来越多的人离不开电脑办公 而与电脑办公分隔不开的 就是处理电脑上保存的数据 虽然说Excel整理数据功能很强大 但在Python面前 曾经统治职场的它也得败下阵来 因为Python在搜集整理分析数据的过程中
  • ConstraintLayout 高级特性,工具总结

    layout constraintWidth 用法 xml中 app layout constrainedWidth true 作用 使得该view的宽受限于他的约束 app layout constrainedHeight true 同理
  • ChatGPT专业应用:基于关键词撰写原创文章

    正文共 485 字 阅读大约需要 2 分钟 内容运营 SEO投放必备技巧 您将在2分钟后获得以下超能力 基于关键词撰写原创文章 Beezy评级 B级 经过简单的寻找 大部分人能立刻掌握 主要节省时间 推荐人 Kim 编辑者 Linda 此图
  • QT CREATOR 插件开发:添加新的工程类型(上)

    Qt Creator 中 新的工程类型将出现在 文件 gt 新建 菜单项中 我们可以通过打开的选择工程类型的对话框来找到所需要的工程 在本章中 我们将学习如何向上面所示的对话框中添加新的工程类型 Core IWizard接口 Qt Crea