Compare commits
No commits in common. "main" and "v1.0" have entirely different histories.
37
README.md
37
README.md
|
@ -1,40 +1,3 @@
|
||||||
# TabEditor
|
# TabEditor
|
||||||
|
|
||||||
这个是一个简约的文本文件编辑工具,主要用于编辑以制表符分隔的数据文本文件。与使用Excel编辑相比,该程序可以确保文本文件的格式和内容不会发生改变,提供更可靠的编辑功能。它简约直观的界面使用户能够轻松地加载、编辑和保存这类文本文件。
|
这个是一个简约的文本文件编辑工具,主要用于编辑以制表符分隔的数据文本文件。与使用Excel编辑相比,该程序可以确保文本文件的格式和内容不会发生改变,提供更可靠的编辑功能。它简约直观的界面使用户能够轻松地加载、编辑和保存这类文本文件。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 运行截图
|
|
||||||
![运行截图](./screenshot/def5f9e083c1f55132797db88b8668f.png)
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
- 自动适配文本文件本身的字符编码格式
|
|
||||||
|
|
||||||
以下功能不知道当前用的 tablewidget 是否支持
|
|
||||||
- 表格内容搜索
|
|
||||||
- 冻结行、列
|
|
||||||
- 隐藏行、列
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
可能需要增加的功能:
|
|
||||||
|
|
||||||
- 转换换行符为可见的“\n”——因为由制表符分隔数据的纯文本文件,不建议直接使用换行(读取改文本的使用场景比较特殊)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Qt程序打包
|
|
||||||
|
|
||||||
1. 使用Qt命令行程序:Qt 5.14.2 (MinGW 7.3.0 64-bit)
|
|
||||||
|
|
||||||
进入Qt程序的build目录下的exe所在路径,输入:
|
|
||||||
```shell
|
|
||||||
windeployqt TabEditor.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 使用此项目中的 [packaging.bat](https://begin2019.com:3000/Crimson/TabEditor-Qt/src/branch/main/packaging.bat) ,双击运行 根据提示操作即可。
|
|
||||||
|
|
||||||
> 前提:安装了Qt 5.14.2 (MinGW 7.3.0 64-bit)
|
|
||||||
|
|
282
mainwindow.cpp
282
mainwindow.cpp
|
@ -12,7 +12,6 @@
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QSqlRecord>
|
#include <QSqlRecord>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
#include <QContextMenuEvent>
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
|
@ -20,211 +19,77 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true); // 允许窗口接受拖放事件
|
||||||
|
|
||||||
connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::onOpenButtonClicked);
|
connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::onOpenButtonClicked);
|
||||||
connect(ui->actionSave, &QAction::triggered, this, &MainWindow::onSaveButtonClicked);
|
connect(ui->actionSave, &QAction::triggered, this, &MainWindow::onSaveButtonClicked);
|
||||||
connect(ui->actionSaveAs, &QAction::triggered, this, &MainWindow::onSaveAsButtonClicked);
|
|
||||||
|
|
||||||
QIcon openIcon = QApplication::style()->standardIcon(QStyle::SP_DialogOpenButton);
|
QIcon openIcon = QApplication::style()->standardIcon(QStyle::SP_DialogOpenButton);
|
||||||
QIcon saveIcon = QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton);
|
QIcon saveIcon = QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton);
|
||||||
QIcon saveAsIcon = QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton);
|
|
||||||
|
|
||||||
ui->actionOpen->setIcon(openIcon);
|
ui->actionOpen->setIcon(openIcon);
|
||||||
ui->actionSave->setIcon(saveIcon);
|
ui->actionSave->setIcon(saveIcon);
|
||||||
ui->actionSave->setIcon(saveAsIcon);
|
|
||||||
|
|
||||||
ui->actionOpen->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
|
ui->actionOpen->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
|
||||||
ui->actionSave->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
|
ui->actionSave->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
|
||||||
|
|
||||||
QMenu* convertMenu = menuBar()->addMenu(tr("转换(&C)"));
|
// 添加 "Convert" 菜单
|
||||||
|
QMenu* convertMenu = menuBar()->addMenu(tr("Convert"));
|
||||||
|
|
||||||
QAction* textToSqliteAction = convertMenu->addAction(tr("txt 转 SQLite"));
|
// 添加 "Text to SQLite" 子菜单项,并关联槽函数
|
||||||
|
QAction* textToSqliteAction = convertMenu->addAction(tr("Text to SQLite"));
|
||||||
connect(textToSqliteAction, &QAction::triggered, this, &MainWindow::convertTextToSqlite);
|
connect(textToSqliteAction, &QAction::triggered, this, &MainWindow::convertTextToSqlite);
|
||||||
|
|
||||||
QAction* sqliteToTextAction = convertMenu->addAction(tr("SQLite 转 txt"));
|
// 添加 "SQLite to Text" 子菜单项,并关联槽函数
|
||||||
|
QAction* sqliteToTextAction = convertMenu->addAction(tr("SQLite to Text"));
|
||||||
connect(sqliteToTextAction, &QAction::triggered, this, &MainWindow::convertSqliteToText);
|
connect(sqliteToTextAction, &QAction::triggered, this, &MainWindow::convertSqliteToText);
|
||||||
|
|
||||||
QIcon convertIcon = QApplication::style()->standardIcon(QStyle::SP_ArrowRight);
|
|
||||||
textToSqliteAction->setIcon(convertIcon);
|
|
||||||
sqliteToTextAction->setIcon(convertIcon);
|
|
||||||
|
|
||||||
firstColMenu = new QMenu(this);
|
|
||||||
QAction* addRowAboveAction = firstColMenu->addAction(tr("↑ 向上添加一行"));
|
|
||||||
QAction* addRowBelowAction = firstColMenu->addAction(tr("向下添加一行 ↓"));
|
|
||||||
QAction* delRowAction = firstColMenu->addAction(tr("删除"));
|
|
||||||
connect(addRowAboveAction, &QAction::triggered, this, &MainWindow::onAddRowAboveActionTriggered);
|
|
||||||
connect(addRowBelowAction, &QAction::triggered, this, &MainWindow::onAddRowBelowActionTriggered);
|
|
||||||
connect(delRowAction, &QAction::triggered, this, &MainWindow::onDelRowActionTriggered);
|
|
||||||
|
|
||||||
firstRowMenu = new QMenu(this);
|
|
||||||
QAction* addColAboveAction = firstRowMenu->addAction(tr("← 向左添加一列"));
|
|
||||||
QAction* addColBelowAction = firstRowMenu->addAction(tr("向右添加一列 →"));
|
|
||||||
QAction* delColAction = firstRowMenu->addAction(tr("删除"));
|
|
||||||
connect(addColAboveAction, &QAction::triggered, this, &MainWindow::onAddColAboveActionTriggered);
|
|
||||||
connect(addColBelowAction, &QAction::triggered, this, &MainWindow::onAddColBelowActionTriggered);
|
|
||||||
connect(delColAction, &QAction::triggered, this, &MainWindow::onDelColActionTriggered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::contextMenuEvent(QContextMenuEvent* event)
|
|
||||||
{
|
|
||||||
QPoint cellPos = ui->tableWidget->viewport()->mapFromGlobal(event->globalPos());
|
|
||||||
int currentColumn = ui->tableWidget->horizontalHeader()->logicalIndexAt(cellPos.x());
|
|
||||||
int currentRow = ui->tableWidget->rowAt(cellPos.y());
|
|
||||||
|
|
||||||
if (currentColumn == -1 && currentRow == -1) {
|
|
||||||
// 没有选中行也没有选中列,不显示菜单
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentColumn == -1 && currentRow >= 0) {
|
|
||||||
// 选中了行,显示行菜单
|
|
||||||
ui->tableWidget->selectRow(currentRow);
|
|
||||||
firstColMenu->popup(event->globalPos());
|
|
||||||
} else if (currentColumn >= 0 && currentRow == -1) {
|
|
||||||
// 选中了列,显示列菜单
|
|
||||||
ui->tableWidget->selectColumn(currentColumn);
|
|
||||||
firstRowMenu->popup(event->globalPos());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onAddRowAboveActionTriggered()
|
|
||||||
{
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int currentRow = tableWidget->currentRow();
|
|
||||||
if (currentRow >= 0)
|
|
||||||
{
|
|
||||||
tableWidget->insertRow(currentRow);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果没有选中行,在末尾追加一行
|
|
||||||
int newRow = tableWidget->rowCount();
|
|
||||||
tableWidget->insertRow(newRow);
|
|
||||||
currentRow = newRow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onAddRowBelowActionTriggered()
|
|
||||||
{
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int currentRow = tableWidget->currentRow();
|
|
||||||
if (currentRow >= 0)
|
|
||||||
{
|
|
||||||
tableWidget->insertRow(currentRow + 1); // 在下方插入一行
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果没有选中行,在末尾追加一行
|
|
||||||
int newRow = tableWidget->rowCount();
|
|
||||||
tableWidget->insertRow(newRow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onAddColAboveActionTriggered()
|
|
||||||
{
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int currentColumn = tableWidget->currentColumn();
|
|
||||||
if (currentColumn >= 0)
|
|
||||||
{
|
|
||||||
tableWidget->insertColumn(currentColumn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果没有选中列,在末尾追加一列
|
|
||||||
int newColumn = tableWidget->columnCount();
|
|
||||||
tableWidget->insertColumn(newColumn);
|
|
||||||
currentColumn = newColumn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onAddColBelowActionTriggered()
|
|
||||||
{
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int currentColumn = tableWidget->currentColumn();
|
|
||||||
if (currentColumn >= 0)
|
|
||||||
{
|
|
||||||
tableWidget->insertColumn(currentColumn + 1); // 在右侧插入一列
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果没有选中列,在末尾追加一列
|
|
||||||
int newColumn = tableWidget->columnCount();
|
|
||||||
tableWidget->insertColumn(newColumn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onDelRowActionTriggered()
|
|
||||||
{
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int currentRow = tableWidget->currentRow();
|
|
||||||
tableWidget->removeRow(currentRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onDelColActionTriggered()
|
|
||||||
{
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int currentColumn = tableWidget->currentColumn();
|
|
||||||
tableWidget->removeColumn(currentColumn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::showProgressDialog(const QString& labelText, int minimum, int maximum)
|
|
||||||
{
|
|
||||||
progressDialog = new QProgressDialog(labelText, "Cancel", minimum, maximum, this);
|
|
||||||
progressDialog->setWindowModality(Qt::WindowModal);
|
|
||||||
progressDialog->setAutoClose(false);
|
|
||||||
progressDialog->setAutoReset(false);
|
|
||||||
progressDialog->setValue(minimum);
|
|
||||||
progressDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::loadTextFile(const QString& fileName)
|
void MainWindow::loadTextFile(const QString& fileName)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
{
|
{
|
||||||
qDebug() << "Failed to open file:" << fileName;
|
// 文件打开失败,处理错误
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextStream in(&file);
|
QTextStream in(&file);
|
||||||
|
|
||||||
// 自动检测并设置正确的文本编码
|
// 获取文件大小并预分配内存
|
||||||
in.setAutoDetectUnicode(true);
|
qint64 fileSize = file.size();
|
||||||
in.setCodec("UTF-16LE");
|
QString textData;
|
||||||
|
textData.reserve(fileSize);
|
||||||
|
|
||||||
int tableRow = 0;
|
int tableRow = 0;
|
||||||
int tableCol = 0;
|
int tableCol = 0;
|
||||||
QStringList rows;
|
|
||||||
|
|
||||||
// 逐行读取文本数据
|
|
||||||
while (!in.atEnd())
|
while (!in.atEnd())
|
||||||
{
|
{
|
||||||
QString line = in.readLine();
|
QString line = in.readLine();
|
||||||
if (!line.isEmpty())
|
textData += line + "\n"; // 保存所有文本数据
|
||||||
{
|
|
||||||
rows.append(line);
|
|
||||||
tableRow++;
|
tableRow++;
|
||||||
|
|
||||||
if (tableRow == 2)
|
if (tableRow == 2)
|
||||||
{
|
{
|
||||||
QStringList columnValues = line.split("\t", QString::SkipEmptyParts);
|
tableCol = line.split("\t").count(); // 获取第二行的列数
|
||||||
tableCol = columnValues.count();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
showProgressDialog("Converting...", 0, tableRow);
|
progressDialog = new QProgressDialog("Loading...", "Cancel", 0, 0, this);
|
||||||
|
progressDialog->setWindowModality(Qt::WindowModal);
|
||||||
|
progressDialog->setAutoClose(false);
|
||||||
|
progressDialog->setAutoReset(false);
|
||||||
|
progressDialog->setRange(0, tableRow);
|
||||||
|
progressDialog->setValue(0);
|
||||||
|
progressDialog->show();
|
||||||
|
|
||||||
// 将数据显示在表格中
|
// 将数据显示在表格中
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
QTableWidget* tableWidget = ui->tableWidget;
|
||||||
|
@ -235,6 +100,7 @@ void MainWindow::loadTextFile(const QString& fileName)
|
||||||
|
|
||||||
tableWidget->blockSignals(true); // 阻止信号发射
|
tableWidget->blockSignals(true); // 阻止信号发射
|
||||||
|
|
||||||
|
QStringList rows = textData.split("\n");
|
||||||
for (int i = 0; i < tableRow; ++i)
|
for (int i = 0; i < tableRow; ++i)
|
||||||
{
|
{
|
||||||
QStringList row = rows.at(i).split("\t");
|
QStringList row = rows.at(i).split("\t");
|
||||||
|
@ -245,87 +111,34 @@ void MainWindow::loadTextFile(const QString& fileName)
|
||||||
tableWidget->setHorizontalHeaderLabels(row);
|
tableWidget->setHorizontalHeaderLabels(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 补充空白内容,确保行的列数与表格的列数一致
|
|
||||||
while (row.count() < tableCol)
|
|
||||||
{
|
|
||||||
row.append(""); // 添加空白内容
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < tableCol; ++j)
|
for (int j = 0; j < tableCol; ++j)
|
||||||
{
|
{
|
||||||
QTableWidgetItem* item = new QTableWidgetItem(row.at(j));
|
QTableWidgetItem* item = new QTableWidgetItem(row.at(j));
|
||||||
tableWidget->setItem(i, j, item);
|
tableWidget->setItem(i, j, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
progressDialog->setValue(i);
|
progressDialog->setValue(i);
|
||||||
QApplication::processEvents();
|
QApplication::processEvents(); // 处理界面事件,使进度条能够更新
|
||||||
if (progressDialog->wasCanceled())
|
if (progressDialog->wasCanceled())
|
||||||
{
|
{
|
||||||
tableWidget->clear();
|
tableWidget->clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
progressDialog->setValue(tableRow);
|
||||||
progressDialog->hide();
|
progressDialog->hide();
|
||||||
tableWidget->blockSignals(false); // 恢复信号发射
|
tableWidget->blockSignals(false); // 恢复信号发射
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::onOpenButtonClicked()
|
void MainWindow::onOpenButtonClicked()
|
||||||
{
|
{
|
||||||
openFilePath = QFileDialog::getOpenFileName(this, "Open Text File", "", "Text Files (*.txt)");
|
QString fileName = QFileDialog::getOpenFileName(this, "Open Text File", "", "Text Files (*.txt)");
|
||||||
if (!openFilePath.isEmpty())
|
if (!fileName.isEmpty())
|
||||||
{
|
{
|
||||||
loadTextFile(openFilePath);
|
loadTextFile(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onSaveButtonClicked()
|
void MainWindow::onSaveButtonClicked()
|
||||||
{
|
|
||||||
if (!openFilePath.isEmpty())
|
|
||||||
{
|
|
||||||
QFile file(openFilePath);
|
|
||||||
if (file.open(QIODevice::WriteOnly))
|
|
||||||
{
|
|
||||||
// 写入UTF-16带有BOM的标记
|
|
||||||
QByteArray bom;
|
|
||||||
bom.append((char)0xFF);
|
|
||||||
bom.append((char)0xFE);
|
|
||||||
file.write(bom);
|
|
||||||
|
|
||||||
QTextStream out(&file);
|
|
||||||
out.setCodec("UTF-16LE");//Qt6 use: out.setEncoding(QStringConverter::Utf16LE);
|
|
||||||
|
|
||||||
QTableWidget* tableWidget = ui->tableWidget;
|
|
||||||
int rowCount = tableWidget->rowCount();
|
|
||||||
int columnCount = tableWidget->columnCount();
|
|
||||||
|
|
||||||
for (int i = 0; i < rowCount; ++i)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < columnCount; ++j)
|
|
||||||
{
|
|
||||||
QTableWidgetItem* item = tableWidget->item(i, j);
|
|
||||||
if (item != nullptr)
|
|
||||||
{
|
|
||||||
QString text = item->text();
|
|
||||||
out << text;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j != columnCount - 1)
|
|
||||||
{
|
|
||||||
out << "\t"; // 制表符分隔
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << "\t"; // 最后一列再加一个制表符,以防万一
|
|
||||||
out << "\r\n"; // 换行,注意使用\r\n表示换行符
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onSaveAsButtonClicked()
|
|
||||||
{
|
{
|
||||||
QString fileName = QFileDialog::getSaveFileName(this, "Save Text File", "", "Text Files (*.txt)");
|
QString fileName = QFileDialog::getSaveFileName(this, "Save Text File", "", "Text Files (*.txt)");
|
||||||
if (!fileName.isEmpty())
|
if (!fileName.isEmpty())
|
||||||
|
@ -362,7 +175,7 @@ void MainWindow::onSaveAsButtonClicked()
|
||||||
out << "\t"; // 制表符分隔
|
out << "\t"; // 制表符分隔
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << "\t"; // 最后一列再加一个制表符,以防万一
|
|
||||||
out << "\r\n"; // 换行,注意使用\r\n表示换行符
|
out << "\r\n"; // 换行,注意使用\r\n表示换行符
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,10 +201,10 @@ void MainWindow::dropEvent(QDropEvent *event)
|
||||||
QList<QUrl> urlList = mimeData->urls();
|
QList<QUrl> urlList = mimeData->urls();
|
||||||
if (urlList.length() == 1)
|
if (urlList.length() == 1)
|
||||||
{
|
{
|
||||||
openFilePath = urlList.first().toLocalFile();
|
QString fileName = urlList.first().toLocalFile();
|
||||||
if (!openFilePath.isEmpty())
|
if (!fileName.isEmpty())
|
||||||
{
|
{
|
||||||
loadTextFile(openFilePath);
|
loadTextFile(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -438,6 +251,7 @@ void MainWindow::convertTextToSqlite()
|
||||||
columnNames = processedLine.split('\t', Qt::SkipEmptyParts);
|
columnNames = processedLine.split('\t', Qt::SkipEmptyParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//QTextStream textStream2(&textFile);
|
||||||
QList<QStringList> data;
|
QList<QStringList> data;
|
||||||
textStream.seek(0);
|
textStream.seek(0);
|
||||||
// 读取数据行
|
// 读取数据行
|
||||||
|
@ -445,20 +259,11 @@ void MainWindow::convertTextToSqlite()
|
||||||
{
|
{
|
||||||
QString line = textStream.readLine();
|
QString line = textStream.readLine();
|
||||||
QStringList values = line.split("\t");
|
QStringList values = line.split("\t");
|
||||||
|
|
||||||
// 截断行内容,保证不超过列名的个数
|
|
||||||
if (values.size() > columnNames.size())
|
|
||||||
{
|
|
||||||
values = values.mid(0, columnNames.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
data.append(values);
|
data.append(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
textFile.close();
|
textFile.close();
|
||||||
|
|
||||||
showProgressDialog("Converting...", 0, data.size());
|
|
||||||
|
|
||||||
// 打开SQLite数据库
|
// 打开SQLite数据库
|
||||||
QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
|
QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
|
||||||
database.setDatabaseName(sqliteFilePath);
|
database.setDatabaseName(sqliteFilePath);
|
||||||
|
@ -495,7 +300,6 @@ void MainWindow::convertTextToSqlite()
|
||||||
insertQuery.chop(2); // 移除最后的逗号和空格
|
insertQuery.chop(2); // 移除最后的逗号和空格
|
||||||
insertQuery += ");";
|
insertQuery += ");";
|
||||||
|
|
||||||
int progress = 0;
|
|
||||||
for (const QStringList& row : data)
|
for (const QStringList& row : data)
|
||||||
{
|
{
|
||||||
if (row.size() != columnNames.size())
|
if (row.size() != columnNames.size())
|
||||||
|
@ -517,17 +321,8 @@ void MainWindow::convertTextToSqlite()
|
||||||
database.close();
|
database.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++progress;
|
|
||||||
progressDialog->setValue(progress);
|
|
||||||
QApplication::processEvents();
|
|
||||||
if (progressDialog->wasCanceled())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progressDialog->hide();
|
|
||||||
database.commit();
|
database.commit();
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
@ -583,8 +378,6 @@ void MainWindow::convertSqliteToText()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
showProgressDialog("Converting...", 0, query.size());
|
|
||||||
|
|
||||||
// Open the text file to write data
|
// Open the text file to write data
|
||||||
QFile textFile(textFilePath);
|
QFile textFile(textFilePath);
|
||||||
if (!textFile.open(QIODevice::WriteOnly))
|
if (!textFile.open(QIODevice::WriteOnly))
|
||||||
|
@ -604,7 +397,6 @@ void MainWindow::convertSqliteToText()
|
||||||
textStream.setCodec("UTF-16LE");
|
textStream.setCodec("UTF-16LE");
|
||||||
|
|
||||||
// Write the data to the text file
|
// Write the data to the text file
|
||||||
int progress = 0;
|
|
||||||
while (query.next())
|
while (query.next())
|
||||||
{
|
{
|
||||||
QSqlRecord record = query.record();
|
QSqlRecord record = query.record();
|
||||||
|
@ -615,19 +407,9 @@ void MainWindow::convertSqliteToText()
|
||||||
if (i < record.count() - 1)
|
if (i < record.count() - 1)
|
||||||
textStream << "\t";
|
textStream << "\t";
|
||||||
}
|
}
|
||||||
textStream << "\t";
|
|
||||||
textStream << "\r\n";
|
textStream << "\r\n";
|
||||||
|
|
||||||
++progress;
|
|
||||||
progressDialog->setValue(progress);
|
|
||||||
QApplication::processEvents();
|
|
||||||
if (progressDialog->wasCanceled())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progressDialog->hide();
|
|
||||||
textFile.close();
|
textFile.close();
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
|
20
mainwindow.h
20
mainwindow.h
|
@ -1,8 +1,9 @@
|
||||||
#ifndef MAINWINDOW_H
|
#ifndef MAINWINDOW_H
|
||||||
#define MAINWINDOW_H
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include "qprogressdialog.h"
|
||||||
|
#include <QThread>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QProgressDialog>
|
|
||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
@ -24,26 +25,15 @@ public:
|
||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event);
|
||||||
void convertTextToSqlite();
|
void convertTextToSqlite();
|
||||||
void convertSqliteToText();
|
void convertSqliteToText();
|
||||||
void showProgressDialog(const QString& labelText, int minimum, int maximum);
|
|
||||||
void contextMenuEvent(QContextMenuEvent* event);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onOpenButtonClicked();
|
void onOpenButtonClicked();
|
||||||
void onSaveButtonClicked();
|
void onSaveButtonClicked();
|
||||||
void onSaveAsButtonClicked();
|
|
||||||
void onAddRowAboveActionTriggered();
|
|
||||||
void onAddRowBelowActionTriggered();
|
|
||||||
void onAddColAboveActionTriggered();
|
|
||||||
void onAddColBelowActionTriggered();
|
|
||||||
void onDelRowActionTriggered();
|
|
||||||
void onDelColActionTriggered();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
QProgressDialog* progressDialog;
|
QProgressDialog* progressDialog; // 添加进度对话框指针
|
||||||
QString openFilePath;
|
QMenu* menuFile;
|
||||||
QMenu* firstColMenu; // 右键菜单
|
QAction* actionFile;
|
||||||
QMenu* firstRowMenu; // 右键菜单
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTableWidget" name="tableWidget"/>
|
<widget class="QTableWidget" name="tableWidget"/>
|
||||||
</item>
|
</item>
|
||||||
|
@ -45,10 +42,10 @@
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionOpen"/>
|
<addaction name="actionOpen"/>
|
||||||
<addaction name="actionSave"/>
|
<addaction name="actionSave"/>
|
||||||
<addaction name="actionSaveAs"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuOpen"/>
|
<addaction name="menuOpen"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
<action name="actionOpen">
|
<action name="actionOpen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>打开</string>
|
<string>打开</string>
|
||||||
|
@ -56,18 +53,12 @@
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSave">
|
<action name="actionSave">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="Save">
|
<iconset theme="Save"/>
|
||||||
<normaloff>.</normaloff>.</iconset>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>保存</string>
|
<string>保存</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSaveAs">
|
|
||||||
<property name="text">
|
|
||||||
<string>另存为...</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
@echo off
|
|
||||||
setlocal
|
|
||||||
|
|
||||||
REM 获取当前脚本所在目录
|
|
||||||
set "SCRIPT_DIR=%~dp0"
|
|
||||||
|
|
||||||
REM 构建路径选择
|
|
||||||
set "BUILD_DIR="
|
|
||||||
|
|
||||||
REM 构建类型选择
|
|
||||||
set "BUILD_TYPE="
|
|
||||||
|
|
||||||
REM 列出同级目录中包含 "build" 的文件夹
|
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
set "BUILD_INDEX=1"
|
|
||||||
for /d %%D in ("%SCRIPT_DIR%..\build*") do (
|
|
||||||
echo [!BUILD_INDEX!] %%~fD
|
|
||||||
set "BUILD_DIRS[!BUILD_INDEX!]=%%~fD"
|
|
||||||
set /a "BUILD_INDEX+=1"
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 检查是否找到 build 文件夹
|
|
||||||
if "%BUILD_INDEX%"=="1" (
|
|
||||||
echo Error: Build directory not found.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 提示用户选择构建目录
|
|
||||||
set /p "BUILD_SELECTION=Enter the number of the build directory: "
|
|
||||||
|
|
||||||
REM 根据用户选择设置构建目录
|
|
||||||
if defined BUILD_DIRS[%BUILD_SELECTION%] (
|
|
||||||
set "BUILD_DIR=!BUILD_DIRS[%BUILD_SELECTION%]!"
|
|
||||||
) else (
|
|
||||||
echo Error: Invalid build directory selection.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 提示用户选择构建类型
|
|
||||||
echo Choose the build type:
|
|
||||||
echo [1] Debug
|
|
||||||
echo [2] Release
|
|
||||||
set /p "BUILD_TYPE=Enter the number of the build type: "
|
|
||||||
|
|
||||||
REM 根据用户选择设置构建目录和构建类型
|
|
||||||
if "%BUILD_TYPE%"=="1" (
|
|
||||||
set "BUILD_DIR=%BUILD_DIR%\debug"
|
|
||||||
) else if "%BUILD_TYPE%"=="2" (
|
|
||||||
set "BUILD_DIR=%BUILD_DIR%\release"
|
|
||||||
) else (
|
|
||||||
echo Error: Invalid build type.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 寻找当前要编译的exe程序
|
|
||||||
set "EXECUTABLE=%BUILD_DIR%\TabEditor.exe"
|
|
||||||
if not exist "%EXECUTABLE%" (
|
|
||||||
echo Error: Executable not found in the selected build directory.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
REM 切换到Qt环境变量脚本所在目录
|
|
||||||
cd /d "C:\Qt\Qt5.14.2\5.14.2\mingw73_64\bin"
|
|
||||||
|
|
||||||
REM 运行Qt环境变量脚本
|
|
||||||
call qtenv2.bat
|
|
||||||
|
|
||||||
REM 切换到构建目录
|
|
||||||
cd /d "%BUILD_DIR%"
|
|
||||||
|
|
||||||
REM 运行windeployqt命令来打包依赖项
|
|
||||||
echo Running windeployqt to package dependencies...
|
|
||||||
windeployqt "%EXECUTABLE%"
|
|
||||||
|
|
||||||
REM 切换回脚本所在目录
|
|
||||||
cd /d "%SCRIPT_DIR%"
|
|
||||||
|
|
||||||
REM 完成打包
|
|
||||||
echo.
|
|
||||||
echo Packaging completed successfully.
|
|
||||||
pause
|
|
Binary file not shown.
Before Width: | Height: | Size: 57 KiB |
Loading…
Reference in New Issue
Block a user