diff options
Diffstat (limited to 'sw/source/filter/ww8/docxtablestyleexport.cxx')
-rw-r--r-- | sw/source/filter/ww8/docxtablestyleexport.cxx | 736 |
1 files changed, 736 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/docxtablestyleexport.cxx b/sw/source/filter/ww8/docxtablestyleexport.cxx new file mode 100644 index 0000000000..46a052e0c7 --- /dev/null +++ b/sw/source/filter/ww8/docxtablestyleexport.cxx @@ -0,0 +1,736 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "docxtablestyleexport.hxx" +#include "docxhelper.hxx" +#include <doc.hxx> +#include <docsh.hxx> +#include <oox/token/tokens.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <sax/fastattribs.hxx> + +#include <optional> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XModel.hpp> + +using namespace com::sun::star; +using namespace oox; + +/// Methods in this class handle values in a table style. +struct DocxTableStyleExport::Impl +{ +private: + SwDoc& m_rDoc; + sax_fastparser::FSHelperPtr m_pSerializer; + +public: + Impl(SwDoc& rDoc) + : m_rDoc(rDoc) + { + } + + void TableStyle(const uno::Sequence<beans::PropertyValue>& rStyle); + + void setSerializer(sax_fastparser::FSHelperPtr pSerializer) + { + m_pSerializer = std::move(pSerializer); + } + + const sax_fastparser::FSHelperPtr& getSerializer() const { return m_pSerializer; } + + SwDoc& getDoc() const { return m_rDoc; } + + /// Handles a boolean value. + void handleBoolean(std::u16string_view aValue, sal_Int32 nToken); + + /// Export of w:pPr. + void tableStylePPr(const uno::Sequence<beans::PropertyValue>& rPPr); + /// Export of w:tblStylePr. + void tableStyleTableStylePr(const uno::Sequence<beans::PropertyValue>& rTableStylePr); + /// Export of w:rPr. + void tableStyleRPr(const uno::Sequence<beans::PropertyValue>& rRPr); + /// Export of w:rFonts. + void tableStyleRRFonts(const uno::Sequence<beans::PropertyValue>& rRFonts); + /// Export of w:lang. + void tableStyleRLang(const uno::Sequence<beans::PropertyValue>& rLang); + /// Export of w:ind in a pPr. + void tableStylePInd(const uno::Sequence<beans::PropertyValue>& rInd); + /// Export of w:spacing. + void tableStylePSpacing(const uno::Sequence<beans::PropertyValue>& rSpacing); + /// Export of w:tblPr. + void tableStyleTablePr(const uno::Sequence<beans::PropertyValue>& rTablePr); + /// Export of w:trPr. + void tableStyleTrPr(const uno::Sequence<beans::PropertyValue>& rTrPr); + /// Export of w:tcPr. + void tableStyleTcPr(const uno::Sequence<beans::PropertyValue>& rTcPr); + /// Export of w:tcBorders (and w:tblBorders). + void tableStyleTcBorders(const uno::Sequence<beans::PropertyValue>& rTcBorders, + sal_Int32 nToken = XML_tcBorders); + /// Export of w:tblInd. + void tableStyleTableInd(const uno::Sequence<beans::PropertyValue>& rTableInd); + /// Export of w:tblCellMar (and w:tcMar). + void tableStyleTableCellMar(const uno::Sequence<beans::PropertyValue>& rTableCellMar, + sal_Int32 nType = XML_tblCellMar); + /// Export of a given table cell border type. + void tableStyleTcBorder(sal_Int32 nToken, const uno::Sequence<beans::PropertyValue>& rTcBorder); + /// Export of w:shd. + void tableStyleShd(const uno::Sequence<beans::PropertyValue>& rShd); + /// Export of w:color. + void tableStyleRColor(const uno::Sequence<beans::PropertyValue>& rColor); +}; + +void DocxTableStyleExport::CnfStyle(const uno::Sequence<beans::PropertyValue>& rAttributeList) +{ + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + + for (const auto& rAttribute : rAttributeList) + { + if (rAttribute.Name == "val") + pAttributeList->add(FSNS(XML_w, XML_val), rAttribute.Value.get<OUString>()); + else + { + static DocxStringTokenMap const aTokens[] + = { { "firstRow", XML_firstRow }, + { "lastRow", XML_lastRow }, + { "firstColumn", XML_firstColumn }, + { "lastColumn", XML_lastColumn }, + { "oddVBand", XML_oddVBand }, + { "evenVBand", XML_evenVBand }, + { "oddHBand", XML_oddHBand }, + { "evenHBand", XML_evenHBand }, + { "firstRowFirstColumn", XML_firstRowFirstColumn }, + { "firstRowLastColumn", XML_firstRowLastColumn }, + { "lastRowFirstColumn", XML_lastRowFirstColumn }, + { "lastRowLastColumn", XML_lastRowLastColumn }, + { nullptr, 0 } }; + + if (sal_Int32 nToken = DocxStringGetToken(aTokens, rAttribute.Name)) + pAttributeList->add(FSNS(XML_w, nToken), rAttribute.Value.get<OUString>()); + } + } + + m_pImpl->getSerializer()->singleElementNS(XML_w, XML_cnfStyle, pAttributeList); +} + +void DocxTableStyleExport::TableStyles(sal_Int32 nCountStylesToWrite) +{ + // Do we have table styles from InteropGrabBag available? + uno::Reference<beans::XPropertySet> xPropertySet( + m_pImpl->getDoc().GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW); + uno::Sequence<beans::PropertyValue> aInteropGrabBag; + xPropertySet->getPropertyValue("InteropGrabBag") >>= aInteropGrabBag; + uno::Sequence<beans::PropertyValue> aTableStyles; + auto pProp = std::find_if( + std::cbegin(aInteropGrabBag), std::cend(aInteropGrabBag), + [](const beans::PropertyValue& rProp) { return rProp.Name == "tableStyles"; }); + if (pProp != std::cend(aInteropGrabBag)) + pProp->Value >>= aTableStyles; + if (!aTableStyles.hasElements()) + return; + + if (nCountStylesToWrite > aTableStyles.getLength()) + nCountStylesToWrite = aTableStyles.getLength(); + + for (sal_Int32 i = 0; i < nCountStylesToWrite; ++i) + { + uno::Sequence<beans::PropertyValue> aTableStyle; + aTableStyles[i].Value >>= aTableStyle; + m_pImpl->TableStyle(aTableStyle); + } +} + +void DocxTableStyleExport::Impl::tableStyleTableCellMar( + const uno::Sequence<beans::PropertyValue>& rTableCellMar, sal_Int32 nType) +{ + static DocxStringTokenMap const aTableCellMarTokens[] + = { { "left", XML_left }, { "right", XML_right }, { "start", XML_start }, + { "end", XML_end }, { "top", XML_top }, { "bottom", XML_bottom }, + { nullptr, 0 } }; + + if (!rTableCellMar.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, nType); + for (const auto& rProp : rTableCellMar) + { + if (sal_Int32 nToken = DocxStringGetToken(aTableCellMarTokens, rProp.Name)) + { + comphelper::SequenceAsHashMap aMap( + rProp.Value.get<uno::Sequence<beans::PropertyValue>>()); + m_pSerializer->singleElementNS(XML_w, nToken, FSNS(XML_w, XML_w), + OString::number(aMap["w"].get<sal_Int32>()), + FSNS(XML_w, XML_type), aMap["type"].get<OUString>()); + } + } + m_pSerializer->endElementNS(XML_w, nType); +} + +void DocxTableStyleExport::Impl::tableStyleTcBorder( + sal_Int32 nToken, const uno::Sequence<beans::PropertyValue>& rTcBorder) +{ + static DocxStringTokenMap const aTcBorderTokens[] = { { "val", XML_val }, + { "sz", XML_sz }, + { "color", XML_color }, + { "space", XML_space }, + { "themeColor", XML_themeColor }, + { "themeTint", XML_themeTint }, + { nullptr, 0 } }; + + if (!rTcBorder.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rTcBorder) + if (sal_Int32 nAttrToken = DocxStringGetToken(aTcBorderTokens, rProp.Name)) + pAttributeList->add(FSNS(XML_w, nAttrToken), rProp.Value.get<OUString>()); + + m_pSerializer->singleElementNS(XML_w, nToken, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStyleTcBorders( + const uno::Sequence<beans::PropertyValue>& rTcBorders, sal_Int32 nToken) +{ + static DocxStringTokenMap const aTcBordersTokens[] = { { "left", XML_left }, + { "right", XML_right }, + { "start", XML_start }, + { "end", XML_end }, + { "top", XML_top }, + { "bottom", XML_bottom }, + { "insideH", XML_insideH }, + { "insideV", XML_insideV }, + { "tl2br", XML_tl2br }, + { "tr2bl", XML_tr2bl }, + { nullptr, 0 } }; + + if (!rTcBorders.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, nToken); + for (const auto& rTcBorder : rTcBorders) + if (sal_Int32 nSubToken = DocxStringGetToken(aTcBordersTokens, rTcBorder.Name)) + tableStyleTcBorder(nSubToken, + rTcBorder.Value.get<uno::Sequence<beans::PropertyValue>>()); + m_pSerializer->endElementNS(XML_w, nToken); +} + +void DocxTableStyleExport::Impl::tableStyleShd(const uno::Sequence<beans::PropertyValue>& rShd) +{ + if (!rShd.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rShd) + { + if (rProp.Name == "val") + pAttributeList->add(FSNS(XML_w, XML_val), rProp.Value.get<OUString>()); + else if (rProp.Name == "color") + pAttributeList->add(FSNS(XML_w, XML_color), rProp.Value.get<OUString>()); + else if (rProp.Name == "fill") + pAttributeList->add(FSNS(XML_w, XML_fill), rProp.Value.get<OUString>()); + else if (rProp.Name == "themeFill") + pAttributeList->add(FSNS(XML_w, XML_themeFill), rProp.Value.get<OUString>()); + else if (rProp.Name == "themeFillShade") + pAttributeList->add(FSNS(XML_w, XML_themeFillShade), rProp.Value.get<OUString>()); + else if (rProp.Name == "themeFillTint") + pAttributeList->add(FSNS(XML_w, XML_themeFillTint), rProp.Value.get<OUString>()); + } + m_pSerializer->singleElementNS(XML_w, XML_shd, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStyleRColor(const uno::Sequence<beans::PropertyValue>& rColor) +{ + if (!rColor.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rColor) + { + if (rProp.Name == "val") + pAttributeList->add(FSNS(XML_w, XML_val), rProp.Value.get<OUString>()); + else if (rProp.Name == "themeColor") + pAttributeList->add(FSNS(XML_w, XML_themeColor), rProp.Value.get<OUString>()); + else if (rProp.Name == "themeTint") + pAttributeList->add(FSNS(XML_w, XML_themeTint), rProp.Value.get<OUString>()); + else if (rProp.Name == "themeShade") + pAttributeList->add(FSNS(XML_w, XML_themeShade), rProp.Value.get<OUString>()); + } + m_pSerializer->singleElementNS(XML_w, XML_color, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStyleRLang(const uno::Sequence<beans::PropertyValue>& rLang) +{ + if (!rLang.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rLang) + { + if (rProp.Name == "eastAsia") + pAttributeList->add(FSNS(XML_w, XML_eastAsia), rProp.Value.get<OUString>()); + else if (rProp.Name == "val") + pAttributeList->add(FSNS(XML_w, XML_val), rProp.Value.get<OUString>()); + else if (rProp.Name == "bidi") + pAttributeList->add(FSNS(XML_w, XML_bidi), rProp.Value.get<OUString>()); + } + m_pSerializer->singleElementNS(XML_w, XML_lang, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStyleRRFonts( + const uno::Sequence<beans::PropertyValue>& rRFonts) +{ + if (!rRFonts.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rRFont : rRFonts) + { + if (rRFont.Name == "eastAsiaTheme") + pAttributeList->add(FSNS(XML_w, XML_eastAsiaTheme), rRFont.Value.get<OUString>()); + else if (rRFont.Name == "asciiTheme") + pAttributeList->add(FSNS(XML_w, XML_asciiTheme), rRFont.Value.get<OUString>()); + else if (rRFont.Name == "cstheme") + pAttributeList->add(FSNS(XML_w, XML_cstheme), rRFont.Value.get<OUString>()); + else if (rRFont.Name == "hAnsiTheme") + pAttributeList->add(FSNS(XML_w, XML_hAnsiTheme), rRFont.Value.get<OUString>()); + } + m_pSerializer->singleElementNS(XML_w, XML_rFonts, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStylePSpacing( + const uno::Sequence<beans::PropertyValue>& rSpacing) +{ + if (!rSpacing.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rSpacing) + { + if (rProp.Name == "after") + pAttributeList->add(FSNS(XML_w, XML_after), rProp.Value.get<OUString>()); + else if (rProp.Name == "before") + pAttributeList->add(FSNS(XML_w, XML_before), rProp.Value.get<OUString>()); + else if (rProp.Name == "line") + pAttributeList->add(FSNS(XML_w, XML_line), rProp.Value.get<OUString>()); + else if (rProp.Name == "lineRule") + pAttributeList->add(FSNS(XML_w, XML_lineRule), rProp.Value.get<OUString>()); + else if (rProp.Name == "beforeLines") + pAttributeList->add(FSNS(XML_w, XML_beforeLines), rProp.Value.get<OUString>()); + else if (rProp.Name == "ParaTopMarginBeforeAutoSpacing") + // Auto spacing will be available in grab bag only if it was set to true + pAttributeList->add(FSNS(XML_w, XML_beforeAutospacing), "1"); + else if (rProp.Name == "afterLines") + pAttributeList->add(FSNS(XML_w, XML_afterLines), rProp.Value.get<OUString>()); + else if (rProp.Name == "ParaBottomMarginAfterAutoSpacing") + // Auto spacing will be available in grab bag only if it was set to true + pAttributeList->add(FSNS(XML_w, XML_afterAutospacing), "1"); + } + m_pSerializer->singleElementNS(XML_w, XML_spacing, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStylePInd(const uno::Sequence<beans::PropertyValue>& rInd) +{ + if (!rInd.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rInd) + { + if (rProp.Name == "rightChars") + pAttributeList->add(FSNS(XML_w, XML_rightChars), rProp.Value.get<OUString>()); + else if (rProp.Name == "right") + pAttributeList->add(FSNS(XML_w, XML_right), rProp.Value.get<OUString>()); + } + m_pSerializer->singleElementNS(XML_w, XML_ind, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStyleTableInd( + const uno::Sequence<beans::PropertyValue>& rTableInd) +{ + if (!rTableInd.hasElements()) + return; + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + for (const auto& rProp : rTableInd) + { + if (rProp.Name == "w") + pAttributeList->add(FSNS(XML_w, XML_w), OString::number(rProp.Value.get<sal_Int32>())); + else if (rProp.Name == "type") + pAttributeList->add(FSNS(XML_w, XML_type), rProp.Value.get<OUString>()); + } + m_pSerializer->singleElementNS(XML_w, XML_tblInd, pAttributeList); +} + +void DocxTableStyleExport::Impl::handleBoolean(std::u16string_view aValue, sal_Int32 nToken) +{ + if (aValue.empty()) + return; + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + if (aValue != u"1") + pAttributeList->add(FSNS(XML_w, XML_val), aValue); + m_pSerializer->singleElementNS(XML_w, nToken, pAttributeList); +} + +void DocxTableStyleExport::Impl::tableStyleRPr(const uno::Sequence<beans::PropertyValue>& rRPr) +{ + if (!rRPr.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, XML_rPr); + + uno::Sequence<beans::PropertyValue> aRFonts; + uno::Sequence<beans::PropertyValue> aLang; + uno::Sequence<beans::PropertyValue> aColor; + uno::Sequence<beans::PropertyValue> aSpacingSequence; + bool bSequenceFlag = false; + OUString aB; + OUString aBCs; + OUString aI; + OUString aSz; + OUString aSzCs; + OUString aCaps; + OUString aSmallCaps; + OUString aSpacing; + for (const auto& rProp : rRPr) + { + if (rProp.Name == "rFonts") + aRFonts = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "lang") + aLang = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "b") + aB = rProp.Value.get<OUString>(); + else if (rProp.Name == "bCs") + aBCs = rProp.Value.get<OUString>(); + else if (rProp.Name == "i") + aI = rProp.Value.get<OUString>(); + else if (rProp.Name == "color") + aColor = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "sz") + aSz = rProp.Value.get<OUString>(); + else if (rProp.Name == "szCs") + aSzCs = rProp.Value.get<OUString>(); + else if (rProp.Name == "caps") + aCaps = rProp.Value.get<OUString>(); + else if (rProp.Name == "smallCaps") + aSmallCaps = rProp.Value.get<OUString>(); + else if (rProp.Name == "spacing") + { + if (rProp.Value.has<OUString>()) + { + aSpacing = rProp.Value.get<OUString>(); + } + else + { + aSpacingSequence = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + bSequenceFlag = true; // set the uno::Sequence flag. + } + } + } + tableStyleRRFonts(aRFonts); + tableStyleRLang(aLang); + handleBoolean(aB, XML_b); + handleBoolean(aBCs, XML_bCs); + handleBoolean(aI, XML_i); + handleBoolean(aCaps, XML_caps); + handleBoolean(aSmallCaps, XML_smallCaps); + tableStyleRColor(aColor); + if (bSequenceFlag) + { + m_pSerializer->singleElementNS(XML_w, XML_spacing, FSNS(XML_w, XML_val), + aSpacingSequence[0].Value.get<OUString>()); + } + if (!aSpacing.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_spacing, FSNS(XML_w, XML_val), aSpacing); + if (!aSz.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_sz, FSNS(XML_w, XML_val), aSz); + if (!aSzCs.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_szCs, FSNS(XML_w, XML_val), aSzCs); + + m_pSerializer->endElementNS(XML_w, XML_rPr); +} + +void DocxTableStyleExport::Impl::tableStylePPr(const uno::Sequence<beans::PropertyValue>& rPPr) +{ + if (!rPPr.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, XML_pPr); + + uno::Sequence<beans::PropertyValue> aSpacing; + uno::Sequence<beans::PropertyValue> aInd; + bool bWordWrap = false; + OUString aJc; + OUString aSnapToGrid; + for (const auto& rProp : rPPr) + { + if (rProp.Name == "spacing") + aSpacing = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "ind") + aInd = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "wordWrap") + bWordWrap = true; + else if (rProp.Name == "jc") + aJc = rProp.Value.get<OUString>(); + else if (rProp.Name == "snapToGrid") + aSnapToGrid = rProp.Value.get<OUString>(); + } + if (bWordWrap) + m_pSerializer->singleElementNS(XML_w, XML_wordWrap); + tableStylePInd(aInd); + handleBoolean(aSnapToGrid, XML_snapToGrid); + tableStylePSpacing(aSpacing); + if (!aJc.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_jc, FSNS(XML_w, XML_val), aJc); + + m_pSerializer->endElementNS(XML_w, XML_pPr); +} + +void DocxTableStyleExport::Impl::tableStyleTablePr( + const uno::Sequence<beans::PropertyValue>& rTablePr) +{ + if (!rTablePr.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, XML_tblPr); + + uno::Sequence<beans::PropertyValue> aTableInd; + uno::Sequence<beans::PropertyValue> aTableBorders; + uno::Sequence<beans::PropertyValue> aTableCellMar; + std::optional<sal_Int32> oTableStyleRowBandSize; + std::optional<sal_Int32> oTableStyleColBandSize; + for (const auto& rProp : rTablePr) + { + if (rProp.Name == "tblStyleRowBandSize") + oTableStyleRowBandSize = rProp.Value.get<sal_Int32>(); + else if (rProp.Name == "tblStyleColBandSize") + oTableStyleColBandSize = rProp.Value.get<sal_Int32>(); + else if (rProp.Name == "tblInd") + aTableInd = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tblBorders") + aTableBorders = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tblCellMar") + aTableCellMar = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + } + if (oTableStyleRowBandSize) + m_pSerializer->singleElementNS(XML_w, XML_tblStyleRowBandSize, FSNS(XML_w, XML_val), + OString::number(*oTableStyleRowBandSize)); + if (oTableStyleColBandSize) + m_pSerializer->singleElementNS(XML_w, XML_tblStyleColBandSize, FSNS(XML_w, XML_val), + OString::number(*oTableStyleColBandSize)); + tableStyleTableInd(aTableInd); + tableStyleTcBorders(aTableBorders, XML_tblBorders); + tableStyleTableCellMar(aTableCellMar); + + m_pSerializer->endElementNS(XML_w, XML_tblPr); +} + +void DocxTableStyleExport::Impl::tableStyleTrPr(const uno::Sequence<beans::PropertyValue>& rTrPr) +{ + if (!rTrPr.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, XML_trPr); + + for (const auto& rProp : rTrPr) + { + if (rProp.Name == "tblHeader") + m_pSerializer->singleElementNS(XML_w, XML_tblHeader); + } + + m_pSerializer->endElementNS(XML_w, XML_trPr); +} + +void DocxTableStyleExport::Impl::tableStyleTcPr(const uno::Sequence<beans::PropertyValue>& rTcPr) +{ + if (!rTcPr.hasElements()) + return; + + m_pSerializer->startElementNS(XML_w, XML_tcPr); + + uno::Sequence<beans::PropertyValue> aShd; + uno::Sequence<beans::PropertyValue> aTcBorders; + uno::Sequence<beans::PropertyValue> aTcMar; + OUString aVAlign; + for (const auto& rProp : rTcPr) + { + if (rProp.Name == "shd") + aShd = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tcBorders") + aTcBorders = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tcMar") + aTcMar = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "vAlign") + aVAlign = rProp.Value.get<OUString>(); + } + tableStyleTcBorders(aTcBorders); + tableStyleTableCellMar(aTcMar, XML_tcMar); + tableStyleShd(aShd); + if (!aVAlign.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_vAlign, FSNS(XML_w, XML_val), aVAlign); + + m_pSerializer->endElementNS(XML_w, XML_tcPr); +} + +void DocxTableStyleExport::Impl::tableStyleTableStylePr( + const uno::Sequence<beans::PropertyValue>& rTableStylePr) +{ + if (!rTableStylePr.hasElements()) + return; + + OUString aType; + uno::Sequence<beans::PropertyValue> aPPr; + uno::Sequence<beans::PropertyValue> aRPr; + uno::Sequence<beans::PropertyValue> aTablePr; + uno::Sequence<beans::PropertyValue> aTrPr; + uno::Sequence<beans::PropertyValue> aTcPr; + for (const auto& rProp : rTableStylePr) + { + if (rProp.Name == "type") + aType = rProp.Value.get<OUString>(); + else if (rProp.Name == "pPr") + aPPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "rPr") + aRPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tblPr") + aTablePr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "trPr") + aTrPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tcPr") + aTcPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + } + + m_pSerializer->startElementNS(XML_w, XML_tblStylePr, FSNS(XML_w, XML_type), aType); + + tableStylePPr(aPPr); + tableStyleRPr(aRPr); + if (aTablePr.hasElements()) + tableStyleTablePr(aTablePr); + else + { + // Even if we have an empty container, write it out, as Word does. + m_pSerializer->singleElementNS(XML_w, XML_tblPr); + } + tableStyleTrPr(aTrPr); + tableStyleTcPr(aTcPr); + + m_pSerializer->endElementNS(XML_w, XML_tblStylePr); +} + +void DocxTableStyleExport::Impl::TableStyle(const uno::Sequence<beans::PropertyValue>& rStyle) +{ + bool bDefault = false; + bool bCustomStyle = false; + bool bQFormat = false; + bool bSemiHidden = false; + bool bUnhideWhenUsed = false; + OUString aStyleId; + OUString aName; + OUString aBasedOn; + OUString aRsid; + OUString aUiPriority; + uno::Sequence<beans::PropertyValue> aPPr; + uno::Sequence<beans::PropertyValue> aRPr; + uno::Sequence<beans::PropertyValue> aTablePr; + uno::Sequence<beans::PropertyValue> aTcPr; + std::vector<uno::Sequence<beans::PropertyValue>> aTableStylePrs; + for (const auto& rProp : rStyle) + { + if (rProp.Name == "default") + bDefault = rProp.Value.get<bool>(); + else if (rProp.Name == "customStyle") + bCustomStyle = rProp.Value.get<bool>(); + else if (rProp.Name == "styleId") + aStyleId = rProp.Value.get<OUString>(); + else if (rProp.Name == "name") + aName = rProp.Value.get<OUString>(); + else if (rProp.Name == "basedOn") + aBasedOn = rProp.Value.get<OUString>(); + else if (rProp.Name == "uiPriority") + aUiPriority = rProp.Value.get<OUString>(); + else if (rProp.Name == "qFormat") + bQFormat = true; + else if (rProp.Name == "semiHidden") + bSemiHidden = true; + else if (rProp.Name == "unhideWhenUsed") + bUnhideWhenUsed = true; + else if (rProp.Name == "rsid") + aRsid = rProp.Value.get<OUString>(); + else if (rProp.Name == "pPr") + aPPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "rPr") + aRPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tblPr") + aTablePr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tcPr") + aTcPr = rProp.Value.get<uno::Sequence<beans::PropertyValue>>(); + else if (rProp.Name == "tblStylePr") + aTableStylePrs.push_back(rProp.Value.get<uno::Sequence<beans::PropertyValue>>()); + } + + rtl::Reference<sax_fastparser::FastAttributeList> pAttributeList + = sax_fastparser::FastSerializerHelper::createAttrList(); + pAttributeList->add(FSNS(XML_w, XML_type), "table"); + if (bDefault) + pAttributeList->add(FSNS(XML_w, XML_default), "1"); + if (bCustomStyle) + pAttributeList->add(FSNS(XML_w, XML_customStyle), "1"); + if (!aStyleId.isEmpty()) + pAttributeList->add(FSNS(XML_w, XML_styleId), aStyleId); + m_pSerializer->startElementNS(XML_w, XML_style, pAttributeList); + + m_pSerializer->singleElementNS(XML_w, XML_name, FSNS(XML_w, XML_val), aName); + if (!aBasedOn.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_basedOn, FSNS(XML_w, XML_val), aBasedOn); + if (!aUiPriority.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_uiPriority, FSNS(XML_w, XML_val), aUiPriority); + if (bSemiHidden) + m_pSerializer->singleElementNS(XML_w, XML_semiHidden); + if (bUnhideWhenUsed) + m_pSerializer->singleElementNS(XML_w, XML_unhideWhenUsed); + if (bQFormat) + m_pSerializer->singleElementNS(XML_w, XML_qFormat); + if (!aRsid.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_rsid, FSNS(XML_w, XML_val), aRsid); + + tableStylePPr(aPPr); + tableStyleRPr(aRPr); + tableStyleTablePr(aTablePr); + tableStyleTcPr(aTcPr); + for (const uno::Sequence<beans::PropertyValue>& i : std::as_const(aTableStylePrs)) + tableStyleTableStylePr(i); + + m_pSerializer->endElementNS(XML_w, XML_style); +} + +void DocxTableStyleExport::SetSerializer(const sax_fastparser::FSHelperPtr& pSerializer) +{ + m_pImpl->setSerializer(pSerializer); +} + +DocxTableStyleExport::DocxTableStyleExport(SwDoc& rDoc, + const sax_fastparser::FSHelperPtr& pSerializer) + : m_pImpl(std::make_unique<Impl>(rDoc)) +{ + m_pImpl->setSerializer(pSerializer); +} + +DocxTableStyleExport::~DocxTableStyleExport() = default; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |