diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2022-07-29 17:00:14 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2022-07-31 14:22:56 +0200 |
commit | 5a9fe1d80ea977c439dd10ee2056abe6b0cb4d07 (patch) | |
tree | 83db83e8e8ee3ace34c8cf00c88c31c1f942be06 | |
parent | 80cdfe4512a66ab58e0ae27c9fafad601c2f84b2 (diff) |
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)
Change-Id: I9b17962decbf9f8ecd2a91551230cf0f012e7a9d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127548
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r-- | sw/source/filter/xml/xmlexp.hxx | 4 | ||||
-rw-r--r-- | sw/source/filter/xml/xmlfmte.cxx | 6 | ||||
-rw-r--r-- | sw/source/filter/xml/xmliteme.cxx | 2 | ||||
-rw-r--r-- | sw/source/filter/xml/xmltble.cxx | 157 | ||||
-rw-r--r-- | sw/source/filter/xml/xmltexte.hxx | 12 |
5 files changed, 103 insertions, 78 deletions
diff --git a/sw/source/filter/xml/xmlexp.hxx b/sw/source/filter/xml/xmlexp.hxx index 53ab4431c645..86b919ac95a7 100644 --- a/sw/source/filter/xml/xmlexp.hxx +++ b/sw/source/filter/xml/xmlexp.hxx @@ -24,6 +24,7 @@ #include "xmlitmap.hxx" #include <xmloff/xmltoken.hxx> +#include <optional> #include <string_view> #include <vector> @@ -75,7 +76,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 60e650e48e72..f0a6aab224d3 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,9 +58,10 @@ 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 ) ); + oStyleName ? *oStyleName : rFormat.GetName(), &bEncoded) ); if( bEncoded ) AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME, rFormat.GetName() ); diff --git a/sw/source/filter/xml/xmliteme.cxx b/sw/source/filter/xml/xmliteme.cxx index 3989fb59b7cd..a8fbc712ac90 100644 --- a/sw/source/filter/xml/xmliteme.cxx +++ b/sw/source/filter/xml/xmliteme.cxx @@ -240,7 +240,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 0da423d4e450..81528e5b8c2f 100644 --- a/sw/source/filter/xml/xmltble.cxx +++ b/sw/source/filter/xml/xmltble.cxx @@ -185,13 +185,18 @@ class SwXMLTableFrameFormatsSort_Impl { private: SwXMLFrameFormats_Impl m_aFormatList; + SwXMLTextParagraphExport::FormatMap & m_rFormatMap; + public: - bool AddRow( SwFrameFormat& rFrameFormat, std::u16string_view rNamePrefix, sal_uInt32 nLine ); - bool AddCell( SwFrameFormat& rFrameFormat, std::u16string_view rNamePrefix, + SwXMLTableFrameFormatsSort_Impl(SwXMLTextParagraphExport::FormatMap & rFormatMap) + : m_rFormatMap(rFormatMap) + {} + ::std::optional<OUString> AddRow(SwFrameFormat& rFrameFormat, std::u16string_view rNamePrefix, sal_uInt32 nLine ); + ::std::optional<OUString> AddCell(SwFrameFormat& rFrameFormat, std::u16string_view rNamePrefix, sal_uInt32 nCol, sal_uInt32 nRow, bool bTop ); }; -bool SwXMLTableFrameFormatsSort_Impl::AddRow( SwFrameFormat& rFrameFormat, +::std::optional<OUString> SwXMLTableFrameFormatsSort_Impl::AddRow(SwFrameFormat& rFrameFormat, std::u16string_view rNamePrefix, sal_uInt32 nLine ) { @@ -204,10 +209,12 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( SwFrameFormat& rFrameFormat, // empty styles have not to be exported if( !pFrameSize && !pBrush && !pRowSplit && !pHasTextChangesOnly ) - 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 = m_aFormatList.begin(); i < m_aFormatList.end(); ++i ) { @@ -284,19 +291,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( OUString::Concat(rNamePrefix) + "." + OUString::number(nLine+1) ); + OUString const name(OUString::Concat(rNamePrefix) + "." + OUString::number(nLine+1)); + m_rFormatMap.emplace(&rFrameFormat, ::std::optional<OUString>(name)); if ( i != m_aFormatList.end() ) ++i; m_aFormatList.insert( i, &rFrameFormat ); + return ::std::optional<OUString>(name); } - - return bInsert; } static OUString lcl_xmltble_appendBoxPrefix(std::u16string_view rNamePrefix, @@ -313,7 +320,7 @@ static OUString lcl_xmltble_appendBoxPrefix(std::u16string_view rNamePrefix, + "." + OUString::number(nRow + 1); } -bool SwXMLTableFrameFormatsSort_Impl::AddCell( SwFrameFormat& rFrameFormat, +::std::optional<OUString> SwXMLTableFrameFormatsSort_Impl::AddCell(SwFrameFormat& rFrameFormat, std::u16string_view rNamePrefix, sal_uInt32 nCol, sal_uInt32 nRow, bool bTop ) { @@ -330,7 +337,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, @@ -338,7 +348,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 = m_aFormatList.begin(); i < m_aFormatList.end(); ++i ) { @@ -454,19 +463,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 != m_aFormatList.end() ) ++i; m_aFormatList.insert( i, &rFrameFormat ); + return ::std::optional<OUString>(name); } - - return bInsert; } class SwXMLTableInfo_Impl @@ -475,10 +484,21 @@ class SwXMLTableInfo_Impl Reference<XTextSection> m_xBaseSection; bool m_bBaseSectionValid; sal_uInt32 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(); } @@ -488,15 +508,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 ) { @@ -631,8 +646,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(); @@ -659,9 +676,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()), @@ -707,8 +726,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(); @@ -736,9 +760,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); @@ -756,10 +780,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)); } } } @@ -889,10 +915,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)); } } @@ -915,10 +943,12 @@ void SwXMLExport::ExportTableLine( const SwTableLine& rLine, const SwFrameFormat* pFormat = pBox->GetFrameFormat(); if (pFormat) { - const OUString& sName = pFormat->GetName(); - if (!sName.isEmpty()) + auto const it(rTableInfo.GetBoxFormats().find(pFormat)); + 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)); } } @@ -1055,29 +1085,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 ) { ::std::optional<sal_uInt16> oPrefix = XML_NAMESPACE_TABLE; @@ -1151,14 +1158,15 @@ void SwXMLExport::ExportTable( const SwTableNode& rTableNd ) XML_DDE_SOURCE, true, false); } - SwXMLTableInfo_Impl aTableInfo(&rTable, *oPrefix); + auto const& rFormats(static_cast<SwXMLTextParagraphExport const*>(GetTextParagraphExport().get())->GetTableFormats()); + auto const it(rFormats.find(&rTableNd)); + assert(it != rFormats.end()); + SwXMLTableInfo_Impl aTableInfo(&rTable, *oPrefix, 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); @@ -1199,6 +1207,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 e1041b7d666a..65f26040651c 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; @@ -39,6 +42,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 ); @@ -61,6 +68,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 |