sw/source/filter/xml/xmlexp.hxx | 5 + sw/source/filter/xml/xmlfmte.cxx | 12 ++- sw/source/filter/xml/xmliteme.cxx | 2 sw/source/filter/xml/xmltble.cxx | 149 +++++++++++++++++++------------------- sw/source/filter/xml/xmltexte.hxx | 12 +++ 5 files changed, 103 insertions(+), 77 deletions(-)
New commits: commit 8fcc188bc37dff0040dfca55f63a7836ef3ae686 Author: Michael Stahl <[email protected]> AuthorDate: Fri Jul 29 17:00:14 2022 +0200 Commit: Thorsten Behrens <[email protected]> CommitDate: Wed Aug 3 21:55:04 2022 +0200 tdf#145226 sw: ODF export: fix table-row/table-cell styles The SwFrameFormat for table lines and table boxes gets an auto-generated name in SwDoc::MakeTableBoxFormat()/MakeTableLineFormat(). The problem is that xmltble.cxx assumes that these SwFrameFormats never have a name, and sets names on them temporarily during exportTextAutoStyles(), then later reads them when exporting the table-rows and table-cells, then eventually resets them all to an empty name. One issue is that it assumes that a non-empty SwFrameFormat name indicates a style has been exported, but that isn't always the case, and the name may still be an auto-generated one. Another issue is that overwriting the names interferes with the use of the names in Undo operations. So store the name for the ODF styles in members of the filter classes instead of the core model. (regression from commit 083fe09958658de8c3da87a28e0f8ff7b3b8a5e9) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127548 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit 5a9fe1d80ea977c439dd10ee2056abe6b0cb4d07) tdf#145226 sw: ODF export: fix table-row/table-cell style display-name Missed this attribute in commit 5a9fe1d80ea977c439dd10ee2056abe6b0cb4d07 Change-Id: I9b17962decbf9f8ecd2a91551230cf0f012e7a9d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137765 Tested-by: Thorsten Behrens <[email protected]> Reviewed-by: Thorsten Behrens <[email protected]> diff --git a/sw/source/filter/xml/xmlexp.hxx b/sw/source/filter/xml/xmlexp.hxx index 22e6a42368a7..a5abc5baf15f 100644 --- a/sw/source/filter/xml/xmlexp.hxx +++ b/sw/source/filter/xml/xmlexp.hxx @@ -23,6 +23,8 @@ #include <xmloff/xmlexp.hxx> #include "xmlitmap.hxx" #include <xmloff/xmltoken.hxx> + +#include <optional> #include <vector> class SwDoc; @@ -73,7 +75,8 @@ class SwXMLExport : public SvXMLExport SwXMLTableInfo_Impl& rTableInfo, bool bTop=false ); - void ExportFormat( const SwFormat& rFormat, enum ::xmloff::token::XMLTokenEnum eClass ); + void ExportFormat(const SwFormat& rFormat, enum ::xmloff::token::XMLTokenEnum eClass, + ::std::optional<OUString> const oStyleName); void ExportTableFormat( const SwFrameFormat& rFormat, sal_uInt32 nAbsWidth ); void ExportTableColumnStyle( const SwXMLTableColumn_Impl& rCol ); diff --git a/sw/source/filter/xml/xmlfmte.cxx b/sw/source/filter/xml/xmlfmte.cxx index 209cdd5a3904..b7aa337eede3 100644 --- a/sw/source/filter/xml/xmlfmte.cxx +++ b/sw/source/filter/xml/xmlfmte.cxx @@ -46,7 +46,8 @@ using namespace ::com::sun::star::drawing; using namespace ::com::sun::star::lang; using namespace ::xmloff::token; -void SwXMLExport::ExportFormat( const SwFormat& rFormat, enum XMLTokenEnum eFamily ) +void SwXMLExport::ExportFormat(const SwFormat& rFormat, enum XMLTokenEnum eFamily, + ::std::optional<OUString> const oStyleName) { // <style:style ...> CheckAttrList(); @@ -57,11 +58,14 @@ void SwXMLExport::ExportFormat( const SwFormat& rFormat, enum XMLTokenEnum eFami return; OSL_ENSURE( eFamily != XML_TOKEN_INVALID, "family must be specified" ); // style:name="..." + assert(oStyleName || (eFamily != XML_TABLE_ROW && eFamily != XML_TABLE_CELL)); bool bEncoded = false; - AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, EncodeStyleName( - rFormat.GetName(), &bEncoded ) ); + OUString const name(oStyleName ? *oStyleName : rFormat.GetName()); + AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, EncodeStyleName(name, &bEncoded)); if( bEncoded ) - AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rFormat.GetName() ); + { + AddAttribute(XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, name); + } if( eFamily != XML_TOKEN_INVALID ) AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, eFamily ); diff --git a/sw/source/filter/xml/xmliteme.cxx b/sw/source/filter/xml/xmliteme.cxx index b307a5c10872..8972bd14a51e 100644 --- a/sw/source/filter/xml/xmliteme.cxx +++ b/sw/source/filter/xml/xmliteme.cxx @@ -219,7 +219,7 @@ void SwXMLExport::ExportTableFormat( const SwFrameFormat& rFormat, sal_uInt32 nA { static_cast<SwXMLTableItemMapper_Impl *>(m_pTableItemMapper.get()) ->SetAbsWidth( nAbsWidth ); - ExportFormat( rFormat, XML_TABLE ); + ExportFormat(rFormat, XML_TABLE, {}); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/xml/xmltble.cxx b/sw/source/filter/xml/xmltble.cxx index 6a4fa1c9902b..d840509ecdc0 100644 --- a/sw/source/filter/xml/xmltble.cxx +++ b/sw/source/filter/xml/xmltble.cxx @@ -179,13 +179,18 @@ class SwXMLTableFrameFormatsSort_Impl { private: SwXMLFrameFormats_Impl aFormatList; + SwXMLTextParagraphExport::FormatMap & m_rFormatMap; + public: - bool AddRow( SwFrameFormat& rFrameFormat, const OUString& rNamePrefix, sal_uInt32 nLine ); - bool AddCell( SwFrameFormat& rFrameFormat, const OUString& rNamePrefix, + SwXMLTableFrameFormatsSort_Impl(SwXMLTextParagraphExport::FormatMap & rFormatMap) + : m_rFormatMap(rFormatMap) + {} + ::std::optional<OUString> AddRow(SwFrameFormat& rFrameFormat, const OUString& rNamePrefix, sal_uInt32 nLine ); + ::std::optional<OUString> AddCell(SwFrameFormat& rFrameFormat, const OUString& rNamePrefix, sal_uInt32 nCol, sal_uInt32 nRow, bool bTop ); }; -bool SwXMLTableFrameFormatsSort_Impl::AddRow( SwFrameFormat& rFrameFormat, +::std::optional<OUString> SwXMLTableFrameFormatsSort_Impl::AddRow(SwFrameFormat& rFrameFormat, const OUString& rNamePrefix, sal_uInt32 nLine ) { @@ -206,10 +211,12 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( SwFrameFormat& rFrameFormat, // empty styles have not to be exported if( !pFrameSize && !pBrush && !pRowSplit ) - return false; + { + m_rFormatMap.emplace(&rFrameFormat, ::std::optional<OUString>()); // empty just to enable assert + return {}; + } // order is: -/brush, size/-, size/brush - bool bInsert = true; SwXMLFrameFormats_Impl::iterator i; for( i = aFormatList.begin(); i < aFormatList.end(); ++i ) { @@ -272,19 +279,19 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( SwFrameFormat& rFrameFormat, continue; // found! - rFrameFormat.SetName( pTestFormat->GetName() ); - bInsert = false; - break; + auto const oName(m_rFormatMap.find(pTestFormat)->second); + assert(oName); + m_rFormatMap.emplace(&rFrameFormat, oName); + return {}; } - if( bInsert ) { - rFrameFormat.SetName( rNamePrefix + "." + OUString::number(nLine+1) ); + OUString const name(rNamePrefix + "." + OUString::number(nLine+1)); + m_rFormatMap.emplace(&rFrameFormat, ::std::optional<OUString>(name)); if ( i != aFormatList.end() ) ++i; aFormatList.insert( i, &rFrameFormat ); + return ::std::optional<OUString>(name); } - - return bInsert; } static OUString lcl_xmltble_appendBoxPrefix(const OUString& rNamePrefix, @@ -301,7 +308,7 @@ static OUString lcl_xmltble_appendBoxPrefix(const OUString& rNamePrefix, + "." + OUString::number(nRow + 1); } -bool SwXMLTableFrameFormatsSort_Impl::AddCell( SwFrameFormat& rFrameFormat, +::std::optional<OUString> SwXMLTableFrameFormatsSort_Impl::AddCell(SwFrameFormat& rFrameFormat, const OUString& rNamePrefix, sal_uInt32 nCol, sal_uInt32 nRow, bool bTop ) { @@ -336,7 +343,10 @@ bool SwXMLTableFrameFormatsSort_Impl::AddCell( SwFrameFormat& rFrameFormat, // empty styles have not to be exported if( !pVertOrient && !pBrush && !pBox && !pNumFormat && !pFrameDir && !pAttCnt ) - return false; + { + m_rFormatMap.emplace(&rFrameFormat, ::std::optional<OUString>()); // empty just to enable assert + return {}; + } // order is: -/-/-/num, // -/-/box/-, -/-/box/num, @@ -344,7 +354,6 @@ bool SwXMLTableFrameFormatsSort_Impl::AddCell( SwFrameFormat& rFrameFormat, // vert/-/-/-, vert/-/-/num, vert/-/box/-, ver/-/box/num, // vert/brush/-/-, vert/brush/-/num, vert/brush/box/-, // vert/brush/box/num - bool bInsert = true; SwXMLFrameFormats_Impl::iterator i; for( i = aFormatList.begin(); i < aFormatList.end(); ++i ) { @@ -462,19 +471,19 @@ bool SwXMLTableFrameFormatsSort_Impl::AddCell( SwFrameFormat& rFrameFormat, continue; // found! - rFrameFormat.SetName( pTestFormat->GetName() ); - bInsert = false; - break; + auto const oName(m_rFormatMap.find(pTestFormat)->second); + assert(oName); + m_rFormatMap.emplace(&rFrameFormat, oName); + return {}; } - if( bInsert ) { - rFrameFormat.SetName( lcl_xmltble_appendBoxPrefix( rNamePrefix, nCol, nRow, bTop ) ); + OUString const name(lcl_xmltble_appendBoxPrefix(rNamePrefix, nCol, nRow, bTop)); + m_rFormatMap.emplace(&rFrameFormat, ::std::optional<OUString>(name)); if ( i != aFormatList.end() ) ++i; aFormatList.insert( i, &rFrameFormat ); + return ::std::optional<OUString>(name); } - - return bInsert; } class SwXMLTableInfo_Impl @@ -483,10 +492,21 @@ class SwXMLTableInfo_Impl Reference<XTextSection> m_xBaseSection; bool m_bBaseSectionValid; sal_uInt32 const m_nPrefix; + SwXMLTextParagraphExport::FormatMap const& m_rLineFormats; + SwXMLTextParagraphExport::FormatMap const& m_rBoxFormats; public: - inline SwXMLTableInfo_Impl( const SwTable *pTable, sal_uInt16 nPrefix ); + inline SwXMLTableInfo_Impl( const SwTable *pTable, sal_uInt16 nPrefix, + SwXMLTextParagraphExport::FormatMap const& rLineFormats, + SwXMLTextParagraphExport::FormatMap const& rBoxFormats) + : m_pTable(pTable) + , m_bBaseSectionValid(false) + , m_nPrefix(nPrefix) + , m_rLineFormats(rLineFormats) + , m_rBoxFormats(rBoxFormats) + { + } const SwTable *GetTable() const { return m_pTable; } const SwFrameFormat *GetTableFormat() const { return m_pTable->GetFrameFormat(); } @@ -496,15 +516,10 @@ public: inline void SetBaseSection( const Reference < XTextSection >& rBase ); /// The namespace (table or loext) that should be used for the elements. sal_uInt16 GetPrefix() const { return m_nPrefix; } + SwXMLTextParagraphExport::FormatMap const& GetLineFormats() const { return m_rLineFormats; } + SwXMLTextParagraphExport::FormatMap const& GetBoxFormats() const { return m_rBoxFormats; } }; -inline SwXMLTableInfo_Impl::SwXMLTableInfo_Impl(const SwTable *pTable, sal_uInt16 nPrefix) : - m_pTable(pTable), - m_bBaseSectionValid(false), - m_nPrefix(nPrefix) -{ -} - inline void SwXMLTableInfo_Impl::SetBaseSection( const Reference < XTextSection >& rBaseSection ) { @@ -638,8 +653,10 @@ void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines& rLines, SwTableLine *pLine = rLines[nLine]; SwFrameFormat *pFrameFormat = pLine->GetFrameFormat(); - if( rExpRows.AddRow( *pFrameFormat, rNamePrefix, nLine ) ) - ExportFormat( *pFrameFormat, XML_TABLE_ROW ); + if (auto oNew = rExpRows.AddRow(*pFrameFormat, rNamePrefix, nLine)) + { + ExportFormat(*pFrameFormat, XML_TABLE_ROW, oNew); + } const SwTableBoxes& rBoxes = pLine->GetTabBoxes(); const size_t nBoxes = rBoxes.size(); @@ -666,9 +683,11 @@ void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines& rLines, if( pBoxSttNd ) { SwFrameFormat *pFrameFormat2 = pBox->GetFrameFormat(); - if( rExpCells.AddCell( *pFrameFormat2, rNamePrefix, nOldCol, nLine, + if (auto oNew = rExpCells.AddCell(*pFrameFormat2, rNamePrefix, nOldCol, nLine, bTop) ) - ExportFormat( *pFrameFormat2, XML_TABLE_CELL ); + { + ExportFormat(*pFrameFormat2, XML_TABLE_CELL, oNew); + } Reference < XCell > xCell = SwXCell::CreateXCell( const_cast<SwFrameFormat *>(rTableInfo.GetTableFormat()), @@ -714,8 +733,13 @@ void SwXMLExport::ExportTableLinesAutoStyles( const SwTableLines& rLines, } } -void SwXMLExport::ExportTableAutoStyles( const SwTableNode& rTableNd ) +void SwXMLExport::ExportTableAutoStyles(const SwTableNode& rTableNd) { + auto & rFormats(static_cast<SwXMLTextParagraphExport *>(GetTextParagraphExport().get())->GetTableFormats()); + auto const it(rFormats.find(&rTableNd)); + assert(it != rFormats.end()); + SwXMLTextParagraphExport::FormatMap & rRowFormats(it->second.first); + SwXMLTextParagraphExport::FormatMap & rBoxFormats(it->second.second); const SwTable& rTable = rTableNd.GetTable(); const SwFrameFormat *pTableFormat = rTable.GetFrameFormat(); @@ -743,9 +767,9 @@ void SwXMLExport::ExportTableAutoStyles( const SwTableNode& rTableNd ) ExportTableFormat( *pTableFormat, nAbsWidth ); SwXMLTableColumnsSortByWidth_Impl aExpCols; - SwXMLTableFrameFormatsSort_Impl aExpRows; - SwXMLTableFrameFormatsSort_Impl aExpCells; - SwXMLTableInfo_Impl aTableInfo( &rTable, XML_NAMESPACE_TABLE ); + SwXMLTableFrameFormatsSort_Impl aExpRows(rRowFormats); + SwXMLTableFrameFormatsSort_Impl aExpCells(rBoxFormats); + SwXMLTableInfo_Impl aTableInfo(&rTable, XML_NAMESPACE_TABLE, rRowFormats, rBoxFormats); ExportTableLinesAutoStyles( rTable.GetTabLines(), nAbsWidth, nBaseWidth, pTableFormat->GetName(), aExpCols, aExpRows, aExpCells, aTableInfo, true); @@ -763,10 +787,12 @@ void SwXMLExport::ExportTableBox( const SwTableBox& rBox, const SwFrameFormat *pFrameFormat = rBox.GetFrameFormat(); if( pFrameFormat ) { - const OUString& sName = pFrameFormat->GetName(); - if( !sName.isEmpty() ) + auto const it(rTableInfo.GetBoxFormats().find(pFrameFormat)); + assert(it != rTableInfo.GetBoxFormats().end()); + if (it->second) { - AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(sName) ); + assert(!it->second->isEmpty()); + AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(*it->second)); } } } @@ -896,10 +922,12 @@ void SwXMLExport::ExportTableLine( const SwTableLine& rLine, const SwFrameFormat *pFrameFormat = rLine.GetFrameFormat(); if( pFrameFormat ) { - const OUString& sName = pFrameFormat->GetName(); - if( !sName.isEmpty() ) + auto const it(rTableInfo.GetLineFormats().find(pFrameFormat)); + assert(it != rTableInfo.GetLineFormats().end()); + if (it->second) { - AddAttribute( XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(sName) ); + assert(!it->second->isEmpty()); + AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, EncodeStyleName(*it->second)); } } @@ -1051,29 +1079,6 @@ void SwXMLExport::ExportTableLines( const SwTableLines& rLines, delete pLines; } -static void lcl_xmltble_ClearName_Line( SwTableLine* pLine ); - -static void lcl_xmltble_ClearName_Box( SwTableBox* pBox ) -{ - if( !pBox->GetSttNd() ) - { - for( SwTableLine* pLine : pBox->GetTabLines() ) - lcl_xmltble_ClearName_Line( pLine ); - } - else - { - SwFrameFormat *pFrameFormat = pBox->GetFrameFormat(); - if( pFrameFormat && !pFrameFormat->GetName().isEmpty() ) - pFrameFormat->SetName( OUString() ); - } -} - -void lcl_xmltble_ClearName_Line( SwTableLine* pLine ) -{ - for( SwTableBox* pBox : pLine->GetTabBoxes() ) - lcl_xmltble_ClearName_Box( pBox ); -} - void SwXMLExport::ExportTable( const SwTableNode& rTableNd ) { const SwTable& rTable = rTableNd.GetTable(); @@ -1132,15 +1137,16 @@ void SwXMLExport::ExportTable( const SwTableNode& rTableNd ) XML_DDE_SOURCE, true, false); } - SwXMLTableInfo_Impl aTableInfo( &rTable, nPrefix ); + auto const& rFormats(static_cast<SwXMLTextParagraphExport const*>(GetTextParagraphExport().get())->GetTableFormats()); + auto const it(rFormats.find(&rTableNd)); + assert(it != rFormats.end()); + SwXMLTableInfo_Impl aTableInfo(&rTable, nPrefix, it->second.first, it->second.second); ExportTableLines( rTable.GetTabLines(), aTableInfo, rTable.GetRowsToRepeat() ); - - for( SwTableLine *pLine : const_cast<SwTable &>(rTable).GetTabLines() ) - lcl_xmltble_ClearName_Line( pLine ); } } void SwXMLTextParagraphExport::exportTableAutoStyles() { + // note: maTableNodes is used here only to keep the iteration order as before for (const auto* pTableNode : maTableNodes) { static_cast<SwXMLExport&>(GetExport()).ExportTableAutoStyles(*pTableNode); @@ -1187,6 +1193,7 @@ void SwXMLTextParagraphExport::exportTable( && (bExportStyles || !pFormat->GetDoc()->IsInHeaderFooter(aIdx))) { maTableNodes.push_back(pTableNd); + m_TableFormats.emplace(pTableNd, ::std::make_pair(SwXMLTextParagraphExport::FormatMap(), SwXMLTextParagraphExport::FormatMap())); // Collect all tables inside cells of this table, too const auto aCellNames = pXTable->getCellNames(); for (const OUString& rCellName : aCellNames) diff --git a/sw/source/filter/xml/xmltexte.hxx b/sw/source/filter/xml/xmltexte.hxx index 4432e4ce0166..78e0271384c3 100644 --- a/sw/source/filter/xml/xmltexte.hxx +++ b/sw/source/filter/xml/xmltexte.hxx @@ -23,6 +23,9 @@ #include <xmloff/txtparae.hxx> #include <tools/globname.hxx> +#include <optional> +#include <unordered_map> + #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "vnd.sun.star.GraphicObject:" class SwXMLExport; @@ -41,6 +44,10 @@ class SwXMLTextParagraphExport : public XMLTextParagraphExport // Collected autostyles for use in exportTextAutoStyles std::vector<const SwTableNode*> maTableNodes; +public: + typedef ::std::unordered_map<SwFrameFormat const*, ::std::optional<OUString>> FormatMap; +private: + ::std::unordered_map<SwTableNode const*, ::std::pair<FormatMap, FormatMap>> m_TableFormats; static SwNoTextNode *GetNoTextNode( const css::uno::Reference < css::beans::XPropertySet >& rPropSet ); @@ -63,6 +70,11 @@ public: SwXMLExport& rExp, SvXMLAutoStylePoolP& rAutoStylePool ); virtual ~SwXMLTextParagraphExport() override; + + ::std::unordered_map<SwTableNode const*, ::std::pair<FormatMap, FormatMap>> const& + GetTableFormats() const { return m_TableFormats; } + ::std::unordered_map<SwTableNode const*, ::std::pair<FormatMap, FormatMap>> & + GetTableFormats() { return m_TableFormats; } }; #endif // INCLUDED_SW_SOURCE_FILTER_XML_XMLTEXTE_HXX
