sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 2 - sw/source/filter/ww8/docxattributeoutput.cxx | 49 ++++++++++++++++++++++++--- sw/source/filter/ww8/docxexport.cxx | 16 +++----- sw/source/filter/ww8/docxexport.hxx | 2 - writerfilter/source/dmapper/OLEHandler.cxx | 45 ++++++++++++++++++++++++ writerfilter/source/dmapper/OLEHandler.hxx | 4 ++ 6 files changed, 102 insertions(+), 16 deletions(-)
New commits: commit 1c993627d893c62ab8f01355895206374bf4eb6c Author: Jacobo Aragunde Pérez <jaragu...@igalia.com> Date: Wed Feb 26 18:29:44 2014 +0100 sw: write other types of embeddings properly to docx Improves patch 1428ec6f4e2bfe0d8654a9ccc713e274e08c6423 When embedding an object into a docx, several things interact: * The properties in the <o:OLEObject> tag in document.xml * The ContentType for the file defined in [Content_Types].xml * The Type of the Relationship defined in document.xml.rels You need the right combination of those three elements for Word to properly recognize the embeddings in exported documents. To know which values must be written, I store some interoperability information in the import phase in the document grab bag. The relevant information is the value of the ProgID attribute in the <o:OLEObject> tag. I have defined three cases depending on the value of ProgID, but more could be needed in the future: * Embedded xlsx sheet. * Embedded pptx presentation. * Generic OLE, this should work with embedded odt/ods in combination with the ProgID attribute stored in the import phase. Change-Id: I26336cb3fe47bd33e1cef11dd1c7edcf390f2e56 diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 675a012..12e5992 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -2579,7 +2579,7 @@ DECLARE_OOXMLEXPORT_TEST(testEmbeddedXlsx, "embedded-xlsx.docx") int nImageFiles = 0; for (int i=0; i<names.getLength(); i++) { - if(names[i].startsWith("word/embeddings/Microsoft_Excel_Worksheet")) + if(names[i].startsWith("word/embeddings/oleObject")) nSheetFiles++; if(names[i].startsWith("word/media/image")) nImageFiles++; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 362c1c8..1b91a13 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3568,12 +3568,53 @@ void DocxAttributeOutput::WritePostponedOLE() SAL_INFO( "sw.ww8", OSL_THIS_FUNC ); + // get interoperability information about embedded objects + uno::Reference< beans::XPropertySet > xPropSet( m_rExport.pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); + OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; + uno::Sequence< beans::PropertyValue > aGrabBag, aObjectsInteropList; + xPropSet->getPropertyValue( pName ) >>= aGrabBag; + for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i ) + if ( aGrabBag[i].Name == "EmbeddedObjects" ) + { + aGrabBag[i].Value >>= aObjectsInteropList; + break; + } + for( std::list< PostponedOLE >::iterator it = m_postponedOLE->begin(); it != m_postponedOLE->end(); ++it ) { + SwOLEObj& aObject = it->object->GetOLEObj(); + uno::Reference < embed::XEmbeddedObject > xObj( aObject.GetOleRef() ); + comphelper::EmbeddedObjectContainer* aContainer = aObject.GetObject().GetContainer(); + OUString sObjectName = aContainer->GetEmbeddedObjectName( xObj ); + + // set some attributes according to the type of the embedded object + OUString sProgID, sMediaType, sRelationType; + for( sal_Int32 i=0; i < aObjectsInteropList.getLength(); ++i ) + if ( aObjectsInteropList[i].Name == sObjectName ) + { + aObjectsInteropList[i].Value >>= sProgID; + break; + } + if( sProgID.startsWith("Excel.Sheet") ) + { + sMediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package"; + } + else if( sProgID.startsWith("PowerPoint.Show") ) + { + sMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package"; + } + else + { + sMediaType = "application/vnd.openxmlformats-officedocument.oleObject"; + sRelationType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject"; + } + // write embedded file - OString sId = m_rExport.WriteOLENode( *it->object ); + OString sId = m_rExport.WriteOLEObject( aObject, sMediaType, sRelationType ); if( sId.isEmpty() ) { @@ -3612,7 +3653,7 @@ void DocxAttributeOutput::WritePostponedOLE() // OLE object definition m_pSerializer->singleElementNS( XML_o, XML_OLEObject, XML_Type, "Embed", - XML_ProgID,"Excel.Sheet.12", //TODO: should be auto-detected somehow + XML_ProgID, OUStringToOString( sProgID, RTL_TEXTENCODING_UTF8 ).getStr(), XML_ShapeID, sShapeId.getStr(), XML_DrawAspect, "Content", XML_ObjectID, "_" + OString::number( rand() ), diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 41e7083..79077f5 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -358,25 +358,23 @@ OString DocxExport::OutputChart( uno::Reference< frame::XModel >& xModel, sal_In return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 ); } -OString DocxExport::WriteOLENode( const SwOLENode& rNode ) +OString DocxExport::WriteOLEObject( SwOLEObj& rObject, OUString sMediaType, OUString sRelationType ) { - uno::Reference <embed::XEmbeddedObject> xObj( const_cast<SwOLENode&>(rNode).GetOLEObj().GetOleRef() ); - OUString sId, sMediaType; - comphelper::EmbeddedObjectContainer* aContainer = const_cast<SwOLENode&>(rNode).GetOLEObj().GetObject().GetContainer(); - uno::Reference< io::XInputStream > xInStream = aContainer->GetObjectStream( xObj, &sMediaType ); + uno::Reference <embed::XEmbeddedObject> xObj( rObject.GetOleRef() ); + comphelper::EmbeddedObjectContainer* aContainer = rObject.GetObject().GetContainer(); + uno::Reference< io::XInputStream > xInStream = aContainer->GetObjectStream( xObj, NULL ); - OUString sFileName = "embeddings/Microsoft_Excel_Worksheet" + OUString::number( ++m_nOLEObjects ) + ".xlsx"; + OUString sFileName = "embeddings/oleObject" + OUString::number( ++m_nOLEObjects ) + ".bin"; uno::Reference< io::XOutputStream > xOutStream = GetFilter().openFragmentStream( OUStringBuffer() .appendAscii( "word/" ) .append( sFileName ) .makeStringAndClear(), sMediaType ); - + OUString sId; if( lcl_CopyStream( xInStream, xOutStream ) ) sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package", - sFileName, false ); + sRelationType, sFileName, false ); return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 ); } diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 4ce76e3..01679d1 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -165,7 +165,7 @@ public: /// Returns the relationd id OString OutputChart( com::sun::star::uno::Reference< com::sun::star::frame::XModel >& xModel, sal_Int32 nCount, ::sax_fastparser::FSHelperPtr m_pSerializer ); - OString WriteOLENode( const SwOLENode& rNode ); + OString WriteOLEObject( SwOLEObj& rObject, OUString sMediaType, OUString sRelationType ); bool lcl_CopyStream( css::uno::Reference< css::io::XInputStream> xIn, css::uno::Reference< css::io::XOutputStream > xOut ); /// Writes the shape using drawingML syntax. diff --git a/writerfilter/source/dmapper/OLEHandler.cxx b/writerfilter/source/dmapper/OLEHandler.cxx index f9487e2..fb49aa4 100644 --- a/writerfilter/source/dmapper/OLEHandler.cxx +++ b/writerfilter/source/dmapper/OLEHandler.cxx @@ -20,6 +20,7 @@ #include <PropertyMap.hxx> #include "GraphicHelpers.hxx" +#include <editeng/unoprnms.hxx> #include <ooxml/resourceids.hxx> #include <rtl/ustring.hxx> #include <com/sun/star/beans/PropertyValue.hpp> @@ -170,6 +171,48 @@ void OLEHandler::lcl_sprm(Sprm & rSprm) } +void OLEHandler::saveInteropProperties( uno::Reference< text::XTextDocument > xTextDocument, OUString sObjectName ) +{ + const OUString sGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; + const OUString sEmbeddingsPropName = "EmbeddedObjects"; + + // get interop grab bag from document + uno::Reference< beans::XPropertySet > xDocProps( xTextDocument, uno::UNO_QUERY ); + uno::Sequence< beans::PropertyValue > aGrabBag; + xDocProps->getPropertyValue( sGrabBagPropName ) >>= aGrabBag; + + // get EmbeddedObjects property inside grab bag + sal_Int32 i = 0; + sal_Int32 nBagLength = aGrabBag.getLength(); + uno::Sequence< beans::PropertyValue > objectsList; + for( ; i < nBagLength; ++i ) + if ( aGrabBag[i].Name == sEmbeddingsPropName ) + { + aGrabBag[i].Value >>= objectsList; + break; + } + + // save ProgID of current object + sal_Int32 length = objectsList.getLength(); + objectsList.realloc( length + 1 ); + objectsList[length].Name = sObjectName; + objectsList[length].Value = uno::Any( m_sProgId ); + + // put objects list back into the grab bag + if( i == nBagLength ) + { + aGrabBag.realloc( nBagLength + 1 ); + aGrabBag[nBagLength].Name = sEmbeddingsPropName; + aGrabBag[nBagLength].Value = uno::Any( objectsList ); + } + else + aGrabBag[i].Value = uno::Any( objectsList ); + + // put grab bag back into the document + xDocProps->setPropertyValue( sGrabBagPropName, uno::Any( aGrabBag ) ); +} + + OUString OLEHandler::copyOLEOStream( uno::Reference< text::XTextDocument > xTextDocument ) { OUString sRet; @@ -202,6 +245,8 @@ OUString OLEHandler::copyOLEOStream( uno::Reference< text::XTextDocument > xText } } + saveInteropProperties( xTextDocument, aURL ); + static const OUString sProtocol("vnd.sun.star.EmbeddedObject:"); OUString aPersistName( xEmbeddedResolver->resolveEmbeddedObjectURL( aURL ) ); sRet = aPersistName.copy( sProtocol.getLength() ); diff --git a/writerfilter/source/dmapper/OLEHandler.hxx b/writerfilter/source/dmapper/OLEHandler.hxx index 1416a70..7a76dd0 100644 --- a/writerfilter/source/dmapper/OLEHandler.hxx +++ b/writerfilter/source/dmapper/OLEHandler.hxx @@ -69,6 +69,10 @@ class OLEHandler : public LoggedProperties virtual void lcl_attribute(Id Name, Value & val); virtual void lcl_sprm(Sprm & sprm); + // Interoperability + virtual void saveInteropProperties( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextDocument > xTextDocument, + OUString sObjectName ); + public: OLEHandler(); virtual ~OLEHandler(); commit 72d9fa114ac103698db97ab2946ebbff66d8e21a Author: Jacobo Aragunde Pérez <jaragu...@igalia.com> Date: Wed Feb 26 10:58:33 2014 +0100 sw: code simplification XEmbeddedObject already implements XClassifiedObject which contains a getClassID method. Change-Id: Ifbeed343493208fff3704b21ee484fd92c570974 diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 27304ca..362c1c8 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3506,9 +3506,7 @@ void DocxAttributeOutput::WritePostponedChart() bool DocxAttributeOutput::WriteOLEMath( const SdrObject*, const SwOLENode& rOLENode, const Size& ) { uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef()); - sal_Int64 nAspect = rOLENode.GetAspect(); - svt::EmbeddedObjectRef aObjRef( xObj, nAspect ); - SvGlobalName aObjName(aObjRef->getClassID()); + SvGlobalName aObjName(xObj->getClassID()); if( !SotExchange::IsMath(aObjName) ) return false;
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits