1 Star 7 Fork 4

xiongqiumin/JZNodeEditor

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mainwindow.cpp 51.58 KB
一键复制 编辑 原始数据 按行查看 历史
xiongqiumin 提交于 2024-09-26 22:22 . update
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
#include "mainwindow.h"
#include <QDebug>
#include <QFile>
#include <QElapsedTimer>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QLabel>
#include <QMenuBar>
#include <QCoreApplication>
#include <QMessageBox>
#include <QCloseEvent>
#include <QElapsedTimer>
#include <QToolBar>
#include "JZUiEditor.h"
#include "JZNodeParamEditor.h"
#include "JZNewProjectDialog.h"
#include "JZDesignerEditor.h"
#include "JZNodeUtils.h"
#include "JZNodeCppGenerater.h"
#include "3rd/jzupdate/JZUpdateClient.h"
#include "3rd/jzupdate/JZUpdateDialog.h"
#include "JZAboutDialog.h"
#include "JZProjectSettingDialog.h"
#include "JZNodeProgramDumper.h"
//Setting
Setting::Setting()
{
}
void Setting::addRecentProject(QString file)
{
recentFile.removeAll(file);
recentFile.insert(0, file);
if (recentFile.size() > 10)
recentFile.pop_back();
}
QDataStream &operator<<(QDataStream &s, const Setting &param)
{
s << param.recentFile;
return s;
}
QDataStream &operator >> (QDataStream &s, Setting &param)
{
s >> param.recentFile;
return s;
}
//AutoBuildInfo
MainWindow::BuildInfo::BuildInfo()
{
clear();
}
void MainWindow::BuildInfo::clear()
{
changeTimestamp = QDateTime::currentMSecsSinceEpoch();
buildTimestamp = 0;
saveTimestamp = 0;
buildVersion = 0;
save = false;
start = false;
success = false;
unitTestItemPath.clear();
}
void MainWindow::BuildInfo::clearTask()
{
save = false;
start = false;
unitTestItemPath.clear();
}
bool MainWindow::BuildInfo::isUnitTest()
{
if(!unitTestItemPath.isEmpty() && !start)
return true;
return false;
}
//ActionStatus
MainWindow::ActionStatus::ActionStatus(QAction *act, QVector<int> act_flags)
{
this->action = act;
this->flags = act_flags;
}
//MainWindow
MainWindow *g_mainWindow = nullptr;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
g_mainWindow = this;
m_editor = nullptr;
m_processMode = Process_none;
m_compilerTimer = new QTimer(this);
connect(m_compilerTimer, &QTimer::timeout, this, &MainWindow::onAutoCompilerTimer);
m_compilerTimer->start(100);
connect(LogManager::instance(), &LogManager::sigLog, this, &MainWindow::onLog);
connect(&m_debuger,&JZNodeDebugClient::sigLog,this,&MainWindow::onRuntimeLog);
connect(&m_debuger,&JZNodeDebugClient::sigRuntimeError,this,&MainWindow::onRuntimeError);
connect(&m_debuger,&JZNodeDebugClient::sigRuntimeStatus, this, &MainWindow::onRuntimeStatus);
connect(&m_debuger,&JZNodeDebugClient::sigNetError, this, &MainWindow::onNetError);
connect(&m_debuger,&JZNodeDebugClient::sigRuntimeWatch, this, &MainWindow::onRuntimeWatch);
connect(&m_process,(void (QProcess::*)(int,QProcess::ExitStatus))&QProcess::finished,this,&MainWindow::onRuntimeFinish);
connect(&m_project,&JZProject::sigItemChanged, this, &MainWindow::onProjectItemChanged);
connect(&m_project,&JZProject::sigDefineChanged, this, &MainWindow::onProjectChanged);
connect(&m_project,&JZProject::sigBreakPointChanged, this, &MainWindow::onBreakPointChanged);
connect(&m_runThread,&JZNodeAutoRunThread::sigResult,this, &MainWindow::onAutoRunResult);
connect(&m_buildThread,&JZNodeBuildThread::sigResult,this, &MainWindow::onBuildFinish);
m_buildThread.init(&m_program);
auto engine = m_runThread.engine();
connect(engine,&JZNodeEngine::sigWatchNotify,this,&MainWindow::onWatchNotify,Qt::BlockingQueuedConnection);
loadSetting();
initUi();
updateActionStatus();
//initLocalProcessTest();
}
MainWindow::~MainWindow()
{
for(auto edit : m_editors)
edit->disconnect();
saveSetting();
}
void MainWindow::loadSetting()
{
QString path = qApp->applicationDirPath() + "/setting.dat";
QFile file(path);
if (file.open(QFile::ReadOnly))
{
QDataStream s(&file);
s >> m_setting;
file.close();
}
}
void MainWindow::saveSetting()
{
QString path = qApp->applicationDirPath() + "/setting.dat";
QFile file(path);
if (file.open(QFile::WriteOnly | QFile::Truncate))
{
QDataStream s(&file);
s << m_setting;
file.close();
}
}
QIcon MainWindow::menuIcon(const QString &name)
{
return QIcon(":/JZNodeEditor/Resources/icons/" + name);
}
void MainWindow::initMenu()
{
using as = ActionStatus;
QMenuBar *menubar = new QMenuBar();
this->setMenuBar(menubar);
QMenu *menu_file = menubar->addMenu("文件");
auto actNewMenu = menu_file->addMenu("新建");
auto actOpenMenu = menu_file->addMenu("打开");
auto actNewProject = actNewMenu->addAction("项目");
auto actOpenProject = actOpenMenu->addAction("项目");
connect(actNewProject, &QAction::triggered, this, &MainWindow::onActionNewProject);
connect(actOpenProject, &QAction::triggered, this, &MainWindow::onActionOpenProject);
menu_file->addSeparator();
/*
QMenu *menu_NewFile = menu_file->addMenu("添加");
auto actNewEventFile = menu_NewFile->addAction("新建项目");
auto actNewClass = menu_NewFile->addAction("类");
auto actNewFunction = menu_NewFile->addAction("函数");
connect(actNewEventFile, &QAction::triggered, this, &MainWindow::onActionNewEvent);
connect(actNewClass, &QAction::triggered, this, &MainWindow::onActionNewClass);
connect(actNewFunction, &QAction::triggered, this, &MainWindow::onActionNewFunction);
menu_file->addSeparator();
*/
auto actCloseFile = menu_file->addAction("关闭");
auto actCloseProject = menu_file->addAction("关闭工程");
connect(actCloseFile, &QAction::triggered, this, &MainWindow::onActionCloseFile);
connect(actCloseProject,&QAction::triggered,this,&MainWindow::onActionCloseProject);
menu_file->addSeparator();
auto actSaveFile = menu_file->addAction(menuIcon("iconSave.png"), "保存文件");
auto actSaveAllFile = menu_file->addAction(menuIcon("iconSaveAll.png"), "全部保存");
auto actCloseAllFile = menu_file->addAction("全部关闭");
connect(actSaveFile,&QAction::triggered,this,&MainWindow::onActionSaveFile);
connect(actSaveAllFile, &QAction::triggered, this, &MainWindow::onActionSaveAllFile);
connect(actCloseAllFile, &QAction::triggered, this, &MainWindow::onActionCloseAllFile);
menu_file->addSeparator();
auto recent = menu_file->addMenu("最近使用过的项目");
for (int i = 0; i < m_setting.recentFile.size(); i++)
{
auto tmp = recent->addAction(m_setting.recentFile[i]);
connect(tmp, &QAction::triggered, this, &MainWindow::onActionRecentProject);
}
menu_file->addSeparator();
auto actExit = menu_file->addAction("退出");
connect(actExit, &QAction::triggered, this, &MainWindow::close);
m_actionStatus << ActionStatus(actCloseProject, { as::ProjectVaild })
<< ActionStatus(actSaveFile, { as::FileIsModify })
<< ActionStatus(actCloseFile, { as::FileOpen })
<< ActionStatus(actSaveAllFile, { as::HasModifyFile })
<< ActionStatus(actCloseAllFile, { as::FileOpen });
QMenu *menu_edit = menubar->addMenu("编辑");
auto actUndo = menu_edit->addAction(menuIcon("iconUndo.png"),"撤销");
auto actRedo = menu_edit->addAction(menuIcon("iconRedo.png"),"重做");
menu_edit->addSeparator();
auto actDel = menu_edit->addAction(menuIcon("iconDelete.png"),"删除");
auto actCut = menu_edit->addAction(menuIcon("iconCut.png"),"剪切");
auto actCopy = menu_edit->addAction(menuIcon("iconCopy.png"),"复制");
auto actPaste = menu_edit->addAction(menuIcon("iconPaste.png"),"粘贴");
menu_edit->addSeparator();
auto actSelectAll = menu_edit->addAction("全选");
actUndo->setShortcut(QKeySequence("Ctrl+Z"));
actRedo->setShortcut(QKeySequence("Ctrl+Y"));
actDel->setShortcut(QKeySequence("Ctrl+D"));
actCut->setShortcut(QKeySequence("Ctrl+X"));
actCopy->setShortcut(QKeySequence("Ctrl+C"));
actPaste->setShortcut(QKeySequence("Ctrl+V"));
actSelectAll->setShortcut(QKeySequence("Ctrl+A"));
actUndo->setShortcutContext(Qt::WidgetShortcut);
actRedo->setShortcutContext(Qt::WidgetShortcut);
actDel->setShortcutContext(Qt::WidgetShortcut);
actCut->setShortcutContext(Qt::WidgetShortcut);
actCopy->setShortcutContext(Qt::WidgetShortcut);
actPaste->setShortcutContext(Qt::WidgetShortcut);
actSelectAll->setShortcutContext(Qt::WidgetShortcut);
connect(actUndo,&QAction::triggered,this,&MainWindow::onActionUndo);
connect(actRedo,&QAction::triggered,this,&MainWindow::onActionRedo);
connect(actDel,&QAction::triggered,this,&MainWindow::onActionDel);
connect(actCut,&QAction::triggered,this,&MainWindow::onActionCut);
connect(actCopy,&QAction::triggered,this,&MainWindow::onActionCopy);
connect(actPaste,&QAction::triggered,this,&MainWindow::onActionPaste);
connect(actSelectAll,&QAction::triggered,this,&MainWindow::onActionSelectAll);
QMenu *menu_view = menubar->addMenu("视图");
menu_view->addAction("显示窗口");
menu_view->addAction("恢复默认");
QMenu *menu_project = menubar->addMenu("项目");
QAction *actProject = menu_project->addAction("属性");
connect(actProject, &QAction::triggered, this, &MainWindow::onActionProjectProp);
QMenu *menu_build = menubar->addMenu("构建");
auto actBuild = menu_build->addAction("编译");
auto actExport = menu_build->addAction("导出");
connect(actBuild,&QAction::triggered,this,&MainWindow::onActionBuild);
connect(actExport,&QAction::triggered,this,&MainWindow::onActionExport);
m_actionStatus << ActionStatus(actBuild, { as::ProjectVaild, as::ProcessIsEmpty });
QMenu *menu_tool = menubar->addMenu("工具");
menu_tool->addAction("性能分析");
QMenu *menu_debug = menubar->addMenu("调试");
auto actRun = menu_debug->addAction(menuIcon("iconRun.png"), "开始调试");
auto actDetach = menu_debug->addAction("脱离调试器");
auto actPause = menu_debug->addAction(menuIcon("iconPause.png"), "中断");
auto actResume = menu_debug->addAction(menuIcon("iconRun.png"), "继续");
auto actStop = menu_debug->addAction(menuIcon("iconStop.png"), "停止调试");
m_debugActions << menu_debug->addSeparator();
auto actStepOver = menu_debug->addAction(menuIcon("iconStepOver.png"), "单步");
auto actStepIn = menu_debug->addAction(menuIcon("iconStepIn.png"), "单步进入");
auto actStepOut = menu_debug->addAction(menuIcon("iconStepOver.png"), "单步跳出");
auto actBreakPoint = menu_debug->addAction(menuIcon("iconStepBreakpoint.png"), "断点");
actRun->setShortcut(QKeySequence("F5"));
actStepOver->setShortcut(QKeySequence("F10"));
actStepIn->setShortcut(QKeySequence("F11"));
actStepOut->setShortcut(QKeySequence("Shift+F11"));
actBreakPoint->setShortcut(QKeySequence("F9"));
m_debugActions << actDetach << actPause << actResume << actStop << actStepOver
<< actStepIn << actStepOut;
m_actionRun = actRun;
m_actionResume = actResume;
connect(actRun,&QAction::triggered,this,&MainWindow::onActionRun);
connect(actDetach,&QAction::triggered,this,&MainWindow::onActionDetach);
connect(actPause,&QAction::triggered,this,&MainWindow::onActionPause);
connect(actResume,&QAction::triggered,this,&MainWindow::onActionResume);
connect(actStop,&QAction::triggered,this,&MainWindow::onActionStop);
connect(actStepOver,&QAction::triggered,this,&MainWindow::onActionStepOver);
connect(actStepIn,&QAction::triggered,this,&MainWindow::onActionStepIn);
connect(actStepOut,&QAction::triggered,this,&MainWindow::onActionStepOut);
connect(actBreakPoint,&QAction::triggered,this,&MainWindow::onActionBreakPoint);
m_actionStatus << ActionStatus(actRun, { as::ProjectVaild, as::ProcessIsEmpty })
<< ActionStatus(actDetach, { as::ProcessIsVaild })
<< ActionStatus(actPause, { as::ProcessCanPause })
<< ActionStatus(actResume, { as::ProcessCanResume })
<< ActionStatus(actStop, { as::ProcessIsVaild })
<< ActionStatus(actStepOver, { as::ProcessCanResume })
<< ActionStatus(actStepIn, { as::ProcessCanResume })
<< ActionStatus(actStepOut, { as::ProcessCanResume })
<< ActionStatus(actBreakPoint, { as::FileIsScript });
QMenu *menu_help = menubar->addMenu("帮助");
auto actHelp = menu_help->addAction("帮助");
menu_help->addSeparator();
auto actCheckUpdate = menu_help->addAction("检查更新");
auto actAbout = menu_help->addAction("关于" + windowTitle());
connect(actHelp, &QAction::triggered, this, &MainWindow::onActionHelp);
connect(actCheckUpdate, &QAction::triggered, this, &MainWindow::onActionCheckUpdate);
connect(actAbout, &QAction::triggered, this, &MainWindow::onActionAbout);
m_menuList << menu_file << menu_edit << menu_view << menu_build << menu_debug << menu_help;
//tool bar
QToolBar *main = new QToolBar();
main->addAction(actSaveFile);
main->addAction(actSaveAllFile);
QToolBar *tool_debug = new QToolBar();
tool_debug->addAction(actResume);
tool_debug->addAction(actPause);
tool_debug->addAction(actStop);
addToolBar(main);
addToolBar(tool_debug);
m_toolDebug = tool_debug;
}
void MainWindow::initUi()
{
initMenu();
m_log = new LogWidget();
connect(m_log, &LogWidget::sigNavigate, this, &MainWindow::onNavigate);
m_stack = m_log->stack();
connect(m_stack, &JZNodeStack::sigStackChanged, this, &MainWindow::onStackChanged);
m_watchAuto = m_log->watchAuto();
m_watchManual = m_log->watchManual();
m_watchAuto->setReadOnly(true);
m_debugWidgets << m_watchAuto << m_watchManual;
for (auto w : m_debugWidgets)
w->setMainWindow(this);
connect(m_watchManual, &JZNodeWatch::sigParamNameChanged, this, &MainWindow::onWatchNameChanged);
connect(m_watchManual, &JZNodeWatch::sigParamValueChanged, this, &MainWindow::onWatchValueChanged);
connect(m_watchAuto, &JZNodeWatch::sigParamValueChanged, this, &MainWindow::onWatchValueChanged);
m_breakPoint = m_log->breakpoint();
m_breakPoint->setProject(&m_project);
connect(m_breakPoint, &JZNodeBreakPoint::sigBreakPointClicked, this, &MainWindow::onBreakPointClicked);
m_projectTree = new JZProjectTree();
connect(m_projectTree,&JZProjectTree::sigActionTrigged,this,&MainWindow::onProjectTreeAction);
QWidget *widget = new QWidget();
QVBoxLayout *center = new QVBoxLayout();
center->setContentsMargins(9,9,9,9);
widget->setLayout(center);
QWidget *widget_left = new QWidget();
QVBoxLayout *l_left = new QVBoxLayout();
l_left->setContentsMargins(0,0,0,0);
widget_left->setLayout(l_left);
//main
QSplitter *splitterMain = new QSplitter(Qt::Horizontal);
splitterMain->setObjectName("splitterMain");
splitterMain->addWidget(m_projectTree);
splitterMain->addWidget(widget_left);
center->addWidget(splitterMain);
//left
JZNodeEditor *node_editor = new JZNodeEditor();
m_editorStack = new QTabWidget();
m_editorStack->setTabsClosable(true);
connect(m_editorStack, &QTabWidget::tabCloseRequested, this, &MainWindow::onEditorClose);
connect(m_editorStack, &QTabWidget::currentChanged, this, &MainWindow::onEditorActivite);
m_editorStack->tabBar()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_editorStack->tabBar(), &QWidget::customContextMenuRequested, this, &MainWindow::onTabContextMenu);
QSplitter *splitterLeft = new QSplitter(Qt::Vertical);
splitterLeft->addWidget(m_editorStack);
splitterLeft->addWidget(m_log);
l_left->addWidget(splitterLeft);
splitterMain->setCollapsible(0,false);
splitterMain->setCollapsible(1,false);
splitterMain->setStretchFactor(0,0);
splitterMain->setStretchFactor(1,1);
splitterMain->setSizes({250,600});
splitterLeft->setCollapsible(0,false);
splitterLeft->setCollapsible(1,false);
splitterLeft->setStretchFactor(0,1);
splitterLeft->setStretchFactor(1,0);
setCentralWidget(widget);
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
QMainWindow::resizeEvent(event);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (m_processMode != Process_none)
{
int ret = QMessageBox::question(this, "", "是否停止调试", QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::No)
{
event->ignore();
return;
}
onActionStop();
}
if (!closeProject())
{
event->ignore();
return;
}
m_runThread.stopRun();
m_buildThread.stopBuild();
JZDesigner::instance()->closeEditor();
QMainWindow::closeEvent(event);
}
const CompilerResult *MainWindow::compilerResult(const QString &path)
{
auto s = (JZScriptItem*)m_project.getItem(path);
return m_buildThread.builder()->compilerInfo(s);
}
JZNodeProgram *MainWindow::program()
{
return &m_program;
}
JZProject *MainWindow::project()
{
return &m_project;
}
JZNodeRuntimeInfo *MainWindow::runtime()
{
return &m_runtime;
}
int MainWindow::stackIndex()
{
return m_stack->stackIndex();
}
void MainWindow::updateActionStatus()
{
using as = ActionStatus;
bool isProject = !m_project.isNull();
bool isEditor = (m_editor != nullptr);
bool isEditorModify = (m_editor && m_editor->isModified());
bool isEditorScript = (m_editor && m_editor->type() == Editor_script);
bool hasModifyFile = false;
bool isProcess = m_processMode != Process_none;
bool canPause = (m_processMode == Process_running);
bool canResume = (m_processMode == Process_pause);
for (auto v : m_editors)
{
if (v->isModified())
{
hasModifyFile = true;
break;
}
}
QMap<int,bool> cond;
cond[as::ProjectVaild] = isProject;
cond[as::FileOpen] = isEditor;
cond[as::FileIsModify] = isEditorModify;
cond[as::FileIsScript] = isEditorScript;
cond[as::HasModifyFile] = hasModifyFile;
cond[as::ProcessIsEmpty] = !isProcess;
cond[as::ProcessIsVaild] = isProcess;
cond[as::ProcessCanPause] = canPause;
cond[as::ProcessCanResume] = canResume;
cond[as::ProcessCanStartResume] = canResume || (isProject && !isProcess);
Q_ASSERT(cond.size() == ActionStatus::Count);
for (int i = 0; i < m_actionStatus.size(); i++)
{
auto act = m_actionStatus[i].action;
auto &flags = m_actionStatus[i].flags;
int enabled_count = 0;
for (int flg_idx = 0; flg_idx < flags.size(); flg_idx++)
{
if (cond[flags[flg_idx]])
enabled_count++;
}
bool enabled = (enabled_count == flags.size());
act->setEnabled(enabled);
}
for (auto act : m_debugActions)
act->setVisible(isProcess);
if (canResume)
{
m_actionRun->setShortcut(QKeySequence());
m_actionResume->setShortcut(QKeySequence("F5"));
}
else
{
m_actionResume->setShortcut(QKeySequence());
m_actionRun->setShortcut(QKeySequence("F5"));
}
}
void MainWindow::onActionNewProject()
{
if (!closeProject())
return;
JZNewProjectDialog dialog(this);
if (dialog.exec() != QDialog::Accepted)
return;
QString name = dialog.name();
QString project_dir = dialog.dir() + "/" + name;
if (!QDir().exists(project_dir))
QDir().mkpath(project_dir);
QString project_tmp;
if (dialog.projectType() == 0)
project_tmp = "ui";
else
project_tmp = "console";
JZProject project;
if (!project.newProject(project_dir, name, project_tmp))
return;
openProject(project.filePath());
}
void MainWindow::onActionOpenProject()
{
QString filepath = QFileDialog::getOpenFileName(this,"","","*.jzproj");
if(filepath.isEmpty())
return;
if (!closeProject())
return;
openProject(filepath);
}
void MainWindow::onActionCloseProject()
{
closeProject();
}
void MainWindow::onActionRecentProject()
{
QAction *act = qobject_cast<QAction*>(sender());
QString filepath = act->text();
if (!closeProject())
return;
if (!openProject(filepath))
{
m_setting.recentFile.removeAll(filepath);
QMenu *menu = qobject_cast<QMenu *>(act->parent());
menu->removeAction(act);
delete act;
}
}
void MainWindow::onActionNewEvent()
{
}
void MainWindow::onActionNewFunction()
{
}
void MainWindow::onActionNewClass()
{
}
void MainWindow::onActionSaveFile()
{
if(!m_editor)
return;
m_editor->save();
updateActionStatus();
}
void MainWindow::onActionCloseFile()
{
if(!m_editor)
return;
closeEditor(m_editor);
updateActionStatus();
}
void MainWindow::onActionSaveAllFile()
{
saveAll();
updateActionStatus();
}
void MainWindow::onActionCloseAllFile()
{
closeAllEditor();
}
void MainWindow::onActionCloseAllFileExcept()
{
closeAllEditor(m_editor);
}
void MainWindow::onActionUndo()
{
if(m_editor)
m_editor->undo();
}
void MainWindow::onActionRedo()
{
if(m_editor)
m_editor->redo();
}
void MainWindow::onActionDel()
{
if(m_editor)
m_editor->remove();
}
void MainWindow::onActionCut()
{
if(m_editor)
m_editor->cut();
}
void MainWindow::onActionCopy()
{
if(m_editor)
m_editor->copy();
}
void MainWindow::onActionPaste()
{
if(m_editor)
m_editor->paste();
}
void MainWindow::onActionSelectAll()
{
if(m_editor)
m_editor->selectAll();
}
void MainWindow::onActionProjectProp()
{
JZProjectSettingDialog dlg(this);
dlg.setProject(&m_project);
dlg.exec();
}
void MainWindow::onActionBuild()
{
if (m_processMode != Process_none)
{
if (QMessageBox::question(this, "", "是否停止调试", QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return;
onActionStop();
}
saveAll();
m_buildInfo.save = true;
build();
}
void MainWindow::onActionExport()
{
//JZNodeCppGenerater gen;
QString output = m_project.path() + "/build/cpp";
//gen.generate(&m_project,output);
m_log->addLog(Log_Compiler, "export to: " + output);
}
void MainWindow::onActionRun()
{
saveAll();
m_buildInfo.save = true;
m_buildInfo.start = true;
build();
}
void MainWindow::onActionDetach()
{
m_debuger.detach();
updateActionStatus();
m_processMode = Process_none;
}
void MainWindow::onActionPause()
{
m_debuger.pause();
updateActionStatus();
}
void MainWindow::onActionResume()
{
m_debuger.resume();
updateActionStatus();
}
void MainWindow::onActionStop()
{
stopProgram();
}
void MainWindow::onActionBreakPoint()
{
if(m_editor && m_editor->type() == Editor_script)
{
JZNodeEditor *node_editor = (JZNodeEditor*)m_editor;
node_editor->breakPointTrigger();
m_breakPoint->updateBreakPoint();
}
}
void MainWindow::onActionStepOver()
{
m_debuger.stepOver();
updateActionStatus();
}
void MainWindow::onActionStepIn()
{
m_debuger.stepIn();
updateActionStatus();
}
void MainWindow::onActionStepOut()
{
m_debuger.stepOut();
updateActionStatus();
}
void MainWindow::onActionHelp()
{
onActionAbout();
}
void MainWindow::onActionCheckUpdate()
{
JZUpdateClient client(qApp->applicationDirPath());
if (!client.init("120.77.183.99", 8888))
{
QMessageBox::information(this, "", "连接服务器失败");
return;
}
bool update = false;
if (!client.checkUpdate(update))
{
QMessageBox::information(this, "", "获取更新信息失败");
return;
}
if (update)
{
QMessageBox::information(this, "", "当前已经是最新版本");
return;
}
else
{
if (QMessageBox::question(this, "", "发现新版本,是否更新", QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return;
if (!closeProject())
return;
JZUpdateDialog dlg(this);
dlg.setClient(&client);
if (dlg.exec() != QDialog::Accepted)
return;
QString exe_path = qApp->applicationFilePath();
QProcess::startDetached(exe_path);
close();
}
}
void MainWindow::onActionAbout()
{
JZAboutDialog dlg(this);
dlg.exec();
}
void MainWindow::onModifyChanged(bool flag)
{
auto editor = qobject_cast<JZEditor*>(sender());
int index = m_editorStack->indexOf(editor);
if (index == -1)
return;
updateTabText(index);
updateActionStatus();
}
void MainWindow::onRedoAvailable(bool flag)
{
m_menuList[1]->actions()[1]->setEnabled(flag);
}
void MainWindow::onUndoAvailable(bool flag)
{
m_menuList[1]->actions()[0]->setEnabled(flag);
}
bool MainWindow::closeProject()
{
if (!closeAllEditor())
return false;
m_projectTree->clear();
m_breakPoint->clear();
m_project.close();
updateActionStatus();
setWindowTitle("JZNodeEditor");
return true;
}
bool MainWindow::openProject(QString filepath)
{
if (!m_project.open(filepath))
{
QMessageBox::information(this, "", "打开工程失败: " + m_project.error());
return false;
}
m_buildInfo.clear();
m_projectTree->setProject(&m_project);
m_setting.addRecentProject(m_project.filePath());
m_breakPoint->updateBreakPoint();
updateActionStatus();
setWindowTitle(m_project.name());
return true;
}
JZEditor *MainWindow::createEditor(int type)
{
JZEditor *editor = nullptr;
if(type == ProjectItem_scriptParamBinding || type == ProjectItem_scriptFunction)
editor = new JZNodeEditor();
else if(type == ProjectItem_param)
editor = new JZNodeParamEditor();
else if(type == ProjectItem_ui)
editor = new JZUiEditor();
if(editor)
editor->setProject(&m_project);
return editor;
}
void MainWindow::gotoNode(QString file, int nodeId)
{
if (openEditor(file))
{
JZNodeEditor *editor = qobject_cast<JZNodeEditor*>(m_editor);
editor->ensureNodeVisible(nodeId);
}
}
void MainWindow::onFunctionOpen(QString functionName)
{
auto file = m_project.functionItem(functionName);
openEditor(file->itemPath());
}
void MainWindow::onAutoCompiler()
{
m_buildInfo.changeTimestamp = QDateTime::currentMSecsSinceEpoch();
}
void MainWindow::onAutoRun()
{
auto edit = qobject_cast<JZNodeEditor*>(sender());
if(m_editor != edit)
return;
startUnitTest(edit->script()->itemPath());
}
void MainWindow::showTopLevel()
{
if(isActiveWindow())
return;
Qt::WindowFlags flags = windowFlags();
this->setWindowFlags((flags | Qt::WindowStaysOnTopHint));
this->show();
this->setWindowFlags(flags);
this->show();
raise();
activateWindow();
}
void MainWindow::onAutoCompilerTimer()
{
qint64 cur = QDateTime::currentMSecsSinceEpoch();
if (cur - m_buildInfo.changeTimestamp <= 1000)
return;
if (m_project.isNull())
return;
if(m_buildInfo.changeTimestamp > m_buildInfo.buildVersion)
build();
}
void MainWindow::onBuildFinish(int flag)
{
QString result = flag ? "successed" : "failed";
m_buildThread.wait();
auto builder = m_buildThread.builder();
if (flag != Build_Cached)
{
auto it = m_editors.begin();
while (it != m_editors.end())
{
if (it.value()->type() == Editor_script)
{
auto node_edit = (JZNodeEditor*)it.value();
auto cmp_info = builder->compilerInfo(node_edit->script());
if (cmp_info)
node_edit->setCompilerResult(cmp_info);
}
it++;
}
}
if (flag == Build_Failed)
{
m_buildInfo.success = false;
m_log->addLog(Log_Compiler, "build failed.");
}
else
{
if (flag == Build_Successed)
{
m_buildInfo.buildTimestamp = QDateTime::currentMSecsSinceEpoch();
m_log->addLog(Log_Compiler, "build finish.");
}
m_buildInfo.success = true;
}
if(m_buildInfo.success)
{
if(m_buildInfo.isUnitTest())
{
auto e = nodeEditor(m_buildInfo.unitTestItemPath);
if (e)
{
m_runThread.startRun(&m_program, e->scriptTestDepend());
}
}
else
{
if (m_buildInfo.save)
{
if (m_buildInfo.saveTimestamp < m_buildInfo.buildTimestamp)
{
if (!saveProgram())
return;
m_buildInfo.saveTimestamp = QDateTime::currentMSecsSinceEpoch();
}
}
if (m_buildInfo.start)
startProgram();
}
}
m_buildInfo.clearTask();
}
void MainWindow::onAutoRunResult(UnitTestResultPtr result)
{
if(result->result == UnitTestResult::Cancel)
return;
auto script_item = m_project.functionItem(result->function);
if(!script_item)
return;
JZEditor *e = editor(script_item->itemPath());
if(!e)
return;
JZNodeEditor *node_e = qobject_cast<JZNodeEditor*>(e);
node_e->setAutoRunResult(*result);
}
JZEditor *MainWindow::editor(QString filepath)
{
auto it = m_editors.begin();
while (it != m_editors.end())
{
if (it.key()->itemPath() == filepath)
return it.value();
it++;
}
return nullptr;
}
QList<JZNodeEditor*> MainWindow::nodeEditorList()
{
QList<JZNodeEditor*> list;
//editor
auto it = m_editors.begin();
while (it != m_editors.end())
{
auto editor = it.value();
if (it.value()->type() == Editor_script)
{
auto node_edit = (JZNodeEditor*)it.value();
list << node_edit;
}
it++;
}
return list;
}
JZNodeEditor *MainWindow::nodeEditor(QString filepath)
{
JZEditor *e = editor(filepath);
if(!e)
return nullptr;
return qobject_cast<JZNodeEditor*>(e);
}
void MainWindow::switchEditor(JZEditor *editor)
{
if(m_editor)
m_editor->removeMenuBar(this->menuBar());
m_editor = editor;
if(editor != nullptr)
{
m_editorStack->setCurrentWidget(m_editor);
m_editor->addMenuBar(this->menuBar());
m_editor->active();
m_editor->setFocus();
}
else
m_editorStack->setCurrentIndex(0);
updateActionStatus();
}
bool MainWindow::openEditor(QString filepath)
{
if (filepath == "__idle__")
return false;
JZProjectItem *item = m_project.getItem(filepath);
if (!item)
return false;
QString file = item->itemPath();
auto new_edit = editor(file);
if (!new_edit) {
new_edit = createEditor(item->itemType());
if (!new_edit)
return false;
connect(new_edit, &JZEditor::redoAvailable, this, &MainWindow::onRedoAvailable);
connect(new_edit, &JZEditor::undoAvailable, this, &MainWindow::onUndoAvailable);
connect(new_edit, &JZEditor::modifyChanged, this, &MainWindow::onModifyChanged);
new_edit->setItem(item);
new_edit->open(item);
if (new_edit->type() == Editor_script)
{
auto node_edit = (JZNodeEditor*)new_edit;
connect(node_edit, &JZNodeEditor::sigFunctionOpen, this, &MainWindow::onFunctionOpen);
connect(node_edit, &JZNodeEditor::sigAutoCompiler, this, &MainWindow::onAutoCompiler);
connect(node_edit, &JZNodeEditor::sigAutoRun, this, &MainWindow::onAutoRun);
connect(node_edit, &JZNodeEditor::sigRuntimeValueChanged, this, &MainWindow::onEditorValueChanged);
node_edit->setRunningMode(m_processMode);
auto cmp_ret = compilerResult(file);
if(cmp_ret)
node_edit->setCompilerResult(cmp_ret);
}
m_editors[item] = new_edit;
m_editorStack->addTab(new_edit, filepath);
}
switchEditor(new_edit);
return true;
}
void MainWindow::resetEditor(JZEditor *editor)
{
if (editor->type() == Editor_script)
{
auto node_edit = (JZNodeEditor*)editor;
node_edit->resetFile();
}
}
void MainWindow::closeEditor(JZEditor *editor)
{
auto item = editor->item();
if (editor->isModified())
{
int ret = QMessageBox::question(this, "", "是否保存", QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (ret == QMessageBox::Yes)
{
editor->save();
}
else if (ret == QMessageBox::No)
{
resetEditor(editor);
}
else if (ret == QMessageBox::Cancel)
{
return;
}
}
editor->close();
editor->setItem(nullptr);
m_editors.remove(item);
if(m_editor == editor)
{
if(m_editors.size() > 0)
switchEditor(m_editors.first());
else
switchEditor(nullptr);
}
int index = m_editorStack->indexOf(editor);
m_editorStack->removeTab(index);
delete editor;
}
void MainWindow::openItem(QString filepath)
{
openEditor(filepath);
}
void MainWindow::closeItem(QString filepath)
{
auto edit = editor(filepath);
if(!edit)
return;
closeEditor(edit);
}
void MainWindow::removeItem(QString itempath)
{
auto item = m_project.getItem(itempath);
auto file_item = m_project.getItemFile(item);
closeItem(itempath);
m_project.removeItem(itempath);
}
void MainWindow::onProjectTreeAction(int type, QString filepah)
{
if (type == Action_open)
openItem(filepah);
else if (type == Action_close)
closeItem(filepah);
else if (type == Action_remove)
removeItem(filepah);
}
void MainWindow::onEditorClose(int index)
{
JZEditor *editor = qobject_cast<JZEditor*>(m_editorStack->widget(index));
closeEditor(editor);
}
void MainWindow::onEditorActivite(int index)
{
if (index == -1)
return;
JZEditor *editor = qobject_cast<JZEditor*>(m_editorStack->widget(index));
editor->active();
switchEditor(editor);
}
void MainWindow::onNavigate(QUrl url)
{
if(openEditor(url.path()))
{
m_editor->navigate(url);
}
}
void MainWindow::onProjectChanged()
{
m_buildInfo.changeTimestamp = QDateTime::currentMSecsSinceEpoch();
//editor
auto list = nodeEditorList();
for(auto node_edit : list)
node_edit->updateDefine();
}
void MainWindow::onProjectItemChanged(JZProjectItem *item)
{
//editor
if (m_editors.contains(item))
{
int index = m_editorStack->indexOf(m_editors[item]);
if (m_editorStack->tabText(index) != item->itemPath())
updateTabText(index);
}
onProjectChanged();
}
void MainWindow::onStackChanged(int stack_index)
{
updateRuntime(stack_index, false);
}
void MainWindow::onEditorValueChanged(int id,QString value)
{
onWatchValueChanged(irId(id),value);
}
void MainWindow::onWatchValueChanged(JZNodeIRParam coor, QString value)
{
JZNodeSetDebugParam param_info;
param_info.stack = m_stack->stackIndex();
param_info.coor = coor;
param_info.value = value;
JZNodeSetDebugParamResp result;
if(!m_debuger.setVariable(param_info,result))
return;
JZNodeGetDebugParamResp get_resp;
get_resp.stack = result.stack;
get_resp.coors << result.coor;
get_resp.values << result.value;
for(auto w : m_debugWidgets)
w->updateParamInfo(&get_resp);
if (coor.isStack())
{
auto stack_info = m_runtime.stacks[param_info.stack];
auto gemo = JZNodeCompiler::paramGemo(coor.id());
setRuntimeValue(stack_info.file,gemo.nodeId,gemo.pinId,result.value);
}
}
void MainWindow::onWatchNameChanged(JZNodeIRParam coor)
{
JZNodeGetDebugParam param_info;
param_info.stack = m_stack->stackIndex();
param_info.coors << coor;
JZNodeGetDebugParamResp ret;
if(!m_debuger.getVariable(param_info,ret))
return;
m_watchManual->updateParamInfo(&ret);
}
void MainWindow::onWatchNotify()
{
auto env = editorEnvironment();
auto inst = env->editorManager();
if(m_runThread.engine()->stack()->size() != 1)
return;
QString file = m_runThread.engine()->stack()->currentEnv()->script->file;
auto e = nodeEditor(file);
if(!e || e != m_editor)
return;
auto &watchMap = m_runThread.engine()->stack()->currentEnv()->watchMap;
auto it = watchMap.begin();
while(it != watchMap.end())
{
JZNodeGemo gemo = JZNodeCompiler::paramGemo(it.key());
JZNodeDebugParamValue value;
value.type = m_programEnv.variantType(it.value());
value.value = JZNodeType::debugString(it.value());
auto d = inst->delegate(value.type);
if (d && d->pack)
value.binValue = d->pack(env, it.value());
e->setRuntimeValue(gemo.nodeId,gemo.pinId,value);
it++;
}
}
void MainWindow::onRuntimeWatch(const JZNodeRuntimeWatch &info)
{
QString file = info.runtimInfo.stacks.back().file;
auto edit = nodeEditor(file);
if (!edit)
return;
auto it = info.values.begin();
while (it != info.values.end())
{
auto gemo = JZNodeCompiler::paramGemo(it.key());
setRuntimeValue(file,gemo.nodeId,gemo.pinId,it.value());
it++;
}
}
void MainWindow::updateAutoWatch(int stack_index)
{
if (m_program.isNull())
return;
auto &stack = m_runtime.stacks[stack_index];
JZNodeGetDebugParam param_info;
param_info.stack = stack_index;
auto func = m_programEnv.functionManager()->function(stack.function);
if(!func || func->isCFunction)
{
m_watchAuto->clear();
return;
}
auto func_debug = m_program.script(stack.file)->functionDebug(stack.function);
if (func->isMemberFunction())
{
param_info.coors << irThis();
}
//local
for (int i = 0; i < func_debug->localVariables.size(); i++)
{
auto &local = func_debug->localVariables[i];
param_info.coors << irRef(local.name);
}
int node_prop_index = param_info.coors.size();
const auto &node_info = func_debug->nodeInfo[stack.nodeId];
for (int i = 0; i < node_info.paramIn.size(); i++)
{
int param_id = JZNodeCompiler::paramId(node_info.id,node_info.paramIn[i].id);
param_info.coors << irId(param_id);
}
for (int i = 0; i < node_info.paramOut.size(); i++)
{
int param_id = JZNodeCompiler::paramId(node_info.id,node_info.paramOut[i].id);
param_info.coors << irId(param_id);
}
JZNodeGetDebugParamResp param_info_resp;
if(!m_debuger.getVariable(param_info,param_info_resp))
return;
m_watchAuto->setParamInfo(&param_info_resp);
auto edit = nodeEditor(stack.file);
if (edit)
{
for (int i = node_prop_index; i < param_info_resp.coors.size(); i++)
{
auto &coor = param_info_resp.coors[i];
if(coor.isStack())
{
auto gemo = JZNodeCompiler::paramGemo(coor.id());
edit->setRuntimeValue(gemo.nodeId,gemo.pinId,param_info_resp.values[i]);
}
}
}
}
void MainWindow::setRuntimeValue(QString file,int node_id,int pin_id,const JZNodeDebugParamValue &value)
{
auto editor = nodeEditor(file);
if(!editor)
return;
editor->setRuntimeValue(node_id,pin_id,value);
}
void MainWindow::updateRuntime(int stack_index,bool isNew)
{
if (stack_index == -1)
{
clearWatchs();
return;
}
auto stack = m_runtime.stacks[stack_index];
if (stack.file == "__idle__")
{
clearWatchs();
return;
}
//this
for (int i = stack_index; i >= 0; i--)
{
auto &top = m_runtime.stacks[i];
if (!top.file.isEmpty())
{
setRuntimeNode(top.file, top.nodeId);
break;
}
}
if (stack.file.isEmpty()) //in c function
return;
//watch auto
updateAutoWatch(stack_index);
//watch manual
JZNodeGetDebugParam param_info_watch;
param_info_watch.stack = stack_index;
QStringList watch_list = m_watchManual->watchList();
for (int i = 0; i < watch_list.size(); i++)
{
param_info_watch.coors << irRef(watch_list[i]);
}
JZNodeGetDebugParamResp param_info_watch_resp;
if(!m_debuger.getVariable(param_info_watch,param_info_watch_resp))
return;
m_watchManual->setParamInfo(&param_info_watch_resp);
}
void MainWindow::build()
{
Q_ASSERT(m_processMode == Process_none);
QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
if (m_buildThread.isRunning() && m_buildInfo.changeTimestamp == m_buildInfo.buildVersion)
return;
m_runThread.stopRun();
if (m_buildInfo.changeTimestamp > m_buildInfo.buildTimestamp)
{
m_buildInfo.buildVersion = m_buildInfo.changeTimestamp;
m_log->clearLog(Log_Compiler);
m_log->addLog(Log_Compiler, "[" + time + "] ===== start build =====");
qDebug() << "start build";
m_buildInfo.success = false;
m_buildThread.startBuild(&m_project);
}
else
{
//wait finish
onBuildFinish(Build_Cached);
}
}
void MainWindow::saveToFile(QString filepath,QString text)
{
QFile file(filepath);
if(file.open(QFile::WriteOnly | QFile::Truncate))
{
QTextStream s(&file);
s.setCodec("utf-8");
s << text;
file.close();
}
}
bool MainWindow::saveProgram()
{
qDebug() << "save program";
QString build_path = m_project.path() + "/build";
QString build_exe = build_path + "/" + m_project.name() + ".program";
QElapsedTimer timer;
timer.start();
QDir dir;
if (!dir.exists(build_path))
dir.mkdir(build_path);
if (!m_program.save(build_exe))
{
m_log->addLog(Log_Compiler, "generate program failed");
return false;
}
JZNodeProgramDumper dumper;
saveToFile(build_path + "/" + m_project.name() + ".jsm", dumper.dump(&m_program));
return true;
}
void MainWindow::startUnitTest(QString unitTestItemPath)
{
if (m_processMode != Process_none)
return;
m_buildInfo.unitTestItemPath = unitTestItemPath;
build();
}
void MainWindow::startProgram()
{
qDebug() << "startProgram";
m_runThread.stopRun();
m_log->clearLog(Log_Runtime);
QString app = qApp->applicationFilePath();
QString build_exe = m_project.path() + "/build/" + m_project.name() + ".program";
QStringList params;
params << "--run" << build_exe << "--debug";
m_log->addLog(Log_Runtime, "start program");
m_process.setWorkingDirectory(m_project.path());
m_process.start(app, params);
if (!m_process.waitForStarted())
{
QMessageBox::information(this, "", "start failed");
return;
}
QThread::msleep(100);
if(!m_debuger.connectToServer("127.0.0.1",19888))
{
QMessageBox::information(this,"","can't connect to process");
return;
}
m_log->addLog(Log_Runtime, "conenct to server");
JZNodeDebugInfo info;
info.breakPoints = m_project.breakPoints();
JZNodeProgramInfo program_info;
if(!m_debuger.init(info,program_info))
{
m_log->addLog(Log_Runtime, "connec to process failed.");
stopProgram();
return;
}
if(!m_program.load(program_info.appPath))
{
m_programEnv.registType(m_program.typeMeta());
m_log->addLog(Log_Runtime, "load debug info failed.");
}
setRunningMode(Process_running);
qDebug() << "startProgram finish";
}
void MainWindow::stopProgram()
{
if (m_processMode == Process_none)
return;
m_process.setProperty("userKill", 1);
m_process.kill();
m_process.waitForFinished();
updateActionStatus();
}
void MainWindow::onTabContextMenu(QPoint pos)
{
QMenu menu(this);
QAction *actSave = menu.addAction("保存");
QAction *actClose = menu.addAction("关闭");
QAction *actAll = menu.addAction("关闭所有文档");
QAction *actAllExcept = menu.addAction("除此之外全部关闭");
auto bar = qobject_cast<QTabBar*>(sender());
QAction *ret = menu.exec(bar->mapToGlobal(pos));
if (!ret)
return;
if (ret == actSave)
{
onActionSaveFile();
}
else if (ret == actClose)
{
onActionCloseFile();
}
else if (ret == actAll)
{
onActionCloseAllFile();
}
else if (ret == actAllExcept)
{
int index = bar->tabAt(pos);
auto editor = qobject_cast<JZEditor*>(m_editorStack->widget(index));
closeAllEditor(editor);
}
}
void MainWindow::onLog(LogObjectPtr log)
{
m_log->addLog(log->module, log->message);
}
void MainWindow::onRuntimeStatus(int status)
{
ProcessStatus process_status;
if (status == Status_idlePause || status == Status_pause)
process_status = Process_pause;
else if(status == Status_error)
process_status = Process_error;
else
process_status = Process_running;
setRunningMode(process_status);
}
void MainWindow::onRuntimeLog(QString log)
{
m_log->addLog(Log_Runtime, log);
}
void MainWindow::onRuntimeError(JZNodeRuntimeError error)
{
QString error_msg = "Runtime Error: " + error.error + "\n\n";
int stack_size = error.info.stacks.size();
for (int i = 0; i < stack_size; i++)
{
auto s = error.info.stacks[stack_size - i - 1];
QString line = JZNodeUtils::makeLink(s.file, s.function, "id=" + QString::number(s.nodeId));
m_log->addLog(Log_Runtime, line);
line = s.function;
if (!s.file.isEmpty())
line += +"(" + s.file + "," + QString::number(s.nodeId) + ")";
error_msg += line + "\n";
}
m_log->addLog(Log_Runtime, error_msg);
showTopLevel();
QMessageBox::information(this, "", error_msg);
}
void MainWindow::onNetError()
{
m_log->addLog(Log_Runtime, "调试连接中断");
onActionStop();
}
void MainWindow::onRuntimeFinish(int code,QProcess::ExitStatus status)
{
if (status == QProcess::CrashExit)
{
if (m_process.property("userKill").isValid())
m_process.setProperty("userKill", QVariant());
else
m_log->addLog(Log_Runtime, "process crash ");
}
else
m_log->addLog(Log_Runtime, "process finish, exit code " + QString::number(code));
setRunningMode(Process_none);
updateActionStatus();
}
void MainWindow::saveAll()
{
m_project.saveTransaction();
auto it = m_editors.begin();
while (it != m_editors.end())
{
auto editor = it.value();
if (editor->isModified())
editor->save();
it++;
}
m_project.saveCommit();
}
bool MainWindow::closeAllEditor(JZEditor *except)
{
QList<JZEditor*> close_list;
m_project.saveTransaction();
bool saveToAll = false, noToAll = false;
auto it = m_editors.begin();
while (it != m_editors.end())
{
auto editor = it.value();
if (except && except == editor)
{
it++;
continue;
}
if (editor->isModified())
{
if (!saveToAll && !noToAll)
{
int ret = QMessageBox::question(this, "", "是否保存", QMessageBox::Yes | QMessageBox::No
| QMessageBox::YesToAll | QMessageBox::NoToAll | QMessageBox::Cancel);
if (ret == QMessageBox::Yes || ret == QMessageBox::YesToAll)
{
editor->save();
if (ret == QMessageBox::YesToAll)
saveToAll = true;
}
else if (ret == QMessageBox::No || ret == QMessageBox::NoToAll)
{
resetEditor(editor);
if(ret == QMessageBox::NoToAll)
noToAll = true;
}
else if (ret == QMessageBox::Cancel)
{
m_project.saveCommit();
return false;
}
}
else if (saveToAll)
{
editor->save();
}
else if (noToAll)
{
resetEditor(editor);
}
}
editor->close();
close_list << editor;
it++;
}
m_project.saveCommit();
for (auto editor : close_list)
{
int index = m_editorStack->indexOf(editor);
m_editorStack->removeTab(index);
m_editors.remove(editor->item());
delete editor;
}
m_editor = nullptr;
switchEditor(except);
return true;
}
void MainWindow::setRunningMode(ProcessStatus flag)
{
if (flag == m_processMode)
return;
m_processMode = flag;
setWatchStatus(flag);
m_stack->setRunningMode(flag);
auto it = m_editors.begin();
while (it != m_editors.end())
{
if (it.value()->type() == Editor_script)
{
auto node_edit = (JZNodeEditor*)it.value();
node_edit->setRunningMode(flag);
}
it++;
}
if (m_processMode == Process_none)
{
m_program.clear();
m_runtime = JZNodeRuntimeInfo();
}
//update
if (m_processMode == Process_pause)
{
JZNodeRuntimeInfo new_runtime;
if (!m_debuger.runtimeInfo(new_runtime))
{
m_log->addLog(Log_Runtime, "获取信息失败");
return;
}
bool isNew = true;
if (new_runtime.stacks.size() > 0 && new_runtime.stacks.size() == m_runtime.stacks.size()
&& new_runtime.stacks.back().file == m_runtime.stacks.back().file
&& new_runtime.stacks.back().function == m_runtime.stacks.back().function)
{
isNew = false;
}
showTopLevel();
m_runtime = new_runtime;
m_log->stack()->setRuntime(m_runtime);
updateRuntime(m_runtime.stacks.size() - 1, isNew);
}
else
{
clearRuntimeNode();
}
updateActionStatus();
}
void MainWindow::clearRuntimeNode()
{
auto it = m_editors.begin();
while (it != m_editors.end())
{
auto editor = it.value();
if (editor->type() == Editor_script)
((JZNodeEditor*)editor)->setRuntimeNode(-1);
it++;
}
}
void MainWindow::setRuntimeNode(QString file, int nodeId)
{
clearRuntimeNode();
if (openEditor(file))
{
JZNodeEditor *editor = qobject_cast<JZNodeEditor*>(m_editor);
editor->setRuntimeNode(nodeId);
}
}
void MainWindow::clearWatchs()
{
for (auto w : m_debugWidgets)
w->clear();
}
void MainWindow::setWatchStatus(ProcessStatus status)
{
for (auto w : m_debugWidgets)
w->setRunningMode(status);
}
void MainWindow::onBreakPointClicked(QString file, int id)
{
onNavigate(file + "?id=" + QString::number(id));
}
void MainWindow::onBreakPointChanged(BreakPointChange reason, QString file, int id)
{
if (m_debuger.isConnect())
{
if (reason == BreakPoint_add)
{
auto bt = m_project.breakPoint(file, id);
m_debuger.addBreakPoint(bt);
}
else if(reason == BreakPoint_remove)
m_debuger.removeBreakPoint(file, id);
}
}
void MainWindow::updateTabText(int index)
{
auto editor = qobject_cast<JZEditor*>(m_editorStack->widget(index));
QString title = editor->item()->itemPath();
if (editor->isModified())
title += "*";
m_editorStack->setTabText(index, title);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xiongqiumin/JZNodeEditor.git
git@gitee.com:xiongqiumin/JZNodeEditor.git
xiongqiumin
JZNodeEditor
JZNodeEditor
master

搜索帮助