summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Bakos (NISZ) <bakos.attilakaroly@nisz.hu>2022-03-04 08:27:49 +0100
committerLászló Németh <nemeth@numbertext.org>2022-03-29 16:29:39 +0200
commitf81800193a942b3f68c61a5cede634f3eeb47b1f (patch)
tree8eba4e0b09aa2777edaf9bce62a48833a56a5233
parentc1ee13b11f78026a323fea7f20d82d7b056ae9bb (diff)
tdf#73499 DOCX import: fix grouped linked textbox
Only ungrouped text boxes were imported correctly. Grouped textboxes lost their linking, resulting broken layout. Now the linking is fixed for DrawingML. Note: in old MSO versions, linking needed grouping. To import these DOC documents correctly, convert them to DOCX/DrawingML in MSO before opening them in Writer. Change-Id: Ib5a8744d783a9c95c42447d204e17891b3aea7bd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130950 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf73499.docxbin0 -> 16470 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport17.cxx28
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx91
3 files changed, 115 insertions, 4 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf73499.docx b/sw/qa/extras/ooxmlexport/data/tdf73499.docx
new file mode 100644
index 000000000000..605c01e2b3ac
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf73499.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index 486dc6c3d1e9..53e80df5a301 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -346,6 +346,34 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148111, "tdf148111.docx")
CPPUNIT_ASSERT(!xFields->hasMoreElements());
}
+DECLARE_OOXMLEXPORT_TEST(TestTdf73499, "tdf73499.docx")
+{
+ // Ensure, the bugdoc is opened
+ CPPUNIT_ASSERT(mxComponent);
+ // Get the groupshape
+ uno::Reference<drawing::XShapes> xGroup(getShape(1), uno::UNO_QUERY_THROW);
+
+ // Get the textboxes of the groupshape
+ uno::Reference<text::XText> xTextBox1(xGroup->getByIndex(0), uno::UNO_QUERY_THROW);
+ uno::Reference<text::XText> xTextBox2(xGroup->getByIndex(1), uno::UNO_QUERY_THROW);
+
+ // Get the properties of the textboxes
+ uno::Reference<beans::XPropertySet> xTextBox1Properties(xTextBox1, uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySet> xTextBox2Properties(xTextBox2, uno::UNO_QUERY_THROW);
+
+ // Get the name of the textboxes
+ uno::Reference<container::XNamed> xTextBox1Name(xTextBox1, uno::UNO_QUERY_THROW);
+ uno::Reference<container::XNamed> xTextBox2Name(xTextBox2, uno::UNO_QUERY_THROW);
+
+ // Check for the links, before the fix that were missing
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Link name missing!", xTextBox2Name->getName(),
+ xTextBox1Properties->getPropertyValue("ChainNextName").get<OUString>());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Link name missing!", xTextBox1Name->getName(),
+ xTextBox2Properties->getPropertyValue("ChainPrevName").get<OUString>());
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf81507, "tdf81507.docx")
{
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index a3d6a4f69498..f8700faee88c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -4634,20 +4634,103 @@ void DomainMapper_Impl::PopTextBoxContent()
void DomainMapper_Impl::AttachTextBoxContentToShape(css::uno::Reference<css::drawing::XShape> xShape)
{
+ // Without textbox or shape pointless to continue
if (m_xPendingTextBoxFrames.empty() || !xShape)
return;
uno::Reference< drawing::XShapes >xGroup(xShape, uno::UNO_QUERY);
uno::Reference< beans::XPropertySet >xProps(xShape, uno::UNO_QUERY);
+ // If this is a group go inside
if (xGroup)
for (sal_Int32 i = 0; i < xGroup->getCount(); ++i)
- AttachTextBoxContentToShape(uno::Reference<drawing::XShape>(xGroup->getByIndex(i),uno::UNO_QUERY_THROW));
+ AttachTextBoxContentToShape(
+ uno::Reference<drawing::XShape>(xGroup->getByIndex(i), uno::UNO_QUERY));
- if (xProps->getPropertyValue("TextBox").get<bool>())
+ // if this shape has to be a textbox, attach the frame
+ if (!xProps->getPropertyValue("TextBox").get<bool>())
+ return;
+
+ // if this is a textbox there must be a waiting frame
+ auto xTextBox = m_xPendingTextBoxFrames.front();
+ if (!xTextBox)
+ return;
+
+ // Pop the pending frames
+ m_xPendingTextBoxFrames.pop();
+
+ // Attach the textbox to the shape
+ try
+ {
+ xProps->setPropertyValue("TextBoxContent", uno::Any(xTextBox));
+ }
+ catch (...)
+ {
+ SAL_WARN("writerfilter.dmapper", "Exception while trying to attach textboxes!");
+ return;
+ }
+
+ // If attaching is successful, then do the linking
+ try
+ {
+ // Get the name of the textbox
+ OUString sTextBoxName;
+ uno::Reference<container::XNamed> xName(xTextBox, uno::UNO_QUERY);
+ if (xName && !xName->getName().isEmpty())
+ sTextBoxName = xName->getName();
+
+ // Try to get the grabbag
+ uno::Sequence<beans::PropertyValue> aOldGrabBagSeq;
+ if (xProps->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
+ xProps->getPropertyValue("InteropGrabBag") >>= aOldGrabBagSeq;
+
+ // If the grabbag successfully get...
+ if (!aOldGrabBagSeq.hasElements())
+ return;
+
+ // Check for the existing linking information
+ bool bSuccess = false;
+ beans::PropertyValues aNewGrabBagSeq;
+ const auto& aHasLink = lcl_getGrabBagValue(aOldGrabBagSeq, "TxbxHasLink");
+
+ // If there must be a link, do it
+ if (aHasLink.hasValue() && aHasLink.get<bool>())
+ {
+ auto aLinkProp = comphelper::makePropertyValue("LinkChainName", sTextBoxName);
+ for (sal_uInt32 i = 0; i < aOldGrabBagSeq.size(); ++i)
+ {
+ aNewGrabBagSeq.realloc(i + 1);
+ // If this is the link name replace it
+ if (!aOldGrabBagSeq[i].Name.isEmpty() && !aLinkProp.Name.isEmpty()
+ && (aOldGrabBagSeq[i].Name == aLinkProp.Name))
+ {
+ aNewGrabBagSeq.getArray()[i] = aLinkProp;
+ bSuccess = true;
+ }
+ // else copy
+ else
+ aNewGrabBagSeq.getArray()[i] = aOldGrabBagSeq[i];
+ }
+
+ // If there was no replacement, append the linking data
+ if (!bSuccess)
+ {
+ aNewGrabBagSeq.realloc(aNewGrabBagSeq.size() + 1);
+ aNewGrabBagSeq.getArray()[aNewGrabBagSeq.size() - 1] = aLinkProp;
+ bSuccess = true;
+ }
+ }
+
+ // If the linking changed the grabbag, apply the modifications
+ if (aNewGrabBagSeq.hasElements() && bSuccess)
+ {
+ xProps->setPropertyValue("InteropGrabBag", uno::Any(aNewGrabBagSeq));
+ m_vTextFramesForChaining.push_back(xShape);
+ }
+ }
+ catch (...)
{
- xProps->setPropertyValue("TextBoxContent", uno::Any(m_xPendingTextBoxFrames.front()));
- m_xPendingTextBoxFrames.pop();
+ SAL_WARN("writerfilter.dmapper", "Exception while trying to link textboxes!");
}
}