From 9f86b320a997c77069cf93dcb32fb71f09ad1348 Mon Sep 17 00:00:00 2001 From: Jim Raykowski Date: Thu, 15 Aug 2019 00:31:25 -0800 Subject: tdf#125191 Give object copies unique names This patch makes a unique name for a copy of an object having a user given name. Change-Id: I14a7f45cc02962fc34a1532dd5db1cb9657b41d3 Reviewed-on: https://gerrit.libreoffice.org/77500 Tested-by: Jenkins Reviewed-by: Noel Grandin --- include/svx/svdmodel.hxx | 7 +++ include/svx/svdobj.hxx | 3 ++ include/svx/svdpage.hxx | 5 ++ .../ui/slidesorter/controller/SlsClipboard.cxx | 12 ++++- sd/source/ui/view/sdview3.cxx | 7 ++- svx/source/svdraw/svdedtv.cxx | 3 +- svx/source/svdraw/svdmodel.cxx | 3 ++ svx/source/svdraw/svdobj.cxx | 40 ++++++++++++++++ svx/source/svdraw/svdpage.cxx | 54 ++++++++++++++++++++++ svx/source/svdraw/svdxcgv.cxx | 5 +- sw/source/core/doc/doclay.cxx | 4 +- 11 files changed, 136 insertions(+), 7 deletions(-) diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index d5c14c0baa57..8153e4f915cc 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -260,6 +260,9 @@ private: // this is a weak reference to a possible living api wrapper for this model css::uno::Reference< css::uno::XInterface > mxUnoModel; + // used to disable unique name checking during page move + bool mbMakePageObjectsNamesUnique = true; + public: SVX_DLLPRIVATE virtual bool IsCreatingDataObj() const { return false; } bool IsTransportContainer() const { return bTransportContainer; } @@ -597,6 +600,10 @@ public: also during the runtime of the Undo() and Redo() methods. */ bool IsUndoEnabled() const; + // used to prevent object name change during page move + bool DoesMakePageObjectsNamesUnique() const { return mbMakePageObjectsNamesUnique; } + void DoMakePageObjectsNamesUnique(bool bDo) { mbMakePageObjectsNamesUnique = bDo; } + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; }; diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx index 97f082563281..3d0699b3f63c 100644 --- a/include/svx/svdobj.hxx +++ b/include/svx/svdobj.hxx @@ -38,6 +38,8 @@ #include #include +#include + class SfxBroadcaster; class AutoTimer; class OutlinerParaObject; @@ -425,6 +427,7 @@ public: // It may also have a Title and a Description for accessibility purposes. void SetName(const OUString& rStr); OUString GetName() const; + void MakeNameUnique(std::unordered_set& rNameSet); void SetTitle(const OUString& rStr); OUString GetTitle() const; void SetDescription(const OUString& rStr); diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx index 60cf0bb49004..cdeb74d3714b 100644 --- a/include/svx/svdpage.hxx +++ b/include/svx/svdpage.hxx @@ -110,6 +110,9 @@ public: virtual void InsertObject(SdrObject* pObj, size_t nPos=SAL_MAX_SIZE); virtual void sort( std::vector& sortOrder ); + void InsertObjectThenMakeNameUnique(SdrObject* pObj); + void InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set& rNameSet, size_t nPos=SAL_MAX_SIZE); + /// remove from list without delete virtual SdrObject* NbcRemoveObject(size_t nObjNum); virtual SdrObject* RemoveObject(size_t nObjNum); @@ -487,6 +490,8 @@ public: void TRG_SetMasterPageVisibleLayers(const SdrLayerIDSet& rNew); sdr::contact::ViewContact& TRG_GetMasterPageDescriptorViewContact() const; + void MakePageObjectsNamesUnique(); + protected: void TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage); public: diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx index 95a38e0ee03f..38fcbd964f18 100644 --- a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx +++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx @@ -730,7 +730,17 @@ sal_Int8 Clipboard::ExecuteDrop ( mrSlideSorter.GetViewShell()->GetViewShellBase().GetMainViewShell())); mxSelectionObserverContext.reset(new SelectionObserver::Context(mrSlideSorter)); - HandlePageDrop(*pDragTransferable); + if (rEvent.mnAction == DND_ACTION_MOVE) + { + SdDrawDocument* pDoc = mrSlideSorter.GetModel().GetDocument(); + const bool bDoesMakePageObjectsNamesUnique = pDoc->DoesMakePageObjectsNamesUnique(); + pDoc->DoMakePageObjectsNamesUnique(false); + HandlePageDrop(*pDragTransferable); + pDoc->DoMakePageObjectsNamesUnique(bDoesMakePageObjectsNamesUnique); + } + else + HandlePageDrop(*pDragTransferable); + nResult = rEvent.mnAction; // We leave the undo context alive for when moving or diff --git a/sd/source/ui/view/sdview3.cxx b/sd/source/ui/view/sdview3.cxx index e45441d1affe..6b750c9cb6bd 100644 --- a/sd/source/ui/view/sdview3.cxx +++ b/sd/source/ui/view/sdview3.cxx @@ -463,6 +463,7 @@ bool View::InsertData( const TransferableDataHelper& rDataHelper, const Size aVector( maDropPos.X() - aCurPos.X(), maDropPos.Y() - aCurPos.Y() ); + std::unordered_set aNameSet; for(size_t a = 0; a < pMarkList->GetMarkCount(); ++a) { SdrMark* pM = pMarkList->GetMark(a); @@ -476,7 +477,11 @@ bool View::InsertData( const TransferableDataHelper& rDataHelper, pObj->NbcMove(aVector); } - pPage->InsertObject(pObj); + SdrObject* pMarkParent = pM->GetMarkedSdrObj()->getParentSdrObjectFromSdrObject(); + if (bCopy || (pMarkParent && pMarkParent->IsGroupObject())) + pPage->InsertObjectThenMakeNameUnique(pObj, aNameSet); + else + pPage->InsertObject(pObj); if( IsUndoEnabled() ) { diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx index d83910a86746..6dfb249d911c 100644 --- a/svx/source/svdraw/svdedtv.cxx +++ b/svx/source/svdraw/svdedtv.cxx @@ -903,13 +903,14 @@ void SdrEditView::CopyMarkedObj() GetMarkedObjectListWriteAccess().Clear(); size_t nCloneErrCnt=0; + std::unordered_set aNameSet; const size_t nMarkCount=aSourceObjectsForCopy.GetMarkCount(); for (size_t nm=0; nmGetMarkedSdrObj()); SdrObject* pO(pSource->CloneSdrObject(pSource->getSdrModelFromSdrObject())); if (pO!=nullptr) { - pM->GetPageView()->GetObjList()->InsertObject(pO, SAL_MAX_SIZE); + pM->GetPageView()->GetObjList()->InsertObjectThenMakeNameUnique(pO, aNameSet); if( bUndo ) AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoCopyObject(*pO)); diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx index eec87abcdf73..e49833f13c5c 100644 --- a/svx/source/svdraw/svdmodel.cxx +++ b/svx/source/svdraw/svdmodel.cxx @@ -1309,6 +1309,9 @@ void SdrModel::InsertPage(SdrPage* pPage, sal_uInt16 nPos) pPage->SetInserted(); pPage->SetPageNum(nPos); + if (mbMakePageObjectsNamesUnique) + pPage->MakePageObjectsNamesUnique(); + if (nPos #include +#include + #include #include #include @@ -3016,6 +3018,44 @@ bool SdrObject::IsTextBox() const return false; } +void SdrObject::MakeNameUnique(std::unordered_set& rNameSet) +{ + if (GetName().isEmpty()) + return; + + if (rNameSet.empty()) + { + SdrPage* pPage; + SdrObject* pObj; + for (sal_uInt16 nPage(0); nPage < mrSdrModelFromSdrObject.GetPageCount(); ++nPage) + { + pPage = mrSdrModelFromSdrObject.GetPage(nPage); + SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups); + while (aIter.IsMore()) + { + pObj = aIter.Next(); + if (pObj != this) + rNameSet.insert(pObj->GetName()); + } + } + } + + OUString sName(GetName()); + OUString sRootName(GetName()); + sal_Int32 index = sName.lastIndexOf("_"); + if ( index > 0) + sRootName = sRootName.copy(0, index); + + sal_uInt32 n = 0; + while (rNameSet.find(sName) != rNameSet.end()) + { + sName = sRootName + "_" + OUString::number(n++); + } + rNameSet.insert(sName); + + SetName(sName); +} + SdrObject* SdrObjFactory::CreateObjectFromFactory(SdrModel& rSdrModel, SdrInventor nInventor, sal_uInt16 nObjIdentifier) { SdrObjCreatorParams aParams { nInventor, nObjIdentifier, rSdrModel }; diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx index 8794c2355dd0..a6cef0633542 100644 --- a/svx/source/svdraw/svdpage.cxx +++ b/svx/source/svdraw/svdpage.cxx @@ -19,6 +19,7 @@ #include #include +#include #include @@ -328,6 +329,32 @@ void SdrObjList::NbcInsertObject(SdrObject* pObj, size_t nPos) pObj->InsertedStateChange(); // calls the UserCall (among others) } +void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj) +{ + std::unordered_set aNameSet; + InsertObjectThenMakeNameUnique(pObj, aNameSet); +} + +void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set& rNameSet, size_t nPos) +{ + InsertObject(pObj, nPos); + if (!pObj->GetName().isEmpty()) + { + pObj->MakeNameUnique(rNameSet); + SdrObjList* pSdrObjList = pObj->GetSubList(); // group + if (pSdrObjList) + { + SdrObject* pListObj; + SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups); + while (aIter.IsMore()) + { + pListObj = aIter.Next(); + pListObj->MakeNameUnique(rNameSet); + } + } + } +} + void SdrObjList::InsertObject(SdrObject* pObj, size_t nPos) { DBG_ASSERT(pObj!=nullptr,"SdrObjList::InsertObject(NULL)"); @@ -1573,6 +1600,33 @@ void SdrPage::TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage) } } +void SdrPage::MakePageObjectsNamesUnique() +{ + std::unordered_set aNameSet; + for (size_t no(0); no < GetObjCount(); ++no) + { + SdrObject* pObj(GetObj(no)); + if(nullptr != pObj) + { + if (!pObj->GetName().isEmpty()) + { + pObj->MakeNameUnique(aNameSet); + SdrObjList* pSdrObjList = pObj->GetSubList(); // group + if (pSdrObjList) + { + SdrObject* pListObj; + SdrObjListIter aIter(pSdrObjList, SdrIterMode::DeepWithGroups); + while (aIter.IsMore()) + { + pListObj = aIter.Next(); + pListObj->MakeNameUnique(aNameSet); + } + } + } + } + } +} + const SdrPageGridFrameList* SdrPage::GetGridFrameList(const SdrPageView* /*pPV*/, const tools::Rectangle* /*pRect*/) const { return nullptr; diff --git a/svx/source/svdraw/svdxcgv.cxx b/svx/source/svdraw/svdxcgv.cxx index a65d38c8738d..f18d536b7bf2 100644 --- a/svx/source/svdraw/svdxcgv.cxx +++ b/svx/source/svdraw/svdxcgv.cxx @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -301,7 +302,7 @@ bool SdrExchangeView::Paste( // #i13033# // New mechanism to re-create the connections of cloned connectors CloneList aCloneList; - + std::unordered_set aNameSet; for (size_t nOb=0; nObGetObj(nOb); @@ -346,7 +347,7 @@ bool SdrExchangeView::Paste( pNewObj->SetLayer(nLayer); } - pDstLst->InsertObject(pNewObj, SAL_MAX_SIZE); + pDstLst->InsertObjectThenMakeNameUnique(pNewObj, aNameSet); if( bUndo ) AddUndo(getSdrModelFromSdrView().GetSdrUndoFactory().CreateUndoNewObject(*pNewObj)); diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx index 5f6e9c669533..2ab4759ec70b 100644 --- a/sw/source/core/doc/doclay.cxx +++ b/sw/source/core/doc/doclay.cxx @@ -142,12 +142,12 @@ SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, bool bMoveWithinDoc, if( xSet.is() ) aVal = xSet->getPropertyValue( sName ); if( bInsInPage ) - pPg->InsertObject( pObj ); + pPg->InsertObjectThenMakeNameUnique( pObj ); if( xSet.is() ) xSet->setPropertyValue( sName, aVal ); } else if( bInsInPage ) - pPg->InsertObject( pObj ); + pPg->InsertObjectThenMakeNameUnique( pObj ); // For drawing objects: set layer of cloned object to invisible layer SdrLayerID nLayerIdForClone = rObj.GetLayer(); -- cgit