From 77b2c7e58ddc944d6be4cde12d34654ea3b41f13 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Thu, 16 Jul 2020 17:56:46 +0300 Subject: [PATCH] batch mode and bug fix --- Fb2File/Fb2File.cpp | 325 ++++++++++++++++++++++++------------------ Fb2File/Fb2File.h | 14 +- Fb2File/test/main.cpp | 104 +++++++++++--- 3 files changed, 283 insertions(+), 160 deletions(-) diff --git a/Fb2File/Fb2File.cpp b/Fb2File/Fb2File.cpp index efffb0b964..47acb4d450 100644 --- a/Fb2File/Fb2File.cpp +++ b/Fb2File/Fb2File.cpp @@ -96,7 +96,7 @@ struct SDocumentInfo std::wstring* m_pProgramUsed; // Использованные программы std::wstring* m_pSrcOcr; // Автор текста - std::wstring* m_pHistory; // История (ФОРМАТИРОВАННЫЙ ТЕКСТ) + std::wstring* m_pHistory; // История SDocumentInfo() { @@ -157,7 +157,6 @@ public: NSStringUtils::CStringBuilder m_oBuilder; // Текст std::wstring m_sTmpFolder; // Рабочая папка - int m_nImageId; // ID картинки int m_nFootnoteId; // ID ссылки int m_nContentsId; // ID оглавления @@ -173,13 +172,14 @@ public: { m_pSrcTitleInfo = NULL; m_pPublishInfo = NULL; - m_nImageId = 1; m_nFootnoteId = 1; m_nContentsId = 1; + m_sTmpFolder = L""; } ~CFb2File_Private() { + NSDirectory::DeleteDirectory(m_sTmpFolder); m_oLightReader.Clear(); m_mFootnotes.clear(); m_mImages.clear(); @@ -227,12 +227,14 @@ public: } // Читает binary - void getImage(const std::wstring& sPath, const std::wstring& sMediaDirectory, NSStringUtils::CStringBuilder& oRels) + bool getImages(const std::wstring& sPath, const std::wstring& sMediaDirectory, NSStringUtils::CStringBuilder& oRels) { // Открывает файл - m_oLightReader.FromFile(sPath); + if (!m_oLightReader.FromFile(sPath)) + return false; // Читаем FictionBook - isSection(L"FictionBook"); + if(!isSection(L"FictionBook")) + return false; int nImageId = 1; int nDeath = m_oLightReader.GetDepth(); @@ -274,7 +276,7 @@ public: unsigned int nX = 4000000; unsigned int nY = oBgraFrame.get_Height() * nX / oBgraFrame.get_Width(); std::vector vImage; - vImage.push_back(L"rPic" + sImageId); + vImage.push_back(sImageId); vImage.push_back(std::to_wstring(nX)); vImage.push_back(std::to_wstring(nY)); @@ -289,6 +291,7 @@ public: } } m_oLightReader.Clear(); + return true; } // Читает image @@ -315,7 +318,6 @@ public: if(it != m_mImages.end()) { // Пишем картинку в файл - std::wstring sImageId = std::to_wstring(m_nImageId++); oBuilder += L""; // extent // РАЗМЕРЫ КАРТИНКИ @@ -326,17 +328,17 @@ public: oBuilder += L"\"/>"; // docPr oBuilder += L"second[0]; oBuilder += L"\" name=\"\"/>"; // graphic oBuilder += L""; // pic:nvPicPr oBuilder += L"second[0]; oBuilder += L"\" name=\"\"/>"; // pic:blipFill // рельсы rPic + id - oBuilder += L"second[0]; oBuilder += L"\"/>"; // pic:spPr @@ -471,23 +473,21 @@ public: } } m_oLightReader.MoveToElement(); + // Читаем текст внутри ссылки + readP(sRStyle, oBuilder); if(sFootnoteName == L"") continue; - // Читаем текст внутри ссылки - readP(sRStyle, oBuilder); - - // Пишем ссылку - std::wstring sFootnoteId = std::to_wstring(m_nFootnoteId); - oBuilder += L""; - // Стиль ссылки - oBuilder += L""; - oBuilder += L""; - - m_mFootnotes.insert(std::make_pair(sFootnoteName, sFootnoteId)); - m_nFootnoteId++; + std::map::iterator it = m_mFootnotes.find(sFootnoteName); + if(it != m_mFootnotes.end()) + { + oBuilder += L""; + // Стиль ссылки + oBuilder += L""; + oBuilder += L"second; + oBuilder += L"\"/>"; + } } // Читаем вычеркнутый текст else if(sName == L"strikethrough") @@ -684,11 +684,7 @@ public: readAnnotation(); // Читаем вложенные section (любое) else if(sName == L"section") - { - m_oBuilder += L""; readSection(nLevel + 1); - m_oBuilder += L""; - } // Читаем произвольный набор else if(sName == L"p") { @@ -744,106 +740,128 @@ public: } // Читает body с именем notes - void readNotes(NSStringUtils::CStringBuilder& oFootnotes) + void readNotes(const std::wstring& sPath, NSStringUtils::CStringBuilder& oFootnotes) { + // Открываем файл + m_oLightReader.FromFile(sPath); + // Читаем FictionBook + isSection(L"FictionBook"); + + int nFootnoteId = 1; int nDepth = m_oLightReader.GetDepth(); while(m_oLightReader.ReadNextSiblingNode(nDepth)) { - // Читаем section (один или более) - if(m_oLightReader.GetName() == L"section") + // Читаем body + if(m_oLightReader.GetName() == L"body") { - // Читаем id - std::wstring sFootnoteName = L""; + bool bNotes = false; while(m_oLightReader.MoveToNextAttribute()) { - if(m_oLightReader.GetName() == L"id") - { - sFootnoteName = m_oLightReader.GetText(); - break; - } + if(m_oLightReader.GetName() == L"name" && + m_oLightReader.GetText() == L"notes") + bNotes = true; } m_oLightReader.MoveToElement(); - if(sFootnoteName == L"") + if(!bNotes) continue; - - // Ищем сноску в списке требующихся - std::map::iterator it = m_mFootnotes.find(sFootnoteName); - if(it != m_mFootnotes.end()) + int nBDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nBDepth)) { - // Пишем сноску - oFootnotes += L"second; - oFootnotes += L"\">"; - - // Читаем внутренность section - int nSDepth = m_oLightReader.GetDepth(); - while(m_oLightReader.ReadNextSiblingNode(nSDepth)) + // Читаем section (один или более) + if(m_oLightReader.GetName() == L"section") { - std::wstring sName = m_oLightReader.GetName(); - if(sName == L"title") + // Читаем id + std::wstring sFootnoteName = L""; + while(m_oLightReader.MoveToNextAttribute()) { - int nTDepth = m_oLightReader.GetDepth(); - while(m_oLightReader.ReadNextSiblingNode(nTDepth)) + if(m_oLightReader.GetName() == L"id") { - if(m_oLightReader.GetName() == L"p") - { - // Стиль section-p - oFootnotes += L""; - oFootnotes += L""; - oFootnotes += L""; - readP(L"", oFootnotes); - oFootnotes += L""; - } + sFootnoteName = m_oLightReader.GetText(); + break; } } - else if(sName == L"p" || sName == L"subtitle") + m_oLightReader.MoveToElement(); + if(sFootnoteName == L"") + continue; + + std::wstring sFootnoteId = std::to_wstring(nFootnoteId++); + m_mFootnotes.insert(std::make_pair(sFootnoteName, sFootnoteId)); + // Пишем сноску + oFootnotes += L""; + + // Читаем внутренность section + int nSDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nSDepth)) { - // Стиль section-p - oFootnotes += L""; - oFootnotes += L""; - oFootnotes += L""; - readP(L"", oFootnotes); - oFootnotes += L""; - } - else if(sName == L"poem") - { - int nPDepth = m_oLightReader.GetDepth(); - while(m_oLightReader.ReadNextSiblingNode(nPDepth)) + std::wstring sName = m_oLightReader.GetName(); + if(sName == L"title") { - std::wstring sPName = m_oLightReader.GetName(); - // Читаем stanza (один или более) - if(sPName == L"stanza") + int nTDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nTDepth)) { - int nSDeath = m_oLightReader.GetDepth(); - while(m_oLightReader.ReadNextSiblingNode(nSDeath)) + if(m_oLightReader.GetName() == L"p") { - // Читаем v (один или более) - if(m_oLightReader.GetName() == L"v") - { - oFootnotes += L""; - oFootnotes += L""; - oFootnotes += L""; - readP(L"", oFootnotes); - oFootnotes += L""; - } + // Стиль section-p + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + readP(L"", oFootnotes); + oFootnotes += L""; } } - // Читаем text-author (любое) - else if(sPName == L"text-author") + } + else if(sName == L"p" || sName == L"subtitle") + { + // Стиль section-p + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + readP(L"", oFootnotes); + oFootnotes += L""; + } + else if(sName == L"poem") + { + int nPDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nPDepth)) { - oFootnotes += L""; - oFootnotes += L""; - oFootnotes += L""; - readP(L"", oFootnotes); - oFootnotes += L""; + std::wstring sPName = m_oLightReader.GetName(); + // Читаем stanza (один или более) + if(sPName == L"stanza") + { + int nSDeath = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nSDeath)) + { + // Читаем v (один или более) + if(m_oLightReader.GetName() == L"v") + { + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + readP(L"", oFootnotes); + oFootnotes += L""; + } + } + } + // Читаем text-author (любое) + else if(sPName == L"text-author") + { + oFootnotes += L""; + oFootnotes += L""; + oFootnotes += L""; + readP(L"", oFootnotes); + oFootnotes += L""; + } } } } + oFootnotes += L""; } - oFootnotes += L""; } } } + m_oLightReader.Clear(); } // Читает оглавление @@ -901,6 +919,8 @@ public: // Читаем p if(m_oLightReader.GetName() == L"p") readP(L"", oContents); + // Вставляем пробел между словами + oContents += L" "; } oContents += L""; } @@ -927,6 +947,7 @@ public: // Читаем title-info if(sName == L"title-info") getTitleInfo(m_oTitleInfo); + /* // Читаем src-title-info (ноль или один) else if(sName == L"src-title-info") { @@ -945,6 +966,7 @@ public: // Читаем custom-info (любое) else if(sName == L"custom-info") getCustomInfo(); + */ } } @@ -1080,8 +1102,29 @@ public: while(m_oLightReader.ReadNextSiblingNode(nDepth)) { std::wstring sName = m_oLightReader.GetName(); + // Читаем annotation (ноль или один) + if(sName == L"annotation") + readAnnotation(); + // Читаем coverpage (ноль или один) + else if(sName == L"coverpage") + { + // Читаем image (один или более) + int nCDepth = m_oLightReader.GetDepth(); + while(m_oLightReader.ReadNextSiblingNode(nCDepth)) + { + if(m_oLightReader.GetName() == L"image") + { + m_oBuilder += L""; + m_oBuilder += L""; + readImage(m_oBuilder); + m_oBuilder += L""; + } + } + // Разрыв страницы + m_oBuilder += L""; + } // Читаем genre (один или более) - if(sName == L"genre") + else if(sName == L"genre") oTitleInfo.m_arGenres.push_back(content()); // Читаем author (один или более) else if(sName == L"author") @@ -1089,9 +1132,6 @@ public: // Читаем book-title else if(sName == L"book-title") oTitleInfo.m_sBookTitle = content(); - // Читаем annotation (ноль или один) - else if(sName == L"annotation") - readAnnotation(); // Читаем keywords (ноль или один) else if(sName == L"keywords") { @@ -1115,24 +1155,6 @@ public: m_oLightReader.MoveToElement(); *oTitleInfo.m_pDate = make_pair(sDate, content()); } - // Читаем coverpage (ноль или один) - else if(sName == L"coverpage") - { - // Читаем image (один или более) - int nCDepth = m_oLightReader.GetDepth(); - while(m_oLightReader.ReadNextSiblingNode(nCDepth)) - { - if(m_oLightReader.GetName() == L"image") - { - m_oBuilder += L""; - m_oBuilder += L""; - readImage(m_oBuilder); - m_oBuilder += L""; - } - } - // Разрыв страницы - m_oBuilder += L""; - } // Читаем lang else if(sName == L"lang") oTitleInfo.m_sLang = content(); @@ -1211,15 +1233,21 @@ bool CFb2File::IsFb2File(const std::wstring& sFile) // Выставление рабочей папки void CFb2File::SetTmpDirectory(const std::wstring& sFolder) { - m_internal->m_sTmpFolder = CorrectPathW(sFolder); + m_internal->m_sTmpFolder = sFolder; + NSDirectory::DeleteDirectory(m_internal->m_sTmpFolder); + NSDirectory::CreateDirectory(m_internal->m_sTmpFolder); } // Проверяет, соответствует ли fb2 файл формату // sPath - путь к файлу fb2, sDirectory - директория, где формируется и создается docx -int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, bool bNeedDocx) +int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, CFb2Params* oParams) { + if(m_internal->m_sTmpFolder == L"") + SetTmpDirectory(sDirectory + L"/tmp"); + std::wstring sTmp = m_internal->m_sTmpFolder; + // Копирование шаблона - if(!ExtractTemplate(sDirectory)) + if(!ExtractTemplate(sTmp)) return FALSE; // Начало файла @@ -1243,16 +1271,26 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, oRels += L""; oRels += L""; - // Создаем содержание + // Читаем содержание + bool bNeedContents = false; + if(oParams) + bNeedContents = oParams->bNeedContents; NSStringUtils::CStringBuilder oContents; - if(!m_internal->readContents(sPath, oContents)) - return FALSE; + if(bNeedContents) + { + if(!m_internal->readContents(sPath, oContents)) + return FALSE; + } // Директория картинок - std::wstring sMediaDirectory = sDirectory + L"/word/media"; + std::wstring sMediaDirectory = sTmp + L"/word/media"; NSDirectory::CreateDirectory(sMediaDirectory); - // Пишем картинки - m_internal->getImage(sPath, sMediaDirectory, oRels); + // Читаем картинки + if(!m_internal->getImages(sPath, sMediaDirectory, oRels)) + return FALSE; + + // Читаем сноски + m_internal->readNotes(sPath, oFootnotes); // Открываем файл на чтение if(!m_internal->m_oLightReader.FromFile(sPath)) @@ -1271,7 +1309,8 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, { m_internal->readDescription(); // После description вставим оглавление - m_internal->m_oBuilder += oContents.GetData(); + if(bNeedContents) + m_internal->m_oBuilder += oContents.GetData(); } // Читаем body else if(sName == L"body") @@ -1285,16 +1324,15 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, } m_internal->m_oLightReader.MoveToElement(); if(bNotes) - m_internal->readNotes(oFootnotes); - else - m_internal->readBody(); + continue; + m_internal->readBody(); } } // Конец сносок oFootnotes += L""; // Пишем сноски в файл - std::wstring sFootnotesDirectory = sDirectory + L"/word"; + std::wstring sFootnotesDirectory = sTmp + L"/word"; NSFile::CFileBinary oFootnotesWriter; if (oFootnotesWriter.CreateFileW(sFootnotesDirectory + L"/footnotes.xml")) { @@ -1307,7 +1345,7 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, m_internal->m_oBuilder += L""; // Пишем документ в файл NSFile::CFileBinary oDocumentXmlWriter; - if (oDocumentXmlWriter.CreateFileW(sDirectory + L"/word/document.xml")) + if (oDocumentXmlWriter.CreateFileW(sTmp + L"/word/document.xml")) { oDocumentXmlWriter.WriteStringUTF8(m_internal->m_oBuilder.GetData()); oDocumentXmlWriter.CloseFile(); @@ -1316,7 +1354,7 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, // Конец рельсов oRels += L""; // Пишем рельсы в файл - std::wstring sRelsDirectory = sDirectory + L"/word/_rels"; + std::wstring sRelsDirectory = sTmp + L"/word/_rels"; NSFile::CFileBinary oRelsWriter; if (oRelsWriter.CreateFileW(sRelsDirectory + L"/document.xml.rels")) { @@ -1325,7 +1363,7 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, } // Директория app и core - std::wstring sDocPropsDirectory = sDirectory + L"/docProps"; + std::wstring sDocPropsDirectory = sTmp + L"/docProps"; NSDirectory::CreateDirectory(sDocPropsDirectory); // Создаем core.xml @@ -1381,13 +1419,20 @@ int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory, } // Архивим в docx + bool bNeedDocx = false; + if(oParams) + bNeedDocx = oParams->bNeedDocx; if(bNeedDocx) { COfficeUtils oZip; - HRESULT oRes = oZip.CompressFileOrDirectory(sDirectory, sDirectory + L"/res.docx"); + HRESULT oRes = oZip.CompressFileOrDirectory(sTmp, sDirectory + L"/" + NSFile::GetFileName(sPath) + L".docx"); if(oRes == S_FALSE) return FALSE; } - + else + { + if(!NSDirectory::CopyDirectory(sTmp, sDirectory)) + return FALSE; + } return TRUE; } diff --git a/Fb2File/Fb2File.h b/Fb2File/Fb2File.h index f43b42a358..9097ab91d9 100644 --- a/Fb2File/Fb2File.h +++ b/Fb2File/Fb2File.h @@ -10,6 +10,18 @@ #define FB2FILE_DECL_EXPORT Q_DECL_EXPORT #endif +struct CFb2Params +{ + bool bNeedDocx; + bool bNeedContents; + + CFb2Params() + { + bNeedDocx = false; + bNeedContents = false; + } +}; + class CFb2File_Private; class FB2FILE_DECL_EXPORT CFb2File { @@ -21,7 +33,7 @@ public: bool IsFb2File(const std::wstring& sFile); void SetTmpDirectory(const std::wstring& sFolder); - int Convert(const std::wstring& sPath, const std::wstring& sDirectory, bool bNeedDocx = false); + int Convert(const std::wstring& sPath, const std::wstring& sDirectory, CFb2Params* oParams = NULL); }; #endif // _FB2FILE_FB2FILE_H diff --git a/Fb2File/test/main.cpp b/Fb2File/test/main.cpp index 4976a95428..0034c40052 100644 --- a/Fb2File/test/main.cpp +++ b/Fb2File/test/main.cpp @@ -1,33 +1,99 @@ #include +#include #include "../Fb2File.h" #include "../../DesktopEditor/common/File.h" #include "../../DesktopEditor/common/Directory.h" +void getDirectories(std::wstring sDirectory, std::vector& arrDirectory) +{ + arrDirectory.push_back(sDirectory); + for(std::wstring sT : NSDirectory::GetDirectories(sDirectory)) + getDirectories(sT, arrDirectory); +} + int main() { - CFb2File oFile; - oFile.SetTmpDirectory(NSFile::GetProcessDirectory() + L"/tmp"); + setlocale(LC_ALL, "Russian"); - // файл, который открываем - std::wstring sFile = NSFile::GetProcessDirectory() + L"/../../../examples/1-posledneye-zhelaniye.fb2"; - - // директория, где будем создавать docx - std::wstring sOutputDirectory = NSFile::GetProcessDirectory() + L"/res"; - NSDirectory::DeleteDirectory(sOutputDirectory); - NSDirectory::CreateDirectory(sOutputDirectory); - - bool bCheck = oFile.IsFb2File(sFile); - if (!bCheck) + bool bBatchMode = true; + if(bBatchMode) { - std::cout << "This isn't a fb2 file" << std::endl; - return 1; - } + // Директория файлов + std::wstring sDirectory = L"C:/Users/Kulik/Downloads/fb2"; + // Вложенные директории + std::vector arrDirectory;// = NSDirectory::GetDirectories(sDirectory); + getDirectories(sDirectory, arrDirectory); - int nResConvert = oFile.Convert(sFile, sOutputDirectory, true); - if(nResConvert) - std::cout << "Success" << std::endl; + // Параметры конвертации + CFb2Params* oParams = new CFb2Params[1]; + oParams[0].bNeedDocx = true; + oParams[0].bNeedContents = true; + + for(std::wstring sD : arrDirectory) + { + std::vector arrFiles = NSDirectory::GetFiles(sD); + + // Директория, где будем создавать docx + size_t nPos = sD.find(L"/fb2"); + std::wstring sOutputDirectory = sD.insert(nPos + 4, L"-res"); + NSDirectory::DeleteDirectory(sOutputDirectory); + NSDirectory::CreateDirectory(sOutputDirectory); + + for(std::wstring sFile : arrFiles) + { + CFb2File oFile; + // Выставляем временную директорию + oFile.SetTmpDirectory(NSFile::GetProcessDirectory() + L"/tmp"); + std::wcout << NSFile::GetFileName(sFile) << std::endl; + if(!oFile.IsFb2File(sFile)) + { + std::cout << "This isn't a fb2 file" << std::endl; + continue; + } + int nResConvert = oFile.Convert(sFile, sOutputDirectory, oParams); + if(nResConvert) + std::cout << "Success" << std::endl; + else + std::cout << "Failure" << std::endl; + } + + + } + + delete[] oParams; + } else - std::cout << "Failure" << std::endl; + { + CFb2File oFile; + oFile.SetTmpDirectory(NSFile::GetProcessDirectory() + L"/tmp"); + + // Файл, который открываем + std::wstring sFile = NSFile::GetProcessDirectory() + L"/../../../examples/8-sezon-groz.fb2"; + + // Директория, где будем создавать docx + std::wstring sOutputDirectory = NSFile::GetProcessDirectory() + L"/res"; + NSDirectory::DeleteDirectory(sOutputDirectory); + NSDirectory::CreateDirectory(sOutputDirectory); + + bool bCheck = oFile.IsFb2File(sFile); + if (!bCheck) + { + std::cout << "This isn't a fb2 file" << std::endl; + return 1; + } + + CFb2Params* oParams = new CFb2Params[1]; + oParams[0].bNeedDocx = true; + oParams[0].bNeedContents = true; + + int nResConvert = oFile.Convert(sFile, sOutputDirectory, oParams); + if(nResConvert) + std::cout << "Success" << std::endl; + else + std::cout << "Failure" << std::endl; + + delete[] oParams; + } return 0; }