QT 组件化开发 自动生成基础组件

在做QT自定义组件开发的时候,拷贝代码,再修改太繁琐了,所以想着能不能自动生成下基础组件,于是有了自动生成组件的想法。一个基本的组件是长这个样子:
QT 组件化开发 自动生成基础组件_第1张图片

.pri QT子工程配置文件
*.cpp,*.h, 组件内容
*plugin.cpp,*plugin.h,组件插件化配置,主要用于qt designer里进行拖拉

一开始的想法是使用bat脚本(因为里面使用了中文,所以此文件需要保存为ansi格式,保存成UTF-8的化执行会有问题)批处理,运行后先拷贝cpushbutton组件目录,然后遍历此目录,对文件进行重命名

@echo off
set target=DialogButtonBox
set cTarget=C%target%
set qTarget=Q%target%
set dir="%cd%/cpushbutton - 副本"

set lowerCTarget=%cTarget%
for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do call set lowerCTarget=%%lowerCTarget:%%i=%%i%%

set upperCTarget=%cTarget%
for %%i in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do call set upperCTarget=%%upperCTarget:%%i=%%i%%

ren %dir% %lowerCTarget%
set newDir="%cd%/%lowerCTarget%"

for /r %newDir% %%i in (*.*) do (
   if "%%~xi"==".pri" (
      ren %%i "%lowerCTarget%%%~xi"
   )else (
      echo "%%~ni"| findstr "plugin" >nul &&(
         ren %%i "%lowerCTarget%plugin%%~xi"
      )||(
         ren %%i "%lowerCTarget%%%~xi"
     )
   )
)

重命名后需要的是文件内容替换,整理了一下后大概是这么些数据,为了方便,我在bat里自动生成了对应内容,在QT creator里直接拷贝过去,执行五次替换即可

echo CPUSHBUTTON-%upperCTarget% > 1.txt
echo QPushButton-%qTarget% >> 1.txt
echo CPushButton-%cTarget% >> 1.txt
echo cpushbutton-%lowerCTarget% >> 1.txt
echo cPushButton-c%target% >> 1.txt

感觉还是繁琐,就想着这五次替换能不能一部到位,可惜的是QT creator不能直接执行定义的脚本,直接做五次替换,所以萌生了自己写个程序呗,做文件替换。

一、定义demo

demo.pri

HEADERS += $$PWD/{FILENAME}.h
HEADERS += $$PWD/{FILENAME}plugin.h
SOURCES += $$PWD/{FILENAME}.cpp
SOURCES += $$PWD/{FILENAME}plugin.cpp

demo.h

/*
*
* @Author       clarence
* @Time         2022-06-28 T 14:32
* @Function     *
*
* Copyright (c) 2022
*
*/
#ifndef {MACRO}_H
#define {MACRO}_H

#include <{PARENTCLASSNAME}>
#include 

class QDESIGNER_WIDGET_EXPORT {CLASSNAME} : public {PARENTCLASSNAME}
{
    Q_OBJECT

public:
    {CLASSNAME}(QWidget *parent = 0);
};

#endif // {MACRO}_H

demo.cpp

/*
*
* @Author       clarence
* @Time         2022-06-28 T 14:34
* @Function     *
*
* Copyright (c) 2022
*
*/
#include "{FILENAME}.h"

{CLASSNAME}::{CLASSNAME}(QWidget *parent) :
    {PARENTCLASSNAME}(parent)
{
}

dempplugin.h

/*
*
* @Author       clarence
* @Time         2022-06-28 T 14:33
* @Function     *
*
* Copyright (c) 2022
*
*/
#ifndef {MACRO}PLUGIN_H
#define {MACRO}PLUGIN_H

#include 

class {CLASSNAME}Plugin : public QObject, public QDesignerCustomWidgetInterface
{
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)


public:
    {CLASSNAME}Plugin(QObject *parent = nullptr);

    bool isContainer() const override;
    bool isInitialized() const override;
    QIcon icon() const override;
    QString domXml() const override;
    QString group() const override;
    QString includeFile() const override;
    QString name() const override;
    QString toolTip() const override;
    QString whatsThis() const override;
    QWidget *createWidget(QWidget *parent) override;
    void initialize(QDesignerFormEditorInterface *core) override;

private:
    bool m_initialized;
};

#endif // {MACRO}PLUGIN_H

demoplugin.cpp

/*
*
* @Author       clarence
* @Time         2022-06-28 T 14:34
* @Function     *
*
* Copyright (c) 2022
*
*/
#include "{FILENAME}.h"
#include "{FILENAME}plugin.h"

#include 

{CLASSNAME}Plugin::{CLASSNAME}Plugin(QObject *parent)
    : QObject(parent)
{
    m_initialized = false;
}

void {CLASSNAME}Plugin::initialize(QDesignerFormEditorInterface * /* core */)
{
    if (m_initialized)
        return;

    // Add extension registrations, etc. here

    m_initialized = true;
}

bool {CLASSNAME}Plugin::isInitialized() const
{
    return m_initialized;
}

