From 8b0ccd20fa203f48008528094ae2d8e66bdf03c8 Mon Sep 17 00:00:00 2001 From: Herwig Birke Date: Tue, 27 Mar 2018 15:01:39 +0200 Subject: [PATCH] . --- cdocumentreader.cpp | 1910 ++++++++++++++++++++++++++++++++++++ cdocumentreader.h | 207 ++++ cdocumentwriter.cpp | 620 ++++++++++++ cdocumentwriter.h | 75 ++ cmainwindow.cpp | 278 ++++++ cmainwindow.h | 27 + cmainwindow.ui | 88 ++ common.cpp | 1 + common.h | 11 + ctextdocument.cpp | 115 +++ ctextdocument.h | 37 + example.html | 79 ++ images/logo32.png | Bin 0 -> 1410 bytes images/mac/editcopy.png | Bin 0 -> 1468 bytes images/mac/editcut.png | Bin 0 -> 1512 bytes images/mac/editpaste.png | Bin 0 -> 1906 bytes images/mac/editredo.png | Bin 0 -> 1752 bytes images/mac/editundo.png | Bin 0 -> 1746 bytes images/mac/exportpdf.png | Bin 0 -> 1215 bytes images/mac/filenew.png | Bin 0 -> 1172 bytes images/mac/fileopen.png | Bin 0 -> 2168 bytes images/mac/fileprint.png | Bin 0 -> 2087 bytes images/mac/filesave.png | Bin 0 -> 1206 bytes images/mac/textbold.png | Bin 0 -> 1611 bytes images/mac/textcenter.png | Bin 0 -> 1404 bytes images/mac/textitalic.png | Bin 0 -> 1164 bytes images/mac/textjustify.png | Bin 0 -> 1257 bytes images/mac/textleft.png | Bin 0 -> 1235 bytes images/mac/textright.png | Bin 0 -> 1406 bytes images/mac/textunder.png | Bin 0 -> 1183 bytes images/mac/zoomin.png | Bin 0 -> 1696 bytes images/mac/zoomout.png | Bin 0 -> 1662 bytes images/win/editcopy.png | Bin 0 -> 1325 bytes images/win/editcut.png | Bin 0 -> 1896 bytes images/win/editpaste.png | Bin 0 -> 1482 bytes images/win/editredo.png | Bin 0 -> 1787 bytes images/win/editundo.png | Bin 0 -> 1768 bytes images/win/exportpdf.png | Bin 0 -> 1059 bytes images/win/filenew.png | Bin 0 -> 768 bytes images/win/fileopen.png | Bin 0 -> 1662 bytes images/win/fileprint.png | Bin 0 -> 1456 bytes images/win/filesave.png | Bin 0 -> 1205 bytes images/win/textbold.png | Bin 0 -> 1134 bytes images/win/textcenter.png | Bin 0 -> 627 bytes images/win/textitalic.png | Bin 0 -> 829 bytes images/win/textjustify.png | Bin 0 -> 695 bytes images/win/textleft.png | Bin 0 -> 673 bytes images/win/textright.png | Bin 0 -> 677 bytes images/win/textunder.png | Bin 0 -> 971 bytes images/win/zoomin.png | Bin 0 -> 1208 bytes images/win/zoomout.png | Bin 0 -> 1226 bytes main.cpp | 11 + qtStoryWriter.pro | 49 + qtstorywriter.qrc | 44 + 54 files changed, 3552 insertions(+) create mode 100644 cdocumentreader.cpp create mode 100644 cdocumentreader.h create mode 100644 cdocumentwriter.cpp create mode 100644 cdocumentwriter.h create mode 100644 cmainwindow.cpp create mode 100644 cmainwindow.h create mode 100644 cmainwindow.ui create mode 100644 common.cpp create mode 100644 common.h create mode 100644 ctextdocument.cpp create mode 100644 ctextdocument.h create mode 100644 example.html create mode 100644 images/logo32.png create mode 100644 images/mac/editcopy.png create mode 100644 images/mac/editcut.png create mode 100644 images/mac/editpaste.png create mode 100644 images/mac/editredo.png create mode 100644 images/mac/editundo.png create mode 100644 images/mac/exportpdf.png create mode 100644 images/mac/filenew.png create mode 100644 images/mac/fileopen.png create mode 100644 images/mac/fileprint.png create mode 100644 images/mac/filesave.png create mode 100644 images/mac/textbold.png create mode 100644 images/mac/textcenter.png create mode 100644 images/mac/textitalic.png create mode 100644 images/mac/textjustify.png create mode 100644 images/mac/textleft.png create mode 100644 images/mac/textright.png create mode 100644 images/mac/textunder.png create mode 100644 images/mac/zoomin.png create mode 100644 images/mac/zoomout.png create mode 100644 images/win/editcopy.png create mode 100644 images/win/editcut.png create mode 100644 images/win/editpaste.png create mode 100644 images/win/editredo.png create mode 100644 images/win/editundo.png create mode 100644 images/win/exportpdf.png create mode 100644 images/win/filenew.png create mode 100644 images/win/fileopen.png create mode 100644 images/win/fileprint.png create mode 100644 images/win/filesave.png create mode 100644 images/win/textbold.png create mode 100644 images/win/textcenter.png create mode 100644 images/win/textitalic.png create mode 100644 images/win/textjustify.png create mode 100644 images/win/textleft.png create mode 100644 images/win/textright.png create mode 100644 images/win/textunder.png create mode 100644 images/win/zoomin.png create mode 100644 images/win/zoomout.png create mode 100644 main.cpp create mode 100644 qtStoryWriter.pro create mode 100644 qtstorywriter.qrc diff --git a/cdocumentreader.cpp b/cdocumentreader.cpp new file mode 100644 index 0000000..3d1de6c --- /dev/null +++ b/cdocumentreader.cpp @@ -0,0 +1,1910 @@ +#include "cdocumentreader.h" +#include "ctextdocument.h" + +#include "common.h" + +#include +#include + +#include + +#include +#include + +cDocumentReader::cDocumentReader(const QString &szFileName) : + m_bFirstBlock(true), + m_szFileName(szFileName) +{ +} + +cDocumentReader::~cDocumentReader() +{ + close(); +} + +bool cDocumentReader::open() +{ + m_file.setFileName(m_szFileName); + + if(!m_file.open(QFile::ReadOnly | QFile::Text)) + return(false); + + return(true); +} + +bool cDocumentReader::close() +{ + if(m_file.isOpen()) + m_file.close();; + + return(true); +} + +cTextDocument* cDocumentReader::readDocument() +{ + if(!m_file.isOpen()) + return(0); + + cTextDocument* lpDocument; + QDomDocument doc; + QString errorStr; + int errorLine; + int errorColumn; + if(!doc.setContent(&m_file, false, &errorStr, &errorLine, &errorColumn)) + return(0); + + QDomElement root = doc.documentElement(); + if(root.tagName().compare("document", Qt::CaseInsensitive)) + return(0); + + lpDocument = new cTextDocument; + QDomNode child = root.firstChild(); + QVector allFormats; + + QTextCursor cursor(lpDocument); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("documentSettings", Qt::CaseInsensitive)) + parseSettings(child.toElement(), lpDocument); + else if(!child.toElement().tagName().compare("defaults", Qt::CaseInsensitive)) + parseDefaults(child.toElement(), lpDocument); + else if(!child.toElement().tagName().compare("allFormats", Qt::CaseInsensitive)) + allFormats = parseAllFormats(child.toElement()); + else if(!child.toElement().tagName().compare("textBlockFormats", Qt::CaseInsensitive)) + { + // SHOULD BE COVERED BY TEXTBLOCKS + } + else if(!child.toElement().tagName().compare("textBlocks", Qt::CaseInsensitive)) + { + QDomNode block = child.firstChild(); + + while(!block.isNull()) + { + if(!block.toElement().tagName().compare("textBlock", Qt::CaseInsensitive)) + parseTextBlock(block.toElement(), &cursor, allFormats); + else + myDebug << "readDocument: unknown element: " << child.toElement().tagName(); + + block = block.nextSibling(); + } + } + else + myDebug << "readDocument: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + m_file.close(); + + return(lpDocument); +} + +void cDocumentReader::parseSettings(const QDomElement &element, cTextDocument* lpDocument) +{ + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("documentMargin", Qt::CaseInsensitive)) + lpDocument->setDocumentMargin(node.toAttr().nodeValue().toDouble()); + else if(!node.toAttr().name().compare("indentWidth", Qt::CaseInsensitive)) + lpDocument->setIndentWidth(node.toAttr().nodeValue().toDouble()); + else if(!node.toAttr().name().compare("textWidth", Qt::CaseInsensitive)) + lpDocument->setTextWidth(node.toAttr().nodeValue().toDouble()); + else if(!node.toAttr().name().compare("useDesignMetrics", Qt::CaseInsensitive)) + lpDocument->setUseDesignMetrics(node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false); + else + myDebug << "parseSettings: unknown attribute: " << node.toAttr().name(); + } + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("metaInformation", Qt::CaseInsensitive)) + { + attributes = child.toElement().attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + if(!node.toAttr().name().compare("documentTitle", Qt::CaseInsensitive)) + lpDocument->setMetaInformation(QTextDocument::DocumentTitle, node.toAttr().nodeValue()); + else if(!node.toAttr().name().compare("documentUrl", Qt::CaseInsensitive)) + lpDocument->setMetaInformation(QTextDocument::DocumentUrl, node.toAttr().nodeValue()); + else + myDebug << "parseSettings: unknown attribute: " << node.toAttr().name(); + } + } + else if(!child.toElement().tagName().compare("baseUrl", Qt::CaseInsensitive)) + { + attributes = child.toElement().attributes(); + QString authority; + QString fragment; + QString host; + QString password; + QString path; + int port; + QString query; + QString scheme; + QString urlName; + QString userInfo; + QString userName; + + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + if(!node.toAttr().name().compare("authority", Qt::CaseInsensitive)) + authority = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("fragment", Qt::CaseInsensitive)) + fragment = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("host", Qt::CaseInsensitive)) + host = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("password", Qt::CaseInsensitive)) + password = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("path", Qt::CaseInsensitive)) + path = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("port", Qt::CaseInsensitive)) + port = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("query", Qt::CaseInsensitive)) + query = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("scheme", Qt::CaseInsensitive)) + scheme = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("url", Qt::CaseInsensitive)) + urlName = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("userInfo", Qt::CaseInsensitive)) + userInfo = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("userName", Qt::CaseInsensitive)) + userName =node.toAttr().nodeValue(); + else + myDebug << "parseSettings: unknown attribute: " << node.toAttr().name(); + } + + if(!urlName.isEmpty()) + { + QUrl url(urlName); + url.setAuthority(authority); + url.setFragment(fragment); + url.setHost(host); + url.setPassword(password); + url.setPath(path); + url.setPort(port); + url.setQuery(query); + url.setScheme(scheme); + url.setUserInfo(userInfo); + url.setUserName(userName); + + if(url.isValid()) + lpDocument->setBaseUrl(url); + } + } + else if(!child.toElement().tagName().compare("pageSize", Qt::CaseInsensitive)) + { + attributes = child.toElement().attributes(); + QSizeF size; + + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + if(!node.toAttr().name().compare("width", Qt::CaseInsensitive)) + size.setWidth(node.toAttr().nodeValue().toDouble()); + else if(!node.toAttr().name().compare("height", Qt::CaseInsensitive)) + size.setHeight(node.toAttr().nodeValue().toDouble()); + } + if(size.isValid()) + lpDocument->setPageSize(size); + } + else + myDebug << "parseSettings: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } +} + +void cDocumentReader::parseDefaults(const QDomElement &element, cTextDocument* lpDocument) +{ + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("defaultCursorMoveStyle", Qt::CaseInsensitive)) + lpDocument->setDefaultCursorMoveStyle((Qt::CursorMoveStyle)node.toAttr().nodeValue().toInt()); + else if(!node.toAttr().name().compare("defaultStyleSheet", Qt::CaseInsensitive)) + lpDocument->setDefaultStyleSheet(node.toAttr().nodeValue()); + else + myDebug << "parseDefaults: unknown attribute: " << node.toAttr().name(); + } + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("defaultFont", Qt::CaseInsensitive)) + lpDocument->setDefaultFont(parseFont(child.toElement())); + else if(!child.toElement().tagName().compare("defaultTextOption", Qt::CaseInsensitive)) + lpDocument->setDefaultTextOption(parseDefaultTextOption(child.toElement())); + else + myDebug << "parseDefaults: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } +} + +QFont cDocumentReader::parseFont(const QDomElement& element) +{ + QDomNamedNodeMap attributes = element.attributes(); + + bool bold; + QFont::Capitalization capitalization; + QString family; + bool fixedPitch; + QFont::HintingPreference hintingPreference; + bool italic; + bool kerning; + qreal letterSpacing; + QFont::SpacingType letterSpacingType; + int overline; + int pixelSize; + int pointSize; + qreal pointSizeF; + int stretch; + bool strikeOut; + QFont::Style style; + QFont::StyleHint styleHint; + QString styleName; + QFont::StyleStrategy styleStrategy; + bool underline; + int weight; + qreal wordSpacing; + + + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("bold", Qt::CaseInsensitive)) + bold = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("capitalization", Qt::CaseInsensitive)) + capitalization = (QFont::Capitalization)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("family", Qt::CaseInsensitive)) + family = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("fixedPitch", Qt::CaseInsensitive)) + fixedPitch = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("hintingPreference", Qt::CaseInsensitive)) + hintingPreference = (QFont::HintingPreference)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("italic", Qt::CaseInsensitive)) + italic = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("kerning", Qt::CaseInsensitive)) + kerning = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("letterSpacing", Qt::CaseInsensitive)) + letterSpacing = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("letterSpacingType", Qt::CaseInsensitive)) + letterSpacingType = (QFont::SpacingType)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("overline", Qt::CaseInsensitive)) + overline = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("pixelSize", Qt::CaseInsensitive)) + pixelSize = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("pointSize", Qt::CaseInsensitive)) + pointSize = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("pointSizeF", Qt::CaseInsensitive)) + pointSizeF = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("stretch", Qt::CaseInsensitive)) + stretch = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("strikeOut", Qt::CaseInsensitive)) + strikeOut = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("style", Qt::CaseInsensitive)) + style = (QFont::Style)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("styleHint", Qt::CaseInsensitive)) + styleHint = (QFont::StyleHint)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("styleName", Qt::CaseInsensitive)) + styleName = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("styleStrategy", Qt::CaseInsensitive)) + styleStrategy = (QFont::StyleStrategy)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("underline", Qt::CaseInsensitive)) + underline = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("weight", Qt::CaseInsensitive)) + weight = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("wordSpacing", Qt::CaseInsensitive)) + wordSpacing = node.toAttr().nodeValue().toDouble(); + else + myDebug << "parseFont: unknown attribute: " << node.toAttr().name(); + } + + QFont font(family); + font.setBold(bold); + font.setCapitalization(capitalization); + font.setFixedPitch(fixedPitch); + font.setHintingPreference(hintingPreference); + font.setItalic(italic); + font.setKerning(kerning); + font.setLetterSpacing(letterSpacingType, letterSpacing); + font.setOverline(overline); + if(pointSizeF > 0) + font.setPointSizeF(pointSizeF); + else if(pointSize > 0) + font.setPointSize(pointSize); + else if(pixelSize > 0) + font.setPixelSize(pixelSize); + font.setStretch(stretch); + font.setStretch(strikeOut); + font.setStyle(style); + font.setStyleHint(styleHint); + font.setStyleName(styleName); + font.setStyleStrategy(styleStrategy); + font.setUnderline(underline); + font.setWeight(weight); + font.setWordSpacing(wordSpacing); + + return(font); +} + +QTextOption cDocumentReader::parseDefaultTextOption(const QDomElement& element) +{ + QTextOption textOption; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("alignment", Qt::CaseInsensitive)) + textOption.setAlignment((Qt::AlignmentFlag)node.toAttr().nodeValue().toInt()); + else if(!node.toAttr().name().compare("flags", Qt::CaseInsensitive)) + textOption.setFlags((QTextOption::Flag)node.toAttr().nodeValue().toInt()); + else if(!node.toAttr().name().compare("tabStopDistance", Qt::CaseInsensitive)) + textOption.setTabStopDistance(node.toAttr().nodeValue().toDouble()); + else if(!node.toAttr().name().compare("textDirection", Qt::CaseInsensitive)) + textOption.setTextDirection((Qt::LayoutDirection)node.toAttr().nodeValue().toInt()); + else if(!node.toAttr().name().compare("useDesignMetrics", Qt::CaseInsensitive)) + textOption.setUseDesignMetrics(node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false); + else if(!node.toAttr().name().compare("wrapMode", Qt::CaseInsensitive)) + textOption.setWrapMode((QTextOption::WrapMode)node.toAttr().nodeValue().toInt()); + else + myDebug << "parseDefaultTextOption: unknown attribute: " << node.toAttr().name(); + } + + QList tabArray; + QList tabs; + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("tabArray", Qt::CaseInsensitive)) + { + QDomNode tab = child.toElement().firstChild(); + + while(!tab.isNull()) + { + if(!tab.toElement().tagName().compare("tab", Qt::CaseInsensitive)) + tabArray.append(tab.toElement().nodeValue().toDouble()); + + tab = tab.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("tabs", Qt::CaseInsensitive)) + tabs = parseTabPositions(child.toElement()); + else + myDebug << "parseDefaultTextOption: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + if(!tabArray.isEmpty()) + textOption.setTabArray(tabArray); + if(!tabs.isEmpty()) + textOption.setTabs(tabs); + + return(textOption); +} + +QList cDocumentReader::parseTabPositions(const QDomElement& element) +{ + QList tabs; + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("tabPosition", Qt::CaseInsensitive)) + { + QTextOption::Tab tab; + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("delimiter", Qt::CaseInsensitive)) + tab.delimiter = node.toAttr().nodeValue().at(0); + else if(!node.toAttr().name().compare("position", Qt::CaseInsensitive)) + tab.position = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + tab.type = (QTextOption::TabType)node.toAttr().nodeValue().toInt(); + } + tabs.append(tab); + } + else + myDebug << "parseTabPositions: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + return(tabs); +} + +QVector cDocumentReader::parseAllFormats(const QDomElement& element) +{ + QVector allFormats; + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("format", Qt::CaseInsensitive)) + { + cTextFormat format = parseFormat(child.toElement()); + if(format.isValid()) + allFormats.append(format); + } + else + myDebug << "parseAllFormats: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + return(allFormats); +} + +cTextFormat cDocumentReader::parseFormat(const QDomElement& element) +{ + QString typeText; + Qt::LayoutDirection layoutDirection; + //UNUSED + int id; + int type; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + //else + // myDebug << "parseFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + + cTextFormat format(typeText); + + if(!typeText.compare("tableCellFormat", Qt::CaseInsensitive)) + format.tableCellFormat = parseTextTableCellFormat(element); + else if(!typeText.compare("tableFormat", Qt::CaseInsensitive)) + format.tableFormat = parseTextTableFormat(element); + else if(!typeText.compare("imageFormat", Qt::CaseInsensitive)) + format.imageFormat = parseTextImageFormat(element); + else if(!typeText.compare("frameFormat", Qt::CaseInsensitive)) + format.frameFormat = parseTextFrameFormat(element); + else if(!typeText.compare("listFormat", Qt::CaseInsensitive)) + format.listFormat = parseTextListFormat(element); + else if(!typeText.compare("blockFormat", Qt::CaseInsensitive)) + format.blockFormat = parseTextBlockFormat(element); + else if(!typeText.compare("charFormat", Qt::CaseInsensitive)) + format.charFormat = parseTextCharFormat(element); + format.setLayoutDirection(layoutDirection); + + return(format); +} + +QPen cDocumentReader::parsePen(const QDomElement& element) +{ + QDomNamedNodeMap attributes = element.attributes(); + Qt::PenCapStyle capStyle; + qreal dashOffset; + bool isCosmetic; + Qt::PenJoinStyle joinStyle; + qreal miterLimit; + Qt::PenStyle style; + int width; + qreal widthF; + QBrush brush; + QColor color; + QVector dashPattern; + + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("capStyle", Qt::CaseInsensitive)) + capStyle = (Qt::PenCapStyle)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("dashOffset", Qt::CaseInsensitive)) + dashOffset = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("isCosmetic", Qt::CaseInsensitive)) + isCosmetic = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("joinStyle", Qt::CaseInsensitive)) + joinStyle = (Qt::PenJoinStyle)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("miterLimit", Qt::CaseInsensitive)) + miterLimit = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("style", Qt::CaseInsensitive)) + style = (Qt::PenStyle)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("width", Qt::CaseInsensitive)) + width = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("widthF", Qt::CaseInsensitive)) + widthF = node.toAttr().nodeValue().toDouble(); + else + myDebug << "parsePen: unknown attribute: " << node.toAttr().name(); + } + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("brush", Qt::CaseInsensitive)) + brush = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("color", Qt::CaseInsensitive)) + color = parseColor(child.toElement()); + else if(!child.toElement().tagName().compare("dashPattern", Qt::CaseInsensitive)) + { + QDomNode pattern = child.toElement().firstChild(); + + while(!pattern.isNull()) + { + if(!pattern.toElement().tagName().compare("pattern", Qt::CaseInsensitive)) + dashPattern.append(pattern.toElement().nodeValue().toDouble()); + else + qDebug() << " parsePen: unknown element: " << pattern.toElement().tagName(); + + pattern = pattern.nextSibling(); + } + } + else + myDebug << " parsePen: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QPen pen(color); + + pen.setBrush(brush); + if(widthF > 0) + pen.setWidthF(widthF); + else + pen.setWidth(width); + pen.setCapStyle(capStyle); + pen.setDashOffset(dashOffset); + pen.setCosmetic(isCosmetic); + pen.setJoinStyle(joinStyle); + pen.setMiterLimit(miterLimit); + pen.setStyle(style); + if(dashPattern.count()) + pen.setDashPattern(dashPattern); + + return(pen); +} + +QBrush cDocumentReader::parseBrush(const QDomElement& element) +{ + QDomNamedNodeMap attributes = element.attributes(); + Qt::BrushStyle style; + + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("style", Qt::CaseInsensitive)) + style = (Qt::BrushStyle)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseBrush: unknown attribute: " << node.toAttr().name(); + } + + QDomNode child = element.firstChild(); + QColor color; + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("color", Qt::CaseInsensitive)) + color = parseColor(child.toElement()); + else + myDebug << " parseBrush: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + return(QBrush(color, style)); +} + +QColor cDocumentReader::parseColor(const QDomElement& element) +{ + QDomNamedNodeMap attributes = element.attributes(); + int alpha; + int r; + int g; + int b; + + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("alpha", Qt::CaseInsensitive)) + alpha = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("r", Qt::CaseInsensitive)) + r = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("g", Qt::CaseInsensitive)) + g = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("b", Qt::CaseInsensitive)) + b = node.toAttr().nodeValue().toInt(); + else + myDebug << " parseColor: unknown attribute: " << node.toAttr().name(); + } + + return(QColor(r, g, b, alpha)); +} + +QTextTableCellFormat cDocumentReader::parseTextTableCellFormat(const QDomElement& element) +{ + int leftPadding; + int topPadding; + int rightPadding; + int bottomPadding; + Qt::LayoutDirection layoutDirection; + + QString anchorHref; + bool isAnchor; + QString toolTip; + QTextImageFormat::VerticalAlignment verticalAlignment; + + QBrush background; + QBrush foreground; + QPen textOutline; + QStringList anchorNames; + QMap properties; + QFont font; + QColor underlineColor; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("anchorHref", Qt::CaseInsensitive)) + anchorHref = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("isAnchor", Qt::CaseInsensitive)) + isAnchor = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("toolTip", Qt::CaseInsensitive)) + toolTip = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("verticalAlignment", Qt::CaseInsensitive)) + verticalAlignment = (QTextImageFormat::VerticalAlignment)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("leftPadding", Qt::CaseInsensitive)) + leftPadding = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("topPadding", Qt::CaseInsensitive)) + topPadding = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("rightPadding", Qt::CaseInsensitive)) + rightPadding = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("bottomPadding", Qt::CaseInsensitive)) + bottomPadding = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextTableCellFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("textOutline", Qt::CaseInsensitive)) + textOutline = parsePen(child.toElement()); + else if(!child.toElement().tagName().compare("anchorNames", Qt::CaseInsensitive)) + { + + QDomNode anchors = child.toElement().firstChild(); + + while(!anchors.isNull()) + { + if(!child.toElement().tagName().compare("anchor", Qt::CaseInsensitive)) + anchorNames.append(child.toElement().nodeValue()); + + anchors = anchors.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("font", Qt::CaseInsensitive)) + font = parseFont(child.toElement()); + else if(!child.toElement().tagName().compare("underlineColor", Qt::CaseInsensitive)) + underlineColor = parseColor(child.toElement()); + else + myDebug << " parseTextTableCellFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextTableCellFormat format; + + format.setAnchorHref(anchorHref); + format.setAnchor(isAnchor); + format.setToolTip(toolTip); + format.setVerticalAlignment(verticalAlignment); + format.setLeftPadding(leftPadding); + format.setTopPadding(topPadding); + format.setRightPadding(rightPadding); + format.setBottomPadding(bottomPadding); + format.setLayoutDirection(layoutDirection); + format.setBackground(background); + format.setForeground(foreground); + format.setTextOutline(textOutline); + format.setAnchorNames(anchorNames); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + format.setFont(font); + format.setUnderlineColor(underlineColor); + + return(format); +} + +QTextTableFormat cDocumentReader::parseTextTableFormat(const QDomElement& element) +{ + Qt::AlignmentFlag alignment; + int cellPadding; + int cellSpacing; + int columns; + int headerRowCount; + qreal border; + QTextTableFormat::BorderStyle borderStyle; + qreal margin; + qreal leftMargin; + qreal topMargin; + qreal rightMargin; + qreal bottomMargin; + qreal width; + qreal height; + qreal padding; + QTextTableFormat::PageBreakFlags pageBreakPolicy; + QTextTableFormat::Position position; + Qt::LayoutDirection layoutDirection; + QVector columnWidthContraints; + QBrush borderBrush; + QBrush background; + QBrush foreground; + QMap properties; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("alignment", Qt::CaseInsensitive)) + alignment = (Qt::AlignmentFlag)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("cellPadding", Qt::CaseInsensitive)) + cellPadding = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("cellSpacing", Qt::CaseInsensitive)) + cellSpacing = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("columns", Qt::CaseInsensitive)) + columns = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("headerRowCount", Qt::CaseInsensitive)) + headerRowCount = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("border", Qt::CaseInsensitive)) + border = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("borderStyle", Qt::CaseInsensitive)) + borderStyle = (QTextTableFormat::BorderStyle)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("margin", Qt::CaseInsensitive)) + margin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("leftMargin", Qt::CaseInsensitive)) + leftMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("topMargin", Qt::CaseInsensitive)) + topMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("rightMargin", Qt::CaseInsensitive)) + rightMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("bottomMargin", Qt::CaseInsensitive)) + bottomMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("width", Qt::CaseInsensitive)) + width = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("height", Qt::CaseInsensitive)) + height = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("padding", Qt::CaseInsensitive)) + padding = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("pageBreakPolicy", Qt::CaseInsensitive)) + pageBreakPolicy = (QTextTableFormat::PageBreakFlags)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("position", Qt::CaseInsensitive)) + position = (QTextTableFormat::Position)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextTableFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("columnWidthConstraints", Qt::CaseInsensitive)) + { + QDomNode constraints = child.toElement().firstChild(); + while(!constraints.isNull()) + { + if(!constraints.toElement().tagName().compare("columnWidthConstraint", Qt::CaseInsensitive)) + { + qreal rawValue; + QTextLength::Type type; + QDomNamedNodeMap constraint = constraints.attributes(); + + for(int x = 0;x < constraint.count();x++) + { + QDomNode node = constraint.item(x); + + if(!node.toAttr().name().compare("rawValue", Qt::CaseInsensitive)) + rawValue = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = (QTextLength::Type)node.toAttr().nodeValue().toInt(); + } + + columnWidthContraints.append(QTextLength(type, rawValue)); + } + else + myDebug << " parseTextTableFormat: unknown element: " << child.toElement().tagName(); + + constraints = constraints.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("borderBrush", Qt::CaseInsensitive)) + borderBrush = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else + myDebug << " parseTextTableFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextTableFormat format; + + format.setAlignment(alignment); + format.setCellPadding(cellPadding); + format.setCellSpacing(cellSpacing); + format.setColumns(columns); + format.setHeaderRowCount(headerRowCount); + format.setBorder(border); + format.setBorderStyle(borderStyle); + format.setMargin(margin); + format.setLeftMargin(leftMargin); + format.setTopMargin(topMargin); + format.setRightMargin(rightMargin); + format.setBottomMargin(bottomMargin); + format.setWidth(width); + format.setHeight(height); + format.setPadding(padding); + format.setPageBreakPolicy(pageBreakPolicy); + format.setPosition(position); + format.setLayoutDirection(layoutDirection); + format.setColumnWidthConstraints(columnWidthContraints); + format.setBorderBrush(borderBrush); + format.setBackground(background); + format.setForeground(foreground); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + return(format); +} + +QTextImageFormat cDocumentReader::parseTextImageFormat(const QDomElement& element) +{ + QString name; + qreal height; + qreal width; + QString anchorHref; + bool isAnchor; + QString toolTip; + QTextImageFormat::VerticalAlignment verticalAlignment; + QBrush background; + QBrush foreground; + QPen textOutline; + QStringList anchorNames; + QMap properties; + QFont font; + QColor underlineColor; + Qt::LayoutDirection layoutDirection; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("anchorHref", Qt::CaseInsensitive)) + anchorHref = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("height", Qt::CaseInsensitive)) + height = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("width", Qt::CaseInsensitive)) + width = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("name", Qt::CaseInsensitive)) + name = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("isAnchor", Qt::CaseInsensitive)) + isAnchor = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("toolTip", Qt::CaseInsensitive)) + toolTip = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("verticalAlignment", Qt::CaseInsensitive)) + verticalAlignment = (QTextImageFormat::VerticalAlignment)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextImageFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("textOutline", Qt::CaseInsensitive)) + textOutline = parsePen(child.toElement()); + else if(!child.toElement().tagName().compare("anchorNames", Qt::CaseInsensitive)) + { + + QDomNode anchors = child.toElement().firstChild(); + + while(!anchors.isNull()) + { + if(!child.toElement().tagName().compare("anchor", Qt::CaseInsensitive)) + anchorNames.append(child.toElement().nodeValue()); + + anchors = anchors.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("font", Qt::CaseInsensitive)) + font = parseFont(child.toElement()); + else if(!child.toElement().tagName().compare("underlineColor", Qt::CaseInsensitive)) + underlineColor = parseColor(child.toElement()); + else + myDebug << " parseTextTableCellFormat: unknown element: " << child.toElement().tagName(); + child = child.nextSibling(); + } + + QTextImageFormat format; + + format.setName(name); + format.setHeight(height); + format.setWidth(width); + format.setAnchorHref(anchorHref); + format.setFont(font); + format.setAnchor(isAnchor); + format.setToolTip(toolTip); + format.setVerticalAlignment(verticalAlignment); + format.setBackground(background); + format.setForeground(foreground); + format.setTextOutline(textOutline); + format.setAnchorNames(anchorNames); + format.setLayoutDirection(layoutDirection); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + format.setUnderlineColor(underlineColor); + + return(format); +} + +QTextFrameFormat cDocumentReader::parseTextFrameFormat(const QDomElement& element) +{ + qreal border; + QTextTableFormat::BorderStyle borderStyle; + qreal margin; + qreal leftMargin; + qreal topMargin; + qreal rightMargin; + qreal bottomMargin; + qreal width; + qreal height; + qreal padding; + QTextTableFormat::PageBreakFlags pageBreakPolicy; + QTextTableFormat::Position position; + QBrush background; + QBrush foreground; + QBrush borderBrush; + QMap properties; + Qt::LayoutDirection layoutDirection; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("border", Qt::CaseInsensitive)) + border = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("borderStyle", Qt::CaseInsensitive)) + borderStyle = (QTextTableFormat::BorderStyle)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("margin", Qt::CaseInsensitive)) + margin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("leftMargin", Qt::CaseInsensitive)) + leftMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("topMargin", Qt::CaseInsensitive)) + topMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("rightMargin", Qt::CaseInsensitive)) + rightMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("bottomMargin", Qt::CaseInsensitive)) + bottomMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("width", Qt::CaseInsensitive)) + width = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("height", Qt::CaseInsensitive)) + height = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("padding", Qt::CaseInsensitive)) + padding = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("pageBreakPolicy", Qt::CaseInsensitive)) + pageBreakPolicy = (QTextTableFormat::PageBreakFlags)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("position", Qt::CaseInsensitive)) + position = (QTextTableFormat::Position)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextTableFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("borderBrush", Qt::CaseInsensitive)) + borderBrush = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else + myDebug << " parseTextFrameFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextFrameFormat format; + + format.setBorder(border); + format.setBorderStyle(borderStyle); + format.setMargin(margin); + format.setLeftMargin(leftMargin); + format.setTopMargin(topMargin); + format.setRightMargin(rightMargin); + format.setBottomMargin(bottomMargin); + format.setWidth(width); + format.setHeight(height); + format.setPadding(padding); + format.setPageBreakPolicy(pageBreakPolicy); + format.setPosition(position); + format.setLayoutDirection(layoutDirection); + format.setBackground(background); + format.setForeground(foreground); + format.setBorderBrush(borderBrush); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + return(format); +} + +QTextListFormat cDocumentReader::parseTextListFormat(const QDomElement& element) +{ + int indent; + QString numberPrefix; + QString numberSuffix; + QTextListFormat::Style style; + Qt::LayoutDirection layoutDirection; + QBrush background; + QBrush foreground; + QMap properties; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("indent", Qt::CaseInsensitive)) + indent = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("numberPrefix", Qt::CaseInsensitive)) + numberPrefix = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("numberSuffix", Qt::CaseInsensitive)) + numberSuffix = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("style", Qt::CaseInsensitive)) + style = (QTextListFormat::Style)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextListFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else + myDebug << " parseTextListFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextListFormat format; + + format.setIndent(indent); + format.setNumberPrefix(numberPrefix); + format.setNumberSuffix(numberSuffix); + format.setStyle(style); + format.setLayoutDirection(layoutDirection); + format.setBackground(background); + format.setForeground(foreground); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + return(format); +} + +QTextBlockFormat cDocumentReader::parseTextBlockFormat(const QDomElement& element) +{ + Qt::AlignmentFlag alignment; + qreal leftMargin; + qreal topMargin; + qreal rightMargin; + qreal bottomMargin; + int indent; + int lineHeight; + int lineHeightType; + bool nonBreakableLines; + QTextTableFormat::PageBreakFlags pageBreakPolicy; + int textIndent; + Qt::LayoutDirection layoutDirection; + QList tabs; + QBrush background; + QBrush foreground; + QMap properties; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("alignment", Qt::CaseInsensitive)) + alignment = (Qt::AlignmentFlag)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("leftMargin", Qt::CaseInsensitive)) + leftMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("topMargin", Qt::CaseInsensitive)) + topMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("rightMargin", Qt::CaseInsensitive)) + rightMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("bottomMargin", Qt::CaseInsensitive)) + bottomMargin = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("indent", Qt::CaseInsensitive)) + indent = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("lineHeight", Qt::CaseInsensitive)) + lineHeight = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("lineHeightType", Qt::CaseInsensitive)) + lineHeightType = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("nonBreakableLines", Qt::CaseInsensitive)) + nonBreakableLines = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("pageBreakPolicy", Qt::CaseInsensitive)) + pageBreakPolicy = (QTextTableFormat::PageBreakFlags)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("textIndent", Qt::CaseInsensitive)) + textIndent = node.toAttr().nodeValue().toDouble(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextBlockFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("tabPositions", Qt::CaseInsensitive)) + tabs = parseTabPositions(child.toElement()); + else + myDebug << " parseTextBlockFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextBlockFormat format; + + format.setAlignment(alignment); + format.setLeftMargin(leftMargin); + format.setTopMargin(topMargin); + format.setRightMargin(rightMargin); + format.setBottomMargin(bottomMargin); + format.setIndent(indent); + format.setLineHeight(lineHeight, lineHeightType); + format.setNonBreakableLines(nonBreakableLines); + format.setPageBreakPolicy(pageBreakPolicy); + format.setTextIndent(textIndent); + format.setTabPositions(tabs); + format.setLayoutDirection(layoutDirection); + + background.setColor(QColor((int)(255*0.827451), (int)(255*0.827451), (int)(255*0.827451), (int)(255*1))); + format.setBackground(background); + format.setForeground(foreground); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + return(format); +} + +QTextCharFormat cDocumentReader::parseTextCharFormat(const QDomElement& element) +{ + QString anchorHref; + bool isAnchor; + QString toolTip; + QTextImageFormat::VerticalAlignment verticalAlignment; + QPen textOutline; + QStringList anchorNames; + QFont font; + QColor underlineColor; + QBrush background; + QBrush foreground; + QMap properties; + Qt::LayoutDirection layoutDirection; + + //UNUSED + int id; + int type; + QString typeText; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("id", Qt::CaseInsensitive)) + id = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + type = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("typeText", Qt::CaseInsensitive)) + typeText = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("anchorHref", Qt::CaseInsensitive)) + anchorHref = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("type", Qt::CaseInsensitive)) + anchorHref = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("isAnchor", Qt::CaseInsensitive)) + isAnchor = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("toolTip", Qt::CaseInsensitive)) + toolTip = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("verticalAlignment", Qt::CaseInsensitive)) + verticalAlignment = (QTextImageFormat::VerticalAlignment)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextCharFormat: unknown attribute: " << node.toAttr().name(); + } + + //UNUSED + id = id; + type = type; + typeText = typeText; + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("textOutline", Qt::CaseInsensitive)) + textOutline = parsePen(child.toElement()); + else if(!child.toElement().tagName().compare("anchorNames", Qt::CaseInsensitive)) + { + + QDomNode anchors = child.toElement().firstChild(); + + while(!anchors.isNull()) + { + if(!child.toElement().tagName().compare("anchor", Qt::CaseInsensitive)) + anchorNames.append(child.toElement().nodeValue()); + + anchors = anchors.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("font", Qt::CaseInsensitive)) + font = parseFont(child.toElement()); + else if(!child.toElement().tagName().compare("underlineColor", Qt::CaseInsensitive)) + underlineColor = parseColor(child.toElement()); + else + myDebug << " parseTextCharFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextCharFormat format; + + format.setAnchorHref(anchorHref); + format.setFont(font); + format.setAnchor(isAnchor); + format.setToolTip(toolTip); + format.setVerticalAlignment(verticalAlignment); + format.setBackground(background); + format.setForeground(foreground); + format.setTextOutline(textOutline); + format.setAnchorNames(anchorNames); + format.setLayoutDirection(layoutDirection); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + format.setUnderlineColor(underlineColor); + + return(format); +} + +void cDocumentReader::parseTextBlock(const QDomElement& element, QTextCursor* lpCursor, const QVector &allFormats) +{ + int blockFormatIndex; + int charFormatIndex; + int listFormatIndex; + int tableFormatIndex; + QVector textFormats; + QString text; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("blockFormatIndex", Qt::CaseInsensitive)) + blockFormatIndex = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("charFormatIndex", Qt::CaseInsensitive)) + charFormatIndex = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("listFormatIndex", Qt::CaseInsensitive)) + listFormatIndex = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("tableFormatIndex", Qt::CaseInsensitive)) + tableFormatIndex = node.toAttr().nodeValue().toInt(); + else + myDebug << " parseTextBlock: unknown attribute: " << node.toAttr().name(); + } + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("textFormats", Qt::CaseInsensitive)) + textFormats = parseTextFormats(child.toElement()); + else if(!child.toElement().tagName().compare("text", Qt::CaseInsensitive)) + text = child.toElement().text(); + else + myDebug << " parseTextBlock: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + int indent; + + if(m_bFirstBlock) + m_bFirstBlock = false; + else + { + if(listFormatIndex != -1) + { + indent = allFormats[listFormatIndex].listFormat.indent(); + + if(!m_textLists.value(indent)) + { + m_textLists.insert(allFormats[listFormatIndex].listFormat.indent(), lpCursor->insertList(allFormats[listFormatIndex].listFormat)); + lpCursor->setBlockFormat(allFormats[blockFormatIndex].blockFormat); + lpCursor->setCharFormat(allFormats[charFormatIndex].charFormat); + lpCursor->setBlockCharFormat(allFormats[charFormatIndex].charFormat); + } + else + { + lpCursor->insertBlock(); + lpCursor->setBlockFormat(allFormats[blockFormatIndex].blockFormat); + lpCursor->setCharFormat(allFormats[charFormatIndex].charFormat); + lpCursor->setBlockCharFormat(allFormats[charFormatIndex].charFormat); + } + + QTextBlock block = lpCursor->block(); + QTextList* list = m_textLists.value(indent); + list->add(block); + } +// else if(tableFormatIndex != -1) +// lpCursor->insertTable(allFormats[tableFormatIndex].tableFormat); + else + { + m_textLists.clear(); + lpCursor->insertBlock(); + lpCursor->setBlockFormat(allFormats[blockFormatIndex].blockFormat); + lpCursor->setCharFormat(allFormats[charFormatIndex].charFormat); + lpCursor->setBlockCharFormat(allFormats[charFormatIndex].charFormat); + } + } + + for(int x = 0;x < textFormats.count();x++) + { + QTextLayout::FormatRange textFormat = textFormats[x]; + int start = textFormat.start; + int length = textFormat.length; + QTextCharFormat format = textFormat.format; + QString textPart = text.mid(start, length); + lpCursor->insertText(textPart, format); + } +} + +QVector cDocumentReader::parseTextFormats(const QDomElement& element) +{ + QDomNode child = element.firstChild(); + QVector formats; + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("range", Qt::CaseInsensitive)) + { + QTextLayout::FormatRange range = parseRange(child.toElement()); + formats.append(range); + } + else + myDebug << " parseTextFormats: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + return(formats); +} + +QTextLayout::FormatRange cDocumentReader::parseRange(const QDomElement& element) +{ + int start; + int length; + QString anchorHref; + bool isAnchor; + QString toolTip; + QTextImageFormat::VerticalAlignment verticalAlignment; + Qt::LayoutDirection layoutDirection; + + QBrush background; + QBrush foreground; + QPen textOutline; + QStringList anchorNames; + QMap properties; + QFont font; + QColor underlineColor; + + QDomNamedNodeMap attributes = element.attributes(); + for(int x = 0;x < attributes.count();x++) + { + QDomNode node = attributes.item(x); + + if(!node.toAttr().name().compare("start", Qt::CaseInsensitive)) + start = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("length", Qt::CaseInsensitive)) + length = node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("anchorHref", Qt::CaseInsensitive)) + anchorHref = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("isAnchor", Qt::CaseInsensitive)) + isAnchor = node.toAttr().nodeValue().compare("true", Qt::CaseInsensitive) == 0 ? true : false; + else if(!node.toAttr().name().compare("toolTip", Qt::CaseInsensitive)) + toolTip = node.toAttr().nodeValue(); + else if(!node.toAttr().name().compare("verticalAlignment", Qt::CaseInsensitive)) + verticalAlignment = (QTextImageFormat::VerticalAlignment)node.toAttr().nodeValue().toInt(); + else if(!node.toAttr().name().compare("layoutDirection", Qt::CaseInsensitive)) + layoutDirection = (Qt::LayoutDirection)node.toAttr().nodeValue().toInt(); + else + myDebug << " parseRange: unknown attribute: " << node.toAttr().name(); + } + + QDomNode child = element.firstChild(); + + while(!child.isNull()) + { + if(!child.toElement().tagName().compare("background", Qt::CaseInsensitive)) + background = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("foreground", Qt::CaseInsensitive)) + foreground = parseBrush(child.toElement()); + else if(!child.toElement().tagName().compare("properties", Qt::CaseInsensitive)) + { + int key; + QVariant::Type type; + QString value; + + QDomNode property = child.toElement().firstChild(); + + while(!property.isNull()) + { + if(!property.toElement().tagName().compare("key", Qt::CaseInsensitive)) + key = property.toElement().toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("type", Qt::CaseInsensitive)) + type = (QVariant::Type)property.toElement().nodeValue().toInt(); + else if(!property.toElement().tagName().compare("value", Qt::CaseInsensitive)) + value = property.toElement().nodeValue(); + + QVariant propertyValue(value); + propertyValue.convert(type); + properties.insert(key, propertyValue); + + property = property.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("textOutline", Qt::CaseInsensitive)) + textOutline = parsePen(child.toElement()); + else if(!child.toElement().tagName().compare("anchorNames", Qt::CaseInsensitive)) + { + + QDomNode anchors = child.toElement().firstChild(); + + while(!anchors.isNull()) + { + if(!child.toElement().tagName().compare("anchor", Qt::CaseInsensitive)) + anchorNames.append(child.toElement().nodeValue()); + + anchors = anchors.nextSibling(); + } + } + else if(!child.toElement().tagName().compare("font", Qt::CaseInsensitive)) + font = parseFont(child.toElement()); + else if(!child.toElement().tagName().compare("underlineColor", Qt::CaseInsensitive)) + underlineColor = parseColor(child.toElement()); + else + myDebug << " parseTextCharFormat: unknown element: " << child.toElement().tagName(); + + child = child.nextSibling(); + } + + QTextCharFormat format; + + format.setAnchorHref(anchorHref); + format.setFont(font); + format.setAnchor(isAnchor); + format.setToolTip(toolTip); + format.setVerticalAlignment(verticalAlignment); + format.setBackground(background); + format.setForeground(foreground); + format.setTextOutline(textOutline); + format.setAnchorNames(anchorNames); + format.setLayoutDirection(layoutDirection); + + QMapIterator property(properties); + while(property.hasNext()) + { + property.next(); + format.setProperty(property.key(), property.value()); + } + + format.setUnderlineColor(underlineColor); + + QTextLayout::FormatRange range; + + range.start = start; + range.length = length; + range.format = format; + + return(range); +} diff --git a/cdocumentreader.h b/cdocumentreader.h new file mode 100644 index 0000000..9391c32 --- /dev/null +++ b/cdocumentreader.h @@ -0,0 +1,207 @@ +#ifndef CDOCUMENTREADER_H +#define CDOCUMENTREADER_H + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class cTextDocument; + +class cTextFormat +{ +public: + enum TextFormatType + { + TextFormatTypeUnknown = 0, + TextFormatTypeTableCell = 1, + TextFormatTypeTable = 2, + TextFormatTypeImage = 3, + TextFormatTypeFrame = 4, + TextFormatTypeList = 5, + TextFormatTypeBlock = 6, + TextFormatTypeChar = 7, + }; + + cTextFormat(TextFormatType type = TextFormatTypeUnknown) : m_type(type) {} + cTextFormat(const QString& szType) : m_type(TextFormatTypeUnknown) + { + if(szType.compare("tableCellFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeTableCell; + else if(szType.compare("tableFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeTable; + else if(szType.compare("imageFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeImage; + else if(szType.compare("frameFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeFrame; + else if(szType.compare("listFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeList; + else if(szType.compare("blockFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeBlock; + else if(szType.compare("charFormat", Qt::CaseInsensitive)) + m_type = TextFormatTypeChar; + } + + void setTableCellFormat(const QTextTableCellFormat& format) + { + tableCellFormat = format; + m_type = TextFormatTypeTableCell; + } + void setTableFormat(const QTextTableFormat& format) + { + tableFormat = format; + m_type = TextFormatTypeTable; + } + void setImageFormat(const QTextImageFormat& format) + { + imageFormat = format; + m_type = TextFormatTypeImage; + } + void setFrameFormat(const QTextFrameFormat& format) + { + frameFormat = format; + m_type = TextFormatTypeFrame; + } + void setListFormat(const QTextListFormat& format) + { + listFormat = format; + m_type = TextFormatTypeList; + } + void setBlockFormat(const QTextBlockFormat& format) + { + blockFormat = format; + m_type = TextFormatTypeBlock; + } + void setCharFormat(const QTextCharFormat& format) + { + charFormat = format; + m_type = TextFormatTypeChar; + } + + bool isValid() + { + switch(m_type) + { + case TextFormatTypeTableCell: + return(tableCellFormat.isValid()); + case TextFormatTypeTable: + return(tableFormat.isValid()); + case TextFormatTypeImage: + return(imageFormat.isValid()); + case TextFormatTypeFrame: + return(frameFormat.isValid()); + case TextFormatTypeList: + return(listFormat.isValid()); + case TextFormatTypeBlock: + return(blockFormat.isValid()); + case TextFormatTypeChar: + return(charFormat.isValid()); + case TextFormatTypeUnknown: + return(false); + } + return(false); + } + + void setLayoutDirection(Qt::LayoutDirection layoutDirection) + { + switch(m_type) + { + case TextFormatTypeTableCell: + tableCellFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeTable: + tableFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeImage: + imageFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeFrame: + frameFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeList: + listFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeBlock: + blockFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeChar: + charFormat.setLayoutDirection(layoutDirection); + break; + case TextFormatTypeUnknown: + break; + } + } + + QTextTableCellFormat tableCellFormat; + QTextTableFormat tableFormat; + QTextImageFormat imageFormat; + QTextFrameFormat frameFormat; + QTextListFormat listFormat; + QTextBlockFormat blockFormat; + QTextCharFormat charFormat; + TextFormatType m_type; +}; + +class cDocumentReader : public QXmlStreamReader +{ +public: + cDocumentReader(const QString& szFileName); + ~cDocumentReader(); + + bool open(); + bool close(); + + cTextDocument* readDocument(); +private: + bool m_bFirstBlock; + QString m_szFileName; + QFile m_file; + + QMap m_textLists; + + void parseSettings(const QDomElement& element, cTextDocument* lpDocument); + void parseDefaults(const QDomElement& element, cTextDocument* lpDocument); + void parseTextBlock(const QDomElement& element, QTextCursor *lpCursor, const QVector& allFormats); + + QVector parseTextFormats(const QDomElement& element); + QTextLayout::FormatRange parseRange(const QDomElement& element); + QFont parseFont(const QDomElement& element); + QTextOption parseDefaultTextOption(const QDomElement& element); + QList parseTabPositions(const QDomElement& element); + QVector parseAllFormats(const QDomElement& element); + cTextFormat parseFormat(const QDomElement& element); + QPen parsePen(const QDomElement& element); + QBrush parseBrush(const QDomElement& element); + QColor parseColor(const QDomElement& element); + + QTextTableCellFormat parseTextTableCellFormat(const QDomElement& element); + QTextTableFormat parseTextTableFormat(const QDomElement& element); + QTextImageFormat parseTextImageFormat(const QDomElement& element); + QTextFrameFormat parseTextFrameFormat(const QDomElement& element); + QTextListFormat parseTextListFormat(const QDomElement& element); + QTextBlockFormat parseTextBlockFormat(const QDomElement& element); + QTextCharFormat parseTextCharFormat(const QDomElement& element); +}; + +#endif // CDOCUMENTREADER_H diff --git a/cdocumentwriter.cpp b/cdocumentwriter.cpp new file mode 100644 index 0000000..893cfc2 --- /dev/null +++ b/cdocumentwriter.cpp @@ -0,0 +1,620 @@ +#include "cdocumentwriter.h" +#include "ctextdocument.h" + +#include + + +cDocumentWriter::cDocumentWriter(const QString &szFileName) : + m_szFileName(szFileName) +{ +} + +cDocumentWriter::~cDocumentWriter() +{ + close(); +} + +bool cDocumentWriter::open() +{ + if(m_szFileName.isEmpty()) + return(false); + + m_file.setFileName(m_szFileName); + if(!m_file.open(QFile::WriteOnly | QFile::Text)) + return(false); + + setDevice(&m_file); + setAutoFormatting(true); + setAutoFormattingIndent(-1); + writeStartDocument(); + writeStartElement("document"); + + return(true); +} + +bool cDocumentWriter::close() +{ + if(m_file.isOpen()) + { + writeEndElement(); + writeEndDocument(); + m_file.close(); + } + + return(true); +} + +bool cDocumentWriter::writeDocument(cTextDocument *lpDocument) +{ + QList> textBlockFormats; + QTextBlock textBlock = lpDocument->firstBlock(); + + while(textBlock.isValid()) + { + int x; + for(x = 0;x < textBlockFormats.count();x++) + { + if(textBlockFormats[x].first == textBlock.blockFormatIndex()) + break; + } + if(x >= textBlockFormats.count()) + textBlockFormats.append(QPair(textBlock.blockFormatIndex(), textBlock.blockFormat())); + + textBlock = textBlock.next(); + } + + writeStartElement("documentSettings"); + writeAttribute("documentMargin", QString::number(lpDocument->documentMargin())); + writeAttribute("indentWidth", QString::number(lpDocument->indentWidth())); + writeAttribute("textWidth", QString::number(lpDocument->textWidth())); + writeAttribute("useDesignMetrics", lpDocument->useDesignMetrics() == true ? "true" : "false"); + + writeStartElement("metaInformation"); + writeAttribute("documentTitle", lpDocument->metaInformation(QTextDocument::DocumentTitle)); + writeAttribute("documentUrl", lpDocument->metaInformation(QTextDocument::DocumentUrl)); + writeEndElement(); + + writeStartElement("baseUrl"); + writeAttribute("authority", lpDocument->baseUrl().authority()); + writeAttribute("fragment", lpDocument->baseUrl().fragment()); + writeAttribute("host", lpDocument->baseUrl().host()); + writeAttribute("password", lpDocument->baseUrl().password()); + writeAttribute("path", lpDocument->baseUrl().path()); + writeAttribute("port", QString::number(lpDocument->baseUrl().port())); + writeAttribute("query", lpDocument->baseUrl().query()); + writeAttribute("scheme", lpDocument->baseUrl().scheme()); + writeAttribute("url", lpDocument->baseUrl().url()); + writeAttribute("userInfo", lpDocument->baseUrl().userInfo()); + writeAttribute("userName", lpDocument->baseUrl().userName()); + writeEndElement(); + + writeStartElement("pageSize"); + writeAttribute("width", QString::number(lpDocument->pageSize().width())); + writeAttribute("height", QString::number(lpDocument->pageSize().height())); + writeEndElement(); + writeEndElement(); + + writeStartElement("defaults"); + writeAttribute("defaultCursorMoveStyle", QString::number(lpDocument->defaultCursorMoveStyle())); + writeAttribute("defaultStyleSheet", lpDocument->defaultStyleSheet()); + + writeStartElement("defaultFont"); + writeFont(lpDocument->defaultFont()); + writeEndElement(); + + writeStartElement("defaultTextOption"); + writeTextOption(lpDocument->defaultTextOption()); + writeEndElement(); + writeEndElement(); + + writeFormats(lpDocument->allFormats()); + writeTextBlockFormats(textBlockFormats); + + textBlock = lpDocument->firstBlock(); + writeTextBlocks(textBlock); + + return(true); +} + +void cDocumentWriter::writeTextBlockFormats(const QList> textBlockFormats) +{ + writeStartElement("textBlockFormats"); + for(int x = 0;x < textBlockFormats.count();x++) + { + writeStartElement("format"); + writeFormat(textBlockFormats[x].second, textBlockFormats[x].first); + writeEndElement(); + } + writeEndElement(); +} + +void cDocumentWriter::writeTextBlocks(QTextBlock& textBlock) +{ + writeStartElement("textBlocks"); + while(textBlock.isValid()) + { + writeStartElement("textBlock"); + writeTextBlock(textBlock); + writeEndElement(); + textBlock = textBlock.next(); + } + writeEndElement(); +} + +#include +#include + +void cDocumentWriter::writeTextBlock(const QTextBlock& textBlock) +{ + QTextCursor cursor(textBlock); + QTextList* lpTextList = cursor.currentList(); + QTextTable* lpTextTable = cursor.currentTable(); + + writeAttribute("blockFormatIndex", QString::number(textBlock.blockFormatIndex())); + writeAttribute("charFormatIndex", QString::number(textBlock.charFormatIndex())); + writeAttribute("listFormatIndex", QString::number(lpTextList == 0 ? -1 : lpTextList->formatIndex())); + writeAttribute("tableFormatIndex", QString::number(lpTextTable == 0 ? -1 : lpTextTable->formatIndex())); + + QVector textFormats = textBlock.textFormats(); + writeStartElement("textFormats"); + for(int x = 0;x < textFormats.count();x++) + { + QTextLayout::FormatRange range = textFormats[x]; + QTextCharFormat format = range.format; + writeStartElement("range"); + writeAttribute("start", QString::number(range.start)); + writeAttribute("length", QString::number(range.length)); + writeTextCharFormat((QTextCharFormat*)&format, -1, WriteAttribute); + writeTextFormat((QTextFormat*)&format, -1, WriteAll); + writeTextCharFormat((QTextCharFormat*)&format, -1, WriteElements); + writeEndElement(); + } + writeEndElement(); + + writeTextElement("text", textBlock.text()); +} + +void cDocumentWriter::writeColor(QColor color) +{ + writeAttribute("alpha", QString::number(color.alpha())); + writeAttribute("r", QString::number(color.red())); + writeAttribute("g", QString::number(color.green())); + writeAttribute("b", QString::number(color.blue())); +} + +void cDocumentWriter::writeGradient(const QGradient* lpGradient) +{ + writeAttribute("type", QString::number(lpGradient->type())); + writeTextElement("spread", QString::number(lpGradient->spread())); + + for(int x = 0;x < lpGradient->stops().count();x++) + { + writeStartElement("stop"); + writeAttribute("pos", QString::number(lpGradient->stops()[x].first)); + + writeStartElement("color"); + writeColor(lpGradient->stops()[x].second); + writeEndElement(); + + writeEndElement(); + } +} + +void cDocumentWriter::writePen(const QPen& pen) +{ + writeAttribute("capStyle", QString::number(pen.capStyle())); + writeAttribute("dashOffset", QString::number(pen.dashOffset())); + writeAttribute("isCosmetic", pen.isCosmetic() == true ? "true" : "false"); + writeAttribute("joinStyle", QString::number(pen.joinStyle())); + writeAttribute("miterLimit", QString::number(pen.miterLimit())); + writeAttribute("style", QString::number(pen.style())); + writeAttribute("width", QString::number(pen.width())); + writeAttribute("widthF", QString::number(pen.widthF())); + + writeStartElement("brush"); + writeBrush(pen.brush()); + writeEndElement(); + + writeStartElement("color"); + writeColor(pen.color()); + writeEndElement(); + + if(pen.dashPattern().count()) + { + writeStartElement("dashPattern"); + for(int x = 0;x < pen.dashPattern().count();x++) + writeTextElement("pattern", QString::number(pen.dashPattern()[x])); + writeEndElement(); + } +} + +void cDocumentWriter::writeBrush(const QBrush& brush) +{ + writeAttribute("style", QString::number(brush.style())); + + writeStartElement("color"); + writeColor(brush.color()); + writeEndElement(); + + if(brush.gradient()) + { + writeStartElement("gradient"); + writeGradient(brush.gradient()); + writeEndElement(); + } + + //matrix + //texture oder textureImage +} + +void cDocumentWriter::writeFont(const QFont& font) +{ + writeAttribute("bold", font.bold() == true ? "true" : "false"); + writeAttribute("capitalization", QString::number(font.capitalization())); +// writeAttribute("defaultFamily", font.defaultFamily()); +// writeAttribute("exactMatch", font.exactMatch() == true ? "true" : "false"); + writeAttribute("family", font.family()); + writeAttribute("fixedPitch", font.fixedPitch() == true ? "true" : "false"); + writeAttribute("hintingPreference", QString::number(font.hintingPreference())); + writeAttribute("italic", font.italic() == true ? "true" : "false"); + writeAttribute("kerning", font.kerning() == true ? "true" : "false"); + writeAttribute("letterSpacing", QString::number(font.letterSpacing())); + writeAttribute("letterSpacingType", QString::number(font.letterSpacingType())); + writeAttribute("overline", QString::number(font.overline())); + writeAttribute("pixelSize", QString::number(font.pixelSize())); + writeAttribute("pointSize", QString::number(font.pointSize())); + writeAttribute("pointSizeF", QString::number(font.pointSizeF())); + writeAttribute("stretch", QString::number(font.stretch())); + writeAttribute("strikeOut", font.strikeOut() == true ? "true" : "false"); + writeAttribute("style", QString::number(font.style())); + writeAttribute("styleHint", QString::number(font.styleHint())); + writeAttribute("styleName", font.styleName()); + writeAttribute("styleStrategy", QString::number(font.styleStrategy())); + writeAttribute("underline", font.underline() == true ? "true" : "false"); + writeAttribute("weight", QString::number(font.weight())); + writeAttribute("wordSpacing", QString::number(font.wordSpacing())); +} + +void cDocumentWriter::writeFormat(const QTextFormat& textFormat, int id) +{ + writeAttribute("type", QString::number(textFormat.type())); + + if(textFormat.isTableCellFormat()) + { + writeAttribute("typeText", "tableCellFormat"); + writeTextTableCellFormat((QTextTableCellFormat*)&textFormat, id, WriteAttribute); + writeTextCharFormat((QTextCharFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextTableCellFormat((QTextTableCellFormat*)&textFormat, id, WriteElements); + writeTextCharFormat((QTextCharFormat*)&textFormat, id, WriteElements); + } + else if(textFormat.isTableFormat()) + { + writeAttribute("typeText", "tableFormat"); + writeTextTableFormat((QTextTableFormat*)&textFormat, id, WriteAttribute); + writeTextFrameFormat((QTextFrameFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextTableFormat((QTextTableFormat*)&textFormat, id, WriteElements); + writeTextFrameFormat((QTextFrameFormat*)&textFormat, id, WriteElements); + } + else if(textFormat.isImageFormat()) + { + writeAttribute("typeText", "imageFormat"); + writeTextImageFormat((QTextImageFormat*)&textFormat, id, WriteAttribute); + writeTextCharFormat((QTextCharFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextImageFormat((QTextImageFormat*)&textFormat, id, WriteElements); + writeTextCharFormat((QTextCharFormat*)&textFormat, id, WriteElements); + } + else if(textFormat.isFrameFormat()) + { + writeAttribute("typeText", "frameFormat"); + writeTextFrameFormat((QTextFrameFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextFrameFormat((QTextFrameFormat*)&textFormat, id, WriteElements); + } + else if(textFormat.isListFormat()) + { + writeAttribute("typeText", "listFormat"); + writeTextListFormat((QTextListFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextListFormat((QTextListFormat*)&textFormat, id, WriteElements); + } + else if(textFormat.isBlockFormat()) + { + writeAttribute("typeText", "blockFormat"); + writeTextBlockFormat((QTextBlockFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextBlockFormat((QTextBlockFormat*)&textFormat, id, WriteElements); + } + else if(textFormat.isCharFormat()) + { + writeAttribute("typeText", "charFormat"); + writeTextCharFormat((QTextCharFormat*)&textFormat, id, WriteAttribute); + writeTextFormat((QTextFormat*)&textFormat, id, WriteAll); + writeTextCharFormat((QTextCharFormat*)&textFormat, id, WriteElements); + } +} + +void cDocumentWriter::writeTextFormat(QTextFormat* lpTextFormat, int /*id*/, WritePart part) +{ + if(lpTextFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("layoutDirection", QString::number(lpTextFormat->layoutDirection())); + } + + if(part & WriteElements) + { + writeStartElement("background"); + writeBrush(lpTextFormat->background()); + writeEndElement(); + + writeStartElement("foreground"); + writeBrush(lpTextFormat->foreground()); + writeEndElement(); + + writeStartElement("properties"); + QMap properties = lpTextFormat->properties(); + QMapIterator property(properties); + + while(property.hasNext()) + { + property.next(); + writeStartElement("property"); + writeAttribute("key", QString::number(property.key())); + writeAttribute("type", QString::number(property.value().type())); + writeTextElement("value", property.value().toString()); + writeEndElement(); + } + writeEndElement(); + } + } +} + +void cDocumentWriter::writeFormats(const QVector formats) +{ + writeStartElement("allFormats"); + for(int x = 0;x < formats.count();x++) + { + writeStartElement("format"); + writeAttribute("id", QString::number(x)); + writeFormat(formats[x]); + writeEndElement(); + } + writeEndElement(); +} + +void cDocumentWriter::writeTabPositions(const QList tabs) +{ + for(int x = 0;x < tabs.count();x++) + { + QTextOption::Tab tab = tabs[x]; + writeStartElement("tabPosition"); + writeAttribute("delimiter", tab.delimiter); + writeAttribute("position", QString::number(tab.position)); + writeAttribute("type", QString::number(tab.type)); + writeEndElement(); + } +} + +void cDocumentWriter::writeTextBlockFormat(QTextBlockFormat* lpTextBlockFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextBlockFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("alignment", QString::number(lpTextBlockFormat->alignment())); + writeAttribute("topMargin", QString::number(lpTextBlockFormat->topMargin())); + writeAttribute("leftMargin", QString::number(lpTextBlockFormat->leftMargin())); + writeAttribute("bottomMargin", QString::number(lpTextBlockFormat->bottomMargin())); + writeAttribute("rightMargin", QString::number(lpTextBlockFormat->rightMargin())); + writeAttribute("indent", QString::number(lpTextBlockFormat->indent())); + writeAttribute("lineHeight", QString::number(lpTextBlockFormat->lineHeight())); + writeAttribute("lineHeightType", QString::number(lpTextBlockFormat->lineHeightType())); + writeAttribute("nonBreakableLines", lpTextBlockFormat->nonBreakableLines() == true ? "true" : "false"); + writeAttribute("pageBreakPolicy", QString::number(lpTextBlockFormat->pageBreakPolicy())); + writeAttribute("textIndent", QString::number(lpTextBlockFormat->textIndent())); + } + + if(part & WriteElements) + { + writeStartElement("tabPositions"); + writeTabPositions(lpTextBlockFormat->tabPositions()); + writeEndElement(); + } + } +} + +void cDocumentWriter::writeTextCharFormat(QTextCharFormat* lpTextCharFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextCharFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("anchorHref", lpTextCharFormat->anchorHref()); +// writeAttribute("fontCapitalization", QString::number(lpTextCharFormat->fontCapitalization())); +// writeAttribute("fontFamily", lpTextCharFormat->fontFamily()); +// writeAttribute("fontFixedPitch", lpTextCharFormat->fontFixedPitch() == true ? "true" : "false"); +// writeAttribute("fontHintingPreference", QString::number(lpTextCharFormat->fontHintingPreference())); +// writeAttribute("fontItalic", lpTextCharFormat->fontItalic() == true ? "true" : "false"); +// writeAttribute("fontKerning", lpTextCharFormat->fontKerning() == true ? "true" : "false"); +// writeAttribute("fontLetterSpacing", QString::number(lpTextCharFormat->fontLetterSpacing())); +// writeAttribute("fontLetterSpacingType", QString::number(lpTextCharFormat->fontLetterSpacingType())); +// writeAttribute("fontOverline", QString::number(lpTextCharFormat->fontOverline())); +// writeAttribute("fontPointSize", QString::number(lpTextCharFormat->fontPointSize())); +// writeAttribute("fontStretch", QString::number(lpTextCharFormat->fontStretch())); +// writeAttribute("fontStrikeOut", lpTextCharFormat->fontStrikeOut() == true ? "true" : "false"); +// writeAttribute("fontStyleHint", QString::number(lpTextCharFormat->fontStyleHint())); +// writeAttribute("fontStyleStrategy", QString::number(lpTextCharFormat->fontStyleStrategy())); +// writeAttribute("fontUnderline", lpTextCharFormat->fontUnderline() == true ? "true" : "false"); +// writeAttribute("fontWeight", QString::number(lpTextCharFormat->fontWeight())); +// writeAttribute("fontWordSpacing", QString::number(lpTextCharFormat->fontWordSpacing())); + writeAttribute("isAnchor", lpTextCharFormat->isAnchor() == true ? "true" : "false"); + writeAttribute("toolTip", lpTextCharFormat->toolTip()); + writeAttribute("verticalAlignment", QString::number(lpTextCharFormat->verticalAlignment())); + } + + if(part & WriteElements) + { + writeStartElement("textOutline"); + writePen(lpTextCharFormat->textOutline()); + writeEndElement(); + + writeStartElement("anchorNames"); + for(int x = 0;x < lpTextCharFormat->anchorNames().count();x++) + writeTextElement("anchor", lpTextCharFormat->anchorNames()[x]); + writeEndElement(); + + writeStartElement("font"); + writeFont(lpTextCharFormat->font()); + writeEndElement(); + + writeStartElement("underlineColor"); + writeColor(lpTextCharFormat->underlineColor()); + writeEndElement(); + } + } +} + +void cDocumentWriter::writeTextFrameFormat(QTextFrameFormat* lpTextFrameFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextFrameFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("border", QString::number(lpTextFrameFormat->border())); + writeAttribute("borderStyle", QString::number(lpTextFrameFormat->borderStyle())); + writeAttribute("margin", QString::number(lpTextFrameFormat->margin())); + writeAttribute("leftMargin", QString::number(lpTextFrameFormat->leftMargin())); + writeAttribute("topMargin", QString::number(lpTextFrameFormat->topMargin())); + writeAttribute("rightMargin", QString::number(lpTextFrameFormat->rightMargin())); + writeAttribute("bottomMargin", QString::number(lpTextFrameFormat->bottomMargin())); + writeAttribute("width", QString::number(lpTextFrameFormat->width().rawValue())); + writeAttribute("height", QString::number(lpTextFrameFormat->height().rawValue())); + writeAttribute("padding", QString::number(lpTextFrameFormat->padding())); + writeAttribute("pageBreakPolicy", QString::number(lpTextFrameFormat->pageBreakPolicy())); + writeAttribute("position", QString::number(lpTextFrameFormat->position())); + } + + if(part & WriteElements) + { + writeStartElement("borderBrush"); + writeBrush(lpTextFrameFormat->borderBrush()); + writeEndElement(); + } + } +} + +void cDocumentWriter::writeTextImageFormat(QTextImageFormat* lpTextImageFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextImageFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("name", lpTextImageFormat->name()); + writeAttribute("height", QString::number(lpTextImageFormat->height())); + writeAttribute("width", QString::number(lpTextImageFormat->width())); + } + } +} + +void cDocumentWriter::writeTextListFormat(QTextListFormat* lpTextListFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextListFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("indent", QString::number(lpTextListFormat->indent())); + writeAttribute("numberPrefix", lpTextListFormat->numberPrefix()); + writeAttribute("numberSuffix", lpTextListFormat->numberSuffix()); + writeAttribute("style", QString::number(lpTextListFormat->style())); + } + } +} + +void cDocumentWriter::writeTextTableCellFormat(QTextTableCellFormat* lpTextTableCellFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextTableCellFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("leftPadding", QString::number(lpTextTableCellFormat->leftPadding())); + writeAttribute("topPadding", QString::number(lpTextTableCellFormat->topPadding())); + writeAttribute("rightPadding", QString::number(lpTextTableCellFormat->rightPadding())); + writeAttribute("bottomPadding", QString::number(lpTextTableCellFormat->bottomPadding())); + } + } +} + +void cDocumentWriter::writeTextTableFormat(QTextTableFormat* lpTextTableFormat, int id, WritePart part) +{ + if(part & WriteAttribute && id != -1) + writeAttribute("id", QString::number(id)); + + if(lpTextTableFormat->isValid()) + { + if(part & WriteAttribute) + { + writeAttribute("alignment", QString::number(lpTextTableFormat->alignment())); + writeAttribute("cellPadding", QString::number(lpTextTableFormat->cellPadding())); + writeAttribute("cellSpacing", QString::number(lpTextTableFormat->cellSpacing())); + writeAttribute("columns", QString::number(lpTextTableFormat->columns())); + writeAttribute("headerRowCount", QString::number(lpTextTableFormat->headerRowCount())); + } + + if(part & WriteElements) + { + if(lpTextTableFormat->columnWidthConstraints().count()) + { + writeStartElement("columnWidthConstraints"); + for(int x = 0;x < lpTextTableFormat->columnWidthConstraints().count();x++) + { + writeStartElement("columnWidthConstraint"); + writeAttribute("rawValue", QString::number(lpTextTableFormat->columnWidthConstraints()[x].rawValue())); + writeAttribute("type", QString::number(lpTextTableFormat->columnWidthConstraints()[x].type())); + writeEndElement(); + } + writeEndElement(); + } + } + } +} + +void cDocumentWriter::writeTextOption(const QTextOption& textOption) +{ + writeAttribute("alignment", QString::number(textOption.alignment())); + writeAttribute("flags", QString::number(textOption.flags())); + writeAttribute("tabStopDistance", QString::number(textOption.tabStopDistance())); + writeAttribute("textDirection", QString::number(textOption.textDirection())); + writeAttribute("useDesignMetrics", textOption.useDesignMetrics() == true ? "true" : "false"); + writeAttribute("wrapMode", QString::number(textOption.wrapMode())); + + writeStartElement("tabArray"); + for(int x = 0;x < textOption.tabArray().count();x++) + writeTextElement("tab", QString::number(textOption.tabArray()[x])); + writeEndElement(); + + writeStartElement("tabs"); + writeTabPositions(textOption.tabs()); + writeEndElement(); +} diff --git a/cdocumentwriter.h b/cdocumentwriter.h new file mode 100644 index 0000000..3a76a32 --- /dev/null +++ b/cdocumentwriter.h @@ -0,0 +1,75 @@ +#ifndef CDOCUMENTWRITER_H +#define CDOCUMENTWRITER_H + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +class cTextDocument; + + +class cDocumentWriter : public QXmlStreamWriter +{ +public: + enum WritePart + { + WriteAll = 3, + WriteAttribute = 1, + WriteElements = 2, + }; + + cDocumentWriter(const QString& szFileName); + ~cDocumentWriter(); + + bool open(); + bool close(); + + bool writeDocument(cTextDocument* lpDocument); + +private: + QString m_szFileName; + QFile m_file; + + void writeTextBlockFormats(const QList> textBlockFormats); + void writeTextBlocks(QTextBlock& textBlock); + void writeColor(QColor color); + void writeGradient(const QGradient* lpGradient); + void writePen(const QPen& pen); + void writeBrush(const QBrush& brush); + void writeFormat(const QTextFormat& textFormat, int id = -1); + void writeFont(const QFont& font); + + void writeTextBlock(const QTextBlock& textBlock); + + void writeFormats(const QVector formats); + + void writeTextFormat(QTextFormat* lpTextFormat, int id = -1, WritePart part = WriteAll); + void writeTextBlockFormat(QTextBlockFormat* lpTextBlockFormat, int id = -1, WritePart part = WriteAll); + void writeTextCharFormat(QTextCharFormat* lpTextCharFormat, int id = -1, WritePart part = WriteAll); + void writeTextFrameFormat(QTextFrameFormat* lpTextFrameFormat, int id = -1, WritePart part = WriteAll); + void writeTextImageFormat(QTextImageFormat* lpTextImageFormat, int id = -1, WritePart part = WriteAll); + void writeTextListFormat(QTextListFormat* lpTextListFormat, int id = -1, WritePart part = WriteAll); + void writeTextTableCellFormat(QTextTableCellFormat* lpTextTableCellFormat, int id = -1, WritePart part = WriteAll); + void writeTextTableFormat(QTextTableFormat* lpTextTableFormat, int id = -1, WritePart part = WriteAll); + + void writeTextOption(const QTextOption &textOption); + + void writeTabPositions(const QList tabs); +}; + +#endif // CDOCUMENTWRITER_H diff --git a/cmainwindow.cpp b/cmainwindow.cpp new file mode 100644 index 0000000..5e209a2 --- /dev/null +++ b/cmainwindow.cpp @@ -0,0 +1,278 @@ +#include "cmainwindow.h" +#include "ui_cmainwindow.h" + +#include "ctextdocument.h" +#include "cdocumentreader.h" + +#include +#include +#include + +#include +#include +#include +#include + + +cTextDocument* g_lpInputDocument = 0; +cTextDocument* g_lpOutputDocument = 0; + + +QTextBlockFormat createTextBlockFormat(Qt::Alignment alignment, qreal leftMargin, qreal topMargin, qreal rightMargin, qreal bottomMargin, int indent, qreal lineHeight, int lineHeightType, + bool nonBreakableLines, QTextBlockFormat::PageBreakFlags pageBreakPolicy, const QList& tabPositions, qreal textIndent, + QBrush background, QBrush foreground, Qt::LayoutDirection layoutDirection, int objectIndex, int objectType /* property*/) +{ + QTextBlockFormat format; + + format.setAlignment(alignment); + format.setLeftMargin(leftMargin); + format.setTopMargin(topMargin); + format.setRightMargin(rightMargin); + format.setBottomMargin(bottomMargin); + format.setIndent(indent); + format.setLineHeight(lineHeight, lineHeightType); + format.setNonBreakableLines(nonBreakableLines); + format.setPageBreakPolicy(pageBreakPolicy); + format.setTabPositions(tabPositions); + format.setTextIndent(textIndent); + + format.setBackground(background); + format.setForeground(foreground); + format.setLayoutDirection(layoutDirection); + format.setObjectIndex(objectIndex); + format.setObjectType(objectType); + //property + + return(format); +} + +QTextCharFormat createTextCharFormat(bool anchor, const QString& anchorHref, const QStringList& anchorNames, const QFont& font, QTextCharFormat::FontPropertiesInheritanceBehavior behavior, + const QPen& textOutline, const QString& toolTip, const QColor& underlineColor, QTextCharFormat::UnderlineStyle underlineStyle, QTextCharFormat::VerticalAlignment verticalAlignment, + QBrush background, QBrush foreground, Qt::LayoutDirection layoutDirection, int objectIndex, int objectType /* property*/) +{ + QTextCharFormat format; + + format.setAnchor(anchor); + format.setAnchorHref(anchorHref); + format.setAnchorNames(anchorNames); + format.setFont(font, behavior); + format.setTextOutline(textOutline); + format.setToolTip(toolTip); + format.setUnderlineColor(underlineColor); + format.setUnderlineStyle(underlineStyle); + format.setVerticalAlignment(verticalAlignment); + + format.setBackground(background); + format.setForeground(foreground); + format.setLayoutDirection(layoutDirection); + format.setObjectIndex(objectIndex); + format.setObjectType(objectType); + //property + + return(format); +} + +void readWriteTest1() +{ + if(!QFile::exists(":/example.html")) + return; + QFile file(":/example.html"); + + if(!file.open(QFile::ReadOnly)) + return; + + QByteArray data = file.readAll(); + QTextCodec* codec = Qt::codecForHtml(data); + QString str = codec->toUnicode(data); + if(Qt::mightBeRichText(str)) + { + g_lpInputDocument->setHtml(str); + } + else + { + str = QString::fromLocal8Bit(data); + g_lpInputDocument->setPlainText(str); + } + + file.close(); +} + +void readWriteTest2() +{ + QTextCursor cursor(g_lpInputDocument); + + // TEXT BLOCK FORMAT + Qt::Alignment alignment = Qt::AlignCenter; + qreal leftMargin = 0; + qreal topMargin = 0; + qreal rightMargin = 0; + qreal bottomMargin = 0; + int indent = 0; + qreal lineHeight = 1; + int lineHeightType = QTextBlockFormat::SingleHeight; // QTextBlockFormat::SingleHeight 0 This is the default line height: single spacing. + // QTextBlockFormat::ProportionalHeight 1 This sets the spacing proportional to the line (in percentage). For example, set to 200 for double spacing. + // QTextBlockFormat::FixedHeight 2 This sets the line height to a fixed line height (in pixels). + // QTextBlockFormat::MinimumHeight 3 This sets the minimum line height (in pixels). + // QTextBlockFormat::LineDistanceHeight 4 This adds the specified height between lines (in pixels). + bool nonBreakableLines = false; + QTextBlockFormat::PageBreakFlags pageBreakPolicy = QTextFormat::PageBreak_Auto; // QTextFormat::PageBreak_Auto 0 The page break is determined automatically depending on the available space on the current page + // QTextFormat::PageBreak_AlwaysBefore 0x001 The page is always broken before the paragraph/table + // QTextFormat::PageBreak_AlwaysAfter 0x010 A new page is always started after the paragraph/table + const QList tabPositions; + qreal textIndent = 0; + QBrush background = QBrush(QColor("lightGray")); + QBrush foreground = QBrush(QColor("black")); + Qt::LayoutDirection layoutDirection = Qt::LeftToRight; // Qt::LeftToRight 0 Left-to-right layout. + // Qt::RightToLeft 1 Right-to-left layout. + // Qt::LayoutDirectionAuto 2 Automatic layout. + int objectIndex = 0; + int objectType = QTextFormat::NoObject; // QTextFormat::NoObject 0 + // QTextFormat::ImageObject 1 + // QTextFormat::TableObject 2 + // QTextFormat::TableCellObject 3 + // QTextFormat::UserObject 0x1000 The first object that can be used for application-specific purposes. + //property + + + // TEXT CHAR FORMAT + bool anchor = false; + QString anchorHref = ""; + QStringList anchorNames; + QFont font = QFont("Arial"); + QTextCharFormat::FontPropertiesInheritanceBehavior behavior = QTextCharFormat::FontPropertiesAll;// QTextCharFormat::FontPropertiesSpecifiedOnly 0 If a property is not explicitly set, do not change the text format's property value. + // QTextCharFormat::FontPropertiesAll 1 If a property is not explicitly set, override the text format's property with a default value. + QPen textOutline = QPen(QColor("blue")); + QString toolTip = "toolTip"; + QColor underlineColor = QColor("yellow"); + QTextCharFormat::UnderlineStyle underlineStyle = QTextCharFormat::NoUnderline; // QTextCharFormat::NoUnderline 0 Text is draw without any underlining decoration. + // QTextCharFormat::SingleUnderline 1 A line is drawn using Qt::SolidLine. + // QTextCharFormat::DashUnderline 2 Dashes are drawn using Qt::DashLine. + // QTextCharFormat::DotLine 3 Dots are drawn using Qt::DotLine; + // QTextCharFormat::DashDotLine 4 Dashs and dots are drawn using Qt::DashDotLine. + // QTextCharFormat::DashDotDotLine 5 Underlines draw drawn using Qt::DashDotDotLine. + // QTextCharFormat::WaveUnderline 6 The text is underlined using a wave shaped line. + // QTextCharFormat::SpellCheckUnderline 7 The underline is drawn depending on the SpellCheckUnderlineStyle theme hint of QPlatformTheme. By default this is mapped to WaveUnderline, on macOS it is mapped to DotLine. + QTextCharFormat::VerticalAlignment verticalAlignment = QTextCharFormat::AlignNormal; // QTextCharFormat::AlignNormal 0 Adjacent characters are positioned in the standard way for text in the writing system in use. + // QTextCharFormat::AlignSuperScript 1 Characters are placed above the base line for normal text. + // QTextCharFormat::AlignSubScript 2 Characters are placed below the base line for normal text. + // QTextCharFormat::AlignMiddle 3 The center of the object is vertically aligned with the base line. Currently, this is only implemented for inline objects. + // QTextCharFormat::AlignBottom 5 The bottom edge of the object is vertically aligned with the base line. + // QTextCharFormat::AlignTop 4 The top edge of the object is vertically aligned with the base line. + // QTextCharFormat::AlignBaseline 6 The base lines of the characters are aligned. + QBrush background1 = QBrush(QColor("red")); + QBrush foreground1 = QBrush(QColor("green")); + Qt::LayoutDirection layoutDirection1 = Qt::LeftToRight; // Qt::LeftToRight 0 Left-to-right layout. + // Qt::RightToLeft 1 Right-to-left layout. + // Qt::LayoutDirectionAuto 2 Automatic layout. + int objectIndex1 = 0; + int objectType1 = QTextFormat::NoObject; // QTextFormat::NoObject 0 + // QTextFormat::ImageObject 1 + // QTextFormat::TableObject 2 + // QTextFormat::TableCellObject 3 + // QTextFormat::UserObject 0x1000 The first object that can be used for application-specific purposes. + //property + + QTextBlockFormat blockFormat1 = createTextBlockFormat(alignment, leftMargin, topMargin, rightMargin, bottomMargin, indent, lineHeight, lineHeightType, nonBreakableLines, pageBreakPolicy, tabPositions, textIndent, background, foreground, layoutDirection, objectIndex, objectType); + QTextCharFormat charFormat1 = createTextCharFormat(anchor, anchorHref, anchorNames, font, behavior, textOutline, toolTip, underlineColor, underlineStyle, verticalAlignment, background1, foreground1, layoutDirection1, objectIndex1, objectType1); // property); + + cursor.setBlockFormat(blockFormat1); + cursor.setBlockCharFormat(charFormat1); + + cursor.insertText("TestText"); +} + +#include + +void readWriteTest3() +{ + QTextCursor cursor(g_lpInputDocument); + + QTextListFormat* lpFormat = new QTextListFormat; + QString numberSuffix = lpFormat->numberSuffix(); + + lpFormat->setNumberSuffix("."); + numberSuffix = lpFormat->numberSuffix(); + + delete lpFormat; + + QTextList* list1; + QTextList* list2; + QTextList* list3; + QTextBlock textBlock; + + QTextListFormat format1; + QTextListFormat format2; + QTextListFormat format3; + format1.setStyle(QTextListFormat::ListDecimal); + format1.setIndent(1); + format2.setStyle(QTextListFormat::ListLowerAlpha); + format2.setIndent(2); + format3.setStyle(QTextListFormat::ListUpperAlpha); + format3.setIndent(3); + + list1 = cursor.insertList(format1); + textBlock = cursor.block(); cursor.insertText("Introduction"); list1->add(textBlock); + cursor.insertBlock(); textBlock = cursor.block(); cursor.insertText("Tools"); list1->add(textBlock); + + list2 = cursor.insertList(format2); + textBlock = cursor.block(); cursor.insertText("Assistant"); list2->add(textBlock); + cursor.insertBlock(); textBlock = cursor.block(); cursor.insertText("Designer"); list2->add(textBlock); + + list3 = cursor.insertList(format3); + textBlock = cursor.block(); cursor.insertText("Form Editor"); list3->add(textBlock); + cursor.insertBlock(); textBlock = cursor.block(); cursor.insertText("Component Architecture"); list3->add(textBlock); + + cursor.insertBlock(); textBlock = cursor.block(); cursor.insertText("Qt Linguist"); list2->add(textBlock); +} + +cMainWindow::cMainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::cMainWindow) +{ + ui->setupUi(this); + ui->m_lpTabWidget->setCurrentIndex(0); + + g_lpInputDocument = new cTextDocument(ui->m_lpInput); + g_lpOutputDocument = new cTextDocument(ui->m_lpOutput); + + ui->m_lpInput->setDocument(g_lpInputDocument); + + readWriteTest1(); +// readWriteTest2(); +// readWriteTest3(); +} + +cMainWindow::~cMainWindow() +{ + delete ui; + + if(g_lpInputDocument) + delete g_lpInputDocument; + + if(g_lpOutputDocument) + delete g_lpOutputDocument; +} + +void cMainWindow::on_actionTest1_triggered() +{ + QTextBlockFormat blockFormatStyle; + blockFormatStyle.setBackground(QColor("red")); + + QTextCursor cursor(g_lpInputDocument); + cursor.setBlockFormat(blockFormatStyle); + + QTextCharFormat charFormatStyle; + +} + +void cMainWindow::on_actionSave_triggered() +{ + g_lpInputDocument->saveAs("C:/Temp/documentText.xml"); + + cDocumentReader reader("C:/Temp/documentText.xml"); + reader.open(); + g_lpOutputDocument = reader.readDocument(); + reader.close(); + + ui->m_lpOutput->setDocument(g_lpOutputDocument); +} diff --git a/cmainwindow.h b/cmainwindow.h new file mode 100644 index 0000000..3f84cb7 --- /dev/null +++ b/cmainwindow.h @@ -0,0 +1,27 @@ +#ifndef CMAINWINDOW_H +#define CMAINWINDOW_H + +#include + +namespace Ui { +class cMainWindow; +} + +class cMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit cMainWindow(QWidget *parent = 0); + ~cMainWindow(); + +private slots: + void on_actionTest1_triggered(); + + void on_actionSave_triggered(); + +private: + Ui::cMainWindow *ui; +}; + +#endif // CMAINWINDOW_H diff --git a/cmainwindow.ui b/cmainwindow.ui new file mode 100644 index 0000000..11431fb --- /dev/null +++ b/cmainwindow.ui @@ -0,0 +1,88 @@ + + + cMainWindow + + + + 0 + 0 + 569 + 460 + + + + cMainWindow + + + + + + + 0 + + + + Input + + + + + + + + + + Output + + + + + + + + + + + + + + + 0 + 0 + 569 + 21 + + + + + Test + + + + + + + + + TopToolBarArea + + + false + + + + + + Test1 + + + + + Save + + + + + + + diff --git a/common.cpp b/common.cpp new file mode 100644 index 0000000..67c02a2 --- /dev/null +++ b/common.cpp @@ -0,0 +1 @@ +#include "common.h" diff --git a/common.h b/common.h new file mode 100644 index 0000000..d4e2cb9 --- /dev/null +++ b/common.h @@ -0,0 +1,11 @@ +#ifndef COMMON_H +#define COMMON_H + + +#include + + +#define myDebug qDebug() << __FILE__ << "(" << __LINE__ << ") - " << __PRETTY_FUNCTION__ << ":" + + +#endif // COMMON_H diff --git a/ctextdocument.cpp b/ctextdocument.cpp new file mode 100644 index 0000000..d69a7a2 --- /dev/null +++ b/ctextdocument.cpp @@ -0,0 +1,115 @@ +#include "ctextdocument.h" +#include "cdocumentwriter.h" + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include + + +#if defined(QT_PRINTSUPPORT_LIB) + #include + #if QT_CONFIG(printer) + #if QT_CONFIG(printdialog) + #include + #endif + #include + #if QT_CONFIG(printpreviewdialog) + #include + #endif + #endif +#endif + + +cTextDocument::cTextDocument(QObject *parent) : + QTextDocument(parent) +{ + init(); +} + +cTextDocument::cTextDocument(const QString &text, QObject *parent) : + QTextDocument(text, parent), + m_szFileName(QString()) +{ + init(); +} + +void cTextDocument::init() +{ + setPageSize((QSizeF(210, 297))); +/* + QTextCursor* myCursor = new QTextCursor(this); + + QTextBlockFormat format; + format.setBackground(Qt::red); + myCursor->setBlockFormat(format); + + myCursor->insertText("the "); + + format.setBackground(Qt::green); + myCursor->insertBlock(format); + myCursor->insertText("fish "); + + format.setBackground(Qt::yellow); + myCursor->insertBlock(format); + myCursor->insertText("are "); + + format.setBackground(Qt::red); + myCursor->insertBlock(format); + myCursor->insertText("coming!"); + + format.setBackground(Qt::green); + myCursor->insertBlock(format); + myCursor->insertText(QString("%1 blocks").arg(this->blockCount())); +*/ +} + +bool cTextDocument::save() +{ + if(!m_szFileName.isEmpty()) + return(saveDocument()); + return(false); +} + +bool cTextDocument::saveAs(const QString& szFileName) +{ + m_szFileName = szFileName; + return(saveDocument()); +} + +bool cTextDocument::saveDocument() +{ + cDocumentWriter docWriter(m_szFileName); + if(!docWriter.open()) + return(false); + + docWriter.writeDocument(this); + + docWriter.close(); + return(true); +} + +void cTextDocument::printPreview(QPrinter* lpPrinter) +{ +#ifdef QT_NO_PRINTER + Q_UNUSED(lpPrinter); +#else + lpPrinter->setPageSizeMM(QSizeF(210, 297)); + print(lpPrinter); +#endif +} diff --git a/ctextdocument.h b/ctextdocument.h new file mode 100644 index 0000000..9e5d8d3 --- /dev/null +++ b/ctextdocument.h @@ -0,0 +1,37 @@ +#ifndef CTEXTDOCUMENT_H +#define CTEXTDOCUMENT_H + + +#include +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QComboBox; +class QFontComboBox; +class QTextEdit; +class QTextCharFormat; +class QMenu; +class QPrinter; +QT_END_NAMESPACE + + +class cTextDocument : public QTextDocument +{ +public: + cTextDocument(QObject *parent = Q_NULLPTR); + cTextDocument(const QString &text, QObject *parent = Q_NULLPTR); + + bool save(); + bool saveAs(const QString& szFileName); + + void printPreview(QPrinter* lpPrinter); +private: + QString m_szFileName; + + void init(); + bool saveDocument(); +private slots: +}; + +#endif // CTEXTDOCUMENT_H diff --git a/example.html b/example.html new file mode 100644 index 0000000..e3a56d1 --- /dev/null +++ b/example.html @@ -0,0 +1,79 @@ +QTextEdit Example +

QTextEdit

+

The QTextEdit widget is an advanced editor that supports formatted rich text. It can be used to display HTML and other rich document formats. Internally, QTextEdit uses the QTextDocument class to describe both the high-level structure of each document and the low-level formatting of paragraphs.

+

If you are viewing this document in the textedit example, you can edit this document to explore Qt's rich text editing features. We have included some comments in each of the following sections to encourage you to experiment.

+

Font and Paragraph Styles

+

QTextEdit supports bold, italic, and underlined font styles, and can display multicolored text. Font families such as Times New Roman and Courier can also be used directly. If you place the cursor in a region of styled text, the controls in the tool bars will change to reflect the current style.

+

Paragraphs can be formatted so that the text is left-aligned, right-aligned, centered, or fully justified.

+

Try changing the alignment of some text and resize the editor to see how the text layout changes.

+

Lists

+

Different kinds of lists can be included in rich text documents. Standard bullet lists can be nested, using different symbols for each level of the list:

+
  • Disc symbols are typically used for top-level list items.
+
  • Circle symbols can be used to distinguish between items in lower-level lists.
+
  • Square symbols provide a reasonable alternative to discs and circles.
+

Ordered lists can be created that can be used for tables of contents. Different characters can be used to enumerate items, and we can use both Roman and Arabic numerals in the same list structure:

