Files
MI-38/s1000d/Converter14/lyx.cpp
2023-06-14 18:08:32 +03:00

1951 lines
98 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "lyx.h"
#include <QListWidget>
#include <QPushButton>
#include <QString>
#include <QVBoxLayout>
#include <QDialog>
#include <QListWidget>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QtAlgorithms>
#include <QTime>
#include <QDate>
#include <QDir>
#include <QRandomGenerator>
#include <QtCore/QCoreApplication>
#include <QMessageBox>
#include <QProcess>
//#include <windows.h>
LyX::LyX()
{
}
bool LyX::Import(S1000D_Manager* _SM, QString fileName, SplashForm* _splash) {
SM = _SM;
ru_const = &SM->ru_const; splash = _splash;
if(!SM->isConsole)
{ splash->Reset(); splash->SetTitle("Копирование файлов..."); }
// создаем папку Develop (SM->projectPath), файлы с нее перемещаем в Develop\Backup
QFileInfo info1(fileName);
QString filePath = info1.absolutePath();
QDir dir = QDir(filePath+"/Develop");
if (!dir.exists()) dir.mkdir(filePath+"/Develop");
SM->projectPath = filePath+"/Develop";
enum OperatingSytem {OS_WINDOWS, OS_UNIX, OS_LINUX, OS_MAC} os;
#if (defined (Q_OS_WIN) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64))
os = OS_WINDOWS;
#elif (defined (Q_OS_UNIX))
os = OS_UNIX;
#elif (defined (Q_OS_LINUX))
os = OS_LINUX;
#elif (defined (Q_OS_MAC))
os = OS_MAC;
#endif
QStringList params;
//AllocConsole(); //AttachConsole(GetCurrentProcessId());
if(os == OS_WINDOWS) {
QString winpath1 = SM->projectPath; winpath1.replace("/","\\");
params << "/C"<<"xcopy"<<"/E" << "/C" << "/Y"<< QCoreApplication::applicationDirPath().replace("/","\\")+"\\Scorm\\app" << winpath1+"\\app\\" << ">nul";
if(!SM->isConsole)
QProcess::startDetached("cmd.exe", params);
else
{
QProcess cmdProc;
cmdProc.setProgram("cmd.exe"); cmdProc.setArguments(params);
cmdProc.start();
while(!cmdProc.waitForFinished(50)) {};
}
} else {
params << "-r"<< QCoreApplication::applicationDirPath()+"/Scorm/app" << SM->projectPath+"/app/";// << "> /dev/null";
if(!SM->isConsole)
QProcess::startDetached("cp", params);
else
{
QProcess cmdProc;
cmdProc.setProgram("cp"); cmdProc.setArguments(params);
cmdProc.start();
while(!cmdProc.waitForFinished(50)) {};
}
}
//FreeConsole();
QDir dirBackup(SM->projectPath+"/Backup");
dirBackup.removeRecursively();
//dirBackup.mkpath(".");
QDir dirProj(SM->projectPath);
dirProj.setFilter( QDir::NoDotAndDotDot | QDir::Files | QDir::AllDirs);
dirProj.setNameFilters(QStringList() << "*.*");
dirProj.mkdir("Backup");
foreach( QString dirItem, dirProj.entryList() ) {
if(!SM->isConsole)
{ splash->Step(); splash->Step(); splash->Step(); splash->Step(); }
QFileInfo fileInfo(dirItem);
if(dirItem != "Backup" && dirItem != "app") {
//qDebug() << dirItem;
dirProj.rename(dirItem, SM->projectPath+"/Backup/" + fileInfo.fileName());
}
}
SM->clearItems();
lyxFileStack.clear(); lyxList.clear();
// lyxLog.clear();
// if(SM->item->schemeType == stDESCRIPT) domContentPath = "content.description";
// if(SM->item->schemeType == stCREW) domContentPath = "content.crew.descrCrew";
// domRootNode = SM->findElement(domContentPath);
// //QString domCurLevelPath = domContentPath;
// //QDomNode domCurLevelNode = domRootNode;
// while(domRootNode.hasChildNodes())
// domRootNode.removeChild(domRootNode.firstChild());
// if(!SM->isNodeCreated("rdf:Description")) {
// QDomNode descr = SM->item->doc.createElement("rdf:Description");
// SM->findElement("").insertBefore(descr, SM->findElement("").firstChild());
// }
// if(!SM->isNodeCreated("rdf:Description.dc:source")) SM->createNode("rdf:Description", "dc:source");
// SM->setNodeText("rdf:Description.dc:source", QFileInfo(fileName).fileName());
// SM->item->importedFromLyX = QFileInfo(fileName).fileName();
docChapter = docSection = docSubsection = -1;
curChapterItem = curSectionItem = curSubsectionItem = -1;
tocItemNum = acrListItemNum = -1;
tableOfContentsRoot.childs.clear(); domTableOfContentsNode.clear(); domAcronymListNode.clear();
labelList.clear(); acronymList.clear();
cntTable = cntFigure = cntPar = 0;
tableTitle = ""; tableID = "";
flags.align = ""; flags.bold = false; flags.italic = false; flags.underlined = false;
domRootNode.clear();
if(!SM->isConsole)
splash->SetTitle("Чтение файла LyX...");
if(!readLyXFile(fileName))
return false;
if(tocItemNum != -1) { // заполняем Содержание
SM->setCurItem(tocItemNum);
QDomNode tocTitleNode = SM->item->doc.createElement("para");
domTableOfContentsNode.appendChild(tocTitleNode); tocTitleNode.appendChild(SM->item->doc.createTextNode(ru_const->tableOfContents+"\n"));
fillTableOfContents(tableOfContentsRoot, domTableOfContentsNode, " ");
}
if(acrListItemNum != -1) { // заполняем список сокращений
SM->setCurItem(acrListItemNum);
fillAcronymList(domAcronymListNode);
}
return true;
}
bool LyX::readLyXFile(QString fileName) {
//if(DBG) qDebug() << "reading" << fileName;
QFile lyxFile(fileName);
if(!lyxFile.open(QFile::ReadOnly | QFile::Text)) {
//lyxLog.append("Error: LyX file not found!");
if(DBG) qDebug() << "Error: LyX file not found - " + fileName;
return false;
}
lyxList.clear();
lyxList = QString(lyxFile.readAll()).split("\n");
lyxFile.close();
lyxEmptyCnt.clear();
int delCnt = 0;
for(int i=0;i<lyxList.length();i++) // удаляем неподдерживаемые теги \size и \align
if(lyxList.at(i) == "" || lyxList.at(i).startsWith("\\size") || lyxList.at(i).startsWith("\\align")) {
lyxList.removeAt(i); i--; delCnt++;
} else {
lyxEmptyCnt.append(delCnt);
}
int i=0;
while(!lyxList.at(i).startsWith("\\begin_body") && i < lyxList.count())
i++;
curLyXFileName = fileName;
parseBlock(i+1, findTagEnd(i)-1, domRootNode); // поехали
if(lyxLog.count() == 2) lyxLog.append("#Завершено без ошибок."); //SM->item->
if(curSubsectionItem != -1) SM->items[curSubsectionItem].lyxLog = lyxLog;
return true;
}
int LyX::findTagEnd(int _beg) {
if(!lyxList.at(_beg).startsWith("\\begin_")) {
if(DBG) qDebug() << "Error: findTagEnd not startsWith(\"\\begin_\")";
return -1;
}
QString tagName = lyxList.at(_beg);
if(tagName.indexOf(" ") != -1)
tagName = tagName.left(tagName.indexOf(" "));
tagName = tagName.mid(7);
int _insideCnt = 0;
QString itemText;
for(int i=_beg+1;i<lyxList.count()-1;i++) {
itemText = lyxList.at(i);
if(itemText == "") continue;
if(itemText.startsWith("\\begin_"+tagName)) _insideCnt++;
if(itemText.startsWith("\\end_"+tagName) && _insideCnt != 0) {
_insideCnt--; continue;
}
if(itemText.startsWith("\\end_"+tagName) && _insideCnt == 0) {
return i;
}
}
if(DBG) qDebug() << "Error: findTagEnd not startsWith(\"\\begin_\")";
return -1;
}
int LyX::findTag(int _beg, int _end, QString startsWithName) {
for(int i=_beg;i<=_end;i++)
if(lyxList.at(i).startsWith(startsWithName))
return i;
return -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PARSE BLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// <para> 649, <table> 541, 547
void LyX::parseBlock(int _beg, int _end, QDomNode _domCurLevelNode) {
pushFlags();
if(!SM->isConsole)
splash->Step();
QDomNode domCurLevelNode = _domCurLevelNode;
QDomNode domCurLevelSubsection;
QString blockText = "";
QString itemName;
for(int i=_beg;i<=_end;i++) {
itemName = lyxList.at(i);
if(itemName == "") continue;
if(itemName == "\\begin_layout Title") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++)
title += lyxList.at(j);
i = _childEnd;
//if(!SM->isNodeCreated("rdf:Description.dc:title")) SM->createNode("rdf:Description", "dc:title");
//SM->setNodeText("rdf:Description.dc:title", title);
continue;
}
if(itemName == "\\begin_layout Chapter*" || itemName == "\\begin_layout Chapter") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++) {
if(lyxList.at(j).startsWith("\\size")) continue;
title += lyxList.at(j);
}
i = _childEnd;
title = title.replace("/n", "").replace(":", "");
//lyxLog.append(" "+title);
//if(itemName == "\\begin_layout Chapter")
// lyxLog.append("#["+QString::number(_childBeg+lyxEmptyCnt[_childBeg])+"] Необходимо использовать стиль текста \"Глава*\" вместо \"Глава\"");
//if(DBG) qDebug() << "" + title;
appendChapter(title);
checkForOldIdent();
SM->item->importedFromLyX = curLyXFileName;
domCurLevelNode.clear();
continue;
}
if(itemName == "\\begin_layout Section*" || itemName == "\\begin_layout Section") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++){
if(lyxList.at(j).startsWith("\\size")) continue;
title += lyxList.at(j);
}
i = _childEnd;
title = title.replace("/n", "").replace(":", "");
//lyxLog.append(" "+title);
//if(itemName == "\\begin_layout Section")
// lyxLog.append("#["+QString::number(_childBeg+lyxEmptyCnt[_childBeg])+"] Необходимо использовать стиль текста \"Раздел*\" вместо \"Раздел\"");
//if(DBG) qDebug() << " " + title;
if(docChapter == -1) appendChapter("");
appendSection(title);
checkForOldIdent();
SM->item->importedFromLyX = curLyXFileName;
domCurLevelNode.clear();
continue;
}
if(itemName == "\\begin_layout Subsection*" || itemName == "\\begin_layout Subsection") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++){
if(lyxList.at(j).startsWith("\\size")) continue;
title += lyxList.at(j);
}
i = _childEnd;
title = title.replace("/n", "").replace(":", "");
//lyxLog.append(" "+title);
//if(itemName == "\\begin_layout Subsection")
// lyxLog.append("#["+QString::number(_childBeg+lyxEmptyCnt[_childBeg])+"] Необходимо использовать стиль текста \"Подраздел*\" вместо \"Подраздел\"");
//if(DBG) qDebug() << " " + title;
//qDebug() << internalRefList.count();
for(int j=0;j<internalRefList.count();j++) {
QString id = internalRefList[j];
lyxLog.append("![] Некорректная ссылка ("+id+")");
//SM->item->isQualifyed = false; ???
}
internalRefList.clear();
if(docChapter == -1) appendChapter("");
if(docSection == -1) appendSection("");
appendSubsection(title);
checkForOldIdent();
SM->item->importedFromLyX = curLyXFileName;
lyxLog.clear();
QDate date = QDate::currentDate(); QTime time = QTime::currentTime();
lyxLog.append(" "+date.toString(Qt::SystemLocaleLongDate)+" "+time.toString("hh:mm")+" Импорт модуля из файла "+curLyXFileName); lyxLog.append("");
//qDebug() << "lyx: " << curLyXFileName;
if(SM->item->schemeType == stDESCRIPT)
domCurLevelNode = SM->findElement("content.description");
if(SM->item->schemeType == stLEARNING)
domCurLevelNode = SM->findElement("content.learning.learningAssessment");
domCurLevelSubsection = domCurLevelNode;
if(SM->item->schemeType == stLEARNING)
i = parseLearningModule(domCurLevelNode, i+1, _end);
continue;
}
if(itemName == "\\begin_layout Standard" && lyxList[i+1] == "\\begin_inset CommandInset include") {
QString filename = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++)
if(lyxList[j].startsWith("filename")) {
filename = lyxList[j].mid(9).replace("\"","");
pushLyXFileData();
readLyXFile(SM->projectPath.left(SM->projectPath.length()-7) + "/" + filename);
popLyXFileData();
}
i = _childEnd;
continue;
}
if(curSubsectionItem == -1) continue; // пока не дошли до модуля данных - читаем только заголовки
if(SM->item->schemeType == stLEARNING) continue;
if(itemName == "\\begin_layout Subsubsection*" || itemName == "\\begin_layout Subsubsection") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++){
if(lyxList.at(j).startsWith("\\size")) continue;
title += lyxList.at(j);
}
i = _childEnd;
if(domCurLevelSubsection.isNull())
blockText += title+"\n";
else {
QDomNode levelledPara = SM->item->doc.createElement("levelledPara");
domCurLevelSubsection.appendChild(levelledPara);
QDomNode titleNode = SM->item->doc.createElement("title");
titleNode.appendChild(SM->item->doc.createTextNode(title));
levelledPara.appendChild(titleNode);
domCurLevelNode = levelledPara;
}
continue;
}
if(itemName == "\\begin_layout Paragraph*" || itemName == "\\begin_layout Paragraph") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++){
if(lyxList.at(j).startsWith("\\size")) continue;
title += lyxList.at(j);
}
i = _childEnd;
_childBeg = i;
QDomNode levelledPara = SM->item->doc.createElement("levelledPara");
domCurLevelNode.appendChild(levelledPara);
QDomNode titleNode = SM->item->doc.createElement("title");
titleNode.appendChild(SM->item->doc.createTextNode(title));
levelledPara.appendChild(titleNode);
_childEnd = _end;
for(int j=_childBeg;j<=_end;j++) {
if(lyxList.at(j).startsWith("\\begin_layout Section") || lyxList.at(j).startsWith("\\begin_layout Subsection") ||
lyxList.at(j).startsWith("\\begin_layout Subsubsection") || lyxList.at(j).startsWith("\\begin_layout Paragraph")) {
_childEnd = j-1; break;
}
}
i = _childEnd;
parseBlock(_childBeg+1, _childEnd, levelledPara);
continue;
}
if(itemName == "\\begin_layout Subparagraph*" || itemName == "\\begin_layout Subparagraph") {
QString title = "";
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
for(int j=_childBeg+1;j<_childEnd;j++){
if(lyxList.at(j).startsWith("\\size")) continue;
title += lyxList.at(j);
}
i = _childEnd;
_childBeg = i;
QDomNode levelledPara = SM->item->doc.createElement("levelledPara");
domCurLevelNode.appendChild(levelledPara);
QDomNode titleNode = SM->item->doc.createElement("title");
titleNode.appendChild(SM->item->doc.createTextNode(title));
levelledPara.appendChild(titleNode);
_childEnd = _end;
for(int j=_childBeg;j<=_end;j++) {
if(lyxList.at(j).startsWith("\\begin_layout Section") || lyxList.at(j).startsWith("\\begin_layout Subsection") ||
lyxList.at(j).startsWith("\\begin_layout Subsubsection") || lyxList.at(j).startsWith("\\begin_layout Paragraph") ||
lyxList.at(j).startsWith("\\begin_layout Subparagraph")) {
_childEnd = j-1; break;
}
}
i = _childEnd;
parseBlock(_childBeg+1, _childEnd, levelledPara);
continue;
}
if((itemName == "\\begin_layout Standard" && lyxList[i+1] == "\\begin_inset Box Shaded") ||
(itemName == "\\begin_inset Box Shaded")) {
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
QDomNode warning = SM->item->doc.createElement("warning");
domCurLevelNode.appendChild(warning);
for(int j=_childBeg;j<_childEnd;j++) {
int _textBeg = findTag(j, _childEnd-1, "\\begin_layout Plain Layout");
if(_textBeg == -1) break;
int _textEnd = findTagEnd(_textBeg);
j = _textEnd;
QDomNode warningAndCautionPara = SM->item->doc.createElement("warningAndCautionPara");
warning.appendChild(warningAndCautionPara);
parseBlock(_textBeg+1, _textEnd-1, warningAndCautionPara);
}
i = _childEnd;
continue;
}
if((itemName == "\\begin_layout Standard" && lyxList[i+1].startsWith("\\begin_inset Box")) ||
(itemName == "\\begin_inset Box")) {
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
QDomNode warning = SM->item->doc.createElement("caution");
domCurLevelNode.appendChild(warning);
for(int j=_childBeg;j<_childEnd;j++) {
int _textBeg = findTag(j, _childEnd-1, "\\begin_layout Plain Layout");
if(_textBeg == -1) break;
int _textEnd = findTagEnd(_textBeg);
j = _textEnd;
QDomNode warningAndCautionPara = SM->item->doc.createElement("warningAndCautionPara");
warning.appendChild(warningAndCautionPara);
parseBlock(_textBeg+1, _textEnd-1, warningAndCautionPara);
}
i = _childEnd;
continue;
}
if((itemName == "\\begin_layout Standard" && (lyxList[i+1] == "\\begin_inset Note Greyedout" || lyxList[i+2] == "\\begin_inset Note Greyedout" || lyxList[i+3] == "\\begin_inset Note Greyedout")) ||
(itemName == "\\begin_inset Note Greyedout")) {
int _childBeg, _childEnd;
_childBeg = findTag(i, _end, "\\begin_inset Note Greyedout");
_childEnd = findTagEnd(_childBeg);
int _textBeg = findTag(_childBeg+2, _childEnd-1, "\\begin_layout Plain Layout");
int _textEnd = findTagEnd(_textBeg);
QDomNode note = SM->item->doc.createElement("note");
domCurLevelNode.appendChild(note);
QDomNode notePara = SM->item->doc.createElement("notePara");
note.appendChild(notePara);
parseBlock(_textBeg+1, _textEnd-1, notePara);
_childEnd = findTagEnd(i);
i = _childEnd;
continue;
}
if(itemName[0] != "\\") { blockText += itemName; continue; }
if(itemName == "\\backslash") { blockText += "\\"; continue; }
if(itemName[0] == "\\" && blockText != "") {
QDomNode blockTextNode = SM->item->doc.createTextNode(blockText);
QDomNode tmpCurNode = domCurLevelNode;
if(flags.bold) {
QDomNode emphasisNode = SM->item->doc.createElement("emphasis");
tmpCurNode.appendChild(emphasisNode); tmpCurNode = emphasisNode;
}
if(flags.italic) {
QDomNode emphasisNode = SM->item->doc.createElement("emphasis");
emphasisNode.toElement().setAttribute("emphasisType", "em02"); //"em03" Underline, "em04" Overline, "em05" Strikethrough, "em51" - "em99" Available for projects
tmpCurNode.appendChild(emphasisNode); tmpCurNode = emphasisNode;
}
if(flags.underlined) {
QDomNode emphasisNode = SM->item->doc.createElement("emphasis");
emphasisNode.toElement().setAttribute("emphasisType", "em03"); //"em04" Overline, "em05" Strikethrough, "em51" - "em99" Available for projects
tmpCurNode.appendChild(emphasisNode); tmpCurNode = emphasisNode;
}
tmpCurNode.appendChild(blockTextNode);
blockText = "";
}
if(itemName == "\\begin_layout Plain Layout" || itemName == "\\begin_layout Standard") {
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
QDomNode paraNode = SM->item->doc.createElement("para");
domCurLevelNode.appendChild(paraNode);
pushFlags();
parseBlock(_childBeg+1, _childEnd-1, paraNode);
popFlags();
i = _childEnd;
continue;
}
if(itemName == "\\begin_layout Enumerate" || itemName == "\\begin_layout Itemize") { //
QDomNode titleNodeClone;
if(domCurLevelNode.hasChildNodes())
if(domCurLevelNode.lastChild().nodeName() == "para") {
titleNodeClone = domCurLevelNode.lastChild().cloneNode();
domCurLevelNode.removeChild(domCurLevelNode.lastChild());
titleNodeClone.toElement().setTagName("title");
}
QDomNode listNode;
if(itemName == "\\begin_layout Enumerate") listNode = SM->item->doc.createElement("sequentialList");
if(itemName == "\\begin_layout Itemize") listNode = SM->item->doc.createElement("randomList");
domCurLevelNode.appendChild(listNode);
QDomNode titleNode;
if(titleNodeClone.isNull()) {
//titleNode = SM->item->doc.createElement("title");
//titleNode.appendChild(SM->item->doc.createTextNode(""));
//listNode.appendChild(titleNode);
}
else {
titleNode = SM->item->doc.importNode(titleNodeClone, true);
listNode.appendChild(titleNode);
}
int _childBeg, _childEnd=i;
for(int j=i;j<=_end;j++) {
if(lyxList.at(j) == "") continue;
if(lyxList.at(j) == itemName || lyxList.at(j) == "\\begin_deeper") {
_childBeg = j; _childEnd = findTagEnd(_childBeg);
QDomNode listItemNode = SM->item->doc.createElement("listItem");
listNode.appendChild(listItemNode);
QDomNode listItemPara = SM->item->doc.createElement("para");
listItemNode.appendChild(listItemPara);
pushFlags();
parseBlock(_childBeg+1, _childEnd-1, listItemPara);
popFlags();
j = _childEnd;
continue;
}
break;
}
i = _childEnd;
continue;
}
if(itemName == "\\series bold") {
flags.bold = true; continue; }
if(itemName == "\\series default") {
flags.bold = false; continue; }
if(itemName == "\\shape italic" || itemName == "\\emph on") {
flags.italic = true; continue; }
if(itemName == "\\shape default" || itemName == "\\emph default") {
flags.italic = false; continue; }
if(itemName == "\\bar under" || itemName == "\\uuline on" || itemName == "\\uwave on") {
flags.underlined = true; continue; }
if(itemName == "\\bar default" || itemName == "\\uuline default" || itemName == "\\uwave default") {
flags.underlined = false; continue; }
if(itemName.startsWith("\\color")) {
lyxLog.append("#["+QString::number(i)+"] Цветовое выделение не поддерживается ("+itemName+")");
continue;
}
if(itemName.startsWith("\\size")) {
//lyxLog.append("#["+QString::number(i+lyxEmptyCnt[i])+"] Изменение размера шрифта не поддерживается ("+itemName+")");
continue;
}
if(itemName.startsWith("\\align")) {
lyxLog.append("#["+QString::number(i+lyxEmptyCnt[i])+"] Выравнивание элементов не поддерживается ("+itemName+")");
continue;
}
if(itemName.startsWith("\\strikeout")) { continue; } // игнорируем:
if(itemName.startsWith("\\xout")) { continue; }
if(itemName.startsWith("\\family")) { continue; }
if(itemName.startsWith("\\shape")) { continue; }
if(itemName.startsWith("\\begin_inset")) {
QString insetName = itemName.mid(13);
int _insetBeg, _insetEnd;
_insetBeg = i; _insetEnd = findTagEnd(_insetBeg);
i = _insetEnd; // !!! не трогать
//pushFlags(); // надо?
if(insetName == "CommandInset toc") { //Содержание
tocItemNum = curSubsectionItem;
domTableOfContentsNode = SM->item->doc.createElement("para");
domCurLevelNode.appendChild(domTableOfContentsNode);
continue;
}
if(insetName == "CommandInset nomencl_print") { //Список сокращений
acrListItemNum = curSubsectionItem;
domAcronymListNode = SM->item->doc.createElement("para");
domCurLevelNode.appendChild(domAcronymListNode);
continue;
}
if(insetName == "Foot") {
QString footName = "";
QString termDef = "";
int _plainEnd=_insetBeg;
int _labelEnd=_insetBeg;
for(int j=_insetBeg+1;j<_insetEnd;j++)
if(lyxList.at(j).startsWith("\\begin_layout Plain Layout")) {
_plainEnd = findTagEnd(j); _labelEnd = j+1;
for(int k=j+1;k<_insetEnd;k++)
if(lyxList.at(k).startsWith("\\begin_inset CommandInset label")) {
_labelEnd = findTagEnd(k);
footName = "";
for(int l=k+1;l<=_labelEnd;l++)
if(lyxList.at(l).startsWith("name")) {
footName = lyxList.at(l).mid(6).replace("\"", "");
break;
}
break;
}
break;
}
for(int j=_labelEnd+1;j<_plainEnd;j++) {
if(lyxList.at(j) == "") continue;
if(lyxList.at(j).startsWith("\\")) {
lyxLog.append("!["+QString::number(j+lyxEmptyCnt[j])+"] Ошибка в структуре сноски: в теле сноски("+footName+") ожидался текст");
SM->item->isQualifyed = false;
continue;
}
termDef += lyxList.at(j);
}
if(footName == "") {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка в структуре сноски: остутствует метка");
SM->item->isQualifyed = false;
continue;
}
int acroNum = -1;
for(int j=0;j<acronymList.count();j++)
if(acronymList[j].term == footName.mid(3)) {acroNum = j; break;}
if(acroNum == -1) {
acroNum = acronymList.count();
acronymStruct newAcronym;
newAcronym.term = footName.mid(3);
newAcronym.id = "ftn-"; for(int j=0;j<4-QString::number(acroNum).length();j++) newAcronym.id += "0";
newAcronym.id += QString::number(acroNum);
acronymList.append(newAcronym);
}
acronymList[acroNum].lyxFootnoteName = footName ;
acronymList[acroNum].definition = termDef;
//qDebug() << "Add acronym: " << acronymList[acroNum].id << acronymList[acroNum].term;
QDomNode footNode = SM->item->doc.createElement("footnote");
domCurLevelNode.appendChild(footNode);
footNode.toElement().setAttribute("id", acronymList[acroNum].id);
QDomNode acronymNode = SM->item->doc.createElement("acronym");
domCurLevelNode.appendChild(acronymNode);
QDomNode acronymTermNode = SM->item->doc.createElement("acronymTerm");
acronymNode.appendChild(acronymTermNode);
acronymTermNode.appendChild(SM->item->doc.createTextNode(acronymList[acroNum].term));
QDomNode acronymDefinitionNode = SM->item->doc.createElement("acronymDefinition");
acronymNode.appendChild(acronymDefinitionNode);
acronymDefinitionNode.toElement().setAttribute("id", acronymList[acroNum].id);
acronymDefinitionNode.appendChild(SM->item->doc.createTextNode(acronymList[acroNum].definition));
continue;
}
if(insetName == "CommandInset nomenclature") { // acronym
QString term = "", termDef = "";
if(lyxList[_insetBeg+2].split(" ")[0] == "symbol")
term = lyxList[_insetBeg+2].mid(7).replace("\"","");
if(lyxList[_insetBeg+3].split(" ")[0] == "description")
termDef = lyxList[_insetBeg+3].mid(12).replace("\"","");
int acroNum = -1;
for(int j=0;j<acronymList.count();j++)
if(acronymList[j].term == term) {acroNum = j; break;}
if(acroNum != -1) {
lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Обозначение уже введено ранее по тексту ("+term+")"); continue;
}
if(acroNum == -1) {
acroNum = acronymList.count();
acronymStruct newAcronym;
newAcronym.lyxFootnoteName = "";
newAcronym.term = term;
newAcronym.id = "acr-"; for(int j=0;j<4-QString::number(acroNum).length();j++) newAcronym.id += "0";
newAcronym.id += QString::number(acroNum);
acronymList.append(newAcronym);
}
acronymList[acroNum].definition = termDef;
//qDebug() << acronymList[acroNum].id << acronymList[acroNum].term << acronymList[acroNum].definition;
QDomNode acronymNode = SM->item->doc.createElement("acronym");
domCurLevelNode.appendChild(acronymNode);
QDomNode acronymTermNode = SM->item->doc.createElement("acronymTerm");
acronymNode.appendChild(acronymTermNode);
acronymTermNode.appendChild(SM->item->doc.createTextNode(acronymList[acroNum].term));
QDomNode acronymDefinitionNode = SM->item->doc.createElement("acronymDefinition");
acronymNode.appendChild(acronymDefinitionNode);
acronymDefinitionNode.toElement().setAttribute("id", acronymList[acroNum].id);
acronymDefinitionNode.appendChild(SM->item->doc.createTextNode(acronymList[acroNum].definition));
continue;
}
if(insetName == "CommandInset ref") {
//if(lyxList.at(_insetBeg+2).split(" ")[0] != "reference") continue;
QString refID = "";
for(int l=_insetBeg+2;l<=_insetEnd;l++)
if(lyxList.at(l).startsWith("reference")) {
refID = QString(lyxList.at(l)).mid(11).replace("\"", "");
break;
}
if(refID == "") continue;
//lyxList.at(_insetBeg+2).right(lyxList.at(_insetBeg+2).length() - 10).replace("\"", "");
if(refID.left(3) == "fn:") { // ссылка на footnote
int acroNum = -1;
for(int j=0;j<acronymList.count();j++)
if(acronymList[j].lyxFootnoteName == refID) {acroNum = j; break;}
if(acroNum == -1) {
acroNum = acronymList.count();
acronymStruct newAcronym;
newAcronym.lyxFootnoteName = refID;
newAcronym.term = refID.mid(3);
newAcronym.id = "ftn-"; for(int j=0;j<4-QString::number(acroNum).length();j++) newAcronym.id += "0";
newAcronym.id += QString::number(acroNum);
acronymList.append(newAcronym);
}
QDomNode footnoteRef = SM->item->doc.createElement("footnoteRef");
footnoteRef.toElement().setAttribute("internalRefId", acronymList[acroNum].id);
domCurLevelNode.appendChild(footnoteRef);
} else { // внутренняя ссылка
int foundLabel = -1;
for(int j=0;j<labelList.count();j++)
if(refID == labelList[j].lyxLabel) { foundLabel = j; break; }
QDomNode internalRef = SM->item->doc.createElement("internalRef");
if(foundLabel == -1) {
if(internalRefList.indexOf(refID) == -1)
internalRefList.append(refID);
//qDebug() << "+ref: "+refID;
}
else {
//qDebug() << "internalRef foundLabel: "+refID+" -> "+labelList[foundLabel].id;
refID = labelList[foundLabel].id;
}
internalRef.toElement().setAttribute("xlink:actuate", "onRequest");
internalRef.toElement().setAttribute("xlink:show", "replace");
internalRef.toElement().setAttribute("xlink:href", "#"+refID); //labelList[foundLabel].id
internalRef.toElement().setAttribute("internalRefId", refID); //labelList[foundLabel].id
QString refTarget = "irtt07";
if(refID.left(3) == "fig") refTarget = "irtt01";
if(refID.left(3) == "tab") refTarget = "irtt02";
if(refID.left(3) == "par") refTarget = "irtt07";
if(refID.left(3) == "mma") refTarget = "irtt03";
if(refID.left(3) == "fig" && refID.mid(9,3) == "hot") refTarget = "irtt11";
internalRef.toElement().setAttribute("internalRefTargetType", refTarget);
domCurLevelNode.appendChild(internalRef);
}
continue;
// <objectUse>attribute internalRefTargetType - Тип объекта внутренней ссылки [BRDP-S1-00100] (Глава 3.9.6.1, таблица 25)</objectUse>
// irtt01 Рисунок (figure)
// irtt02 table (table)
// irtt03 Мультимедиа (multimedia)
// irtt04 Предмет поставки (supply)
// irtt05 Вспомогательное оборудование (supportEquip)
// irtt06 Запасная деталь (spare)
// irtt07 Параграф (para, levelledPara)
// irtt08 Шаг (proceduralStep, faultIsolationStep, crewDrillStep)
// irtt09 Графическое изображение (graphic)
// irtt10 Мультимедийный объект (multimediaObject)
// irtt11 Активный участок (hotspot)
// irtt12 Параметр (parameter)
// irtt13 Зона (zone)
// irtt14 Место работы (workArea)
// irtt15 Набор материалов сервисного бюллетеня (в том числе отдельные, внешние и снятые материалы)
// irtt16 Точка доступа (accessPoint)
// <!-- Запрещено использовать irtt17~irtt99 -->
}
if(insetName == "CommandInset href") {
// <structureObjectRule>
// <objectPath allowedObjectFlag="0">//externalPubCode</objectPath>
// <objectUse>Заполнение элемента externalPubCode — Не использовать [BRDP-S1-00540]</objectUse>
// </structureObjectRule>
// <structureObjectRule>
// <objectPath allowedObjectFlag="0">//externalPubRef</objectPath>
// <objectUse>Формат ссылок в АУКНе использовать [BRDP-S1-00543]</objectUse>
// </structureObjectRule>
QString name, target, type; name = target = type = "";
for(int j=_insetBeg+1;j<_insetEnd;j++) {
if(lyxList[j].startsWith("name ")) name = lyxList[j].mid(5).replace("\"", "");
if(lyxList[j].startsWith("target ")) target = lyxList[j].mid(7).replace("\"", "");
if(lyxList[j].startsWith("type ")) type = lyxList[j].mid(5).replace("\"", "");
}
if(name == "" || target == "") {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка в гиперссылке ("+name+", "+target+")");
SM->item->isQualifyed = false;
continue;
}
QDomNode externalPubRef = SM->item->doc.createElement("externalPubRef");
domCurLevelNode.appendChild(externalPubRef);
QDomNode externalPubRefIdent = SM->item->doc.createElement("externalPubRefIdent");
externalPubRef.appendChild(externalPubRefIdent);
QDomNode externalPubCode = SM->item->doc.createElement("externalPubCode");
externalPubRefIdent.appendChild(externalPubCode);
if(type == "file:")
externalPubCode.toElement().setAttribute("pubCodingScheme", "file");
else
externalPubCode.toElement().setAttribute("pubCodingScheme", "URL");
externalPubCode.appendChild(SM->item->doc.createTextNode(target.replace("\\","/")));
QDomNode externalPubTitle = SM->item->doc.createElement("externalPubTitle");
externalPubRefIdent.appendChild(externalPubTitle);
externalPubTitle.appendChild(SM->item->doc.createTextNode(name));
continue;
}
if(insetName == "script superscript") {
QDomNode scriptNode = SM->item->doc.createElement("supScript");
domCurLevelNode.appendChild(scriptNode);
for(int j=_insetBeg+1;j<_insetEnd;j++)
if(lyxList.at(j).startsWith("\\begin_layout Plain Layout")) {
parseBlock(j+1, findTagEnd(j)-1, scriptNode);
break;
}
continue;
}
if(insetName == "script subscript") {
QDomNode scriptNode = SM->item->doc.createElement("subScript");
domCurLevelNode.appendChild(scriptNode);
for(int j=_insetBeg+1;j<_insetEnd;j++)
if(lyxList.at(j).startsWith("\\begin_layout Plain Layout")) {
parseBlock(j+1, findTagEnd(j)-1, scriptNode);
break;
}
continue;
}
if(insetName == "Float figure") {
figureTitle = ""; figureID = "";
QString lyxID;
int _graphicsBeg = -1; int _graphicsEnd = -1;
for(int j=_insetBeg+1;j<_insetEnd;j++) {
if(lyxList.at(j).startsWith("\\begin_inset Graphics")) {
_graphicsBeg = j; _graphicsEnd = findTagEnd(j);
j = _graphicsEnd;
}
if(lyxList.at(j).startsWith("\\begin_inset Caption Standard")) {
int _capEnd = findTagEnd(j);
for(int k=j+1;k<_capEnd;k++) {
if(lyxList.at(k).startsWith("\\begin_inset CommandInset label")) {
int _labelEnd = findTagEnd(k);
for(int l=k+1;l<_labelEnd;l++)
if(lyxList.at(l).startsWith("name")) {
lyxID = lyxList.at(l).right(lyxList.at(l).length() - 5).replace("\"", "");
break;
}
k = _labelEnd;
}
if(!lyxList.at(k).startsWith("\\"))
figureTitle += lyxList.at(k);
}
}
}
cntFigure += 1;
figureTitle = ru_const->figureTitle+" "+QString::number(docChapter+1)+"."+QString::number(cntFigure)+": "+figureTitle;
QString z; z.fill('0',3-QString::number(cntFigure).length());
figureID = "fig-" + z + QString::number(cntFigure);
//figureID = lyxID;
if(lyxID != "") {
int foundLabel = -1;
for(int j=0;j<labelList.count();j++)
if(lyxID == labelList[j].lyxLabel) {foundLabel = j; break;}
if(foundLabel != -1) {
if(labelList[foundLabel].defined) {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Повторное определение метки \""+figureID+"\" в изображении ("+figureTitle+")");
SM->item->isQualifyed = false;
}
} else {
labelStruct lbl;
lbl.lyxLabel = lyxID;
lbl.id = figureID;
labelList.append(lbl); foundLabel = labelList.count()-1;
//qDebug() << "+fig: lyx="+lyxID+" id="+figureID+" internalRefList.count()="+QString::number(internalRefList.count());
}
labelList[foundLabel].defined = true;
for(int j=0;j<internalRefList.count();j++) {
QString id = internalRefList[j];
if(id == lyxID) {
QList<QDomNode> nodeList;
QDomNode node;
nodeList.append(SM->item->doc.namedItem("dmodule").namedItem("content"));
while(!nodeList.isEmpty()) {
node = nodeList.takeFirst();
if(node.nodeName() == "internalRef")
if(//node.toElement().attributes().namedItem("internalRefId").nodeName() == "internalRefId" &&
node.toElement().attributes().namedItem("internalRefId").nodeValue() == lyxID) {
//qDebug() << " ! "+QString::number(j)+": "+ lyxID+ " -> "+figureID;
node.toElement().setAttribute("xlink:href", "#"+figureID);
node.toElement().setAttribute("internalRefId", figureID);
QString refTarget = "irtt07";
if(figureID.left(3) == "fig") refTarget = "irtt01";
if(figureID.left(3) == "tab") refTarget = "irtt02";
if(figureID.left(3) == "par") refTarget = "irtt07";
if(figureID.left(3) == "mma") refTarget = "irtt03";
if(figureID.left(3) == "fig" && figureID.mid(9,3) == "hot") refTarget = "irtt11";
node.toElement().setAttribute("internalRefTargetType", refTarget);
}
for(int k=0;k<node.childNodes().count();k++)
nodeList.append(node.childNodes().at(k));
}
// QString output;
// QTextStream stream(&output);
// domCurLevelNode.save(stream, 0);
// qDebug() << " "+output;
// output = "";
// qDebug() << " /-------------- begin -------------\\";
// domCurLevelNode.parentNode().save(stream, 0);
// qDebug() << " "+output;
// qDebug() << " \\-------------- end ---------------/";
internalRefList.removeAt(j); j--;
} else {
//qDebug() << " "+QString::number(j)+": "+id+" != "+lyxID;
}
}
}
if(_graphicsBeg == -1 || _graphicsEnd == -1)
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка вставки плавающего рисунка \""+figureTitle+"\"");
else
parseBlock(_graphicsBeg, _graphicsEnd, domCurLevelNode);
continue;
}
if(insetName == "Graphics") {
QString filename = "";
QString oldfilename = ""; QString newfilename;
for(int j=_insetBeg+1;j<_insetEnd;j++) {
//qDebug() << lyxList[j];
while(lyxList[j].startsWith(" ") || lyxList[j].startsWith("\t"))
lyxList[j] = lyxList[j].mid(1);
if(lyxList[j].startsWith("filename "))
filename = lyxList[j].mid(9);
}
if(filename == "") {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка чтения LyX Graphics ("+figureTitle+")");
SM->item->isQualifyed = false;
continue;
}
if(filename.startsWith("../")) filename = filename.mid(3);
QString absfilename = QString(QFileInfo(curLyXFileName).absolutePath()+"/"+filename);
if (QFile::exists(absfilename)) {
oldfilename = absfilename;
} else {
if (QFile::exists(filename)) {
oldfilename = filename;
lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Рекомендуется использовать относительные пути к файлам изображений: "+filename+" ("+figureTitle+")");
}
}
if(oldfilename == "") {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Файл изображения не найден "+filename+" ("+figureTitle+")");
SM->item->isQualifyed = false;
continue;
}
newfilename = SM->projectPath+"/"+ QString::number(docChapter+1) + "." + QString::number(docSection+1) + "." + QString::number(docSubsection+1) +
" " + QFileInfo(oldfilename).fileName();
if (QFile::exists(newfilename)) {
lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Дублирование имен файлов изображений: "+filename+" ("+figureTitle+")");
//newfilename = SM->projectPath+"/"+ QString::number(docChapter+1) + "." + QString::number(docSection+1) + "." + QString::number(docSubsection+1)+
// "_"+QFileInfo(oldfilename).fileName()+"("+QString::number(QRandomGenerator::global()->generate() % 0xFF)+")";
//if (QFile::exists(newfilename)) QFile::remove(newfilename);
QFile::remove(newfilename);
}
if(!QFile::copy(oldfilename, newfilename))
if(DBG) qDebug() << "lyx: Error copy" << oldfilename << "to" << newfilename;
QDomNode figure = SM->item->doc.createElement("figure");
domCurLevelNode.appendChild(figure);
if(figureID != "")
figure.toElement().setAttribute("id", figureID);
QDomNode title = SM->item->doc.createElement("title");
figure.appendChild(title);
title.appendChild(SM->item->doc.createTextNode(figureTitle));
QDomNode graphic = SM->item->doc.createElement("graphic");
figure.appendChild(graphic);
graphic.toElement().setAttribute("infoEntityIdent", QFileInfo(newfilename).fileName());
// если есть файл .txt с хотспотами - копируем его и файлы в нем указанные
QString txtoldfilename = oldfilename; txtoldfilename.replace(".svg", ".txt");
QString txtnewfilename = newfilename; txtnewfilename.replace(".svg", ".txt");
if(oldfilename.split(".").last().toLower() == "svg" && QFileInfo(txtoldfilename).exists()) {
if (QFile::exists(txtnewfilename)) QFile::remove(txtnewfilename);
if(!QFile::copy(txtoldfilename, txtnewfilename))
if(DBG) qDebug() << "lyx: Error copy" << txtoldfilename << "to" << txtnewfilename;
QFile txtFile(txtoldfilename);
if (!txtFile.open(QFile::ReadOnly)) {
qDebug() << "lyx: Ошибка открытия файла "+txtoldfilename;
return;
}
QByteArray data = txtFile.readAll();
for(int i=0;i < data.length()-2;i++)
if(int(data[i]) == 10 && int(data[i+1]) != 13) data[i] = 13;
QStringList txtLines = QString(QString(data).toUtf8()).replace("\r\r","\r").split("\r"); //
txtFile.close();
QDomDocument svg;
//splash->SetTitle("Обработка SVG файла: "+infoEntityIdent);
QFile svgFile(oldfilename);
if (!svgFile.open(QFile::ReadOnly | QFile::Text)){
qDebug() << "lyx: Ошибка открытия файла "+oldfilename;
return;
}
svg.setContent(svgFile.readAll());
svgFile.close();
QDomNode svgNode = svg.namedItem("svg");
if(svgNode.isNull()) {
qDebug() << "lyx: Ошибка в svg-файле "+oldfilename;
return;
}
QStringList txtNums, txtTitles, txtHotID;
foreach(QString s, txtLines)
if(s.indexOf(" - "))
{
txtNums.append(s.mid(0, s.indexOf(" - ")));
txtTitles.append(s.mid(s.indexOf(" - ")+3));
txtHotID.append("");
}
for(int j=0;j<svgNode.childNodes().count();j++)
{
if(!SM->isConsole) splash->Step();
QDomNode g = svgNode.childNodes().at(j);
if(g.nodeName() != "g") continue;
if(!SM->isConsole) splash->Step();
QDomNode spanNode = searchSVGNodeForSpanNode(g);
if(spanNode.isNull()) continue;
QString title = spanNode.childNodes().at(0).nodeValue();
if(title == "") continue;
int ind = txtNums.indexOf(title);
if(ind == -1) continue;
txtHotID[ind] = spanNode.attributes().namedItem("id").nodeValue();
}
int hotCnt=0;
bool isImage;
for(int j=0;j<txtNums.count();j++) {
isImage = false;
if(txtTitles[j].indexOf(".") != -1)
{
QString picfile = QFileInfo(oldfilename).path()+"/" + txtTitles[j];
QString newpicfile = SM->projectPath+"/"+txtTitles[j];
if(QFileInfo::exists(picfile)) {
if (QFile::exists(newpicfile)) QFile::remove(newpicfile);
if(!QFile::copy(picfile, newpicfile))
if(DBG) qDebug() << "lyx: Error copy" << picfile << "to" << newpicfile;
isImage = true;
}
}
QDomNode hotspot = SM->item->doc.createElement("hotspot");
graphic.appendChild(hotspot);
QString hotID; hotID.fill('0', 3-QString::number(hotCnt).length());
hotID = figureID+"-gra000-hot"+hotID+QString::number(hotCnt++);
hotspot.toElement().setAttribute("id", hotID);
hotspot.toElement().setAttribute("applicationStructureIdent", txtHotID[j]);
hotspot.toElement().setAttribute("applicationStructureName", txtNums[j]);
hotspot.toElement().setAttribute("hotspotTitle", txtTitles[j]);
hotspot.toElement().setAttribute("hotspotType", "callout");
if(!isImage)
hotspot.toElement().setAttribute("objectDescr", "text");
else
hotspot.toElement().setAttribute("objectDescr", "image");
}
}
//TODO child: <hotspot> 562 Chapter 3.9.5.2.1.8
figureTitle = ""; figureID = "";
continue;
}
if(insetName == "CommandInset label") {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Команда <метка> вне слоя, обратитесь к разработчику");
SM->item->isQualifyed = false;
continue;
}
if(insetName == "Float table") {
tableTitle = ""; tableID = "";
QString lyxID="";
int _tabularBeg = -1; int _tabularEnd = -1;
for(int j=_insetBeg+1;j<_insetEnd;j++) {
if(lyxList.at(j).startsWith("\\begin_inset Tabular")) {
_tabularBeg = j; _tabularEnd = findTagEnd(j);
j = _tabularEnd;
}
if(lyxList.at(j).startsWith("\\begin_inset Caption Standard")) {
int _capEnd = findTagEnd(j);
for(int k=j+1;k<_capEnd;k++) {
if(lyxList.at(k).startsWith("\\begin_inset CommandInset label")) {
int _labelEnd = findTagEnd(k);
for(int l=k+1;l<_labelEnd;l++)
if(lyxList.at(l).startsWith("name")) {
lyxID = lyxList.at(l).right(lyxList.at(l).length() - 5).replace("\"", "");
break;
}
k = _labelEnd;
}
if(!lyxList.at(k).startsWith("\\"))
tableTitle += lyxList.at(k);
}
}
}
cntTable += 1;
tableTitle = ru_const->tableTitle+" "+QString::number(docChapter+1)+"."+QString::number(cntTable)+": "+tableTitle;
QString z; z.fill('0',3-QString::number(cntTable).length());
tableID = "tab-" + z + QString::number(cntTable);
if(lyxID != "") {
int foundLabel = -1;
for(int j=0;j<labelList.count();j++)
if(lyxID == labelList[j].lyxLabel) {foundLabel = j; break;}
if(foundLabel != -1) {
if(labelList[foundLabel].defined) {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Повторное определение метки \""+tableID+"\" в таблице ("+tableTitle+")");
SM->item->isQualifyed = false;
}
} else {
labelStruct lbl;
lbl.lyxLabel = lyxID;
lbl.id = tableID; // в дальнейшем возможно пересмотреть и присваивать номера (tab-0001)
labelList.append(lbl); foundLabel = labelList.count()-1;
}
labelList[foundLabel].defined = true;
for(int j=0;j<internalRefList.count();j++) {
QString id = internalRefList[j];
if(id == lyxID) {
QList<QDomNode> nodeList;
QDomNode node;
nodeList.append(SM->item->doc.namedItem("dmodule").namedItem("content"));
while(!nodeList.isEmpty()) {
node = nodeList.takeFirst();
if(node.nodeName() == "internalRef")
if(//node.toElement().attributes().namedItem("internalRefId").nodeName() == "internalRefId" &&
node.toElement().attributes().namedItem("internalRefId").nodeValue() == lyxID) {
//qDebug() << " ! "+QString::number(j)+": "+ lyxID+ " -> "+tableID;
node.toElement().setAttribute("xlink:href", "#"+tableID);
node.toElement().setAttribute("internalRefId", tableID);
QString refTarget = "irtt07";
if(tableID.left(3) == "fig") refTarget = "irtt01";
if(tableID.left(3) == "tab") refTarget = "irtt02";
if(tableID.left(3) == "par") refTarget = "irtt07";
if(tableID.left(3) == "mma") refTarget = "irtt03";
if(tableID.left(3) == "fig" && tableID.mid(9,3) == "hot") refTarget = "irtt11";
node.toElement().setAttribute("internalRefTargetType", refTarget);
}
for(int k=0;k<node.childNodes().count();k++)
nodeList.append(node.childNodes().at(k));
}
internalRefList.removeAt(j); j--;
}
}
}
if(_tabularBeg == -1 || _tabularEnd == -1)
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка вставки плавающей таблицы \""+tableTitle+"\"");
else
parseBlock(_tabularBeg, _tabularEnd, domCurLevelNode);
continue;
}
if(insetName == "Tabular") {
QStringList colsAlign, colsVAlign;
int _lyxtabularBeg = findTag(_insetBeg+1, _insetEnd-1, "<lyxtabular");
int rows=0, cols=0;
for(int k=1;k<lyxList.at(_lyxtabularBeg).split(" ").count();k++) {
if(lyxList.at(_lyxtabularBeg).split(" ")[k].split("=")[0] == "rows")
rows = lyxList.at(_lyxtabularBeg).split(" ")[k].split("=")[1].replace("\"","").replace(">","").toInt();
if(lyxList.at(_lyxtabularBeg).split(" ")[k].split("=")[0] == "columns")
cols = lyxList.at(_lyxtabularBeg).split(" ")[k].split("=")[1].replace("\"","").replace(">","").toInt();
}
if(rows == 0 || cols == 0) continue;
for(int j=_lyxtabularBeg+1;j<findTag(_lyxtabularBeg+1, _insetEnd-1, "<row>");j++)
if(lyxList.at(j).startsWith("<column")) {
QString al = ""; QString val = "";
for(int k=1;k<lyxList.at(j).split(" ").count();k++) {
if(lyxList.at(j).split(" ")[k].split("=")[0] == "alignment")
al = lyxList.at(j).split(" ")[k].split("=")[1].replace("\"","");
if(lyxList.at(j).split(" ")[k].split("=")[0] == "valignment")
val = lyxList.at(j).split(" ")[k].split("=")[1].replace("\"","");
}
colsAlign.append(al); colsVAlign.append(val);
}
//<entry 546
QDomNode table = SM->item->doc.createElement("table");
domCurLevelNode.appendChild(table);
table.toElement().setAttribute("frame", "topbot");
if(tableID != "") table.toElement().setAttribute("id", tableID);
table.toElement().setAttribute("colsep", "0");
table.toElement().setAttribute("rowsep", "0");
table.toElement().setAttribute("tocentry", "1");
if(tableTitle != "") {
QDomNode title = SM->item->doc.createElement("title");
title.appendChild(SM->item->doc.createTextNode(tableTitle));
table.appendChild(title);
}
QDomNode tgroup = SM->item->doc.createElement("tgroup");
table.appendChild(tgroup);
tgroup.toElement().setAttribute("cols", QString::number(cols));
for(int j=0;j<cols;j++) {
QDomNode colspec = SM->item->doc.createElement("colspec");
colspec.toElement().setAttribute("colname", "col"+QString::number(j+1));
if(colsAlign.count() == cols)
colspec.toElement().setAttribute("align", colsAlign[j]);
tgroup.appendChild(colspec); //<colspec colname="col2" colwidth="1*"/>
}
QList<QList<cellStruct>> tableArr;
// cellStruct** tableArr = new cellStruct*[rows];
// for(int j=0;j<rows;j++)
// tableArr[j] = new cellStruct[cols];
// читаем таблицу в массив
int _rowBeg = _lyxtabularBeg; int _rowEnd = _lyxtabularBeg;
for(int j=0;j<rows;j++) {
QList<cellStruct> rowStruct;
tableArr.append(rowStruct);
_rowBeg = findTag(_rowEnd+1, _insetEnd, "<row");
_rowEnd = findTag(_rowBeg+1, _insetEnd, "</row>");
int _cellBeg = _rowBeg; int _cellEnd;
for(int k=0;k<cols;k++) {
cellStruct cellStructItem;
tableArr[j].append(cellStructItem);
_cellBeg = findTag(_cellBeg+1, _rowEnd-1, "<cell");
_cellEnd = findTag(_cellBeg+1, _rowEnd-1, "</cell>");
tableArr[j][k]._cellBeg = _cellBeg+1; tableArr[j][k]._cellEnd = _cellEnd-1;
if(_cellBeg == -1) break;
tableArr[j][k].alignment = tableArr[j][k].rotate = "";
tableArr[j][k].multiCol = tableArr[j][k].multiRow = "";
tableArr[j][k].checkPassed = false;
tableArr[j][k].topline = tableArr[j][k].bottomline = tableArr[j][k].leftline = tableArr[j][k].rightline = false;
tableArr[j][k].createS1000D_entry = true;
QStringList cellAttr = lyxList[_cellBeg].split(" ");
for(int l=1; l<cellAttr.count();l++) {
QString cellAttrName = cellAttr[l].split("=")[0];
QString cellAttrVal = cellAttr[l].split("=")[1].replace("\"","").replace(">","");
if(cellAttrName == "alignment")
tableArr[j][k].alignment = cellAttrVal;
if(cellAttrName == "rotate")
tableArr[j][k].rotate = cellAttrVal;
if(cellAttrName == "multicolumn") tableArr[j][k].multiCol = cellAttrVal;
if(cellAttrName == "multirow") tableArr[j][k].multiRow = cellAttrVal;
if(cellAttrName == "topline") tableArr[j][k].topline = (cellAttrVal == "true");
if(cellAttrName == "bottomline") tableArr[j][k].bottomline = (cellAttrVal == "true");
if(cellAttrName == "leftline") tableArr[j][k].leftline = (cellAttrVal == "true");
if(cellAttrName == "rightline") tableArr[j][k].rightline = (cellAttrVal == "true");
}
} //cols
} //rows
// выявляем multicolumn, multirow
int lastHeadRow = 0;
for(int j=0;j<rows;j++) {
for(int k=0;k<cols;k++)
if(!tableArr[j][k].checkPassed)
{
QString namest, nameend, spanname;
tableArr[j][k].colname = tableArr[j][k].spanname = "";
//qDebug() << j << k; // << tableArr[j][k].multiCol << tableArr[j][k].multiRow << tableArr[j][k].alignment << tableArr[j][k].rotate << tableArr[j][k].topline << "...";
if(tableArr[j][k].multiCol == "1") {
//qDebug() << " " << tableArr[j][k].multiCol;
namest = "col"+QString::number(k+1);
int l;
for(l=k+1;l<cols;l++)
if(tableArr[j][l].multiCol == "2") {
tableArr[j][l].createS1000D_entry = false;
tableArr[j][l].checkPassed = true;
} else
break;
spanname = "col"+QString::number(k+1)+"-"+QString::number(l-1+1);
nameend = "col"+QString::number(l-1+1);
tableArr[j][k].spanname = spanname;
}
if(tableArr[j][k].multiRow == "3") {
namest = "row"+QString::number(j+1);
int l;
for(l=j+1;l<rows;l++)
if(tableArr[l][k].multiRow == "4") {
tableArr[l][k].createS1000D_entry = false;
tableArr[l][k].checkPassed = true;
if(j == 0 && lastHeadRow < l) lastHeadRow = l;
} else
break;
spanname = "row"+QString::number(j+1)+"-"+QString::number(l-1+1);
nameend = "row"+QString::number(l-1+1);
tableArr[j][k].spanname = spanname;
}
tableArr[j][k].checkPassed = true;
if(tableArr[j][k].multiCol == "" && tableArr[j][k].multiRow == "") continue;
QDomNode spanspec = SM->item->doc.createElement("spanspec");
spanspec.toElement().setAttribute("namest", namest);
spanspec.toElement().setAttribute("nameend", nameend);
spanspec.toElement().setAttribute("spanname", spanname);
tgroup.appendChild(spanspec);
}
}
QDomNode thead = SM->item->doc.createElement("thead");
tgroup.appendChild(thead);
QDomNode tbody = SM->item->doc.createElement("tbody");
tgroup.appendChild(tbody);
// создаем dom из прочитанного
//bool rowToHead = true;
for(int j=0;j<rows;j++) {
QDomNode row = SM->item->doc.createElement("row");
//bool multiRowFlag = false;
for(int k=0;k<cols;k++) {
if (tableArr[j][k].createS1000D_entry) {
QDomNode entry = SM->item->doc.createElement("entry");
row.appendChild(entry);
if(tableArr[j][k].alignment != "")
entry.toElement().setAttribute("align", tableArr[j][k].alignment);
if(tableArr[j][k].rotate != "")
entry.toElement().setAttribute("rotate", tableArr[j][k].rotate);
if(tableArr[j][k].spanname != "")
entry.toElement().setAttribute("spanname", tableArr[j][k].spanname);
parseBlock(tableArr[j][k]._cellBeg+1, tableArr[j][k]._cellEnd-1, entry);
} //cols
//if(tableArr[j][k].multiRow != "") multiRowFlag = true;
}
//if(!multiRowFlag) rowToHead = false;
if(j <= lastHeadRow) { //j==0 || rowToHead
row.toElement().setAttribute("rowsep", "1");
thead.appendChild(row);
} else {
row.toElement().setAttribute("rowsep", "0");
tbody.appendChild(row);
}
} //rows
// for(int j=0;j<rows;j++)
// delete[] tableArr[j];
// delete[] tableArr;
tableTitle = ""; tableID = "";
continue;
}
if(insetName == "Text") {
parseBlock(_insetBeg+1, _insetEnd-1, domCurLevelNode);
continue;
}
if(insetName == "Newline newline") { // para 647
if(domCurLevelNode.nodeName() == "para") {
domCurLevelNode = domCurLevelNode.parentNode();
QDomNode newParaNode = SM->item->doc.createElement("para");
domCurLevelNode.appendChild(newParaNode);
domCurLevelNode = newParaNode;
}
continue;
}
if(insetName == "Note Note") {
QStringList noteContent;
bool flag = false;
QString txt="";
for(int j=_insetBeg+1;j<_insetEnd;j++) {
if(lyxList[j].startsWith("\\begin_layout Plain Layout")) { flag = true; txt = ""; continue; }
if(lyxList[j].startsWith("\\end_layout")) { flag = false; noteContent.append(txt); continue; }
if(lyxList[j] != "" && flag) txt += lyxList[j];
}
if(noteContent.count() == 0) continue;
if(noteContent[0] == "Video") { // стр. 557
QString oldfilename="", newfilename="";
if(noteContent[1].startsWith("../")) noteContent[1] = noteContent[1].mid(3);
QString absfilename = QString(QFileInfo(curLyXFileName).absolutePath()+"/"+noteContent[1]);
if (QFile::exists(absfilename)) {
oldfilename = absfilename;
} else {
if (QFile::exists(noteContent[1])) {
oldfilename = noteContent[1];
lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Рекомендуется использовать относительные пути к файлам видео: "+noteContent[1]);
}
}
if(oldfilename == "") {
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Файл видео не найден "+noteContent[1]);
SM->item->isQualifyed = false;
continue;
}
newfilename = SM->projectPath+"/"+ QFileInfo(oldfilename).fileName();
if (QFile::exists(newfilename)) {
lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Дублирование имен файлов видео: "+noteContent[1]);
//newfilename = SM->projectPath+"/"+ QFileInfo(oldfilename).fileName() + "("+QString::number(QRandomGenerator::global()->generate() % 0xFF)+")";
}
if (QFile::exists(newfilename)) QFile::remove(newfilename);
if(!QFile::copy(oldfilename, newfilename))
if(DBG) qDebug() << "lyx: Error copy" << oldfilename << "to" << newfilename;
QDomNode multimedia = SM->item->doc.createElement("multimedia");
domCurLevelNode.appendChild(multimedia);
QDomNode title = SM->item->doc.createElement("title");
multimedia.appendChild(title);
title.appendChild(SM->item->doc.createTextNode(noteContent[2]));
QDomNode multimediaObject = SM->item->doc.createElement("multimediaObject");
multimedia.appendChild(multimediaObject);
multimediaObject.toElement().setAttribute("infoEntityIdent", QFileInfo(newfilename).fileName());
multimediaObject.toElement().setAttribute("multimediaType", "video");
continue;
}
if(noteContent[0] == "3D") {
if(noteContent.length() < 4) {
lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка подключения 3D: синтаксис - 3D / имя файла / титул / имя сценария."+noteContent[1]);
return;
}
//QString scfilename = QFileInfo(curLyXFileName).absolutePath()+"/"+ QFileInfo(noteContent[1]).path()+"/StreamingAssets/Scenario/"+QFileInfo(noteContent[3]).fileName();
//if (!QFile::exists(scfilename)) {
// lyxLog.append("#["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Ошибка подключения 3D: файл сценария не найден ("+scfilename+")");
// return;
//}
QDomNode multimedia = SM->item->doc.createElement("multimedia");
domCurLevelNode.appendChild(multimedia);
QDomNode title = SM->item->doc.createElement("title");
multimedia.appendChild(title);
title.appendChild(SM->item->doc.createTextNode(noteContent[2]));
QDomNode multimediaObject = SM->item->doc.createElement("multimediaObject");
multimedia.appendChild(multimediaObject);
multimediaObject.toElement().setAttribute("infoEntityIdent", noteContent[1]);
multimediaObject.toElement().setAttribute("multimediaType", "3D");
QDomNode parameter = SM->item->doc.createElement("parameter");
parameter.toElement().setAttribute("id", "");
parameter.toElement().setAttribute("scenario", noteContent[3]);
multimediaObject.appendChild(parameter);
continue;
}
//lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Неизвестные параметры заметки ("+noteContent[0]+").");
//SM->item->isQualifyed = false;
continue;
}
if(insetName == "Quotes rld") {
blockText += "«";
continue;
}
if(insetName == "Quotes rrd") {
blockText += "»";
continue;
}
lyxLog.append("!["+QString::number(_insetBeg+lyxEmptyCnt[_insetBeg])+"] Неизвестная команда ("+itemName+").");
SM->item->isQualifyed = false;
//popFlags(); //???
continue;
}
if(itemName.startsWith("\\begin_")) {
lyxLog.append("!["+QString::number(i+lyxEmptyCnt[i])+"] Неизвестный блок ("+itemName+").");
SM->item->isQualifyed = false;
int _childBeg, _childEnd;
_childBeg = i; _childEnd = findTagEnd(_childBeg);
i = _childEnd;
continue;
}
lyxLog.append("!["+QString::number(i+lyxEmptyCnt[i])+"] Неизвестная команда ("+itemName+").");
SM->item->isQualifyed = false;
}
if(curSubsectionItem != -1) SM->items[curSubsectionItem].lyxLog = lyxLog;
if(blockText != "") {
QDomNode blockTextNode = SM->item->doc.createTextNode(blockText);
QDomNode tmpCurNode = domCurLevelNode;
if(flags.bold) {
QDomNode emphasisNode = SM->item->doc.createElement("emphasis");
tmpCurNode.appendChild(emphasisNode); tmpCurNode = emphasisNode;
}
if(flags.italic) {
QDomNode emphasisNode = SM->item->doc.createElement("emphasis");
emphasisNode.toElement().setAttribute("emphasisType", "em02");
tmpCurNode.appendChild(emphasisNode); tmpCurNode = emphasisNode;
}
if(flags.underlined) {
QDomNode emphasisNode = SM->item->doc.createElement("emphasis");
emphasisNode.toElement().setAttribute("emphasisType", "em03"); //"em04" Overline, "em05" Strikethrough, "em51" - "em99" Available for projects
tmpCurNode.appendChild(emphasisNode); tmpCurNode = emphasisNode;
}
tmpCurNode.appendChild(blockTextNode);
}
popFlags();
return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ END OF PARSE BLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void LyX::appendChapter(QString title) {
// if(title == "") {
// title = "Имя главы не задано (создано автоматически)";
// lyxLog.append("!Ошибка в структуре заголовков: "+title);
// SM->item->isQualifyed = false;
// }
docChapter++; docSection = docSubsection = -1;
cntTable = cntFigure = cntPar = 0;
if(lyxLog.count() == 2) lyxLog.append("#Завершено без ошибок.");
if(curSubsectionItem != -1) SM->items[curSubsectionItem].lyxLog = lyxLog;
curChapterItem = SM->createPM(-1, -1);
SM->setCurItem(curChapterItem);
curSectionItem = curSubsectionItem = -1;
SM->item->origTitle = title;
SM->item->fileName = QString::number(docChapter+1) + " " + title + ".xml"; // SM->projectPath + "/" +
SM->setNodeText("identAndStatusSection.pmAddress.pmAddressItems.pmTitle", title);
//QString id = "par-"+QString::number(docChapter+1)+QString::number(docSection+1)+QString::number(docSubsection+1)+"0";
tableOfContentsStruct tocItem;
tocItem.id = ""; tocItem.title = title;
tableOfContentsRoot.childs.append(tocItem);
}
void LyX::appendSection(QString title) {
// if(title == "") {
// title = "Имя раздела не задано (создано автоматически)";
// lyxLog.append("!Ошибка в структуре заголовков: "+title);
// }
docSection++; docSubsection = -1;
if(lyxLog.count() == 2) lyxLog.append("#Завершено без ошибок.");
if(curSubsectionItem != -1) SM->items[curSubsectionItem].lyxLog = lyxLog;
curSectionItem = SM->createPM(curChapterItem, SM->items[curChapterItem].child.count()-1);
SM->setCurItem(curSectionItem);
curSubsectionItem = -1;
SM->item->origTitle = title;
SM->item->fileName = QString::number(docChapter+1) + "." + QString::number(docSection+1) + " " + title + ".xml";
SM->setNodeText("identAndStatusSection.pmAddress.pmAddressItems.pmTitle", title);
//QString id = "par-"+QString::number(docChapter+1)+QString::number(docSection+1)+QString::number(docSubsection+1)++"0";
tableOfContentsStruct tocItem;
tocItem.id = ""; tocItem.title = title;
tableOfContentsRoot.childs[docChapter].childs.append(tocItem);
}
void LyX::appendSubsection(QString title) {
// if(title == "") {
// title = "Имя подраздела не задано (создано автоматически)";
// lyxLog.append("!Ошибка в структуре заголовков: "+title);
// }
docSubsection++;
if(lyxLog.count() == 2) lyxLog.append("#Завершено без ошибок.");
if(curSubsectionItem != -1) SM->items[curSubsectionItem].lyxLog = lyxLog;
//SM->item->fileName = QString::number(docChapter+1) + "." + QString::number(docSection+1) + "." + QString::number(docSubsection+1) + " " + title + ".xml";
if(title.startsWith("~")) {
curSubsectionItem = SM->createDM(curSectionItem, SM->items[curSectionItem].child.count()-1, "LEARNING");
title = title.mid(1);
} else
curSubsectionItem = SM->createDM(curSectionItem, SM->items[curSectionItem].child.count()-1, "DESCRIPT");
SM->setCurItem(curSubsectionItem);
SM->item->origTitle = title;
SM->item->fileName = QString::number(docChapter+1) + "." + QString::number(docSection+1) + "." + QString::number(docSubsection+1) + " " + title + ".xml";
SM->setNodeText("identAndStatusSection.dmAddress.dmAddressItems.dmTitle.techName", title);
//QString id = "par-"+QString::number(docChapter+1)+QString::number(docSection+1)+QString::number(docSubsection+1)+QString::number(docSubsubsection+1);
tableOfContentsStruct tocItem;
tocItem.id = ""; tocItem.title = title;
tableOfContentsRoot.childs[docChapter].childs[docSection].childs.append(tocItem);
}
void LyX::checkForOldIdent() {
QDomDocument doc;
QFile xmlFile(SM->projectPath + "/Backup/" + SM->item->fileName);
if (!xmlFile.open(QFile::ReadOnly | QFile::Text)) {
SM->item->isQualifyed = false;
return;
}
QByteArray fileData = xmlFile.readAll();
xmlFile.close();
doc.setContent(fileData);
QString curST = QFileInfo(doc.documentElement().attribute("xsi:noNamespaceSchemaLocation", "")).baseName().toUpper();
QString curMT = doc.documentElement().nodeName().toUpper();
if(curMT == "DMODULE" && SM->item->moduleType != mtDM) return;
if(curMT == "PM" && SM->item->moduleType != mtPM) return;
if(SM->item->schemeType != SM->getSchemeTypeByStr(curST)) {
if(DBG) qDebug() << " Несоответствует тип схемы при импорте identAndStatusSection: " + SM->item->fileName;
return;
}
QDomNode oldIdent;
oldIdent = doc.documentElement().namedItem("identAndStatusSection").cloneNode();
if(oldIdent.isNull()) return;
SM->deleteNode("identAndStatusSection");
SM->item->doc.importNode(oldIdent, true);
SM->item->doc.documentElement().insertBefore(oldIdent, SM->findElement("content"));
QDomNode oldDescr = doc.documentElement().namedItem("rdf:Description").cloneNode();
if(oldDescr.isNull()) return;
SM->deleteNode("rdf:Description");
SM->item->doc.importNode(oldDescr, true);
SM->item->doc.documentElement().insertBefore(oldDescr, SM->findElement("identAndStatusSection"));
//SM->item->crewFlags = oldDescr.attributes().namedItem("flags").nodeValue().toInt(nullptr,16);
if(SM->item->isQualifyed)
SM->item->isQualifyed = (oldDescr.attributes().namedItem("qualifyed").nodeValue() == "true");
//if(DBG) qDebug() << " loaded ident from " + SM->projectPath + "/Backup/" + SM->item->fileName;
}
void LyX::pushFlags() {
flagsStack.append(flags);
}
void LyX::popFlags() {
if(flagsStack.count() == 0) return;
flags = flagsStack.takeLast();
}
void LyX::pushLyXFileData() {
fileStruct lyxFileData;
lyxFileData.fileName = curLyXFileName;
lyxFileData.lyxList = lyxList;
lyxFileStack.append(lyxFileData);
}
void LyX::popLyXFileData() {
if(lyxFileStack.count() == 0) return;
fileStruct lyxFileData = lyxFileStack.takeLast();
curLyXFileName = lyxFileData.fileName;
lyxList = lyxFileData.lyxList;
}
void LyX::fillTableOfContents(tableOfContentsStruct tocNode, QDomNode domToCNode, QString deepSpaces) {
for(int i=0;i<tocNode.childs.count();i++) {
QDomNode para = SM->item->doc.createElement("para");
QDomText spaces = SM->item->doc.createTextNode(deepSpaces);
para.appendChild(spaces);
QDomNode internalRef = SM->item->doc.createElement("internalRef");
internalRef.toElement().setAttribute("xlink:actuate", "onRequest");
internalRef.toElement().setAttribute("xlink:show", "replace");
internalRef.toElement().setAttribute("xlink:href", "#"+tocNode.childs[i].id);
internalRef.toElement().setAttribute("internalRefId", tocNode.childs[i].id);
internalRef.toElement().setAttribute("internalRefTargetType", "irtt07");
para.appendChild(internalRef);
fillTableOfContents(tocNode.childs[i], para, deepSpaces+" ");
domToCNode.appendChild(para);
}
}
void LyX::fillAcronymList(QDomNode domAcronymListNode) {
//QDomNode paraTitle = SM->item->doc.createElement("para");
//domAcronymListNode.appendChild(paraTitle); paraTitle.appendChild(SM->item->doc.createTextNode(ru_const->acronymsList+"\n"));
QDomNode para = SM->item->doc.createElement("para");
domAcronymListNode.appendChild(para);
QDomNode table = SM->item->doc.createElement("table");
para.appendChild(table);
QDomNode tgroup = SM->item->doc.createElement("tgroup");
tgroup.toElement().setAttribute("cols", "2");
table.appendChild(tgroup);
QDomNode colspec = SM->item->doc.createElement("colspec");
colspec.toElement().setAttribute("colwidth", "1*");
tgroup.appendChild(colspec);
colspec = SM->item->doc.createElement("colspec");
colspec.toElement().setAttribute("colwidth", "4*");
tgroup.appendChild(colspec);
QDomNode tbody = SM->item->doc.createElement("tbody");
tgroup.appendChild(tbody);
QStringList sortedList;
for(int i=0;i<acronymList.count();i++)
sortedList.append(acronymList[i].term);
// qSort(sortedList.begin(), sortedList.end());
std::sort(sortedList.begin(), sortedList.end());
for(int i=0;i<sortedList.count();i++)
for(int j=0;j<acronymList.count();j++)
if(sortedList[i] == acronymList[j].term) {
QDomNode row = SM->item->doc.createElement("row");
tbody.appendChild(row);
QDomNode entry = SM->item->doc.createElement("entry");
row.appendChild(entry);
QDomNode para = SM->item->doc.createElement("para");
entry.appendChild(para);
// QDomNode internalRef = SM->item->doc.createElement("internalRef");
// internalRef.toElement().setAttribute("xlink:actuate", "onRequest");
// internalRef.toElement().setAttribute("xlink:show", "replace");
// internalRef.toElement().setAttribute("xlink:href", "#"+acronymList[j].id);
// internalRef.toElement().setAttribute("internalRefId", acronymList[j].id);
// QString refTarget = "irtt07";
// internalRef.toElement().setAttribute("internalRefTargetType", refTarget);
// internalRef.appendChild(SM->item->doc.createTextNode(acronymList[j].term));
// para.appendChild(internalRef);
para.appendChild(SM->item->doc.createTextNode(acronymList[j].term));
entry = SM->item->doc.createElement("entry");
row.appendChild(entry);
para = SM->item->doc.createElement("para");
entry.appendChild(para);
para.appendChild(SM->item->doc.createTextNode(acronymList[j].definition));
break;
}
}
int LyX::parseLearningModule(QDomNode domLearnNode, int _learnBeg, int _learnMaxEnd) {
QString itemName, text;
int i, _lend;
bool isQuestion;
QString question;
QStringList answers;
SM->setNodeText("content.learning.learningAssessment.title", ""); // что сюда поставить?
for(i=_learnBeg;i<=_learnMaxEnd;i++) {
itemName = lyxList[i];
if(itemName == "") continue;
if(itemName == "\\begin_layout Standard") {
_lend = findTagEnd(i);
text = ""; isQuestion = false;
for(int j=i+1;j<_lend;j++) {
if(lyxList[j] == "") continue;
if(lyxList[j] == "\\series bold") { isQuestion = true; continue; }
text += lyxList[j];
}
i = _lend;
if(!isQuestion && !text.startsWith("+") && !text.startsWith("-")) {
lyxLog.append("!["+QString::number(i+lyxEmptyCnt[i])+"] Неизвестный тип ответа ("+text+")");
SM->item->isQualifyed = false;
continue;
}
if(isQuestion) {
if(question != "") {
addQuestInteraction(domLearnNode, question, answers);
question = ""; answers.clear();
}
question = text;
continue;
}
answers.append(text);
continue;
}
break;
}
if(question != "")
addQuestInteraction(domLearnNode, question, answers);
return i-1;
}
void LyX::addQuestInteraction(QDomNode domLearnNode, QString question, QStringList answers) {
if(!SM->isConsole) splash->Step();
int correctAnswers=0;
foreach (QString s, answers)
if(s.startsWith("+")) correctAnswers++;
if(answers.count() == 0) {
lyxLog.append("! Отсутствуют ответы к вопросу ("+question+")");
SM->item->isQualifyed = false;
return;
}
if(correctAnswers == 0) {
lyxLog.append("! Кол-во верных ответов = 0 ("+question+")");
SM->item->isQualifyed = false;
return;
}
// question = questLyXtoHTML(question);
// for(int i=0;i<answers.count();i++)
// answers[i] = questLyXtoHTML(answers[i]);
QDomNode lcInteraction = SM->item->doc.createElement("lcInteraction");
domLearnNode.appendChild(lcInteraction);
QDomNode lcSelect;
QString lcName;
if(correctAnswers == 1)
lcName = "lcSingleSelect";
else
lcName = "lcMultipleSelect";
lcSelect = SM->item->doc.createElement(lcName);
lcInteraction.appendChild(lcSelect);
lcSelect.toElement().setAttribute("lcName", lcName);
QDomNode lcQuestion = SM->item->doc.createElement("lcQuestion");
lcSelect.appendChild(lcQuestion);
QDomNode questdescription = SM->item->doc.createElement("description");
lcQuestion.appendChild(questdescription);
QDomNode questpara = SM->item->doc.createElement("para");
questdescription.appendChild(questpara);
questpara.appendChild(SM->item->doc.createTextNode(question));
QDomNode lcAnswerOptionGroup = SM->item->doc.createElement("lcAnswerOptionGroup");
lcSelect.appendChild(lcAnswerOptionGroup);
bool isCorrect;
foreach (QString s, answers) {
if(!s.startsWith("+") && !s.startsWith("-")) lyxLog.append("# Ответ должен начинаться со знака +/- ("+s+"). Учтен как отрицательный.");
isCorrect = s.startsWith("+");
s = s.mid(1);
if(s.startsWith(" ")) s = s.mid(1);
QDomNode lcAnswerOption = SM->item->doc.createElement("lcAnswerOption");
lcAnswerOptionGroup.appendChild(lcAnswerOption);
QDomNode lcAnswerOptionContent = SM->item->doc.createElement("lcAnswerOptionContent");
lcAnswerOption.appendChild(lcAnswerOptionContent);
QDomNode answerdescription = SM->item->doc.createElement("description");
lcAnswerOptionContent.appendChild(answerdescription);
QDomNode answerpara = SM->item->doc.createElement("para");
answerdescription.appendChild(answerpara);
answerpara.appendChild(SM->item->doc.createTextNode(s));
if(isCorrect) {
QDomNode lcCorrectResponse = SM->item->doc.createElement("lcCorrectResponse");
lcAnswerOption.appendChild(lcCorrectResponse);
lcCorrectResponse.toElement().setAttribute("lcName", "lcCorrectResponse");
}
}
}
//QString LyX::questLyXtoHTML(QString answer) {
// // функция пока не используется
// qDebug() << answer;
// QString sb, se;
// int _end, _beg;
// while(1) {
// sb = "\\begin_inset script superscript\\begin_layout Plain Layout";
// se = "\\end_layout\\end_inset";
// _beg = answer.indexOf(sb);
// if(_beg != -1) {
// //QString innertext = answer.mid(_beg+sb.length(), _end-_beg-sb.length());
// answer = answer.replace(_beg, sb.length(), "<sup><small>");
// _end = answer.indexOf(se, _beg);
// answer = answer.replace(_end, se.length(), "</small></sup>");
// continue;
// }
// sb = "\\begin_inset script subscript\\begin_layout Plain Layout";
// se = "\\end_layout\\end_inset";
// _beg = answer.indexOf(sb);
// if(_beg != -1) {
// answer = answer.replace(_beg, sb.length(), "<sub><small>");
// _end = answer.indexOf(se, _beg);
// answer = answer.replace(_end, se.length(), "</small></sub>");
// continue;
// }
// break;
// }
// qDebug() << " "+answer;
// return answer;
//}
QDomNode LyX::searchSVGNodeForSpanNode(QDomNode node) {
if(node.nodeName() == "tspan")
return node;
QDomNode nd;
for(int j=0;j<node.childNodes().count();j++) {
QDomNode nd = searchSVGNodeForSpanNode(node.childNodes().at(j));
if(!nd.isNull()) return nd;
}
return nd;
}
//lyxLog.append("childNodes:");
//for(int a=0;a<domRootNode.childNodes().count();a++) { // дебаг-костыль деревянный :)
// QDomNode ch1 = domRootNode.childNodes().at(a);
// lyxLog.append(" " + ch1.nodeName() + " - " + ch1.nodeValue());
// for(int b=0;b<ch1.childNodes().count();b++) {
// QDomNode ch2 = ch1.childNodes().at(b);
// lyxLog.append(" " + ch2.nodeName() + " - " + ch2.nodeValue());
// for(int c=0;c<ch2.childNodes().count();c++) {
// QDomNode ch3 = ch2.childNodes().at(c);
// lyxLog.append(" " + ch3.nodeName() + " - " + ch3.nodeValue());
// for(int d=0;d<ch3.childNodes().count();d++) {
// QDomNode ch4 = ch3.childNodes().at(d);
// lyxLog.append(" " + ch4.nodeName() + " - " + ch4.nodeValue());
// for(int e=0;e<ch4.childNodes().count();e++) {
// QDomNode ch5 = ch4.childNodes().at(e);
// lyxLog.append(" " + ch5.nodeName() + " - " + ch5.nodeValue());
// for(int f=0;f<ch5.childNodes().count();f++) {
// QDomNode ch6 = ch5.childNodes().at(f);
// lyxLog.append(" " + ch6.nodeName() + " - " + ch6.nodeValue());
// //for(int i=0;i<ch4.childNodes().count();i++) {
// //
// //}
// }
// }
// }
// }
// }
//}
// Сообщество SVG и в частности разработчик Jonathan Watt
// рекомендуют (https://jwatt.org/svg/authoring/#doctype-declaration) не использовать декларацию DOCTYPE в SVG версий 1.0 и 1.1.
// Вместо этого рекомендовано включать атрибут baseProfile в корневой элемент svg со значением “full”.
// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
// <svg version="1.1"
// baseProfile="full"
// xmlns="http://www.w3.org/2000/svg"
// xmlns:xlink="http://www.w3.org/1999/xlink"
// xmlns:ev="http://www.w3.org/2001/xml-events"