/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/XEmbedPersist.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <comphelper/fileformat.h>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/tempfile.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/flditem.hxx>
#include <svx/svdpagv.hxx>
#include <sfx2/app.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdograf.hxx>
#include <svx/svdotext.hxx>
#include <editeng/outlobj.hxx>
#include <sot/storage.hxx>
#include <svl/itempool.hxx>
#include <editeng/editobj.hxx>
#include <svx/fmglob.hxx>
#include <svx/svdouno.hxx>
#include <sot/formats.hxx>
#include <svl/urlbmk.hxx>
#include <editeng/outliner.hxx>
#include <com/sun/star/form/FormButtonType.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <unotools/streamwrap.hxx>
#include <svx/svdotable.hxx>
#include <svx/unomodel.hxx>
#include <svx/svditer.hxx>
#include <sfx2/docfile.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/servicehelper.hxx>
#include <svtools/embedtransfer.hxx>
#include <DrawDocShell.hxx>
#include <View.hxx>
#include <sdmod.hxx>
#include <sdpage.hxx>
#include <drawview.hxx>
#include <drawdoc.hxx>
#include <stlpool.hxx>
#include <imapinfo.hxx>
#include <sdxfer.hxx>
#include <unomodel.hxx>
#include <vcl/virdev.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::datatransfer;
using namespace ::com::sun::star::datatransfer::clipboard;
constexpr sal_uInt32 SDTRANSFER_OBJECTTYPE_DRAWMODEL = 1;
constexpr sal_uInt32 SDTRANSFER_OBJECTTYPE_DRAWOLE = 2;
SdTransferable::SdTransferable( SdDrawDocument* pSrcDoc, ::sd::View* pWorkView, bool bInitOnGetData )
: mpPageDocShell( nullptr )
, mpSdView( pWorkView )
, mpSdViewIntern( pWorkView )
, mpSdDrawDocument( nullptr )
, mpSdDrawDocumentIntern( nullptr )
, mpSourceDoc( pSrcDoc )
, mpVDev( nullptr )
, mbInternalMove( false )
, mbOwnDocument( false )
, mbOwnView( false )
, mbLateInit( bInitOnGetData )
, mbPageTransferable( false )
, mbPageTransferablePersistent( false )
, maUserData()
{
if( mpSourceDoc )
StartListening( *mpSourceDoc );
if( pWorkView )
StartListening( *pWorkView );
if( !mbLateInit )
CreateData();
}
SdTransferable::~SdTransferable()
{
SolarMutexGuard g;
if( mpSourceDoc )
EndListening( *mpSourceDoc );
if( mpSdView )
EndListening( *const_cast< sd::View *>( mpSdView) );
ObjectReleased();
if( mbOwnView )
delete mpSdViewIntern;
mpOLEDataHelper.reset();
if( maDocShellRef.is() )
{
SfxObjectShell* pObj = maDocShellRef.get();
::sd::DrawDocShell* pDocSh = static_cast< ::sd::DrawDocShell*>(pObj);
pDocSh->DoClose();
}
maDocShellRef.clear();
if( mbOwnDocument )
delete mpSdDrawDocumentIntern;
mpGraphic.reset();
mpBookmark.reset();
mpImageMap.reset();
mpVDev.disposeAndClear();
mpObjDesc.reset();
//call explicitly at end of dtor to be covered by above SolarMutex
maUserData.clear();
}
void SdTransferable::CreateObjectReplacement( SdrObject* pObj )
{
if( pObj )
{
mpOLEDataHelper.reset();
mpGraphic.reset();
mpBookmark.reset();
mpImageMap.reset();
if( nullptr!= dynamic_cast< const SdrOle2Obj* >( pObj ) )
{
try
{
uno::Reference < embed::XEmbeddedObject > xObj = static_cast< SdrOle2Obj* >( pObj )->GetObjRef();
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if( xObj.is() && xPersist.is() && xPersist->hasEntry() )
{
mpOLEDataHelper.reset( new TransferableDataHelper( new SvEmbedTransferHelper( xObj, static_cast< SdrOle2Obj* >( pObj )->GetGraphic(), static_cast< SdrOle2Obj* >( pObj )->GetAspect() ) ) );
// TODO/LATER: the standalone handling of the graphic should not be used any more in future
// The EmbedDataHelper should bring the graphic in future
const Graphic* pObjGr = static_cast< SdrOle2Obj* >( pObj )->GetGraphic();
if ( pObjGr )
mpGraphic.reset( new Graphic( *pObjGr ) );
}
}
catch( uno::Exception& )
{}
}
else if( dynamic_cast< const SdrGrafObj *>( pObj ) != nullptr && (mpSourceDoc && !SdDrawDocument::GetAnimationInfo( pObj )) )
{
mpGraphic.reset( new Graphic( static_cast< SdrGrafObj* >( pObj )->GetTransformedGraphic() ) );
}
else if( pObj->IsUnoObj() && SdrInventor::FmForm == pObj->GetObjInventor() && ( pObj->GetObjIdentifier() == sal_uInt16(OBJ_FM_BUTTON) ) )
{
SdrUnoObj* pUnoCtrl = static_cast< SdrUnoObj* >( pObj );
if (pUnoCtrl && SdrInventor::FmForm == pUnoCtrl->GetObjInventor())
{
Reference< css::awt::XControlModel > xControlModel( pUnoCtrl->GetUnoControlModel() );
if( !xControlModel.is() )
return;
Reference< css::beans::XPropertySet > xPropSet( xControlModel, UNO_QUERY );
if( !xPropSet.is() )
return;
css::form::FormButtonType eButtonType;
Any aTmp( xPropSet->getPropertyValue( "ButtonType" ) );
if( aTmp >>= eButtonType )
{
OUString aLabel, aURL;
xPropSet->getPropertyValue( "Label" ) >>= aLabel;
xPropSet->getPropertyValue( "TargetURL" ) >>= aURL;
mpBookmark.reset( new INetBookmark( aURL, aLabel ) );
}
}
}
else if( dynamic_cast< const SdrTextObj *>( pObj ) != nullptr )
{
const OutlinerParaObject* pPara;
if( (pPara = static_cast< SdrTextObj* >( pObj )->GetOutlinerParaObject()) != nullptr )
{
const SvxFieldItem* pField;
if( (pField = pPara->GetTextObject().GetField()) != nullptr )
{
const SvxFieldData* pData = pField->GetField();
if( auto pURL = dynamic_cast< const SvxURLField *>( pData ) )
{
// #i63399# This special code identifies TextFrames which have just an URL
// as content and directly add this to the clipboard, probably to avoid adding
// an unnecessary DrawObject to the target where paste may take place. This is
// wanted only for SdrObjects with no fill and no line, else it is necessary to
// use the whole SdrObect. Test here for Line/FillStyle and take shortcut only
// when both are unused
if(!pObj->HasFillStyle() && !pObj->HasLineStyle())
{
mpBookmark.reset( new INetBookmark( pURL->GetURL(), pURL->GetRepresentation() ) );
}
}
}
}
}
SdIMapInfo* pInfo = SdDrawDocument::GetIMapInfo( pObj );
if( pInfo )
mpImageMap.reset( new ImageMap( pInfo->GetImageMap() ) );
}
}
void SdTransferable::CreateData()
{
if( mpSdDrawDocument && !mpSdViewIntern )
{
mbOwnView = true;
SdPage* pPage = mpSdDrawDocument->GetSdPage(0, PageKind::Standard);
if( 1 == pPage->GetObjCount() )
CreateObjectReplacement( pPage->GetObj( 0 ) );
mpVDev = VclPtr<VirtualDevice>::Create( *Application::GetDefaultDevice() );
mpVDev->SetMapMode( MapMode( mpSdDrawDocumentIntern->GetScaleUnit(), Point(), mpSdDrawDocumentIntern->GetScaleFraction(), mpSdDrawDocumentIntern->GetScaleFraction() ) );
mpSdViewIntern = new ::sd::View( *mpSdDrawDocumentIntern, mpVDev );
mpSdViewIntern->EndListening(*mpSdDrawDocumentIntern );
mpSdViewIntern->hideMarkHandles();
SdrPageView* pPageView = mpSdViewIntern->ShowSdrPage(pPage);
mpSdViewIntern->MarkAllObj(pPageView);
}
else if( mpSdView && !mpSdDrawDocumentIntern )
{
const SdrMarkList& rMarkList = mpSdView->GetMarkedObjectList();
if( rMarkList.GetMarkCount() == 1 )
CreateObjectReplacement( rMarkList.GetMark( 0 )->GetMarkedSdrObj() );
if( mpSourceDoc )
mpSourceDoc->CreatingDataObj(this);
mpSdDrawDocumentIntern = static_cast<SdDrawDocument*>( mpSdView->CreateMarkedObjModel().release() );
if( mpSourceDoc )
mpSourceDoc->CreatingDataObj(nullptr);
if( !maDocShellRef.is() && mpSdDrawDocumentIntern->GetDocSh() )
maDocShellRef = mpSdDrawDocumentIntern->GetDocSh();
if( !maDocShellRef.is() )
{
OSL_FAIL( "SdTransferable::CreateData(), failed to create a model with persist, clipboard operation will fail for OLE objects!" );
mbOwnDocument = true;
}
// Use dimension of source page
SdrPageView* pPgView = mpSdView->GetSdrPageView();
SdPage* pOldPage = static_cast<SdPage*>( pPgView->GetPage() );
SdrModel* pOldModel = mpSdView->GetModel();
SdStyleSheetPool* pOldStylePool = static_cast<SdStyleSheetPool*>( pOldModel->GetStyleSheetPool() );
SdStyleSheetPool* pNewStylePool = static_cast<SdStyleSheetPool*>( mpSdDrawDocumentIntern->GetStyleSheetPool() );
SdPage* pPage = mpSdDrawDocumentIntern->GetSdPage( 0, PageKind::Standard );
OUString aOldLayoutName( pOldPage->GetLayoutName() );
pPage->SetSize( pOldPage->GetSize() );
pPage->SetLayoutName( aOldLayoutName );
pNewStylePool->CopyGraphicSheets( *pOldStylePool );
pNewStylePool->CopyCellSheets( *pOldStylePool );
pNewStylePool->CopyTableStyles( *pOldStylePool );
sal_Int32 nPos = aOldLayoutName.indexOf( SD_LT_SEPARATOR );
if( nPos != -1 )
aOldLayoutName = aOldLayoutName.copy( 0, nPos );
StyleSheetCopyResultVector aCreatedSheets;
pNewStylePool->CopyLayoutSheets( aOldLayoutName, *pOldStylePool, aCreatedSheets );
}
// set VisArea and adjust objects if necessary
if( maVisArea.IsEmpty() &&
mpSdDrawDocumentIntern && mpSdViewIntern &&
mpSdDrawDocumentIntern->GetPageCount() )
{
SdPage* pPage = mpSdDrawDocumentIntern->GetSdPage( 0, PageKind::Standard );
if( 1 == mpSdDrawDocumentIntern->GetPageCount() )
{
// #112978# need to use GetAllMarkedBoundRect instead of GetAllMarkedRect to get
// fat lines correctly
Point aOrigin( ( maVisArea = mpSdViewIntern->GetAllMarkedBoundRect() ).TopLeft() );
Size aVector( -aOrigin.X(), -aOrigin.Y() );
for( size_t nObj = 0, nObjCount = pPage->GetObjCount(); nObj < nObjCount; ++nObj )
{
SdrObject* pObj = pPage->GetObj( nObj );
pObj->NbcMove( aVector );
}
}
else
maVisArea.SetSize( pPage->GetSize() );
// output is at the zero point
maVisArea.SetPos( Point() );
}
}
static bool lcl_HasOnlyControls( SdrModel* pModel )
{
bool bOnlyControls = false; // default if there are no objects
if ( pModel )
{
SdrPage* pPage = pModel->GetPage(0);
if (pPage)
{
SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
SdrObject* pObj = aIter.Next();
if ( pObj )
{
bOnlyControls = true; // only set if there are any objects at all
while ( pObj )
{
if (dynamic_cast< const SdrUnoObj *>( pObj ) == nullptr)
{
bOnlyControls = false;
break;
}
pObj = aIter.Next();
}
}
}
}
return bOnlyControls;
}
static bool lcl_HasOnlyOneTable( SdrModel* pModel )
{
if ( pModel )
{
SdrPage* pPage = pModel->GetPage(0);
if (pPage && pPage->GetObjCount() == 1 )
{
if( dynamic_cast< sdr::table::SdrTableObj* >( pPage->GetObj(0) ) != nullptr )
return true;
}
}
return false;
}
void SdTransferable::AddSupportedFormats()
{
if( !mbPageTransferable || mbPageTransferablePersistent )
{
if( !mbLateInit )
CreateData();
if( mpObjDesc )
AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
if( mpOLEDataHelper )
{
AddFormat( SotClipboardFormatId::EMBED_SOURCE );
DataFlavorExVector aVector( mpOLEDataHelper->GetDataFlavorExVector() );
DataFlavorExVector::iterator aIter( aVector.begin() ), aEnd( aVector.end() );
while( aIter != aEnd )
AddFormat( *aIter++ );
}
else if( mpGraphic )
{
// #i25616#
AddFormat( SotClipboardFormatId::DRAWING );
AddFormat( SotClipboardFormatId::SVXB );
if( mpGraphic->GetType() == GraphicType::Bitmap )
{
AddFormat( SotClipboardFormatId::PNG );
AddFormat( SotClipboardFormatId::BITMAP );
AddFormat( SotClipboardFormatId::GDIMETAFILE );
}
else
{
AddFormat( SotClipboardFormatId::GDIMETAFILE );
AddFormat( SotClipboardFormatId::PNG );
AddFormat( SotClipboardFormatId::BITMAP );
}
}
else if( mpBookmark )
{
AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
AddFormat( SotClipboardFormatId::STRING );
}
else
{
AddFormat( SotClipboardFormatId::EMBED_SOURCE );
AddFormat( SotClipboardFormatId::DRAWING );
if( !mpSdDrawDocument || !lcl_HasOnlyControls( mpSdDrawDocument ) )
{
AddFormat( SotClipboardFormatId::GDIMETAFILE );
AddFormat( SotClipboardFormatId::PNG );
AddFormat( SotClipboardFormatId::BITMAP );
}
if( lcl_HasOnlyOneTable( mpSdDrawDocument ) ) {
AddFormat( SotClipboardFormatId::RTF );
AddFormat( SotClipboardFormatId::RICHTEXT );
}
}
if( mpImageMap )
AddFormat( SotClipboardFormatId::SVIM );
}
}
bool SdTransferable::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
{
if (SD_MOD()==nullptr)
return false;
SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
bool bOK = false;
CreateData();
if( nFormat == SotClipboardFormatId::RTF && lcl_HasOnlyOneTable( mpSdDrawDocument ) )
{
bOK = SetTableRTF( mpSdDrawDocument );
}
else if( mpOLEDataHelper && mpOLEDataHelper->HasFormat( rFlavor ) )
{
SdrSwapGraphicsMode nOldSwapMode(SdrSwapGraphicsMode::DEFAULT);
if( mpSdDrawDocumentIntern )
{
nOldSwapMode = mpSdDrawDocumentIntern->GetSwapGraphicsMode();
mpSdDrawDocumentIntern->SetSwapGraphicsMode( SdrSwapGraphicsMode::PURGE );
}
// TODO/LATER: support all the graphical formats, the embedded object scenario should not have separated handling
if( nFormat == SotClipboardFormatId::GDIMETAFILE && mpGraphic )
bOK = SetGDIMetaFile( mpGraphic->GetGDIMetaFile() );
else
bOK = SetAny( mpOLEDataHelper->GetAny(rFlavor, rDestDoc) );
if( mpSdDrawDocumentIntern )
mpSdDrawDocumentIntern->SetSwapGraphicsMode( nOldSwapMode );
}
else if( HasFormat( nFormat ) )
{
if( ( nFormat == SotClipboardFormatId::LINKSRCDESCRIPTOR || nFormat == SotClipboardFormatId::OBJECTDESCRIPTOR ) && mpObjDesc )
{
bOK = SetTransferableObjectDescriptor( *mpObjDesc );
}
else if( nFormat == SotClipboardFormatId::DRAWING )
{
SfxObjectShellRef aOldRef( maDocShellRef );
maDocShellRef.clear();
if( mpSdViewIntern )
{
SdDrawDocument& rInternDoc = mpSdViewIntern->GetDoc();
rInternDoc.CreatingDataObj(this);
SdDrawDocument* pDoc = dynamic_cast< SdDrawDocument* >( mpSdViewIntern->CreateMarkedObjModel().release() );
rInternDoc.CreatingDataObj(nullptr);
bOK = SetObject( pDoc, SDTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor );
if( maDocShellRef.is() )
{
maDocShellRef->DoClose();
}
else
{
delete pDoc;
}
}
maDocShellRef = aOldRef;
}
else if( nFormat == SotClipboardFormatId::GDIMETAFILE )
{
if (mpSdViewIntern)
{
const bool bToggleOnlineSpell = mpSdDrawDocumentIntern && mpSdDrawDocumentIntern->GetOnlineSpell();
if (bToggleOnlineSpell)
mpSdDrawDocumentIntern->SetOnlineSpell(false);
bOK = SetGDIMetaFile( mpSdViewIntern->GetMarkedObjMetaFile( true ) );
if (bToggleOnlineSpell)
mpSdDrawDocumentIntern->SetOnlineSpell(true);
}
}
else if( SotClipboardFormatId::BITMAP == nFormat || SotClipboardFormatId::PNG == nFormat )
{
if (mpSdViewIntern)
{
const bool bToggleOnlineSpell = mpSdDrawDocumentIntern && mpSdDrawDocumentIntern->GetOnlineSpell();
if (bToggleOnlineSpell)
mpSdDrawDocumentIntern->SetOnlineSpell(false);
bOK = SetBitmapEx( mpSdViewIntern->GetMarkedObjBitmapEx(true), rFlavor );
if (bToggleOnlineSpell)
mpSdDrawDocumentIntern->SetOnlineSpell(true);
}
}
else if( ( nFormat == SotClipboardFormatId::STRING ) && mpBookmark )
{
bOK = SetString( mpBookmark->GetURL(), rFlavor );
}
else if( ( nFormat == SotClipboardFormatId::SVXB ) && mpGraphic )
{
bOK = SetGraphic( *mpGraphic );
}
else if( ( nFormat == SotClipboardFormatId::SVIM ) && mpImageMap )
{
bOK = SetImageMap( *mpImageMap );
}
else if( mpBookmark )
{
bOK = SetINetBookmark( *mpBookmark, rFlavor );
}
else if( nFormat == SotClipboardFormatId::EMBED_SOURCE )
{
if( mpSdDrawDocumentIntern )
{
SdrSwapGraphicsMode nOldSwapMode = mpSdDrawDocumentIntern->GetSwapGraphicsMode();
mpSdDrawDocumentIntern->SetSwapGraphicsMode( SdrSwapGraphicsMode::PURGE );
if( !maDocShellRef.is() )
{
maDocShellRef = new ::sd::DrawDocShell(
mpSdDrawDocumentIntern,
SfxObjectCreateMode::EMBEDDED,
true,
mpSdDrawDocumentIntern->GetDocumentType());
mbOwnDocument = false;
maDocShellRef->DoInitNew();
}
maDocShellRef->SetVisArea( maVisArea );
bOK = SetObject( maDocShellRef.get(), SDTRANSFER_OBJECTTYPE_DRAWOLE, rFlavor );
mpSdDrawDocumentIntern->SetSwapGraphicsMode( nOldSwapMode );
}
}
}
return bOK;
}
bool SdTransferable::WriteObject( tools::SvRef<SotStorageStream>& rxOStm, void* pObject, sal_uInt32 nObjectType, const DataFlavor& )
{
bool bRet = false;
switch( nObjectType )
{
case SDTRANSFER_OBJECTTYPE_DRAWMODEL:
{
try
{
static const bool bDontBurnInStyleSheet = ( getenv( "AVOID_BURN_IN_FOR_GALLERY_THEME" ) != nullptr );
SdDrawDocument* pDoc = static_cast<SdDrawDocument*>(pObject);
if ( !bDontBurnInStyleSheet )
pDoc->BurnInStyleSheetAttributes();
rxOStm->SetBufferSize( 16348 );
Reference< XComponent > xComponent( new SdXImpressDocument( pDoc, true ) );
pDoc->setUnoModel( Reference< XInterface >::query( xComponent ) );
{
css::uno::Reference<css::io::XOutputStream> xDocOut( new utl::OOutputStreamWrapper( *rxOStm ) );
if( SvxDrawingLayerExport( pDoc, xDocOut, xComponent, (pDoc->GetDocumentType() == DocumentType::Impress) ? "com.sun.star.comp.Impress.XMLClipboardExporter" : "com.sun.star.comp.DrawingLayer.XMLExporter" ) )
rxOStm->Commit();
}
xComponent->dispose();
bRet = ( rxOStm->GetError() == ERRCODE_NONE );
}
catch( Exception& )
{
OSL_FAIL( "sd::SdTransferable::WriteObject(), exception caught!" );
bRet = false;
}
}
break;
case SDTRANSFER_OBJECTTYPE_DRAWOLE:
{
SfxObjectShell* pEmbObj = static_cast<SfxObjectShell*>(pObject);
::utl::TempFile aTempFile;
aTempFile.EnableKillingFile();
try
{
uno::Reference< embed::XStorage > xWorkStore =
::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
// write document storage
pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
// mba: no relative URLs for clipboard!
SfxMedium aMedium( xWorkStore, OUString() );
bRet = pEmbObj->DoSaveObjectAs( aMedium, false );
pEmbObj->DoSaveCompleted();
uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
if ( xTransact.is() )
xTransact->commit();
std::unique_ptr<SvStream> pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ );
if( pSrcStm )
{
rxOStm->SetBufferSize( 0xff00 );
rxOStm->WriteStream( *pSrcStm );
pSrcStm.reset();
}
bRet = true;
rxOStm->Commit();
}
catch ( Exception& )
{}
}
break;
default:
break;
}
return bRet;
}
void SdTransferable::DragFinished( sal_Int8 nDropAction )
{
if( mpSdView )
const_cast< ::sd::View* >(mpSdView)->DragFinished( nDropAction );
}
void SdTransferable::ObjectReleased()
{
if( this == SD_MOD()->pTransferClip )
SD_MOD()->pTransferClip = nullptr;
if( this == SD_MOD()->pTransferDrag )
SD_MOD()->pTransferDrag = nullptr;
if( this == SD_MOD()->pTransferSelection )
SD_MOD()->pTransferSelection = nullptr;
}
void SdTransferable::SetObjectDescriptor( std::unique_ptr<TransferableObjectDescriptor> pObjDesc )
{
mpObjDesc = std::move(pObjDesc);
PrepareOLE( *mpObjDesc );
}
void SdTransferable::SetPageBookmarks( const std::vector<OUString> &rPageBookmarks, bool bPersistent )
{
if( mpSourceDoc )
{
if( mpSdViewIntern )
mpSdViewIntern->HideSdrPage();
mpSdDrawDocument->ClearModel(false);
mpPageDocShell = nullptr;
maPageBookmarks.clear();
if( bPersistent )
{
mpSdDrawDocument->CreateFirstPages(mpSourceDoc);
mpSdDrawDocument->InsertBookmarkAsPage( rPageBookmarks, nullptr, false, true, 1, true,
mpSourceDoc->GetDocSh(), true, true, false );
}
else
{
mpPageDocShell = mpSourceDoc->GetDocSh();
maPageBookmarks = rPageBookmarks;
}
if( mpSdViewIntern )
{
SdPage* pPage = mpSdDrawDocument->GetSdPage( 0, PageKind::Standard );
if( pPage )
{
mpSdViewIntern->MarkAllObj( mpSdViewIntern->ShowSdrPage( pPage ) );
}
}
// set flags for page transferable; if ( mbPageTransferablePersistent == sal_False ),
// don't offer any formats => it's just for internal purposes
mbPageTransferable = true;
mbPageTransferablePersistent = bPersistent;
}
}
sal_Int64 SAL_CALL SdTransferable::getSomething( const css::uno::Sequence< sal_Int8 >& rId )
{
sal_Int64 nRet;
if( ( rId.getLength() == 16 ) &&
( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
{
nRet = sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
}
else
{
nRet = 0;
}
return nRet;
}
void SdTransferable::AddUserData (const std::shared_ptr<UserData>& rpData)
{
maUserData.push_back(rpData);
}
sal_Int32 SdTransferable::GetUserDataCount() const
{
return maUserData.size();
}
std::shared_ptr<SdTransferable::UserData> SdTransferable::GetUserData (const sal_Int32 nIndex) const
{
if (nIndex>=0 && nIndex<sal_Int32(maUserData.size()))
return maUserData[nIndex];
else
return std::shared_ptr<UserData>();
}
namespace
{
class theSdTransferableUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSdTransferableUnoTunnelId > {};
}
const css::uno::Sequence< sal_Int8 >& SdTransferable::getUnoTunnelId()
{
return theSdTransferableUnoTunnelId::get().getSeq();
}
SdTransferable* SdTransferable::getImplementation( const Reference< XInterface >& rxData ) throw()
{
try
{
Reference< css::lang::XUnoTunnel > xUnoTunnel( rxData, UNO_QUERY_THROW );
return reinterpret_cast<SdTransferable*>(sal::static_int_cast<sal_uIntPtr>(xUnoTunnel->getSomething( SdTransferable::getUnoTunnelId()) ) );
}
catch( const css::uno::Exception& )
{
}
return nullptr;
}
void SdTransferable::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
const SdrHint* pSdrHint = dynamic_cast< const SdrHint* >( &rHint );
if( pSdrHint )
{
if( SdrHintKind::ModelCleared == pSdrHint->GetKind() )
{
EndListening(*mpSourceDoc);
mpSourceDoc = nullptr;
}
}
else
{
if( rHint.GetId() == SfxHintId::Dying )
{
if( &rBC == mpSourceDoc )
mpSourceDoc = nullptr;
if( &rBC == mpSdViewIntern )
mpSdViewIntern = nullptr;
if( &rBC == mpSdView )
mpSdView = nullptr;
}
}
}
void SdTransferable::SetView(const ::sd::View* pView)
{
if (mpSdView)
EndListening(*const_cast<sd::View*>(mpSdView));
mpSdView = pView;
if (mpSdView)
StartListening(*const_cast<sd::View*>(mpSdView));
}
bool SdTransferable::SetTableRTF( SdDrawDocument* pModel )
{
if ( pModel )
{
SdrPage* pPage = pModel->GetPage(0);
if (pPage && pPage->GetObjCount() == 1 )
{
sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pPage->GetObj(0) );
if( pTableObj )
{
SvMemoryStream aMemStm( 65535, 65535 );
sdr::table::SdrTableObj::ExportAsRTF( aMemStm, *pTableObj );
return SetAny( Any( Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) ) ) );
}
}
}
return false;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V560 A part of conditional expression is always true: pUnoCtrl.
↑ V519 The 'bRet' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 629, 644.