diff options
author | Attila Bakos (NISZ) <bakos.attilakaroly@nisz.hu> | 2021-11-11 14:02:12 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2022-01-06 10:41:32 +0100 |
commit | 121cbc250b36290f0f8c7265fea57256dad69553 (patch) | |
tree | 6ecc1d2c1b9905a1a8a8899cdf6343734d0d1483 /writerfilter/source/dmapper | |
parent | 470d1be4ec5a3a5a0aba8febda06600ea39852c5 (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.cxx | 11 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.hxx | 3 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 69 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 10 | ||||
-rw-r--r-- | writerfilter/source/dmapper/FontTable.hxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/GraphicImport.hxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/LoggedResources.cxx | 4 | ||||
-rw-r--r-- | writerfilter/source/dmapper/LoggedResources.hxx | 4 |
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*/) {} |