From fd38553be15ea1211e6f17f8c4d0b195df75a8a1 Mon Sep 17 00:00:00 2001 From: taocong Date: Tue, 26 May 2026 09:59:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=98=E5=8F=A0=E6=8C=89=E9=92=AE=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E8=BD=AC=E7=A0=81=E9=A1=B5=E9=9D=A2=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 8 +- ICON_GUIDE.md | 24 ++ Uft30ChangeCode.pro | 47 ++++ app.rc | 2 +- main.cpp | 4 +- resources.qrc | 6 + resources/README.md | 17 ++ resources/icons/.gitkeep | 1 + resources/images/.gitkeep | 1 + resources/images/ChangeCode.ico | Bin 0 -> 16555 bytes resources/images/ChangeCode.png | Bin 0 -> 8228 bytes resources/images/delect.png | Bin 0 -> 5995 bytes resources/images/max.png | Bin 0 -> 3468 bytes resources/images/min.png | Bin 0 -> 2896 bytes resources/images/zhedie_left.png | Bin 0 -> 3052 bytes resources/images/zhedie_right.png | Bin 0 -> 3048 bytes src/mainwindow/mainwindow.cpp | 101 +++++++- src/mainwindow/mainwindow.h | 8 + src/pages/batchconvert/batchconvertpage.cpp | 246 +++++++++++++++++--- src/pages/batchconvert/batchconvertpage.h | 14 +- 20 files changed, 441 insertions(+), 38 deletions(-) create mode 100644 ICON_GUIDE.md create mode 100644 Uft30ChangeCode.pro create mode 100644 resources/README.md create mode 100644 resources/icons/.gitkeep create mode 100644 resources/images/.gitkeep create mode 100644 resources/images/ChangeCode.ico create mode 100644 resources/images/ChangeCode.png create mode 100644 resources/images/delect.png create mode 100644 resources/images/max.png create mode 100644 resources/images/min.png create mode 100644 resources/images/zhedie_left.png create mode 100644 resources/images/zhedie_right.png diff --git a/.gitignore b/.gitignore index bc9c90a..e5f941e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,15 @@ !python_bindings/** !src/ !src/** +!resources/ +!resources/** !*.bat !*.rc !*.prp !*.cpp !*.qrc -!.gitignore \ No newline at end of file +!*.h +!*.pro +!*.md +!.gitignore +!.gitkeep diff --git a/ICON_GUIDE.md b/ICON_GUIDE.md new file mode 100644 index 0000000..23936eb --- /dev/null +++ b/ICON_GUIDE.md @@ -0,0 +1,24 @@ +# 图标设置说明 + +## 已完成配置 + +1. **应用程序窗口图标** - 已设置为 `resources/icons/转码工具.svg` +2. **资源文件** - 图标已添加到 `resources.qrc` + +## Windows 可执行程序图标(可选) + +如需设置 Windows 可执行文件的图标(任务栏、文件管理器显示的图标),需要: + +### 方法 1:使用在线工具转换 +1. 将 `resources/images/转码工具.png` 转换为 `.ico` 格式 +2. 推荐尺寸:包含 16x16, 32x32, 48x48, 256x256 等多种尺寸 +3. 保存为 `app.ico` 并放在项目根目录 +4. `app.rc` 已配置引用 `app.ico` + +### 方法 2:使用 ImageMagick 转换 +```bash +magick convert 转码工具.png -define icon:auto-resize=256,128,96,64,48,32,16 app.ico +``` + +### 重新编译 +设置好图标后重新编译项目即可。 diff --git a/Uft30ChangeCode.pro b/Uft30ChangeCode.pro new file mode 100644 index 0000000..2ed4392 --- /dev/null +++ b/Uft30ChangeCode.pro @@ -0,0 +1,47 @@ +QT += core gui widgets + +TARGET = Uft30ChangeCode +TEMPLATE = app + +DEFINES += QT_DEPRECATED_WARNINGS + +SOURCES += main.cpp \ + src/mainwindow/mainwindow.cpp \ + src/pythonrunner/PythonRunner.cpp \ + src/pages/about/aboutpage.cpp \ + src/pages/batchconvert/batchconvertpage.cpp \ + src/pages/functionsearch/functionsearchpage.cpp \ + src/pages/help/helppage.cpp \ + src/pages/settings/settingspage.cpp + +HEADERS += src/mainwindow/mainwindow.h \ + src/pythonrunner/PythonRunner.h \ + src/pages/about/aboutpage.h \ + src/pages/batchconvert/batchconvertpage.h \ + src/pages/functionsearch/functionsearchpage.h \ + src/pages/help/helppage.h \ + src/pages/settings/settingspage.h + +RESOURCES += resources.qrc + +CONFIG += c++17 +CONFIG += debug_and_release + +QMAKE_CXXFLAGS += -Wall -Wextra +QMAKE_LFLAGS += -fno-use-linker-plugin + +INCLUDEPATH += src +INCLUDEPATH += 3rd/ElaWidgetTools/include + +win32 { + LIBS += -L$$PWD/3rd/ElaWidgetTools/lib -lElaWidgetTools + LIBS += -ld3d11 -ldxgi + RC_FILE = app.rc +} + +DESTDIR = $$PWD/bin +OBJECTS_DIR = $$PWD/build +MOC_DIR = $$PWD/build +RCC_DIR = $$PWD/build + + diff --git a/app.rc b/app.rc index 901a305..5d9f7ea 100644 --- a/app.rc +++ b/app.rc @@ -1 +1 @@ -IDI_ICON1 ICON DISCARDABLE "app.ico" \ No newline at end of file +IDI_ICON1 ICON DISCARDABLE "resources/images/ChangeCode.ico" \ No newline at end of file diff --git a/main.cpp b/main.cpp index 8131a80..c2644f0 100644 --- a/main.cpp +++ b/main.cpp @@ -1,12 +1,14 @@ #include "src/mainwindow/mainwindow.h" #include "ElaApplication.h" #include +#include int main(int argc, char *argv[]) { QApplication a(argc, argv); + a.setWindowIcon(QIcon(":resources/images/ChangeCode.png")); eApp->init(); MainWindow w; - w.show(); + w.showMaximized(); return a.exec(); } \ No newline at end of file diff --git a/resources.qrc b/resources.qrc index 71fe652..282607c 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,4 +1,10 @@ + resources/images/ChangeCode.png + resources/images/delect.png + resources/images/zhedie_left.png + resources/images/zhedie_right.png + resources/images/max.png + resources/images/min.png \ No newline at end of file diff --git a/resources/README.md b/resources/README.md new file mode 100644 index 0000000..0b6dc10 --- /dev/null +++ b/resources/README.md @@ -0,0 +1,17 @@ +# 资源目录 + +此目录用于存放项目使用的图标、图片等资源文件。 + +## 目录结构 + +``` +resources/ +├── icons/ # 图标文件 +└── images/ # 图片文件 +``` + +## 添加新资源 + +1. 将资源文件放入对应目录 +2. 更新 resources.qrc 文件添加资源引用 +3. 重新编译项目 diff --git a/resources/icons/.gitkeep b/resources/icons/.gitkeep new file mode 100644 index 0000000..f38471a --- /dev/null +++ b/resources/icons/.gitkeep @@ -0,0 +1 @@ +# 此文件用于保持icons目录在Git仓库中 diff --git a/resources/images/.gitkeep b/resources/images/.gitkeep new file mode 100644 index 0000000..88405d5 --- /dev/null +++ b/resources/images/.gitkeep @@ -0,0 +1 @@ +# 此文件用于保持images目录在Git仓库中 diff --git a/resources/images/ChangeCode.ico b/resources/images/ChangeCode.ico new file mode 100644 index 0000000000000000000000000000000000000000..f7035a59c8f46e4c906494d421f32af74ade8e70 GIT binary patch literal 16555 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 literal 0 HcmV?d00001 diff --git a/resources/images/ChangeCode.png b/resources/images/ChangeCode.png new file mode 100644 index 0000000000000000000000000000000000000000..8922aebc18dcceb6f2b18e08b14ed1024601de2d GIT binary patch literal 8228 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 a!^7|!W10O{`GgC#z{p7}NmWW1g8u_7pq^_0 literal 0 HcmV?d00001 diff --git a/resources/images/delect.png b/resources/images/delect.png new file mode 100644 index 0000000000000000000000000000000000000000..212b56bacdc7a1549f53e729e86897f47742f7e4 GIT binary patch literal 5995 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 X4Mh9fp+5TGVGUvz-HCR~&YS-qzO4_C literal 0 HcmV?d00001 diff --git a/resources/images/min.png b/resources/images/min.png new file mode 100644 index 0000000000000000000000000000000000000000..52f9a75c2dcdec000ea4cfb8ade067dbdb848245 GIT binary patch literal 2896 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 Nu(YtHmzuGn{tIuVI9>n% literal 0 HcmV?d00001 diff --git a/resources/images/zhedie_right.png b/resources/images/zhedie_right.png new file mode 100644 index 0000000000000000000000000000000000000000..a2bc0edf04d739998e9e8d23037379a622247237 GIT binary patch literal 3048 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 literal 0 HcmV?d00001 diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp index d64d886..c7da07b 100644 --- a/src/mainwindow/mainwindow.cpp +++ b/src/mainwindow/mainwindow.cpp @@ -2,6 +2,7 @@ #include "ElaIcon.h" #include "ElaText.h" #include "ElaTheme.h" +#include "ElaToolButton.h" #include #include #include @@ -16,10 +17,15 @@ #include #include #include +#include +#include MainWindow::MainWindow(QWidget *parent) : ElaWindow(parent) , m_pythonRunner(new PythonRunner(this)) + , m_iconsSet(false) + , m_navigationButton(nullptr) + , m_isNavigationExpanded(true) { initWindow(); initContent(); @@ -52,6 +58,9 @@ MainWindow::MainWindow(QWidget *parent) connect(m_pythonRunner, &PythonRunner::started, [this]() { m_batchLogEdit->append("转换任务已启动..."); }); + + // 延迟查找并更新导航按钮(等待窗口完全显示后) + QTimer::singleShot(100, this, &MainWindow::updateNavigationButtonIcon); } MainWindow::~MainWindow() @@ -61,10 +70,14 @@ MainWindow::~MainWindow() void MainWindow::initWindow() { setWindowTitle("UFT30 Change Code"); - setWindowIcon(QIcon(":/Resource/Image/Cirno.jpg")); + setWindowIcon(QIcon(":/resources/images/ChangeCode.png")); resize(900, 600); - setUserInfoCardTitle("UFT30"); - setUserInfoCardSubTitle("Change Code Tool"); + setUserInfoCardVisible(false); + + // 隐藏返回和前进按钮 + + setWindowButtonFlag(ElaAppBarType::RouteBackButtonHint, false); + setWindowButtonFlag(ElaAppBarType::RouteForwardButtonHint, false); } void MainWindow::initContent() @@ -73,7 +86,7 @@ void MainWindow::initContent() QString aboutKey; QString settingKey; addPageNode("转码业务", createBatchConvertPage(), ElaIconType::FileCode); - addPageNode("功能搜索", createFunctionSearchPage(), ElaIconType::MagnifyingGlass); + //addPageNode("功能搜索", createFunctionSearchPage(), ElaIconType::MagnifyingGlass); addFooterNode("帮助", createHelpPage(), helpKey, 0, ElaIconType::CircleQuestion); addFooterNode("关于", createAboutPage(), aboutKey, 0, ElaIconType::User); addFooterNode("设置", createSettingsPage(), settingKey, 0, ElaIconType::GearComplex); @@ -167,3 +180,83 @@ void MainWindow::onPythonRunnerError(const QString &error) m_batchLogEdit->append(QString("[ERROR] %1").arg(error)); } } + +void MainWindow::updateNavigationButtonIcon() +{ + // 使用资源文件中的图标 + QIcon leftIcon(":/resources/images/zhedie_left.png"); + + if (leftIcon.isNull()) { + return; + } + + // 查找所有 ElaToolButton + QList allButtons = this->findChildren(QString(), Qt::FindChildrenRecursively); + + // 尝试查找导航按钮 - 可能在不同位置 + for (int i = 0; i < allButtons.size(); i++) { + ElaToolButton* btn = allButtons[i]; + QString objName = btn->objectName(); + + // 检查是否是导航按钮(可能的名称) + if (objName.contains("Nav", Qt::CaseInsensitive) || + objName.contains("Menu", Qt::CaseInsensitive) || + objName.contains("Navigation", Qt::CaseInsensitive)) { + m_navigationButton = btn; + break; + } + } + + // 如果没有找到有名称的导航按钮,使用第一个可见按钮 + if (!m_navigationButton) { + for (ElaToolButton* btn : allButtons) { + if (btn->isVisible()) { + m_navigationButton = btn; + break; + } + } + } + + if (m_navigationButton) { + m_navigationButton->setProperty("ElaIconType", ""); + m_navigationButton->setIcon(leftIcon); + m_navigationButton->setIconSize(QSize(24, 24)); + m_navigationButton->update(); + + // 先断开可能存在的连接,然后重新连接,避免多次连接 + disconnect(m_navigationButton, &ElaToolButton::clicked, this, &MainWindow::onNavigationButtonClicked); + connect(m_navigationButton, &ElaToolButton::clicked, this, &MainWindow::onNavigationButtonClicked); + } +} + +bool MainWindow::eventFilter(QObject *obj, QEvent *event) +{ + if (!m_iconsSet && event->type() == QEvent::Show) { + // 窗口显示后尝试设置图标 + updateNavigationButtonIcon(); + m_iconsSet = true; + } + return ElaWindow::eventFilter(obj, event); +} + +void MainWindow::onNavigationButtonClicked() +{ + if (!m_navigationButton) { + return; + } + + QIcon leftIcon(":/resources/images/zhedie_left.png"); + QIcon rightIcon(":/resources/images/zhedie_right.png"); + + // 使用状态变量来判断当前状态,而不是依赖 cacheKey + if (m_isNavigationExpanded) { + // 当前是展开状态,切换到折叠状态 + m_navigationButton->setIcon(rightIcon); + m_isNavigationExpanded = false; + } else { + // 当前是折叠状态,切换到展开状态 + m_navigationButton->setIcon(leftIcon); + m_isNavigationExpanded = true; + } + m_navigationButton->update(); +} diff --git a/src/mainwindow/mainwindow.h b/src/mainwindow/mainwindow.h index 5b07b6b..5f2ba20 100644 --- a/src/mainwindow/mainwindow.h +++ b/src/mainwindow/mainwindow.h @@ -2,6 +2,7 @@ #define MAINWINDOW_H #include "ElaWindow.h" +#include "ElaToolButton.h" #include #include #include "src/pythonrunner/PythonRunner.h" @@ -34,8 +35,15 @@ private: void onPythonRunnerOutput(const QString &output); void onPythonRunnerError(const QString &error); + void updateNavigationButtonIcon(); + bool eventFilter(QObject *obj, QEvent *event) override; + void onNavigationButtonClicked(); + PythonRunner *m_pythonRunner; QTextEdit *m_batchLogEdit; + bool m_iconsSet; + ElaToolButton* m_navigationButton; + bool m_isNavigationExpanded; }; #endif // MAINWINDOW_H \ No newline at end of file diff --git a/src/pages/batchconvert/batchconvertpage.cpp b/src/pages/batchconvert/batchconvertpage.cpp index fa96941..e8eea2d 100644 --- a/src/pages/batchconvert/batchconvertpage.cpp +++ b/src/pages/batchconvert/batchconvertpage.cpp @@ -6,6 +6,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include BatchConvertPage::BatchConvertPage(QWidget *parent) : QWidget(parent) @@ -27,13 +33,33 @@ void BatchConvertPage::initUI() QVBoxLayout *funcLayout = new QVBoxLayout(funcBox); funcLayout->setSpacing(10); - QLabel *funcLabel = new QLabel("请输入需要转码的功能名称(每行一个):"); - funcLayout->addWidget(funcLabel); + m_funcTable = new QTableWidget; + m_funcTable->setColumnCount(3); + m_funcTable->setHorizontalHeaderLabels({"UF20函数名", "是否存在", "操作"}); + m_funcTable->setMinimumHeight(200); + m_funcTable->setSelectionBehavior(QAbstractItemView::SelectRows); + m_funcTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed); + m_funcTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed); + m_funcTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed); + m_funcTable->horizontalHeader()->setStretchLastSection(false); + m_funcTable->setColumnWidth(2, 80); + funcLayout->addWidget(m_funcTable); - m_funcEdit = new QTextEdit; - m_funcEdit->setPlaceholderText(""); - m_funcEdit->setMinimumHeight(120); - funcLayout->addWidget(m_funcEdit); + QHBoxLayout *tableBtnLayout = new QHBoxLayout; + QPushButton *addBtn = new QPushButton("添加"); + addBtn->setStyleSheet("padding: 6px 20px;"); + connect(addBtn, &QPushButton::clicked, this, &BatchConvertPage::onAddFunction); + QPushButton *removeBtn = new QPushButton("删除选中"); + removeBtn->setStyleSheet("padding: 6px 15px;"); + connect(removeBtn, &QPushButton::clicked, this, &BatchConvertPage::onRemoveFunction); + QPushButton *clearBtn = new QPushButton("清空列表"); + clearBtn->setStyleSheet("padding: 6px 15px;"); + connect(clearBtn, &QPushButton::clicked, this, &BatchConvertPage::onClearTable); + tableBtnLayout->addWidget(addBtn); + tableBtnLayout->addStretch(); + tableBtnLayout->addWidget(removeBtn); + tableBtnLayout->addWidget(clearBtn); + funcLayout->addLayout(tableBtnLayout); layout->addWidget(funcBox); @@ -41,11 +67,11 @@ void BatchConvertPage::initUI() QPushButton *startBtn = new QPushButton("开始转换"); startBtn->setStyleSheet("background-color: #1abc9c; color: white; padding: 10px 30px; font-size: 14px; border: none; border-radius: 4px;"); connect(startBtn, &QPushButton::clicked, this, &BatchConvertPage::onStartConvert); - QPushButton *clearBtn = new QPushButton("清空"); - connect(clearBtn, &QPushButton::clicked, this, &BatchConvertPage::onClearLog); + QPushButton *clearLogBtn = new QPushButton("清空日志"); + connect(clearLogBtn, &QPushButton::clicked, this, &BatchConvertPage::onClearLog); btnLayout->addStretch(); btnLayout->addWidget(startBtn); - btnLayout->addWidget(clearBtn); + btnLayout->addWidget(clearLogBtn); layout->addLayout(btnLayout); m_logEdit = new QTextEdit; @@ -55,6 +81,183 @@ void BatchConvertPage::initUI() layout->addWidget(m_logEdit); } +bool BatchConvertPage::checkFunctionExists(const QString &funcName) +{ + QString jsonPath = QCoreApplication::applicationDirPath() + "/uf2touft3/cust.json"; + QFile file(jsonPath); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + + QByteArray data = file.readAll(); + file.close(); + + QString content = QString::fromUtf8(data); + return content.contains("\"" + funcName + "\""); +} + +void BatchConvertPage::updateTable() +{ + m_funcTable->setRowCount(m_funcList.size()); + + for (int i = 0; i < m_funcList.size(); ++i) { + QString funcName = m_funcList[i]; + + QTableWidgetItem *nameItem = new QTableWidgetItem(funcName); + nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable); + m_funcTable->setItem(i, 0, nameItem); + + bool exists = checkFunctionExists(funcName); + QString statusText = exists ? "是" : "否"; + + QTableWidgetItem *statusItem = new QTableWidgetItem(statusText); + statusItem->setFlags(statusItem->flags() & ~Qt::ItemIsEditable); + statusItem->setTextAlignment(Qt::AlignCenter); + + if (exists) { + statusItem->setBackground(QColor(144, 238, 144)); + statusItem->setForeground(QColor(0, 100, 0)); + } else { + statusItem->setBackground(QColor(255, 182, 193)); + statusItem->setForeground(QColor(139, 0, 0)); + } + m_funcTable->setItem(i, 1, statusItem); + + QPushButton *delBtn = new QPushButton; + delBtn->setIcon(QIcon(":/resources/images/delect.png")); + delBtn->setIconSize(QSize(20, 20)); + delBtn->setStyleSheet("padding: 2px; border: none; background-color: transparent;"); + delBtn->setToolTip("删除"); + connect(delBtn, &QPushButton::clicked, this, [this, i]() { + onDeleteRow(i); + }); + m_funcTable->setCellWidget(i, 2, delBtn); + } + + int totalWidth = m_funcTable->width(); + m_funcTable->setColumnWidth(0, (totalWidth - 80) * 8 / 10); + m_funcTable->setColumnWidth(1, (totalWidth - 80) * 2 / 10); + m_funcTable->setColumnWidth(2, 80); +} + +void BatchConvertPage::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + if (m_funcTable) { + int totalWidth = m_funcTable->width(); + m_funcTable->setColumnWidth(0, (totalWidth - 80) * 8 / 10); + m_funcTable->setColumnWidth(1, (totalWidth - 80) * 2 / 10); + m_funcTable->setColumnWidth(2, 80); + } +} + +void BatchConvertPage::onDeleteRow(int row) +{ + if (row >= 0 && row < m_funcList.size()) { + m_funcList.removeAt(row); + updateTable(); + } +} + +void BatchConvertPage::onAddFunction() +{ + QDialog dialog(this); + dialog.setWindowTitle("添加UF20函数"); + dialog.resize(400, 250); + + QVBoxLayout *layout = new QVBoxLayout(&dialog); + + QTextEdit *textEdit = new QTextEdit; + textEdit->setPlaceholderText("每行输入一个函数名"); + layout->addWidget(textEdit); + + QHBoxLayout *btnLayout = new QHBoxLayout; + QPushButton *okBtn = new QPushButton("确定"); + QPushButton *cancelBtn = new QPushButton("取消"); + btnLayout->addStretch(); + btnLayout->addWidget(okBtn); + btnLayout->addWidget(cancelBtn); + layout->addLayout(btnLayout); + + connect(okBtn, &QPushButton::clicked, &dialog, &QDialog::accept); + connect(cancelBtn, &QPushButton::clicked, &dialog, &QDialog::reject); + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + QString text = textEdit->toPlainText().trimmed(); + if (text.isEmpty()) { + return; + } + + QStringList funcNames = text.split('\n', Qt::SkipEmptyParts); + int addedCount = 0; + int existCount = 0; + + for (const QString &name : funcNames) { + QString trimmedName = name.trimmed(); + if (trimmedName.isEmpty()) { + continue; + } + if (m_funcList.contains(trimmedName)) { + existCount++; + continue; + } + m_funcList.append(trimmedName); + addedCount++; + } + + if (existCount > 0) { + QMessageBox::information(this, "提示", + QString("成功添加 %1 个函数,%2 个函数已存在").arg(addedCount).arg(existCount)); + } else if (addedCount > 0) { + QMessageBox::information(this, "提示", + QString("成功添加 %1 个函数").arg(addedCount)); + } + + updateTable(); +} + +void BatchConvertPage::onRemoveFunction() +{ + QList selectedItems = m_funcTable->selectedItems(); + if (selectedItems.isEmpty()) { + QMessageBox::warning(this, "提示", "请先选中要删除的行!"); + return; + } + + QList rowsToRemove; + for (QTableWidgetItem *item : selectedItems) { + int row = item->row(); + if (!rowsToRemove.contains(row)) { + rowsToRemove.append(row); + } + } + + std::sort(rowsToRemove.begin(), rowsToRemove.end(), std::greater()); + for (int row : rowsToRemove) { + m_funcList.removeAt(row); + } + + updateTable(); +} + +void BatchConvertPage::onClearTable() +{ + if (m_funcList.isEmpty()) { + return; + } + + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, "确认清空", "确定要清空所有函数吗?", + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) { + m_funcList.clear(); + updateTable(); + } +} + bool BatchConvertPage::saveToCustJson(const QStringList &funcList) { QString jsonPath = QCoreApplication::applicationDirPath() + "/uf2touft3/cust.json"; @@ -111,23 +314,8 @@ bool BatchConvertPage::saveToCustJson(const QStringList &funcList) void BatchConvertPage::onStartConvert() { - QString funcText = m_funcEdit->toPlainText().trimmed(); - if (funcText.isEmpty()) { - m_logEdit->append("请输入需要转码的功能名称!"); - return; - } - - QStringList funcs = funcText.split('\n', Qt::SkipEmptyParts); - QStringList trimmedFuncs; - for (const QString &func : funcs) { - QString trimmed = func.trimmed(); - if (!trimmed.isEmpty()) { - trimmedFuncs.append(trimmed); - } - } - - if (trimmedFuncs.isEmpty()) { - m_logEdit->append("请输入有效的功能名称!"); + if (m_funcList.isEmpty()) { + m_logEdit->append("请先添加需要转码的函数!"); return; } @@ -135,11 +323,11 @@ void BatchConvertPage::onStartConvert() m_logEdit->append("正在写入 cust.json ..."); m_logEdit->append("功能列表:"); - for (const QString &func : trimmedFuncs) { + for (const QString &func : m_funcList) { m_logEdit->append(" - " + func + ".service_design"); } - if (saveToCustJson(trimmedFuncs)) { + if (saveToCustJson(m_funcList)) { m_logEdit->append("[OK] cust.json 写入成功!"); } else { m_logEdit->append("[FAIL] cust.json 写入失败!"); @@ -155,4 +343,4 @@ void BatchConvertPage::onClearLog() { m_logEdit->clear(); m_logEdit->append("转码工具已准备就绪..."); -} +} \ No newline at end of file diff --git a/src/pages/batchconvert/batchconvertpage.h b/src/pages/batchconvert/batchconvertpage.h index 4dca8e7..4b4e8d7 100644 --- a/src/pages/batchconvert/batchconvertpage.h +++ b/src/pages/batchconvert/batchconvertpage.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include class BatchConvertPage : public QWidget { @@ -21,13 +23,21 @@ signals: private slots: void onStartConvert(); void onClearLog(); + void onAddFunction(); + void onRemoveFunction(); + void onClearTable(); + void onDeleteRow(int row); private: void initUI(); bool saveToCustJson(const QStringList &funcList); + bool checkFunctionExists(const QString &funcName); + void updateTable(); + void resizeEvent(QResizeEvent *event) override; - QTextEdit *m_funcEdit; + QTableWidget *m_funcTable; QTextEdit *m_logEdit; + QStringList m_funcList; }; -#endif // BATCHCONVERTPAGE_H +#endif // BATCHCONVERTPAGE_H \ No newline at end of file