+
  1. Introduction
  2. +
  3. Qt Tools
+
  1. Qt Assistant
  2. +
  3. Qt Designer
  4. +
    1. Form Editor
    2. +
    3. Component Architecture
    +
  5. Qt Linguist
+

+

The list will automatically be renumbered if you add or remove items. Try adding new sections to the above list or removing existing item to see the numbers change.

+

+

Images

+

Inline images are treated like ordinary ranges of characters in the text editor, so they flow with the surrounding text. Images can also be selected in the same way as text, making it easy to cut, copy, and paste them.

+

Try to select this image by clicking and dragging over it with the mouse, or use the text cursor to select it by holding down Shift and using the arrow keys. You can then cut or copy it, and paste it into different parts of this document.

+

Tables

+

QTextEdit can arrange and format tables, supporting features such as row and column spans, text formatting within cells, and size constraints for columns.

+

+

+ + + + + + + + + + + + + + + + + + + + + + +
+

+

Development Tools

+

Programming Techniques

+

Graphical User Interfaces

+

9:00 - 11:00

+

Introduction to Qt

+

11:00 - 13:00

+

Using qmake

+

Object-oriented Programming

+

Layouts in Qt

+

13:00 - 15:00

+

Qt Designer Tutorial

+

Extreme Programming

+

