summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-05-29 17:26:57 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-05-30 17:43:12 +0200
commit4a504709498628378bcdf576a7e2da85d33e20a3 (patch)
tree95c85b0bcb7df1c7348492884505b22431e15ac8
parent8a556a1509bbb04eb00bea41761f5616927ac773 (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. (cherry picked from commit 6bb241ccc61c6904efec95978fa17e33c0eb1df3) Conflicts: offapi/com/sun/star/text/CellProperties.idl sw/inc/cmdid.h sw/inc/unoprnms.hxx sw/source/filter/xml/xmlfmte.cxx 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.idl7
-rw-r--r--sw/inc/cmdid.h1
-rw-r--r--sw/inc/unoprnms.hxx1
-rw-r--r--sw/inc/unotbl.hxx1
-rw-r--r--sw/qa/extras/odfexport/data/user-field-decl.odtbin0 -> 8597 bytes
-rw-r--r--sw/qa/extras/odfexport/odfexport.cxx8
-rw-r--r--sw/source/core/unocore/unomap.cxx1
-rw-r--r--sw/source/core/unocore/unotbl.cxx23
-rw-r--r--sw/source/filter/xml/xmlfmte.cxx1
-rw-r--r--xmloff/source/text/txtflde.cxx29
10 files changed, 71 insertions, 1 deletions
diff --git a/offapi/com/sun/star/text/CellProperties.idl b/offapi/com/sun/star/text/CellProperties.idl
index 6144d9fc8530..f2a26fe9abd7 100644
--- a/offapi/com/sun/star/text/CellProperties.idl
+++ b/offapi/com/sun/star/text/CellProperties.idl
@@ -122,6 +122,13 @@ published service CellProperties
*/
[property] short VertOrient;
+ /** 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 e626bbb93458..f91a1fd6489c 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -513,6 +513,7 @@
#define FN_UNO_FOOTER (FN_EXTRA2 + 38)
#define FN_UNO_FOOTER_LEFT (FN_EXTRA2 + 39)
#define FN_UNO_FOOTER_RIGHT (FN_EXTRA2 + 40)
+#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 24cc71cb8740..7a3aa2f95d32 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -391,6 +391,7 @@
#define UNO_NAME_FOOTER_BODY_DISTANCE "FooterBodyDistance"
#define UNO_NAME_FOOTER_IS_DYNAMIC_HEIGHT "FooterIsDynamicHeight"
#define UNO_NAME_FOOTER_IS_SHARED "FooterIsShared"
+#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 7b06cc143e6c..d649c51f8ac7 100644
--- a/sw/inc/unotbl.hxx
+++ b/sw/inc/unotbl.hxx
@@ -73,6 +73,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
new file mode 100644
index 000000000000..f037f403ec68
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/user-field-decl.odt
Binary files differ
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index e9e458c4a243..e6dc81d274e0 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -150,6 +150,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 aa98dbbf7ab9..9c71545d6510 100644
--- a/sw/source/core/unocore/unomap.cxx
+++ b/sw/source/core/unocore/unomap.cxx
@@ -213,6 +213,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 17c9819dc26a..2fc660b9a8a7 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -1098,6 +1098,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 7ee76a429f9f..25d6ca8f9855 100644
--- a/sw/source/filter/xml/xmlfmte.cxx
+++ b/sw/source/filter/xml/xmlfmte.cxx
@@ -37,6 +37,7 @@
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include "xmlexp.hxx"
#include <SwStyleNameMapper.hxx>
+#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 959b2e75162b..e37817ae7d70 100644
--- a/xmloff/source/text/txtflde.cxx
+++ b/xmloff/source/text/txtflde.cxx
@@ -156,6 +156,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 ),
@@ -747,7 +772,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);