QtNovelUI/WordsIDE/mainwindow.cpp

476 lines
16 KiB
C++
Raw Normal View History

#include "SourceEditView.h"
2022-11-06 00:37:50 +00:00
#include "mainwindow.h"
#include <QLabel>
#include <QMenuBar>
#include <QStatusBar>
#include <QDebug>
#include <QDateTime>
#include <QTextEdit>
2022-11-15 08:07:02 +00:00
#include <QToolBar>
2022-11-18 23:47:32 +00:00
#include <xmlconfig.h>
2022-11-15 08:07:02 +00:00
#include <xmlprojectmanager.h>
#include <QFileDialog>
#include <QInputDialog>
#include <QApplication>
#include <QMessageBox>
2022-11-15 08:07:02 +00:00
using namespace Project;
using namespace MakeTools;
2022-11-15 12:58:12 +00:00
using namespace Parse::Result;
using namespace Components;
2022-11-06 00:37:50 +00:00
MainWindow::MainWindow(QWidget *parent)
2022-11-15 08:07:02 +00:00
: QMainWindow(parent),
2022-11-18 23:47:32 +00:00
global_config(new Config::XMLConfig(this)),
sync_kernel(new StatusSyncCore(this)),
2022-11-15 08:07:02 +00:00
horizontal_split(new QSplitter(Qt::Horizontal, this)),
vertical_split(new QSplitter(Qt::Vertical, this)),
left_funcs(new QTabWidget(this)),
right_funcs(new QTabWidget(this)),
center_funcs(new QTabWidget(this)),
bottom_funcs(new QTabWidget(this)),
2022-11-15 12:58:12 +00:00
project_manager(new XMLProjectManager(this)),
2022-11-18 05:43:27 +00:00
parse_core(new ParseCore()),
make_tool(new StoryTool(parse_core)),
project_list(new QListView(this)),
2022-11-18 23:47:32 +00:00
project_structure(new ProjectView(project_manager, this)),
2022-11-18 05:43:27 +00:00
chains_view(new StoryChainsPresent(parse_core, this)),
2022-11-18 23:47:32 +00:00
units_view(new StoryUnitsPresent(parse_core, this)),
errors_present(new MessagePresent(make_tool, this)),
framework(new SensitiveCore(make_tool))
2022-11-06 00:37:50 +00:00
{
2022-11-18 23:47:32 +00:00
QApplication::instance()->installEventFilter(this);
global_config->loadFile(QDir(QApplication::applicationDirPath()).filePath(".software.xml"));
setMinimumSize(1000, 600);
2022-11-15 12:58:12 +00:00
setWindowTitle("提线木偶集成开发工具");
2022-11-18 23:47:32 +00:00
chains_view->setVisible(false);
units_view->setVisible(false);
errors_present->setVisible(false);
project_structure->setVisible(false);
left_funcs->setVisible(false);
right_funcs->setVisible(false);
bottom_funcs->setVisible(false);
2022-11-15 08:07:02 +00:00
auto xtool = new QToolBar(this);
2022-11-18 23:47:32 +00:00
xtool->setVisible(false);
2022-11-15 08:07:02 +00:00
addToolBar(Qt::ToolBarArea::TopToolBarArea, xtool);
auto xstatus = statusBar();
2022-11-18 23:47:32 +00:00
xstatus->setVisible(false);
2022-11-15 08:07:02 +00:00
statusBar()->addWidget(new QLabel("文本消息", this));
auto mbar = menuBar();
// 项目菜单树
auto project = mbar->addMenu("项目");
project->addAction("新建路径", [this](){
auto packages = QInputDialog::getText(this, "输入包路径名称", "packagea#packageb#packagec");
if(packages == "")
return;
QList<QString> names;
QRegExp exp("([^#]+)");
auto idx=0;
while ((idx = exp.indexIn(packages, idx)) != -1) {
names << exp.capturedTexts()[1];
idx += names.last().length();
}
project_manager->newPath(names);
});
auto _xnew = project->addMenu("最后卷新建文件");
2022-11-15 08:07:02 +00:00
_xnew->addAction("发展脉络");
_xnew->addAction("故事单元");
2022-11-15 08:07:02 +00:00
_xnew->addAction("故事大纲");
_xnew->addAction("叙事大纲");
2022-11-15 12:58:12 +00:00
_xnew->addSeparator();
2022-11-15 08:07:02 +00:00
_xnew->addAction("小说章节");
project->addSeparator();
2022-11-15 08:07:02 +00:00
auto sav = project->addAction("保存");
2022-11-18 23:47:32 +00:00
sync_kernel->registerActionSync(sav, [this]()->bool{return project_manager->isOpen();});
2022-11-15 08:07:02 +00:00
connect(sav, &QAction::triggered, [this](){
this->project_manager->save();
framework->saveAll();
2022-11-15 08:07:02 +00:00
});
project->addSeparator();
auto opnp = project->addAction("打开项目");
2022-11-18 23:47:32 +00:00
sync_kernel->registerActionSync(opnp, [this]()->bool{return !project_manager->isOpen();});
connect(opnp, &QAction::triggered, [this](){
2022-11-15 08:07:02 +00:00
auto file = QFileDialog::getOpenFileName(this, "打开项目", QString(), "小说项目(*.nsf)");
if(file == "")
return;
project_manager->openProject(file);
build_internal(true);
2022-11-15 08:07:02 +00:00
});
auto newp = project->addAction("新建项目");
2022-11-18 23:47:32 +00:00
sync_kernel->registerActionSync(newp, [this]()->bool{return !project_manager->isOpen();});
connect(newp, &QAction::triggered, [this](){
2022-11-15 08:07:02 +00:00
auto name = QInputDialog::getText(this, "输入项目名称", "项目名称");
if(name == "")
return;
auto dir_path = QFileDialog::getExistingDirectory(this, "指定项目存储路径");
if(dir_path == "")
return;
this->project_manager->newProject(dir_path, name);
});
auto clsp = project->addAction("关闭项目");
2022-11-18 23:47:32 +00:00
sync_kernel->registerActionSync(clsp, [this]()->bool{return project_manager->isOpen();});
connect(clsp, &QAction::triggered, [this](){
2022-11-15 08:07:02 +00:00
this->project_manager->closeProject();
});
project->addSeparator();
project->addAction("项目配置");
project->addAction("软件配置");
project->addSeparator();
project->addAction("退出", [](){ QApplication::exit(0); });
// 编辑菜单
auto edit = mbar->addMenu("编辑");
edit->addAction("撤销一步");
edit->addAction("重做一步");
edit->addSeparator();
edit->addAction("查找关键词");
edit->addAction("替换关键词");
// 视图菜单
auto view = mbar->addMenu("视图");
2022-11-15 08:07:02 +00:00
auto area = view->addMenu("区域管理");
2022-11-18 23:47:32 +00:00
2022-11-15 08:07:02 +00:00
auto act_tool = area->addAction("工具栏");
act_tool->setCheckable(true);
connect(act_tool, &QAction::triggered, [xtool](bool v){ xtool->setVisible(v); });
auto act_status = area->addAction("状态栏");
act_status->setCheckable(true);
connect(act_status,&QAction::triggered, [xstatus](bool v){xstatus->setVisible(v);});
auto act_left = area->addAction("左侧功能区");
act_left->setCheckable(true);
connect(act_left, &QAction::triggered, [this](bool v){this->left_funcs->setVisible(v);});
auto act_right = area->addAction("右侧功能区");
act_right->setCheckable(true);
connect(act_right, &QAction::triggered, [this](bool v){this->right_funcs->setVisible(v);});
auto act_bottom = area->addAction("底部功能区");
act_bottom->setCheckable(true);
connect(act_bottom, &QAction::triggered, [this](bool v){this->bottom_funcs->setVisible(v);});
view->addSeparator();
2022-11-15 08:07:02 +00:00
auto change = view->addMenu("内容切换");
change->addAction("序列视图");
change->addAction("编辑视图");
2022-11-15 08:07:02 +00:00
view->addSeparator();
auto func = view->addMenu("功能视图");
2022-11-18 23:47:32 +00:00
// 项目管理
{
auto project_v = func->addAction("项目管理", [this](bool v){
toggle_widget_visible(v, left_funcs, project_structure, "项目管理");
});
project_v->setCheckable(true);
sync_kernel->registerAutoRun([this]()->bool{return this->project_structure->isVisible();},
[project_v](bool v){ if(v != project_v->isChecked()) project_v->setChecked(v); });
}
func->addAction("引用统计");
func->addAction("脉络分蘖");
2022-11-18 23:47:32 +00:00
// 编译信息
{
auto msgs = func->addAction("终端输出", [this](bool v){
toggle_widget_visible(v, bottom_funcs, errors_present, "编译信息");
});
msgs->setCheckable(true);
sync_kernel->registerAutoRun([this]()->bool{return errors_present->isVisible();},
[msgs](bool v){if(v!=msgs->isChecked()) msgs->setChecked(v);});
}
// 脉络统计
{
auto chain_v = func->addAction("脉络统计", [this](bool v){
toggle_widget_visible(v, right_funcs, chains_view, "脉络统计");
});
chain_v->setCheckable(true);
sync_kernel->registerAutoRun([this]()->bool{return chains_view->isVisible();},
[chain_v](bool v){ if(v != chain_v->isChecked()) chain_v->setChecked(v);});
}
// 单元统计
{
auto unit_v = func->addAction("单元统计", [this](bool v){
toggle_widget_visible(v, right_funcs, units_view, "单元统计");
});
unit_v->setCheckable(true);
sync_kernel->registerAutoRun([this]()->bool{return units_view->isVisible();},
[unit_v](bool v){if(v != unit_v->isChecked()) unit_v->setChecked(v);});
}
// 工具菜单
auto tool = mbar->addMenu("工具");
auto word = tool->addMenu("敏感词检测");
word->addAction("工具配置");
word->addAction("敏感词编辑");
auto vcs = tool->addMenu("版本管理");
vcs->addAction("工具配置");
vcs->addAction("启用");
auto exp = tool->addMenu("导入导出");
2022-11-18 23:47:32 +00:00
exp->addAction("导入WsOutlines");
exp->addSeparator();
2022-11-15 08:07:02 +00:00
exp->addAction("导出TXT大纲");
2022-11-18 23:47:32 +00:00
exp->addAction("导出Web大纲");
exp->addAction("导出WsOutlines");
exp->addSeparator();
exp->addAction("导出TXT内容");
2022-11-15 12:58:12 +00:00
tool->addAction("编译", [this](){
this->build_internal();
});
// 窗口菜单
auto window = mbar->addMenu("窗口");
window->addAction("新建窗口");
window->addAction("关闭窗口");
window->addSeparator();
window->addAction("布局管理");
window->addMenu("布局切换");
window->addMenu("窗口切换");
// 系统
auto sys = mbar->addMenu("系统");
sys->addAction("软件激活");
sys->addAction("系统信息");
sys->addSeparator();
sys->addAction("关于……");
2022-11-18 23:47:32 +00:00
setCentralWidget(this->horizontal_split);
2022-11-15 08:07:02 +00:00
this->horizontal_split->addWidget(left_funcs);
this->horizontal_split->addWidget(vertical_split);
this->horizontal_split->addWidget(right_funcs);
this->vertical_split->addWidget(center_funcs);
this->vertical_split->addWidget(bottom_funcs);
2022-11-18 23:47:32 +00:00
left_funcs->setTabsClosable(true);
connect(left_funcs, &QTabWidget::tabCloseRequested,
[this](int index){ toggle_widget_visible(false, left_funcs, left_funcs->widget(index)); });
bottom_funcs->setTabsClosable(true);
connect(bottom_funcs, &QTabWidget::tabCloseRequested,
[this](int index){ toggle_widget_visible(false, bottom_funcs, bottom_funcs->widget(index)); });
right_funcs->setTabsClosable(true);
connect(right_funcs, &QTabWidget::tabCloseRequested,
[this](int index){ toggle_widget_visible(false, right_funcs, right_funcs->widget(index)); });
center_funcs->setTabsClosable(true);
connect(center_funcs, &QTabWidget::tabCloseRequested,
[this](int index){ toggle_widget_visible(false, center_funcs, center_funcs->widget(index)); });
2022-11-18 05:43:27 +00:00
center_funcs->addTab(project_list, "欢迎界面");
2022-11-18 23:47:32 +00:00
connect(project_structure, &ProjectView::activeDocument,
[this](const QString &file_path, const QString &name){
2022-11-17 08:52:37 +00:00
if(framework->contains(file_path)){
auto ins = framework->queryComponent(QFileInfo(file_path));
center_funcs->setCurrentWidget(ins->textView());
return;
2022-11-17 08:52:37 +00:00
}
VariedTextView *tview = nullptr;
if(file_path.endsWith("storychain")){
tview = new Components::StoryChainSourceEdit(QFileInfo(file_path), this);
framework->addPerceptionList(tview);
2022-11-18 05:43:27 +00:00
auto doc = parse_core->queryDocument(QFileInfo(file_path));
if(doc == nullptr){
this->make_tool->compile(QFileInfo(file_path));
doc = parse_core->queryDocument(QFileInfo(file_path));
}
tview->reset(doc);
}
else if(file_path.endsWith("storyunit")){
tview = new Components::StoryUnitSourceEdit(QFileInfo(file_path), this);
framework->addPerceptionList(tview);
2022-11-18 23:47:32 +00:00
auto doc = parse_core->queryDocument(QFileInfo(file_path));
if(doc == nullptr){
this->make_tool->compile(QFileInfo(file_path));
doc = parse_core->queryDocument(QFileInfo(file_path));
}
tview->reset(doc);
}
else if(file_path.endsWith("storyboard")){
tview = new Components::StoryBoardSourceEdit(QFileInfo(file_path), this);
framework->addPerceptionList(tview);
2022-11-18 23:47:32 +00:00
auto doc = parse_core->queryDocument(QFileInfo(file_path));
if(doc == nullptr){
this->make_tool->compile(QFileInfo(file_path));
doc = parse_core->queryDocument(QFileInfo(file_path));
}
tview->reset(doc);
}
else if(file_path.endsWith("storyvolume")){
tview = new Components::StoryVolumeSourceEdit(QFileInfo(file_path), this);
framework->addPerceptionList(tview);
2022-11-18 23:47:32 +00:00
auto doc = parse_core->queryDocument(QFileInfo(file_path));
if(doc == nullptr){
this->make_tool->compile(QFileInfo(file_path));
doc = parse_core->queryDocument(QFileInfo(file_path));
}
tview->reset(doc);
}
else{
2022-11-18 23:47:32 +00:00
auto xview = new Components::TextContentEdit(QFileInfo(file_path), this);
xview->getConfigHost()->reload(QList<Config::Configration*>() << project_manager->configraions());
tview = xview;
framework->addPerceptionList(tview, SensitiveType::DoNothing);
}
if(tview == nullptr)
{
QMessageBox::critical(this, "系统错误", "指定文件类型没有确定编辑器");
return;
}
QFile fin(file_path);
if(!fin.open(QIODevice::ReadOnly | QIODevice::Text)){
QMessageBox::critical(this, "系统错误", QString("无法打开指定文件:%1(%2)").arg(name, file_path));
return;
}
QTextStream tin(&fin);
tview->textContentReset(tin.readAll());
center_funcs->addTab(tview->textView(), name);
center_funcs->setCurrentWidget(tview->textView());
});
2022-11-18 05:43:27 +00:00
framework->addProcTrigger([this](){
errors_present->refresh();
chains_view->refresh();
2022-11-18 23:47:32 +00:00
units_view->refresh();
2022-11-18 05:43:27 +00:00
});
2022-11-06 00:37:50 +00:00
}
MainWindow::~MainWindow()
{
}
2022-11-15 12:58:12 +00:00
void MainWindow::build_internal(bool all_from_disk)
2022-11-15 12:58:12 +00:00
{
if(!all_from_disk)
framework->saveAll();
2022-11-15 12:58:12 +00:00
auto chains = project_manager->filesWithEnds("storychain");
for(auto &it : chains)
make_tool->compile(it);
auto units = project_manager->filesWithEnds("storyunit");
for(auto &it : units)
make_tool->compile(it);
auto storys = project_manager->filesWithEnds("storyboard");
for(auto &it : storys)
make_tool->compile(it);
auto volumes = project_manager->filesWithEnds("storyvolume");
for(auto &it : volumes)
make_tool->compile(it);
errors_present->refresh();
2022-11-18 05:43:27 +00:00
chains_view->refresh();
2022-11-18 23:47:32 +00:00
units_view->refresh();
}
void MainWindow::toggle_widget_visible(bool visible, QTabWidget *con, QWidget *target, const QString &title)
{
if(visible && con->indexOf(target) == -1){
con->addTab(target, title);
target->setVisible(true);
}else if(!visible && con->indexOf(target) != -1){
target->setVisible(false);
con->removeTab(con->indexOf(target));
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
// 关闭事件
if(project_manager->isOpen()){
project_manager->save();
framework->saveAll();
}
QMainWindow::closeEvent(event);
2022-11-15 12:58:12 +00:00
}
2022-11-18 23:47:32 +00:00
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
auto ev = event->type();
switch(ev){
case QEvent::Type::MouseButtonPress:
case QEvent::Type::MouseButtonRelease:
case QEvent::Type::Wheel:
case QEvent::Type::MouseMove:
case QEvent::Type::KeyPress:
case QEvent::Type::KeyRelease:
sync_kernel->sync();
break;
default:
break;
}
return QMainWindow::eventFilter(watched, event);
}
Run::Run(bool manual_flag, std::function<bool ()> judge, std::function<void (bool)> execution)
: manual(manual_flag), judgement(judge), execution(execution){}
void Run::exec()
{
if(!manual)
execution(judgement());
}
StatusSyncCore::StatusSyncCore(QObject *p)
: QObject(p){}
void StatusSyncCore::registerWidgetSync(QWidget *tar, std::function<bool ()> proc)
{
widget_trigger_map[tar] = proc;
}
void StatusSyncCore::registerActionSync(QAction *tar, std::function<bool ()> proc)
{
action_trigger_map[tar] = proc;
}
void StatusSyncCore::registerAutoRun(std::function<bool ()> judge, std::function<void (bool)> exec)
{
auto run = new Run(false, judge, exec);
alltriggers << run;
}
Run *StatusSyncCore::registerManualRun(std::function<bool ()> judge, std::function<void (bool)> exec)
{
auto run = new Run(true, judge, exec);
alltriggers << run;
return run;
}
void StatusSyncCore::sync()
{
for(auto &it : widget_trigger_map.keys()){
auto status = widget_trigger_map[it]();
if(it->isEnabled() != status)
it->setEnabled(status);
}
for(auto &it : action_trigger_map.keys()){
auto status = action_trigger_map[it]();
if(it->isEnabled() != status)
it->setEnabled(status);
}
for(auto &act : alltriggers){
act->exec();
}
}