Writing Custom Styles

+

15:00 - 17:00

+

Qt Linguist and Internationalization

+

+

Try adding text to the cells in the table and experiment with the alignment of the paragraphs.

+

Hyperlinks

+

QTextEdit is designed to support hyperlinks between documents, and this feature is used extensively in Qt Assistant. Hyperlinks are automatically created when an HTML file is imported into an editor. Since the rich text framework supports hyperlinks natively, they can also be created programatically.

+

Undo and Redo

+

Full support for undo and redo operations is built into QTextEdit and the underlying rich text framework. Operations on a document can be packaged together to make editing a more comfortable experience for the user.

+

Try making changes to this document and press Ctrl+Z to undo them. You can always recover the original contents of the document.

diff --git a/images/logo32.png b/images/logo32.png new file mode 100644 index 0000000000000000000000000000000000000000..5f91e9873b7852876a84f0853a092868618a3fb1 GIT binary patch literal 1410 zcmV-|1%3L7P)v$L~SY6-f!x;i>HR#sK=^78fd z^~J@-XlZ9jN=O9;1SKaT932@F6bwK?KiJsVG&M1Ca&Vl(4EXr?&(F{A@9*K^;VmvI z-rnBl=jZ_e0ssI12t_Js|+|6Aoqv%b5VR3+&@t{S^PwGNDh`@iek**Q>Z7>0!uElblri*S-) zlJ-U4<0&Hl4JZ|bBEwL1ODpWS=y8&TSrKCbn#kV(d!}CjC8Y@bk6cm`uDc9_z53$;R2mG#|hWxbXhLH~z zLaN^k`Zz-jib?farw z)%*S9@@*x2{x(VwS{hU>AtVk;P1AyNR@ezWajq&soXhG9DqAZ)>Rd$0BY;B}4SG_ns5RUeEX zOx8ND1c8;%1RfNP`!NARRUN_f6am1S8{s&PQxc5zeBfsM>edRl0BN*ZO9D#)8>ZL%}Pjz|$tX^|4b0h{$W@Ux%et$1fQAtnc~_IYJydCNSu^IT>_ zH(P~c1SCZEF97iKTv+%SFlE-_Tk5ckvMd202&K7G4O*m`hBETw3c~dc=f4P|`TYvJ z>@<5`*SW4d*TW*aPWWiO<#BKh)S~^Xh+w>2pAoMtAAu_iB|uqrho$xEnW>i4P96%I z>TT`0b#7QCCTkm?yp8Mzk;$)dGgIEid$s#R9VOS3Aai1K23f2S9jkr#FkM+LL2+k~BONJB-N+SW6a}qWFBZ5|qLy10YuX z<}|`Wx`XfMl97;}s*OQ|&@Q4EpsF@}g?HC0EEBsw058{y0}ht21EBR9%W5Q)BndSR zh3$krJLt8}yBqVQ7vU*vHz|KDqykTnYKGMeW81dAWt`+DOHu{(sqHv1RA2@0I^NdN zj3NMW@h((5{Dur)A4X3?2Su;*f)JY)k0vPiMsdKJVFS*W@R2Rk2U{lWAmh;tiz{n5 zJ)<`^t3hybRT{^y8gPl#_K4RM_$WXxZo74zGXVH{w@5h+`jn+iG|gCYUn_g^>ubGw znwQPyvi-P=Vr9Z|a6qgegeXv8el<*@)P6gZrLI1j?!W;*REeMp%oR@reg?pf5;%&{ zEZx!|hyAaGp<^q)mCNX#e{Ecx2KE&&#cu&>TW?%sZyAkq*!OXtBnL&&OP=801ONzK z&<1Aj)XF-Hl<&kz3Q7uFDPuzZ2Y}#!8WbUQXw)WGl0rLAQxYYCfs};&1uTQy^!f3= Q0RR9107*qoM6N<$g5cAf`2YX_ literal 0 HcmV?d00001 diff --git a/images/mac/editcopy.png b/images/mac/editcopy.png new file mode 100644 index 0000000000000000000000000000000000000000..f551364464a7f4500a2660fd3aa450e79010b0cb GIT binary patch literal 1468 zcmV;t1w;CYP)j91nuo^rMU``FpK}lmcH2BoZ zAH4JCyEWmjwMzgT#=uOCdmd7JuO$v)s8lK_84mKr3f?+?`0VR1?tg<)*HQ}J{^;_d zx+S0Y_4P-WQtN}){+tE#xOPNB3Z5T~fVOJdJdnQKmA@NUp8wZ z?$zp{)J%XNrjyRSus42A?Cl?jb<@afrs%r1WnkxaM7vZ3@+)At< zl`TV!sF2PwGTtu5AKvyjs4rA-qt%${9h(@D41&{(T zn8XDH>P|Q8whCx0La*w<^E@zO22eD33b<_!Q`>H{03sKo>$;F2@wvzODg1sK81Se7 zXg2VlTtfnRF4nRvL9>8>%_G3Q_jpaTF#^JSA{Ha<@i)NsIHARWyv9?(=O$}&1Ssr8 zEDDn5bPZisMnMBy1?bt#Jx4g$#%n0TPNX!_qa+0JbW~kLfJ9nCPGg4pF{+ML3+gaHLO^`>>3d5AaWOXXLDedCV3tU)P&1)oPTCjX*K5}0@QqH zO(G~76n^TCB#t^`Ik$*k#>bF(lmH~zwB+suqqLR=5F{VyIR3p>h-svrPjk~WiIfCT zL!y!I&5m8e$d!l4mh?p>q)stJ7Fjj8$jsFE%#H5~03raG4_Dc!$cT(gi@c~ zLseB0#6L51ows7ID$$1^8eBO$E%%%;5Jcm#~)CE0Jxx)4}dz+2FRW35VI&O1b5c ztKVJ_qymyagMj8jXkHb6&l~<30XPL<7Qj^iH-Gr@Oj@d$Ao7XPguGq^8idrf;(q`V WtAfH(WC6_p0000P)<*VVWcuS0Ev&yc^UgmMxPuCq=o+h)UUDGbvCiz9KZ#z>#2T zH*7#DEhZZSSjH(6t!!&*4Y=|TLKTXy*{F8wRwLgUrhFc}3~-1;E4$B<4F?4UCH_=X(?2pYg3Kt<)7W_X9hIt7q`_@k0wj;P zCfM+)m>3-G@5iiwfL76-3y8I0zP_2K%FFu)2M1B&N>2}dn~=~air9DByWrkbv=$cr zW-u6#IhUKu`P>}h9olgM)(;$H&K!xq0;} zmZYZMsIIQY*49?+?Cdmh{`6@qiHp0);s~!9ZNqy7us5e`YOW0r52ISG#^mH=tgWrZ z;^Jb|YPER0Aph2D9v%mU*9&I6j%Do_vBJS&_ko0j>t$tS#t{4a`=gDG4Gs(p;PHkA zOo@)}p3bJ6%BYPfuy?umb~`)&d?Yt_vZA5_v$L}?FE0-(D=V?Sz8)`Kx@6?CPG<;E zsnQ=5_9+F>$CJI__W+)D`vJy`ZD(eN1y)w5NlU}S`T3K(Vq<%gZN12L2=UTp0B0!K&mQ7SXV z{VXv z>S`#owl-dS9bgBYJtX4^;?#e#IfgL1l?{0uT_METfDHM8dfVYJ(58)+?c}9jxoO5BWAeIx)5pQns^E+0Ukuh;h ztv1mAZ^%=ymh-Ri^1_23+|>mnbq&=)SAjx-yzfh#osAUHgyWqb0uWC>@)i$fL!<{nxj2az zWULo$M?Zl;A;wokgwx|B(xbTVAc`Ty+W|iR44{biW-+;(vhGgE-Txy2O3^8bsV1R< zm`6NJ*b_@c-e-~mXEE9>Oc7uvhRb}>at@-pm;H+(Tq2CyifPM^nN7Kjgot@UgtZ8t zy~v}fZOFnG2`AXNx!ikGwxJ|~!)7H?Vr{}8S}4N(h%js^o}-X^&-@MJSdp!hcmgc| O00002`C_)0KC{3#V>P6y5 z{***fN|TDJMNOkdidvOO7HMchA*}*}7Gf?oHpW-*jkUcO@9yl*<#ae&W!3d!3;Ig0 z&S=gYeb4#6Z_dsNDJA73gxC(OXK{5&DgVxWN&%DvUaM(Z)C2pT<2W5GBJbHh0G$Pp zUhYv^>8=kvz3Hc~@7wwFCpNBm^5Vsd3=R!3H0XJ#;K4yPdiU|>+5P0^XFhm!=WA=5 z!q0i|5$;h&3BZQ-Xm(dsWsa*MNl#A?;c%F{DV0iLObygI-2-(?v~(&$`FtMRwyCYHr6N8>qC&%Vxi1+d^%O{OfySWV z!oU88nVCbwMFIkd=q|b@@Cku&Te2)-AaKE`2t4(|&%XZBFS{NBHULqe8E8R?&w+Oi z|6qMzS%4!)jtE`XHK{oYVAZM>_%b?@5K>CdAOzHhg9HqnfKOvQE4V%}$-gJZ2yWWB zXY00Ydn&>qmevLc1$3$_b?U-?qE&u+Mw0EvKAQ>v`%3`kccl<`ivz5QR+6jKxa;R+-IR|+(t?knF)Iehi$%|z?!Rd1A$>X&3PNiY~x&HVlC&Di#hB191Y z_U_#)J32aCLkN5t_;n4#(9sasx{E7O0EVU!Ff{dyna!#oKA(?rvMh^4B0)_}jRFV+ z0_Z#-&H6t3$^q3ak1s>THFTx-nbY~tx0*}RSANJ4&{*(}tW zCJV`N95R`VDg(tvXJbo%O9R>GfukBlAwB6D7&`cU0$WN3VkxdB4UAP=c(DChzP#gQ z>bE>g&BI%{)<44O)2E5WVyfn+PMzZL;lpYyp0IHI_;C&$I>f<)2kGqWr2obsww>36 zr}+T70$^x1%ehI1)*T&e`{7Y4x4y#o13S3vJjP}D1exV~XnA};mZ;;{hn?zF93GwI zn@{cK%9Se$K-YCbp%9gomFhYYiC`E8u4+>EE^mPlOlBqVrLBDDz%NMY^(0a`gl>T* zNatK)ag$UkPj}wsa#ethty{R#+s9b8jhV9(7%G7LB4|rXi#oJ~5L8uFF_8psPL>4_ z8Vsi-yI%Y;;U&u$>3o-|{>vDF3R+t>uzb~{^iG7iF`ObcV=_9GVa&538kveEXn!n7 zLlHpj-rF^Gb#(v=D&?fT(Ux~KKLZ-HLC z+c&t_6KBlMkV@uBr!CJm2tXFk1n&(|0EMGof%%L)LYH^Xz_N%SZx7(Fj8M0-mV#K( zP(?gr(SPb~lJ)=Lp@&}}nf75>4z}Ye8$Jzbstiyf1*J@Ju3QF`8zMe@p#Y_-t@QCg z*w5K3XIcNqZbCtWtY_Pno?Q%G15k}7C<+M(i7aM^yJkRHsBxao56mz)Yq6u_EqZ37 z=z$c$pss@3mVwXEP`h+pBqfp*<`x0aG=WfNp8BU!y!u`j{kPJHYLn*r3bLj{&a^ST zantG=&YUP;0$}kH2=TvJC{=4ynAdl&XDDH#H>_sOy056tE{HQD(AL(rFo0aF2No#7 zD_J_{-WPyG0%G9|WX8Gyia|}uXhL!=<}#L& z=3u@q@$IS=jrR)RIF2$H3%`bz12b7k|BUBpmx(!PPNil4Y*zLU$7RpDE$!>8n_8bK z0xTYQdU~4C(NQMSL10eq#J$~ z14yUS>VHI6R~I)1N71TR5^3HH8t;??82xnExzRl($H!B$%YzvLCV_Dv4fp^Z2wHj5 za2=-{fcgNLn3zyM%iZ1G#L_x}hP70!-iGE6{oc}yx4p09bL9ZK{@CUG1c(6xfC+?w zN+7^INeTce#WOQAT)%#uOP4M&IzCO_*F;6bX8d)Lv#xaB8@_h#Pk;U0k8XRwZrQiM zo9GonTn98DPzam{bU*@5VNUn?gSJF4Gds(~__zu>Ff>Zau0pSFK{P!&W~CD!4xIbw zgG;C1?*rxllM)%smn;S&2ME9^fEZr@1VXWqTT@*9>@Q4b1NfuO7>(NzX7ndJ0| s3m^aXw#k*dH0@s?zwlm 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 RY-0cb002ovPDHLkV1oVh`pp0U literal 0 HcmV?d00001 diff --git a/images/mac/filesave.png b/images/mac/filesave.png new file mode 100644 index 0000000000000000000000000000000000000000..b41ecf5319863b3c5319579e19116f346802563b GIT binary patch literal 1206 zcmV;n1WEgeP)&5=xu1RdJ#IDvEdG#3 zHaCTnPtA0PfLqE+VPYbS+|emGrh`l-GZFyPPdo~Dysj3;K6>T=x3rysAOY8jkHDy!V7X1OV!!}8XFd%6MIs~jQ1$9!5 zC684vblv5b$90roQufLluWeb+J+m-_W$hJgV2{9qtn45cPc!se-reB4C7@O=? zSt*nu*e2O#AAJF6LZvoJVsqj}O+|wL3Pm)M5-y^j?GN-k$3p6HY%j6jAAryzwER*m zLs|wz+R}70^>H|C-W?nQS~*cHDGZ{aDOW;cNnsIwkl0J?_X8jj-vZu53TIz?{%{+e zcMXH`+@8}HmVc#PDfV&nWk3k!TnGclk5AD8QzI!vY^zk-RdzcObTA-b(Ec|J0oQTx z^MzH6AMsRuxR=J;y1KikY#D~3L<|C8@aher6t7*cVC%1H5*o<;^f~w~q8vk4bobM` zNtMxL=WKf*14_Y&(3*hGV1l(eK~iWF&sN~0=cP& z4-*2tdZvpj*2f=xfSsKk)M_=fTCD`2Mb$ADPE_t0G|#EnQ_=D1aEj&gFTPSXS=h%A z1~?B4OlEV*{}&e*v9z?L9B=`eot>pBId^Cl*p`TLppyZk6F{7V4rOlKip3(G<#bQT z<&+c(g(1~hc7(x67AC}yLZrhW)TtLYmyTIJ8Dom$zF+HFrP7x@cgdX$AVSC>4j4I@ zJlx;)?ufRmj1IX0mGD5>?uqx_8s9DWF5uIRiKQU z25$Ym-5NbgsDi-@lIk0gSG! UB0_&5sQ>@~07*qoM6N<$f^ZKn4*&oF literal 0 HcmV?d00001 diff --git a/images/mac/textbold.png b/images/mac/textbold.png new file mode 100644 index 0000000000000000000000000000000000000000..38400bd1f69dd4b49ffc29bb2f0eddd14ca39a34 GIT binary patch literal 1611 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 KMNUMnLSTZ+RFne% literal 0 HcmV?d00001 diff --git a/images/mac/textitalic.png b/images/mac/textitalic.png new file mode 100644 index 0000000000000000000000000000000000000000..0170ee26a6fc568e9b6490e4a45e04f4ff55a19e GIT binary patch literal 1164 zcmV;71atd|P)8>eW)l!AzGVM8#k=|EC4uK5YENM=>0xku0=q3%Tx@Cy=CPKKK1sA6|N30mSsXZy!Ca>jN5} z@ZcGS$#QE2LlE2rz5BYAo}Mll$j*K|%ZG;~fQZL?LqSQAOdFul0MPYJH;4ctijdG_ z5a~b(`Hfo!07M>23W&KczB~`e8_x_6C8wrdNy$o7u}}z)Kro07?K(Su>4*Gx7p`nl zYUZGg?Wzc=9^N~4?4`4#hsF{$6F`yxG!9=sR6)3Adm7^=0c_h{z*wD?ikr7E|LeX9p!`Qe zVeP4KSFcvH+yh7q@bIs-s^8}b3=O7Jp<2z&ze5H1Pq9G#@4tX-A{Eza)PCFo0f43J zf9+WWM&o)q!f!u|`adWGtSsjY%>SN5V5F-z$qNt|N&E^sblsUNiKxfZ@+X4Irqzh>Aw?C>se*5X~I8~7jLZNj*@*{BD zUO@ZJ6-0e@^8J@X;qYXrI~6f%?iI`!&wr`Ln7#Z+EHeNAQF?%ekr1Mh7@7R-EPzys zNMQ8U4<=rC^VDZ!Z=E?eG<P`TXFfSHJ*D@>`qd^VQnd=ezrG9QHJSSY3ZUEJ=g0fT zkBs-_mRAPPef`bB&Gp5TrIm#Z0I)p%8PY(gCfXOF5Rm204owR<;0UEc(d27P!)zAv z>vbwKP*hdwkH?iQ{H1)`U1(GcsNO9#DD)!I^av5}xeI=opS|HYaAtXF@pWvmAUI8_ z(XdUkdS?wBM?e9h6p%GVjie}d4j*n8Z(gq4Eg27b4mb$=_2TSh9Iqm(H;;%!qwt?K zO%DykBJ5W9ckTj*U`QP?kP1>pw(f&6t*at6Z~ogxz(J$Kqk#Y|vgv>H<;eCC@J4|V ewuk0+hta>;sLepRg`ge)0000=P)qhXCOuvAB1>1$~LJ*45g^Hl43wge}u?lK;3c7G(7uL^E5Eoro zL90--YNtA5+o_%DOxu}v?@f*&Sp>rMPN^99b8>IaBe^-hcTOUz%0ca^6AJ+Zpx8kv zWP9O@xpHtrR5ed>eDMZwjNv9D?{#!B!#aQA-27btM`_2-d@w(oGBLD$fDmHeVGMDMWL2|_QD!rE>$TGWX#s}PlC!gbz@_VO zXlCQ&mP>1bh_Gw}-~6m;@(`47*RpTpO!R@^eOm0-S2}th@F66hw(D4#!o^>eiIwpX z48&QA%JXpi(W8Y}d@=f@49>lJH+@2+_S0fis_ z1ZNGiY3#2HjdKw^!%u&Kk&poYKKfXr)DY&_D>a0*Ol5~443(_~pu-^$&H(QLHmN{2 z&0>}6J-a08bXeKbauYFzYj>x zgiT{m1<(kOu)WjatWEDBXTixtl8*+#H5t<2g=O0@om%=nXGsy*-Cgp;<5OOGc^E>m z0;tlq9anC^-d>9Um#+u*9s~}rH2iVbpgyPQtD8dTm5Gz+uXM|RApEka2}s{7Yug5A z!5aAOjsq$PpFIAy0HC}H90dfR+H&&#UeEVhv&0fe{Exzi#1R2+Ix(LipLo^VOaE0f5Hl^4d6q06r+j2;M6q zBq(?9ba+0tSy1QkLE7!iztm8o#@)Ix_Kr0oLJ#$bT!TX1M>z|$lMx8p1l}-&zADX(K}ZeVNJ(b&>r0=5Abk4sPv)y3z;fwv z&Jt7;JRt!Hh@=eZoJ0#66l3$aH3o!KF-0W78-c`#A!r6y12hdhck1*ogaUYkU7H{K>!d$NI)j&kTeFMkoic*J>|snr}p=#` zT8V&ZBHsvX?;8X~Ltt|!gQ^O*VqZ1uP6X8$a{oaFPf>2&Rb&Lh^Us`IP={bdb<+`1 zY{`Tp7nAC8QlNC@xw@E?Ojn?*E+zHFqz(ajus&4KXBEP;*efdOx2pZ4lLPz%BE0P^ TcPZ9h00000NkvXXu0mjf)&4_P literal 0 HcmV?d00001 diff --git a/images/mac/textleft.png b/images/mac/textleft.png new file mode 100644 index 0000000000000000000000000000000000000000..83a66d553556318edf017cbb0575eb767401d708 GIT binary patch literal 1235 zcmV;^1T6cBP)Z1U5Qg9C?isHQ7moNJguein{0qo|6CVP}oIv6dtu{dl;Q%rxkl?_DT!7q=5Qj)8 zND+`rferwbYuKRTN5k-R+*5?%J(qt7b?= zHA24$;&|oDv0$-51Bi!w55Y5iego?=6iko4x^ij!J^(l*d+y?gZ|9kQ;*<7;ggDJQQ!nwG)iE>FOg335L^+^nHP!m)KRdH;Rz^V++ zJb)J<__>32iZWf_M$f0_G{VK1>vuf}q}$$5AEU6{*d&zBh5HEu+$0ENp~)f4WzyISA@`)jo){G z`PUj-Z~g`VW0$c`!}^Z0*+CTa)eRfNTTv zm?`)!^U0f+f6i}NsRKn{79%3SMCF}YXJP*OOg+ISE z&y71Op^llp2H`?yCH(x8@w3w-)`h}qd(}>-yR*c~Cm;frO2Xm88q1>s0MyqS(k{p% zD4d1001JVcVTiCYBE0(M1OP5{L5Qm6K(W!qjR(NWl7R^0?mcK#BS@GFh=KrYO&uEV zwT*A?8x3H2WU+Y=%L52^_XMM2eocb^a2>ey#@cy>@X71Ia0)sD$RM=c5UR=n2&xWRyEUt#p7JvG0K(QkZq~O#SpN?0Vf!WN%Ijb-kq6i=WBCU|l%}40E zwbYJt2ZFY8B2su8&lr^kFTXzF*piV4Ve%^BeM|e+z8Af(w(ds{a-1#tYcpaVm0h&$0}{XPtcB=pgOOD zi`#MDR30C~G*?UG>6a#*PsOJ$eKuaL8^9XCD_Df8VtwhT8$sbni9zLc$cH}e3C_IM^J1dzBKiRO;1TJa)=~gW57z_sPmFFU%-B0rP!+h{X?w5) z-4CD|gLeK%KTr$vfq=|FC4BLf$#$NC0p%ur>UuHB-i)%h;QZwzLFuAw{$i3UovO|% xU-mGX%w%-tFmc*65gv7%l*(`PYlaU`_8+QxueyjM5HSD%002ovPDHLkV1fu7LRJ6( literal 0 HcmV?d00001 diff --git a/images/mac/textright.png b/images/mac/textright.png new file mode 100644 index 0000000000000000000000000000000000000000..e7c04645cf4db5caf5558a356d6969eeefb5c17c GIT binary patch literal 1406 zcmV-^1%djBP)#K_=t~%38c?zswBGxN0hto8X>(%-@OYLs&MeQvTjL6967!|V%)O|VyAq5IN{!vN*p=9|4X>W{$sWl*arhfcuVi#>`kcSw2lrN;Q!XnpAn0gX3yZEPlr_kqYMs=44K4TKPgBS#zy zApit?5Yp6Biz5J9Ny^|r%;lzMV3y;;WXjNBOe;0|YeFl5*#q!e2La_2NSn>=3`hsd zt?k?@Q&N?JHrTX?s1z|!E5@k!e2RepWIzfe#h8^M6k%hdb=$P1Q6C$vH>Nvq_0Mww z#tz_-Y4@t#sCw#9;mFmo62j?E?=ZgHx?}hHl|w=>ICRVy8TL4*{CY|m8O~>adn9B1 zazRA-^^|bOqKsM;@x$M+W@$iC4jnf}mUx^hLxal8+o~A2D!>&2zIf~H`uYo#o?7g< z-11;XUoFCbB=tm2$+CcRN*qJ873hl{W`+;ooZ!9ToX~7#%o&Vu%1i-m_PZhluXIR( zc7ZTdq`+pRqdf%`0$d5Yz9RaIu~x(ss8fI?MYMosF}6xj`XUV2JvLh3GgE-E6L_=@ zHthhRRJ?-L!-*aa7~j6Qr@rBqfjqB295Y6i3aR(}c2ZckLJ1yz8HY8?q1p5tKBa89 zO=z|PKm84BZxy0Q`0*I59uCAc<(F|-H9t_RDJp^O+xJ#7pcvom+gIN(dC{<7s8du8 zpFxsks49_DLNMZ5UM4SHN|-xT<8sr$z(oakk$^#(<|48r05Eq*dG>`8g!gaWGiBw} zyZ_jg>*;B@-V}tk>vA193p_YBTDR#AOs{@Zu=Te=*jE7RN`=T5ptaf{Y?k0GSH)db z5Ox#LkMS(O_P@XQO14iNSb@cz5?)oBK)2NgpE($t8e+>k5_ z_z)PJ9g(I6NIoYEI8_YjtHIOH-7ujPY~A z@K7L%9OLKV*7;xtNB<2hnZXEphKz-whGscp6d9Ke~R2I%QMB(Iwv21~o zW`VPpl!b#}!8mqf%-=8 z4Kv9fPjZS?bNxO9KuUmtYCcyTgpgOi5DXPavs{1(`3S^uX8}7pq@YuD+L&}+3tq>@ zq^dH;r6T1jHYUE*a?`fTcZG}gU9+@r&pU{46(J=7R-(KdUH=^5KeRqG?paFC4*&oF M07*qoM6N<$g4^GUS^xk5 literal 0 HcmV?d00001 diff --git a/images/mac/textunder.png b/images/mac/textunder.png new file mode 100644 index 0000000000000000000000000000000000000000..968bac5e90e3bc101959e8acc0f06fdaa79bbc73 GIT binary patch literal 1183 zcmV;Q1YrA#P)f&a`GGn%E-KNVXQ8%L@nVL-sQ%vvA(bS zArVvC?sQjL9Igtp!*vB*wK`m49p7`uUh(R4*K9*vZ??NexQz%ub2-;@JHHv&l%8Wd zoL||aYjL`p28c`!BFh~j>z$F&Um^HSW`2vm42bbHZBBQ`eWDsngrB+GZw5R%Qi50x zXzU}ZyG2yrOLQ==vIpgfV1d7N72{d7>j9B4a4eVm-2*;4YBXWyHC^KZ>4(pCploTN z8;s*ST||5hXcPMCpb-K(2pAxcCPAQmSf+pxOHkE;W#}PFl_1b6SHOS`c(sj4e;Wda zf){AMFH@ivGcRu@s_rC8ksx5ZCsRO&nP0Xc3s{Ej2ZI-|-jykE4I8l3N>tG*O~5=P zQ{W0_e!+w+U>TAn2sAil3jEVfbhd%01j~?gAb5fLL74)VTZoGOCAx@ZNR%LOeL$u_ zDN9Ul=h(RUIAYWrmh{B@J)L@m*2bn&eO0o{Kx1^&hoX!OW}0pEfj%Wk18I>5n| zaj7}B@~)9l+*e5z$UR==aA|6gg*u|_0(~E!83GiDPJ?h^-P7lWU<9`8Db)AnVfHy% zNNAmIJ|zVxp#JHSZHVLjNl(^E=<01pEPt9tMt{dLGh1tlO1J`Fqvo?oQe{7yt%Mt0KClI|kQ@c$R_>sW$g+NEw}Mcey8qqUF0 z&&=L4#(_`2I?{xgIH8}Ai6s0DJ_Ec6W`S40YagsmPKk(9S8m#QqBA3}y8q|$_Tk*> z-iHj|b6HH%FRdTO?A$*u{ImBE^AdOgOlOHn1%$z;3WIa-tKcp0E|?D%f<<%R|M<%# ztF~q>Ta!|-{EPJS%h#qAFZ(?8kMQViYURA8QD_qe-Ugihmj#JwzOvvg5F#|3`BBV{ zeX0$+ZCJybm~{)%*~+X~pV2lEVw>^y>Sm5t#b-8Qe^_`Q`O1PX0Zvya2a10}I)|kr z_Q4xAXaNJhWQ-2yLal(#KK`r|@9iFSeDx^ft6^}QU<97&5(Kmf!D6t)gT+EQ@B9Ul xH{oQjAy9%h!5lExgE@le8^WM0K0A=t@DY&122E81RKNfL002ovPDHLkV1kBi8^r(s literal 0 HcmV?d00001 diff --git a/images/mac/zoomin.png b/images/mac/zoomin.png new file mode 100644 index 0000000000000000000000000000000000000000..d46f5aff0d9810d21bc98be02776e843b2db7ee9 GIT binary patch literal 1696 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 IM6N<$f`v>W)&Kwi literal 0 HcmV?d00001 diff --git a/images/win/editcopy.png b/images/win/editcopy.png new file mode 100644 index 0000000000000000000000000000000000000000..1121b47d8b6b48f6cdf525851e7c0f502454ffe1 GIT binary patch literal 1325 zcmV+|1=9M7P)+{buk{F=nCJX#i^AQGtBfP^U9E=s!&EKn3+*9AyOC5y5_m4HQB2~pH` zRYX%2)m58>DgqW&sAx;EBU4=37{7w!SM2eOJs!`@eVlXtjqY3tTS5?(-{yaHb@l)B zec!pdSBVIB!=;~|e%P7xymRJ$5osgh_&4efy`JyCUMhx9Kk}ogMRI&{UihAR)H(VP z5`ixu00_b{5e5q-zVY>M|NPMBA38(Y-oZLchI61bL7|V$#mUE~-@NcRpbiK;|6O(N zfk%J%Y@t+fHjUDudrucpC_qYs_XMTNy?z?C^q*foM`|MO`|`smOlCq5Y$|AffYRZk z1m#2g^824X`-5laF9IMU{OT;%tWD%U5hqqQHn+rzNOfaXUit9}xpwhevNrpY)K=e+ z>e6d6H~pftTia5-{gJHQcvaqe>5RPb)EA!+5j21}j7vL!fJ7h$Fxhq7s2$=XbQ*apq!syTR7h7DJ;ak=_$L@YoY5qR0x4qnI>JyURTfv?kuG)9hFQ(Bzig%{x2T0Vw))rZsUuJTqc?}RB zayzmI$t>XKE_%9=#B-p^;FY>ji9xH7Anaju4o)p z9%uqB5oz!1paas%Pl^wu;12>?@7Wcg0d(Zx zhlqm$W(R^Xh!-Io1+@po6A*q0JdbvDCs~`i(%Gx6@WB#qEmxCq5xK#C!6ygR1K}{F z4Jh9Og<%N$=~Oqu`pG7hW&{7(U;2z<{$co^Ef>^0+f z`TE<9*>|q)G;S}O%acqlZ1T6YZ9d*=aWjvj1$6F8Kzppmtr|VSaptG4)aU>DhsN&h zS#$oPdv2-51h5X&^WrRbO)e0I{N~r^&-Nf3pIBgF>R(LU+~oac!W>Y~iu;rt_-#>2 jRe%!E1{&Go|C3Ju!Z7S4^>URZ00000NkvXXu0mjfFDrHZ literal 0 HcmV?d00001 diff --git a/images/win/editcut.png b/images/win/editcut.png new file mode 100644 index 0000000000000000000000000000000000000000..38e55f7420e267a891dcbf805d8ce51dc8b27a4b GIT binary patch literal 1896 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 kH>AflK=n!07*qoM6N<$f|Xs>*8l(j literal 0 HcmV?d00001 diff --git a/images/win/editredo.png b/images/win/editredo.png new file mode 100644 index 0000000000000000000000000000000000000000..9d679fe6fcbb334eafcc2dfd8af377bf050f0f76 GIT binary patch literal 1787 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 KMNUMnLSTY!`bcR2 literal 0 HcmV?d00001 diff --git a/images/win/exportpdf.png b/images/win/exportpdf.png new file mode 100644 index 0000000000000000000000000000000000000000..eef5132928be462a4aa01552c3ea09312dc6ee12 GIT binary patch literal 1059 zcmV+;1l;?HP)gY~PDBh=qfNApHBybnVEtGSgDgmlF?QjuZcTSCx@)?q z#F#d-ZdlkRWh17zfT(F3Eu|Hzduh@iDWYrQ7SlK}v8Lqm+6KFw>FFH@MBVx+g1 zcv~BX`}+YH>FcAkv{ZILFh+X-*6oncYgBv|P9_-{v66rMcN00L8)-CFe9ATud4`bV&eUS=4f;$M2o69kO{d#4* zI6O?_i4)`|CYZc*iBK|$D7CJ!2wG{h(p6Ts1vtyg+#eXIjHfagrZSnz_|Ca=)k#zd zkpisk0hZ6l<9G_kAHpYQM;W>rs=*G|U{y2-JOKct-s$E_YZ|RRfEa@ah^)Vj2x0_d z1o8U`HXTGM7(@(OdqM_-0mKMcf^rQ?DTL4# zfDJpkeRG`JkmjS~2k}{g5rZ)Xr8Gusl-4L$G5=_l+jADRsd^s#JwqfK#&y-!l`Q3A z(b}aZ7Nt2Uyp*ovhk+lt`qMQ;;LESR;Q5Yr9LK>aDVh>~#up5S4mC6L?*gu?a9veZ zXo1a{V2pU@iZR%BiMhFX?oHeW;NkK^3i&*a<4`JbWI z7-NXVVq~)`72~U`Hrk}tE7^5XuB!IHvMdX*IzITWe{}S(!Tn9CL?IR+5;QD4c6qkr z6hCxMXby#|ct$432_iJWNm=QppI>fM#DTq-r9;Nz1bQfU$rG&z`vo+t=(TaRecA@ dS$qB4@*jxcBlgPF?Z*HB002ovPDHLkV1i~?^WXpg literal 0 HcmV?d00001 diff --git a/images/win/filenew.png b/images/win/filenew.png new file mode 100644 index 0000000000000000000000000000000000000000..af5d1221412881e8727fe26930e5d0b5b0633aae GIT binary patch literal 768 zcmV+b1ONPqP)R27cmB`+Wkx8a_@65j^u^siVQp>_ zPwn8;)Y0kK7)l|lBE%wFmC-v$eL~)Yfy# z^Ob>gz1owlwa4nuL@ZOXxYpY|_=&3meg}r2l-hGYxpQ6xt+akF&AwE-Rj{%5WonE%=bMnbMjE6fFxi8F4En`*+~J=7Qars`&=Io zhuwOigX}AaoB2WbpNI;Z{V^LaLk(JDtl#%qy z0f>Sm3j{{aCY8&CEXN`MM|ZE8%R+uhohP>-UnM8m)ey5NDv83-9qxc}B#Vq3KoHKA zr9$dh3?K|tQxUGnzF?FXfupNPBJcqpK@|`Kj_Uz9$Li`v=>Q=x&=v?xE!YNlY%Pp2 z`(c97k@x;0y2r zSkx79I6z~aP_V?vz+;97?mOd?a$#bTcUmw3OasdW&9Ju0FEPu=Z0000NkluMLp6h%0z3=<;A2g_#%st8T@8|R6`^WPY zN+~|cy!}H_Tu~a@KD%tm_m%7DBeBj`kG8vQU){vgw8h}2SJgOx_Wy$a@FNi_DPZfe z`nBJwsC#Z*QE@GJoQ`tuDa(UlIM}E5i50 zBA$rOU%pfGhYOm1CieM!Vph$nt*?~TY^loi`LXV`5}%pm#t@`))-rF!=crz=2waH* z;&%?&t(Tk+00|(JQV1c$vDa8QD>{33#j+hQ&7QY9D6ARciDBIrh-i^WiBC;mWoDv} z!6`vsx{B(RFHl;wgmA7OUDr{{iz~czzq@99`0t%p{lXW}qVfl#^_OC$#}{5(QTOzo zk_Fo%L2DS5x`{{AAP_~_I{M52cSceSW=aW^ZDx7>212EvwFb$?inmyRDnA3U(o1R+5=&d7U!}&E2ZTB0{=@8pPcNL+3uBftDi44tm{OIN(koEl8E)va^lqVyXUj5-2)s2 zuHBC#0hkYqo2M57N?UsXwh`2YX_07*qo IM6N<$f-Pt`I{*Lx literal 0 HcmV?d00001 diff --git a/images/win/fileprint.png b/images/win/fileprint.png new file mode 100644 index 0000000000000000000000000000000000000000..ba7c02dc18d3145ffc2565afd7761cf8d3bbea99 GIT binary patch literal 1456 zcmV;h1yA~kP)b-8&)Yht(3npj! zhVZz-1RFN&M_Jjs*iyCsr1Br})rl5`9!vdS1b~`S#iy$JW0wVxgL2xnlvejVftS)` zTKUc6;s?zyOrQ~b4PSpzcWVZ4(}_)5%DYZrOq#!QQ`PI0w4^^aL2|-VFePLo-nasN z*IK{-{nt6Te1OXfI6O;fodf8H!d2_Ev=sjnEGa1o(b3Tl5_n}VWUm)KAEByLKX9faxzp;q-{ z>lTYhucS2H_>FX@YA5Z$@Dy-s3>f$m7#f)`>;2jfo|YtOx5wjoB=}+neBJL?ffbTv zfBCMO^w=tAkqc_N@rAcvg)IH?>4}DuF+}ni$veda50xlz zt)=B6k$96%pJo?^z%^$>&$TW{BVO2LH-dO3l7yfjEpFY8fW?x5LqQUtv$GSD+YMuEJR-uvpwVhzFlgX$`>|^E zYT=ym@o{8iWMoD}L`)w#bf|zJuiZyLz(v{F*tvNb6ir(H{*zI;Y z9>eg^5T>j%h>M9sFx0ezpyPT40fGFLmzP(>a-2DHMgV4IWg#UcMF21vcf&dl5fBrz zG=bHeW$;rtmDJc;eGYPwgH7zbKMpsuC1_lPi z@L49UR*NulRBmoAmM>q9=*Va|Jr1axufdtDLX&dtewzjd2S>6L9I>&nsHv&J;NT#- zySvfQ&>$+0i;EL!GMT`|Fahh&UG(()f>RBr@KQ+y;*yQ9OE&*P2Z|sd879u3KaVwQ z)+{oor>6@bzSi8_LNaL(85t?&Fg-nqt5>fIx!k-*$N*KZR3b4kQMhl}GK-Ps6CzB* zn~Z%;>pIfBv97Kzk%t}FfNaML7cK~Cbh;26Ir0e&+$Dycl9Gyqghb@$=cA&cf|Y<@ z@gpxc&)(P9_dG$|6d*jrdnBtZDk@T1T3QxAlQa*dz5Sxn)^#{D?mf0*?u}E%yICkwE#w=FOWGvZK<`(V-kXctBaZ_E}}e zj#}mD(JPA0HV@p`*r<>h=zE7BDc_+q-}kl)5Cpb=AlNAs>*>{SgEkw#4y}~mQNCv~ zrMGY2{-#1Zm|q8tl+_CrKNyc9V3*tznNMq!WhGU zDb0?ir%%5E<_$1MjY0D7B#lW{;<)?El`Cg|1R~9@%$x6h^uLpO_>ug@xmmgJ*No_P znnEHG0)+hmDMa6YiFRG4o_LlgUp&G194;$ z#|Q7e%Hu~Tky2s+BT^*7)&c<-q*B=0DRAb}Cf_b=^dCQH;0Q1UG+z@p-S0s>z(fLJdaXofa#Y{a{XE!DHR|93_w4?hG<8kq+lom3=aj}y`daH}yY*TMGX*PU}a?k^Z$mMe=dBBKr3MP(B@#**TcTpzBa|A=h93v%QS-kjptJB{4u^z@&y0LCI4T6TSa45CS|$;yRAqEsIM__GKF%A16&yfb3{?Ev3O= zWp`NK(`0awX_vDHsHDgM8ZYP2344@ECC0|a7#$t8fc=zn6g_`~Gzu^#jRElxKudw6 z9$4;tmaREZLZad}%d_8@%6e3-*Khp}bb(|KKnidjfs}wT93TtVTG{6kY+YmJ^6l=8 z>lZ#>U;q0&umyDY?jo%iDv^z46gTJE4_y{w-(;l(uB)>!J7T{u)|M^Y%M$(Q0;0yWQjJ)lC|WuBldAVWm>@ zYqi>@@7LCS|K4h~T3%gTynM%)v;o`!%0SCx>I0b8{Dmvcx$`r{^6IAfuzWTu7V=>n zht*cAvEloba;37qRxV#(t5)yUfG*GhflRd$wsDcfR`M{f{>xbi>|uW%=st z#`gB=U1QP^==3?TwFS`Yb4+F%ysJLI!or#FfIoo|Kmay)=NJKTf0)V094!6;(N7PE TmU#bB00000NkvXXu0mjf&~!wG literal 0 HcmV?d00001 diff --git a/images/win/textbold.png b/images/win/textbold.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbc7138b90d84b6d11e56227d4327ca4cef4d76 GIT binary patch literal 1134 zcmV-!1d;oRP)ua>XPW*|HpIlFET8~IOVRLqtUK*+x_A8?)}|$3&MkQt3Td*_U!w4KCjQu=c@pq z_&+t_W#xwb2~^K*NJG6x&6pNIqrlyVw5IES0z%iu0OKfdl^XaBF#Qe;{oy<)h8qiR)|Y-y+S=ISM|^|U zo?jTKJm&vWv^FVEGWQGv9X#v#2{_qc7=8BDohkzEbqf%5VX$=d2QS7Q)S5bO08Iq6 zn}O_;vSnf5>qR^lQO;Q&`DtbCWvji##0&k1 z!I8Oi@Q|=s5tWjx))__{uL1Q8;?mE+hPZsgTyOtXRO*Lqbw(#Zf5UNed1T^6o(E8OO$*pTKoe7!`UtrSWS;m3z;k63qir!e&&0E! zs(WNnP(%gK7kiXJY`WG|$Mh?EfU~_oT8V6N&HpF4lKFI})n3i)Y6v*qFgWJ7Vq>G% ztVg!e`D~ARu$_P!reAh}6VeIj23Q78OBb8j&gs#yEN8ys=t_fQ%ho1#E)H2=Oy`eN z_jm+|IiNLF8Gw>@ptJ)hsvowcYh+8t38&8X*&I^86Y@>J<7Rx0WDW_BPkr+FcfC9U zY$M<_>tEDL0JGR%EL*&nzFe{Bx$pwfi;(b-n^Q{(Vi2b;u~f`R1Q4v;bAVagJuP4> z0pezg~iE>3IoIEJXkcm7k0o`Wo*#0Q2-Cu)+NL%=P0< zr&l{UmK!{yfwM)gg@mQpb zjG;9p@egwZyjZ2cqM1sJH#_{XXeK;mCpQ$?3zBoX!6csY$1%F#_9so0C-pA*%T+H(sFgzgyvDH&-!>?z=!=HTR zrHfsT)Lb=>D*@6A%SBc}!DU8K+yhS_m z)2{yt^o%<6_KO3=b(?JLd`I-@asv1Yj%Zh0nq=pJ3s?6frmI!D@d=FyVA5HDXqFz{4kvN3ZyOC)U~ttKrM4497U zT&BXP{S2r-0v%?cl5Q( zRa`21(KlAF2WopLA}Vs~-MS%PahQCjzIO$XTh?N-)%F5Ux~Rxh=va!(-P4El|H_2` zv^DhGC(C)Dq7$g;9-jz_y{IAcP|}il0oZ^^GZe;W6wgDo15nHvtbq|H>dD-Ht^zv) zklw1|EeeXJs2O1I?6ZGp!lRiMn;-z0uV?ueaI`I3f%__24-`|1Twz@6C%HlZZ1n&(j5wMpb_JkorKQHyKpj)110GZM zr5!+})^UxU6*d~IyANMuyJ(r(v_F%~gI!v7Y=Mzhu}Pgp-fYn3ngyq}>3sADF*owLD2&Ff00000NkvXX Hu0mjfNaS)2 literal 0 HcmV?d00001 diff --git a/images/win/textjustify.png b/images/win/textjustify.png new file mode 100644 index 0000000000000000000000000000000000000000..9de0c8808502f5c30ed02ff038e0325464ee0fa1 GIT binary patch literal 695 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 + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + cMainWindow w; + w.show(); + + return a.exec(); +} diff --git a/qtStoryWriter.pro b/qtStoryWriter.pro new file mode 100644 index 0000000..8e013b9 --- /dev/null +++ b/qtStoryWriter.pro @@ -0,0 +1,49 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-03-26T11:30:37 +# +#------------------------------------------------- + +QT += core gui xml + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = qtStoryWriter +TEMPLATE = app +qtHaveModule(printsupport): QT += printsupport + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + cmainwindow.cpp \ + cdocumentreader.cpp \ + cdocumentwriter.cpp \ + ctextdocument.cpp \ + common.cpp + +HEADERS += \ + cmainwindow.h \ + cdocumentreader.h \ + cdocumentwriter.h \ + ctextdocument.h \ + common.h + +FORMS += \ + cmainwindow.ui + +DISTFILES += \ + example.html + +RESOURCES += \ + qtstorywriter.qrc diff --git a/qtstorywriter.qrc b/qtstorywriter.qrc new file mode 100644 index 0000000..def5add --- /dev/null +++ b/qtstorywriter.qrc @@ -0,0 +1,44 @@ + + + example.html + images/logo32.png + images/mac/editcopy.png + images/mac/editcut.png + images/mac/editpaste.png + images/mac/editredo.png + images/mac/editundo.png + images/mac/exportpdf.png + images/mac/filenew.png + images/mac/fileopen.png + images/mac/fileprint.png + images/mac/filesave.png + images/mac/textbold.png + images/mac/textcenter.png + images/mac/textitalic.png + images/mac/textjustify.png + images/mac/textleft.png + images/mac/textright.png + images/mac/textunder.png + images/mac/zoomin.png + images/mac/zoomout.png + images/win/editcopy.png + images/win/editcut.png + images/win/editpaste.png + images/win/editredo.png + images/win/editundo.png + images/win/exportpdf.png + images/win/filenew.png + images/win/fileopen.png + images/win/fileprint.png + images/win/filesave.png + images/win/textbold.png + images/win/textcenter.png + images/win/textitalic.png + images/win/textjustify.png + images/win/textleft.png + images/win/textright.png + images/win/textunder.png + images/win/zoomin.png + images/win/zoomout.png + +