QWidget *{CLASSNAME}Plugin::createWidget(QWidget *parent)
{
    return new {CLASSNAME}(parent);
}

QString {CLASSNAME}Plugin::name() const
{
    return QLatin1String("{SHOWNAME}");
}

QString {CLASSNAME}Plugin::group() const
{
    return QLatin1String("{GROUP}");
}

QIcon {CLASSNAME}Plugin::icon() const
{
    return QIcon(QLatin1String(""));
}

QString {CLASSNAME}Plugin::toolTip() const
{
    return QLatin1String("");
}

QString {CLASSNAME}Plugin::whatsThis() const
{
    return QLatin1String("");
}

bool {CLASSNAME}Plugin::isContainer() const
{
    return false;
}

QString {CLASSNAME}Plugin::domXml() const
{
    return QLatin1String(R"(
    >
      
    )"
    R"(
        
          
            {CLASSNAME}
            
{FILENAME}.h
{PARENTCLASSNAME}
") R"(
)"); } QString {CLASSNAME}Plugin::includeFile() const { return QLatin1String(""); }

二、敲代码
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    bool checkForms();
    void toString();
    bool CopyDirectoryFiles(const QString &fromDir,const QString &toDir);
    bool changeFiles(const QString &dir);
    void changeFile(const QString &filePath);
    QString replace(const QString sourceStr);
    void renderTreeView(QFileSystemModel *fileSystemModel,QTreeView *view,const QString &dir);

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::MainWindow *ui;

    QString m_sourceDir;
    QString m_targetDir;

    QString m_fileName;
    QString m_className;
    QString m_macro;
    QString m_caseName;
    QString m_parentClassName;
    QString m_group;
    QString m_showName;

    QFileSystemModel *sourceFileModel;
    QFileSystemModel *targetFileModel;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->setWindowTitle (tr("初始化组件自动生成"));

    QDir dir(QCoreApplication::applicationDirPath ());
    dir.cdUp ();
    this->m_sourceDir = dir.absolutePath ()+ "/" + "demo";

    sourceFileModel = new QFileSystemModel(this);
    targetFileModel = new QFileSystemModel(this);

    //初始化数据
    QSettings settings("setting.ini",QSettings::IniFormat);

    ui->classNameQLE->setText (settings.value ("classNameQLE").toString ());
    ui->parentClassNameQLE->setText (settings.value ("parentClassNameQLE").toString ());
    ui->groupQLE->setText (settings.value ("groupQLE").toString ());
    ui->showNameQLE->setText (settings.value ("showNameQLE").toString ());
    ui->targetDirQLE->setText (settings.value ("targetDirQLE").toString ());
}

MainWindow::~MainWindow()
{
    //退出保存配置
    QSettings settings("setting.ini",QSettings::IniFormat);
    settings.setValue ("classNameQLE",ui->classNameQLE->text ());
    settings.setValue ("parentClassNameQLE",ui->parentClassNameQLE->text ());
    settings.setValue ("groupQLE",ui->groupQLE->text ());
    settings.setValue ("showNameQLE",ui->showNameQLE->text ());
    settings.setValue ("targetDirQLE",ui->targetDirQLE->text ());
    delete ui;
}

bool MainWindow::checkForms()
{
    if(ui->classNameQLE->text ()== ""){
        QMessageBox::critical (this,tr("错误"),tr("请输入类名"));
        return false;
    }
    if(ui->parentClassNameQLE->text ()== ""){
        QMessageBox::critical (this,tr("错误"),tr("请输入父类名"));
        return false;
    }
    if(ui->groupQLE->text ()== ""){
        QMessageBox::critical (this,tr("错误"),tr("请输入组信息"));
        return false;
    }
    if(ui->showNameQLE->text ()== ""){
        QMessageBox::critical (this,tr("错误"),tr("请输入显示名称"));
        return false;
    }
    if(ui->targetDirQLE->text ()== ""){
        QMessageBox::critical (this,tr("错误"),tr("请选择存放目录"));
        return false;
    }
    return true;
}

void MainWindow::toString()
{
    qDebug()<<"文件名:" << m_fileName;
    qDebug()<<"类名:" << m_className;
    qDebug()<<"宏名:" << m_macro;
    qDebug()<<"实例名:" << m_caseName;
    qDebug()<<"父类名:" << m_parentClassName;
    qDebug()<<"组信息:" << m_group;
    qDebug()<<"显示名称:" << m_showName;
    qDebug()<<"源路径信息:" << m_sourceDir;
    qDebug()<<"目标路径信息:" << m_targetDir;
}

