1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/XEmbeddedObject.hpp>
21 #include <com/sun/star/embed/XEmbedPersist.hpp>
22 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
23 #include <com/sun/star/datatransfer/XTransferable.hpp>
24 #include <com/sun/star/embed/Aspects.hpp>
25 #include <osl/diagnose.h>
26 #include <sot/exchange.hxx>
27 #include <svtools/embedtransfer.hxx>
28 #include <tools/mapunit.hxx>
29 #include <vcl/outdev.hxx>
30 #include <vcl/filter/SvmWriter.hxx>
31 #include <vcl/gdimtf.hxx>
32 #include <comphelper/fileformat.h>
33 #include <comphelper/propertysequence.hxx>
34 #include <comphelper/storagehelper.hxx>
35 #include <unotools/ucbstreamhelper.hxx>
36 #include <unotools/streamwrap.hxx>
37 #include <unotools/tempfile.hxx>
38 #include <toolkit/helper/vclunohelper.hxx>
40 #include <svtools/embedhlp.hxx>
42 using namespace ::com::sun::star
;
44 SvEmbedTransferHelper::SvEmbedTransferHelper( const uno::Reference
< embed::XEmbeddedObject
>& xObj
,
45 const Graphic
* pGraphic
,
48 , m_nAspect( nAspect
)
51 m_oGraphic
.emplace(*pGraphic
);
54 TransferableObjectDescriptor aObjDesc
;
56 FillTransferableObjectDescriptor( aObjDesc
, m_xObj
, nullptr, m_nAspect
);
57 PrepareOLE( aObjDesc
);
62 SvEmbedTransferHelper::~SvEmbedTransferHelper()
66 void SvEmbedTransferHelper::SetParentShellID( const OUString
& rShellID
)
68 maParentShellID
= rShellID
;
72 void SvEmbedTransferHelper::AddSupportedFormats()
74 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
75 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
76 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
77 AddFormat( SotClipboardFormatId::BITMAP
);
81 bool SvEmbedTransferHelper::GetData( const css::datatransfer::DataFlavor
& rFlavor
, const OUString
& rDestDoc
)
89 SotClipboardFormatId nFormat
= SotExchange::GetFormat( rFlavor
);
90 if( HasFormat( nFormat
) )
92 if( nFormat
== SotClipboardFormatId::OBJECTDESCRIPTOR
)
94 TransferableObjectDescriptor aDesc
;
95 FillTransferableObjectDescriptor( aDesc
, m_xObj
, m_oGraphic
? &*m_oGraphic
: nullptr, m_nAspect
);
96 bRet
= SetTransferableObjectDescriptor( aDesc
);
98 else if( nFormat
== SotClipboardFormatId::EMBED_SOURCE
)
102 // TODO/LATER: Probably the graphic should be copied here as well
103 // currently it is handled by the applications
104 utl::TempFileFast aTmp
;
105 uno::Reference
< embed::XEmbedPersist
> xPers( m_xObj
, uno::UNO_QUERY
);
108 uno::Reference
< embed::XStorage
> xStg
= comphelper::OStorageHelper::GetTemporaryStorage();
109 OUString
aName( u
"Dummy"_ustr
);
110 SvStream
* pStream
= nullptr;
111 bool bDeleteStream
= false;
112 uno::Sequence
< beans::PropertyValue
> aEmpty
;
113 uno::Sequence
<beans::PropertyValue
> aObjArgs( comphelper::InitPropertySequence({
114 { "SourceShellID", uno::Any(maParentShellID
) },
115 { "DestinationShellID", uno::Any(rDestDoc
) }
117 xPers
->storeToEntry(xStg
, aName
, aEmpty
, aObjArgs
);
118 if ( xStg
->isStreamElement( aName
) )
120 uno::Reference
< io::XStream
> xStm
= xStg
->cloneStreamElement( aName
);
121 pStream
= utl::UcbStreamHelper::CreateStream( xStm
).release();
122 bDeleteStream
= true;
126 pStream
= aTmp
.GetStream( StreamMode::STD_READWRITE
);
127 uno::Reference
< embed::XStorage
> xStor
= comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper( *pStream
) );
128 xStg
->openStorageElement( aName
, embed::ElementModes::READ
)->copyToStorage( xStor
);
131 const sal_uInt32 nLen
= pStream
->TellEnd();
132 css::uno::Sequence
< sal_Int8
> aSeq( nLen
);
134 pStream
->Seek( STREAM_SEEK_TO_BEGIN
);
135 pStream
->ReadBytes(aSeq
.getArray(), nLen
);
139 bRet
= aSeq
.hasElements();
142 SetAny( uno::Any(aSeq
) );
147 //TODO/LATER: how to handle objects without persistence?!
150 catch ( uno::Exception
& )
154 else if ( nFormat
== SotClipboardFormatId::GDIMETAFILE
&& m_oGraphic
)
156 SvMemoryStream
aMemStm( 65535, 65535 );
157 aMemStm
.SetVersion( SOFFICE_FILEFORMAT_CURRENT
);
159 const GDIMetaFile
& aMetaFile
= m_oGraphic
->GetGDIMetaFile();
160 SvmWriter
aWriter( aMemStm
);
161 aWriter
.Write( aMetaFile
);
163 aAny
<<= uno::Sequence
< sal_Int8
>( static_cast< const sal_Int8
* >( aMemStm
.GetData() ),
168 else if ( ( nFormat
== SotClipboardFormatId::BITMAP
|| nFormat
== SotClipboardFormatId::PNG
) && m_oGraphic
)
170 bRet
= SetBitmapEx( m_oGraphic
->GetBitmapEx(), rFlavor
);
172 else if ( m_xObj
.is() && ::svt::EmbeddedObjectRef::TryRunningState( m_xObj
) )
174 uno::Reference
< datatransfer::XTransferable
> xTransferable( m_xObj
->getComponent(), uno::UNO_QUERY
);
175 if ( xTransferable
.is() )
177 uno::Any aAny
= xTransferable
->getTransferData( rFlavor
);
184 catch( uno::Exception
& )
194 void SvEmbedTransferHelper::ObjectReleased()
199 void SvEmbedTransferHelper::FillTransferableObjectDescriptor( TransferableObjectDescriptor
& rDesc
,
200 const css::uno::Reference
< css::embed::XEmbeddedObject
>& xObj
,
201 const Graphic
* pGraphic
,
204 //TODO/LATER: need TypeName to fill it into the Descriptor (will be shown in listbox)
205 css::datatransfer::DataFlavor aFlavor
;
206 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::OBJECTDESCRIPTOR
, aFlavor
);
208 rDesc
.maClassName
= SvGlobalName( xObj
->getClassID() );
209 rDesc
.maTypeName
= aFlavor
.HumanPresentableName
;
211 //TODO/LATER: the aspect size in the descriptor is wrong, unfortunately the stream
212 // representation of the descriptor allows only 4 bytes for the aspect
213 // so for internal transport something different should be found
214 rDesc
.mnViewAspect
= sal::static_int_cast
<sal_uInt16
>( nAspect
);
217 MapMode
aMapMode( MapUnit::Map100thMM
);
218 if ( nAspect
== embed::Aspects::MSOLE_ICON
)
222 aMapMode
= pGraphic
->GetPrefMapMode();
223 aSize
= pGraphic
->GetPrefSize();
226 aSize
= Size( 2500, 2500 );
232 awt::Size aSz
= xObj
->getVisualAreaSize( rDesc
.mnViewAspect
);
233 aSize
= Size( aSz
.Width
, aSz
.Height
);
235 catch( embed::NoVisualAreaSizeException
& )
237 OSL_FAIL( "Can not get visual area size!" );
238 aSize
= Size( 5000, 5000 );
241 // TODO/LEAN: getMapUnit can switch object to running state
242 aMapMode
= MapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( rDesc
.mnViewAspect
) ) );
245 rDesc
.maSize
= OutputDevice::LogicToLogic( aSize
, aMapMode
, MapMode( MapUnit::Map100thMM
) );
246 rDesc
.maDragStartPos
= Point();
247 rDesc
.maDisplayName
.clear();
250 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */