sw/source/uibase/inc/conttree.hxx | 6 sw/source/uibase/inc/swcont.hxx | 1 sw/source/uibase/utlui/content.cxx | 247 ++++++++++++++++++------- sw/uiconfig/swriter/ui/navigatorcontextmenu.ui | 2 vcl/source/treelist/treelistbox.cxx | 10 - 5 files changed, 195 insertions(+), 71 deletions(-)
New commits: commit 492c94abe05e5ac213475cdd85f158b7a462f824 Author: Karthik <m...@karthikreddy.org> AuthorDate: Tue Mar 18 16:47:35 2025 +0530 Commit: Jim Raykowski <rayk...@gmail.com> CommitDate: Wed Apr 16 09:05:50 2025 +0200 tdf#139633 Rename objects from tree view in navigator Add functionality to enable inline editing of tree node objects in the navigator panel to rename objects. Change-Id: If9933ab03f19d0e5482a46b1a98b31c075602d20 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183095 Tested-by: Jenkins Reviewed-by: Jim Raykowski <rayk...@gmail.com> diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx index 62f85d3392e4..6ab741bf2744 100644 --- a/sw/source/uibase/inc/conttree.hxx +++ b/sw/source/uibase/inc/conttree.hxx @@ -141,6 +141,8 @@ class SwContentTree final : public SfxListener ImplSVEvent* m_nRowActivateEventId = nullptr; bool m_bSelectTo = false; + bool m_bEditing = false; + std::unique_ptr<weld::TreeIter> m_xOverlayCompareEntry; std::unique_ptr<sdr::overlay::OverlayObject> m_xOverlayObject; @@ -224,6 +226,10 @@ class SwContentTree final : public SfxListener DECL_LINK(MouseMoveHdl, const MouseEvent&, bool); DECL_LINK(MousePressHdl, const MouseEvent&, bool); + DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool); + typedef std::pair<const weld::TreeIter&, OUString> IterString; + DECL_LINK(EditedEntryHdl, const IterString&, bool); + public: SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog); ~SwContentTree(); diff --git a/sw/source/uibase/inc/swcont.hxx b/sw/source/uibase/inc/swcont.hxx index 57908b106834..89f09ca84f45 100644 --- a/sw/source/uibase/inc/swcont.hxx +++ b/sw/source/uibase/inc/swcont.hxx @@ -93,6 +93,7 @@ public: bool IsInvisible() const {return m_bInvisible;} void SetInvisible(){ m_bInvisible = true;} + void SetName(const OUString& rStr) {m_sContentName = rStr;} }; #endif diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx index 4d97da8ec223..1af6edcb3fd4 100644 --- a/sw/source/uibase/utlui/content.cxx +++ b/sw/source/uibase/utlui/content.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <svx/svditer.hxx> #include <comphelper/lok.hxx> #include <comphelper/string.hxx> #include <editeng/frmdiritem.hxx> @@ -1185,6 +1186,9 @@ SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNaviga m_xTreeView->connect_drag_begin(LINK(this, SwContentTree, DragBeginHdl)); m_xTreeView->connect_mouse_move(LINK(this, SwContentTree, MouseMoveHdl)); m_xTreeView->connect_mouse_press(LINK(this, SwContentTree, MousePressHdl)); + m_xTreeView->set_column_editables({true}); + m_xTreeView->connect_editing(LINK(this, SwContentTree, EditingEntryHdl), + LINK(this, SwContentTree, EditedEntryHdl)); for (ContentTypeId i : o3tl::enumrange<ContentTypeId>()) { @@ -2792,6 +2796,164 @@ void SwContentTree::Expand(const weld::TreeIter& rParent, RequestingChildren(rParent); } +IMPL_LINK(SwContentTree, EditingEntryHdl, const weld::TreeIter&, rIter, bool) +{ + SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(rIter)); + m_bEditing = pCnt->GetParent()->IsRenamable(); + return m_bEditing; +} + +IMPL_LINK(SwContentTree, EditedEntryHdl, const IterString&, rIterString, bool) +{ + SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(rIterString.first)); + const ContentTypeId nType = pCnt->GetParent()->GetType(); + const OUString& sNewName = rIterString.second; + + rtl::Reference<SwXTextDocument> xModel + = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); + uno::Reference<container::XNameAccess> xNameAccess, xSecond, xThird; + + // Empty or unchanged name + if (sNewName.isEmpty() || (pCnt->GetName() == rIterString.second)) + { + m_bEditing = false; + return false; + } + + switch (nType) + { + case ContentTypeId::TABLE: + { + xNameAccess = xModel->getTextTables(); + break; + } + break; + case ContentTypeId::GRAPHIC: + { + xNameAccess = xModel->getGraphicObjects(); + xSecond = xModel->getTextFrames(); + xThird = xModel->getEmbeddedObjects(); + } + break; + case ContentTypeId::FRAME: + case ContentTypeId::OLE: + { + if (ContentTypeId::FRAME == nType) + { + xNameAccess = xModel->getTextFrames(); + xSecond = xModel->getEmbeddedObjects(); + } + else + { + xNameAccess = xModel->getEmbeddedObjects(); + xSecond = xModel->getTextFrames(); + } + xThird = xModel->getGraphicObjects(); + } + break; + case ContentTypeId::BOOKMARK: + { + assert(!m_pActiveShell->getIDocumentSettingAccess().get( + DocumentSettingId::PROTECT_BOOKMARKS)); + xNameAccess = xModel->getBookmarks(); + } + break; + case ContentTypeId::REGION: + { + xNameAccess = xModel->getTextSections(); + } + break; + case ContentTypeId::INDEX: + { + rtl::Reference<SwXDocumentIndexes> xIdxAcc = xModel->getSwDocumentIndexes(); + xNameAccess = xIdxAcc; + } + break; + case ContentTypeId::DRAWOBJECT: + { + GotoContent(pCnt); + + SdrView* pSdrView = m_pActiveShell->GetDrawView(); + rtl::Reference<SdrObject> pSelected + = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + + // Drawing Object name uniqueness + SwDrawModel* pModel = m_pActiveShell->getIDocumentDrawModelAccess().GetDrawModel(); + SdrObjListIter aIter(pModel->GetPage(0), SdrIterMode::DeepWithGroups); + while (aIter.IsMore()) + { + SdrObject* pTempObj = aIter.Next(); + if (pSelected != pTempObj && pTempObj->GetName() == sNewName) + { + m_bEditing = false; + return false; + } + + } + + pCnt->SetName(sNewName); + pSelected->SetName(sNewName); + m_pActiveShell->SetModified(); + m_bEditing = false; + return true; + } + default: + break; + } + + OUString sForbiddenChars; + if (ContentTypeId::BOOKMARK == nType) + { + sForbiddenChars = "/\@:*?\";,.#"; + } + else if (ContentTypeId::TABLE == nType) + { + sForbiddenChars = " .<>"; + } + + if (!sForbiddenChars.isEmpty()) + { + for (int i = 0; i < sForbiddenChars.getLength(); i++) + { + if (sNewName.indexOf(sForbiddenChars[i]) != -1) + { + m_bEditing = false; + return false; + } + } + } + + if (xNameAccess.is()) + { + if (xNameAccess->hasByName(sNewName) || (xSecond.is() && xSecond->hasByName(sNewName)) + || (xThird.is() && xThird->hasByName(sNewName))) + { + m_bEditing = false; + return false; + } + + uno::Any aObj = xNameAccess->getByName(pCnt->GetName()); + uno::Reference<uno::XInterface> xTmp; + aObj >>= xTmp; + uno::Reference<container::XNamed> xNamed(xTmp, uno::UNO_QUERY); + + try + { + pCnt->SetName(sNewName); + xNamed->setName(sNewName); + m_bEditing = false; + return true; + } + catch (const uno::RuntimeException) + { + OSL_FAIL("Couldn't rename"); + } + } + + m_bEditing = false; + return false; +} + IMPL_LINK(SwContentTree, ExpandHdl, const weld::TreeIter&, rParent, bool) { Expand(rParent, nullptr); @@ -3475,6 +3637,11 @@ void SwContentTree::ToggleToRoot() bool SwContentTree::HasContentChanged() { + if (m_bEditing) + { + return false; + } + bool bContentChanged = false; // - Run through the local array and the Treelistbox in parallel. @@ -5257,6 +5424,11 @@ IMPL_LINK_NOARG(SwContentTree, FocusInHdl, weld::Widget&, void) IMPL_LINK(SwContentTree, KeyInputHdl, const KeyEvent&, rEvent, bool) { + if (m_bEditing) + { + return false; + } + bool bConsumed = true; const vcl::KeyCode aCode = rEvent.GetKeyCode(); @@ -6083,6 +6255,12 @@ OUString SwContentType::RemoveNewline(const OUString& rEntry) void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) { + if (nMode == EditEntryMode::RENAME) + { + m_xTreeView->start_editing(rEntry); + return; + } + SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(rEntry)); GotoContent(pCnt); const ContentTypeId nType = pCnt->GetParent()->GetType(); @@ -6091,7 +6269,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) if(EditEntryMode::DELETE == nMode) m_bIgnoreDocChange = true; - uno::Reference< container::XNameAccess > xNameAccess, xSecond, xThird; switch(nType) { case ContentTypeId::OUTLINE : @@ -6111,11 +6288,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) { nSlot = FN_TABLE_DELETE_TABLE; } - else if(nMode == EditEntryMode::RENAME) - { - rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); - xNameAccess = xModel->getTextTables(); - } else nSlot = FN_FORMAT_TABLE_DLG; break; @@ -6125,13 +6297,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) { m_pActiveShell->DelRight(); } - else if(nMode == EditEntryMode::RENAME) - { - rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); - xNameAccess = xModel->getGraphicObjects(); - xSecond = xModel->getTextFrames(); - xThird = xModel->getEmbeddedObjects(); - } else nSlot = FN_FORMAT_GRAFIC_DLG; break; @@ -6142,21 +6307,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) { m_pActiveShell->DelRight(); } - else if(nMode == EditEntryMode::RENAME) - { - rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); - if(ContentTypeId::FRAME == nType) - { - xNameAccess = xModel->getTextFrames(); - xSecond = xModel->getEmbeddedObjects(); - } - else - { - xNameAccess = xModel->getEmbeddedObjects(); - xSecond = xModel->getTextFrames(); - } - xThird = xModel->getGraphicObjects(); - } else nSlot = FN_FORMAT_FRAME_DLG; break; @@ -6167,12 +6317,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess(); pMarkAccess->deleteMark(pMarkAccess->findMark(ReferenceMarkerName(pCnt->GetName())), false); } - else if(nMode == EditEntryMode::RENAME) - { - assert(!m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS)); - rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); - xNameAccess = xModel->getBookmarks(); - } else { // allowed despite PROTECT_BOOKMARKS: the dialog itself enforces it @@ -6192,11 +6336,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) m_pActiveShell->GetDoc()->DelSectionFormat( const_cast<SwSectionFormat*>(pSectionFormat), false); } - else if (nMode == EditEntryMode::RENAME) - { - rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); - xNameAccess = xModel->getTextSections(); - } else nSlot = FN_EDIT_REGION; break; @@ -6275,13 +6414,10 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) } break; case EditEntryMode::UPD_IDX: - case EditEntryMode::RENAME: { rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); rtl::Reference< SwXDocumentIndexes> xIdxAcc = xModel->getSwDocumentIndexes(); - if(EditEntryMode::RENAME == nMode) - xNameAccess = xIdxAcc; - else if(xIdxAcc.is() && xIdxAcc->hasByName(pBase->GetTOXName())) + if(xIdxAcc.is() && xIdxAcc->hasByName(pBase->GetTOXName())) { Any aIdx = xIdxAcc->getByName(pBase->GetTOXName()); Reference< XDocumentIndex> xIdx; @@ -6297,8 +6433,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) case ContentTypeId::DRAWOBJECT : if(EditEntryMode::DELETE == nMode) nSlot = SID_DELETE; - else if(nMode == EditEntryMode::RENAME) - nSlot = FN_NAME_SHAPE; else if (nMode == EditEntryMode::EDIT) { vcl::KeyCode aKeyCode(KEY_RETURN, false, false, false, false); @@ -6320,29 +6454,6 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode) if(nSlot) m_pActiveShell->GetView().GetViewFrame(). GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON); - else if(xNameAccess.is()) - { - uno::Any aObj = xNameAccess->getByName(pCnt->GetName()); - uno::Reference< uno::XInterface > xTmp; - aObj >>= xTmp; - uno::Reference< container::XNamed > xNamed(xTmp, uno::UNO_QUERY); - SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); - ScopedVclPtr<AbstractSwRenameXNamedDlg> pDlg(pFact->CreateSwRenameXNamedDlg(m_xTreeView.get(), xNamed, xNameAccess)); - if(xSecond.is()) - pDlg->SetAlternativeAccess( xSecond, xThird); - - OUString sForbiddenChars; - if(ContentTypeId::BOOKMARK == nType) - { - sForbiddenChars = "/\@:*?\";,.#"; - } - else if(ContentTypeId::TABLE == nType) - { - sForbiddenChars = " .<>"; - } - pDlg->SetForbiddenChars(sForbiddenChars); - pDlg->Execute(); - } if(EditEntryMode::DELETE == nMode) { auto nPos = m_xTreeView->vadjustment_get_value(); diff --git a/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui b/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui index 530da9796c21..fa59caf10f85 100644 --- a/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui +++ b/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui @@ -401,7 +401,7 @@ <object class="GtkMenuItem" id="502"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes" context="navigatorcontextmenu|STR_RENAME">_Rename...</property> + <property name="label" translatable="yes" context="navigatorcontextmenu|STR_RENAME">_Rename</property> <property name="use-underline">True</property> </object> </child> diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx index 0448222b4685..1d327274e9dd 100644 --- a/vcl/source/treelist/treelistbox.cxx +++ b/vcl/source/treelist/treelistbox.cxx @@ -1407,8 +1407,10 @@ enum class TreeListButtonType // take care of GetTextOffset when doing changes void SvTreeListBox::SetTabs() { - if( IsEditingActive() ) - EndEditing( true ); + // Moved to SvTreeListBox::Paint to make inplace editing work for X11 in the enhancement patch + // tdf#139663 Rename objects from tree view in navigator. + // if( IsEditingActive() ) + // EndEditing( true ); nTreeFlags &= ~SvTreeFlags::RECALCTABS; nFocusWidth = -1; const WinBits nStyle( GetStyle() ); @@ -2245,7 +2247,11 @@ void SvTreeListBox::Paint(vcl::RenderContext& rRenderContext, const tools::Recta { Control::Paint(rRenderContext, rRect); if (nTreeFlags & SvTreeFlags::RECALCTABS) + { + if (IsEditingActive()) + EndEditing(true); SetTabs(); + } pImpl->Paint(rRenderContext, rRect); //Add visual focus draw