diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-03-19 08:42:35 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-03-22 10:28:00 +0100 |
commit | 60e43bafe25a8352b1658b0e12c855a48db4d2a2 (patch) | |
tree | 6530269f419aff7d22eb50d28f153c4edda92b0a | |
parent | 630e1a35d189d07a9bade63279ad179bbcd7318e (diff) |
ODT import: handle style name of covered cells
Similar to commit 66ac8e60896f6306bed8fbb34606fd14474f19ce (sw: fix
unwanted long vertical border around vertically merged Word cell,
2021-03-04), but that one was for the DOCX import / rendering.
(cherry picked from commit 1001dbaef4dec2b51c25ed8343bab6910f1219e1)
Conflicts:
sw/qa/extras/odfimport/odfimport.cxx
sw/source/filter/xml/xmltbli.cxx
Change-Id: I394a4f062544a9774b9b40ec757cb37e72220561
-rw-r--r-- | sw/CppunitTest_sw_odfimport.mk | 2 | ||||
-rw-r--r-- | sw/qa/extras/odfimport/data/vmerge-cell-border.odt | bin | 0 -> 8996 bytes | |||
-rw-r--r-- | sw/qa/extras/odfimport/odfimport.cxx | 26 | ||||
-rw-r--r-- | sw/source/filter/xml/xmltbli.cxx | 71 | ||||
-rw-r--r-- | sw/source/filter/xml/xmltbli.hxx | 10 |
5 files changed, 107 insertions, 2 deletions
diff --git a/sw/CppunitTest_sw_odfimport.mk b/sw/CppunitTest_sw_odfimport.mk index bf227939f074..c3a3b535c8a4 100644 --- a/sw/CppunitTest_sw_odfimport.mk +++ b/sw/CppunitTest_sw_odfimport.mk @@ -17,11 +17,13 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sw_odfimport, \ $(eval $(call gb_CppunitTest_use_libraries,sw_odfimport, \ comphelper \ + editeng \ cppu \ cppuhelper \ sal \ svt \ sfx \ + svl \ sw \ test \ unotest \ diff --git a/sw/qa/extras/odfimport/data/vmerge-cell-border.odt b/sw/qa/extras/odfimport/data/vmerge-cell-border.odt Binary files differnew file mode 100644 index 000000000000..bf387bcb183e --- /dev/null +++ b/sw/qa/extras/odfimport/data/vmerge-cell-border.odt diff --git a/sw/qa/extras/odfimport/odfimport.cxx b/sw/qa/extras/odfimport/odfimport.cxx index 4df20d9e42a8..3aea453dfb2e 100644 --- a/sw/qa/extras/odfimport/odfimport.cxx +++ b/sw/qa/extras/odfimport/odfimport.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/PageNumberType.hpp> #include <com/sun/star/text/VertOrientation.hpp> +#include <editeng/boxitem.hxx> #include <IDocumentSettingAccess.hxx> #include <wrtsh.hxx> @@ -31,6 +32,7 @@ #include <edtwin.hxx> #include <olmenu.hxx> #include <cmdid.h> +#include <frmatr.hxx> typedef std::map<OUString, css::uno::Sequence< css::table::BorderLine> > AllBordersMap; typedef std::pair<OUString, css::uno::Sequence< css::table::BorderLine> > StringSequencePair; @@ -935,5 +937,29 @@ DECLARE_ODFIMPORT_TEST(testTdf113289, "tdf113289.odt") } +DECLARE_ODFIMPORT_TEST(testVerticallyMergedCellBorder, "vmerge-cell-border.odt") +{ + // Given a document with two cells, vertically merged, when loading the document: + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + + // Then make sure that the first cell has a right border while the second has no right border: + SwDocShell* pDocShell = pDoc->GetDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->Down(/*bSelect=*/false, /*nCount=*/1); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(/*bBlock=*/false); + SwStartNode* pA1 = pShellCursor->Start()->nNode.GetNode().StartOfSectionNode(); + const SwAttrSet& rA1Set = pA1->GetTableBox()->GetFrameFormat()->GetAttrSet(); + CPPUNIT_ASSERT(rA1Set.GetBox().GetRight()); + SwNodeIndex aA2(*pA1->EndOfSectionNode(), 1); + const SwAttrSet& rA2Set = aA2.GetNode().GetTableBox()->GetFrameFormat()->GetAttrSet(); + + // Without the accompanying fix in place, this test would have failed, as the A2 cell also had a + // right border, even if <table:covered-table-cell table:style-name="..."> explicitly disabled + // it. + CPPUNIT_ASSERT(!rA2Set.GetBox().GetRight()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx index 2207d929a9c4..ed73304a7e5d 100644 --- a/sw/source/filter/xml/xmltbli.cxx +++ b/sw/source/filter/xml/xmltbli.cxx @@ -218,6 +218,7 @@ public: sal_uInt32 GetRowSpan() const { return nRowSpan; } void SetRowSpan( sal_uInt32 nSet ) { nRowSpan = nSet; } sal_uInt32 GetColSpan() const { return nColSpan; } + void SetStyleName(const OUString& rStyleName) { aStyleName = rStyleName; } const OUString& GetStyleName() const { return aStyleName; } const OUString& GetFormula() const { return sFormula; } double GetValue() const { return dValue; } @@ -436,6 +437,47 @@ public: SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); } }; +/// Handles <table:covered-table-cell>. +class SwXMLCoveredTableCellContext : public SvXMLImportContext +{ +public: + SwXMLCoveredTableCellContext(SwXMLImport& rImport, + const Reference<xml::sax::XAttributeList>& xAttrList, + SwXMLTableContext& rTable); +}; + +SwXMLCoveredTableCellContext::SwXMLCoveredTableCellContext( + SwXMLImport& rImport, const Reference<xml::sax::XAttributeList>& xAttrList, + SwXMLTableContext& rTable) + : SvXMLImportContext(rImport) +{ + OUString aStyleName; + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + + OUString aLocalName; + const sal_uInt16 nPrefix = + GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, + &aLocalName ); + const OUString& rValue = xAttrList->getValueByIndex( i ); + const SvXMLTokenMap& rTokenMap = + rImport.GetTableCellAttrTokenMap(); + switch( rTokenMap.Get( nPrefix, aLocalName ) ) + { + case XML_TOK_TABLE_STYLE_NAME: + aStyleName = rValue; + break; + } + } + + if (!aStyleName.isEmpty()) + { + rTable.InsertCoveredCell(aStyleName); + } +} + SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList > & xAttrList, @@ -966,8 +1008,17 @@ SvXMLImportContextRef SwXMLTableRowContext_Impl::CreateChildContext( GetTable() ); } else if( IsXMLToken( rLocalName, XML_COVERED_TABLE_CELL ) ) - pContext = new SvXMLImportContext( GetImport(), nPrefix, - rLocalName ); + { + if (GetTable()->IsValid() && GetTable()->IsInsertCoveredCellPossible()) + { + pContext = new SwXMLCoveredTableCellContext(GetSwImport(), xAttrList, *GetTable()); + } + else + { + pContext = new SvXMLImportContext( GetImport(), nPrefix, + rLocalName ); + } + } } if( !pContext ) @@ -1262,6 +1313,7 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, m_nHeaderRows( 0 ), m_nCurRow( 0 ), m_nCurCol( 0 ), + m_nNonMergedCurCol( 0 ), m_nWidth( 0 ) { OUString aName; @@ -1402,6 +1454,7 @@ SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport, m_nHeaderRows( 0 ), m_nCurRow( 0 ), m_nCurCol( 0 ), + m_nNonMergedCurCol( 0 ), m_nWidth( 0 ) { } @@ -1634,10 +1687,23 @@ void SwXMLTableContext::InsertCell( const OUString& rStyleName, // Set current col to the next (free) column m_nCurCol = nColsReq; + m_nNonMergedCurCol = nColsReq; while( m_nCurCol<GetColumnCount() && GetCell(m_nCurRow,m_nCurCol)->IsUsed() ) m_nCurCol++; } +void SwXMLTableContext::InsertCoveredCell(const OUString& rStyleName) +{ + SwXMLTableCell_Impl* pCell = GetCell(m_nCurRow, m_nNonMergedCurCol); + ++m_nNonMergedCurCol; + if (!pCell) + { + return; + } + + pCell->SetStyleName(rStyleName); +} + void SwXMLTableContext::InsertRow( const OUString& rStyleName, const OUString& rDfltCellStyleName, bool bInHead, @@ -1669,6 +1735,7 @@ void SwXMLTableContext::InsertRow( const OUString& rStyleName, // We start at the first column ... m_nCurCol=0; + m_nNonMergedCurCol = 0; // ... but this cell may be occupied already. while( m_nCurCol<GetColumnCount() && GetCell(m_nCurRow,m_nCurCol)->IsUsed() ) diff --git a/sw/source/filter/xml/xmltbli.hxx b/sw/source/filter/xml/xmltbli.hxx index 157be580f67f..a2e39f0d2c47 100644 --- a/sw/source/filter/xml/xmltbli.hxx +++ b/sw/source/filter/xml/xmltbli.hxx @@ -90,6 +90,8 @@ class SwXMLTableContext : public XMLTextTableContext sal_uInt16 m_nHeaderRows; sal_uInt32 m_nCurRow; sal_uInt32 m_nCurCol; + /// Same as m_nCurCol, but not incremented multiple times for table cells with row span. + sal_uInt32 m_nNonMergedCurCol; sal_Int32 m_nWidth; // The maximum table width (i.e., maximum value for m_nWidth); must be >= MINLAY and must also @@ -156,6 +158,10 @@ public: inline sal_uInt32 GetColumnCount() const; bool IsInsertCellPossible() const { return m_nCurCol < GetColumnCount(); } + + /// Determines if it's OK to insert a covered cell, given the total column count. + bool IsInsertCoveredCellPossible() const { return m_nNonMergedCurCol < GetColumnCount(); } + bool IsInsertColPossible() const { return m_nCurCol < USHRT_MAX; } bool IsInsertRowPossible() const { return m_nCurRow < USHRT_MAX; } bool IsValid() const { return m_pTableNode != nullptr; } @@ -170,6 +176,10 @@ public: bool bHasValue = false, double fValue = 0.0, OUString const*const pStringValue = nullptr); + + /// Sets formatting of an already created covered cell. + void InsertCoveredCell(const OUString& rStyleName); + void InsertRow( const OUString& rStyleName, const OUString& rDfltCellStyleName, bool bInHead, |