bool MainWindow::CopyDirectoryFiles(const QString &fromDir, const QString &toDir)
{
    QDir sourceDir(fromDir);
    QDir targetDir(toDir);

    if(!targetDir.exists())
    {
        if(!targetDir.mkdir(targetDir.absolutePath()))
        {
            return false;
        }
    }

    QFileInfoList list = sourceDir.entryInfoList();
    for(int i = 0; i < list.size(); i++)
    {
        QFileInfo fileInfo = list.at(i);
        if(fileInfo.fileName()=="." || fileInfo.fileName()=="..")
        {
            continue;
        }

        if(fileInfo.isDir())
        {
            if(!CopyDirectoryFiles(fileInfo.filePath(),targetDir.filePath(fileInfo.fileName())))
            {
                return false;
            }
        }
        else
        {
            if(targetDir.exists(fileInfo.fileName()))
            {
                targetDir.remove(fileInfo.fileName());        //有相同的,直接删除
            }
            if(!QFile::copy(fileInfo.filePath(),targetDir.filePath(fileInfo.fileName())))
            {
                return false;
            }
        }
    }
    return true;
}

bool MainWindow::changeFiles(const QString &dir)
{
    QDir sourceDir(dir);

    if(!sourceDir.exists())
    {
        return false;
    }

    QFileInfoList list = sourceDir.entryInfoList();
    for(int i = 0; i < list.size(); i++)
    {
        QFileInfo fileInfo = list.at(i);
        QString filePath = fileInfo.filePath ();
        QDir dir(filePath);
        if(fileInfo.fileName()=="." || fileInfo.fileName()=="..")
        {
            continue;
        }
        changeFile(filePath);

        //重命名
        dir.cdUp ();
        QString newName = fileInfo.fileName ().replace("demo",m_fileName);
        QFile::rename (dir.absolutePath ()+"/"+fileInfo.fileName (),dir.absolutePath ()+"/"+newName);
    }
    return true;
}

void MainWindow::changeFile(const QString &filePath)
{
    QFile file(filePath); //以文件方式读出
    QString str;

    //读取内容
    if (file.open(QIODevice::ReadOnly))
    {
        QTextStream s(&file); //用文本流读取文件
        str = s.readAll ();
    }
    file.close();

    //清空内容
    file.open(QIODevice::ReadWrite | QIODevice::Truncate);
    file.close ();

    //替换内容
    str = replace(str);

    //写入新内容
    if (file.open(QIODevice::WriteOnly))
    {
        QTextStream s(&file);
        s << str;
    }
    file.close();
}

QString MainWindow::replace(const QString sourceStr)
{
    QString targetStr = sourceStr;
    //可以在这里增加其它变量替换
    targetStr = targetStr.replace ("{FILENAME}",m_fileName);
    targetStr = targetStr.replace ("{CLASSNAME}",m_className);
    targetStr = targetStr.replace ("{PARENTCLASSNAME}",m_parentClassName);
    targetStr = targetStr.replace ("{MACRO}",m_macro);
    targetStr = targetStr.replace ("{SHOWNAME}",m_showName);
    targetStr = targetStr.replace ("{GROUP}",m_group);
    targetStr = targetStr.replace ("{CASENAME}",m_caseName);
    return targetStr;
}

void MainWindow::renderTreeView(QFileSystemModel *fileSystemModel,QTreeView *view, const QString &dir)
{
    fileSystemModel->setRootPath(dir);
    view->setModel (fileSystemModel);
    view->setRootIndex(fileSystemModel->index(dir));
}

void MainWindow::on_pushButton_clicked()
{
    //校验数据
    if(!checkForms ()){
        return;
    }

    //赋值
    QString classNameQLEText = ui->classNameQLE->text ();
    QString parentClassNameQLEText = ui->parentClassNameQLE->text ();
    QString groupQLEText = ui->groupQLE->text ();
    QString showNameQLEText = ui->showNameQLE->text ();
    QString targetDirQLEText = ui->targetDirQLE->text ();

    m_fileName = classNameQLEText.toLower ();
    m_className = classNameQLEText;
    m_macro = classNameQLEText.toUpper ();
    m_caseName = classNameQLEText.sliced (0,1).toLower() + classNameQLEText.sliced (1);
    m_parentClassName = parentClassNameQLEText;
    m_group = groupQLEText;
    m_showName = showNameQLEText;
    m_targetDir = targetDirQLEText + "/" + m_fileName;

    //拷贝目录
    if(!CopyDirectoryFiles(m_sourceDir,m_targetDir)){
        QMessageBox::critical (this,tr("错误"),tr("拷贝目录失败!"));
        return;
    }

    //读取文件并替换
    if(!changeFiles(m_targetDir)){
        QMessageBox::critical (this,tr("错误"),tr("文件修改失败!"));
        return;
    }

    //渲染view
    renderTreeView(sourceFileModel,ui->sourceTreeView,m_sourceDir);
    renderTreeView(targetFileModel,ui->targetTreeView,m_targetDir);

    QMessageBox::information (this,tr("成功"),tr("组件生成成功!"));
}


void MainWindow::on_pushButton_2_clicked()
{
    QString dir = QFileDialog::getExistingDirectory (this,"Select Directory","/",QFileDialog::ShowDirsOnly);
    ui->targetDirQLE->setText (dir);
}

最后的成型:
QT 组件化开发 自动生成基础组件_第2张图片

QT 组件化开发 自动生成基础组件_第3张图片

QT 组件化开发 自动生成基础组件_第4张图片

你可能感兴趣的:(qt)