LCOV - code coverage report
Current view: top level - sd/source/ui/slidesorter/controller - SlsClipboard.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 9 384 2.3 %
Date: 2015-06-13 12:38:46 Functions: 5 31 16.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "controller/SlsClipboard.hxx"
      21             : 
      22             : #include "SlideSorterViewShell.hxx"
      23             : #include "SlideSorter.hxx"
      24             : #include "model/SlideSorterModel.hxx"
      25             : #include "model/SlsPageDescriptor.hxx"
      26             : #include "model/SlsPageEnumerationProvider.hxx"
      27             : #include "view/SlideSorterView.hxx"
      28             : #include "view/SlsTheme.hxx"
      29             : #include "controller/SlideSorterController.hxx"
      30             : #include "controller/SlsInsertionIndicatorHandler.hxx"
      31             : #include "controller/SlsPageSelector.hxx"
      32             : #include "controller/SlsSelectionFunction.hxx"
      33             : #include "controller/SlsCurrentSlideManager.hxx"
      34             : #include "controller/SlsScrollBarManager.hxx"
      35             : #include "controller/SlsFocusManager.hxx"
      36             : #include "controller/SlsSelectionManager.hxx"
      37             : #include "controller/SlsTransferableData.hxx"
      38             : #include "controller/SlsSelectionObserver.hxx"
      39             : #include "controller/SlsVisibleAreaManager.hxx"
      40             : #include "cache/SlsPageCache.hxx"
      41             : 
      42             : #include "ViewShellBase.hxx"
      43             : #include "View.hxx"
      44             : #include "DrawViewShell.hxx"
      45             : #include "Window.hxx"
      46             : #include "fupoor.hxx"
      47             : #include "fuzoom.hxx"
      48             : #include "fucushow.hxx"
      49             : #include "fusldlg.hxx"
      50             : #include "fuexpand.hxx"
      51             : #include "fusumry.hxx"
      52             : #include "app.hrc"
      53             : #include "glob.hrc"
      54             : #include "strings.hrc"
      55             : #include "sdresid.hxx"
      56             : #include "sdxfer.hxx"
      57             : #include "sdmod.hxx"
      58             : #include "ins_paste.hxx"
      59             : #include "drawdoc.hxx"
      60             : #include "DrawDocShell.hxx"
      61             : #include "sdpage.hxx"
      62             : #include "sdtreelb.hxx"
      63             : 
      64             : #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
      65             : #include <sfx2/request.hxx>
      66             : #include <sfx2/viewfrm.hxx>
      67             : #include <sfx2/bindings.hxx>
      68             : #include <sfx2/docfile.hxx>
      69             : #include <svx/svxids.hrc>
      70             : #include <svx/svdstr.hrc>
      71             : #include <vcl/msgbox.hxx>
      72             : #include <tools/urlobj.hxx>
      73             : #include <rtl/ustring.hxx>
      74             : #include <osl/mutex.hxx>
      75             : #include <vcl/svapp.hxx>
      76             : #include <boost/bind.hpp>
      77             : 
      78             : namespace sd { namespace slidesorter { namespace controller {
      79             : 
      80             : namespace {
      81             : /** Temporarily deactivate slide tracking of the VisibleAreaManager.
      82             :     This is used as a workaround to avoid unwanted repositioning of
      83             :     the visible area when the selection of slides is copied to the
      84             :     clipboard (cloning of slides leads to model change notifications
      85             :     for the original model.)
      86             : */
      87             : class TemporarySlideTrackingDeactivator
      88             : {
      89             : public:
      90           0 :     TemporarySlideTrackingDeactivator (SlideSorterController& rController)
      91             :         : mrController(rController),
      92             :           mbIsCurrentSlideTrackingActive (
      93           0 :               mrController.GetVisibleAreaManager().IsCurrentSlideTrackingActive())
      94             :     {
      95           0 :         if (mbIsCurrentSlideTrackingActive)
      96           0 :             mrController.GetVisibleAreaManager().DeactivateCurrentSlideTracking();
      97           0 :     }
      98           0 :     ~TemporarySlideTrackingDeactivator()
      99             :     {
     100           0 :         if (mbIsCurrentSlideTrackingActive)
     101           0 :             mrController.GetVisibleAreaManager().ActivateCurrentSlideTracking();
     102           0 :     }
     103             : 
     104             : private:
     105             :     SlideSorterController& mrController;
     106             :     const bool mbIsCurrentSlideTrackingActive;
     107             : };
     108             : } // end of anonymous namespace
     109             : 
     110             : class Clipboard::UndoContext
     111             : {
     112             : public:
     113           0 :     UndoContext (
     114             :         SdDrawDocument* pDocument,
     115             :         const ::boost::shared_ptr<ViewShell>& rpMainViewShell)
     116             :         : mpDocument(pDocument),
     117           0 :           mpMainViewShell(rpMainViewShell)
     118             :     {
     119           0 :         if (mpDocument!=NULL && mpDocument->IsUndoEnabled())
     120             :         {
     121           0 :             if (mpMainViewShell && mpMainViewShell->GetShellType() == ViewShell::ST_DRAW)
     122           0 :                 mpDocument->BegUndo(SD_RESSTR(STRING_DRAG_AND_DROP_PAGES));
     123             :             else
     124           0 :                 mpDocument->BegUndo(SD_RESSTR(STRING_DRAG_AND_DROP_SLIDES));
     125             :         }
     126           0 :     }
     127             : 
     128           0 :     ~UndoContext()
     129           0 :     {
     130           0 :         if (mpDocument!=NULL && mpDocument->IsUndoEnabled())
     131           0 :             mpDocument->EndUndo();
     132           0 :         if (mpMainViewShell && mpMainViewShell->GetViewFrame()!=NULL)
     133             :         {
     134           0 :             SfxBindings& rBindings = mpMainViewShell->GetViewFrame()->GetBindings();
     135           0 :             rBindings.Invalidate(SID_UNDO);
     136           0 :             rBindings.Invalidate(SID_REDO);
     137             :         }
     138           0 :     }
     139             : private:
     140             :     SdDrawDocument* mpDocument;
     141             :     ::boost::shared_ptr<ViewShell> mpMainViewShell;
     142             : };
     143             : 
     144          64 : Clipboard::Clipboard (SlideSorter& rSlideSorter)
     145          64 :     : ViewClipboard(rSlideSorter.GetView()),
     146             :       mrSlideSorter(rSlideSorter),
     147          64 :       mrController(mrSlideSorter.GetController()),
     148             :       maPagesToRemove(),
     149             :       maPagesToSelect(),
     150             :       mbUpdateSelectionPending(false),
     151             :       mxUndoContext(),
     152             :       mxSelectionObserverContext(),
     153         128 :       mnDragFinishedUserEventId(0)
     154             : {
     155          64 : }
     156             : 
     157         192 : Clipboard::~Clipboard()
     158             : {
     159          64 :     if (mnDragFinishedUserEventId != 0)
     160           0 :         Application::RemoveUserEvent(mnDragFinishedUserEventId);
     161         128 : }
     162             : 
     163             : /** With the current implementation the forwarded calls to the current
     164             :     function will come back eventually to call the local Do(Cut|Copy|Paste)
     165             :     methods.  A shortcut is possible but would be an unclean hack.
     166             : */
     167           0 : void Clipboard::HandleSlotCall (SfxRequest& rRequest)
     168             : {
     169           0 :     ViewShell* pViewShell = mrSlideSorter.GetViewShell();
     170           0 :     rtl::Reference<FuPoor> xFunc;
     171           0 :     if (pViewShell != NULL)
     172           0 :         xFunc = pViewShell->GetCurrentFunction();
     173           0 :     switch (rRequest.GetSlot())
     174             :     {
     175             :         case SID_CUT:
     176           0 :             if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
     177             :             {
     178           0 :                 if(xFunc.is())
     179           0 :                     xFunc->DoCut();
     180             :                 else
     181           0 :                     DoCut();
     182             :             }
     183           0 :             rRequest.Done();
     184           0 :             break;
     185             : 
     186             :         case SID_COPY:
     187           0 :             if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
     188             :             {
     189           0 :                 if(xFunc.is())
     190           0 :                     xFunc->DoCopy();
     191             :                 else
     192           0 :                     DoCopy();
     193             :             }
     194           0 :             rRequest.Done();
     195           0 :             break;
     196             : 
     197             :         case SID_PASTE:
     198             :             // Prevent redraws while inserting pages from the clipboard
     199             :             // because the intermediate inconsistent state might lead to
     200             :             // a crash.
     201           0 :             if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
     202             :             {
     203           0 :                 view::SlideSorterView::DrawLock aLock (mrSlideSorter);
     204           0 :                 SelectionObserver::Context aContext (mrSlideSorter);
     205           0 :                 if(xFunc.is())
     206           0 :                     xFunc->DoPaste();
     207             :                 else
     208           0 :                     DoPaste();
     209             :             }
     210           0 :             rRequest.Done();
     211           0 :             break;
     212             : 
     213             :         case SID_DELETE:
     214           0 :             DoDelete();
     215           0 :             rRequest.Done();
     216           0 :             break;
     217           0 :     }
     218           0 : }
     219             : 
     220           0 : void Clipboard::DoCut (vcl::Window* pWindow)
     221             : {
     222           0 :     if (mrSlideSorter.GetModel().GetPageCount() > 1)
     223             :     {
     224           0 :         DoCopy(pWindow);
     225           0 :         DoDelete(pWindow);
     226             :     }
     227           0 : }
     228             : 
     229           0 : void Clipboard::DoDelete (vcl::Window* )
     230             : {
     231           0 :     if (mrSlideSorter.GetModel().GetPageCount() > 1)
     232             :     {
     233           0 :         mrController.GetSelectionManager()->DeleteSelectedPages();
     234             :     }
     235           0 : }
     236             : 
     237           0 : void Clipboard::DoCopy (vcl::Window* pWindow )
     238             : {
     239           0 :     CreateSlideTransferable( pWindow, false );
     240           0 : }
     241             : 
     242           0 : void Clipboard::DoPaste (vcl::Window* pWindow)
     243             : {
     244           0 :     SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
     245             : 
     246           0 :     if (pClipTransferable!=NULL && pClipTransferable->IsPageTransferable())
     247             :     {
     248           0 :         sal_Int32 nInsertPosition = GetInsertionPosition(pWindow);
     249             : 
     250           0 :         if (nInsertPosition >= 0)
     251             :         {
     252             :             // Paste the pages from the clipboard.
     253           0 :             sal_Int32 nInsertPageCount = PasteTransferable(nInsertPosition);
     254             :             // Select the pasted pages and make the first of them the
     255             :             // current page.
     256           0 :             mrSlideSorter.GetContentWindow()->GrabFocus();
     257           0 :             SelectPageRange(nInsertPosition, nInsertPageCount);
     258             :         }
     259             :     }
     260           0 : }
     261             : 
     262           0 : sal_Int32 Clipboard::GetInsertionPosition (vcl::Window* pWindow)
     263             : {
     264           0 :     sal_Int32 nInsertPosition = -1;
     265             : 
     266             :     // Determine the insertion position:
     267             :     // a) When the insertion indicator is visible, then at that position.
     268             :     // b) When the focus indicator is visible, then before or after the
     269             :     // focused page, depending on user input to a dialog.
     270             :     // c) When there is a selection but no focus, then after the
     271             :     // selection.
     272             :     // d) After the last page when there is no selection and no focus.
     273             : 
     274             :     ::boost::shared_ptr<controller::InsertionIndicatorHandler> pInsertionIndicatorHandler (
     275           0 :         mrController.GetInsertionIndicatorHandler());
     276           0 :     if (pInsertionIndicatorHandler->IsActive())
     277             :     {
     278             :         // Use the insertion index of an active insertion indicator.
     279           0 :         nInsertPosition = pInsertionIndicatorHandler->GetInsertionPageIndex();
     280             :     }
     281           0 :     else if (mrController.GetSelectionManager()->GetInsertionPosition() >= 0)
     282             :     {
     283             :         // Use the insertion index of an insertion indicator that has been
     284             :         // deactivated a short while ago.
     285           0 :         nInsertPosition = mrController.GetSelectionManager()->GetInsertionPosition();
     286             :     }
     287           0 :     else if (mrController.GetFocusManager().IsFocusShowing())
     288             :     {
     289             :         // Use the focus to determine the insertion position.
     290           0 :         ScopedVclPtrInstance< SdInsertPasteDlg > aDialog(pWindow);
     291           0 :         if (aDialog->Execute() == RET_OK)
     292             :         {
     293           0 :             nInsertPosition = mrController.GetFocusManager().GetFocusedPageIndex();
     294           0 :             if ( ! aDialog->IsInsertBefore())
     295           0 :                 nInsertPosition ++;
     296           0 :         }
     297             :     }
     298             : 
     299           0 :     return nInsertPosition;
     300             : }
     301             : 
     302           0 : sal_Int32 Clipboard::PasteTransferable (sal_Int32 nInsertPosition)
     303             : {
     304           0 :     SdTransferable* pClipTransferable = SD_MOD()->pTransferClip;
     305           0 :     model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
     306           0 :     bool bMergeMasterPages = !pClipTransferable->HasSourceDoc (rModel.GetDocument());
     307           0 :     sal_uInt16 nInsertIndex (rModel.GetCoreIndex(nInsertPosition));
     308           0 :     sal_Int32 nInsertPageCount (0);
     309           0 :     if (pClipTransferable->HasPageBookmarks())
     310             :     {
     311           0 :         const std::vector<OUString> &rBookmarkList = pClipTransferable->GetPageBookmarks();
     312           0 :         const SolarMutexGuard aGuard;
     313             : 
     314           0 :         nInsertPageCount = (sal_uInt16) rBookmarkList.size();
     315             :         rModel.GetDocument()->InsertBookmarkAsPage(
     316             :             rBookmarkList,
     317             :             NULL,
     318             :             false,
     319             :             false,
     320             :             nInsertIndex,
     321             :             false,
     322             :             pClipTransferable->GetPageDocShell(),
     323             :             true,
     324             :             bMergeMasterPages,
     325           0 :             false);
     326             :     }
     327             :     else
     328             :     {
     329           0 :         SfxObjectShell* pShell = pClipTransferable->GetDocShell();
     330           0 :         DrawDocShell* pDataDocSh = static_cast<DrawDocShell*>(pShell);
     331           0 :         SdDrawDocument* pDataDoc = pDataDocSh->GetDoc();
     332             : 
     333           0 :         if (pDataDoc!=NULL
     334           0 :             && pDataDoc->GetSdPageCount(PK_STANDARD))
     335             :         {
     336           0 :             const SolarMutexGuard aGuard;
     337             : 
     338           0 :             bMergeMasterPages = (pDataDoc != rModel.GetDocument());
     339           0 :             nInsertPageCount = pDataDoc->GetSdPageCount( PK_STANDARD );
     340             :             rModel.GetDocument()->InsertBookmarkAsPage(
     341             :                 std::vector<OUString>(),
     342             :                 NULL,
     343             :                 false,
     344             :                 false,
     345             :                 nInsertIndex,
     346             :                 false,
     347             :                 pDataDocSh,
     348             :                 true,
     349             :                 bMergeMasterPages,
     350           0 :                 false);
     351             :         }
     352             :     }
     353           0 :     mrController.HandleModelChange();
     354           0 :     return nInsertPageCount;
     355             : }
     356             : 
     357           0 : void Clipboard::SelectPageRange (sal_Int32 nFirstIndex, sal_Int32 nPageCount)
     358             : {
     359             :     // Select the newly inserted pages.  That are the nInsertPageCount pages
     360             :     // after the nInsertIndex position.
     361           0 :     PageSelector& rSelector (mrController.GetPageSelector());
     362           0 :     rSelector.DeselectAllPages();
     363           0 :     for (sal_Int32 i=0; i<nPageCount; i++)
     364             :     {
     365             :         model::SharedPageDescriptor pDescriptor (
     366           0 :             mrSlideSorter.GetModel().GetPageDescriptor(nFirstIndex + i));
     367           0 :         if (pDescriptor.get() != NULL)
     368             :         {
     369           0 :             rSelector.SelectPage(pDescriptor);
     370             :             // The first page of the new selection is made the current page.
     371           0 :             if (i == 0)
     372             :             {
     373           0 :                 mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
     374             :             }
     375             :         }
     376           0 :     }
     377           0 : }
     378             : 
     379           0 : void Clipboard::CreateSlideTransferable (
     380             :     vcl::Window* pWindow,
     381             :     bool bDrag)
     382             : {
     383           0 :     std::vector<OUString> aBookmarkList;
     384             : 
     385             :     // Insert all selected pages into a bookmark list and remember them in
     386             :     // maPagesToRemove for possible later removal.
     387             :     model::PageEnumeration aSelectedPages
     388             :         (model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
     389           0 :             mrSlideSorter.GetModel()));
     390           0 :     while (aSelectedPages.HasMoreElements())
     391             :     {
     392           0 :         model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
     393           0 :         aBookmarkList.push_back(pDescriptor->GetPage()->GetName());
     394           0 :         maPagesToRemove.push_back (pDescriptor->GetPage());
     395           0 :     }
     396             : 
     397             :     // Create a small set of representatives of the selection for which
     398             :     // previews are included into the transferable so that an insertion
     399             :     // indicator can be rendered.
     400           0 :     aSelectedPages.Rewind();
     401           0 :     ::std::vector<TransferableData::Representative> aRepresentatives;
     402           0 :     aRepresentatives.reserve(3);
     403             :     ::boost::shared_ptr<cache::PageCache> pPreviewCache (
     404           0 :         mrSlideSorter.GetView().GetPreviewCache());
     405           0 :     while (aSelectedPages.HasMoreElements())
     406             :     {
     407           0 :         model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
     408           0 :         if ( ! pDescriptor || pDescriptor->GetPage()==NULL)
     409           0 :             continue;
     410           0 :         Bitmap aPreview (pPreviewCache->GetPreviewBitmap(pDescriptor->GetPage(), false));
     411             :         aRepresentatives.push_back(TransferableData::Representative(
     412             :             aPreview,
     413           0 :             pDescriptor->HasState(model::PageDescriptor::ST_Excluded)));
     414           0 :         if (aRepresentatives.size() >= 3)
     415           0 :             break;
     416           0 :     }
     417             : 
     418           0 :     if (!aBookmarkList.empty())
     419             :     {
     420           0 :         mrSlideSorter.GetView().BrkAction();
     421           0 :         SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
     422             :         SdTransferable* pTransferable = TransferableData::CreateTransferable (
     423             :             pDocument,
     424             :             NULL,
     425             :             false,
     426           0 :             dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()),
     427           0 :             aRepresentatives);
     428             : 
     429           0 :         if (bDrag)
     430           0 :             SD_MOD()->pTransferDrag = pTransferable;
     431             :         else
     432           0 :             SD_MOD()->pTransferClip = pTransferable;
     433             : 
     434           0 :         pDocument->CreatingDataObj (pTransferable);
     435           0 :         pTransferable->SetWorkDocument(pDocument->AllocSdDrawDocument());
     436           0 :         pDocument->CreatingDataObj (NULL);
     437           0 :         TransferableObjectDescriptor aObjDesc;
     438           0 :         pTransferable->GetWorkDocument()->GetDocSh()
     439           0 :             ->FillTransferableObjectDescriptor (aObjDesc);
     440             : 
     441           0 :         if (pDocument->GetDocSh() != NULL)
     442           0 :             aObjDesc.maDisplayName = pDocument->GetDocSh()
     443           0 :                 ->GetMedium()->GetURLObject().GetURLNoPass();
     444             : 
     445           0 :         vcl::Window* pActionWindow = pWindow;
     446           0 :         if (pActionWindow == NULL)
     447             :         {
     448           0 :             ViewShell* pViewShell = mrSlideSorter.GetViewShell();
     449           0 :             if (pViewShell != NULL)
     450           0 :                 pActionWindow = pViewShell->GetActiveWindow();
     451             :         }
     452             : 
     453             :         pTransferable->SetStartPos (pActionWindow->PixelToLogic(
     454           0 :             pActionWindow->GetPointerPosPixel()));
     455           0 :         pTransferable->SetObjectDescriptor (aObjDesc);
     456             : 
     457             :         {
     458           0 :             TemporarySlideTrackingDeactivator aDeactivator (mrController);
     459           0 :             pTransferable->SetPageBookmarks (aBookmarkList, !bDrag);
     460             :         }
     461             : 
     462           0 :         if (bDrag)
     463             :         {
     464           0 :             pTransferable->SetView (&mrSlideSorter.GetView());
     465           0 :             pTransferable->StartDrag (pActionWindow, DND_ACTION_COPY | DND_ACTION_MOVE);
     466             :         }
     467             :         else
     468           0 :             pTransferable->CopyToClipboard (pActionWindow);
     469           0 :     }
     470           0 : }
     471             : 
     472           0 : ::boost::shared_ptr<SdTransferable::UserData> Clipboard::CreateTransferableUserData (SdTransferable* pTransferable)
     473             : {
     474             :     do
     475             :     {
     476             :         SdPageObjsTLB::SdPageObjsTransferable* pTreeListBoxTransferable
     477           0 :             = dynamic_cast<SdPageObjsTLB::SdPageObjsTransferable*>(pTransferable);
     478           0 :         if (pTreeListBoxTransferable == NULL)
     479           0 :             break;
     480             : 
     481             :         // Find view shell for the document of the transferable.
     482             :         ::sd::ViewShell* pViewShell
     483           0 :               = SdPageObjsTLB::GetViewShellForDocShell(pTreeListBoxTransferable->GetDocShell());
     484           0 :         if (pViewShell == NULL)
     485           0 :             break;
     486             : 
     487             :         // Find slide sorter for the document of the transferable.
     488             :         SlideSorterViewShell* pSlideSorterViewShell
     489           0 :             = SlideSorterViewShell::GetSlideSorter(pViewShell->GetViewShellBase());
     490           0 :         if (pSlideSorterViewShell == NULL)
     491           0 :             break;
     492           0 :         SlideSorter& rSlideSorter (pSlideSorterViewShell->GetSlideSorter());
     493             : 
     494             :         // Get bookmark from transferable.
     495           0 :         TransferableDataHelper  aDataHelper (pTransferable);
     496           0 :         INetBookmark aINetBookmark;
     497           0 :         if ( ! aDataHelper.GetINetBookmark(SotClipboardFormatId::NETSCAPE_BOOKMARK, aINetBookmark))
     498           0 :             break;
     499           0 :         const OUString sURL (aINetBookmark.GetURL());
     500           0 :         const sal_Int32 nIndex (sURL.indexOf((sal_Unicode)'#'));
     501           0 :         if (nIndex == -1)
     502           0 :             break;
     503           0 :         OUString sBookmark (sURL.copy(nIndex+1));
     504             : 
     505             :         // Make sure that the bookmark points to a page.
     506           0 :         SdDrawDocument* pTransferableDocument = rSlideSorter.GetModel().GetDocument();
     507           0 :         if (pTransferableDocument == NULL)
     508           0 :             break;
     509           0 :         bool bIsMasterPage = false;
     510           0 :         const sal_uInt16 nPageIndex (pTransferableDocument->GetPageByName(sBookmark, bIsMasterPage));
     511           0 :         if (nPageIndex == SDRPAGE_NOTFOUND)
     512           0 :             break;
     513             : 
     514             :         // Create preview.
     515           0 :         ::std::vector<TransferableData::Representative> aRepresentatives;
     516           0 :         aRepresentatives.reserve(1);
     517             :         ::boost::shared_ptr<cache::PageCache> pPreviewCache (
     518           0 :             rSlideSorter.GetView().GetPreviewCache());
     519           0 :         model::SharedPageDescriptor pDescriptor (rSlideSorter.GetModel().GetPageDescriptor((nPageIndex-1)/2));
     520           0 :         if ( ! pDescriptor || pDescriptor->GetPage()==NULL)
     521           0 :             break;
     522           0 :         Bitmap aPreview (pPreviewCache->GetPreviewBitmap(pDescriptor->GetPage(), false));
     523             :         aRepresentatives.push_back(TransferableData::Representative(
     524             :                 aPreview,
     525           0 :                 pDescriptor->HasState(model::PageDescriptor::ST_Excluded)));
     526             : 
     527             :         // Remember the page in maPagesToRemove so that it can be removed
     528             :         // when drag and drop action is "move".
     529           0 :         Clipboard& rOtherClipboard (pSlideSorterViewShell->GetSlideSorter().GetController().GetClipboard());
     530           0 :         rOtherClipboard.maPagesToRemove.clear();
     531           0 :         rOtherClipboard.maPagesToRemove.push_back(pDescriptor->GetPage());
     532             : 
     533             :         // Create the new transferable.
     534             :         ::boost::shared_ptr<SdTransferable::UserData> pNewTransferable (
     535             :             new TransferableData(
     536             :                 pSlideSorterViewShell,
     537           0 :                 aRepresentatives));
     538           0 :         pTransferable->SetWorkDocument(pTreeListBoxTransferable->GetSourceDoc()->AllocSdDrawDocument());
     539             :         //        pTransferable->SetView(&mrSlideSorter.GetView());
     540             : 
     541             :         // Set page bookmark list.
     542           0 :         std::vector<OUString> aPageBookmarks;
     543           0 :         aPageBookmarks.push_back(sBookmark);
     544           0 :         pTransferable->SetPageBookmarks(aPageBookmarks, false);
     545             : 
     546             :         // Replace the view referenced by the transferable with the
     547             :         // corresponding slide sorter view.
     548           0 :         pTransferable->SetView(&pSlideSorterViewShell->GetSlideSorter().GetView());
     549             : 
     550           0 :         return pNewTransferable;
     551             :     }
     552             :     while (false);
     553             : 
     554           0 :     return ::boost::shared_ptr<SdTransferable::UserData>();
     555             : }
     556             : 
     557           0 : void Clipboard::StartDrag (
     558             :     const Point& rPosition,
     559             :     vcl::Window* pWindow)
     560             : {
     561           0 :     maPagesToRemove.clear();
     562           0 :     maPagesToSelect.clear();
     563           0 :     mbUpdateSelectionPending = false;
     564           0 :     CreateSlideTransferable(pWindow, true);
     565             : 
     566             :     mrController.GetInsertionIndicatorHandler()->UpdatePosition(
     567             :         rPosition,
     568           0 :         InsertionIndicatorHandler::UnknownMode);
     569           0 : }
     570             : 
     571           0 : void Clipboard::DragFinished (sal_Int8 nDropAction)
     572             : {
     573           0 :     if (mnDragFinishedUserEventId == 0)
     574             :     {
     575             :         mnDragFinishedUserEventId = Application::PostUserEvent(
     576             :             LINK(this, Clipboard, ProcessDragFinished),
     577           0 :             reinterpret_cast<void*>(nDropAction));
     578             :     }
     579           0 : }
     580             : 
     581           0 : IMPL_LINK(Clipboard, ProcessDragFinished, void*, pUserData)
     582             : {
     583           0 :     const sal_Int8 nDropAction (static_cast<sal_Int8>(reinterpret_cast<sal_IntPtr>(pUserData)));
     584             : 
     585           0 :     mnDragFinishedUserEventId = 0;
     586             : 
     587             :     // Hide the substitution display and insertion indicator.
     588           0 :     ::rtl::Reference<SelectionFunction> pFunction (mrController.GetCurrentSelectionFunction());
     589           0 :     if (pFunction.is())
     590           0 :         pFunction->NotifyDragFinished();
     591             : 
     592           0 :     PageSelector& rSelector (mrController.GetPageSelector());
     593           0 :     if ((nDropAction & DND_ACTION_MOVE) != 0
     594           0 :         && ! maPagesToRemove.empty())
     595             :     {
     596             :         // Remove the pages that have been moved to another place (possibly
     597             :         // in the same document.)
     598           0 :         rSelector.DeselectAllPages();
     599           0 :         PageList::iterator aDraggedPage;
     600           0 :         for (aDraggedPage=maPagesToRemove.begin();
     601           0 :              aDraggedPage!=maPagesToRemove.end();
     602             :              ++aDraggedPage)
     603             :         {
     604           0 :             rSelector.SelectPage(*aDraggedPage);
     605             :         }
     606           0 :         mrController.GetSelectionManager()->DeleteSelectedPages();
     607             :     }
     608           0 :     mxUndoContext.reset();
     609           0 :     mxSelectionObserverContext.reset();
     610             : 
     611           0 :     return 1;
     612             : }
     613             : 
     614           0 : sal_Int8 Clipboard::AcceptDrop (
     615             :     const AcceptDropEvent& rEvent,
     616             :     DropTargetHelper& rTargetHelper,
     617             :     ::sd::Window* pTargetWindow,
     618             :     sal_uInt16 nPage,
     619             :     sal_uInt16 nLayer)
     620             : {
     621           0 :     sal_Int8 nAction (DND_ACTION_NONE);
     622             : 
     623           0 :     const Clipboard::DropType eDropType (IsDropAccepted(rTargetHelper));
     624             : 
     625           0 :     switch (eDropType)
     626             :     {
     627             :         case DT_PAGE:
     628             :         case DT_PAGE_FROM_NAVIGATOR:
     629             :         {
     630             :             // Accept a drop.
     631           0 :             nAction = rEvent.mnAction;
     632             : 
     633             :             // Use the copy action when the drop action is the default, i.e. not
     634             :             // explicitly set to move or link, and when the source and
     635             :             // target models are not the same.
     636           0 :             SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
     637           0 :             if (pDragTransferable != NULL
     638           0 :                 && pDragTransferable->IsPageTransferable()
     639           0 :                 && ((rEvent.maDragEvent.DropAction
     640           0 :                         & ::com::sun::star::datatransfer::dnd::DNDConstants::ACTION_DEFAULT) != 0)
     641           0 :                 && (mrSlideSorter.GetModel().GetDocument()->GetDocSh()
     642           0 :                     != pDragTransferable->GetPageDocShell()))
     643             :             {
     644           0 :                 nAction = DND_ACTION_COPY;
     645             :             }
     646           0 :             else if (IsInsertionTrivial(pDragTransferable, nAction))
     647             :             {
     648           0 :                 nAction = DND_ACTION_NONE;
     649             :             }
     650             : 
     651             :             // Show the insertion marker and the substitution for a drop.
     652             :             SelectionFunction* pSelectionFunction = dynamic_cast<SelectionFunction*>(
     653           0 :                 mrSlideSorter.GetViewShell()->GetCurrentFunction().get());
     654           0 :             if (pSelectionFunction != NULL)
     655           0 :                 pSelectionFunction->MouseDragged(rEvent, nAction);
     656             : 
     657             :             // Scroll the window when the mouse reaches the window border.
     658             :             //            mrController.GetScrollBarManager().AutoScroll (rEvent.maPosPixel);
     659             :         }
     660           0 :         break;
     661             : 
     662             :         case DT_SHAPE:
     663             :             nAction = ExecuteOrAcceptShapeDrop(
     664             :                 DC_ACCEPT,
     665             :                 rEvent.maPosPixel,
     666             :                 &rEvent,
     667             :                 rTargetHelper,
     668             :                 pTargetWindow,
     669             :                 nPage,
     670           0 :                 nLayer);
     671           0 :             break;
     672             : 
     673             :         default:
     674             :         case DT_NONE:
     675           0 :             nAction = DND_ACTION_NONE;
     676           0 :             break;
     677             :     }
     678             : 
     679           0 :     return nAction;
     680             : }
     681             : 
     682           0 : sal_Int8 Clipboard::ExecuteDrop (
     683             :     const ExecuteDropEvent& rEvent,
     684             :     DropTargetHelper& rTargetHelper,
     685             :     ::sd::Window* pTargetWindow,
     686             :     sal_uInt16 nPage,
     687             :     sal_uInt16 nLayer)
     688             : {
     689           0 :     sal_Int8 nResult = DND_ACTION_NONE;
     690           0 :     mxUndoContext.reset();
     691           0 :     const Clipboard::DropType eDropType (IsDropAccepted(rTargetHelper));
     692             : 
     693           0 :     switch (eDropType)
     694             :     {
     695             :         case DT_PAGE:
     696             :         case DT_PAGE_FROM_NAVIGATOR:
     697             :         {
     698           0 :             SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
     699             :             const Point aEventModelPosition (
     700           0 :                 pTargetWindow->PixelToLogic (rEvent.maPosPixel));
     701           0 :             const sal_Int32 nXOffset (labs (pDragTransferable->GetStartPos().X()
     702           0 :                 - aEventModelPosition.X()));
     703           0 :             const sal_Int32 nYOffset (labs (pDragTransferable->GetStartPos().Y()
     704           0 :                 - aEventModelPosition.Y()));
     705             :             bool bContinue =
     706           0 :                 ( pDragTransferable->GetView() != &mrSlideSorter.GetView() )
     707           0 :                 || ( nXOffset >= 2 && nYOffset >= 2 );
     708             : 
     709             :             ::boost::shared_ptr<InsertionIndicatorHandler> pInsertionIndicatorHandler(
     710           0 :                         mrController.GetInsertionIndicatorHandler());
     711             :             // Get insertion position and then turn off the insertion indicator.
     712           0 :             pInsertionIndicatorHandler->UpdatePosition(aEventModelPosition, rEvent.mnAction);
     713             :             //            sal_uInt16 nIndex = DetermineInsertPosition(*pDragTransferable);
     714             : 
     715             :             // Do not process the insertion when it is trivial,
     716             :             // i.e. would insert pages at their original place.
     717           0 :             if (IsInsertionTrivial(pDragTransferable, rEvent.mnAction))
     718           0 :                 bContinue = false;
     719             : 
     720             :             // Tell the insertion indicator handler to hide before the model
     721             :             // is modified.  Doing it later may result in page objects whose
     722             :             // animation state is not properly reset because they are then
     723             :             // in another run then before the model change.
     724           0 :             pInsertionIndicatorHandler->End(Animator::AM_Immediate);
     725             : 
     726           0 :             if (bContinue)
     727             :             {
     728           0 :                 SlideSorterController::ModelChangeLock aModelChangeLock (mrController);
     729             : 
     730             :                 // Handle a general drop operation.
     731             :                 mxUndoContext.reset(new UndoContext (
     732           0 :                     mrSlideSorter.GetModel().GetDocument(),
     733           0 :                     mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell()));
     734           0 :                 mxSelectionObserverContext.reset(new SelectionObserver::Context(mrSlideSorter));
     735             : 
     736           0 :                 HandlePageDrop(*pDragTransferable);
     737           0 :                 nResult = rEvent.mnAction;
     738             : 
     739             :                 // We leave the undo context alive for when moving or
     740             :                 // copying inside one view then the actions in
     741             :                 // NotifyDragFinished should be covered as well as
     742             :                 // well as the ones above.
     743             :             }
     744             : 
     745             :             // When the pages originated in another slide sorter then
     746             :             // only that is notified automatically about the drag
     747             :             // operation being finished.  Because the target slide sorter
     748             :             // has be notified, too, add a callback for that.
     749             :             ::boost::shared_ptr<TransferableData> pSlideSorterTransferable (
     750           0 :                 TransferableData::GetFromTransferable(pDragTransferable));
     751             :             BOOST_ASSERT(pSlideSorterTransferable);
     752           0 :             if (pSlideSorterTransferable
     753           0 :                 && pSlideSorterTransferable->GetSourceViewShell() != mrSlideSorter.GetViewShell())
     754             :             {
     755           0 :                 DragFinished(nResult);
     756             :             }
     757             : 
     758             :             // Notify the receiving selection function that drag-and-drop is
     759             :             // finished and the substitution handler can be released.
     760             :             ::rtl::Reference<SelectionFunction> pFunction (
     761           0 :                 mrController.GetCurrentSelectionFunction());
     762           0 :             if (pFunction.is())
     763           0 :                 pFunction->NotifyDragFinished();
     764             :         }
     765           0 :         break;
     766             : 
     767             :         case DT_SHAPE:
     768             :             nResult = ExecuteOrAcceptShapeDrop(
     769             :                 DC_EXECUTE,
     770             :                 rEvent.maPosPixel,
     771             :                 &rEvent,
     772             :                 rTargetHelper,
     773             :                 pTargetWindow,
     774             :                 nPage,
     775           0 :                 nLayer);
     776           0 :             break;
     777             : 
     778             :         default:
     779             :         case DT_NONE:
     780           0 :             break;
     781             :     }
     782             : 
     783           0 :     return nResult;
     784             : }
     785             : 
     786           0 : bool Clipboard::IsInsertionTrivial (
     787             :     SdTransferable* pTransferable,
     788             :     const sal_Int8 nDndAction) const
     789             : {
     790             :     ::boost::shared_ptr<TransferableData> pSlideSorterTransferable (
     791           0 :         TransferableData::GetFromTransferable(pTransferable));
     792           0 :     if (pSlideSorterTransferable
     793           0 :         && pSlideSorterTransferable->GetSourceViewShell() != mrSlideSorter.GetViewShell())
     794           0 :         return false;
     795           0 :     return mrController.GetInsertionIndicatorHandler()->IsInsertionTrivial(nDndAction);
     796             : }
     797             : 
     798           0 : void Clipboard::Abort()
     799             : {
     800           0 :     if (mxSelectionObserverContext)
     801             :     {
     802           0 :         mxSelectionObserverContext->Abort();
     803           0 :         mxSelectionObserverContext.reset();
     804             :     }
     805           0 : }
     806             : 
     807           0 : sal_uInt16 Clipboard::DetermineInsertPosition (const SdTransferable& )
     808             : {
     809             :     // Tell the model to move the dragged pages behind the one with the
     810             :     // index nInsertionIndex which first has to be transformed into an index
     811             :     // understandable by the document.
     812             :     const sal_Int32 nInsertionIndex (
     813           0 :         mrController.GetInsertionIndicatorHandler()->GetInsertionPageIndex());
     814             : 
     815             :     // Convert to insertion index to that of an SdModel.
     816           0 :     if (nInsertionIndex >= 0)
     817           0 :         return mrSlideSorter.GetModel().GetCoreIndex(nInsertionIndex);
     818             :     else
     819           0 :         return 0;
     820             : }
     821             : 
     822           0 : sal_uInt16 Clipboard::InsertSlides (
     823             :     const SdTransferable& rTransferable,
     824             :     sal_uInt16 nInsertPosition)
     825             : {
     826             :     sal_uInt16 nInsertedPageCount = ViewClipboard::InsertSlides (
     827             :         rTransferable,
     828           0 :         nInsertPosition);
     829             : 
     830             :     // Remember the inserted pages so that they can be selected when the
     831             :     // operation is finished.
     832           0 :     maPagesToSelect.clear();
     833           0 :     SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument();
     834           0 :     if (pDocument != NULL)
     835           0 :         for (sal_Int32 i=0; i<=nInsertedPageCount; i+=2)
     836             :             maPagesToSelect.push_back(
     837           0 :                 dynamic_cast<SdPage*>(pDocument->GetPage(nInsertPosition+i)));
     838             : 
     839           0 :     mbUpdateSelectionPending |= (nInsertedPageCount>0);
     840             : 
     841           0 :     return nInsertedPageCount;
     842             : }
     843             : 
     844           0 : Clipboard::DropType Clipboard::IsDropAccepted (DropTargetHelper&) const
     845             : {
     846           0 :     const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
     847           0 :     if (pDragTransferable == NULL)
     848           0 :         return DT_NONE;
     849             : 
     850           0 :     if (pDragTransferable->IsPageTransferable())
     851             :     {
     852           0 :         if (mrSlideSorter.GetModel().GetEditMode() != EM_MASTERPAGE)
     853           0 :             return DT_PAGE;
     854             :         else
     855           0 :             return DT_NONE;
     856             :     }
     857             : 
     858             :     const SdPageObjsTLB::SdPageObjsTransferable* pPageObjsTransferable
     859           0 :         = dynamic_cast<const SdPageObjsTLB::SdPageObjsTransferable*>(pDragTransferable);
     860           0 :     if (pPageObjsTransferable != NULL)
     861           0 :         return DT_PAGE_FROM_NAVIGATOR;
     862             : 
     863           0 :     return DT_SHAPE;
     864             : }
     865             : 
     866           0 : sal_Int8 Clipboard::ExecuteOrAcceptShapeDrop (
     867             :     DropCommand eCommand,
     868             :     const Point& rPosition,
     869             :     const void* pDropEvent,
     870             :     DropTargetHelper& rTargetHelper,
     871             :     ::sd::Window* pTargetWindow,
     872             :     sal_uInt16 nPage,
     873             :     sal_uInt16 nLayer)
     874             : {
     875           0 :     sal_Int8 nResult = 0;
     876             : 
     877             :     // The dropping of a shape is accepted or executed only when there is
     878             :     // DrawViewShell available to which we can forward this call.  This has
     879             :     // technical reasons:  The actual code to accept or execute a shape drop
     880             :     // is implemented in the ViewShell class and uses the page view of the
     881             :     // main edit view.  This is not possible without a DrawViewShell.
     882           0 :     ::boost::shared_ptr<DrawViewShell> pDrawViewShell;
     883           0 :     if (mrSlideSorter.GetViewShell() != NULL)
     884           0 :         pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>(
     885           0 :             mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell());
     886           0 :     if (pDrawViewShell.get() != NULL
     887           0 :         && (pDrawViewShell->GetShellType() == ViewShell::ST_IMPRESS
     888           0 :             || pDrawViewShell->GetShellType() == ViewShell::ST_DRAW))
     889             :     {
     890             :         // The drop is only accepted or executed when it takes place over a
     891             :         // page object.  Therefore we replace a missing page number by the
     892             :         // number of the page under the mouse.
     893           0 :         if (nPage == SDRPAGE_NOTFOUND)
     894             :         {
     895             :             model::SharedPageDescriptor pDescriptor (
     896           0 :                 mrSlideSorter.GetModel().GetPageDescriptor(
     897           0 :                     mrSlideSorter.GetView().GetPageIndexAtPoint(rPosition)));
     898           0 :             if (pDescriptor)
     899           0 :                 nPage = pDescriptor->GetPageIndex();
     900             :         }
     901             : 
     902             :         // Now comes the code that is different for the Execute and Accept:
     903             :         // We simply forward the call to the AcceptDrop() or ExecuteDrop()
     904             :         // methods of the DrawViewShell in the center pane.
     905           0 :         if (nPage != SDRPAGE_NOTFOUND)
     906           0 :             switch (eCommand)
     907             :             {
     908             :                 case DC_ACCEPT:
     909           0 :                     nResult = pDrawViewShell->AcceptDrop(
     910             :                         *static_cast<const AcceptDropEvent*>(pDropEvent),
     911             :                         rTargetHelper,
     912             :                         pTargetWindow,
     913             :                         nPage,
     914           0 :                         nLayer);
     915           0 :                     break;
     916             : 
     917             :                 case DC_EXECUTE:
     918           0 :                     nResult = pDrawViewShell->ExecuteDrop(
     919             :                         *static_cast<const ExecuteDropEvent*>(pDropEvent),
     920             :                         rTargetHelper,
     921             :                         pTargetWindow,
     922             :                         nPage,
     923           0 :                         nLayer);
     924           0 :                     break;
     925             :             }
     926             :     }
     927             : 
     928           0 :     return nResult;
     929             : }
     930             : 
     931          66 : } } } // end of namespace ::sd::slidesorter::controller
     932             : 
     933             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11