-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmainwindow.cpp
More file actions
202 lines (172 loc) · 8.6 KB
/
Copy pathmainwindow.cpp
File metadata and controls
202 lines (172 loc) · 8.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "mainwindow.h"
#include "src/common/utils/FileUtils.h"
#include "src/ui/view/LexicalConfigResultView.h"
#include "src/ui/view/SyntaxConfigResultView.h"
#include "src/ui/view/AnalysisResultView.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
resize(1200, 800);
setWindowTitle("简易IDE - 未加载项目");
setupUI();
setupMenu();
setupComponents();
}
MainWindow::~MainWindow() {}
void MainWindow::onActionOpenProject()
{
QString dirPath = QFileDialog::getExistingDirectory(this, "选择项目文件夹", QDir::homePath());
if (dirPath.isEmpty()) return;
// 让 ProjectPanel 加载目录
projectPanel_->loadProject(dirPath);
setWindowTitle("简易 IDE - " + QDir(dirPath).dirName());
}
void MainWindow::onActionSave()
{
// 让 EditorTabWidget 保存当前标签页
editorTabWidget_->saveCurrentFile();
}
void MainWindow::onViewLexicalConfigResult()
{
LexicalConfigResultView* lexicalConfigResultView = new LexicalConfigResultView(lexicalServicer_->processingUnits());
lexicalConfigResultView->setAttribute(Qt::WA_DeleteOnClose);
lexicalConfigResultView->show();
}
void MainWindow::onViewLexicalCode()
{
QString cppSaveFilePath = lexicalServicer_->configArgs().cppSaveFilePath;
QString cppFileName = FileUtils::fileName(cppSaveFilePath);
editorTabWidget_->openFile(cppSaveFilePath, cppFileName);
}
void MainWindow::onViewSyntaxConfigResult()
{
SyntaxConfigResultView* syntaxConfigResultView = new SyntaxConfigResultView();
syntaxConfigResultView->setFirstFollowSets(syntaxServicer_->firstSets(), syntaxServicer_->followSets());
syntaxConfigResultView->setLR0Data(syntaxServicer_->lr0DFAGraph(), syntaxServicer_->lr0StateToItemSetMap(),
syntaxServicer_->grammarCore().productions, syntaxServicer_->slr1Report());
syntaxConfigResultView->setLR1Data(syntaxServicer_->lr1DFAGraph(), syntaxServicer_->lr1StateToItemSetMap(), syntaxServicer_->grammarCore().productions);
syntaxConfigResultView->setLR1ParseTable(syntaxServicer_->lr1ParseTable());
syntaxConfigResultView->setAttribute(Qt::WA_DeleteOnClose);
syntaxConfigResultView->show();
}
void MainWindow::onAnalysisClicked()
{
QString sourceFilePath = editorTabWidget_->getCurrentFilePath();
if (sourceFilePath.isEmpty()) {
QMessageBox::information(this, "提醒", "请先打开文件");
return;
}
centralConsole_->clearConsole();
centralConsole_->clearErrorLog();
QString lexSaveFilePath = FileUtils::filePathWithExtension(sourceFilePath, ".lex");
QString tableFilePath = lexicalServicer_->configArgs().tableSaveFilePath;
// 这种写法可以在词法分析错误时不再进行语法分析
if (lexicalServicer_->analyze(sourceFilePath, lexSaveFilePath) && syntaxServicer_->analyze(tableFilePath, lexSaveFilePath, sourceFilePath)) {
AnalysisResultView* analysisView = new AnalysisResultView();
analysisView->setAttribute(Qt::WA_DeleteOnClose);
analysisView->setAST(syntaxServicer_->analysisResult().root);
analysisView->setAnalysisSteps(syntaxServicer_->analysisResult().steps);
analysisView->setQuadruples(syntaxServicer_->analysisResult().quadruples);
analysisView->show();
}
}
void MainWindow::onConfigClicked()
{
if (compilerConfig_->exec() == QDialog::Accepted) {
viewLexMenu_->setEnabled(false);
viewSynAction_->setEnabled(false);
if (compilerConfig_->isEmpty()) {
QMessageBox::information(this, "提醒", "配置路径不齐全,未启用配置功能");
return;
}
centralConsole_->clearConsole();
centralConsole_->clearErrorLog();
CFW::LexicalConfig lexicalConfigArgs;
lexicalConfigArgs.regexFilePath = compilerConfig_->regexPath();
lexicalConfigArgs.commpilerCppFilePath = compilerConfig_->cppCompilerPath();
lexicalConfigArgs.cppSaveFilePath = FileUtils::filePathWithExtension(lexicalConfigArgs.regexFilePath, ".cpp");
lexicalConfigArgs.exeSaveFilePath = FileUtils::filePathWithExtension(lexicalConfigArgs.regexFilePath, ".exe");
lexicalConfigArgs.tableSaveFilePath = FileUtils::filePathWithExtension(lexicalConfigArgs.regexFilePath, ".table");
bool lexicalSuccess = lexicalServicer_->config(lexicalConfigArgs);
CFW::SyntaxConfig syntaxConfigArgs;
syntaxConfigArgs.bnfFilePath = compilerConfig_->bnfPath();
bool syntaxSuccess = syntaxServicer_->config(syntaxConfigArgs);
triangleButton_->setEnabled(lexicalSuccess && syntaxSuccess);
viewLexMenu_->setEnabled(lexicalSuccess);
viewSynAction_->setEnabled(syntaxSuccess);
}
}
void MainWindow::setupUI()
{
// --- 实例化三大面板 ---
projectPanel_ = new ProjectPanel(this);
editorTabWidget_ = new EditorTabWidget(this);
centralConsole_ = new CentralConsole(this);
// --- 连接组件间的信号与槽 ---
// 1. 项目面板 -> 编辑器 (请求打开文件)
connect(projectPanel_, &ProjectPanel::fileOpenRequested, editorTabWidget_, &EditorTabWidget::openFile);
// --- 布局管理 (Splitters) ---
// 垂直分割:上方是编辑器,下方是控制台
QSplitter *vSplitter = new QSplitter(Qt::Vertical, this);
vSplitter->addWidget(editorTabWidget_);
vSplitter->addWidget(centralConsole_);
vSplitter->setStretchFactor(0, 4); // 编辑器占 4/5
vSplitter->setStretchFactor(1, 1); // 控制台占 1/5
// 水平分割:左侧是文件树,右侧是 (编辑器+控制台)
QSplitter *hSplitter = new QSplitter(Qt::Horizontal, this);
hSplitter->addWidget(projectPanel_);
hSplitter->addWidget(vSplitter);
hSplitter->setStretchFactor(0, 1); // 左侧窄
hSplitter->setStretchFactor(1, 5); // 右侧宽
// 设置为主窗口中心部件
setCentralWidget(hSplitter);
}
void MainWindow::setupMenu()
{
QMenuBar *bar = menuBar();
// === 文件菜单 ===
QMenu *fileMenu = bar->addMenu("文件(&F)");
fileMenu->addAction("打开项目文件夹...", QKeySequence::Open, this, &MainWindow::onActionOpenProject);
fileMenu->addAction("保存当前文件", QKeySequence::Save, this, &MainWindow::onActionSave);
fileMenu->addSeparator();
fileMenu->addAction("退出", this, &QWidget::close);
// === 查看菜单 ===
QMenu *viewMenu = bar->addMenu("查看(&V)");
// 子菜单:控制面板显示/隐藏
QMenu *viewBarMenu = viewMenu->addMenu("视图布局");
viewBarMenu->addAction("显示/隐藏文件栏", this, [=](){ projectPanel_->toggleView(!projectPanel_->isVisible());});
viewBarMenu->addAction("显示/隐藏底部面板", this, [=](){ centralConsole_->setVisible(!centralConsole_->isVisible());});
// 子菜单:词法配置结果相关
viewLexMenu_ = viewMenu->addMenu("词法配置结果");
viewLexMenu_->addAction("状态转换表", this, &MainWindow::onViewLexicalConfigResult);
viewLexMenu_->addAction("词法分析源程序", this, &MainWindow::onViewLexicalCode);
viewLexMenu_->setEnabled(false);
// 子菜单:语法配置结果相关
viewSynAction_ = viewMenu->addAction("语法配置结果");
connect(viewSynAction_, &QAction::triggered, this, &MainWindow::onViewSyntaxConfigResult);
viewSynAction_->setEnabled(false);
// === 配置菜单
QMenu *configMenu = bar->addMenu("配置(&C)");
configMenu->addAction("编译配置...", this, &MainWindow::onConfigClicked);
// === 在菜单栏最右侧添加三角形“构建”按钮 ===
QWidget* rightContainer = new QWidget(bar);
QHBoxLayout* hl = new QHBoxLayout(rightContainer);
hl->setContentsMargins(0, 0, 6, 0); // 右侧留一点空隙
hl->addStretch();
triangleButton_ = new TriangleButton(QStringLiteral("构建"), rightContainer);
connect(triangleButton_, &QPushButton::clicked, this, &MainWindow::onAnalysisClicked);
hl->addWidget(triangleButton_);
// 将容器放到菜单栏右上角
bar->setCornerWidget(rightContainer, Qt::TopRightCorner);
}
void MainWindow::setupComponents()
{
// 页面初始化
compilerConfig_ = new CompilerConfig(this);
// 服务初始化
lexicalServicer_ = new LexicalServicer();
connect(lexicalServicer_, &LexicalServicer::errorOccurred, centralConsole_, &CentralConsole::onErrorOccurred);
connect(lexicalServicer_, &LexicalServicer::infoOccurred, centralConsole_, &CentralConsole::onInfoOccurred);
syntaxServicer_ = new SyntaxServicer();
connect(syntaxServicer_, &SyntaxServicer::errorOccurred, centralConsole_, &CentralConsole::onErrorOccurred);
connect(syntaxServicer_, &SyntaxServicer::infoOccurred, centralConsole_, &CentralConsole::onInfoOccurred);
}