XNSim/XNIDLGen/mainwindow.cpp

396 lines
14 KiB
C++
Raw Permalink Normal View History

2025-04-28 12:25:20 +08:00
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QTableWidget>
#include <QVBoxLayout>
#include <QTabWidget>
#include <QGroupBox>
#include <QLabel>
#include <QGridLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QFileDialog>
#include <QHeaderView>
#include <QMessageBox>
#include <QProcess>
#include "xlsxcellrange.h"
#include "xlsxchart.h"
#include "xlsxchartsheet.h"
#include "xlsxdocument.h"
#include "xlsxrichstring.h"
#include "xlsxworkbook.h"
using namespace QXlsx;
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("XNSim IDL Generator");
setWindowIcon(QIcon(":/icon/XNIDLGen.png"));
//菜单栏
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QAction *openAction = new QAction(tr("&Open"), this);
QAction *closeAction = new QAction(tr("&Close"), this);
fileMenu->addAction(openAction);
fileMenu->addAction(closeAction);
QMenu *operationMenu = menuBar()->addMenu(tr("&Operation"));
QAction *generateAction = new QAction(tr("Generate &IDL"), this);
QAction *generatePrjAction = new QAction(tr("Generate &DDS Project"), this);
operationMenu->addAction(generateAction);
operationMenu->addAction(generatePrjAction);
connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
connect(closeAction, &QAction::triggered, this, &MainWindow::closeFile);
connect(generateAction, &QAction::triggered, this, &MainWindow::generate);
connect(generatePrjAction, &QAction::triggered, this, &MainWindow::generatePrj);
//主界面
QGroupBox *namespaceGroupBox = new QGroupBox(tr("Namespace"), this);
QGridLayout *namespaceGroupBoxLayout = new QGridLayout();
namespaceGroupBox->setLayout(namespaceGroupBoxLayout);
QLabel *firstNamespaceLabel = new QLabel(tr("First Namespace:"), namespaceGroupBox);
QLabel *secondNamespaceLabel = new QLabel(tr("Second Namespace:"), namespaceGroupBox);
QLabel *thirdNamespaceLabel = new QLabel(tr("Third Namespace:"), namespaceGroupBox);
QLabel *modelNameLabel = new QLabel(tr("Model Name:"), namespaceGroupBox);
QLineEdit *firstNamespaceLineEdit = new QLineEdit(namespaceGroupBox);
firstNamespaceLineEdit->setText("XNSim");
firstNamespaceLineEdit->setReadOnly(true);
firstNamespaceLineEdit->setObjectName("firstNamespaceLineEdit");
QLineEdit *secondNamespaceLineEdit = new QLineEdit(namespaceGroupBox);
secondNamespaceLineEdit->setObjectName("secondNamespaceLineEdit");
QLineEdit *thirdNamespaceLineEdit = new QLineEdit(namespaceGroupBox);
thirdNamespaceLineEdit->setObjectName("thirdNamespaceLineEdit");
QLineEdit *modelNameLineEdit = new QLineEdit(namespaceGroupBox);
modelNameLineEdit->setObjectName("modelNameLineEdit");
namespaceGroupBoxLayout->addWidget(firstNamespaceLabel, 0, 0);
namespaceGroupBoxLayout->addWidget(firstNamespaceLineEdit, 0, 1);
namespaceGroupBoxLayout->addWidget(secondNamespaceLabel, 0, 2);
namespaceGroupBoxLayout->addWidget(secondNamespaceLineEdit, 0, 3);
namespaceGroupBoxLayout->addWidget(thirdNamespaceLabel, 1, 0);
namespaceGroupBoxLayout->addWidget(thirdNamespaceLineEdit, 1, 1);
namespaceGroupBoxLayout->addWidget(modelNameLabel, 1, 2);
namespaceGroupBoxLayout->addWidget(modelNameLineEdit, 1, 3);
QGroupBox *groupBox = new QGroupBox(tr("File Preview"), this);
groupBox->setObjectName("groupBox");
QTabWidget *tabWidget = new QTabWidget(groupBox);
tabWidget->setObjectName("tabWidget");
QWidget *tab1 = new QWidget();
QTableWidget *table1 = new QTableWidget(10, 3, tab1); // 10 rows, 5 columns
table1->setObjectName("table1");
QStringList headers;
headers << "name" << "type" << "size";
table1->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
table1->setHorizontalHeaderLabels(headers);
QVBoxLayout *tab1Layout = new QVBoxLayout();
tab1Layout->addWidget(table1);
tab1->setLayout(tab1Layout);
QWidget *tab2 = new QWidget();
QTableWidget *table2 = new QTableWidget(10, 3, tab2); // 10 rows, 5 columns
table2->setObjectName("table2");
table2->setHorizontalHeaderLabels(headers);
table2->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
QVBoxLayout *tab2Layout = new QVBoxLayout();
tab2Layout->addWidget(table2);
tab2->setLayout(tab2Layout);
tabWidget->addTab(tab1, tr("Inputs"));
tabWidget->addTab(tab2, tr("Outputs"));
QVBoxLayout *groupBoxLayout = new QVBoxLayout();
groupBoxLayout->addWidget(tabWidget);
groupBox->setLayout(groupBoxLayout);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->setContentsMargins(
10, 10, 10, 10); // Add margins to create space between the menu bar and central widget
mainLayout->addWidget(namespaceGroupBox);
mainLayout->addWidget(groupBox);
centralWidget()->setLayout(mainLayout);
centralWidget()->setEnabled(false);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::openFile()
{
QString fileName =
QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("ICD file (*.xlsx)"));
if (fileName.isEmpty())
return;
QXlsx::Document xlsx(fileName);
if (xlsx.load()) {
setWindowTitle("XNSim IDL Generator - " + fileName);
QStringList sheetNames = xlsx.sheetNames();
for (const QString &sheetName : sheetNames) {
if (sheetName == "Inputs") {
xlsx.selectSheet(sheetName);
QTableWidget *table1 = findChild<QTableWidget *>("table1");
table1->setRowCount(xlsx.dimension().rowCount() - 1);
for (int col = 1; col <= xlsx.dimension().columnCount(); ++col) {
QString columnName = xlsx.read(1, col).toString();
if (columnName == "SACSC name" || columnName == "SACSC Name"
|| columnName == "NameSACSC") {
for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
QString value = xlsx.read(row, col).toString();
if (value.isEmpty()) {
continue;
}
value = value.toLower();
table1->setItem(row - 2, 0, new QTableWidgetItem(value));
}
} else if (columnName == "Variable Type") {
for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
QString value = xlsx.read(row, col).toString();
if (value.isEmpty()) {
continue;
}
table1->setItem(row - 2, 1, new QTableWidgetItem(value));
}
} else if (columnName == "Variable Dimensions") {
for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
QString value = xlsx.read(row, col).toString();
if (value.isEmpty()) {
continue;
}
if (!value.contains("[") && value.toInt() > 1) {
value = "[" + value + "]";
}
table1->setItem(row - 2, 2, new QTableWidgetItem(value));
}
} else {
continue;
}
}
} else if (sheetName == "Outputs") {
xlsx.selectSheet(sheetName);
QTableWidget *table2 = findChild<QTableWidget *>("table2");
table2->setRowCount(xlsx.dimension().rowCount() - 1);
for (int col = 1; col <= xlsx.dimension().columnCount(); ++col) {
QString columnName = xlsx.read(1, col).toString();
if (columnName == "SACSC name" || columnName == "SACSC Name"
|| columnName == "NameSACSC") {
for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
QString value = xlsx.read(row, col).toString();
if (value.isEmpty()) {
continue;
}
value = value.toLower();
table2->setItem(row - 2, 0, new QTableWidgetItem(value));
}
} else if (columnName == "Variable Type") {
for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
QString value = xlsx.read(row, col).toString();
if (value.isEmpty()) {
continue;
}
table2->setItem(row - 2, 1, new QTableWidgetItem(value));
}
} else if (columnName == "Variable Dimensions") {
for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
QString value = xlsx.read(row, col).toString();
if (value.isEmpty()) {
continue;
}
if (!value.contains("[") && value.toInt() > 1) {
value = "[" + value + "]";
}
table2->setItem(row - 2, 2, new QTableWidgetItem(value));
}
} else {
continue;
}
}
} else {
continue;
}
}
}
centralWidget()->setEnabled(true);
}
void MainWindow::closeFile()
{
QTableWidget *table1 = findChild<QTableWidget *>("table1");
QTableWidget *table2 = findChild<QTableWidget *>("table2");
table1->clear();
table2->clear();
table1->setRowCount(0);
table2->setRowCount(0);
centralWidget()->setEnabled(false);
}
void MainWindow::generate()
{
QLineEdit *modelNameLineEdit = findChild<QLineEdit *>("modelNameLineEdit");
if (!modelNameLineEdit || modelNameLineEdit->text().isEmpty()) {
QMessageBox::warning(this, tr("Error"), tr("Model name is empty"));
return;
}
QString modelName = modelNameLineEdit->text();
QString defaultFileName = modelName + ".idl";
QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
QDir::currentPath() + "/" + defaultFileName,
tr("IDL Files (*.idl)"));
if (filePath.isEmpty()) {
return;
}
if (!filePath.endsWith(".idl", Qt::CaseInsensitive)) {
filePath += ".idl";
}
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
QTextStream out(&file);
QLineEdit *firstNamespaceLineEdit = findChild<QLineEdit *>("firstNamespaceLineEdit");
QLineEdit *secondNamespaceLineEdit = findChild<QLineEdit *>("secondNamespaceLineEdit");
QLineEdit *thirdNamespaceLineEdit = findChild<QLineEdit *>("thirdNamespaceLineEdit");
if (firstNamespaceLineEdit) {
out << "module " << firstNamespaceLineEdit->text() << "\n";
out << "{\n";
if (secondNamespaceLineEdit && !secondNamespaceLineEdit->text().isEmpty()) {
out << "\tmodule " << secondNamespaceLineEdit->text() << "\n";
out << "\t{\n";
if (thirdNamespaceLineEdit && !thirdNamespaceLineEdit->text().isEmpty()) {
out << "\t\tmodule " << thirdNamespaceLineEdit->text() << "\n";
out << "\t\t{\n";
genInput(modelName, "\t\t\t", out);
genOutput(modelName, "\t\t\t", out);
out << "\t\t};\n";
} else {
genInput(modelName, "\t\t", out);
genOutput(modelName, "\t\t", out);
}
out << "\t};\n";
} else {
genInput(modelName, "\t", out);
genOutput(modelName, "\t", out);
}
out << "};\n";
}
file.close();
}
void MainWindow::generatePrj()
{
QFileDialog fileDialog(this);
fileDialog.setNameFilter(tr("IDL Files (*.idl)"));
fileDialog.setViewMode(QFileDialog::Detail);
QString idlFilePath;
if (fileDialog.exec()) {
idlFilePath = fileDialog.selectedFiles().first();
}
if (idlFilePath.isEmpty()) {
return;
}
QString savePath = QFileDialog::getExistingDirectory(this, tr("Select Save Directory"),
QString(), QFileDialog::ShowDirsOnly);
if (savePath.isEmpty()) {
return;
}
QDir dir(savePath);
savePath = dir.absolutePath();
QProcess process;
QStringList arguments = QStringList()
<< "-flat-output-dir" << "-replace" << "-d" << savePath << idlFilePath;
process.start("fastddsgen", arguments);
process.waitForFinished();
QString output = process.readAllStandardOutput();
QMessageBox::information(this, tr("Generate DDS Project Result"), output);
//TODO 生成Interface头文件和源文件
}
QString MainWindow::typeChange(QString type)
{
if (type == "char" || type == "unsigned char") {
return "char";
} else if (type == "short" || type == "unsigned short" || type == "long"
|| type == "unsigned long" || type == "long long" || type == "unsigned long long"
|| type == "float" || type == "double" || type == "long double"
|| type == "string") {
return type;
} else if (type == "int") {
return "long";
} else if (type == "unsigned int") {
return "unsigned long";
} else if (type == "bool") {
return "boolean";
} else if (type == "std::string") {
return "string";
}
return "error";
}
void MainWindow::genInput(QString name, QString prefix, QTextStream &out)
{
out << prefix << "struct " << name << "_input" << "\n";
out << prefix << "{\n";
QTableWidget *table1 = findChild<QTableWidget *>("table1");
if (table1) {
for (int row = 0; row < table1->rowCount(); ++row) {
QString name = table1->item(row, 0)->text();
QString type = table1->item(row, 1)->text();
QString size = table1->item(row, 2)->text();
if (typeChange(type) == "error") {
QMessageBox::warning(this, tr("Error"), name + tr("is unknown type!"));
return;
}
if (size.isEmpty() || size == "1") {
out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << ";\n";
} else {
out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << size
<< ";\n";
}
}
}
out << prefix << "};\n";
}
void MainWindow::genOutput(QString name, QString prefix, QTextStream &out)
{
out << prefix << "struct " << name << "_output" << "\n";
out << prefix << "{\n";
QTableWidget *table2 = findChild<QTableWidget *>("table2");
if (table2) {
for (int row = 0; row < table2->rowCount(); ++row) {
QString name = table2->item(row, 0)->text();
QString type = table2->item(row, 1)->text();
QString size = table2->item(row, 2)->text();
if (typeChange(type) == "error") {
QMessageBox::warning(this, tr("Error"), name + tr("is unknown type!"));
return;
}
if (size.isEmpty() || size == "1") {
out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << ";\n";
} else {
out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << size
<< ";\n";
}
}
}
out << prefix << "};\n";
}