Document.cpp 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095
  1. #include "Document.h"
  2. #include "VPGlobal.h"
  3. #include "GvlManager.h"
  4. #include "PouManager.h"
  5. #include "TaskManager.h"
  6. #include "UiManager.h"
  7. #include "WindowAppBlockPort.h"
  8. #include "WindowAppBlockGoto.h"
  9. #include "WindowAppBlockParallel.h"
  10. #include "WindowAppBlockWait.h"
  11. #include "WindowAppResourceManagerTree.h"
  12. #include "WindowAppGvlView.h"
  13. #include "WindowAppPouFrame.h"
  14. #include "WindowAppTaskView.h"
  15. #include "WindowAppMdiFrame.h"
  16. #include "WindowAppUiFrame.h"
  17. #include "WindowAppBlockParallel.h"
  18. #include "WindowAppItemLink.h"
  19. #include "WindowAppItemInterface.h"
  20. #include "WindowAppPouScene.h"
  21. #include "DialogNewPou.h"
  22. #include "ToolDepository.h"
  23. #include "Preferences.h"
  24. extern ToolDepository toolDepository;
  25. // 存档文件的主版本(主版本号不同代表不能兼容)
  26. #define DOC_MAJOR_VERSION 3
  27. // 存档文件的次版本(仅次版本号不同则可以兼容)
  28. #define DOC_MINOR_VERSION 104
  29. // 硬件组态文件的主版本(主版本号不同代表不能兼容)
  30. #define DOC_HW_MAJOR_VERSION 3
  31. // 硬件组态文件的次版本(仅次版本号不同则可以兼容)
  32. #define DOC_HW_MINOR_VERSION 102
  33. /*
  34. 需要额外特殊处理的几种类型
  35. (1) 系统变量:不参与序列化,但是每次重置时需要恢复到默认值,并且程序启动时无论创建项目与否都自动建立变量;
  36. (2) Pou内部变量:不参与序列化,重置时参数恢复默认值,随Pou创建时自动创建,随Pou删除时删除;
  37. (3) 任务监视窗体:不参与序列化,重置时参数恢复默认值并清空界面,并且在删除全部窗体时不删除此窗体;
  38. (4) 日志信息窗体:不参与序列化,重置时参数恢复默认值并清空界面,并且在删除全部窗体时不删除此窗体;
  39. (5) 硬件组态:进行独立序列化(固定名称文件),重置时参数恢复默认值,并且在删除全部窗体时不删除此窗体;
  40. */
  41. /// <summary>
  42. /// 序列化 PORT_BIND_INFO
  43. /// </summary>
  44. /// <returns></returns>
  45. QDataStream& operator<<(QDataStream& out, const _tagDocBindToolInfo& info)
  46. {
  47. out << info.strSrcPou;
  48. out << info.strSourceTool;
  49. out << info.strDestPou;
  50. out << info.strDestInf;
  51. out << info.infType;
  52. return out;
  53. }
  54. /// <summary>
  55. /// 反序列化 PORT_BIND_INFO
  56. /// </summary>
  57. /// <param name="in"></param>
  58. /// <param name="w"></param>
  59. /// <returns></returns>
  60. QDataStream& operator>>(QDataStream& in, _tagDocBindToolInfo& info)
  61. {
  62. in >> info.strSrcPou;
  63. in >> info.strSourceTool;
  64. in >> info.strDestPou;
  65. in >> info.strDestInf;
  66. in >> info.infType;
  67. return in;
  68. }
  69. Document::Document()
  70. {
  71. VPGlobal::m_pDoc = this;
  72. }
  73. Document::~Document()
  74. {
  75. }
  76. /// <summary>
  77. /// 执行存档文件保存
  78. /// </summary>
  79. /// <returns></returns>
  80. bool Document::Save(const QString& strFullPath)
  81. {
  82. qDebug() << "[Documents] Document save.";
  83. // 根据用户选定的路径生成临时文件名,等待压缩之后形成正式的存档文件
  84. QString strSaveFullPath = strFullPath.left(strFullPath.length() - DOC_POSTFIX.length());
  85. strSaveFullPath += TMP_POSTFIX;
  86. // 建立存档文件
  87. QFile fileOut(strSaveFullPath);
  88. if (!fileOut.open(QFile::WriteOnly | QFile::Truncate))
  89. {
  90. Utility::VPCriticalMessageBox(strSaveFullPath + " create failed!");
  91. return false;
  92. }
  93. // 创建序列化对象
  94. QDataStream out(&fileOut);
  95. // 设置版本
  96. out.setVersion(QDataStream::Qt_5_14);
  97. // 写入当前版本号
  98. saveVersion(out, DOC_MAJOR_VERSION, DOC_MINOR_VERSION);
  99. // 写入系统全局配置区段
  100. saveConfig(out);
  101. out << (QString)"saveConfig " + LOAD_DOC_KEYWORDS;
  102. // 写入全局和局部变量区段
  103. saveVariables(out);
  104. out << (QString)"saveVariables " + LOAD_DOC_KEYWORDS;
  105. // 写入POU区段
  106. savePous(out);
  107. out << (QString)"savePous " + LOAD_DOC_KEYWORDS;
  108. // 写入Link区段
  109. saveLinks(out);
  110. out << (QString)"saveLinks " + LOAD_DOC_KEYWORDS;
  111. // 保存Task区段
  112. saveTasks(out);
  113. out << (QString)"saveTasks " + LOAD_DOC_KEYWORDS;
  114. // 保存UI区段
  115. saveUIs(out);
  116. out << (QString)"saveUIs " + LOAD_DOC_KEYWORDS;
  117. //// 写入硬件区段
  118. //saveHardwares(out);
  119. // 关闭文件
  120. fileOut.close();
  121. qDebug() << ("[Document] Serialized to " + strSaveFullPath + " finished.");
  122. // 执行压缩
  123. compress(strSaveFullPath);
  124. qDebug() << ("[Document] Comressed to " + strSaveFullPath + " finished.");
  125. Utility::VPInformationMessageBox("Serialized to " + strSaveFullPath + " finished. DocVersion: " + QString::number(thePrefs.m_nDocVersion));
  126. return true;
  127. }
  128. /// <summary>
  129. /// 2022-2-24,执行硬件组态数据保存
  130. /// </summary>
  131. /// <param name="strFullPath"></param>
  132. /// <returns></returns>
  133. bool Document::saveHdw(const QString& strFullPath)
  134. {
  135. qDebug() << "[Documents] Document harware save.";
  136. QFileInfo FileInfo(strFullPath);
  137. // 建立存档文件
  138. QFile fileOut(strFullPath);
  139. if (!fileOut.open(QFile::WriteOnly | QFile::Truncate))
  140. {
  141. Utility::VPCriticalMessageBox(strFullPath + " create failed!");
  142. return false;
  143. }
  144. // 创建序列化对象
  145. QDataStream out(&fileOut);
  146. // 设置版本
  147. out.setVersion(QDataStream::Qt_5_14);
  148. // 写入硬件组态文件版本号
  149. saveHdwVersion(out, DOC_HW_MAJOR_VERSION, DOC_HW_MINOR_VERSION);
  150. if (thePrefs.m_strHdwConfigID.isEmpty())
  151. {
  152. thePrefs.m_strHdwConfigID = "123456789";
  153. }
  154. out << thePrefs.m_strHdwConfigID;
  155. // 保存硬件组态Pou相关信息
  156. savePou(GROUP_NAME_HARDWARE, out);
  157. out << (QString)"savePou " + LOAD_DOC_KEYWORDS;
  158. // 保存硬件组态局部变量
  159. saveGVL(GROUP_NAME_HARDWARE, out);
  160. out << (QString)"saveGVL " + LOAD_DOC_KEYWORDS;
  161. fileOut.close();
  162. qDebug() << ("[Document] Serialized hardware to " + strFullPath + " finished. DocVersion: " + QString::number(thePrefs.m_nDocVersion));
  163. return true;
  164. }
  165. /// <summary>
  166. /// 整个系统重置(包括界面和UI)
  167. /// </summary>
  168. void Document::systemReset()
  169. {
  170. qDebug() << "[Document] System reset.";
  171. // 先重置所有的数据结构
  172. g_pGvlManager->reset();
  173. // 重置树状结构和子页面
  174. g_pResourceManager->reset();
  175. // 重置Task数据结构
  176. g_pTaskManager->reset();
  177. //// 重置硬件页面
  178. //VPGlobal::getWindowHdw()->reset();
  179. // 重置所有的Pou数据结构
  180. g_pPouManager->resetAllPous();
  181. // 重置所有UI窗体
  182. g_pUiManager->reset();
  183. //// 重置Link信息
  184. //m_Links.clear();
  185. // 重置Port绑定信息
  186. m_PortBindInfos.clear();
  187. // 重置Goto绑定信息
  188. m_GotoBindInfos.clear();
  189. // 重置Para绑定信息
  190. m_ParallelInfos.clear();
  191. }
  192. /// <summary>
  193. /// 执行存档文件加载
  194. /// </summary>
  195. /// <returns></returns>
  196. bool Document::Load(const QString& strFullPath)
  197. {
  198. qDebug() << "[Document] Load file : " << strFullPath;
  199. QString strLoadFullPath = strFullPath;
  200. // 解压缩
  201. if (! uncompress(strLoadFullPath))
  202. {
  203. return false;
  204. }
  205. // 打开存档文件
  206. QFile fileIn(strLoadFullPath);
  207. if (!fileIn.open(QFile::ReadOnly))
  208. {
  209. // Utility::VPCriticalMessageBox(strLoadFullPath + " open failed!");
  210. return false;
  211. }
  212. // 序列化对象
  213. QDataStream in(&fileIn);
  214. // 设置版本
  215. in.setVersion(QDataStream::Qt_5_14);
  216. // 读取文档版本号
  217. bool bRet = loadAndCheckVersion(in, DOC_MAJOR_VERSION, DOC_MINOR_VERSION);
  218. // 如果版本号有问题则不读取
  219. if (!bRet)
  220. {
  221. Utility::VPCriticalMessageBox("The document version is incompatible!");
  222. return false;
  223. }
  224. QString strInfo;
  225. // 首先重置系统环境,准备加载新的数据
  226. this->systemReset();
  227. // 读取配置信息
  228. if (! this->loadConfig(in))
  229. {
  230. fileIn.close();
  231. return false;
  232. }
  233. // 检查硬件组态的配置ID与 文档中存储的配置ID是否匹配
  234. thePrefs.m_strHdwConfigID = getHWAndDocConfigID();
  235. if (! checkHWAndDocConfigID(m_strHdwConfigID, thePrefs.m_strHdwConfigID))
  236. {
  237. fileIn.close();
  238. return false;
  239. }
  240. in >> strInfo;
  241. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  242. {
  243. vWarning() << "loadVariables Error";
  244. return false;
  245. }
  246. // 读取全局和局部变量区段
  247. this->loadVariables(in);
  248. in >> strInfo;
  249. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  250. {
  251. vWarning() << "loadVariables Error";
  252. return false;
  253. }
  254. // 读取Pou区段
  255. this->loadPous(in);
  256. in >> strInfo;
  257. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  258. {
  259. vWarning() << "loadPous Error";
  260. return false;
  261. }
  262. // 读取Link区段
  263. this->loadLinks(in);
  264. in >> strInfo;
  265. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  266. {
  267. vWarning() << "loadLinks Error";
  268. return false;
  269. }
  270. // 读取Task区段
  271. this->loadTasks(in);
  272. in >> strInfo;
  273. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  274. {
  275. vWarning() << "loadTasks Error";
  276. return false;
  277. }
  278. // 读取UI区段
  279. this->loadUIs(in);
  280. in >> strInfo;
  281. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  282. {
  283. vWarning() << "loadUIs Error";
  284. return false;
  285. }
  286. // 至此所有的数据都已经读取完毕,开始执行还原工作
  287. fileIn.close();
  288. // 还原Port绑定关系
  289. this->restorePortBindInfo();
  290. // 还原Goto绑定关系
  291. this->restoreGotoBindInfo();
  292. //// 还原Link信息
  293. //this->restoreLinks();
  294. // 还原ParallelTool相关信息
  295. this->restoreParallelInfos();
  296. // 读取完毕后,删除此临时文件
  297. QFile::remove(strLoadFullPath);
  298. Utility::VPInformationMessageBox("Deserialized from " + strFullPath + " finished. DocVersion: " + QString::number(thePrefs.m_nDocVersion) );
  299. return true;
  300. }
  301. /// <summary>
  302. /// 2022-2-24增加,加载硬件组态存档数据
  303. /// </summary>
  304. /// <param name="strFullPath"></param>
  305. /// <returns></returns>
  306. bool Document::loadHdw(const QString& strFullPath)
  307. {
  308. qDebug() << "[Document] Load hardware file : " << strFullPath;
  309. // 打开存档文件
  310. QFile fileIn(strFullPath);
  311. if (!fileIn.open(QFile::ReadOnly))
  312. {
  313. // Utility::VPCriticalMessageBox(strFullPath + " open failed!");
  314. qDebug() << "[Error] Document::loadHdw - load[" << strFullPath << "] failed.";
  315. return false;
  316. }
  317. // 序列化对象
  318. QDataStream in(&fileIn);
  319. // 设置版本
  320. in.setVersion(QDataStream::Qt_5_14);
  321. // 读取文档版本号
  322. bool bRet = loadAndCheckHdwVersion(in, DOC_HW_MAJOR_VERSION, DOC_HW_MINOR_VERSION);
  323. // 如果版本号有问题则不读取
  324. if (!bRet)
  325. {
  326. Utility::VPCriticalMessageBox("The hardware document version is incompatible!");
  327. return false;
  328. }
  329. // 旧版本的系统,不能加载配置文件ID
  330. if (thePrefs.m_nHdwVersion != 0)
  331. {
  332. in >> thePrefs.m_strHdwConfigID;
  333. }
  334. // 首先应该清理硬件组态的所有数据
  335. {
  336. POU* pHdPou = g_pPouManager->getPouByName(GROUP_NAME_HARDWARE);
  337. if (pHdPou)
  338. {
  339. pHdPou->reset();
  340. }
  341. }
  342. QString strInfo;
  343. // 加载硬件组态
  344. loadPou(in, GROUP_NAME_HARDWARE);
  345. in >> strInfo;
  346. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  347. {
  348. vWarning() << "load Hdw Pou Error";
  349. return false;
  350. }
  351. // 加载硬件组态局部变量
  352. loadGVL(in, GROUP_NAME_HARDWARE);
  353. in >> (QString&)strInfo;
  354. if (strInfo.indexOf(LOAD_DOC_KEYWORDS) == -1)
  355. {
  356. vWarning() << "load Hdw GVL Error";
  357. return false;
  358. }
  359. fileIn.close();
  360. return true;
  361. }
  362. //========================================================
  363. //
  364. // Version
  365. //
  366. //========================================================
  367. /// <summary>
  368. /// 写入当前版本号
  369. /// </summary>
  370. /// <returns></returns>
  371. bool Document::saveVersion(QDataStream& out, int major, int minor)
  372. {
  373. qDebug() << "[Documents] Save [Version]: " + QString::number(major) + "." + QString::number(minor);
  374. out << major;
  375. out << minor;
  376. // 设置文档的版本号
  377. thePrefs.m_nDocVersion = minor;
  378. int paranum;//参数数量
  379. {
  380. paranum = 1;
  381. out << paranum;//先保存参数数量
  382. out << (int)1 << thePrefs.m_nDocVersion;
  383. }
  384. return true;
  385. }
  386. /// <summary>
  387. /// 写入当前版本号
  388. /// </summary>
  389. /// <returns></returns>
  390. bool Document::saveHdwVersion(QDataStream& out, int major, int minor)
  391. {
  392. qDebug() << "[Documents] Save [Version]: " + QString::number(major) + "." + QString::number(minor);
  393. out << major;
  394. out << minor;
  395. // 设置文档的版本号
  396. thePrefs.m_nHdwVersion = minor;
  397. int paranum;//参数数量
  398. {
  399. paranum = 1;
  400. out << paranum;//先保存参数数量
  401. out << (int)1 << thePrefs.m_nHdwVersion;
  402. }
  403. return true;
  404. }
  405. /// <summary>
  406. /// 加载当前版本号
  407. /// </summary>
  408. /// <param name="in"></param>
  409. /// <returns></returns>
  410. bool Document::loadAndCheckVersion(QDataStream& in, int major, int minor)
  411. {
  412. int nMajorVersion = 0, nMinorVersion = 0;
  413. in >> nMajorVersion;
  414. in >> nMinorVersion;
  415. int nDocVersion = 0;
  416. if (nMinorVersion > 0)
  417. {
  418. int paranum = 0;
  419. int para = 0;
  420. in >> paranum;//读取参数数量
  421. for (int i = 0; i < paranum; i++)
  422. {
  423. in >> para;
  424. switch (para)
  425. {
  426. case 1: in >> nDocVersion; break;
  427. default:
  428. {
  429. vWarning() << "Serialized(In) Error";
  430. return false;
  431. }
  432. break;
  433. }
  434. }
  435. }
  436. thePrefs.m_nDocVersion = nDocVersion;
  437. // 比较大版本号是否一致
  438. if (nMajorVersion != major)
  439. {
  440. QString strDocVer = QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
  441. QString strExeVer = QString::number(major) + "." + QString::number(minor);
  442. Utility::VPCriticalMessageBox("Incompatible document version: [exe]" + strDocVer + " " + "[Doc]" + strExeVer);
  443. return false;
  444. }
  445. qDebug() << "[Documents] Load [Version]: " + QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
  446. return true;
  447. }
  448. /// <summary>
  449. /// 加载当前版本号
  450. /// </summary>
  451. /// <param name="in"></param>
  452. /// <returns></returns>
  453. bool Document::loadAndCheckHdwVersion(QDataStream& in, int major, int minor)
  454. {
  455. int nMajorVersion = 0, nMinorVersion = 0;
  456. in >> nMajorVersion;
  457. in >> nMinorVersion;
  458. int nHdwVersion = 0;
  459. if (nMinorVersion > 0)
  460. {
  461. int paranum = 0;
  462. int para = 0;
  463. in >> paranum;//读取参数数量
  464. for (int i = 0; i < paranum; i++)
  465. {
  466. in >> para;
  467. switch (para)
  468. {
  469. case 1: in >> nHdwVersion; break;
  470. default:
  471. {
  472. vWarning() << "Serialized(In) Error";
  473. return false;
  474. }
  475. break;
  476. }
  477. }
  478. }
  479. thePrefs.m_nHdwVersion = nHdwVersion;
  480. // 比较大版本号是否一致
  481. if (nMajorVersion != major)
  482. {
  483. QString strDocVer = QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
  484. QString strExeVer = QString::number(major) + "." + QString::number(minor);
  485. Utility::VPCriticalMessageBox("[Hdw] Incompatible document version: [exe]" + strDocVer + " " + "[Doc]" + strExeVer);
  486. return false;
  487. }
  488. qDebug() << "[Hdw] Load [Version]: " + QString::number(nMajorVersion) + "." + QString::number(nMinorVersion);
  489. return true;
  490. }
  491. //========================================================
  492. //
  493. // Config
  494. //
  495. //========================================================
  496. /// <summary>
  497. /// 写入系统全局配置区段
  498. /// </summary>
  499. /// <returns></returns>
  500. bool Document::saveConfig(QDataStream& out)
  501. {
  502. int paranum = 1;
  503. thePrefs.m_strHdwConfigID = getHWAndDocConfigID();
  504. //先保存参数数量
  505. out << paranum;
  506. // 硬件ConfigID
  507. out << 1 << thePrefs.m_strHdwConfigID;
  508. return true;
  509. }
  510. /// <summary>
  511. /// 读取系统全局配置区段
  512. /// </summary>
  513. /// <param name="in"></param>
  514. /// <returns></returns>
  515. bool Document::loadConfig(QDataStream& in)
  516. {
  517. // 旧版本的系统,不能加载配置文件
  518. if (thePrefs.m_nDocVersion == 0)
  519. {
  520. return true;
  521. }
  522. int paranum = 0;
  523. int para = 0;
  524. // 首先读取参数数量
  525. in >> paranum;
  526. for (int i = 0; i < paranum; i++)
  527. {
  528. in >> para;
  529. switch (para)
  530. {
  531. case 1: in >> m_strHdwConfigID; break;
  532. default:
  533. {
  534. vWarning() << "Serialized(In) Error";
  535. return false;
  536. }
  537. break;
  538. }
  539. }
  540. return true;
  541. }
  542. //========================================================
  543. //
  544. // Variables
  545. //
  546. //========================================================
  547. /// <summary>
  548. /// 写入全局和局部变量区段
  549. /// </summary>
  550. /// <returns></returns>
  551. bool Document::saveVariables(QDataStream& out)
  552. {
  553. qDebug() << "[Documents] Save GVLs...";
  554. //// 遍历所有变量进行储存
  555. //QHash<QString, GVL*>* pAllVariables = g_pVariablesManager->getAllGvls();
  556. //// 写入总数量
  557. //out << pAllVariables->size();
  558. // 2022-2-22,这里需要跳过全局变量分组以及硬件分组
  559. QList<GVL*> AllGvls = g_pGvlManager->getAllSerializedGvls();
  560. // 写入总数量
  561. out << AllGvls.size();
  562. QListIterator<GVL*> it(AllGvls);
  563. while (it.hasNext())
  564. {
  565. saveGVL(it.next()->strName, out);
  566. }
  567. return true;
  568. }
  569. /// <summary>
  570. /// 写入单组变量
  571. /// </summary>
  572. /// <param name="strVarName"></param>
  573. /// <param name="out"></param>
  574. /// <returns></returns>
  575. bool Document::saveGVL(const QString strGroupName, QDataStream& out)
  576. {
  577. const GVL* pGvl = g_pGvlManager->getGvl(strGroupName);
  578. if (pGvl == nullptr)
  579. {
  580. qDebug() << "[Documents] Gvl[" << strGroupName << "] hasn't any variable.";
  581. out << 0;
  582. return false;
  583. }
  584. else
  585. {
  586. out << 1;
  587. }
  588. int nParanum = 4;//参数数量
  589. out << nParanum;//先保存参数数量
  590. out << nParanum;//此处写两次,用来后面做数据校验
  591. out << (int)1 << pGvl->Type;
  592. out << (int)2 << pGvl->strName;
  593. out << (int)3 << pGvl->gvlMode;
  594. out << (int)4 << pGvl->strHdwInstName;
  595. // 继续保存其中变量
  596. const VARIABLES& vars = pGvl->Variables;
  597. // 以 bShow 为标记为,判断内部变量,并排除掉
  598. int nSize = 0;
  599. for (int i = 0; i < vars.size(); i++)
  600. {
  601. if (vars[i]->bShow == true)
  602. {
  603. nSize++;
  604. }
  605. }
  606. // 写入变量数量
  607. out << nSize;
  608. //// 2022-2-22修改,只保存序列化的变量
  609. //const VARIABLES& vars = g_pGvlManager->getSerializedVariablesByGroup(pGvl->strName);
  610. //// 写入变量数量
  611. //out << vars.size();
  612. // 写入变量细节
  613. for (const VARIABLE* var : vars)
  614. {
  615. if (var->bShow)
  616. {
  617. this->saveInterface(out, var);
  618. // 2022-9-2 增加,保存变量的触发状态
  619. if (var->eventTrigger != nullptr)
  620. {
  621. out << 1;
  622. }
  623. else
  624. {
  625. out << 0;
  626. }
  627. }
  628. }
  629. qDebug() << "[Documents] Saved GVL Group[" << pGvl->strName << "]: " << nSize << " counts.";
  630. return true;
  631. }
  632. /// <summary>
  633. /// 读取全局和局部变量区段
  634. /// </summary>
  635. /// <param name="in"></param>
  636. /// <returns></returns>
  637. bool Document::loadVariables(QDataStream& in)
  638. {
  639. qDebug() << "[Documents] Load GVLs...";
  640. // 读入分组个数
  641. int nGroup = 0;
  642. in >> nGroup;
  643. // 循环读取所有变量分组
  644. for (int i = 0; i < nGroup; i++)
  645. {
  646. // 逐一读取每一个变量组
  647. loadGVL(in);
  648. }
  649. return true;
  650. }
  651. /// <summary>
  652. /// 读取单组的变量信息
  653. /// </summary>
  654. /// <param name="in"></param>
  655. /// <returns></returns>
  656. bool Document::loadGVL(QDataStream& in, const QString& strLoadName, bool bLoadName)
  657. {
  658. // 首先获取本Group是否有局部变量信息
  659. int nContinue = 0;
  660. in >> nContinue;
  661. if (nContinue == 0)
  662. {
  663. return true;
  664. }
  665. // 变量分组名称
  666. QString strGroupName;
  667. QString strHdwInstName;
  668. // 变量类型
  669. TOOL_TYPE type = TOOL_TYPE::TOOL_TYPE_STANDARD;
  670. GVL_MODE gvlType = GVL_MODE::GVL_BASIC;
  671. int nPara = 0;
  672. int nParanum = 0;
  673. in >> nParanum;//读取参数数量
  674. // 此处的校验值
  675. int nCheck = 0;
  676. in >> nCheck;//读取校验参数
  677. int nMaxParanum = 4;// 该参数的最大数量(需要根据参数的数量来调整,用来校验)
  678. if (nParanum < 0 || nParanum != nCheck || nParanum > nMaxParanum)
  679. {
  680. return false;
  681. }
  682. for (int i = 0; i < nParanum; i++)
  683. {
  684. in >> nPara;
  685. switch (nPara)
  686. {
  687. case 1: in >> type; break;
  688. case 2: in >> strGroupName; break;
  689. case 3: in >> gvlType; break;
  690. case 4: in >> strHdwInstName; break;
  691. default:
  692. {
  693. vWarning() << "GVL Serialized(In) Error";
  694. }
  695. break;
  696. }
  697. }
  698. if (!bLoadName)
  699. {
  700. strGroupName = strLoadName;
  701. }
  702. // 根据不同的类型添加不同的页面
  703. QWidget* pNewView = nullptr;
  704. // 如果是全局变量,则需要创建全局变量视图
  705. if (type == TOOL_TYPE::TOOL_TYPE_GLOBAL_VARIABLE)
  706. {
  707. DllTool* pHdwTool = nullptr;
  708. TOOL* pTool = nullptr;
  709. if (gvlType == GVL_MODE::GVL_DB)
  710. {
  711. POU* pHdwPou = g_pPouManager->getHdwPou();
  712. pTool = pHdwPou->GetToolByName(strHdwInstName);
  713. if (pTool == nullptr)
  714. {
  715. vWarning() << strHdwInstName << " not found in hardware configuration ";
  716. }
  717. else
  718. {
  719. pHdwTool = pTool->pDllPtr;
  720. }
  721. }
  722. // 创建全局变量视图
  723. pNewView = (WindowAppGvlView*)(g_pResourceManager->addGvlNode(strGroupName, gvlType, pHdwTool, false));
  724. g_pGvlManager->bindHdwToolAndDB(pTool, strGroupName);
  725. }
  726. // 局部变量则创建Pou视图
  727. else if (type == TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE)
  728. {
  729. // 创建Pou视图
  730. pNewView = (WindowAppPouFrame*)(g_pResourceManager->addPouNode(strGroupName));
  731. }
  732. int nVarCount = 0;
  733. in >> nVarCount;
  734. // 循环读取所有变量
  735. for (int j = 0; j < nVarCount; j++)
  736. {
  737. VARIABLE* pNewVariable = new VARIABLE(nullptr);
  738. // in >> *pNewVariable;
  739. // 读取变量
  740. this->loadInterface(in, pNewVariable);
  741. // 2022-9-27,由于index目前不参与序列化了,所以需要根据手动重新设置index(不过变量的Index基本没有用到)
  742. pNewVariable->nIndex = j;
  743. // 2022-9-2 增加,如果变量是带有触发事件的,需要额外生成一下触发事件
  744. int nTigger;
  745. in >> nTigger;
  746. if (nTigger == 1)
  747. {
  748. pNewVariable->eventTrigger = new ToolEvent(strGroupName, pNewVariable->strName, TOOL_EVENT_TYPE::TASK_TRIGGER);
  749. }
  750. // 直接读取,但是无需执行任何操作
  751. // Tip:因为变量会作为Port的接口被绑定,在后续保存Tool信息的时候会重新保存一下link信息
  752. // loadLinks(in, pNewVariable->strFullName, nullptr, false, LINK_MODE::LINK_NORMAL);
  753. // 数据结构中添加本变量信息
  754. g_pGvlManager->addNewVariable(strGroupName, pNewVariable);
  755. // 在界面中添加新的变量
  756. if (type == TOOL_TYPE::TOOL_TYPE_GLOBAL_VARIABLE)
  757. {
  758. ((WindowAppGvlView*)pNewView)->addNewVariable(pNewVariable);
  759. }
  760. else if (type == TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE)
  761. {
  762. ((WindowAppPouFrame*)pNewView)->addNewVariable(pNewVariable);
  763. }
  764. //// 2022-3-3 如果是DB模式的,还需要额外再读取一下DB和硬件Tool的绑定关系
  765. //if (pNewVariable->pParentTool->gvlMode == GVL_MODE::GVL_DB)
  766. //{
  767. // QString strHdwName;
  768. // in >> strHdwName;
  769. // POU* pHdwPou = g_pPouManager->getHdwPou();
  770. // TOOL* HdwTool = pHdwPou->GetToolByName(strHdwName);
  771. // DllTool* pHdwTool = HdwTool->pDllPtr;
  772. // g_pGvlManager->bindHdwToolAndDB(pHdwTool, strGroupName);
  773. //}
  774. }
  775. qDebug() << "[Documents] Loaded GVL group[" << strGroupName << "]: " << nVarCount << " counts.";
  776. return true;
  777. }
  778. //========================================================
  779. //
  780. // Pous
  781. //
  782. //========================================================
  783. /// <summary>
  784. /// 写入Pou区段
  785. /// </summary>
  786. /// <param name="out"></param>
  787. /// <returns></returns>
  788. bool Document::savePous(QDataStream& out)
  789. {
  790. qDebug() << "[Documents] Save POUs...";
  791. // 获取全部Pou
  792. const QMap<QString, POU*>& allPous = g_pPouManager->getAllPous();
  793. // 写入Pou总数量
  794. out << allPous.size() - 1;
  795. // 遍历所有的Pou信息
  796. QMapIterator<QString, POU*> it(allPous);
  797. while (it.hasNext())
  798. {
  799. it.next();
  800. // 2022-2-24 跳过硬件Pou
  801. if (it.key() != GROUP_NAME_HARDWARE)
  802. {
  803. savePou(it.key(), out);
  804. }
  805. }
  806. return true;
  807. }
  808. /// <summary>
  809. /// 写入单个Pou
  810. /// </summary>
  811. /// <param name="strPouName"></param>
  812. /// <param name="out"></param>
  813. /// <returns></returns>
  814. bool Document::savePou(const QString strPouName, QDataStream& out)
  815. {
  816. // 写入本Pou的分组名称
  817. out << strPouName;
  818. // 逐个保存Pou信息
  819. POU* pPou = g_pPouManager->getPouByName(strPouName);
  820. if (pPou == nullptr)
  821. {
  822. qDebug() << "[Documents] save pou, but can't find pou[" << strPouName << "].";
  823. return false;
  824. }
  825. // 2022-8-30 增加,首先序列化Pou界面相关参数
  826. out << pPou->parentScene()->parentFrame();
  827. // 遍历本Pou下的所有工具和接口
  828. const QMap<QString, TOOL*>& allTools = pPou->GetAllTools();
  829. // 写入总数量
  830. out << allTools.size();
  831. QMapIterator<QString, TOOL*> i(allTools);
  832. while (i.hasNext())
  833. {
  834. TOOL* pTool = i.next().value();
  835. // 保存Tool信息
  836. this->saveTool(out, pTool);
  837. // 保存此Tool在界面中的坐标
  838. out << pPou->GetToolItemPos(pTool->strInstanceName);
  839. // 如果是Port类型,还需要额外存储一下Port的绑定关系
  840. if (pTool->isPortTool())
  841. {
  842. this->savePortBindInfo(out, pTool);
  843. }
  844. // 如果是Goto类型,还需要额外存储一下Goto的绑定关系
  845. else if (pTool->isGotoTool())
  846. {
  847. this->saveGotoBindInfo(out, pTool);
  848. }
  849. // 2022-9-4,如果是Wait类型,还需要额外存储一下Wait工具的相关参数
  850. else if (pTool->isWaitTool())
  851. {
  852. this->saveWaitToolSettings(out, pPou, pTool);
  853. }
  854. //// 如果是Parallel类型,还需要额外存储一下Parallel的绑定关系
  855. //else if (pTool->isParallelTool())
  856. //{
  857. // this->saveParallelBindInfo(out, pTool);
  858. //}
  859. else
  860. {
  861. // 2021-8-14增加,标准工具则再保存dll中的内部变量
  862. if (pTool->pDllPtr)
  863. {
  864. // 工具序列化出错的时候,会抛出异常,需要退出后续序列化
  865. try
  866. {
  867. pTool->pDllPtr->SerializedToDoc(out);
  868. }
  869. catch (...)
  870. {
  871. return false;
  872. }
  873. }
  874. }
  875. qDebug() << "[Documents] Saved " << pTool->strInstanceName << ": " << pTool->Interfaces.size() << " interfaces.";
  876. }
  877. return true;
  878. }
  879. /// <summary>
  880. /// 读取Pou区段
  881. /// </summary>
  882. /// <param name="in"></param>
  883. /// <returns></returns>
  884. bool Document::loadPous(QDataStream& in)
  885. {
  886. qDebug() << "[Documents] Load POUs...";
  887. // 读入Pou总数量
  888. int nPouCount = 0;
  889. in >> nPouCount;
  890. // 循环读取所有Pou分组
  891. for (int i = 0; i < nPouCount; i++)
  892. {
  893. loadPou(in);
  894. }
  895. return true;
  896. }
  897. /// <summary>
  898. /// 读取单组的Pou相关信息
  899. /// </summary>
  900. /// <param name="in"></param>
  901. /// <param name="strLoadName">之前已经加载过的Pou分组名字</param>
  902. /// <param name="bLoadName">本次是否还需要继续加载名字</param>
  903. /// <returns></returns>
  904. bool Document::loadPou(QDataStream& in, const QString& strLoadName, bool bLoadName)
  905. {
  906. // 创建对应的Pou页面
  907. WindowAppPouFrame* pouFrame = nullptr;
  908. // 2021-8-24增加,由于单独导入导出Pou的时候,需要提前加载一下名字
  909. // 用于判断当前加载的Pou节点是否已经存在
  910. // Pou分组名称
  911. QString strPouName = strLoadName;
  912. if (bLoadName)
  913. {
  914. in >> strPouName;
  915. }
  916. // 创建Pou视图
  917. pouFrame = qobject_cast<WindowAppPouFrame*>(g_pResourceManager->addPouNode(strPouName, false));
  918. // 2022-8-30 增加,首先完成pouFrame的参数序列化
  919. in >> pouFrame;
  920. // 读入工具数量
  921. int nToolCount = 0;
  922. in >> nToolCount;
  923. // 逐个生成对应的工具
  924. for (int j = 0; j < nToolCount; j++)
  925. {
  926. // 根据信息创建新的工具
  927. TOOL* pNewTool = new TOOL();
  928. // 加载本工具信息
  929. bool state = this->loadTool(in, pNewTool);
  930. if (!state)
  931. {
  932. vWarning() << "[Error] Document::loadPou - LoadTools Error in " << strPouName;
  933. return false;
  934. }
  935. // 读取本Tool的屏幕坐标
  936. QPointF toolPos;
  937. in >> toolPos;
  938. // 如果本工具是Port类型,还需要额外读取Port绑定信息
  939. if (pNewTool->isPortTool())
  940. {
  941. this->loadPortBindInfo(in, strLoadName, bLoadName);
  942. }
  943. // 如果本工具是Goto类型,还需要额外读取Goto绑定信息
  944. else if (pNewTool->isGotoTool())
  945. {
  946. this->loadGotoBindInfo(in);
  947. }
  948. // 如果是Parallel工具,额外保存并行工具信息用于最后执行恢复
  949. else if (pNewTool->isParallelTool())
  950. {
  951. this->loadParallelInfos(in, pNewTool);
  952. }
  953. // 2022-6-12 直接用Scene指针创建对应的工具Block
  954. g_pPouManager->getPouSceneByName(strPouName)->addToolItem(pNewTool, toolPos, true);
  955. // 2021-8-14增加,保存dll中的内部变量(仅限标准工具)
  956. if (pNewTool->isStandardTool())
  957. {
  958. if (pNewTool->pDllPtr == nullptr)
  959. {
  960. return false;
  961. }
  962. this->loadFromToolDll(in ,pNewTool);
  963. }
  964. // 2022-9-4,如果是Wait工具,在功能块创建完毕之后,还需要额外读取一下Wait工具的相关参数保存到功能块中
  965. else if (pNewTool->isWaitTool())
  966. {
  967. this->loadWaitToolSettings(in, g_pPouManager->getPouByName(strPouName), pNewTool);
  968. }
  969. }
  970. qDebug() << "[Documents] Load pou [" + strPouName + "] finished.";
  971. return true;
  972. }
  973. /// <summary>
  974. /// 从Tool的Dll中反序列化
  975. /// </summary>
  976. /// <param name="in"></param>
  977. /// <param name="pNewTool"></param>
  978. void Document::loadFromToolDll(QDataStream& in, TOOL*& pNewTool)
  979. {
  980. pNewTool->pDllPtr->SerializedFromDoc(in);
  981. //QFuture<bool> future = QtConcurrent::run(
  982. // pNewTool->pDllPtr,
  983. // &DllTool::SerializedFromDoc,
  984. // in
  985. //);
  986. //
  987. //while (true)
  988. //{
  989. // if (future.isFinished())
  990. // {
  991. // break;
  992. // }
  993. // QCoreApplication::processEvents();
  994. // Utility::qSleep(100);
  995. //}
  996. for (int i = 0; i < pNewTool->Interfaces.size(); i++)
  997. {
  998. const _INTERFACE* pInf = pNewTool->Interfaces[i];
  999. // 如果是动态加载的端口,不从工具的基础端口里去查找,直接添加
  1000. if (pInf->bDynamic)
  1001. {
  1002. // TODO: 加载的端口,Ptr未绑定值,需要调用dll 对应的函数,来绑定变量
  1003. if (pNewTool->pDllPtr != nullptr)
  1004. {
  1005. DLL_INF inf;
  1006. inf.strName = pInf->strName;
  1007. inf.Direction = pInf->Direction;
  1008. inf.Type = pInf->Type;
  1009. inf.value.passMode = pInf->value.passMode;
  1010. inf.value.type = pInf->value.type;
  1011. inf.nIndex = pInf->nIndex;
  1012. inf.bDynamic = pInf->bDynamic;
  1013. pNewTool->pDllPtr->AddInterface(inf);
  1014. pNewTool->pDllPtr->bindValuePtrByName(pInf->strName, pInf->nIndex);
  1015. }
  1016. }
  1017. }
  1018. }
  1019. //========================================================
  1020. //
  1021. // Tools
  1022. //
  1023. //========================================================
  1024. /// <summary>
  1025. /// 写入Tool区段
  1026. /// </summary>
  1027. /// <returns></returns>
  1028. bool Document::saveTool(QDataStream& out, const TOOL* pTool)
  1029. {
  1030. int nParanum = 11;//参数数量
  1031. out << nParanum;//先保存参数数量
  1032. out << (int)1 << pTool->Type;
  1033. out << (int)2 << pTool->strPouName;
  1034. out << (int)3 << pTool->strName;
  1035. out << (int)4 << pTool->strAliasName;
  1036. out << (int)5 << pTool->strInstanceName;
  1037. out << (int)6 << pTool->strInfo;
  1038. out << (int)7 << pTool->strVersion;
  1039. out << (int)8 << pTool->bEnable;
  1040. out << (int)9 << pTool->nIndex;
  1041. out << (int)10 << pTool->strComment;
  1042. out << (int)11 << pTool->bEnable;
  1043. // 保存所有的接口信息
  1044. this->saveToolInterfaces(out, pTool);
  1045. return true;
  1046. }
  1047. /// <summary>
  1048. /// 读入Tool区段
  1049. /// </summary>
  1050. /// <param name="in"></param>
  1051. /// <returns></returns>
  1052. bool Document::loadTool(QDataStream& in, TOOL*& pNewTool)
  1053. {
  1054. int nPara;
  1055. int nParanum;
  1056. in >> nParanum;//读取参数数量
  1057. // 校验值
  1058. int nMaxParanum = 11;// 该参数的最大数量(需要根据参数的数量来调整,用来校验)
  1059. if (nParanum < 0 || nParanum > nMaxParanum)
  1060. {
  1061. return false;
  1062. }
  1063. for (int i = 0; i < nParanum; i++)
  1064. {
  1065. in >> nPara;
  1066. switch (nPara)
  1067. {
  1068. case 1: in >> pNewTool->Type; break;
  1069. case 2: in >> pNewTool->strPouName; break;
  1070. case 3: in >> pNewTool->strName; break;
  1071. case 4: in >> pNewTool->strAliasName; break;
  1072. case 5: in >> pNewTool->strInstanceName; break;
  1073. case 6: in >> pNewTool->strInfo; break;
  1074. case 7: in >> pNewTool->strVersion; break;
  1075. case 8: in >> pNewTool->bEnable; break;
  1076. case 9: in >> pNewTool->nIndex; break;
  1077. case 10: in >> pNewTool->strComment; break;
  1078. case 11: in >> pNewTool->bEnable; break;
  1079. default:
  1080. {
  1081. vWarning() << "[Error] Document::loadTool - invalid para index: " << nPara;
  1082. }
  1083. break;
  1084. }
  1085. }
  1086. int nInfCount = 0;
  1087. in >> nInfCount;
  1088. TOOL* pTool_Dll = toolDepository.getToolByName(pNewTool->strName);
  1089. if (pTool_Dll == nullptr && pNewTool->isStandardTool())
  1090. {
  1091. return false;
  1092. }
  1093. // 处理工具改名的相关问题
  1094. if (pTool_Dll->strName != pNewTool->strName)
  1095. {
  1096. pNewTool->strName = pTool_Dll->strName;
  1097. pNewTool->strAliasName = pTool_Dll->strAliasName;
  1098. }
  1099. // 读取接口信息
  1100. this->loadToolInterfaces(in, pNewTool, pTool_Dll, nInfCount);
  1101. return true;
  1102. }
  1103. //========================================================
  1104. //
  1105. // Interfaces
  1106. //
  1107. //========================================================
  1108. /// <summary>
  1109. /// 写入所有的Interface信息
  1110. /// </summary>
  1111. /// <param name="out"></param>
  1112. /// <param name="pTool"></param>
  1113. /// <returns></returns>
  1114. bool Document::saveToolInterfaces(QDataStream& out, const TOOL* pTool)
  1115. {
  1116. // 写入接口数量
  1117. out << pTool->Interfaces.size();
  1118. // 继续遍历标准接口,逐一保存
  1119. for (_INTERFACE* pInf : pTool->Interfaces)
  1120. {
  1121. // out << *pInf;
  1122. this->saveInterface(out, pInf);
  1123. }
  1124. //// 如果是具备ToolStart接口的,还需要额外保存一下ToolStart接口信息
  1125. //if (pTool->startInterface != nullptr)
  1126. //{
  1127. // // out << *pTool->TopInterface;
  1128. // this->saveInterfaces(out, pTool->startInterface);
  1129. //}
  1130. //// 如果具备ToolEnd接口的,还需要额外保存一下ToolEnd接口信息
  1131. //if (pTool->endInterface != nullptr)
  1132. //{
  1133. // this->saveInterfaces(out, pTool->endInterface);
  1134. //}
  1135. // 2022-8-25,遍历ToolInterface接口(如果有的话),逐一保存
  1136. for (const auto& toolInterface : pTool->ToolInterfaces)
  1137. {
  1138. this->saveInterface(out, toolInterface);
  1139. }
  1140. return true;
  1141. }
  1142. /// <summary>
  1143. /// 写入Interface信息
  1144. /// </summary>
  1145. /// <param name="out"></param>
  1146. /// <param name="inf"></param>
  1147. /// <returns></returns>
  1148. bool Document::saveInterface(QDataStream& out, const _INTERFACE* inf)
  1149. {
  1150. //int nParanum = 19;//参数数量
  1151. //out << nParanum;//先保存参数数量
  1152. //out << (int)1 << inf->strName;
  1153. //out << (int)2 << inf->strFullName;
  1154. //out << (int)3 << inf->strNameWithType;
  1155. //out << (int)4 << inf->Direction;
  1156. //out << (int)5 << inf->Type;
  1157. //out << (int)6 << inf->nIndex;
  1158. //out << (int)7 << inf->bEnable;
  1159. //out << (int)8 << inf->strComment;
  1160. //out << (int)9 << inf->bSerialized;
  1161. //out << (int)10 << inf->bShow;
  1162. //out << (int)11 << inf->bDynamic;
  1163. //out << (int)12 << (int&)inf->parent()->gvlMode;
  1164. //out << (int)13 << inf->bWatch;
  1165. //out << (int)14 << inf->bDataLink;
  1166. //out << (int)15 << inf->valueString;
  1167. //out << (int)16 << inf->bComplexLinkIndex;
  1168. //out << (int)17 << inf->accessMode;
  1169. //out << (int)18 << inf->strCommAddress;
  1170. //out << (int)19 << inf->bShowName;
  1171. // 2022-9-27,此处不再保存接口的index了
  1172. // 因为下次反序列化的时候接口可能已经变动了,index就已经不准了
  1173. int nParanum = 18;//参数数量
  1174. out << nParanum;//先保存参数数量
  1175. out << (int)1 << inf->strName;
  1176. out << (int)2 << inf->strFullName;
  1177. out << (int)3 << inf->strNameWithType;
  1178. out << (int)4 << inf->Direction;
  1179. out << (int)5 << inf->Type;
  1180. out << (int)6 << inf->bEnable;
  1181. out << (int)7 << inf->strComment;
  1182. out << (int)8 << inf->bSerialized;
  1183. out << (int)9 << inf->bShow;
  1184. out << (int)10 << inf->bDynamic;
  1185. out << (int)11 << (int&)inf->parent()->gvlMode;
  1186. out << (int)12 << inf->bWatch;
  1187. out << (int)13 << inf->bDataLink;
  1188. out << (int)14 << inf->valueString;
  1189. out << (int)15 << inf->bComplexLinkIndex;
  1190. out << (int)16 << inf->accessMode;
  1191. out << (int)17 << inf->strCommAddress;
  1192. out << (int)18 << inf->bShowName;
  1193. // Pou类型的接口是不存具体数值的,只有变量类型的才会存
  1194. // 2022-2-23 增加,只有基础模式的变量才需要保存值
  1195. if (inf->Type == INF_TYPE::INF_TYPE_VALUE
  1196. && inf->parent()->gvlMode == GVL_MODE::GVL_BASIC
  1197. )
  1198. {
  1199. out << inf->value;
  1200. }
  1201. //// 2022-3-31 增加,Goto的输入接口也需要保存值(bool类型)
  1202. //else if (inf.pParentTool->isGotoTool()
  1203. // && inf.Direction == INF_DIRECTION::INF_DIR_IN )
  1204. //{
  1205. // out << inf.value;
  1206. //}
  1207. else
  1208. {
  1209. out << inf->value.passMode;
  1210. out << inf->value.type;
  1211. }
  1212. return true;
  1213. }
  1214. /// <summary>
  1215. /// 读取所有的Interface信息
  1216. /// </summary>
  1217. /// <param name="out"></param>
  1218. /// <param name="pNewTool"></param>
  1219. /// <param name="pTool_Dll"></param>
  1220. /// <returns></returns>
  1221. bool Document::loadToolInterfaces(QDataStream& in, TOOL*& pNewTool, TOOL*& pTool_Dll, int nInfCount)
  1222. {
  1223. // 判断是删除了端口,还是增加了端口,
  1224. // 如果新dll删除了端口,则引用就版本存储下来的端口(暂用新工具的端口,序列化上来过期的端口将被抛弃)
  1225. // 如果新dll增加了端口,则将新添加的的端口插入进来,注意,新端口可能不是在末添加的,可能是任意位置
  1226. for (int i = 0; i < nInfCount; i++)
  1227. {
  1228. _INTERFACE* pNewInf = new _INTERFACE(pNewTool);
  1229. // 2022-9-27由于目前接口index不参与序列化了,后面需要手工补一下接口序号
  1230. this->loadInterface(in, pNewInf);
  1231. // 如果是动态加载的端口,不从工具的基础端口里去查找,直接添加
  1232. if (pNewInf->bDynamic || pNewTool->isPortTool())
  1233. {
  1234. pNewTool->Interfaces.push_back(pNewInf);
  1235. // TODO: 加载的端口,Ptr未绑定值,需要调用dll 对应的函数,来绑定变量
  1236. }
  1237. else
  1238. {
  1239. // TODO:2022-3-31 此处的代码是有问题的,因为作为Goto这种动态绑定的端口,端口名字都会随着绑定接口的名称而改变
  1240. // 所以肯定是在toolDepository中查询不到的,并且 pTool_Dll 作为动态生成的端口,使用完毕之后需要手工删除
  1241. // 如果在工具中找到对应端口,则说明该端口正常使用中
  1242. // 端口被标记为废弃,是因为
  1243. // 1:直接删除端口的代码,
  1244. // 2:端口代码没删除,而是内部标记为废弃
  1245. // 3:修改了端口的数据类型或者输入输出类型,或者数据传递类型
  1246. //
  1247. INF_DISCARD Discard = INF_DISCARD::INF_MARK_DELETE;
  1248. for (int j = 0; j < pTool_Dll->Interfaces.size(); j++)
  1249. {
  1250. _INTERFACE* pDllInf = pTool_Dll->Interfaces[j];
  1251. // 必须确保所有的类型都一样
  1252. if (pDllInf->strName == pNewInf->strName)
  1253. {
  1254. if (pDllInf->Direction == pNewInf->Direction
  1255. && pDllInf->value.passMode == pNewInf->value.passMode
  1256. && pDllInf->value.type == pNewInf->value.type
  1257. )
  1258. {
  1259. // 所有数据类型都校验成功,引用 DLL 实际配置的端口信息(在此接受工具开发者主动废弃端口)
  1260. Discard = pDllInf->Discard;
  1261. break;
  1262. }
  1263. // 如果数据类型和其它属性校验失败,证明数据数据已经被修改
  1264. else
  1265. {
  1266. Discard = INF_DISCARD::INF_MARK_CHANGE;
  1267. // TODO:如果数据结构已经被修改。需要在功能块上添加一个最新的接口(从dll中加载的)
  1268. //pDllInf->strName += "(new)";
  1269. //pNewTool->Interfaces.push_back(pDllInf);
  1270. }
  1271. }
  1272. }
  1273. pNewInf->Discard = Discard;
  1274. pNewTool->Interfaces.push_back(pNewInf);
  1275. }
  1276. }
  1277. // 如果dll 中添加了新的端口,则需要在pNewTool->Interfaces中,插入新添加的
  1278. if (pTool_Dll->Interfaces.size() > nInfCount)
  1279. {
  1280. for (int i = 0; i < pTool_Dll->Interfaces.size(); i++)
  1281. {
  1282. _INTERFACE* pDllInf = pTool_Dll->Interfaces[i];
  1283. // 遍历序DLL 的端口,与DOC 的对比,检查是否有新添加进来的端口
  1284. bool bIsLookupOK = false; //
  1285. for (int j = 0; j < pNewTool->Interfaces.size(); j++)
  1286. {
  1287. _INTERFACE* pDocInf = pNewTool->Interfaces[j];
  1288. if (pDllInf->strName == pDocInf->strName
  1289. && pDllInf->strNameWithType == pDocInf->strNameWithType
  1290. && pDllInf->value.type == pDocInf->value.type
  1291. )
  1292. {
  1293. bIsLookupOK = true;
  1294. }
  1295. }
  1296. // 如果在 Doc加载上来的端口序列中没找到,即 i 的位置插入这个端口
  1297. if (!bIsLookupOK)
  1298. {
  1299. pNewTool->Interfaces.insert(i, pDllInf);
  1300. }
  1301. }
  1302. }
  1303. // 2022-9-28,端口反序列化结束,并且已经和Dll比对完毕后,给所有的端口重新编一下序号
  1304. int infIndex = 0;
  1305. for (int i = 0; i < pNewTool->Interfaces.size(); i++)
  1306. {
  1307. // 需要跳过废弃的端口
  1308. // if (pNewTool->Interfaces[i]->Discard != INF_DISCARD::INF_MARK_DELETE
  1309. // && pNewTool->Interfaces[i]->Discard != INF_DISCARD::INF_MARK_DISCARD
  1310. // )
  1311. {
  1312. pNewTool->Interfaces[i]->nIndex = infIndex++;
  1313. }
  1314. }
  1315. // 2022-4-7 如果是标准工具还需要继续读取ToolInterface接口的相关信息
  1316. if (pNewTool->isHaveToolInterfaces())
  1317. {
  1318. pNewTool->ToolInterfaces.clear();
  1319. // 重新读取ToolInterface
  1320. // (TODO:此处固定按2个接口读的,因为写入的时候并没有写入ToolInterface的数量,有隐患)
  1321. for (int i = 0; i < TOOL_INTERFACE_COUNT; i++)
  1322. {
  1323. _INTERFACE* newInf = new _INTERFACE(pNewTool, INF_TYPE::INF_TYPE_TOOL);
  1324. pNewTool->ToolInterfaces.push_back(newInf);
  1325. this->loadInterface(in, pNewTool->ToolInterfaces[i]);
  1326. }
  1327. //// 如果本工具加入了并行组,则保存Link信息用于后续恢复
  1328. //if (pNewTool->bParallelized)
  1329. //{
  1330. // // loadLinks(in, pNewTool->TopInterface->strFullName, pView, true, LINK_MODE::LINK_PARALLEL);
  1331. //}
  1332. //// 如果是其他情况,则跳过link的处理
  1333. //// 例如Goto工具的连接,或者是未连接等等
  1334. //else
  1335. //{
  1336. // // loadLinks(in, pNewTool->TopInterface->strFullName, pView, false, LINK_MODE::LINK_NORMAL);
  1337. //}
  1338. }
  1339. return true;
  1340. }
  1341. /// <summary>
  1342. /// 读取Interface信息
  1343. /// </summary>
  1344. /// <param name="in"></param>
  1345. /// <param name="inf"></param>
  1346. /// <returns></returns>
  1347. bool Document::loadInterface(QDataStream& in, _INTERFACE*& inf)
  1348. {
  1349. GVL_MODE gvlMode = GVL_MODE::GVL_BASIC;
  1350. int nPara;
  1351. int nParanum;
  1352. in >> nParanum;//读取参数数量
  1353. //// 校验
  1354. //int nMaxParanum = 19;// 该参数的最大数量(需要根据参数的数量来调整,用来校验)
  1355. //if (nParanum < 0 || nParanum > nMaxParanum)
  1356. //{
  1357. // return false;
  1358. //}
  1359. //for (int i = 0; i < nParanum; i++)
  1360. //{
  1361. // in >> nPara;
  1362. // switch (nPara)
  1363. // {
  1364. // case 1: in >> inf->strName; break;
  1365. // case 2: in >> inf->strFullName; break;
  1366. // case 3: in >> inf->strNameWithType; break;
  1367. // case 4: in >> inf->Direction; break;
  1368. // case 5: in >> inf->Type; break;
  1369. // case 6: in >> inf->nIndex; break;
  1370. // case 7: in >> inf->bEnable; break;
  1371. // case 8: in >> inf->strComment; break;
  1372. // case 9: in >> inf->bSerialized; break;
  1373. // case 10: in >> inf->bShow; break;
  1374. // case 11: in >> inf->bDynamic; break;
  1375. // case 12: in >> (int&)gvlMode; break;
  1376. // case 13: in >> inf->bWatch; break;
  1377. // case 14: in >> inf->bDataLink; break;
  1378. // case 15: in >> inf->valueString; break;
  1379. // case 16: in >> inf->bComplexLinkIndex; break;
  1380. // case 17: in >> inf->accessMode; break;
  1381. // case 18: in >> inf->strCommAddress; break;
  1382. // case 19: in >> inf->bShowName; break;
  1383. //
  1384. // default:
  1385. // {
  1386. // vWarning() << "_INTERFACE Serialized(In) Error";
  1387. // }
  1388. // break;
  1389. // }
  1390. //}
  1391. // 2022-9-27,去掉了index序列化,因为下次反序列化的时候接口可能已经变动了,index需要重新计算,而不是直接读取
  1392. // 校验,该参数的最大数量(需要根据参数的数量来调整,用来校验)
  1393. int nMaxParanum = 18;
  1394. if (nParanum < 0 || nParanum > nMaxParanum)
  1395. {
  1396. return false;
  1397. }
  1398. for (int i = 0; i < nParanum; i++)
  1399. {
  1400. in >> nPara;
  1401. switch (nPara)
  1402. {
  1403. case 1: in >> inf->strName; break;
  1404. case 2: in >> inf->strFullName; break;
  1405. case 3: in >> inf->strNameWithType; break;
  1406. case 4: in >> inf->Direction; break;
  1407. case 5: in >> inf->Type; break;
  1408. case 6: in >> inf->bEnable; break;
  1409. case 7: in >> inf->strComment; break;
  1410. case 8: in >> inf->bSerialized; break;
  1411. case 9: in >> inf->bShow; break;
  1412. case 10: in >> inf->bDynamic; break;
  1413. case 11: in >> (int&)gvlMode; break;
  1414. case 12: in >> inf->bWatch; break;
  1415. case 13: in >> inf->bDataLink; break;
  1416. case 14: in >> inf->valueString; break;
  1417. case 15: in >> inf->bComplexLinkIndex; break;
  1418. case 16: in >> inf->accessMode; break;
  1419. case 17: in >> inf->strCommAddress; break;
  1420. case 18: in >> inf->bShowName; break;
  1421. default:
  1422. {
  1423. vWarning() << "_INTERFACE Serialized(In) Error";
  1424. }
  1425. break;
  1426. }
  1427. }
  1428. // 2022-2-23 增加,只有基础模式的变量才需要读取数值
  1429. if (inf->Type == INF_TYPE::INF_TYPE_VALUE)
  1430. {
  1431. if (gvlMode == GVL_MODE::GVL_BASIC)
  1432. {
  1433. in >> inf->value;
  1434. }
  1435. // 如果是其他类型的数值,则需要重置为默认值
  1436. else
  1437. {
  1438. in >> inf->value.passMode;
  1439. in >> inf->value.type;
  1440. inf->value.setValue(QString(""));
  1441. }
  1442. }
  1443. //// 2022-3-31 增加,Goto的输入接口也需要保存值(bool类型)
  1444. //else if (inf->pParentTool->isGotoTool()
  1445. // && inf->Direction == INF_DIRECTION::INF_DIR_IN)
  1446. //{
  1447. // in >> inf->value;
  1448. //}
  1449. // 如果是dll中的值,则留空
  1450. else
  1451. {
  1452. in >> inf->value.passMode;
  1453. in >> inf->value.type;
  1454. }
  1455. // 如果属性设置了不参与序列化,即把该变量的值设置为空,
  1456. if (!inf->bSerialized)
  1457. {
  1458. inf->value.setValue(QString(""));
  1459. }
  1460. return true;
  1461. }
  1462. //========================================================
  1463. //
  1464. // Port
  1465. //
  1466. //========================================================
  1467. /// <summary>
  1468. /// 写入Port信息
  1469. /// </summary>
  1470. /// <param name="out"></param>
  1471. /// <returns></returns>
  1472. bool Document::savePortBindInfo(QDataStream& out, const TOOL* pTool)
  1473. {
  1474. const _INTERFACE* pPortInf = pTool->Interfaces[0];
  1475. // 是否已经处于绑定状态
  1476. if (pPortInf->isBinded())
  1477. {
  1478. out << 1;
  1479. DOC_BIND_TOOL_INFO info;
  1480. info.strSrcPou = pTool->strPouName;
  1481. info.strSourceTool = pTool->strInstanceName;
  1482. info.strDestPou = pPortInf->bindedParent()->strPouName;
  1483. info.strDestInf = pPortInf->pBindInterface->strFullName;
  1484. info.infType = pPortInf->bindedParent()->Type;
  1485. out << info;
  1486. }
  1487. // 否则,写入空
  1488. else
  1489. {
  1490. out << 0;
  1491. }
  1492. return true;
  1493. }
  1494. /// <summary>
  1495. /// 读取Port信息
  1496. /// </summary>
  1497. /// <param name="in"></param>
  1498. /// <returns></returns>
  1499. bool Document::loadPortBindInfo(QDataStream& in, const QString& strLoadName, bool bLoadName)
  1500. {
  1501. int nBindCount = 0;
  1502. in >> nBindCount;
  1503. // 如果没有绑定,则无需读取
  1504. if (nBindCount <= 0)
  1505. {
  1506. return true;
  1507. }
  1508. DOC_BIND_TOOL_INFO info;
  1509. in >> info;
  1510. if (! bLoadName)
  1511. {
  1512. info.strSrcPou = strLoadName;
  1513. info.strDestPou = strLoadName;
  1514. }
  1515. m_PortBindInfos.push_back(info);
  1516. return true;
  1517. }
  1518. /// <summary>
  1519. /// 还原Port绑定关系
  1520. /// </summary>
  1521. /// <param name="pTool"></param>
  1522. /// <returns></returns>
  1523. bool Document::restorePortBindInfo()
  1524. {
  1525. for (const DOC_BIND_TOOL_INFO& info : m_PortBindInfos)
  1526. {
  1527. // 首先找到这个Port
  1528. POU* pou = g_pPouManager->getPouByName(info.strSrcPou);
  1529. TOOL* pPort = pou->GetToolByName(info.strSourceTool);
  1530. // 找到此Port对应的功能块
  1531. WindowAppBlockPort* pPortItem = qgraphicsitem_cast<WindowAppBlockPort*>(pou->GetToolItem(info.strSourceTool));
  1532. // 检查错误
  1533. if (pou == nullptr || pPort == nullptr || pPortItem == nullptr)
  1534. {
  1535. qDebug() << "[Error] Document::restorePortBindInfo - pou[" << info.strSrcPou << "] or PORT["
  1536. << info.strSourceTool << "] or pPortItem is nullptr.";
  1537. continue;
  1538. }
  1539. // 然后找到这个接口(2022-3-2处理,区分Pou和Gvl)
  1540. _INTERFACE* pInf = nullptr;
  1541. // 如果绑定的是工具接口
  1542. if (info.infType == TOOL_TYPE::TOOL_TYPE_STANDARD)
  1543. {
  1544. POU* toolPou = g_pPouManager->getPouByName(info.strDestPou);
  1545. if (toolPou != nullptr)
  1546. {
  1547. pInf = toolPou->GetInterface(info.strDestInf);
  1548. }
  1549. }
  1550. // 如果绑定的是变量
  1551. else if(info.infType == TOOL_TYPE::TOOL_TYPE_GLOBAL_VARIABLE
  1552. || info.infType == TOOL_TYPE::TOOL_TYPE_LOCAL_VARIABLE
  1553. )
  1554. {
  1555. GVL* gvl = g_pGvlManager->getGvl(info.strDestPou);
  1556. if (gvl != nullptr)
  1557. {
  1558. pInf = gvl->getInterfaceByFullName(info.strDestInf);
  1559. }
  1560. }
  1561. // 不应该执行到这里
  1562. else
  1563. {
  1564. vWarning() << "[Error] Document::restorePortBindInfo - Unknown infType [" << (short)info.infType << "] if inf["
  1565. << info.strDestInf << "].";
  1566. // 直接重置本Port接口的绑定状态
  1567. pPort->setPortError();
  1568. continue;
  1569. }
  1570. // 2022-3-23,此处inf为空有可能是因为单独输入输出Pou的时候,关联的接口并没有导入所致,所以直接清空Port的绑定状态
  1571. if (pInf == nullptr)
  1572. {
  1573. vWarning() << "[Error] Document::restorePortBindInfo - inf [" << info.strDestInf << "] is nullptr.";
  1574. // 重置本Port接口的绑定状态
  1575. pPort->setPortError();
  1576. continue;
  1577. }
  1578. // 重新执行Port的绑定动作
  1579. pPortItem->bindInterface(pInf);
  1580. }
  1581. return true;
  1582. }
  1583. //========================================================
  1584. //
  1585. // Goto
  1586. //
  1587. //========================================================
  1588. /// <summary>
  1589. /// 写入Goto的绑定关系
  1590. /// </summary>
  1591. /// <param name="out"></param>
  1592. /// <param name="pTool"></param>
  1593. /// <returns></returns>
  1594. bool Document::saveGotoBindInfo(QDataStream& out, const TOOL* pTool)
  1595. {
  1596. const _INTERFACE* pPortInf = pTool->Interfaces[GOTO_OUTPUT_INDX];
  1597. // 是否已经处于绑定状态
  1598. if (pPortInf->isBinded())
  1599. {
  1600. out << 1;
  1601. DOC_BIND_TOOL_INFO info;
  1602. info.strSrcPou = pTool->strPouName;
  1603. info.strSourceTool = pTool->strInstanceName;
  1604. info.strDestPou = pPortInf->bindedParent()->strPouName;
  1605. info.strDestInf = pPortInf->pBindInterface->strFullName;
  1606. info.infType = pPortInf->bindedParent()->Type;
  1607. out << info;
  1608. }
  1609. // 否则,写入空
  1610. else
  1611. {
  1612. out << 0;
  1613. }
  1614. return true;
  1615. }
  1616. /// <summary>
  1617. /// 读取Goto的绑定关系
  1618. /// TODO:此处同样涉及到Tool改名问题
  1619. /// </summary>
  1620. /// <param name="in"></param>
  1621. /// <returns></returns>
  1622. bool Document::loadGotoBindInfo(QDataStream& in)
  1623. {
  1624. int nBindCount = 0;
  1625. in >> nBindCount;
  1626. // 如果没有绑定,则无需读取
  1627. if (nBindCount <= 0)
  1628. {
  1629. return true;
  1630. }
  1631. DOC_BIND_TOOL_INFO info;
  1632. in >> info;
  1633. m_GotoBindInfos.push_back(info);
  1634. return true;
  1635. }
  1636. /// <summary>
  1637. /// 还原Goto绑定关系
  1638. /// </summary>
  1639. /// <returns></returns>
  1640. bool Document::restoreGotoBindInfo()
  1641. {
  1642. for (auto info : m_GotoBindInfos)
  1643. {
  1644. // 首先找到这个Port
  1645. POU* pou = g_pPouManager->getPouByName(info.strSrcPou);
  1646. TOOL* pGoto = pou->GetToolByName(info.strSourceTool);
  1647. // 找到此Goto对应的功能块
  1648. WindowAppBlockGoto* pItem = qgraphicsitem_cast<WindowAppBlockGoto*>(pou->GetToolItem(info.strSourceTool));
  1649. // 检查错误
  1650. if (pou == nullptr || pGoto == nullptr || pItem == nullptr)
  1651. {
  1652. qDebug() << "[Error] Document::restoreGotoBindInfo - pou[" << info.strSrcPou <<
  1653. "] or GotoTool[" << info.strSourceTool << "] or pItem is nullptr.";
  1654. continue;
  1655. }
  1656. _INTERFACE* pInf = nullptr;
  1657. POU* toolPou = g_pPouManager->getPouByName(info.strDestPou);
  1658. if (toolPou != nullptr)
  1659. {
  1660. pInf = toolPou->GetInterface(info.strDestInf);
  1661. }
  1662. // 检查错误
  1663. if (pInf == nullptr)
  1664. {
  1665. vWarning() << "[Error] Document::restoreGotoBindInfo - inf [" << info.strDestInf << "] is nullptr.";
  1666. continue;
  1667. }
  1668. // 重新执行Port的绑定动作
  1669. pItem->bindOutputInterface(pInf->parent());
  1670. // 此处为Goto的输入接口重置bool类型的值为false
  1671. pGoto->Interfaces[GOTO_INPUT_INDX]->value.setValue<bool>(false);
  1672. }
  1673. return true;
  1674. }
  1675. //========================================================
  1676. //
  1677. // Links
  1678. //
  1679. //========================================================
  1680. /// <summary>
  1681. /// 保存Link信息
  1682. /// </summary>
  1683. /// <param name="out"></param>
  1684. /// <returns></returns>
  1685. bool Document::saveLinks(QDataStream& out)
  1686. {
  1687. // 遍历所有Pou取出其中的Link信息
  1688. // 获取全部Pou
  1689. const QMap<QString, POU*>& allPous = g_pPouManager->getAllPous();
  1690. // 写入总数量
  1691. out << allPous.size();
  1692. // 遍历所有的Pou信息
  1693. QMapIterator<QString, POU*> it(allPous);
  1694. while (it.hasNext())
  1695. {
  1696. it.next();
  1697. //// 跳过硬件Pou
  1698. //if (it.key() == GROUP_NAME_HARDWARE)
  1699. //{
  1700. // continue;
  1701. //}
  1702. // 保存本Pou中的Link信息
  1703. this->saveLink(out, it.value());
  1704. }
  1705. return true;
  1706. }
  1707. /// <summary>
  1708. /// 保存单组Pou中的Link信息
  1709. /// </summary>
  1710. /// <param name="out"></param>
  1711. /// <param name="pou"></param>
  1712. /// <returns></returns>
  1713. bool Document::saveLink(QDataStream& out, POU* pou)
  1714. {
  1715. // 然后写入本Pou所有的Link信息
  1716. const QVector<LINK>& allLinks = pou->getAllLinks();
  1717. // 总数量
  1718. int linkCount = allLinks.size();
  1719. out << linkCount;
  1720. if (linkCount <= 0)
  1721. {
  1722. return true;
  1723. }
  1724. // 如果有Link的话,则写入Pou的名字
  1725. out << pou->pouName();
  1726. // 然后写入所有Link细节信息
  1727. for (const auto& one_link : allLinks)
  1728. {
  1729. // 起始接口全名
  1730. out << one_link.pSrcItem->m_infInfo->strFullName;
  1731. // 终点接口全名
  1732. out << one_link.pDstItem->m_infInfo->strFullName;
  1733. // 连接模式
  1734. out << one_link.linkMode;
  1735. // 本Link在Scene中的坐标(用于还原Link线段)
  1736. out << one_link.pLinkItem->getAllLinkLinePoints();
  1737. }
  1738. return true;
  1739. }
  1740. /// <summary>
  1741. /// 读取Link信息
  1742. /// </summary>
  1743. /// <param name="in"></param>
  1744. /// <returns></returns>
  1745. bool Document::loadLinks(QDataStream& in)
  1746. {
  1747. // 首先读取Pou总数量
  1748. int pouCount = 0;
  1749. in >> pouCount;
  1750. for (int i = 0; i < pouCount; i++)
  1751. {
  1752. // 读取本Pou的link数量
  1753. int linkCount = 0;
  1754. in >> linkCount;
  1755. if (linkCount <= 0)
  1756. {
  1757. continue;
  1758. }
  1759. // 读取并恢复本Pou中的Link
  1760. this->loadLink(in, linkCount);
  1761. }
  1762. return true;
  1763. }
  1764. /// <summary>
  1765. /// 读取单组Pou中的Link信息
  1766. /// </summary>
  1767. /// <param name="in"></param>
  1768. /// <returns></returns>
  1769. bool Document::loadLink(QDataStream& in, const int& linkCount)
  1770. {
  1771. // 读入Pou名称
  1772. QString pouName;
  1773. in >> pouName;
  1774. // 获取本Pou
  1775. POU* pou = g_pPouManager->getPouByName(pouName);
  1776. // Error
  1777. if (pou == nullptr)
  1778. {
  1779. qDebug() << "[Error] Document::loadLink - can't find pou[" << pouName << "]";
  1780. return false;
  1781. }
  1782. // 读取并恢复本Pou下的所有Link
  1783. for (int i = 0; i < linkCount; i++)
  1784. {
  1785. DOC_LINK_INFO linkInfo;
  1786. // 起始接口全名
  1787. in >> linkInfo.strSrcInf;
  1788. // 目的接口全名
  1789. in >> linkInfo.strDesInf;
  1790. // 连接模式
  1791. in >> linkInfo.linkMode;
  1792. // Link线段坐标
  1793. in >> linkInfo.lines;
  1794. // 通过Pou中的Scene重新建立Link
  1795. pou->parentScene()->addLink(
  1796. linkInfo.strSrcInf,
  1797. linkInfo.strDesInf,
  1798. linkInfo.linkMode,
  1799. linkInfo.lines
  1800. );
  1801. }
  1802. return true;
  1803. }
  1804. //========================================================
  1805. //
  1806. // Parallel
  1807. //
  1808. //========================================================
  1809. /// <summary>
  1810. /// 读取并行工具的配置信息
  1811. /// </summary>
  1812. /// <param name="in"></param>
  1813. /// <param name="pNewTool"></param>
  1814. /// <returns></returns>
  1815. bool Document::loadParallelInfos(QDataStream& in, TOOL*& pNewTool)
  1816. {
  1817. Q_UNUSED(in);
  1818. DOC_TOOL_INFO docTool;
  1819. docTool.strPouName = pNewTool->strPouName;
  1820. docTool.strToolInstanceName = pNewTool->strInstanceName;
  1821. m_ParallelInfos.push_back(docTool);
  1822. return true;
  1823. }
  1824. /// <summary>
  1825. /// 还原并行工具相关信息(由于并行母线的长度需要所有的Tool和Link全部恢复之后才可以判定)
  1826. /// </summary>
  1827. void Document::restoreParallelInfos()
  1828. {
  1829. // 遍历所有的并行母线恢复信息
  1830. for (auto parainfo: m_ParallelInfos)
  1831. {
  1832. // 首先找到这个工具所在Pou
  1833. POU* pou = g_pPouManager->getPouByName(parainfo.strPouName);
  1834. // 找到此工具对应的功能块
  1835. WindowAppBlockParallel* pItem = qgraphicsitem_cast<WindowAppBlockParallel*>(pou->GetToolItem(parainfo.strToolInstanceName));
  1836. // 刷新并行母线
  1837. pItem->updateParallelLine();
  1838. }
  1839. }
  1840. //========================================================
  1841. //
  1842. // Wait Tool
  1843. //
  1844. //========================================================
  1845. /// <summary>
  1846. /// 写入WaitTool的配置参数信息
  1847. /// </summary>
  1848. /// <param name="out"></param>
  1849. /// <param name="pTool"></param>
  1850. /// <returns></returns>
  1851. bool Document::saveWaitToolSettings(QDataStream& out, POU* pou, TOOL*& pTool)
  1852. {
  1853. // WaitTool的设置 - 绑定的ToolEvent信息
  1854. // 到TaskManager中查询ToolEvent信息
  1855. ToolEvent* event = g_pTaskManager->getEventByTool(pTool);
  1856. if (event != nullptr)
  1857. {
  1858. out << event->groupName();
  1859. out << event->name();
  1860. }
  1861. else
  1862. {
  1863. out << "";
  1864. out << "";
  1865. }
  1866. // 找到此Tool对应的功能块
  1867. WindowAppBlockWait* pWaitBlock = qgraphicsitem_cast<WindowAppBlockWait*>(pou->GetToolItem(pTool->strInstanceName));
  1868. // WaitTool的设置 - 单步执行时是否跳过等待
  1869. out << pWaitBlock->m_bSkipWait;
  1870. // WaitTool的设置 - 等待的超时时间
  1871. out << pWaitBlock->m_nTimeout;
  1872. // WaitTool的设置 - 等待的触发变量值
  1873. out << pWaitBlock->m_WaitValue;
  1874. return true;
  1875. }
  1876. /// <summary>
  1877. /// 读取WaitTool的配置参数信息
  1878. /// </summary>
  1879. /// <param name="in"></param>
  1880. /// <returns></returns>
  1881. bool Document::loadWaitToolSettings(QDataStream& in, POU* pou, TOOL*& pNewTool)
  1882. {
  1883. QString groupName, name;
  1884. in >> groupName;
  1885. in >> name;
  1886. // 如果确实绑定了Event,则此处重新到TaskManager注册一下
  1887. if (!groupName.isEmpty() && !name.isEmpty())
  1888. {
  1889. // 首先检查是否是系统内置事件
  1890. VARIABLE* var = g_pTaskManager->getSysEventByName(name);
  1891. // 如果不是的话,再判断是否是某一个变量
  1892. if (var == nullptr)
  1893. {
  1894. // 转换成对应的Variable
  1895. var = g_pGvlManager->getVariableByName(groupName, name);
  1896. // 校验是否有异常
  1897. if (var == nullptr)
  1898. {
  1899. vDebug() << "[Error] Load event[" << groupName << "," << name << "] failed.";
  1900. return false;
  1901. }
  1902. // 重新到TaskManager绑定此对应关系
  1903. g_pTaskManager->registerToolEvent(var->eventTrigger, pNewTool);
  1904. }
  1905. }
  1906. // 找到此Tool对应的功能块
  1907. WindowAppBlockWait* pWaitBlock = qgraphicsitem_cast<WindowAppBlockWait*>(pou->GetToolItem(pNewTool->strInstanceName));
  1908. // Error
  1909. if (pWaitBlock == nullptr)
  1910. {
  1911. vDebug() << "WaitBlock is nullptr.";
  1912. return false;
  1913. }
  1914. // WaitTool的设置 - 单步执行时是否跳过等待
  1915. in >> pWaitBlock->m_bSkipWait;
  1916. // WaitTool的设置 - 等待的超时时间
  1917. in >> pWaitBlock->m_nTimeout;
  1918. // WaitTool的设置 - 等待的触发变量值
  1919. in >> pWaitBlock->m_WaitValue;
  1920. return true;
  1921. }
  1922. //========================================================
  1923. //
  1924. // Tasks
  1925. //
  1926. //========================================================
  1927. /// <summary>
  1928. /// 保存Task区段
  1929. /// </summary>
  1930. /// <param name="out"></param>
  1931. bool Document::saveTasks(QDataStream& out)
  1932. {
  1933. qDebug() << "Save [Tasks].";
  1934. // 从公共区域获取所有的Task数据
  1935. const QMap<QString, TASK*>& allTasks = g_pTaskManager->getAllTasks();
  1936. // 写入Task总数量
  1937. out << allTasks.size();
  1938. // 遍历所有的Task信息
  1939. QMapIterator<QString, TASK*> it(allTasks);
  1940. while (it.hasNext())
  1941. {
  1942. // 获取Task
  1943. const TASK* pTask = it.next().value();
  1944. // 写入Task基本信息
  1945. out << *pTask;
  1946. // pous size
  1947. out << pTask->pous.size();
  1948. // pous
  1949. QVectorIterator<POU*> it(pTask->pous);
  1950. while (it.hasNext())
  1951. {
  1952. out << it.next()->pouName();
  1953. }
  1954. qDebug() << " Saved " << pTask->strName;
  1955. }
  1956. return true;
  1957. }
  1958. /// <summary>
  1959. /// 读取Task区段
  1960. /// </summary>
  1961. /// <param name="in"></param>
  1962. bool Document::loadTasks(QDataStream& in)
  1963. {
  1964. qDebug() << "Load [Tasks].";
  1965. // 创建默认的Task Monitor View
  1966. g_pResourceManager->addDefaultTaskMonitorNode(GROUP_NAME_TASKMONITOR);
  1967. // 创建默认的LogView
  1968. g_pResourceManager->addDefaultLogViewNode(GROUP_NAME_LOGVIEW);
  1969. // 读入Task数量
  1970. int nTask = 0;
  1971. in >> nTask;
  1972. // 循环读取所有Task信息
  1973. for (int i = 0; i < nTask; i++)
  1974. {
  1975. // 读入Task名字
  1976. QString strNewTaskName;
  1977. in >> strNewTaskName;
  1978. // 添加对应的节点,并且创建对应的Task视图
  1979. WindowAppTaskView* pTaskView =
  1980. qobject_cast<WindowAppTaskView*>(g_pResourceManager->addTaskNode(strNewTaskName, false));
  1981. TASK* pNewTask = new TASK(strNewTaskName);
  1982. // 读入Task基础信息
  1983. in >> *pNewTask;
  1984. // 2022-9-2,如果Task带有事件触发信息,则绑定一下事件
  1985. if (pNewTask->modeType == TASK_MODE_TYPE::MODE_VAL && !pNewTask->strModeName.isEmpty())
  1986. {
  1987. pNewTask->bindEventByMode();
  1988. }
  1989. // 将用户输入的Task参数绑定到视图中
  1990. pTaskView->addNewTask(pNewTask);
  1991. // 继续读取Pou信息
  1992. int nPouCount = 0;
  1993. in >> nPouCount;
  1994. QVector<POU*> taskPous;
  1995. for (int j = 0; j < nPouCount; j++)
  1996. {
  1997. QString strPouName;
  1998. in >> strPouName;
  1999. taskPous.push_back(g_pPouManager->getPouByName(strPouName));
  2000. }
  2001. // 还原Pou信息到Task中
  2002. pTaskView->addTaskPous(taskPous);
  2003. }
  2004. return true;
  2005. }
  2006. //========================================================
  2007. //
  2008. // SinglePou
  2009. //
  2010. //========================================================
  2011. /// <summary>
  2012. /// 导出整个Pou(pou、tool、link、variables)
  2013. /// </summary>
  2014. /// <param name="strPouFullPath"></param>
  2015. /// <param name="strPouName"></param>
  2016. /// <returns></returns>
  2017. bool Document::saveSinglePou(const QString& strPouFullPath, const QString& strPouName)
  2018. {
  2019. // 建立存档文件
  2020. QFile fileOut(strPouFullPath);
  2021. if (!fileOut.open(QFile::WriteOnly | QFile::Truncate))
  2022. {
  2023. Utility::VPCriticalMessageBox(strPouFullPath + " create failed!");
  2024. return false;
  2025. }
  2026. // 序列化对象
  2027. QDataStream out(&fileOut);
  2028. // 设置版本
  2029. out.setVersion(QDataStream::Qt_5_14);
  2030. // 保存单个Pou相关信息
  2031. savePou(strPouName, out);
  2032. // 保存本组局部变量
  2033. saveGVL(strPouName, out);
  2034. fileOut.close();
  2035. Utility::VPInformationMessageBox("Serialized to " + strPouFullPath + " finished.");
  2036. return true;
  2037. }
  2038. /// <summary>
  2039. /// 导入单个Pou(pou、tool、link、variables)
  2040. /// </summary>
  2041. /// <param name="strPouFullPath"></param>
  2042. /// <returns></returns>
  2043. bool Document::loadSinglePou(const QString& strPouFullPath)
  2044. {
  2045. qDebug() << "Load file : " << strPouFullPath;
  2046. // 打开存档文件
  2047. QFile fileIn(strPouFullPath);
  2048. if (!fileIn.open(QFile::ReadOnly))
  2049. {
  2050. Utility::VPCriticalMessageBox(strPouFullPath + " open failed!");
  2051. return false;
  2052. }
  2053. // 序列化对象
  2054. QDataStream in(&fileIn);
  2055. // 设置版本
  2056. in.setVersion(QDataStream::Qt_5_14);
  2057. // 首先加载一下选择文档的Pou名字
  2058. QString strLoadName;
  2059. in >> strLoadName;
  2060. int nPouSize = g_pPouManager->getAllPous().size();
  2061. QString strPouName("Pou_" + QString::number(nPouSize));
  2062. DialogNewPou dlgNewPou;
  2063. dlgNewPou.setDefaultName(strPouName);
  2064. int res = dlgNewPou.exec();
  2065. if (res != QDialog::Accepted)
  2066. {
  2067. fileIn.close();
  2068. return false;
  2069. }
  2070. // 使用新的POU名字
  2071. strLoadName = dlgNewPou.m_strPouName + POU_POSTFIX;
  2072. // 读取Pou相关数据信息(不需要再次读取名字了)
  2073. bool state = loadPou(in, strLoadName, false);
  2074. if (!state)
  2075. {
  2076. vWarning() << "Load Pou Error" << strLoadName;
  2077. return false;
  2078. }
  2079. // 读取本Pou的局部变量
  2080. this->loadGVL(in, strLoadName, false);
  2081. // 还原Port绑定关系
  2082. this->restorePortBindInfo();
  2083. // 还原Goto绑定关系
  2084. this->restoreGotoBindInfo();
  2085. //// 还原Link信息
  2086. //this->restoreLinks();
  2087. // 还原Parallel工具信息
  2088. this->restoreParallelInfos();
  2089. Utility::VPInformationMessageBox("Deserialized from " + strPouFullPath + " finished.");
  2090. fileIn.close();
  2091. return true;
  2092. }
  2093. /// <summary>
  2094. /// 单个Pou重置(包括页面和数据结构)
  2095. /// </summary>
  2096. void Document::pouReset(const QString& strPouName)
  2097. {
  2098. qDebug() << "[Document] Reset pou - " << strPouName;
  2099. // 重置Pou信息
  2100. g_pPouManager->RemovePou(strPouName);
  2101. // 重置Variable
  2102. g_pGvlManager->removeGvl(strPouName);
  2103. // 清除对应的子页面
  2104. VPGlobal::getMdiFrame()->deleteSubView(strPouName);
  2105. // 清除临时数据结构(link、port info、Goto)
  2106. // m_Links.clear();
  2107. m_PortBindInfos.clear();
  2108. m_GotoBindInfos.clear();
  2109. m_ParallelInfos.clear();
  2110. }
  2111. //========================================================
  2112. //
  2113. // UI
  2114. //
  2115. //========================================================
  2116. /// <summary>
  2117. /// 写入UI区段
  2118. /// </summary>
  2119. /// <param name="out"></param>
  2120. /// <returns></returns>
  2121. bool Document::saveUIs(QDataStream& out)
  2122. {
  2123. qDebug() << "Save [UIs].";
  2124. g_pUiManager->serialized(out);
  2125. return true;
  2126. }
  2127. /// <summary>
  2128. /// 读取UI区段
  2129. /// </summary>
  2130. /// <param name="in"></param>
  2131. /// <returns></returns>
  2132. bool Document::loadUIs(QDataStream& in)
  2133. {
  2134. qDebug() << "Load [UIs].";
  2135. // g_pUiManager->deserialized(in);
  2136. // 读入UI的数量
  2137. int nUI = 0;
  2138. in >> nUI;
  2139. for (int i = 0; i < nUI; i++)
  2140. {
  2141. // 读入UI名字
  2142. QString strNewUiName;
  2143. in >> strNewUiName;
  2144. // 添加对应的节点,并且创建对应的UI视图
  2145. WindowAppUiFrame* pUiFrame =
  2146. qobject_cast<WindowAppUiFrame*>(g_pResourceManager->addUiNode(strNewUiName, false, true));
  2147. // 进行 WindowAppUiView* 的序列化
  2148. in >> pUiFrame->getUiView();
  2149. }
  2150. // 只有ui数量大于 0 的时候,才发布页面
  2151. if ( nUI>0 )
  2152. {
  2153. // 通过Manager发布所有UI
  2154. bool bRet = g_pUiManager->publishAll();
  2155. if (bRet)
  2156. {
  2157. }
  2158. }
  2159. return true;
  2160. }
  2161. //========================================================
  2162. //
  2163. // Compress
  2164. //
  2165. //========================================================
  2166. /// <summary>
  2167. /// 压缩
  2168. /// </summary>
  2169. /// <returns></returns>
  2170. bool Document::compress(QString strPath)
  2171. {
  2172. QString strTmpPath = strPath;
  2173. // 生成正式的文件名
  2174. strPath = strPath.left(strPath.length() - TMP_POSTFIX.length());
  2175. strPath += DOC_POSTFIX;
  2176. QByteArray bufferDoc;
  2177. QByteArray bufferHdw;
  2178. // 打包后的数据缓冲区
  2179. QByteArray buffer;
  2180. // 读取工程文件
  2181. {
  2182. QFile fileTmp(strTmpPath);
  2183. fileTmp.open(QIODevice::ReadOnly);
  2184. qint64 docLength = fileTmp.size();
  2185. bufferDoc = fileTmp.read(docLength);
  2186. fileTmp.close();
  2187. qDebug() << "Doc 压缩前字节大小:" << bufferDoc.size();
  2188. }
  2189. // 读取硬件组态文件
  2190. {
  2191. QFileInfo fileInfo(DOC_HARDWARE_FULLPATH);
  2192. if (fileInfo.exists() != true)
  2193. {
  2194. saveHdw(DOC_HARDWARE_FULLPATH);
  2195. }
  2196. QFile fileTmp(DOC_HARDWARE_FULLPATH);
  2197. fileTmp.open(QIODevice::ReadOnly);
  2198. qint64 docLength = fileTmp.size();
  2199. bufferHdw = fileTmp.read(docLength);
  2200. fileTmp.close();
  2201. qDebug() << "Hdw 压缩前字节大小:" << bufferDoc.size();
  2202. }
  2203. QString strDocMD5 = QCryptographicHash::hash(bufferDoc, QCryptographicHash::Md5).toHex().toUpper();
  2204. QString strHdwMD5 = QCryptographicHash::hash(bufferHdw, QCryptographicHash::Md5).toHex().toUpper();
  2205. QBuffer bufferTmp;
  2206. bufferTmp.open(QIODevice::WriteOnly);
  2207. QDataStream ar(&bufferTmp);
  2208. ar.setVersion(QDataStream::Qt_5_14);
  2209. int paranum = 5;//参数数量
  2210. ar << paranum;//先保存参数数量
  2211. ar << (int)1 << (int)DOC_MINOR_VERSION;
  2212. ar << (int)2 << strDocMD5;
  2213. ar << (int)3 << strHdwMD5;
  2214. ar << (int)4 << bufferDoc;
  2215. ar << (int)5 << bufferHdw;
  2216. // 压缩文件数据(第二个参数为压缩级别,0 - 9)
  2217. buffer = qCompress(bufferTmp.buffer() , 5);
  2218. qDebug() << "压缩后字节大小:" << buffer.size();
  2219. // 保存文件
  2220. QFile fileSave(strPath);
  2221. fileSave.open(QIODevice::WriteOnly);
  2222. fileSave.write(buffer);
  2223. fileSave.close();
  2224. // 释放资源
  2225. bufferTmp.close();
  2226. // 删除临时文件
  2227. QFile::remove(strTmpPath);
  2228. return true;
  2229. }
  2230. /// <summary>
  2231. /// 解压缩
  2232. /// </summary>
  2233. /// <returns></returns>
  2234. bool Document::uncompress(QString& strPath)
  2235. {
  2236. QString saveFileName = strPath;
  2237. // 生成解压后的临时文件名,按照临时文件名进行读取
  2238. strPath = strPath.left(strPath.length() - DOC_POSTFIX.length());
  2239. strPath += TMP_POSTFIX;
  2240. // 读取文件
  2241. QFile fileTmp(saveFileName);
  2242. fileTmp.open(QIODevice::ReadOnly);
  2243. qint64 docLength = fileTmp.size();
  2244. QByteArray buffer = fileTmp.read(docLength);
  2245. fileTmp.close();
  2246. QByteArray bufferDoc;
  2247. QByteArray bufferHdw;
  2248. int nVersion= 0;
  2249. QString strLoadDocMD5;
  2250. QString strLoadHdwMD5;
  2251. // 解压缩
  2252. buffer = qUncompress(buffer);
  2253. QDataStream ar(buffer);
  2254. ar.setVersion(QDataStream::Qt_5_14);
  2255. int para = 0;
  2256. int paranum = 0;
  2257. ar >> paranum;//读取参数数量
  2258. if (paranum == 5)
  2259. {
  2260. for (int i = 0; i < paranum; i++)
  2261. {
  2262. ar >> para;
  2263. switch (para)
  2264. {
  2265. case 1: ar >> nVersion; break;
  2266. case 2: ar >> strLoadDocMD5; break;
  2267. case 3: ar >> strLoadHdwMD5; break;
  2268. case 4: ar >> bufferDoc; break;
  2269. case 5: ar >> bufferHdw; break;
  2270. default:
  2271. {
  2272. vWarning() << "Serialized(In) Error";
  2273. return false;
  2274. }
  2275. break;
  2276. }
  2277. }
  2278. QString strDocMD5 = QCryptographicHash::hash(bufferDoc, QCryptographicHash::Md5).toHex().toUpper();
  2279. QString strHdwMD5 = QCryptographicHash::hash(bufferHdw, QCryptographicHash::Md5).toHex().toUpper();
  2280. if (strLoadDocMD5 != strDocMD5)
  2281. {
  2282. return false;
  2283. }
  2284. if (strLoadHdwMD5 != strLoadHdwMD5)
  2285. {
  2286. return false;
  2287. }
  2288. // 将buffer 存起来
  2289. m_bufferHdw = bufferHdw;
  2290. }
  2291. else
  2292. {
  2293. bufferDoc = buffer;
  2294. }
  2295. // 写入临时文件
  2296. QFile fileSave(strPath);
  2297. fileSave.open(QIODevice::WriteOnly);
  2298. fileSave.write(bufferDoc);
  2299. fileSave.close();
  2300. return true;
  2301. }
  2302. //========================================================
  2303. //
  2304. // Other
  2305. //
  2306. //========================================================
  2307. /// <summary>
  2308. /// 2022-3-25 检查接口是否还有效(防止Port端绑定对象无效后,依旧链接的问题)
  2309. /// </summary>
  2310. /// <param name="infFullName"></param>
  2311. /// <returns></returns>
  2312. bool Document::checkInfValid(const QString& infGroupName, const QString& infFullName)
  2313. {
  2314. POU* pou = g_pPouManager->getPouByName(infGroupName);
  2315. if (pou == nullptr)
  2316. {
  2317. return false;
  2318. }
  2319. _INTERFACE* pInf = pInf = pou->GetInterface(infFullName);
  2320. if (pInf == nullptr)
  2321. {
  2322. return false;
  2323. }
  2324. // 如果类型无效,则说明是Port接口并且尚未绑定接口
  2325. if (pInf->Type == INF_TYPE::INF_TYPE_UNKNOWN)
  2326. {
  2327. return false;
  2328. }
  2329. //// 如果是Port类型,并且绑定信息无效了,则返回false
  2330. //if (pInf->parent()->Type == TOOL_TYPE::TOOL_TYPE_PORT_INPUT
  2331. // || pInf->parent()->Type == TOOL_TYPE::TOOL_TYPE_PORT_OUTPUT
  2332. // )
  2333. //{
  2334. // if (pInf->pBindInterface == nullptr)
  2335. // {
  2336. // return false;
  2337. // }
  2338. //}
  2339. return true;
  2340. }
  2341. /// <summary>
  2342. /// 检查硬件组态与文档是否匹配
  2343. /// </summary>
  2344. /// <param name="strHardwareID"></param>
  2345. /// <param name="strDocID"></param>
  2346. /// <returns></returns>
  2347. bool Document::checkHWAndDocConfigID(QString strDocID, QString strHardwareID)
  2348. {
  2349. // 只有当前硬件配置的ID 与 文档 ID 相匹配,才继续加载文档
  2350. bool bLoadHdw = false;
  2351. QStringList value = strDocID.split("|");
  2352. for (int i=0; i< value.size(); i++)
  2353. {
  2354. QString str = value[i];
  2355. if (strHardwareID.indexOf(str) == -1)
  2356. {
  2357. bLoadHdw = true;
  2358. continue;
  2359. }
  2360. }
  2361. if (bLoadHdw == true)
  2362. {
  2363. if (m_bufferHdw.size() == 0)
  2364. {
  2365. return true;
  2366. }
  2367. // TODO:需要引导用户从备份的文件中释放硬件组态文件,并加载释放的文件
  2368. m_bufferHdw;
  2369. DOC_HARDWARE_FULLPATH;
  2370. {
  2371. // 写入临时文件
  2372. QFile fileSave(DOC_HARDWARE_FULLPATH);
  2373. fileSave.open(QIODevice::WriteOnly);
  2374. fileSave.write(m_bufferHdw);
  2375. fileSave.close();
  2376. // 重新加载
  2377. loadHdw(DOC_HARDWARE_FULLPATH);
  2378. }
  2379. }
  2380. return true;
  2381. }
  2382. /// <summary>
  2383. /// 根据硬件组态的工具实例名有工具名字生成一个ID。此ID后面会保存进硬件组态的数据中
  2384. /// </summary>
  2385. /// <returns></returns>
  2386. QString Document::getHWAndDocConfigID()
  2387. {
  2388. QString strID;
  2389. POU* pHdPou = g_pPouManager->getPouByName(GROUP_NAME_HARDWARE);
  2390. if (pHdPou != nullptr)
  2391. {
  2392. QMap<QString, TOOL*> allTools = pHdPou->GetAllTools();
  2393. QMapIterator<QString, TOOL*> i(allTools);
  2394. while (i.hasNext())
  2395. {
  2396. const TOOL* pTool = i.next().value();
  2397. strID.append(pTool->strName);
  2398. strID.append(".");
  2399. strID.append(pTool->strInstanceName);
  2400. strID.append("|");
  2401. }
  2402. strID.chop(1);
  2403. }
  2404. return strID;
  2405. }