diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-05-29 17:26:57 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-05-30 08:43:22 +0200 |
commit | 6bb241ccc61c6904efec95978fa17e33c0eb1df3 (patch) | |
tree | d1d6b92a09402765e2581b8bf5be81b3aac52f4d | |
parent | 18d0d8541432782e9bf761992a8bda5d29ee6564 (diff) |
ODT export: fix lost <text:user-field-decl> for fields in tables in headers
The problem was that XMLTextFieldExport::ExportFieldAutoStyle() assumed
that the text of a field anchor is always the toplevel XText, which is
true in case of body vs header text, but false in case header text vs
text-in-table-in-header.
So add an UNO property which exposes the parent of a table cell, this
way text in header (regardless of it's in a table or not) will have the
same XText, leading to writing the necessary <text:user-field-decl>
element for the matching <text:user-field-get> definition.
Change-Id: I077b8d7e9dfae4062539894318637e266b925382
Reviewed-on: https://gerrit.libreoffice.org/73176
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r-- | offapi/com/sun/star/text/CellProperties.idl | 8 | ||||
-rw-r--r-- | sw/inc/cmdid.h | 1 | ||||
-rw-r--r-- | sw/inc/unoprnms.hxx | 1 | ||||
-rw-r--r-- | sw/inc/unotbl.hxx | 1 | ||||
-rw-r--r-- | sw/qa/extras/odfexport/data/user-field-decl.odt | bin | 0 -> 8597 bytes | |||
-rw-r--r-- | sw/qa/extras/odfexport/odfexport.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/unocore/unomap.cxx | 1 | ||||
-rw-r--r-- | sw/source/core/unocore/unotbl.cxx | 23 | ||||
-rw-r--r-- | sw/source/filter/xml/xmlfmte.cxx | 1 | ||||
-rw-r--r-- | xmloff/source/text/txtflde.cxx | 29 |
10 files changed, 72 insertions, 1 deletions
diff --git a/offapi/com/sun/star/text/CellProperties.idl b/offapi/com/sun/star/text/CellProperties.idl index 17c9c556d7e4..21bda1c22ab9 100644 --- a/offapi/com/sun/star/text/CellProperties.idl +++ b/offapi/com/sun/star/text/CellProperties.idl @@ -134,6 +134,14 @@ published service CellProperties @since LibreOffice 6.1 */ [optional, property] com::sun::star::graphic::XGraphic BackGraphic; + + /** Parent text of this table cell. + + This might be a header text, body text, parent cell, etc. + + @since LibreOffice 6.3 + */ + [optional, readonly, property] com::sun::star::text::XText ParentText; }; diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index 55ec66b1a116..9ad470acddc2 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -524,6 +524,7 @@ #define FN_UNO_FOOTER_LEFT (FN_EXTRA2 + 39) #define FN_UNO_FOOTER_RIGHT (FN_EXTRA2 + 40) #define FN_UNO_TEXT_PARAGRAPH (FN_EXTRA2 + 41) +#define FN_UNO_PARENT_TEXT (FN_EXTRA2 + 42) #define FN_UNO_FOLLOW_STYLE (FN_EXTRA2 + 59) #define FN_API_CALL (FN_EXTRA2 + 60) diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 8e03b0bb9c59..ccde05f87f77 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -400,6 +400,7 @@ #define UNO_NAME_FOOTER_IS_DYNAMIC_HEIGHT "FooterIsDynamicHeight" #define UNO_NAME_FOOTER_IS_SHARED "FooterIsShared" #define UNO_NAME_TEXT_PARAGRAPH "TextParagraph" +#define UNO_NAME_PARENT_TEXT "ParentText" #define UNO_NAME_FOOTER_HEIGHT "FooterHeight" #define UNO_NAME_FOOTER_IS_ON "FooterIsOn" diff --git a/sw/inc/unotbl.hxx b/sw/inc/unotbl.hxx index f3061f309faf..b31e425b6753 100644 --- a/sw/inc/unotbl.hxx +++ b/sw/inc/unotbl.hxx @@ -72,6 +72,7 @@ class SwXCell final : public SwXCellBaseClass, // table position where pBox was found last size_t nFndPos; + css::uno::Reference<css::text::XText> m_xParentText; static size_t const NOTFOUND = SAL_MAX_SIZE; virtual const SwStartNode *GetStartNode() const override; diff --git a/sw/qa/extras/odfexport/data/user-field-decl.odt b/sw/qa/extras/odfexport/data/user-field-decl.odt Binary files differnew file mode 100644 index 000000000000..f037f403ec68 --- /dev/null +++ b/sw/qa/extras/odfexport/data/user-field-decl.odt diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx index 90a467b0d05c..8725efcc500b 100644 --- a/sw/qa/extras/odfexport/odfexport.cxx +++ b/sw/qa/extras/odfexport/odfexport.cxx @@ -251,6 +251,14 @@ DECLARE_ODFEXPORT_TEST(testTdf103567, "tdf103567.odt") CPPUNIT_ASSERT_EQUAL(sal_Int32( 408), rect.Height); } +DECLARE_ODFEXPORT_TEST(testUserFieldDecl, "user-field-decl.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("styles.xml")) + // Without the accompanying fix in place, this test would have failed with 'Expected: 2; + // Actual: 1', i.e. the in-table field had no declaration (in the header), while the + // outside-table one had the declaration. + assertXPath(pXmlDoc, "//style:header/text:user-field-decls/text:user-field-decl", 2); +} DECLARE_ODFEXPORT_TEST(testFramebackgrounds, "framebackgrounds.odt") { diff --git a/sw/source/core/unocore/unomap.cxx b/sw/source/core/unocore/unomap.cxx index ba31f396b3e2..b1b7ab4b49e8 100644 --- a/sw/source/core/unocore/unomap.cxx +++ b/sw/source/core/unocore/unomap.cxx @@ -229,6 +229,7 @@ const SfxItemPropertyMapEntry* SwUnoPropertyMapProvider::GetPropertyMapEntries(s { OUString(UNO_NAME_WRITING_MODE), RES_FRAMEDIR, cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE, 0 }, { OUString(UNO_NAME_ROW_SPAN), FN_UNO_CELL_ROW_SPAN, cppu::UnoType<sal_Int32>::get(), 0, 0 }, { OUString(UNO_NAME_CELL_INTEROP_GRAB_BAG), RES_FRMATR_GRABBAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0 }, + { OUString(UNO_NAME_PARENT_TEXT), FN_UNO_PARENT_TEXT, cppu::UnoType<text::XText>::get(), PropertyAttribute::MAYBEVOID | PropertyAttribute::READONLY, 0 }, REDLINE_NODE_PROPERTIES { OUString(), 0, css::uno::Type(), 0, 0 } }; diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx index 1d124a5a2725..3fdb6fa6d6ad 100644 --- a/sw/source/core/unocore/unotbl.cxx +++ b/sw/source/core/unocore/unotbl.cxx @@ -1092,6 +1092,29 @@ uno::Any SwXCell::getPropertyValue(const OUString& rPropertyName) return SwXText::getPropertyValue(rPropertyName); } break; + case FN_UNO_PARENT_TEXT: + { + if (!m_xParentText.is()) + { + const SwStartNode* pSttNd = pBox->GetSttNd(); + if (!pSttNd) + return uno::Any(); + + const SwTableNode* pTableNode = pSttNd->FindTableNode(); + if (!pTableNode) + return uno::Any(); + + SwPosition aPos(*pTableNode); + SwDoc* pDoc = aPos.GetDoc(); + if (!pDoc) + return uno::Any(); + + m_xParentText = sw::CreateParentXText(*pDoc, aPos); + } + + return uno::makeAny(m_xParentText); + } + break; default: { const SwAttrSet& rSet = pBox->GetFrameFormat()->GetAttrSet(); diff --git a/sw/source/filter/xml/xmlfmte.cxx b/sw/source/filter/xml/xmlfmte.cxx index c739acac7a1a..737f0e7ed8c9 100644 --- a/sw/source/filter/xml/xmlfmte.cxx +++ b/sw/source/filter/xml/xmlfmte.cxx @@ -39,6 +39,7 @@ #include "xmlexp.hxx" #include <SwStyleNameMapper.hxx> #include <osl/diagnose.h> +#include <sal/log.hxx> using namespace ::com::sun::star::beans; using namespace ::com::sun::star::uno; diff --git a/xmloff/source/text/txtflde.cxx b/xmloff/source/text/txtflde.cxx index df43562daf23..293362b8ab10 100644 --- a/xmloff/source/text/txtflde.cxx +++ b/xmloff/source/text/txtflde.cxx @@ -157,6 +157,31 @@ static sal_Char const FIELD_SERVICE_MEASURE[] = "Measure"; static sal_Char const FIELD_SERVICE_TABLE_FORMULA[] = "TableFormula"; static sal_Char const FIELD_SERVICE_DROP_DOWN[] = "DropDown"; +namespace +{ +/// Walks up the parent chain of xText and returns the topmost text. +uno::Reference<text::XText> GetToplevelText(const uno::Reference<text::XText>& xText) +{ + uno::Reference<text::XText> xRet = xText; + while (true) + { + uno::Reference<beans::XPropertySet> xPropertySet(xRet, uno::UNO_QUERY); + if (!xPropertySet.is()) + return xRet; + + if (!xPropertySet->getPropertySetInfo()->hasPropertyByName("ParentText")) + return xRet; + + uno::Reference<text::XText> xParent; + if (xPropertySet->getPropertyValue("ParentText") >>= xParent) + xRet = xParent; + else + return xRet; + } + return xRet; +} +} + SvXMLEnumStringMapEntry<FieldIdEnum> const aFieldServiceNameMapping[] = { ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SENDER, FIELD_ID_SENDER ), @@ -749,7 +774,9 @@ void XMLTextFieldExport::ExportFieldAutoStyle( Reference<XDependentTextField> xDepField(rTextField, UNO_QUERY); if (xDepField.is()) { - Reference<XText> xOurText = rTextField->getAnchor()->getText(); + // The direct parent may be just the table cell, while we want the topmost parent, e.g. + // a header text. + Reference<XText> xOurText = GetToplevelText(rTextField->getAnchor()->getText()); map<Reference<XText>, set<OUString> >::iterator aMapIter = pUsedMasters->find(xOurText); |