12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095 |
- #include "Document.h"
- #include "VPGlobal.h"
- #include "GvlManager.h"
- #include "PouManager.h"
- #include "TaskManager.h"
- #include "UiManager.h"
- #include "WindowAppBlockPort.h"
- #include "WindowAppBlockGoto.h"
- #include "WindowAppBlockParallel.h"
- #include "WindowAppBlockWait.h"
- #include "WindowAppResourceManagerTree.h"
- #include "WindowAppGvlView.h"
- #include "WindowAppPouFrame.h"
- #include "WindowAppTaskView.h"
- #include "WindowAppMdiFrame.h"
- #include "WindowAppUiFrame.h"
- #include "WindowAppBlockParallel.h"
- #include "WindowAppItemLink.h"
- #include "WindowAppItemInterface.h"
- #include "WindowAppPouScene.h"
- #include "DialogNewPou.h"
- #include "ToolDepository.h"
- #include "Preferences.h"
- extern ToolDepository toolDepository;
- // 存档文件的主版本(主版本号不同代表不能兼容)
- #define DOC_MAJOR_VERSION 3
- // 存档文件的次版本(仅次版本号不同则可以兼容)
- #define DOC_MINOR_VERSION 104
- // 硬件组态文件的主版本(主版本号不同代表不能兼容)
- #define DOC_HW_MAJOR_VERSION 3
- // 硬件组态文件的次版本(仅次版本号不同则可以兼容)
- #define DOC_HW_MINOR_VERSION 102
- /*
- 需要额外特殊处理的几种类型
- (1) 系统变量:不参与序列化,但是每次重置时需要恢复到默认值,并且程序启动时无论创建项目与否都自动建立变量;
- (2) Pou内部变量:不参与序列化,重置时参数恢复默认值,随Pou创建时自动创建,随Pou删除时删除;
- (3) 任务监视窗体:不参与序列化,重置时参数恢复默认值并清空界面,并且在删除全部窗体时不删除此窗体;
- (4) 日志信息窗体:不参与序列化,重置时参数恢复默认值并清空界面,并且在删除全部窗体时不删除此窗体;
- (5) 硬件组态:进行独立序列化(固定名称文件),重置时参数恢复默认值,并且在删除全部窗体时不删除此窗体;
- */
- /// <summary>
- /// 序列化 PORT_BIND_INFO
- /// </summary>
- /// <returns></returns>
- QDataStream& operator<<(QDataStream& out, const _tagDocBindToolInfo& info)
- {
- out << info.strSrcPou;
- out << info.strSourceTool;
- out << info.strDestPou;
- out << info.strDestInf;
- out << info.infType;
- return out;
- }
- /// <summary>
- /// 反序列化 PORT_BIND_INFO
- /// </summary>
- /// <param name="in"></param>
- /// <param name="w"></param>
- /// <returns></returns>
- QDataStream& operator>>(QDataStream& in, _tagDocBindToolInfo& info)
- {
- in >> info.strSrcPou;
- in >> info.strSourceTool;
- in >> info.strDestPou;
- in >> info.strDestInf;
- in >> info.infType;
- return in;
- }
- Document::Document()
- {
- VPGlobal::m_pDoc = this;
- }
- Document::~Document()
- {
- }
- /// <summary>
- /// 执行存档文件保存
- /// </summary>
- /// <returns></returns>
- bool Document::Save(const QString& strFullPath)
- {
- qDebug() << "[Documents] Document save.";
- // 根据用户选定的路径生成临时文件名,等待压缩之后形成正式的存档文件
- QString strSaveFullPath = strFullPath.left(strFullPath.length() - DOC_POSTFIX.length());
- strSaveFullPath += TMP_POSTFIX;
- // 建立存档文件
- QFile fileOut(strSaveFullPath);
- if (!fileOut.open(QFile::WriteOnly | QFile::Truncate))
- {
- Utility::VPCriticalMessageBox(strSaveFullPath + " create failed!");
- return false;
- }
- // 创建序列化对象
- QDataStream out(&fileOut);
- // 设置版本
- out.setVersion(QDataStream::Qt_5_14);
- // 写入当前版本号
- saveVersion(out, DOC_MAJOR_VERSION, DOC_MINOR_VERSION);
- // 写入系统全局配置区段
- saveConfig(out);
- out << (QString)"saveConfig " + LOAD_DOC_KEYWORDS;
- // 写入全局和局部变量区段
- saveVariables(out);
- out << (QString)"saveVariables " + LOAD_DOC_KEYWORDS;
- // 写入POU区段
- savePous(out);
- out << (QString)"savePous " + LOAD_DOC_KEYWORDS;
- // 写入Link区段
- saveLinks(out);
- out << (QString)"saveLinks " + LOAD_DOC_KEYWORDS;
- // 保存Task区段
- saveTasks(out);
- out << (QString)"saveTasks " + LOAD_DOC_KEYWORDS;
- // 保存UI区段
- saveUIs(out);
- out << (QString)"saveUIs " + LOAD_DOC_KEYWORDS;
- //// 写入硬件区段
- //saveHardwares(out);
- // 关闭文件
- fileOut.close();
- qDebug() << ("[Document] Serialized to " + strSaveFullPath + " finished.");
- // 执行压缩
- compress(strSaveFullPath);
- qDebug() << ("[Document] Comressed to " + strSaveFullPath + " finished.");
- Utility::VPInformationMessageBox("Serialized to " + strSaveFullPath + " finished. DocVersion: " + QString::number(thePrefs.m_nDocVersion));
- return true;
- }
- /// <summary>
- /// 2022-2-24,执行硬件组态数据保存
- /// </summary>
- /// <param name="strFullPath"></param>
- /// <returns></returns>
- bool Document::saveHdw(const QString& strFullPath)
- {
- qDebug() << "[Documents] Document harware save.";
- QFileInfo FileInfo(strFullPath);
- // 建立存档文件
- QFile fileOut(strFullPath);
- if (!fileOut.open(QFile::WriteOnly | QFile::Truncate))
- {
- Utility::VPCriticalMessageBox(strFullPath + " create failed!");
- return false;
- }
- // 创建序列化对象
- QDataStream out(&fileOut);
- // 设置版本
- out.setVersion(QDataStream::Qt_5_14);
-
- // 写入硬件组态文件版本号
- saveHdwVersion(out, DOC_HW_MAJOR_VERSION, DOC_HW_MINOR_VERSION);
- if (thePrefs.m_strHdwConfigID.isEmpty())
- {
- thePrefs.m_strHdwConfigID = "123456789";
- }
- out << thePrefs.m_strHdwConfigID;
- // 保存硬件组态Pou相关信息
- savePou(GROUP_NAME_HARDWARE, out);
- out << (QString)"savePou " + LOAD_DOC_KEYWORDS;
- // 保存硬件组态局部变量
- saveGVL(GROUP_NAME_HARDWARE, out);
- out << (QString)"saveGVL " + LOAD_DOC_KEYWORDS;
- fileOut.close();
-
- qDebug() << ("[Document] Serialized hardware to " + strFullPath + " finished. DocVersion: " + QString::number(thePrefs.m_nDocVersion));
- return true;
- }
- /// <summary>
- /// 整个系统重置(包括界面和UI)
- /// </summary>
- void Document::systemReset()
- {
- qDebug() << "[Document] System reset.";
- // 先重置所有的数据结构
- g_pGvlManager->reset();
- // 重置树状结构和子页面
- g_pResourceManager->reset();
- // 重置Task数据结构
- g_pTaskManager->reset();
- //// 重置硬件页面
- //VPGlobal::getWindowHdw()->reset();
- // 重置所有的Pou数据结构
- g_pPouManager->resetAllPous();
- // 重置所有UI窗体
- g_pUiManager->reset();
- //// 重置Link信息
- //m_Links.clear();
- // 重置Port绑定信息
- m_PortBindInfos.clear();
- // 重置Goto绑定信息
- m_GotoBindInfos.clear();
- // 重置Para绑定信息
- m_ParallelInfos.clear();
- }
- /// <summary>
- /// 执行存档文件加载
- /// </summary>
- /// <returns></returns>
- bool Document::Load(const QString& strFullPath)
- {
- qDebug() << "[Document] Load file : " << strFullPath;
- QString strLoadFullPath = strFullPath;
- // 解压缩
- if (! uncompress(strLoadFullPath))
- {
- return false;
- }
- // 打开存档文件
- QFile fileIn(strLoadFullPath);
- if (!fileIn.open(QFile::ReadOnly))
- {
- // Utility::VPCriticalMessageBox(strLoadFullPath + " open failed!");
- return false;
- }
- // 序列化对象
- QDataStream in(&fileIn);
- // 设置版本
- in.setVersion(QDataStream::Qt_5_14);
- // 读取文档版本号
- bool bRet = loadAndCheckVersion(in, DOC_MAJOR_VERSION, DOC_MINOR_VERSION);
- // 如果版本号有问题则不读取
- if (!bRet)
- {
- Utility::VPCriticalMessageBox("The document version is incompatible!");
- return false;
- }
- QString strInfo;
- // 首先重置系统环境,准备加载新的数据
- this->systemReset();
- // 读取配置信息
- if (! this->loadConfig(in))
- {
- fileIn.close();
- return false;
- }
- // 检查硬件组态的配置ID与 文档中存储的配置ID是否匹配
- thePrefs.m_strHdwConfigID = getHWAndDocConfigID();
- if (! checkHWAndDocConfigID(m_strHdwConfigID, thePrefs.m_strHdwConfigID))
- {
- fileIn.close();
- return false;
- }
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "loadVariables Error";
- return false;
- }
- // 读取全局和局部变量区段
- this->loadVariables(in);
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "loadVariables Error";
- return false;
- }
- // 读取Pou区段
- this->loadPous(in);
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "loadPous Error";
- return false;
- }
- // 读取Link区段
- this->loadLinks(in);
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "loadLinks Error";
- return false;
- }
- // 读取Task区段
- this->loadTasks(in);
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "loadTasks Error";
- return false;
- }
- // 读取UI区段
- this->loadUIs(in);
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "loadUIs Error";
- return false;
- }
- // 至此所有的数据都已经读取完毕,开始执行还原工作
- fileIn.close();
- // 还原Port绑定关系
- this->restorePortBindInfo();
- // 还原Goto绑定关系
- this->restoreGotoBindInfo();
- //// 还原Link信息
- //this->restoreLinks();
- // 还原ParallelTool相关信息
- this->restoreParallelInfos();
- // 读取完毕后,删除此临时文件
- QFile::remove(strLoadFullPath);
- Utility::VPInformationMessageBox("Deserialized from " + strFullPath + " finished. DocVersion: " + QString::number(thePrefs.m_nDocVersion) );
- return true;
- }
- /// <summary>
- /// 2022-2-24增加,加载硬件组态存档数据
- /// </summary>
- /// <param name="strFullPath"></param>
- /// <returns></returns>
- bool Document::loadHdw(const QString& strFullPath)
- {
- qDebug() << "[Document] Load hardware file : " << strFullPath;
- // 打开存档文件
- QFile fileIn(strFullPath);
- if (!fileIn.open(QFile::ReadOnly))
- {
- // Utility::VPCriticalMessageBox(strFullPath + " open failed!");
- qDebug() << "[Error] Document::loadHdw - load[" << strFullPath << "] failed.";
- return false;
- }
- // 序列化对象
- QDataStream in(&fileIn);
- // 设置版本
- in.setVersion(QDataStream::Qt_5_14);
- // 读取文档版本号
- bool bRet = loadAndCheckHdwVersion(in, DOC_HW_MAJOR_VERSION, DOC_HW_MINOR_VERSION);
- // 如果版本号有问题则不读取
- if (!bRet)
- {
- Utility::VPCriticalMessageBox("The hardware document version is incompatible!");
- return false;
- }
- // 旧版本的系统,不能加载配置文件ID
- if (thePrefs.m_nHdwVersion != 0)
- {
- in >> thePrefs.m_strHdwConfigID;
- }
- // 首先应该清理硬件组态的所有数据
- {
- POU* pHdPou = g_pPouManager->getPouByName(GROUP_NAME_HARDWARE);
- if (pHdPou)
- {
- pHdPou->reset();
- }
- }
- QString strInfo;
-
- // 加载硬件组态
- loadPou(in, GROUP_NAME_HARDWARE);
- in >> strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "load Hdw Pou Error";
- return false;
- }
- // 加载硬件组态局部变量
- loadGVL(in, GROUP_NAME_HARDWARE);
- in >> (QString&)strInfo;
- if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
- {
- vWarning() << "load Hdw GVL Error";
- return false;
- }
- fileIn.close();
- return true;
- }
- //========================================================
- //
- // Version
- //
- //========================================================
- /// <summary>
- /// 写入当前版本号
- /// </summary>
- /// <returns></returns>
- bool Document::saveVersion(QDataStream& out, int major, int minor)
- {
- qDebug() << "[Documents] Save [Version]: " + QString::number(major) + "." + QString::number(minor);
- out << major;
- out << minor;
- // 设置文档的版本号
- thePrefs.m_nDocVersion = minor;
- int paranum;//参数数量
- {
- paranum = 1;
- out << paranum;//先保存参数数量
- out << (int)1 << thePrefs.m_nDocVersion;
- }
- return true;
- }
- /// <summary>
- /// 写入当前版本号
- /// </summary>
- /// <returns></returns>
- bool Document::saveHdwVersion(QDataStream& out, int major, int minor)
- {
- qDebug() << "[Documents] Save [Version]: " + QString::number(major) + "." + QString::number(minor);
- out << major;
- out << minor;
- // 设置文档的版本号
- thePrefs.m_nHdwVersion = minor;
- int paranum;//参数数量
- {
- paranum = 1;
- out << paranum;//先保存参数数量
- out << (int)1 << thePrefs.m_nHdwVersion;
- }
- return true;
- }
- /// <summary>
- /// 加载当前版本号
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadAndCheckVersion(QDataStream& in, int major, int minor)
- {
- int nMajorVersion = 0, nMinorVersion = 0;
- in >> nMajorVersion;
- in >> nMinorVersion;
- int nDocVersion = 0;
- if (nMinorVersion > 0)
- {
- int paranum = 0;
- int para = 0;
- in >> paranum;//读取参数数量
- for (int i = 0; i < paranum; i++)
- {
- in >> para;
- switch (para)
- {
- case 1: in >> nDocVersion; break;
- default:
- {
- vWarning() << "Serialized(In) Error";
- return false;
- }
- break;
- }
- }
- }
- thePrefs.m_nDocVersion = nDocVersion;
- // 比较大版本号是否一致
- if (nMajorVersion != major)
- {
- QString strDocVer = QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
- QString strExeVer = QString::number(major) + "." + QString::number(minor);
- Utility::VPCriticalMessageBox("Incompatible document version: [exe]" + strDocVer + " " + "[Doc]" + strExeVer);
- return false;
- }
- qDebug() << "[Documents] Load [Version]: " + QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
- return true;
- }
- /// <summary>
- /// 加载当前版本号
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadAndCheckHdwVersion(QDataStream& in, int major, int minor)
- {
- int nMajorVersion = 0, nMinorVersion = 0;
- in >> nMajorVersion;
- in >> nMinorVersion;
- int nHdwVersion = 0;
- if (nMinorVersion > 0)
- {
- int paranum = 0;
- int para = 0;
- in >> paranum;//读取参数数量
- for (int i = 0; i < paranum; i++)
- {
- in >> para;
- switch (para)
- {
- case 1: in >> nHdwVersion; break;
- default:
- {
- vWarning() << "Serialized(In) Error";
- return false;
- }
- break;
- }
- }
- }
- thePrefs.m_nHdwVersion = nHdwVersion;
- // 比较大版本号是否一致
- if (nMajorVersion != major)
- {
- QString strDocVer = QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
- QString strExeVer = QString::number(major) + "." + QString::number(minor);
- Utility::VPCriticalMessageBox("[Hdw] Incompatible document version: [exe]" + strDocVer + " " + "[Doc]" + strExeVer);
- return false;
- }
- qDebug() << "[Hdw] Load [Version]: " + QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
- return true;
- }
- //========================================================
- //
- // Config
- //
- //========================================================
- /// <summary>
- /// 写入系统全局配置区段
- /// </summary>
- /// <returns></returns>
- bool Document::saveConfig(QDataStream& out)
- {
- int paranum = 1;
- thePrefs.m_strHdwConfigID = getHWAndDocConfigID();
- //先保存参数数量
- out << paranum;
- // 硬件ConfigID
- out << 1 << thePrefs.m_strHdwConfigID;
- return true;
- }
- /// <summary>
- /// 读取系统全局配置区段
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadConfig(QDataStream& in)
- {
- // 旧版本的系统,不能加载配置文件
- if (thePrefs.m_nDocVersion == 0)
- {
- return true;
- }
- int paranum = 0;
- int para = 0;
- // 首先读取参数数量
- in >> paranum;
- for (int i = 0; i < paranum; i++)
- {
- in >> para;
- switch (para)
- {
- case 1: in >> m_strHdwConfigID; break;
- default:
- {
- vWarning() << "Serialized(In) Error";
- return false;
- }
- break;
- }
- }
- return true;
- }
- //========================================================
- //
- // Variables
- //
- //========================================================
- /// <summary>
- /// 写入全局和局部变量区段
- /// </summary>
- /// <returns></returns>
- bool Document::saveVariables(QDataStream& out)
- {
- qDebug() << "[Documents] Save GVLs...";
- //// 遍历所有变量进行储存
- //QHash<QString, GVL*>* pAllVariables = g_pVariablesManager->getAllGvls();
- //// 写入总数量
- //out << pAllVariables->size();
- // 2022-2-22,这里需要跳过全局变量分组以及硬件分组
- QList<GVL*> AllGvls = g_pGvlManager->getAllSerializedGvls();
- // 写入总数量
- out << AllGvls.size();
- QListIterator<GVL*> it(AllGvls);
- while (it.hasNext())
- {
- saveGVL(it.next()->strName, out);
- }
- return true;
- }
- /// <summary>
- /// 写入单组变量
- /// </summary>
- /// <param name="strVarName"></param>
- /// <param name="out"></param>
- /// <returns></returns>
- bool Document::saveGVL(const QString strGroupName, QDataStream& out)
- {
- const GVL* pGvl = g_pGvlManager->getGvl(strGroupName);
- if (pGvl == nullptr)
- {
- qDebug() << "[Documents] Gvl[" << strGroupName << "] hasn't any variable.";
- out << 0;
- return false;
- }
- else
- {
- out << 1;
- }
- int nParanum = 4;//参数数量
- out << nParanum;//先保存参数数量
- out << nParanum;//此处写两次,用来后面做数据校验
- out << (int)1 << pGvl->Type;
- out << (int)2 << pGvl->strName;
- out << (int)3 << pGvl->gvlMode;
- out << (int)4 << pGvl->strHdwInstName;
- // 继续保存其中变量
- const VARIABLES& vars = pGvl->Variables;
- // 以 bShow 为标记为,判断内部变量,并排除掉
- int nSize = 0;
- for (int i = 0; i < vars.size(); i++)
- {
- if (vars[i]->bShow == true)
- {
- nSize++;
- }
- }
-
- // 写入变量数量
- out << nSize;
-
- //// 2022-2-22修改,只保存序列化的变量
- //const VARIABLES& vars = g_pGvlManager->getSerializedVariablesByGroup(pGvl->strName);
- //// 写入变量数量
- //out << vars.size();
-
- // 写入变量细节
- for (const VARIABLE* var : vars)
- {
- if (var->bShow)
- {
- this->saveInterface(out, var);
- // 2022-9-2 增加,保存变量的触发状态
- if (var->eventTrigger != nullptr)
- {
- out << 1;
- }
- else
- {
- out << 0;
- }
- }
- }
- qDebug() << "[Documents] Saved GVL Group[" << pGvl->strName << "]: " << nSize << " counts.";
- return true;
- }
- /// <summary>
- /// 读取全局和局部变量区段
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadVariables(QDataStream& in)
- {
- qDebug() << "[Documents] Load GVLs...";
- // 读入分组个数
- int nGroup = 0;
- in >> nGroup;
- // 循环读取所有变量分组
- for (int i = 0; i < nGroup; i++)
- {
- // 逐一读取每一个变量组
- loadGVL(in);
- }
- return true;
- }
- /// <summary>
- /// 读取单组的变量信息
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadGVL(QDataStream& in, const QString& strLoadName, bool bLoadName)
- {
- // 首先获取本Group是否有局部变量信息
- int nContinue = 0;
- in >> nContinue;
- if (nContinue == 0)
- {
- return true;
- }
- // 变量分组名称
- QString strGroupName;
- QString strHdwInstName;
- // 变量类型
- TOOL_TYPE type = TOOL_TYPE::TOOL_TYPE_STANDARD;
- GVL_MODE gvlType = GVL_MODE::GVL_BASIC;
- int nPara = 0;
- int nParanum = 0;
- in >> nParanum;//读取参数数量
- // 此处的校验值
- int nCheck = 0;
- in >> nCheck;//读取校验参数
- int nMaxParanum = 4;// 该参数的最大数量(需要根据参数的数量来调整,用来校验)
- if (nParanum < 0 || nParanum != nCheck || nParanum > nMaxParanum)
- {
- return false;
- }
- for (int i = 0; i < nParanum; i++)
- {
- in >> nPara;
- switch (nPara)
- {
- case 1: in >> type; break;
- case 2: in >> strGroupName; break;
- case 3: in >> gvlType; break;
- case 4: in >> strHdwInstName; break;
-
- default:
- {
- vWarning() << "GVL Serialized(In) Error";
- }
- break;
- }
- }
- if (!bLoadName)
- {
- strGroupName = strLoadName;
- }
- // 根据不同的类型添加不同的页面
- QWidget* pNewView = nullptr;
- // 如果是全局变量,则需要创建全局变量视图
- if (type == TOOL_TYPE::TOOL_TYPE_GLOBAL_VARIABLE)
- {
- DllTool* pHdwTool = nullptr;
- TOOL* pTool = nullptr;
- if (gvlType == GVL_MODE::GVL_DB)
- {
- POU* pHdwPou = g_pPouManager->getHdwPou();
- pTool = pHdwPou->GetToolByName(strHdwInstName);
- if (pTool == nullptr)
- {
- vWarning() << strHdwInstName << " not found in hardware configuration ";
- }
- else
- {
- pHdwTool = pTool->pDllPtr;
- }
- }
-
- // 创建全局变量视图
- pNewView = (WindowAppGvlView*)(g_pResourceManager->addGvlNode(strGroupName, gvlType, pHdwTool, false));
- g_pGvlManager->bindHdwToolAndDB(pTool, strGroupName);
-
- }
- // 局部变量则创建Pou视图
- else if (type == TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE)
- {
- // 创建Pou视图
- pNewView = (WindowAppPouFrame*)(g_pResourceManager->addPouNode(strGroupName));
- }
- int nVarCount = 0;
- in >> nVarCount;
- // 循环读取所有变量
- for (int j = 0; j < nVarCount; j++)
- {
- VARIABLE* pNewVariable = new VARIABLE(nullptr);
- // in >> *pNewVariable;
- // 读取变量
- this->loadInterface(in, pNewVariable);
- // 2022-9-27,由于index目前不参与序列化了,所以需要根据手动重新设置index(不过变量的Index基本没有用到)
- pNewVariable->nIndex = j;
- // 2022-9-2 增加,如果变量是带有触发事件的,需要额外生成一下触发事件
- int nTigger;
- in >> nTigger;
- if (nTigger == 1)
- {
- pNewVariable->eventTrigger = new ToolEvent(strGroupName, pNewVariable->strName, TOOL_EVENT_TYPE::TASK_TRIGGER);
- }
- // 直接读取,但是无需执行任何操作
- // Tip:因为变量会作为Port的接口被绑定,在后续保存Tool信息的时候会重新保存一下link信息
- // loadLinks(in, pNewVariable->strFullName, nullptr, false, LINK_MODE::LINK_NORMAL);
- // 数据结构中添加本变量信息
- g_pGvlManager->addNewVariable(strGroupName, pNewVariable);
- // 在界面中添加新的变量
- if (type == TOOL_TYPE::TOOL_TYPE_GLOBAL_VARIABLE)
- {
- ((WindowAppGvlView*)pNewView)->addNewVariable(pNewVariable);
- }
- else if (type == TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE)
- {
- ((WindowAppPouFrame*)pNewView)->addNewVariable(pNewVariable);
- }
- //// 2022-3-3 如果是DB模式的,还需要额外再读取一下DB和硬件Tool的绑定关系
- //if (pNewVariable->pParentTool->gvlMode == GVL_MODE::GVL_DB)
- //{
- // QString strHdwName;
- // in >> strHdwName;
- // POU* pHdwPou = g_pPouManager->getHdwPou();
- // TOOL* HdwTool = pHdwPou->GetToolByName(strHdwName);
- // DllTool* pHdwTool = HdwTool->pDllPtr;
- // g_pGvlManager->bindHdwToolAndDB(pHdwTool, strGroupName);
- //}
- }
- qDebug() << "[Documents] Loaded GVL group[" << strGroupName << "]: " << nVarCount << " counts.";
- return true;
- }
- //========================================================
- //
- // Pous
- //
- //========================================================
- /// <summary>
- /// 写入Pou区段
- /// </summary>
- /// <param name="out"></param>
- /// <returns></returns>
- bool Document::savePous(QDataStream& out)
- {
- qDebug() << "[Documents] Save POUs...";
- // 获取全部Pou
- const QMap<QString, POU*>& allPous = g_pPouManager->getAllPous();
- // 写入Pou总数量
- out << allPous.size() - 1;
- // 遍历所有的Pou信息
- QMapIterator<QString, POU*> it(allPous);
- while (it.hasNext())
- {
- it.next();
- // 2022-2-24 跳过硬件Pou
- if (it.key() != GROUP_NAME_HARDWARE)
- {
- savePou(it.key(), out);
- }
- }
- return true;
- }
- /// <summary>
- /// 写入单个Pou
- /// </summary>
- /// <param name="strPouName"></param>
- /// <param name="out"></param>
- /// <returns></returns>
- bool Document::savePou(const QString strPouName, QDataStream& out)
- {
- // 写入本Pou的分组名称
- out << strPouName;
- // 逐个保存Pou信息
- POU* pPou = g_pPouManager->getPouByName(strPouName);
- if (pPou == nullptr)
- {
- qDebug() << "[Documents] save pou, but can't find pou[" << strPouName << "].";
- return false;
- }
- // 2022-8-30 增加,首先序列化Pou界面相关参数
- out << pPou->parentScene()->parentFrame();
- // 遍历本Pou下的所有工具和接口
- const QMap<QString, TOOL*>& allTools = pPou->GetAllTools();
- // 写入总数量
- out << allTools.size();
- QMapIterator<QString, TOOL*> i(allTools);
- while (i.hasNext())
- {
- TOOL* pTool = i.next().value();
- // 保存Tool信息
- this->saveTool(out, pTool);
- // 保存此Tool在界面中的坐标
- out << pPou->GetToolItemPos(pTool->strInstanceName);
- // 如果是Port类型,还需要额外存储一下Port的绑定关系
- if (pTool->isPortTool())
- {
- this->savePortBindInfo(out, pTool);
- }
- // 如果是Goto类型,还需要额外存储一下Goto的绑定关系
- else if (pTool->isGotoTool())
- {
- this->saveGotoBindInfo(out, pTool);
- }
- // 2022-9-4,如果是Wait类型,还需要额外存储一下Wait工具的相关参数
- else if (pTool->isWaitTool())
- {
- this->saveWaitToolSettings(out, pPou, pTool);
- }
- //// 如果是Parallel类型,还需要额外存储一下Parallel的绑定关系
- //else if (pTool->isParallelTool())
- //{
- // this->saveParallelBindInfo(out, pTool);
- //}
- else
- {
- // 2021-8-14增加,标准工具则再保存dll中的内部变量
- if (pTool->pDllPtr)
- {
- // 工具序列化出错的时候,会抛出异常,需要退出后续序列化
- try
- {
- pTool->pDllPtr->SerializedToDoc(out);
- }
- catch (...)
- {
- return false;
- }
- }
- }
- qDebug() << "[Documents] Saved " << pTool->strInstanceName << ": " << pTool->Interfaces.size() << " interfaces.";
- }
- return true;
- }
- /// <summary>
- /// 读取Pou区段
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadPous(QDataStream& in)
- {
- qDebug() << "[Documents] Load POUs...";
- // 读入Pou总数量
- int nPouCount = 0;
- in >> nPouCount;
- // 循环读取所有Pou分组
- for (int i = 0; i < nPouCount; i++)
- {
- loadPou(in);
- }
- return true;
- }
- /// <summary>
- /// 读取单组的Pou相关信息
- /// </summary>
- /// <param name="in"></param>
- /// <param name="strLoadName">之前已经加载过的Pou分组名字</param>
- /// <param name="bLoadName">本次是否还需要继续加载名字</param>
- /// <returns></returns>
- bool Document::loadPou(QDataStream& in, const QString& strLoadName, bool bLoadName)
- {
- // 创建对应的Pou页面
- WindowAppPouFrame* pouFrame = nullptr;
- // 2021-8-24增加,由于单独导入导出Pou的时候,需要提前加载一下名字
- // 用于判断当前加载的Pou节点是否已经存在
- // Pou分组名称
- QString strPouName = strLoadName;
- if (bLoadName)
- {
- in >> strPouName;
- }
- // 创建Pou视图
- pouFrame = qobject_cast<WindowAppPouFrame*>(g_pResourceManager->addPouNode(strPouName, false));
- // 2022-8-30 增加,首先完成pouFrame的参数序列化
- in >> pouFrame;
- // 读入工具数量
- int nToolCount = 0;
- in >> nToolCount;
- // 逐个生成对应的工具
- for (int j = 0; j < nToolCount; j++)
- {
- // 根据信息创建新的工具
- TOOL* pNewTool = new TOOL();
- // 加载本工具信息
- bool state = this->loadTool(in, pNewTool);
- if (!state)
- {
- vWarning() << "[Error] Document::loadPou - LoadTools Error in " << strPouName;
- return false;
- }
- // 读取本Tool的屏幕坐标
- QPointF toolPos;
- in >> toolPos;
- // 如果本工具是Port类型,还需要额外读取Port绑定信息
- if (pNewTool->isPortTool())
- {
- this->loadPortBindInfo(in, strLoadName, bLoadName);
- }
- // 如果本工具是Goto类型,还需要额外读取Goto绑定信息
- else if (pNewTool->isGotoTool())
- {
- this->loadGotoBindInfo(in);
- }
- // 如果是Parallel工具,额外保存并行工具信息用于最后执行恢复
- else if (pNewTool->isParallelTool())
- {
- this->loadParallelInfos(in, pNewTool);
- }
-
- // 2022-6-12 直接用Scene指针创建对应的工具Block
- g_pPouManager->getPouSceneByName(strPouName)->addToolItem(pNewTool, toolPos, true);
- // 2021-8-14增加,保存dll中的内部变量(仅限标准工具)
- if (pNewTool->isStandardTool())
- {
- if (pNewTool->pDllPtr == nullptr)
- {
- return false;
- }
- this->loadFromToolDll(in ,pNewTool);
- }
- // 2022-9-4,如果是Wait工具,在功能块创建完毕之后,还需要额外读取一下Wait工具的相关参数保存到功能块中
- else if (pNewTool->isWaitTool())
- {
- this->loadWaitToolSettings(in, g_pPouManager->getPouByName(strPouName), pNewTool);
- }
- }
- qDebug() << "[Documents] Load pou [" + strPouName + "] finished.";
- return true;
- }
- /// <summary>
- /// 从Tool的Dll中反序列化
- /// </summary>
- /// <param name="in"></param>
- /// <param name="pNewTool"></param>
- void Document::loadFromToolDll(QDataStream& in, TOOL*& pNewTool)
- {
- pNewTool->pDllPtr->SerializedFromDoc(in);
- //QFuture<bool> future = QtConcurrent::run(
- // pNewTool->pDllPtr,
- // &DllTool::SerializedFromDoc,
- // in
- //);
- //
- //while (true)
- //{
- // if (future.isFinished())
- // {
- // break;
- // }
- // QCoreApplication::processEvents();
- // Utility::qSleep(100);
- //}
- for (int i = 0; i < pNewTool->Interfaces.size(); i++)
- {
- const _INTERFACE* pInf = pNewTool->Interfaces[i];
- // 如果是动态加载的端口,不从工具的基础端口里去查找,直接添加
- if (pInf->bDynamic)
- {
- // TODO: 加载的端口,Ptr未绑定值,需要调用dll 对应的函数,来绑定变量
- if (pNewTool->pDllPtr != nullptr)
- {
- DLL_INF inf;
- inf.strName = pInf->strName;
- inf.Direction = pInf->Direction;
- inf.Type = pInf->Type;
- inf.value.passMode = pInf->value.passMode;
- inf.value.type = pInf->value.type;
- inf.nIndex = pInf->nIndex;
- inf.bDynamic = pInf->bDynamic;
- pNewTool->pDllPtr->AddInterface(inf);
- pNewTool->pDllPtr->bindValuePtrByName(pInf->strName, pInf->nIndex);
- }
- }
- }
- }
- //========================================================
- //
- // Tools
- //
- //========================================================
- /// <summary>
- /// 写入Tool区段
- /// </summary>
- /// <returns></returns>
- bool Document::saveTool(QDataStream& out, const TOOL* pTool)
- {
- int nParanum = 11;//参数数量
- out << nParanum;//先保存参数数量
- out << (int)1 << pTool->Type;
- out << (int)2 << pTool->strPouName;
- out << (int)3 << pTool->strName;
- out << (int)4 << pTool->strAliasName;
- out << (int)5 << pTool->strInstanceName;
- out << (int)6 << pTool->strInfo;
- out << (int)7 << pTool->strVersion;
- out << (int)8 << pTool->bEnable;
- out << (int)9 << pTool->nIndex;
- out << (int)10 << pTool->strComment;
- out << (int)11 << pTool->bEnable;
- // 保存所有的接口信息
- this->saveToolInterfaces(out, pTool);
- return true;
- }
- /// <summary>
- /// 读入Tool区段
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadTool(QDataStream& in, TOOL*& pNewTool)
- {
- int nPara;
- int nParanum;
- in >> nParanum;//读取参数数量
- // 校验值
- int nMaxParanum = 11;// 该参数的最大数量(需要根据参数的数量来调整,用来校验)
- if (nParanum < 0 || nParanum > nMaxParanum)
- {
- return false;
- }
- for (int i = 0; i < nParanum; i++)
- {
- in >> nPara;
- switch (nPara)
- {
- case 1: in >> pNewTool->Type; break;
- case 2: in >> pNewTool->strPouName; break;
- case 3: in >> pNewTool->strName; break;
- case 4: in >> pNewTool->strAliasName; break;
- case 5: in >> pNewTool->strInstanceName; break;
- case 6: in >> pNewTool->strInfo; break;
- case 7: in >> pNewTool->strVersion; break;
- case 8: in >> pNewTool->bEnable; break;
- case 9: in >> pNewTool->nIndex; break;
- case 10: in >> pNewTool->strComment; break;
- case 11: in >> pNewTool->bEnable; break;
-
- default:
- {
- vWarning() << "[Error] Document::loadTool - invalid para index: " << nPara;
- }
- break;
- }
- }
- int nInfCount = 0;
- in >> nInfCount;
- TOOL* pTool_Dll = toolDepository.getToolByName(pNewTool->strName);
- if (pTool_Dll == nullptr && pNewTool->isStandardTool())
- {
- return false;
- }
- // 处理工具改名的相关问题
- if (pTool_Dll->strName != pNewTool->strName)
- {
- pNewTool->strName = pTool_Dll->strName;
- pNewTool->strAliasName = pTool_Dll->strAliasName;
- }
- // 读取接口信息
- this->loadToolInterfaces(in, pNewTool, pTool_Dll, nInfCount);
- return true;
- }
- //========================================================
- //
- // Interfaces
- //
- //========================================================
- /// <summary>
- /// 写入所有的Interface信息
- /// </summary>
- /// <param name="out"></param>
- /// <param name="pTool"></param>
- /// <returns></returns>
- bool Document::saveToolInterfaces(QDataStream& out, const TOOL* pTool)
- {
- // 写入接口数量
- out << pTool->Interfaces.size();
- // 继续遍历标准接口,逐一保存
- for (_INTERFACE* pInf : pTool->Interfaces)
- {
- // out << *pInf;
- this->saveInterface(out, pInf);
- }
- //// 如果是具备ToolStart接口的,还需要额外保存一下ToolStart接口信息
- //if (pTool->startInterface != nullptr)
- //{
- // // out << *pTool->TopInterface;
- // this->saveInterfaces(out, pTool->startInterface);
- //}
- //// 如果具备ToolEnd接口的,还需要额外保存一下ToolEnd接口信息
- //if (pTool->endInterface != nullptr)
- //{
- // this->saveInterfaces(out, pTool->endInterface);
- //}
- // 2022-8-25,遍历ToolInterface接口(如果有的话),逐一保存
- for (const auto& toolInterface : pTool->ToolInterfaces)
- {
- this->saveInterface(out, toolInterface);
- }
- return true;
- }
- /// <summary>
- /// 写入Interface信息
- /// </summary>
- /// <param name="out"></param>
- /// <param name="inf"></param>
- /// <returns></returns>
- bool Document::saveInterface(QDataStream& out, const _INTERFACE* inf)
- {
- //int nParanum = 19;//参数数量
- //out << nParanum;//先保存参数数量
- //out << (int)1 << inf->strName;
- //out << (int)2 << inf->strFullName;
- //out << (int)3 << inf->strNameWithType;
- //out << (int)4 << inf->Direction;
- //out << (int)5 << inf->Type;
- //out << (int)6 << inf->nIndex;
- //out << (int)7 << inf->bEnable;
- //out << (int)8 << inf->strComment;
- //out << (int)9 << inf->bSerialized;
- //out << (int)10 << inf->bShow;
- //out << (int)11 << inf->bDynamic;
- //out << (int)12 << (int&)inf->parent()->gvlMode;
- //out << (int)13 << inf->bWatch;
- //out << (int)14 << inf->bDataLink;
- //out << (int)15 << inf->valueString;
- //out << (int)16 << inf->bComplexLinkIndex;
- //out << (int)17 << inf->accessMode;
- //out << (int)18 << inf->strCommAddress;
- //out << (int)19 << inf->bShowName;
- // 2022-9-27,此处不再保存接口的index了
- // 因为下次反序列化的时候接口可能已经变动了,index就已经不准了
- int nParanum = 18;//参数数量
- out << nParanum;//先保存参数数量
- out << (int)1 << inf->strName;
- out << (int)2 << inf->strFullName;
- out << (int)3 << inf->strNameWithType;
- out << (int)4 << inf->Direction;
- out << (int)5 << inf->Type;
- out << (int)6 << inf->bEnable;
- out << (int)7 << inf->strComment;
- out << (int)8 << inf->bSerialized;
- out << (int)9 << inf->bShow;
- out << (int)10 << inf->bDynamic;
- out << (int)11 << (int&)inf->parent()->gvlMode;
- out << (int)12 << inf->bWatch;
- out << (int)13 << inf->bDataLink;
- out << (int)14 << inf->valueString;
- out << (int)15 << inf->bComplexLinkIndex;
- out << (int)16 << inf->accessMode;
- out << (int)17 << inf->strCommAddress;
- out << (int)18 << inf->bShowName;
- // Pou类型的接口是不存具体数值的,只有变量类型的才会存
- // 2022-2-23 增加,只有基础模式的变量才需要保存值
- if (inf->Type == INF_TYPE::INF_TYPE_VALUE
- && inf->parent()->gvlMode == GVL_MODE::GVL_BASIC
- )
- {
- out << inf->value;
- }
- //// 2022-3-31 增加,Goto的输入接口也需要保存值(bool类型)
- //else if (inf.pParentTool->isGotoTool()
- // && inf.Direction == INF_DIRECTION::INF_DIR_IN )
- //{
- // out << inf.value;
- //}
- else
- {
- out << inf->value.passMode;
- out << inf->value.type;
- }
- return true;
- }
- /// <summary>
- /// 读取所有的Interface信息
- /// </summary>
- /// <param name="out"></param>
- /// <param name="pNewTool"></param>
- /// <param name="pTool_Dll"></param>
- /// <returns></returns>
- bool Document::loadToolInterfaces(QDataStream& in, TOOL*& pNewTool, TOOL*& pTool_Dll, int nInfCount)
- {
- // 判断是删除了端口,还是增加了端口,
- // 如果新dll删除了端口,则引用就版本存储下来的端口(暂用新工具的端口,序列化上来过期的端口将被抛弃)
- // 如果新dll增加了端口,则将新添加的的端口插入进来,注意,新端口可能不是在末添加的,可能是任意位置
- for (int i = 0; i < nInfCount; i++)
- {
- _INTERFACE* pNewInf = new _INTERFACE(pNewTool);
- // 2022-9-27由于目前接口index不参与序列化了,后面需要手工补一下接口序号
- this->loadInterface(in, pNewInf);
- // 如果是动态加载的端口,不从工具的基础端口里去查找,直接添加
- if (pNewInf->bDynamic || pNewTool->isPortTool())
- {
- pNewTool->Interfaces.push_back(pNewInf);
- // TODO: 加载的端口,Ptr未绑定值,需要调用dll 对应的函数,来绑定变量
- }
- else
- {
- // TODO:2022-3-31 此处的代码是有问题的,因为作为Goto这种动态绑定的端口,端口名字都会随着绑定接口的名称而改变
- // 所以肯定是在toolDepository中查询不到的,并且 pTool_Dll 作为动态生成的端口,使用完毕之后需要手工删除
- // 如果在工具中找到对应端口,则说明该端口正常使用中
- // 端口被标记为废弃,是因为
- // 1:直接删除端口的代码,
- // 2:端口代码没删除,而是内部标记为废弃
- // 3:修改了端口的数据类型或者输入输出类型,或者数据传递类型
- //
- INF_DISCARD Discard = INF_DISCARD::INF_MARK_DELETE;
- for (int j = 0; j < pTool_Dll->Interfaces.size(); j++)
- {
- _INTERFACE* pDllInf = pTool_Dll->Interfaces[j];
- // 必须确保所有的类型都一样
- if (pDllInf->strName == pNewInf->strName)
- {
- if (pDllInf->Direction == pNewInf->Direction
- && pDllInf->value.passMode == pNewInf->value.passMode
- && pDllInf->value.type == pNewInf->value.type
- )
- {
- // 所有数据类型都校验成功,引用 DLL 实际配置的端口信息(在此接受工具开发者主动废弃端口)
- Discard = pDllInf->Discard;
- break;
- }
- // 如果数据类型和其它属性校验失败,证明数据数据已经被修改
- else
- {
- Discard = INF_DISCARD::INF_MARK_CHANGE;
- // TODO:如果数据结构已经被修改。需要在功能块上添加一个最新的接口(从dll中加载的)
- //pDllInf->strName += "(new)";
- //pNewTool->Interfaces.push_back(pDllInf);
- }
- }
- }
- pNewInf->Discard = Discard;
- pNewTool->Interfaces.push_back(pNewInf);
- }
- }
- // 如果dll 中添加了新的端口,则需要在pNewTool->Interfaces中,插入新添加的
- if (pTool_Dll->Interfaces.size() > nInfCount)
- {
- for (int i = 0; i < pTool_Dll->Interfaces.size(); i++)
- {
- _INTERFACE* pDllInf = pTool_Dll->Interfaces[i];
- // 遍历序DLL 的端口,与DOC 的对比,检查是否有新添加进来的端口
- bool bIsLookupOK = false; //
- for (int j = 0; j < pNewTool->Interfaces.size(); j++)
- {
- _INTERFACE* pDocInf = pNewTool->Interfaces[j];
- if (pDllInf->strName == pDocInf->strName
- && pDllInf->strNameWithType == pDocInf->strNameWithType
- && pDllInf->value.type == pDocInf->value.type
- )
- {
- bIsLookupOK = true;
- }
- }
- // 如果在 Doc加载上来的端口序列中没找到,即 i 的位置插入这个端口
- if (!bIsLookupOK)
- {
- pNewTool->Interfaces.insert(i, pDllInf);
- }
- }
- }
- // 2022-9-28,端口反序列化结束,并且已经和Dll比对完毕后,给所有的端口重新编一下序号
- int infIndex = 0;
- for (int i = 0; i < pNewTool->Interfaces.size(); i++)
- {
- // 需要跳过废弃的端口
- // if (pNewTool->Interfaces[i]->Discard != INF_DISCARD::INF_MARK_DELETE
- // && pNewTool->Interfaces[i]->Discard != INF_DISCARD::INF_MARK_DISCARD
- // )
- {
- pNewTool->Interfaces[i]->nIndex = infIndex++;
- }
- }
- // 2022-4-7 如果是标准工具还需要继续读取ToolInterface接口的相关信息
- if (pNewTool->isHaveToolInterfaces())
- {
- pNewTool->ToolInterfaces.clear();
- // 重新读取ToolInterface
- // (TODO:此处固定按2个接口读的,因为写入的时候并没有写入ToolInterface的数量,有隐患)
- for (int i = 0; i < TOOL_INTERFACE_COUNT; i++)
- {
- _INTERFACE* newInf = new _INTERFACE(pNewTool, INF_TYPE::INF_TYPE_TOOL);
- pNewTool->ToolInterfaces.push_back(newInf);
- this->loadInterface(in, pNewTool->ToolInterfaces[i]);
- }
- //// 如果本工具加入了并行组,则保存Link信息用于后续恢复
- //if (pNewTool->bParallelized)
- //{
- // // loadLinks(in, pNewTool->TopInterface->strFullName, pView, true, LINK_MODE::LINK_PARALLEL);
- //}
- //// 如果是其他情况,则跳过link的处理
- //// 例如Goto工具的连接,或者是未连接等等
- //else
- //{
- // // loadLinks(in, pNewTool->TopInterface->strFullName, pView, false, LINK_MODE::LINK_NORMAL);
- //}
- }
- return true;
- }
- /// <summary>
- /// 读取Interface信息
- /// </summary>
- /// <param name="in"></param>
- /// <param name="inf"></param>
- /// <returns></returns>
- bool Document::loadInterface(QDataStream& in, _INTERFACE*& inf)
- {
- GVL_MODE gvlMode = GVL_MODE::GVL_BASIC;
- int nPara;
- int nParanum;
- in >> nParanum;//读取参数数量
- //// 校验
- //int nMaxParanum = 19;// 该参数的最大数量(需要根据参数的数量来调整,用来校验)
- //if (nParanum < 0 || nParanum > nMaxParanum)
- //{
- // return false;
- //}
- //for (int i = 0; i < nParanum; i++)
- //{
- // in >> nPara;
- // switch (nPara)
- // {
- // case 1: in >> inf->strName; break;
- // case 2: in >> inf->strFullName; break;
- // case 3: in >> inf->strNameWithType; break;
- // case 4: in >> inf->Direction; break;
- // case 5: in >> inf->Type; break;
- // case 6: in >> inf->nIndex; break;
- // case 7: in >> inf->bEnable; break;
- // case 8: in >> inf->strComment; break;
- // case 9: in >> inf->bSerialized; break;
- // case 10: in >> inf->bShow; break;
- // case 11: in >> inf->bDynamic; break;
- // case 12: in >> (int&)gvlMode; break;
- // case 13: in >> inf->bWatch; break;
- // case 14: in >> inf->bDataLink; break;
- // case 15: in >> inf->valueString; break;
- // case 16: in >> inf->bComplexLinkIndex; break;
- // case 17: in >> inf->accessMode; break;
- // case 18: in >> inf->strCommAddress; break;
- // case 19: in >> inf->bShowName; break;
- //
- // default:
- // {
- // vWarning() << "_INTERFACE Serialized(In) Error";
- // }
- // break;
- // }
- //}
- // 2022-9-27,去掉了index序列化,因为下次反序列化的时候接口可能已经变动了,index需要重新计算,而不是直接读取
- // 校验,该参数的最大数量(需要根据参数的数量来调整,用来校验)
- int nMaxParanum = 18;
- if (nParanum < 0 || nParanum > nMaxParanum)
- {
- return false;
- }
- for (int i = 0; i < nParanum; i++)
- {
- in >> nPara;
- switch (nPara)
- {
- case 1: in >> inf->strName; break;
- case 2: in >> inf->strFullName; break;
- case 3: in >> inf->strNameWithType; break;
- case 4: in >> inf->Direction; break;
- case 5: in >> inf->Type; break;
- case 6: in >> inf->bEnable; break;
- case 7: in >> inf->strComment; break;
- case 8: in >> inf->bSerialized; break;
- case 9: in >> inf->bShow; break;
- case 10: in >> inf->bDynamic; break;
- case 11: in >> (int&)gvlMode; break;
- case 12: in >> inf->bWatch; break;
- case 13: in >> inf->bDataLink; break;
- case 14: in >> inf->valueString; break;
- case 15: in >> inf->bComplexLinkIndex; break;
- case 16: in >> inf->accessMode; break;
- case 17: in >> inf->strCommAddress; break;
- case 18: in >> inf->bShowName; break;
- default:
- {
- vWarning() << "_INTERFACE Serialized(In) Error";
- }
- break;
- }
- }
- // 2022-2-23 增加,只有基础模式的变量才需要读取数值
- if (inf->Type == INF_TYPE::INF_TYPE_VALUE)
- {
- if (gvlMode == GVL_MODE::GVL_BASIC)
- {
- in >> inf->value;
- }
- // 如果是其他类型的数值,则需要重置为默认值
- else
- {
- in >> inf->value.passMode;
- in >> inf->value.type;
- inf->value.setValue(QString(""));
- }
- }
- //// 2022-3-31 增加,Goto的输入接口也需要保存值(bool类型)
- //else if (inf->pParentTool->isGotoTool()
- // && inf->Direction == INF_DIRECTION::INF_DIR_IN)
- //{
- // in >> inf->value;
- //}
- // 如果是dll中的值,则留空
- else
- {
- in >> inf->value.passMode;
- in >> inf->value.type;
- }
- // 如果属性设置了不参与序列化,即把该变量的值设置为空,
- if (!inf->bSerialized)
- {
- inf->value.setValue(QString(""));
- }
- return true;
- }
- //========================================================
- //
- // Port
- //
- //========================================================
- /// <summary>
- /// 写入Port信息
- /// </summary>
- /// <param name="out"></param>
- /// <returns></returns>
- bool Document::savePortBindInfo(QDataStream& out, const TOOL* pTool)
- {
- const _INTERFACE* pPortInf = pTool->Interfaces[0];
- // 是否已经处于绑定状态
- if (pPortInf->isBinded())
- {
- out << 1;
- DOC_BIND_TOOL_INFO info;
- info.strSrcPou = pTool->strPouName;
- info.strSourceTool = pTool->strInstanceName;
- info.strDestPou = pPortInf->bindedParent()->strPouName;
- info.strDestInf = pPortInf->pBindInterface->strFullName;
- info.infType = pPortInf->bindedParent()->Type;
- out << info;
- }
- // 否则,写入空
- else
- {
- out << 0;
- }
- return true;
- }
- /// <summary>
- /// 读取Port信息
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadPortBindInfo(QDataStream& in, const QString& strLoadName, bool bLoadName)
- {
- int nBindCount = 0;
- in >> nBindCount;
- // 如果没有绑定,则无需读取
- if (nBindCount <= 0)
- {
- return true;
- }
- DOC_BIND_TOOL_INFO info;
- in >> info;
- if (! bLoadName)
- {
- info.strSrcPou = strLoadName;
- info.strDestPou = strLoadName;
- }
- m_PortBindInfos.push_back(info);
- return true;
- }
- /// <summary>
- /// 还原Port绑定关系
- /// </summary>
- /// <param name="pTool"></param>
- /// <returns></returns>
- bool Document::restorePortBindInfo()
- {
- for (const DOC_BIND_TOOL_INFO& info : m_PortBindInfos)
- {
- // 首先找到这个Port
- POU* pou = g_pPouManager->getPouByName(info.strSrcPou);
- TOOL* pPort = pou->GetToolByName(info.strSourceTool);
- // 找到此Port对应的功能块
- WindowAppBlockPort* pPortItem = qgraphicsitem_cast<WindowAppBlockPort*>(pou->GetToolItem(info.strSourceTool));
- // 检查错误
- if (pou == nullptr || pPort == nullptr || pPortItem == nullptr)
- {
- qDebug() << "[Error] Document::restorePortBindInfo - pou[" << info.strSrcPou << "] or PORT["
- << info.strSourceTool << "] or pPortItem is nullptr.";
- continue;
- }
- // 然后找到这个接口(2022-3-2处理,区分Pou和Gvl)
- _INTERFACE* pInf = nullptr;
- // 如果绑定的是工具接口
- if (info.infType == TOOL_TYPE::TOOL_TYPE_STANDARD)
- {
- POU* toolPou = g_pPouManager->getPouByName(info.strDestPou);
- if (toolPou != nullptr)
- {
- pInf = toolPou->GetInterface(info.strDestInf);
- }
- }
- // 如果绑定的是变量
- else if(info.infType == TOOL_TYPE::TOOL_TYPE_GLOBAL_VARIABLE
- || info.infType == TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE
- )
- {
- GVL* gvl = g_pGvlManager->getGvl(info.strDestPou);
- if (gvl != nullptr)
- {
- pInf = gvl->getInterfaceByFullName(info.strDestInf);
- }
- }
- // 不应该执行到这里
- else
- {
- vWarning() << "[Error] Document::restorePortBindInfo - Unknown infType [" << (short)info.infType << "] if inf["
- << info.strDestInf << "].";
- // 直接重置本Port接口的绑定状态
- pPort->setPortError();
- continue;
- }
- // 2022-3-23,此处inf为空有可能是因为单独输入输出Pou的时候,关联的接口并没有导入所致,所以直接清空Port的绑定状态
- if (pInf == nullptr)
- {
- vWarning() << "[Error] Document::restorePortBindInfo - inf [" << info.strDestInf << "] is nullptr.";
- // 重置本Port接口的绑定状态
- pPort->setPortError();
-
- continue;
- }
- // 重新执行Port的绑定动作
- pPortItem->bindInterface(pInf);
- }
- return true;
- }
- //========================================================
- //
- // Goto
- //
- //========================================================
- /// <summary>
- /// 写入Goto的绑定关系
- /// </summary>
- /// <param name="out"></param>
- /// <param name="pTool"></param>
- /// <returns></returns>
- bool Document::saveGotoBindInfo(QDataStream& out, const TOOL* pTool)
- {
- const _INTERFACE* pPortInf = pTool->Interfaces[GOTO_OUTPUT_INDX];
- // 是否已经处于绑定状态
- if (pPortInf->isBinded())
- {
- out << 1;
- DOC_BIND_TOOL_INFO info;
- info.strSrcPou = pTool->strPouName;
- info.strSourceTool = pTool->strInstanceName;
- info.strDestPou = pPortInf->bindedParent()->strPouName;
- info.strDestInf = pPortInf->pBindInterface->strFullName;
- info.infType = pPortInf->bindedParent()->Type;
- out << info;
- }
- // 否则,写入空
- else
- {
- out << 0;
- }
- return true;
- }
- /// <summary>
- /// 读取Goto的绑定关系
- /// TODO:此处同样涉及到Tool改名问题
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadGotoBindInfo(QDataStream& in)
- {
- int nBindCount = 0;
- in >> nBindCount;
- // 如果没有绑定,则无需读取
- if (nBindCount <= 0)
- {
- return true;
- }
- DOC_BIND_TOOL_INFO info;
- in >> info;
- m_GotoBindInfos.push_back(info);
- return true;
- }
- /// <summary>
- /// 还原Goto绑定关系
- /// </summary>
- /// <returns></returns>
- bool Document::restoreGotoBindInfo()
- {
- for (auto info : m_GotoBindInfos)
- {
- // 首先找到这个Port
- POU* pou = g_pPouManager->getPouByName(info.strSrcPou);
- TOOL* pGoto = pou->GetToolByName(info.strSourceTool);
- // 找到此Goto对应的功能块
- WindowAppBlockGoto* pItem = qgraphicsitem_cast<WindowAppBlockGoto*>(pou->GetToolItem(info.strSourceTool));
- // 检查错误
- if (pou == nullptr || pGoto == nullptr || pItem == nullptr)
- {
- qDebug() << "[Error] Document::restoreGotoBindInfo - pou[" << info.strSrcPou <<
- "] or GotoTool[" << info.strSourceTool << "] or pItem is nullptr.";
- continue;
- }
- _INTERFACE* pInf = nullptr;
- POU* toolPou = g_pPouManager->getPouByName(info.strDestPou);
- if (toolPou != nullptr)
- {
- pInf = toolPou->GetInterface(info.strDestInf);
- }
- // 检查错误
- if (pInf == nullptr)
- {
- vWarning() << "[Error] Document::restoreGotoBindInfo - inf [" << info.strDestInf << "] is nullptr.";
- continue;
- }
- // 重新执行Port的绑定动作
- pItem->bindOutputInterface(pInf->parent());
- // 此处为Goto的输入接口重置bool类型的值为false
- pGoto->Interfaces[GOTO_INPUT_INDX]->value.setValue<bool>(false);
- }
- return true;
- }
- //========================================================
- //
- // Links
- //
- //========================================================
- /// <summary>
- /// 保存Link信息
- /// </summary>
- /// <param name="out"></param>
- /// <returns></returns>
- bool Document::saveLinks(QDataStream& out)
- {
- // 遍历所有Pou取出其中的Link信息
-
- // 获取全部Pou
- const QMap<QString, POU*>& allPous = g_pPouManager->getAllPous();
- // 写入总数量
- out << allPous.size();
- // 遍历所有的Pou信息
- QMapIterator<QString, POU*> it(allPous);
- while (it.hasNext())
- {
- it.next();
- //// 跳过硬件Pou
- //if (it.key() == GROUP_NAME_HARDWARE)
- //{
- // continue;
- //}
- // 保存本Pou中的Link信息
- this->saveLink(out, it.value());
- }
- return true;
- }
- /// <summary>
- /// 保存单组Pou中的Link信息
- /// </summary>
- /// <param name="out"></param>
- /// <param name="pou"></param>
- /// <returns></returns>
- bool Document::saveLink(QDataStream& out, POU* pou)
- {
- // 然后写入本Pou所有的Link信息
- const QVector<LINK>& allLinks = pou->getAllLinks();
- // 总数量
- int linkCount = allLinks.size();
- out << linkCount;
- if (linkCount <= 0)
- {
- return true;
- }
- // 如果有Link的话,则写入Pou的名字
- out << pou->pouName();
- // 然后写入所有Link细节信息
- for (const auto& one_link : allLinks)
- {
- // 起始接口全名
- out << one_link.pSrcItem->m_infInfo->strFullName;
- // 终点接口全名
- out << one_link.pDstItem->m_infInfo->strFullName;
- // 连接模式
- out << one_link.linkMode;
- // 本Link在Scene中的坐标(用于还原Link线段)
- out << one_link.pLinkItem->getAllLinkLinePoints();
- }
- return true;
- }
- /// <summary>
- /// 读取Link信息
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadLinks(QDataStream& in)
- {
- // 首先读取Pou总数量
- int pouCount = 0;
- in >> pouCount;
- for (int i = 0; i < pouCount; i++)
- {
- // 读取本Pou的link数量
- int linkCount = 0;
- in >> linkCount;
- if (linkCount <= 0)
- {
- continue;
- }
- // 读取并恢复本Pou中的Link
- this->loadLink(in, linkCount);
- }
- return true;
- }
- /// <summary>
- /// 读取单组Pou中的Link信息
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadLink(QDataStream& in, const int& linkCount)
- {
- // 读入Pou名称
- QString pouName;
- in >> pouName;
- // 获取本Pou
- POU* pou = g_pPouManager->getPouByName(pouName);
- // Error
- if (pou == nullptr)
- {
- qDebug() << "[Error] Document::loadLink - can't find pou[" << pouName << "]";
- return false;
- }
- // 读取并恢复本Pou下的所有Link
- for (int i = 0; i < linkCount; i++)
- {
- DOC_LINK_INFO linkInfo;
- // 起始接口全名
- in >> linkInfo.strSrcInf;
- // 目的接口全名
- in >> linkInfo.strDesInf;
- // 连接模式
- in >> linkInfo.linkMode;
- // Link线段坐标
- in >> linkInfo.lines;
- // 通过Pou中的Scene重新建立Link
- pou->parentScene()->addLink(
- linkInfo.strSrcInf,
- linkInfo.strDesInf,
- linkInfo.linkMode,
- linkInfo.lines
- );
- }
- return true;
- }
- //========================================================
- //
- // Parallel
- //
- //========================================================
- /// <summary>
- /// 读取并行工具的配置信息
- /// </summary>
- /// <param name="in"></param>
- /// <param name="pNewTool"></param>
- /// <returns></returns>
- bool Document::loadParallelInfos(QDataStream& in, TOOL*& pNewTool)
- {
- Q_UNUSED(in);
- DOC_TOOL_INFO docTool;
- docTool.strPouName = pNewTool->strPouName;
- docTool.strToolInstanceName = pNewTool->strInstanceName;
- m_ParallelInfos.push_back(docTool);
- return true;
- }
- /// <summary>
- /// 还原并行工具相关信息(由于并行母线的长度需要所有的Tool和Link全部恢复之后才可以判定)
- /// </summary>
- void Document::restoreParallelInfos()
- {
- // 遍历所有的并行母线恢复信息
- for (auto parainfo: m_ParallelInfos)
- {
- // 首先找到这个工具所在Pou
- POU* pou = g_pPouManager->getPouByName(parainfo.strPouName);
- // 找到此工具对应的功能块
- WindowAppBlockParallel* pItem = qgraphicsitem_cast<WindowAppBlockParallel*>(pou->GetToolItem(parainfo.strToolInstanceName));
- // 刷新并行母线
- pItem->updateParallelLine();
- }
- }
- //========================================================
- //
- // Wait Tool
- //
- //========================================================
- /// <summary>
- /// 写入WaitTool的配置参数信息
- /// </summary>
- /// <param name="out"></param>
- /// <param name="pTool"></param>
- /// <returns></returns>
- bool Document::saveWaitToolSettings(QDataStream& out, POU* pou, TOOL*& pTool)
- {
- // WaitTool的设置 - 绑定的ToolEvent信息
- // 到TaskManager中查询ToolEvent信息
- ToolEvent* event = g_pTaskManager->getEventByTool(pTool);
- if (event != nullptr)
- {
- out << event->groupName();
- out << event->name();
- }
- else
- {
- out << "";
- out << "";
- }
- // 找到此Tool对应的功能块
- WindowAppBlockWait* pWaitBlock = qgraphicsitem_cast<WindowAppBlockWait*>(pou->GetToolItem(pTool->strInstanceName));
- // WaitTool的设置 - 单步执行时是否跳过等待
- out << pWaitBlock->m_bSkipWait;
- // WaitTool的设置 - 等待的超时时间
- out << pWaitBlock->m_nTimeout;
- // WaitTool的设置 - 等待的触发变量值
- out << pWaitBlock->m_WaitValue;
- return true;
- }
- /// <summary>
- /// 读取WaitTool的配置参数信息
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadWaitToolSettings(QDataStream& in, POU* pou, TOOL*& pNewTool)
- {
- QString groupName, name;
- in >> groupName;
- in >> name;
- // 如果确实绑定了Event,则此处重新到TaskManager注册一下
- if (!groupName.isEmpty() && !name.isEmpty())
- {
- // 首先检查是否是系统内置事件
- VARIABLE* var = g_pTaskManager->getSysEventByName(name);
- // 如果不是的话,再判断是否是某一个变量
- if (var == nullptr)
- {
- // 转换成对应的Variable
- var = g_pGvlManager->getVariableByName(groupName, name);
- // 校验是否有异常
- if (var == nullptr)
- {
- vDebug() << "[Error] Load event[" << groupName << "," << name << "] failed.";
- return false;
- }
- // 重新到TaskManager绑定此对应关系
- g_pTaskManager->registerToolEvent(var->eventTrigger, pNewTool);
- }
- }
- // 找到此Tool对应的功能块
- WindowAppBlockWait* pWaitBlock = qgraphicsitem_cast<WindowAppBlockWait*>(pou->GetToolItem(pNewTool->strInstanceName));
- // Error
- if (pWaitBlock == nullptr)
- {
- vDebug() << "WaitBlock is nullptr.";
- return false;
- }
- // WaitTool的设置 - 单步执行时是否跳过等待
- in >> pWaitBlock->m_bSkipWait;
- // WaitTool的设置 - 等待的超时时间
- in >> pWaitBlock->m_nTimeout;
- // WaitTool的设置 - 等待的触发变量值
- in >> pWaitBlock->m_WaitValue;
- return true;
- }
- //========================================================
- //
- // Tasks
- //
- //========================================================
- /// <summary>
- /// 保存Task区段
- /// </summary>
- /// <param name="out"></param>
- bool Document::saveTasks(QDataStream& out)
- {
- qDebug() << "Save [Tasks].";
- // 从公共区域获取所有的Task数据
- const QMap<QString, TASK*>& allTasks = g_pTaskManager->getAllTasks();
- // 写入Task总数量
- out << allTasks.size();
- // 遍历所有的Task信息
- QMapIterator<QString, TASK*> it(allTasks);
- while (it.hasNext())
- {
- // 获取Task
- const TASK* pTask = it.next().value();
- // 写入Task基本信息
- out << *pTask;
- // pous size
- out << pTask->pous.size();
- // pous
- QVectorIterator<POU*> it(pTask->pous);
- while (it.hasNext())
- {
- out << it.next()->pouName();
- }
- qDebug() << " Saved " << pTask->strName;
- }
- return true;
- }
- /// <summary>
- /// 读取Task区段
- /// </summary>
- /// <param name="in"></param>
- bool Document::loadTasks(QDataStream& in)
- {
- qDebug() << "Load [Tasks].";
- // 创建默认的Task Monitor View
- g_pResourceManager->addDefaultTaskMonitorNode(GROUP_NAME_TASKMONITOR);
- // 创建默认的LogView
- g_pResourceManager->addDefaultLogViewNode(GROUP_NAME_LOGVIEW);
- // 读入Task数量
- int nTask = 0;
- in >> nTask;
- // 循环读取所有Task信息
- for (int i = 0; i < nTask; i++)
- {
- // 读入Task名字
- QString strNewTaskName;
- in >> strNewTaskName;
- // 添加对应的节点,并且创建对应的Task视图
- WindowAppTaskView* pTaskView =
- qobject_cast<WindowAppTaskView*>(g_pResourceManager->addTaskNode(strNewTaskName, false));
- TASK* pNewTask = new TASK(strNewTaskName);
- // 读入Task基础信息
- in >> *pNewTask;
- // 2022-9-2,如果Task带有事件触发信息,则绑定一下事件
- if (pNewTask->modeType == TASK_MODE_TYPE::MODE_VAL && !pNewTask->strModeName.isEmpty())
- {
- pNewTask->bindEventByMode();
- }
- // 将用户输入的Task参数绑定到视图中
- pTaskView->addNewTask(pNewTask);
- // 继续读取Pou信息
- int nPouCount = 0;
- in >> nPouCount;
- QVector<POU*> taskPous;
- for (int j = 0; j < nPouCount; j++)
- {
- QString strPouName;
- in >> strPouName;
- taskPous.push_back(g_pPouManager->getPouByName(strPouName));
- }
- // 还原Pou信息到Task中
- pTaskView->addTaskPous(taskPous);
- }
- return true;
- }
- //========================================================
- //
- // SinglePou
- //
- //========================================================
- /// <summary>
- /// 导出整个Pou(pou、tool、link、variables)
- /// </summary>
- /// <param name="strPouFullPath"></param>
- /// <param name="strPouName"></param>
- /// <returns></returns>
- bool Document::saveSinglePou(const QString& strPouFullPath, const QString& strPouName)
- {
- // 建立存档文件
- QFile fileOut(strPouFullPath);
- if (!fileOut.open(QFile::WriteOnly | QFile::Truncate))
- {
- Utility::VPCriticalMessageBox(strPouFullPath + " create failed!");
- return false;
- }
- // 序列化对象
- QDataStream out(&fileOut);
- // 设置版本
- out.setVersion(QDataStream::Qt_5_14);
- // 保存单个Pou相关信息
- savePou(strPouName, out);
- // 保存本组局部变量
- saveGVL(strPouName, out);
- fileOut.close();
- Utility::VPInformationMessageBox("Serialized to " + strPouFullPath + " finished.");
- return true;
- }
- /// <summary>
- /// 导入单个Pou(pou、tool、link、variables)
- /// </summary>
- /// <param name="strPouFullPath"></param>
- /// <returns></returns>
- bool Document::loadSinglePou(const QString& strPouFullPath)
- {
- qDebug() << "Load file : " << strPouFullPath;
- // 打开存档文件
- QFile fileIn(strPouFullPath);
- if (!fileIn.open(QFile::ReadOnly))
- {
- Utility::VPCriticalMessageBox(strPouFullPath + " open failed!");
- return false;
- }
- // 序列化对象
- QDataStream in(&fileIn);
- // 设置版本
- in.setVersion(QDataStream::Qt_5_14);
- // 首先加载一下选择文档的Pou名字
- QString strLoadName;
- in >> strLoadName;
- int nPouSize = g_pPouManager->getAllPous().size();
- QString strPouName("Pou_" + QString::number(nPouSize));
- DialogNewPou dlgNewPou;
- dlgNewPou.setDefaultName(strPouName);
- int res = dlgNewPou.exec();
- if (res != QDialog::Accepted)
- {
- fileIn.close();
- return false;
- }
- // 使用新的POU名字
- strLoadName = dlgNewPou.m_strPouName + POU_POSTFIX;
-
- // 读取Pou相关数据信息(不需要再次读取名字了)
- bool state = loadPou(in, strLoadName, false);
- if (!state)
- {
- vWarning() << "Load Pou Error" << strLoadName;
- return false;
- }
- // 读取本Pou的局部变量
- this->loadGVL(in, strLoadName, false);
- // 还原Port绑定关系
- this->restorePortBindInfo();
- // 还原Goto绑定关系
- this->restoreGotoBindInfo();
- //// 还原Link信息
- //this->restoreLinks();
- // 还原Parallel工具信息
- this->restoreParallelInfos();
- Utility::VPInformationMessageBox("Deserialized from " + strPouFullPath + " finished.");
- fileIn.close();
- return true;
- }
- /// <summary>
- /// 单个Pou重置(包括页面和数据结构)
- /// </summary>
- void Document::pouReset(const QString& strPouName)
- {
- qDebug() << "[Document] Reset pou - " << strPouName;
- // 重置Pou信息
- g_pPouManager->RemovePou(strPouName);
- // 重置Variable
- g_pGvlManager->removeGvl(strPouName);
- // 清除对应的子页面
- VPGlobal::getMdiFrame()->deleteSubView(strPouName);
- // 清除临时数据结构(link、port info、Goto)
- // m_Links.clear();
- m_PortBindInfos.clear();
- m_GotoBindInfos.clear();
- m_ParallelInfos.clear();
- }
- //========================================================
- //
- // UI
- //
- //========================================================
- /// <summary>
- /// 写入UI区段
- /// </summary>
- /// <param name="out"></param>
- /// <returns></returns>
- bool Document::saveUIs(QDataStream& out)
- {
- qDebug() << "Save [UIs].";
- g_pUiManager->serialized(out);
- return true;
- }
- /// <summary>
- /// 读取UI区段
- /// </summary>
- /// <param name="in"></param>
- /// <returns></returns>
- bool Document::loadUIs(QDataStream& in)
- {
- qDebug() << "Load [UIs].";
- // g_pUiManager->deserialized(in);
- // 读入UI的数量
- int nUI = 0;
- in >> nUI;
- for (int i = 0; i < nUI; i++)
- {
- // 读入UI名字
- QString strNewUiName;
- in >> strNewUiName;
- // 添加对应的节点,并且创建对应的UI视图
- WindowAppUiFrame* pUiFrame =
- qobject_cast<WindowAppUiFrame*>(g_pResourceManager->addUiNode(strNewUiName, false, true));
- // 进行 WindowAppUiView* 的序列化
- in >> pUiFrame->getUiView();
- }
- // 只有ui数量大于 0 的时候,才发布页面
- if ( nUI>0 )
- {
- // 通过Manager发布所有UI
- bool bRet = g_pUiManager->publishAll();
- if (bRet)
- {
- }
- }
-
- return true;
- }
- //========================================================
- //
- // Compress
- //
- //========================================================
- /// <summary>
- /// 压缩
- /// </summary>
- /// <returns></returns>
- bool Document::compress(QString strPath)
- {
- QString strTmpPath = strPath;
- // 生成正式的文件名
- strPath = strPath.left(strPath.length() - TMP_POSTFIX.length());
- strPath += DOC_POSTFIX;
- QByteArray bufferDoc;
- QByteArray bufferHdw;
- // 打包后的数据缓冲区
- QByteArray buffer;
- // 读取工程文件
- {
- QFile fileTmp(strTmpPath);
- fileTmp.open(QIODevice::ReadOnly);
- qint64 docLength = fileTmp.size();
- bufferDoc = fileTmp.read(docLength);
- fileTmp.close();
- qDebug() << "Doc 压缩前字节大小:" << bufferDoc.size();
- }
-
- // 读取硬件组态文件
- {
- QFileInfo fileInfo(DOC_HARDWARE_FULLPATH);
- if (fileInfo.exists() != true)
- {
- saveHdw(DOC_HARDWARE_FULLPATH);
- }
- QFile fileTmp(DOC_HARDWARE_FULLPATH);
- fileTmp.open(QIODevice::ReadOnly);
- qint64 docLength = fileTmp.size();
- bufferHdw = fileTmp.read(docLength);
- fileTmp.close();
- qDebug() << "Hdw 压缩前字节大小:" << bufferDoc.size();
- }
- QString strDocMD5 = QCryptographicHash::hash(bufferDoc, QCryptographicHash::Md5).toHex().toUpper();
- QString strHdwMD5 = QCryptographicHash::hash(bufferHdw, QCryptographicHash::Md5).toHex().toUpper();
- QBuffer bufferTmp;
- bufferTmp.open(QIODevice::WriteOnly);
- QDataStream ar(&bufferTmp);
- ar.setVersion(QDataStream::Qt_5_14);
- int paranum = 5;//参数数量
- ar << paranum;//先保存参数数量
- ar << (int)1 << (int)DOC_MINOR_VERSION;
- ar << (int)2 << strDocMD5;
- ar << (int)3 << strHdwMD5;
- ar << (int)4 << bufferDoc;
- ar << (int)5 << bufferHdw;
-
- // 压缩文件数据(第二个参数为压缩级别,0 - 9)
- buffer = qCompress(bufferTmp.buffer() , 5);
- qDebug() << "压缩后字节大小:" << buffer.size();
- // 保存文件
- QFile fileSave(strPath);
- fileSave.open(QIODevice::WriteOnly);
- fileSave.write(buffer);
- fileSave.close();
- // 释放资源
- bufferTmp.close();
- // 删除临时文件
- QFile::remove(strTmpPath);
- return true;
- }
- /// <summary>
- /// 解压缩
- /// </summary>
- /// <returns></returns>
- bool Document::uncompress(QString& strPath)
- {
- QString saveFileName = strPath;
- // 生成解压后的临时文件名,按照临时文件名进行读取
- strPath = strPath.left(strPath.length() - DOC_POSTFIX.length());
- strPath += TMP_POSTFIX;
- // 读取文件
- QFile fileTmp(saveFileName);
- fileTmp.open(QIODevice::ReadOnly);
- qint64 docLength = fileTmp.size();
- QByteArray buffer = fileTmp.read(docLength);
- fileTmp.close();
- QByteArray bufferDoc;
- QByteArray bufferHdw;
- int nVersion= 0;
- QString strLoadDocMD5;
- QString strLoadHdwMD5;
- // 解压缩
- buffer = qUncompress(buffer);
- QDataStream ar(buffer);
- ar.setVersion(QDataStream::Qt_5_14);
- int para = 0;
- int paranum = 0;
- ar >> paranum;//读取参数数量
- if (paranum == 5)
- {
- for (int i = 0; i < paranum; i++)
- {
- ar >> para;
- switch (para)
- {
- case 1: ar >> nVersion; break;
- case 2: ar >> strLoadDocMD5; break;
- case 3: ar >> strLoadHdwMD5; break;
- case 4: ar >> bufferDoc; break;
- case 5: ar >> bufferHdw; break;
- default:
- {
- vWarning() << "Serialized(In) Error";
- return false;
- }
- break;
- }
- }
- QString strDocMD5 = QCryptographicHash::hash(bufferDoc, QCryptographicHash::Md5).toHex().toUpper();
- QString strHdwMD5 = QCryptographicHash::hash(bufferHdw, QCryptographicHash::Md5).toHex().toUpper();
- if (strLoadDocMD5 != strDocMD5)
- {
- return false;
- }
- if (strLoadHdwMD5 != strLoadHdwMD5)
- {
- return false;
- }
- // 将buffer 存起来
- m_bufferHdw = bufferHdw;
- }
- else
- {
- bufferDoc = buffer;
- }
- // 写入临时文件
- QFile fileSave(strPath);
- fileSave.open(QIODevice::WriteOnly);
- fileSave.write(bufferDoc);
- fileSave.close();
- return true;
- }
- //========================================================
- //
- // Other
- //
- //========================================================
- /// <summary>
- /// 2022-3-25 检查接口是否还有效(防止Port端绑定对象无效后,依旧链接的问题)
- /// </summary>
- /// <param name="infFullName"></param>
- /// <returns></returns>
- bool Document::checkInfValid(const QString& infGroupName, const QString& infFullName)
- {
- POU* pou = g_pPouManager->getPouByName(infGroupName);
- if (pou == nullptr)
- {
- return false;
- }
-
- _INTERFACE* pInf = pInf = pou->GetInterface(infFullName);
- if (pInf == nullptr)
- {
- return false;
- }
- // 如果类型无效,则说明是Port接口并且尚未绑定接口
- if (pInf->Type == INF_TYPE::INF_TYPE_UNKNOWN)
- {
- return false;
- }
- //// 如果是Port类型,并且绑定信息无效了,则返回false
- //if (pInf->parent()->Type == TOOL_TYPE::TOOL_TYPE_PORT_INPUT
- // || pInf->parent()->Type == TOOL_TYPE::TOOL_TYPE_PORT_OUTPUT
- // )
- //{
- // if (pInf->pBindInterface == nullptr)
- // {
- // return false;
- // }
- //}
- return true;
- }
- /// <summary>
- /// 检查硬件组态与文档是否匹配
- /// </summary>
- /// <param name="strHardwareID"></param>
- /// <param name="strDocID"></param>
- /// <returns></returns>
- bool Document::checkHWAndDocConfigID(QString strDocID, QString strHardwareID)
- {
- // 只有当前硬件配置的ID 与 文档 ID 相匹配,才继续加载文档
- bool bLoadHdw = false;
- QStringList value = strDocID.split("|");
- for (int i=0; i< value.size(); i++)
- {
- QString str = value[i];
- if (strHardwareID.indexOf(str) == -1)
- {
- bLoadHdw = true;
- continue;
- }
- }
- if (bLoadHdw == true)
- {
- if (m_bufferHdw.size() == 0)
- {
- return true;
- }
- // TODO:需要引导用户从备份的文件中释放硬件组态文件,并加载释放的文件
- m_bufferHdw;
- DOC_HARDWARE_FULLPATH;
- {
- // 写入临时文件
- QFile fileSave(DOC_HARDWARE_FULLPATH);
- fileSave.open(QIODevice::WriteOnly);
- fileSave.write(m_bufferHdw);
- fileSave.close();
- // 重新加载
- loadHdw(DOC_HARDWARE_FULLPATH);
- }
- }
- return true;
- }
- /// <summary>
- /// 根据硬件组态的工具实例名有工具名字生成一个ID。此ID后面会保存进硬件组态的数据中
- /// </summary>
- /// <returns></returns>
- QString Document::getHWAndDocConfigID()
- {
- QString strID;
- POU* pHdPou = g_pPouManager->getPouByName(GROUP_NAME_HARDWARE);
- if (pHdPou != nullptr)
- {
- QMap<QString, TOOL*> allTools = pHdPou->GetAllTools();
- QMapIterator<QString, TOOL*> i(allTools);
- while (i.hasNext())
- {
- const TOOL* pTool = i.next().value();
- strID.append(pTool->strName);
- strID.append(".");
- strID.append(pTool->strInstanceName);
- strID.append("|");
- }
- strID.chop(1);
- }
- return strID;
- }
|