From 14d05c9b852a0f94c6cbace7cd7887523a89d7d1 Mon Sep 17 00:00:00 2001 From: Justin Luth Date: Wed, 28 Dec 2016 22:04:43 +0300 Subject: tdf#64588 - prevent loss of non-uniquely-named slide Although the UI prevents someone from renaming slides so that two have the same name, it is still possible to have such non-uniquely named pages apparently. Since drag/drop uses the name to add a slide to the clipboard, it resulted in duplicates of the first found instance of the slidename, and loss of the similarly-named slides when they were dragged to a new location. Change-Id: I2986a7c6c3360162adf9430f645d0dfc73f1d4e2 Reviewed-on: https://gerrit.libreoffice.org/32481 Tested-by: Jenkins Reviewed-by: Justin Luth Reviewed-by: Thorsten Behrens --- sd/inc/drawdoc.hxx | 7 ++++ sd/source/core/drawdoc2.cxx | 37 ++++++++++++++++++++++ sd/source/ui/docshell/docshel2.cxx | 5 +++ sd/source/ui/inc/DrawDocShell.hxx | 8 +++++ .../ui/slidesorter/controller/SlsClipboard.cxx | 17 ++++++++++ 5 files changed, 74 insertions(+) diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index 8c491cd428d1..23a42accc349 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -355,6 +355,13 @@ public: SDRPAGE_NOTFOUND (=0xffff) when such a page does not exist. */ SAL_DLLPRIVATE sal_uInt16 GetPageByName(const OUString& rPgName, bool& rbIsMasterPage ) const; + /** checks, if the given name is a *unique* name for an *existing* slide + + @param rPageName the name of an existing slide + + @return true, if the name is unique and the slide exists + */ + bool IsPageNameUnique( const OUString& rPageName ) const; SdPage*GetSdPage(sal_uInt16 nPgNum, PageKind ePgKind) const; sal_uInt16 GetSdPageCount(PageKind ePgKind) const; diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx index 747d316f28c8..190f5c0914c9 100644 --- a/sd/source/core/drawdoc2.cxx +++ b/sd/source/core/drawdoc2.cxx @@ -184,6 +184,43 @@ sal_uInt16 SdDrawDocument::GetPageByName(const OUString& rPgName, bool& rbIsMast return nPageNum; } +bool SdDrawDocument::IsPageNameUnique( const OUString& rPgName ) const +{ + sal_uInt16 nCount = 0; + SdPage* pPage = nullptr; + + // Search all regular pages and all notes pages (handout pages are ignored) + sal_uInt16 nPage = 0; + sal_uInt16 nMaxPages = GetPageCount(); + while (nPage < nMaxPages) + { + pPage = const_cast(static_cast(GetPage(nPage))); + + if (pPage && pPage->GetName() == rPgName && pPage->GetPageKind() != PageKind::Handout) + nCount++; + + nPage++; + } + + // Search all master pages + nPage = 0; + nMaxPages = GetMasterPageCount(); + while (nPage < nMaxPages) + { + pPage = const_cast(static_cast(GetMasterPage(nPage))); + + if (pPage && pPage->GetName() == rPgName) + nCount++;; + + nPage++; + } + + if (nCount == 1) + return true; + else + return false; +} + SdPage* SdDrawDocument::GetSdPage(sal_uInt16 nPgNum, PageKind ePgKind) const { return mpDrawPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum)); diff --git a/sd/source/ui/docshell/docshel2.cxx b/sd/source/ui/docshell/docshel2.cxx index ecb95ba5fe16..af8320e8a531 100644 --- a/sd/source/ui/docshell/docshel2.cxx +++ b/sd/source/ui/docshell/docshel2.cxx @@ -406,6 +406,11 @@ bool DrawDocShell::IsNewPageNameValid( OUString & rInOutPageName, bool bResetStr return bCanUseNewName; } +bool DrawDocShell::IsPageNameUnique( const OUString & rPageName ) const +{ + return mpDoc->IsPageNameUnique(rPageName); +} + IMPL_LINK( DrawDocShell, RenameSlideHdl, AbstractSvxNameDialog&, rDialog, bool ) { OUString aNewName; diff --git a/sd/source/ui/inc/DrawDocShell.hxx b/sd/source/ui/inc/DrawDocShell.hxx index 8d1ad05b001b..ccb139532641 100644 --- a/sd/source/ui/inc/DrawDocShell.hxx +++ b/sd/source/ui/inc/DrawDocShell.hxx @@ -183,6 +183,14 @@ public: */ bool IsNewPageNameValid( OUString & rInOutPageName, bool bResetStringIfStandardName = false ); + /** checks, if the given name is a *unique* name for an *existing* slide + + @param rPageName the name of an existing slide + + @return true, if the name is unique and the slide exists + */ + bool IsPageNameUnique(const OUString& rPagName) const; + /** Return the reference device for the current document. When the inherited implementation returns a device then this is passed to the caller. Otherwise the returned value depends on the printer diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx index cb73c3dc9fb7..5014da6d0ec6 100644 --- a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx +++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx @@ -389,9 +389,26 @@ void Clipboard::CreateSlideTransferable ( SdDrawDocument* const pDocument = mrSlideSorter.GetModel().GetDocument(); DrawDocShell* const pDataDocSh = pDocument ? pDocument->GetDocSh() : nullptr; + sal_Int32 nUniqueID = 0; while (aSelectedPages.HasMoreElements()) { model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement()); + + //ensure that the slides have unique names + const OUString sOrigName = pDescriptor->GetPage()->GetName(); + if ( pDataDocSh && !pDataDocSh->IsPageNameUnique( sOrigName ) ) + { + OUString sUniqueName; + bool bUnique = false; + while ( !bUnique ) + { + sUniqueName = sOrigName + "_clipboard" + OUString::number(nUniqueID++); + bUnique = pDataDocSh->IsNewPageNameValid( sUniqueName ); + if ( bUnique ) + pDescriptor->GetPage()->SetName(sUniqueName); + } + } + aBookmarkList.push_back(pDescriptor->GetPage()->GetName()); maPagesToRemove.push_back (pDescriptor->GetPage()); } -- cgit