/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sd { using namespace ::com::sun::star; namespace { struct SdNavigatorDropEvent : public ExecuteDropEvent { VclPtr< ::sd::Window> mpTargetWindow; SdNavigatorDropEvent ( const ExecuteDropEvent& rEvt, ::sd::Window* pTargetWindow ) : ExecuteDropEvent( rEvt ), mpTargetWindow( pTargetWindow ) {} }; } css::uno::Reference< css::datatransfer::XTransferable > View::CreateClipboardDataObject() { // since SdTransferable::CopyToClipboard is called, this // dynamically created object is destroyed automatically rtl::Reference pTransferable = new SdTransferable( &mrDoc, nullptr, false ); SD_MOD()->pTransferClip = pTransferable.get(); mrDoc.CreatingDataObj( pTransferable.get() ); pTransferable->SetWorkDocument( static_cast(CreateMarkedObjModel().release()) ); mrDoc.CreatingDataObj( nullptr ); // #112978# need to use GetAllMarkedBoundRect instead of GetAllMarkedRect to get // fat lines correctly const ::tools::Rectangle aMarkRect( GetAllMarkedBoundRect() ); std::unique_ptr pObjDesc(new TransferableObjectDescriptor); SdrOle2Obj* pSdrOleObj = nullptr; SdrPageView* pPgView = GetSdrPageView(); SdPage* pOldPage = pPgView ? static_cast( pPgView->GetPage() ) : nullptr; SdPage* pNewPage = const_cast(static_cast( pTransferable->GetWorkDocument()->GetPage( 0 ) )); if( pOldPage ) { pNewPage->SetSize( pOldPage->GetSize() ); pNewPage->SetLayoutName( pOldPage->GetLayoutName() ); } if( GetMarkedObjectCount() == 1 ) { SdrObject* pObj = GetMarkedObjectByIndex(0); if( auto pOle2Obj = dynamic_cast( pObj ) ) if( pOle2Obj->GetObjRef() ) { // If object has no persistence it must be copied as part of the document try { uno::Reference< embed::XEmbedPersist > xPersObj( pOle2Obj->GetObjRef(), uno::UNO_QUERY ); if ( xPersObj.is() && xPersObj->hasEntry() ) pSdrOleObj = pOle2Obj; } catch( uno::Exception& ) {} } } if( pSdrOleObj ) SvEmbedTransferHelper::FillTransferableObjectDescriptor( *pObjDesc, pSdrOleObj->GetObjRef(), pSdrOleObj->GetGraphic(), pSdrOleObj->GetAspect() ); else pTransferable->GetWorkDocument()->GetDocSh()->FillTransferableObjectDescriptor( *pObjDesc ); if( mpDocSh ) pObjDesc->maDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass(); pObjDesc->maSize = aMarkRect.GetSize(); pTransferable->SetStartPos( aMarkRect.TopLeft() ); pTransferable->SetObjectDescriptor( std::move(pObjDesc) ); pTransferable->CopyToClipboard( mpViewSh->GetActiveWindow() ); return pTransferable; } css::uno::Reference< css::datatransfer::XTransferable > View::CreateDragDataObject( View* pWorkView, vcl::Window& rWindow, const Point& rDragPos ) { rtl::Reference pTransferable = new SdTransferable( &mrDoc, pWorkView, false ); SD_MOD()->pTransferDrag = pTransferable.get(); std::unique_ptr pObjDesc(new TransferableObjectDescriptor); OUString aDisplayName; SdrOle2Obj* pSdrOleObj = nullptr; if( GetMarkedObjectCount() == 1 ) { SdrObject* pObj = GetMarkedObjectByIndex( 0 ); if( auto pOle2Obj = dynamic_cast( pObj ) ) if( pOle2Obj->GetObjRef() ) { // If object has no persistence it must be copied as part of the document try { uno::Reference< embed::XEmbedPersist > xPersObj( pOle2Obj->GetObjRef(), uno::UNO_QUERY ); if ( xPersObj.is() && xPersObj->hasEntry() ) pSdrOleObj = pOle2Obj; } catch( uno::Exception& ) {} } } if( mpDocSh ) aDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass(); if( pSdrOleObj ) SvEmbedTransferHelper::FillTransferableObjectDescriptor( *pObjDesc, pSdrOleObj->GetObjRef(), pSdrOleObj->GetGraphic(), pSdrOleObj->GetAspect() ); else if (mpDocSh) mpDocSh->FillTransferableObjectDescriptor( *pObjDesc ); pObjDesc->maSize = GetAllMarkedRect().GetSize(); pObjDesc->maDragStartPos = rDragPos; pObjDesc->maDisplayName = aDisplayName; pTransferable->SetStartPos( rDragPos ); pTransferable->SetObjectDescriptor( std::move(pObjDesc) ); pTransferable->StartDrag( &rWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK ); return pTransferable; } css::uno::Reference< css::datatransfer::XTransferable > View::CreateSelectionDataObject( View* pWorkView ) { rtl::Reference pTransferable = new SdTransferable( &mrDoc, pWorkView, true ); std::unique_ptr pObjDesc(new TransferableObjectDescriptor); const ::tools::Rectangle aMarkRect( GetAllMarkedRect() ); SD_MOD()->pTransferSelection = pTransferable.get(); if( mpDocSh ) { mpDocSh->FillTransferableObjectDescriptor( *pObjDesc ); pObjDesc->maDisplayName = mpDocSh->GetMedium()->GetURLObject().GetURLNoPass(); } pObjDesc->maSize = aMarkRect.GetSize(); pTransferable->SetStartPos( aMarkRect.TopLeft() ); pTransferable->SetObjectDescriptor( std::move(pObjDesc) ); pTransferable->CopyToPrimarySelection(); return pTransferable; } void View::UpdateSelectionClipboard() // false case { if (!mpViewSh) return; if (!mpViewSh->GetActiveWindow()) return; if (GetMarkedObjectList().GetMarkCount()) CreateSelectionDataObject( this ); else ClearSelectionClipboard(); } void View::ClearSelectionClipboard() // true case { if (!mpViewSh) return; if (!mpViewSh->GetActiveWindow()) return; if (SD_MOD()->pTransferSelection && SD_MOD()->pTransferSelection->GetView() == this) { TransferableHelper::ClearPrimarySelection(); SD_MOD()->pTransferSelection = nullptr; } } void View::DoCut() { const OutlinerView* pOLV = GetTextEditOutlinerView(); if( pOLV ) const_cast(pOLV)->Cut(); else if( AreObjectsMarked() ) { OUString aStr(SdResId(STR_UNDO_CUT)); DoCopy(); BegUndo(aStr + " " + GetDescriptionOfMarkedObjects()); DeleteMarked(); EndUndo(); } } void View::DoCopy() { const OutlinerView* pOLV = GetTextEditOutlinerView(); if( pOLV ) const_cast(pOLV)->Copy(); else if( AreObjectsMarked() ) { BrkAction(); CreateClipboardDataObject(); } } void View::DoPaste (::sd::Window* pWindow) { TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewSh->GetActiveWindow() ) ); if( !aDataHelper.GetTransferable().is() ) return; // empty clipboard? const OutlinerView* pOLV = GetTextEditOutlinerView(); if( pOLV && EditEngine::HasValidData( aDataHelper.GetTransferable() ) ) { const_cast< OutlinerView* >(pOLV)->PasteSpecial(); SdrObject* pObj = GetTextEditObject(); SdPage* pPage = static_cast( pObj ? pObj->getSdrPageFromSdrObject() : nullptr ); ::Outliner* pOutliner = pOLV->GetOutliner(); if( pOutliner) { if( pObj && pPage && pPage->GetPresObjKind(pObj) == PresObjKind::Title ) { // remove all hard linebreaks from the title if (pOutliner->GetParagraphCount() > 1) { bool bOldUpdateMode = pOutliner->SetUpdateLayout( false ); const EditEngine& rEdit = pOutliner->GetEditEngine(); const sal_Int32 nParaCount = rEdit.GetParagraphCount(); for( sal_Int32 nPara = nParaCount - 2; nPara >= 0; nPara-- ) { const sal_Int32 nParaLen = rEdit.GetTextLen( nPara ); pOutliner->QuickDelete( ESelection( nPara, nParaLen, nPara+1, 0 ) ); pOutliner->QuickInsertLineBreak( ESelection( nPara, nParaLen, nPara, nParaLen ) ); } DBG_ASSERT( rEdit.GetParagraphCount() <= 1, "Titleobject contains hard line breaks" ); pOutliner->SetUpdateLayout(bOldUpdateMode); } } if( !mrDoc.IsChanged() ) { if (pOutliner->IsModified()) mrDoc.SetChanged(); } } } else { Point aPos = pWindow->GetVisibleCenter(); DrawViewShell* pDrViewSh = static_cast( mpDocSh->GetViewShell() ); if (pDrViewSh != nullptr) { sal_Int8 nDnDAction = DND_ACTION_COPY; if( !InsertData( aDataHelper, aPos, nDnDAction, false ) ) { INetBookmark aINetBookmark( "", "" ); if( ( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) || ( aDataHelper.HasFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::FILEGRPDESCRIPTOR, aINetBookmark ) ) || ( aDataHelper.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::UNIFORMRESOURCELOCATOR, aINetBookmark ) ) ) { pDrViewSh->InsertURLField( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), "" ); } } } } } void View::StartDrag( const Point& rStartPos, vcl::Window* pWindow ) { if (!AreObjectsMarked() || !IsAction() || !mpViewSh || !pWindow) return; BrkAction(); if( IsTextEdit() ) SdrEndTextEdit(); if (DrawViewShell* pDrawViewShell = dynamic_cast(mpDocSh ? mpDocSh->GetViewShell() : nullptr)) { const rtl::Reference& xFunction(pDrawViewShell->GetCurrentFunction()); if (FuDraw* pFunction = dynamic_cast(xFunction.get())) pFunction->ForcePointer(); } mpDragSrcMarkList.reset( new SdrMarkList(GetMarkedObjectList()) ); mnDragSrcPgNum = GetSdrPageView()->GetPage()->GetPageNum(); CreateDragDataObject( this, *pWindow, rStartPos ); } void View::DragFinished( sal_Int8 nDropAction ) { const bool bUndo = IsUndoEnabled(); const bool bGroupUndo = bUndo && mpDragSrcMarkList; if (bGroupUndo) { OUString aStr(SdResId(STR_UNDO_DRAGDROP)); BegUndo(aStr + " " + mpDragSrcMarkList->GetMarkDescription()); } SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; if( pDragTransferable ) pDragTransferable->SetView( nullptr ); if( ( nDropAction & DND_ACTION_MOVE ) && pDragTransferable && !pDragTransferable->IsInternalMove() && mpDragSrcMarkList && mpDragSrcMarkList->GetMarkCount() && !IsPresObjSelected() ) { mpDragSrcMarkList->ForceSort(); if( bUndo ) BegUndo(); const size_t nCnt = mpDragSrcMarkList->GetMarkCount(); for( size_t nm = nCnt; nm>0; ) { --nm; SdrMark* pM=mpDragSrcMarkList->GetMark(nm); if( bUndo ) AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeleteObject(*pM->GetMarkedSdrObj())); } mpDragSrcMarkList->GetMark(0)->GetMarkedSdrObj()->GetOrdNum(); for (size_t nm = nCnt; nm>0;) { --nm; SdrMark* pM=mpDragSrcMarkList->GetMark(nm); SdrObject* pObj=pM->GetMarkedSdrObj(); if( pObj && pObj->getSdrPageFromSdrObject() ) { const size_t nOrdNum = pObj->GetOrdNumDirect(); rtl::Reference pChkObj = pObj->getSdrPageFromSdrObject()->RemoveObject(nOrdNum); DBG_ASSERT(pChkObj.get()==pObj,"pChkObj!=pObj in RemoveObject()"); } } if( bUndo ) EndUndo(); } if( pDragTransferable ) pDragTransferable->SetInternalMove( false ); if (bGroupUndo) EndUndo(); mnDragSrcPgNum = SDRPAGE_NOTFOUND; mpDragSrcMarkList.reset(); } sal_Int8 View::AcceptDrop( const AcceptDropEvent& rEvt, DropTargetHelper& rTargetHelper, SdrLayerID nLayer ) { OUString aLayerName = GetActiveLayer(); SdrPageView* pPV = GetSdrPageView(); sal_Int8 nDropAction = rEvt.mnAction; sal_Int8 nRet = DND_ACTION_NONE; if( nLayer != SDRLAYER_NOTFOUND ) { SdrLayerAdmin& rLayerAdmin = mrDoc.GetLayerAdmin(); SdrLayer* pLayer = rLayerAdmin.GetLayerPerID(nLayer); assert(pLayer && "layer missing"); aLayerName = pLayer->GetName(); } if( mbIsDropAllowed && !pPV->IsLayerLocked( aLayerName ) && pPV->IsLayerVisible( aLayerName ) ) { const OutlinerView* pOLV = GetTextEditOutlinerView(); bool bIsInsideOutlinerView = false; if( pOLV ) { ::tools::Rectangle aRect( pOLV->GetOutputArea() ); if (GetMarkedObjectCount() == 1) { SdrMark* pMark = GetSdrMarkByIndex(0); SdrObject* pObj = pMark->GetMarkedSdrObj(); aRect.Union( pObj->GetLogicRect() ); } if( aRect.Contains( pOLV->GetWindow()->PixelToLogic( rEvt.maPosPixel ) ) ) { bIsInsideOutlinerView = true; } } if( !bIsInsideOutlinerView ) { SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; if(pDragTransferable && (nDropAction & DND_ACTION_LINK)) { // suppress own data when it's intention is to use it as fill information pDragTransferable = nullptr; } if( pDragTransferable ) { const View* pSourceView = pDragTransferable->GetView(); if( pDragTransferable->IsPageTransferable() ) { nRet = DND_ACTION_COPY; } else if( pSourceView ) { if( !( nDropAction & DND_ACTION_LINK ) || !pSourceView->GetDocSh()->GetMedium()->GetName().isEmpty() ) { nRet = nDropAction; } } } else { const bool bDrawing = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::DRAWING ); const bool bGraphic = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SVXB ); const bool bMtf = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::GDIMETAFILE ); const bool bBitmap = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::BITMAP ); bool bBookmark = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK ); bool bXFillExchange = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::XFA ); // check handle insert if ((bXFillExchange && (SdrDragMode::Gradient == GetDragMode())) || (SdrDragMode::Transparence == GetDragMode())) { const SdrHdlList& rHdlList = GetHdlList(); for( size_t n = 0; n < rHdlList.GetHdlCount(); ++n ) { SdrHdl* pIAOHandle = rHdlList.GetHdl( n ); if( pIAOHandle && ( SdrHdlKind::Color == pIAOHandle->GetKind() ) ) { if(pIAOHandle->getOverlayObjectList().isHitPixel(rEvt.maPosPixel)) { nRet = nDropAction; static_cast< SdrHdlColor* >( pIAOHandle )->SetSize( SDR_HANDLE_COLOR_SIZE_SELECTED ); } else { static_cast< SdrHdlColor* >( pIAOHandle )->SetSize( SDR_HANDLE_COLOR_SIZE_NORMAL ); } } } } // check object insert if( !nRet && ( bXFillExchange || ( ( bDrawing || bGraphic || bMtf || bBitmap || bBookmark ) && ( nDropAction & DND_ACTION_LINK ) ) ) ) { SdrPageView* pPageView = nullptr; ::sd::Window* pWindow = mpViewSh->GetActiveWindow(); Point aPos( pWindow->PixelToLogic( rEvt.maPosPixel ) ); SdrObject* pPickObj = PickObj(aPos, getHitTolLog(), pPageView); bool bIsPresTarget = false; if (pPickObj && (pPickObj->IsEmptyPresObj() || pPickObj->GetUserCall())) { SdPage* pPage = static_cast( pPickObj->getSdrPageFromSdrObject() ); if( pPage && pPage->IsMasterPage() ) bIsPresTarget = pPage->IsPresObj( pPickObj ); } if (pPickObj && !bIsPresTarget && (bGraphic || bMtf || bBitmap || bXFillExchange)) { if( mpDropMarkerObj != pPickObj ) { mpDropMarkerObj = pPickObj; ImplClearDrawDropMarker(); if(mpDropMarkerObj) { mpDropMarker.reset( new SdrDropMarkerOverlay(*this, *mpDropMarkerObj) ); } } nRet = nDropAction; } else bXFillExchange = false; } // check normal insert if( !nRet ) { const bool bSBAFormat = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SVX_FORMFIELDEXCH ); const bool bEditEngineODF = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ); const bool bString = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::STRING ); const bool bRTF = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::RTF ); const bool bFile = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ); const bool bFileList = rTargetHelper.IsDropFormatSupported( SotClipboardFormatId::FILE_LIST ); if( mpDropMarker ) { ImplClearDrawDropMarker(); mpDropMarkerObj = nullptr; } if( bBookmark && bFile && ( nDropAction & DND_ACTION_MOVE ) && mpViewSh && ( SlideShow::IsRunning(mpViewSh->GetViewShellBase()) && !SlideShow::IsInteractiveSlideshow(&mpViewSh->GetViewShellBase()) )) // IASS bBookmark = false; if( bDrawing || bGraphic || bMtf || bBitmap || bBookmark || bFile || bFileList || bXFillExchange || bSBAFormat || bEditEngineODF || bString || bRTF ) nRet = nDropAction; // For entries from the navigator, change action copy. if (bBookmark && rTargetHelper.IsDropFormatSupported( SdPageObjsTLV::SdPageObjsTransferable::GetListBoxDropFormatId()) && (nDropAction & DND_ACTION_MOVE)!=0) { nRet = DND_ACTION_COPY; } } } } } // destroy drop marker if this is a leaving event if( rEvt.mbLeaving && mpDropMarker ) { ImplClearDrawDropMarker(); mpDropMarkerObj = nullptr; } return nRet; } sal_Int8 View::ExecuteDrop( const ExecuteDropEvent& rEvt, ::sd::Window* pTargetWindow, sal_uInt16 nPage, SdrLayerID nLayer ) { SdrPageView* pPV = GetSdrPageView(); OUString aActiveLayer = GetActiveLayer(); sal_Int8 nDropAction = rEvt.mnAction; sal_Int8 nRet = DND_ACTION_NONE; // destroy drop marker if it is shown if( mpDropMarker ) { ImplClearDrawDropMarker(); mpDropMarkerObj = nullptr; } if( !pPV->IsLayerLocked( aActiveLayer ) ) { const OutlinerView* pOLV = GetTextEditOutlinerView(); bool bIsInsideOutlinerView = false; if( pOLV ) { ::tools::Rectangle aRect( pOLV->GetOutputArea() ); if( GetMarkedObjectCount() == 1 ) { SdrMark* pMark = GetSdrMarkByIndex(0); SdrObject* pObj = pMark->GetMarkedSdrObj(); aRect.Union( pObj->GetLogicRect() ); } Point aPos( pOLV->GetWindow()->PixelToLogic( rEvt.maPosPixel ) ); if( aRect.Contains( aPos ) ) { bIsInsideOutlinerView = true; } } if( !bIsInsideOutlinerView ) { Point aPos; TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable ); if( pTargetWindow ) aPos = pTargetWindow->PixelToLogic( rEvt.maPosPixel ); // handle insert? if ((SdrDragMode::Gradient == GetDragMode()) || ((SdrDragMode::Transparence == GetDragMode()) && aDataHelper.HasFormat(SotClipboardFormatId::XFA))) { const SdrHdlList& rHdlList = GetHdlList(); for( size_t n = 0; !nRet && n < rHdlList.GetHdlCount(); ++n ) { SdrHdl* pIAOHandle = rHdlList.GetHdl( n ); if( pIAOHandle && ( SdrHdlKind::Color == pIAOHandle->GetKind() ) ) { if(pIAOHandle->getOverlayObjectList().isHitPixel(rEvt.maPosPixel)) { uno::Any const data(aDataHelper.GetAny(SotClipboardFormatId::XFA, "")); uno::Sequence props; if (data >>= props) { ::comphelper::SequenceAsHashMap const map(props); Color aColor(COL_BLACK); auto const it = map.find("FillColor"); if (it != map.end()) { XFillColorItem color; color.PutValue(it->second, 0); aColor = color.GetColorValue(); } static_cast< SdrHdlColor* >( pIAOHandle )->SetColor( aColor, true ); nRet = nDropAction; } } } } } // standard insert? if( !nRet && InsertData( aDataHelper, aPos, nDropAction, true, SotClipboardFormatId::NONE, nPage, nLayer ) ) nRet = nDropAction; // special insert? if( !nRet && mpViewSh ) { INetBookmark aINetBookmark( (OUString()), (OUString()) ); // insert bookmark if( aDataHelper.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK ) && aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) { SdPageObjsTLV::SdPageObjsTransferable* pPageObjsTransferable = SdPageObjsTLV::SdPageObjsTransferable::getImplementation( aDataHelper.GetXTransferable() ); if( pPageObjsTransferable && ( NAVIGATOR_DRAGTYPE_LINK == pPageObjsTransferable->GetDragType() || NAVIGATOR_DRAGTYPE_EMBEDDED == pPageObjsTransferable->GetDragType() ) ) { // insert bookmark from own navigator (handled async. due to possible message box ) Application::PostUserEvent( LINK( this, View, ExecuteNavigatorDrop ), new SdNavigatorDropEvent( rEvt, pTargetWindow ) ); nRet = nDropAction; } else { SdrPageView* pPageView = nullptr; SdrObject* pPickObj = PickObj(aPos, getHitTolLog(), pPageView); if (pPickObj) { // insert as clip action => jump OUString aBookmark( aINetBookmark.GetURL() ); SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo( pPickObj ); if( !aBookmark.isEmpty() ) { bool bCreated = false; presentation::ClickAction eClickAction = presentation::ClickAction_DOCUMENT; sal_Int32 nIndex = aBookmark.indexOf( '#' ); if( nIndex != -1 ) { const std::u16string_view aDocName( aBookmark.subView( 0, nIndex ) ); if (mpDocSh->GetMedium()->GetName() == aDocName || aDocName == mpDocSh->GetName()) { // internal jump, only use the part after and including '#' eClickAction = presentation::ClickAction_BOOKMARK; aBookmark = aBookmark.copy( nIndex+1 ); } } if( !pInfo ) { pInfo = SdDrawDocument::GetShapeUserData( *pPickObj, true ); bCreated = true; } // create undo action with old and new sizes std::unique_ptr pAction(new SdAnimationPrmsUndoAction(&mrDoc, pPickObj, bCreated)); pAction->SetActive(pInfo->mbActive, pInfo->mbActive); pAction->SetEffect(pInfo->meEffect, pInfo->meEffect); pAction->SetTextEffect(pInfo->meTextEffect, pInfo->meTextEffect); pAction->SetSpeed(pInfo->meSpeed, pInfo->meSpeed); pAction->SetDim(pInfo->mbDimPrevious, pInfo->mbDimPrevious); pAction->SetDimColor(pInfo->maDimColor, pInfo->maDimColor); pAction->SetDimHide(pInfo->mbDimHide, pInfo->mbDimHide); pAction->SetSoundOn(pInfo->mbSoundOn, pInfo->mbSoundOn); pAction->SetSound(pInfo->maSoundFile, pInfo->maSoundFile); pAction->SetPlayFull(pInfo->mbPlayFull, pInfo->mbPlayFull); pAction->SetClickAction(pInfo->meClickAction, eClickAction); pAction->SetBookmark(pInfo->GetBookmark(), aBookmark); pAction->SetVerb(pInfo->mnVerb, pInfo->mnVerb); pAction->SetSecondEffect(pInfo->meSecondEffect, pInfo->meSecondEffect); pAction->SetSecondSpeed(pInfo->meSecondSpeed, pInfo->meSecondSpeed); pAction->SetSecondSoundOn(pInfo->mbSecondSoundOn, pInfo->mbSecondSoundOn); pAction->SetSecondPlayFull(pInfo->mbSecondPlayFull, pInfo->mbSecondPlayFull); OUString aString(SdResId(STR_UNDO_ANIMATION)); pAction->SetComment(aString); mpDocSh->GetUndoManager()->AddUndoAction(std::move(pAction)); pInfo->meClickAction = eClickAction; pInfo->SetBookmark( aBookmark ); mrDoc.SetChanged(); nRet = nDropAction; } } else if( auto pDrawViewShell = dynamic_cast< DrawViewShell *>( mpViewSh ) ) { // insert as normal URL button pDrawViewShell->InsertURLButton( aINetBookmark.GetURL(), aINetBookmark.GetDescription(), OUString(), &aPos ); nRet = nDropAction; } } } } } } return nRet; } IMPL_LINK( View, ExecuteNavigatorDrop, void*, p, void ) { SdNavigatorDropEvent* pSdNavigatorDropEvent = static_cast(p); TransferableDataHelper aDataHelper( pSdNavigatorDropEvent->maDropEvent.Transferable ); SdPageObjsTLV::SdPageObjsTransferable* pPageObjsTransferable = SdPageObjsTLV::SdPageObjsTransferable::getImplementation( aDataHelper.GetXTransferable() ); INetBookmark aINetBookmark; if( pPageObjsTransferable && aDataHelper.GetINetBookmark( SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark ) ) { Point aPos; OUString aBookmark; SdPage* pPage = static_cast( GetSdrPageView()->GetPage() ); sal_uInt16 nPgPos = 0xFFFF; if( pSdNavigatorDropEvent->mpTargetWindow ) aPos = pSdNavigatorDropEvent->mpTargetWindow->PixelToLogic( pSdNavigatorDropEvent->maPosPixel ); const OUString& aURL( aINetBookmark.GetURL() ); sal_Int32 nIndex = aURL.indexOf( '#' ); if( nIndex != -1 ) aBookmark = aURL.copy( nIndex+1 ); std::vector aExchangeList; std::vector aBookmarkList(1,aBookmark); if( !pPage->IsMasterPage() ) { if( pPage->GetPageKind() == PageKind::Standard ) nPgPos = pPage->GetPageNum() + 2; else if( pPage->GetPageKind() == PageKind::Notes ) nPgPos = pPage->GetPageNum() + 1; } /* In order t ensure unique page names, we test the ones we want to insert. If necessary. we put them into and replacement list (bNameOK == sal_False -> User canceled). */ bool bLink = pPageObjsTransferable->GetDragType() == NAVIGATOR_DRAGTYPE_LINK; bool bNameOK = GetExchangeList( aExchangeList, aBookmarkList, 2 ); /* Since we don't know the type (page or object), we fill a list with pages and objects. Of course we have problems if there are pages and objects with the same name!!! */ if( bNameOK ) { mrDoc.InsertBookmark( aBookmarkList, aExchangeList, bLink, nPgPos, &pPageObjsTransferable->GetDocShell(), &aPos ); } } delete pSdNavigatorDropEvent; } bool View::GetExchangeList (std::vector &rExchangeList, std::vector &rBookmarkList, const sal_uInt16 nType) { assert(rExchangeList.empty()); bool bListIdentical = true; ///< Bookmark list and exchange list are identical bool bNameOK = true; ///< name is unique for ( const auto& rBookmark : rBookmarkList ) { OUString aNewName = rBookmark; if( nType == 0 || nType == 2 ) bNameOK = mpDocSh->CheckPageName(mpViewSh->GetFrameWeld(), aNewName); if( bNameOK && ( nType == 1 || nType == 2 ) ) { if( mrDoc.GetObj( aNewName ) ) { OUString aTitle(SdResId(STR_TITLE_NAMEGROUP)); OUString aDesc(SdResId(STR_DESC_NAMEGROUP)); SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); ScopedVclPtr pDlg(pFact->CreateSvxNameDialog(mpViewSh->GetFrameWeld(), aNewName, aDesc)); pDlg->SetEditHelpId( HID_SD_NAMEDIALOG_OBJECT ); bNameOK = false; pDlg->SetText( aTitle ); while( !bNameOK && pDlg->Execute() == RET_OK ) { aNewName = pDlg->GetName(); if( !mrDoc.GetObj( aNewName ) ) bNameOK = true; } } } bListIdentical = rBookmark == aNewName; rExchangeList.push_back(aNewName); if (!bNameOK) break; } // Exchange list is identical to bookmark list if( !rExchangeList.empty() && bListIdentical ) rExchangeList.clear(); return bNameOK; } } // end of namespace sd /* vim:set shiftwidth=4 softtabstop=4 expandtab: */