summaryrefslogtreecommitdiff
path: root/writerfilter/source/dmapper
diff options
context:
space:
mode:
authorAttila Bakos (NISZ) <bakos.attilakaroly@nisz.hu>2021-11-11 14:02:12 +0100
committerLászló Németh <nemeth@numbertext.org>2022-01-06 10:41:32 +0100
commit121cbc250b36290f0f8c7265fea57256dad69553 (patch)
tree6ecc1d2c1b9905a1a8a8899cdf6343734d0d1483 /writerfilter/source/dmapper
parent470d1be4ec5a3a5a0aba8febda06600ea39852c5 (diff)
tdf#66039 DOCX: import textboxes (with tables, images etc.) in group shapes
Text boxes in group shapes were imported as shapes, losing complex text content: tables (tdf#66039), colors (tdf#73022), images (tdf#81958), lists, paragraph styles, hyperlinks (tdf#122960) and track changes. Note: a few unit tests have been deactivated temporarily. Test document "groupshape-trackedchanges.docx" of testGroupshapeTrackedchanges is imported correctly now: with track changes, and the test was modified accordingly. Follow-up to commit 2951cbdf3a6e2b62461665546b47e1d253fcb834 "tdf#143574 OOXML export/import of textboxes in group shapes". Change-Id: I6eb918dbf64393fd723fe43f798f93b5b9a12575 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125051 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'writerfilter/source/dmapper')
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx11
-rw-r--r--writerfilter/source/dmapper/DomainMapper.hxx3
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx69
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx10
-rw-r--r--writerfilter/source/dmapper/FontTable.hxx2
-rw-r--r--writerfilter/source/dmapper/GraphicImport.hxx2
-rw-r--r--writerfilter/source/dmapper/LoggedResources.cxx4
-rw-r--r--writerfilter/source/dmapper/LoggedResources.hxx4
8 files changed, 103 insertions, 2 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 43d134b23805..e8b5a3f40e5b 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3245,6 +3245,7 @@ void DomainMapper::lcl_startShape(uno::Reference<drawing::XShape> const& xShape)
{
assert(xShape.is());
+ m_pImpl->AttachTextBoxContentToShape(xShape);
if (m_pImpl->GetTopContext())
{
// If there is a deferred page break, handle it now, so that the
@@ -3292,6 +3293,16 @@ void DomainMapper::lcl_endShape( )
m_pImpl->SetIsOutsideAParagraph(false);
}
+void DomainMapper::lcl_startTextBoxContent()
+{
+ m_pImpl->PushTextBoxContent();
+}
+
+void DomainMapper::lcl_endTextBoxContent()
+{
+ m_pImpl->PopTextBoxContent();
+}
+
void DomainMapper::PushStyleSheetProperties( const PropertyMapPtr& pStyleProperties, bool bAffectTableMngr )
{
m_pImpl->PushStyleProperties( pStyleProperties );
diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx
index c0134866537c..07d089e22348 100644
--- a/writerfilter/source/dmapper/DomainMapper.hxx
+++ b/writerfilter/source/dmapper/DomainMapper.hxx
@@ -149,7 +149,8 @@ private:
virtual void lcl_endCharacterGroup() override;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
virtual void lcl_endShape( ) override;
-
+ virtual void lcl_startTextBoxContent() override;
+ virtual void lcl_endTextBoxContent() override;
virtual void lcl_text(const sal_uInt8 * data, size_t len) override;
virtual void lcl_utext(const sal_uInt8 * data, size_t len) override;
virtual void lcl_positionOffset(const OUString& rText, bool bVertical) override;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 2857d113a913..57ffccbac8f6 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -333,6 +333,7 @@ DomainMapper_Impl::DomainMapper_Impl(
m_aSmartTagHandler(m_xComponentContext, m_xTextDocument),
m_xInsertTextRange(rMediaDesc.getUnpackedValueOrDefault("TextInsertModeRange", uno::Reference<text::XTextRange>())),
m_xAltChunkStartingRange(rMediaDesc.getUnpackedValueOrDefault("AltChunkStartingRange", uno::Reference<text::XTextRange>())),
+ m_bIsInTextBox(false),
m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", false)),
m_bIsAltChunk(rMediaDesc.getUnpackedValueOrDefault("AltChunkMode", false)),
m_bIsReadGlossaries(rMediaDesc.getUnpackedValueOrDefault("ReadGlossaries", false)),
@@ -3468,7 +3469,8 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape
{
try
{
- uno::Reference<beans::XPropertySet> xSyncedPropertySet(xShapes->getByIndex(i), uno::UNO_QUERY_THROW);
+ uno::Reference<text::XTextRange> xFrame(xShapes->getByIndex(i), uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySet> xSyncedPropertySet(xFrame, uno::UNO_QUERY_THROW);
comphelper::SequenceAsHashMap aGrabBag( xSyncedPropertySet->getPropertyValue("CharInteropGrabBag") );
// only VML import has checked for style. Don't apply default parastyle properties to other imported shapes
@@ -4408,6 +4410,71 @@ void DomainMapper_Impl::ChainTextFrames()
}
}
+void DomainMapper_Impl::PushTextBoxContent()
+{
+ if (m_bIsInTextBox)
+ return;
+
+ try
+ {
+ uno::Reference<text::XTextFrame> xTBoxFrame(
+ m_xTextFactory->createInstance("com.sun.star.text.TextFrame"), uno::UNO_QUERY_THROW);
+ uno::Reference<container::XNamed>(xTBoxFrame, uno::UNO_QUERY_THROW)
+ ->setName("textbox" + OUString::number(m_xPendingTextBoxFrames.size() + 1));
+ uno::Reference<text::XTextAppendAndConvert>(m_aTextAppendStack.top().xTextAppend,
+ uno::UNO_QUERY_THROW)
+ ->appendTextContent(xTBoxFrame, beans::PropertyValues());
+ m_xPendingTextBoxFrames.push(xTBoxFrame);
+
+ m_aTextAppendStack.push(TextAppendContext(uno::Reference<text::XTextAppend>(xTBoxFrame, uno::UNO_QUERY_THROW), {}));
+ m_bIsInTextBox = true;
+
+ appendTableManager();
+ appendTableHandler();
+ getTableManager().startLevel();
+ }
+ catch (uno::Exception& e)
+ {
+ SAL_WARN("writerfilter.dmapper", "Exception during creating textbox (" + e.Message + ")!");
+ }
+}
+
+void DomainMapper_Impl::PopTextBoxContent()
+{
+ if (!m_bIsInTextBox || m_xPendingTextBoxFrames.empty())
+ return;
+
+ if (uno::Reference<text::XTextFrame>(m_aTextAppendStack.top().xTextAppend, uno::UNO_QUERY).is())
+ {
+ if (hasTableManager())
+ {
+ getTableManager().endLevel();
+ popTableManager();
+ }
+ m_aTextAppendStack.pop();
+ m_bIsInTextBox = false;
+ }
+}
+
+void DomainMapper_Impl::AttachTextBoxContentToShape(css::uno::Reference<css::drawing::XShape> xShape)
+{
+ 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 (xGroup)
+ for (sal_Int32 i = 0; i < xGroup->getCount(); ++i)
+ AttachTextBoxContentToShape(uno::Reference<drawing::XShape>(xGroup->getByIndex(i),uno::UNO_QUERY_THROW));
+
+ if (xProps->getPropertyValue("TextBox").get<bool>())
+ {
+ xProps->setPropertyValue("TextBoxContent", uno::Any(m_xPendingTextBoxFrames.front()));
+ m_xPendingTextBoxFrames.pop();
+ }
+}
+
uno::Reference<beans::XPropertySet> DomainMapper_Impl::FindOrCreateFieldMaster(const char* pFieldMasterService, const OUString& rFieldMasterName)
{
// query master, create if not available
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index ae267c5c390e..7238d129f766 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -22,6 +22,7 @@
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/text/XTextCursor.hpp>
#include <com/sun/star/text/XTextAppend.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
#include <com/sun/star/style/TabStop.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/embed/XStorage.hpp>
@@ -62,6 +63,7 @@ namespace com::sun::star{
namespace text
{
class XTextField;
+ class XTextFrame;
class XFormField;
}
namespace beans{ class XPropertySet;}
@@ -618,9 +620,13 @@ private:
css::uno::Reference<css::text::XTextRange> m_xGlossaryEntryStart;
css::uno::Reference<css::text::XTextRange> m_xSdtEntryStart;
+ std::queue< css::uno::Reference< css::text::XTextFrame > > m_xPendingTextBoxFrames;
+
public:
css::uno::Reference<css::text::XTextRange> m_xInsertTextRange;
css::uno::Reference<css::text::XTextRange> m_xAltChunkStartingRange;
+
+ bool m_bIsInTextBox;
private:
bool m_bIsNewDoc;
bool m_bIsAltChunk = false;
@@ -667,6 +673,10 @@ public:
void EndParaMarkerChange( );
void ChainTextFrames();
+ void PushTextBoxContent();
+ void PopTextBoxContent();
+ void AttachTextBoxContentToShape(css::uno::Reference<css::drawing::XShape> xShape);
+
void RemoveDummyParaForTableInSection();
void AddDummyParaForTableInSection();
void RemoveLastParagraph( );
diff --git a/writerfilter/source/dmapper/FontTable.hxx b/writerfilter/source/dmapper/FontTable.hxx
index ff4d11fba83e..5f32776a2819 100644
--- a/writerfilter/source/dmapper/FontTable.hxx
+++ b/writerfilter/source/dmapper/FontTable.hxx
@@ -80,6 +80,8 @@ class FontTable : public LoggedProperties, public LoggedTable
::writerfilter::Reference<Stream>::Pointer_t ref) override;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
virtual void lcl_endShape( ) override;
+ virtual void lcl_startTextBoxContent() override {};
+ virtual void lcl_endTextBoxContent() override {};
};
typedef tools::SvRef< FontTable > FontTablePtr;
diff --git a/writerfilter/source/dmapper/GraphicImport.hxx b/writerfilter/source/dmapper/GraphicImport.hxx
index 7ca4e09ed30d..57c3dbef906a 100644
--- a/writerfilter/source/dmapper/GraphicImport.hxx
+++ b/writerfilter/source/dmapper/GraphicImport.hxx
@@ -122,6 +122,8 @@ public:
writerfilter::Reference<Table>::Pointer_t ref) override;
virtual void lcl_substream(Id name, writerfilter::Reference<Stream>::Pointer_t ref) override;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
+ virtual void lcl_startTextBoxContent() override {};
+ virtual void lcl_endTextBoxContent() override {};
virtual void lcl_endShape() override;
void handleWrapTextValue(sal_uInt32 nVal);
diff --git a/writerfilter/source/dmapper/LoggedResources.cxx b/writerfilter/source/dmapper/LoggedResources.cxx
index 4a0886e44812..661bf17cd1e8 100644
--- a/writerfilter/source/dmapper/LoggedResources.cxx
+++ b/writerfilter/source/dmapper/LoggedResources.cxx
@@ -147,6 +147,10 @@ void LoggedStream::endShape()
#endif
}
+void LoggedStream::startTextBoxContent() { lcl_startTextBoxContent(); }
+
+void LoggedStream::endTextBoxContent() { lcl_endTextBoxContent(); }
+
void LoggedStream::text(const sal_uInt8* data, size_t len)
{
#ifdef DBG_UTIL
diff --git a/writerfilter/source/dmapper/LoggedResources.hxx b/writerfilter/source/dmapper/LoggedResources.hxx
index 74b7b0b2c9a5..cecf64c91b23 100644
--- a/writerfilter/source/dmapper/LoggedResources.hxx
+++ b/writerfilter/source/dmapper/LoggedResources.hxx
@@ -60,6 +60,8 @@ public:
void endCharacterGroup() override;
void startShape(css::uno::Reference<css::drawing::XShape> const& xShape) override;
void endShape() override;
+ void startTextBoxContent() override;
+ void endTextBoxContent() override;
void text(const sal_uInt8* data, size_t len) override;
void utext(const sal_uInt8* data, size_t len) override;
void positionOffset(const OUString& rText, bool bVertical) override;
@@ -83,6 +85,8 @@ protected:
virtual void lcl_endCharacterGroup() = 0;
virtual void lcl_startShape(css::uno::Reference<css::drawing::XShape> const& xShape) = 0;
virtual void lcl_endShape() = 0;
+ virtual void lcl_startTextBoxContent() = 0;
+ virtual void lcl_endTextBoxContent() = 0;
virtual void lcl_text(const sal_uInt8* data, size_t len) = 0;
virtual void lcl_utext(const sal_uInt8* data, size_t len) = 0;
virtual void lcl_positionOffset(const OUString& /*rText*/, bool /*bVertical*/) {}