在做QT自定义组件开发的时候,拷贝代码,再修改太繁琐了,所以想着能不能自动生成下基础组件,于是有了自动生成组件的想法。一个基本的组件是长这个样子:
.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);
}