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 <noel.grandin@collabora.co.uk>
diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx
index d5c14c0..8153e4f 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 97f0825..3d0699b 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -38,6 +38,8 @@
#include <osl/diagnose.h>
#include <typeinfo>
#include <unordered_set>
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<OUString>& 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 60cf0bb..cdeb74d 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<sal_Int32>& sortOrder );
void InsertObjectThenMakeNameUnique(SdrObject* pObj);
void InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set<rtl::OUString>& 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 95a38e0..38fcbd9 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 e45441d1..6b750c9 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<rtl::OUString> 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 d83910a..6dfb249 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<rtl::OUString> aNameSet;
const size_t nMarkCount=aSourceObjectsForCopy.GetMarkCount();
for (size_t nm=0; nm<nMarkCount; ++nm) {
SdrMark* pM=aSourceObjectsForCopy.GetMark(nm);
SdrObject* pSource(pM->GetMarkedSdrObj());
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 eec87abc..e49833f 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<nCount) bPagNumsDirty=true;
SetChanged();
SdrHint aHint(SdrHintKind::PageOrderChange, pPage);
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index 7b3d0ba..eaa5abf 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -136,6 +136,8 @@
#include <svdobjplusdata.hxx>
#include <svdobjuserdatalist.hxx>
#include <unordered_set>
#include <boost/optional.hpp>
#include <libxml/xmlwriter.h>
#include <memory>
@@ -3016,6 +3018,44 @@ bool SdrObject::IsTextBox() const
return false;
}
void SdrObject::MakeNameUnique(std::unordered_set<OUString>& 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 8794c23..a6cef06 100644
--- a/svx/source/svdraw/svdpage.cxx
+++ b/svx/source/svdraw/svdpage.cxx
@@ -19,6 +19,7 @@
#include <memory>
#include <cassert>
#include <unordered_set>
#include <svx/svdpage.hxx>
@@ -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<rtl::OUString> aNameSet;
InsertObjectThenMakeNameUnique(pObj, aNameSet);
}
void SdrObjList::InsertObjectThenMakeNameUnique(SdrObject* pObj, std::unordered_set<OUString>& 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<OUString> 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 a65d38c..f18d536 100644
--- a/svx/source/svdraw/svdxcgv.cxx
+++ b/svx/source/svdraw/svdxcgv.cxx
@@ -18,6 +18,7 @@
*/
#include <vector>
#include <unordered_set>
#include <editeng/editdata.hxx>
#include <editeng/editeng.hxx>
#include <rtl/strbuf.hxx>
@@ -301,7 +302,7 @@ bool SdrExchangeView::Paste(
// #i13033#
// New mechanism to re-create the connections of cloned connectors
CloneList aCloneList;
std::unordered_set<rtl::OUString> aNameSet;
for (size_t nOb=0; nOb<nObjCount; ++nOb)
{
const SdrObject* pSrcOb=pSrcPg->GetObj(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 5f6e9c6..2ab4759 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();