sw/qa/uitest/navigator/tdf154521.py |   10 +--
 sw/qa/uitest/navigator/tdf154545.py |   98 ++++++++++++++++++++++++++++++++++++
 sw/source/uibase/inc/conttree.hxx   |    1 
 sw/source/uibase/utlui/content.cxx  |   30 +++++++++--
 4 files changed, 129 insertions(+), 10 deletions(-)

New commits:
commit c4a58634753a84b09f20f7271d6525a6656522d3
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Sat Apr 1 21:40:49 2023 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Sun Apr 2 22:54:14 2023 +0200

    tdf#154545 sw Navigator: select & track nested bookmarks
    
    After selecting a nested bookmark in the Navigator with
    double click or Enter, the selected item changed to the
    item of the main bookmark in the tree list. This jumping
    was very annoying especially with multiple nested bookmarks
    inside the same bookmark.
    
    Navigator didn't track nested bookmarks, i.e. it always
    showed the main bookmark instead of the actual nested one
    under the text cursor.
    
    Change-Id: Ic3f1e8321454d4ad892708e76c001da6eca30cf9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149915
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/qa/uitest/navigator/tdf154521.py 
b/sw/qa/uitest/navigator/tdf154521.py
index 0dca50379fab..ac3c21de3c56 100644
--- a/sw/qa/uitest/navigator/tdf154521.py
+++ b/sw/qa/uitest/navigator/tdf154521.py
@@ -38,12 +38,6 @@ class tdf154521(UITestCase):
         global selectionChangedResult
         with self.ui_test.create_doc_in_start_center("writer") as xDoc:
 
-            # type "foo", and create a bookmark on it
-
-            self.xUITest.executeCommand(".uno:Escape")
-
-            # click on the bookmark name in the Navigator
-
             xWriterDoc = self.xUITest.getTopFocusWindow()
             xWriterEdit = xWriterDoc.getChild("writer_edit")
 
@@ -54,6 +48,10 @@ class tdf154521(UITestCase):
             xToolBar = xNavigatorPanel.getChild("content5")
             xToolBar.executeAction("CLICK", mkPropertyValues({"POS": "0"})) # 
'root' button
 
+            # type "foo", and create a bookmark on it
+
+            self.xUITest.executeCommand(".uno:Escape")
+
             xDoc.Text.insertString(xDoc.Text.getStart(), "foo", False)
             self.xUITest.executeCommand(".uno:SelectAll")
 
diff --git a/sw/qa/uitest/navigator/tdf154545.py 
b/sw/qa/uitest/navigator/tdf154545.py
new file mode 100644
index 000000000000..718f6894a588
--- /dev/null
+++ b/sw/qa/uitest/navigator/tdf154545.py
@@ -0,0 +1,98 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+from uitest.framework import UITestCase
+from libreoffice.uno.propertyvalue import mkPropertyValues
+from uitest.uihelper.common import get_state_as_dict
+import unohelper
+
+class tdf154545(UITestCase):
+
+    def test_tdf154545(self):
+        global selectionChangedResult
+        with self.ui_test.create_doc_in_start_center("writer") as xDoc:
+
+            # click on the bookmark name in the Navigator
+
+            xWriterDoc = self.xUITest.getTopFocusWindow()
+            xWriterEdit = xWriterDoc.getChild("writer_edit")
+
+            self.xUITest.executeCommand(".uno:Sidebar")
+            xWriterEdit.executeAction("SIDEBAR", mkPropertyValues({"PANEL": 
"SwNavigatorPanel"}))
+
+            xNavigatorPanel = xWriterEdit.getChild("NavigatorPanel")
+            xToolBar = xNavigatorPanel.getChild("content5")
+            xToolBar.executeAction("CLICK", mkPropertyValues({"POS": "0"})) # 
'root' button
+
+            # type "foo", and create a bookmark on it
+
+            xDoc.Text.insertString(xDoc.Text.getStart(), "foo", False)
+            self.xUITest.executeCommand(".uno:SelectAll")
+
+            with 
self.ui_test.execute_dialog_through_command(".uno:InsertBookmark", 
close_button="insert"):
+                pass
+
+            # check selected bookmark in Navigator
+
+            xWriterEdit.executeAction("FOCUS", tuple())
+
+            xContentTree = xNavigatorPanel.getChild("contenttree")
+
+            self.ui_test.wait_until_property_is_updated(xContentTree, 
"SelectEntryText", "Bookmark 1")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "Bookmark 
1")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectionCount"], "1")
+
+            self.xUITest.executeCommand(".uno:Escape")
+
+            # create a nested bookmark on the last "o"
+
+            cursor = xDoc.getCurrentController().getViewCursor()
+            cursor.goLeft(1, True)
+
+            with 
self.ui_test.execute_dialog_through_command(".uno:InsertBookmark", 
close_button="insert"):
+                pass
+
+            self.xUITest.executeCommand(".uno:Escape")
+
+            # check selected nested bookmark in Navigator
+
+            # This never occured: Navigator didn't track nested bookmarks
+            self.ui_test.wait_until_property_is_updated(xContentTree, 
"SelectEntryText", "Bookmark 2")
+            # This was Bookmark 1
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "Bookmark 
2")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectionCount"], "1")
+
+            # Select nested bookmark in Navigator
+
+            xContentTree.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"RETURN"}))
+
+            # This jumped to Bookmark 1 after selection
+            self.ui_test.wait_until_property_is_updated(xContentTree, 
"SelectEntryText", "Bookmark 2")
+            # This was Bookmark 1
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "Bookmark 
2")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectionCount"], "1")
+
+            # Try the same selection with Bookmark 1
+            xContentTree.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"UP"}))
+            self.ui_test.wait_until_property_is_updated(xContentTree, 
"SelectEntryText", "Bookmark 1")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "Bookmark 
1")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectionCount"], "1")
+            xContentTree.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"RETURN"}))
+            self.ui_test.wait_until_property_is_updated(xContentTree, 
"SelectEntryText", "Bookmark 1")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "Bookmark 
1")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectionCount"], "1")
+
+            # go to the previous item
+            xContentTree.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"UP"}))
+            self.ui_test.wait_until_property_is_updated(xContentTree, 
"SelectEntryText", "Bookmarks")
+            
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], 
"Bookmarks")
+
+            self.xUITest.executeCommand(".uno:Sidebar")
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/inc/conttree.hxx 
b/sw/source/uibase/inc/conttree.hxx
index 587f1ce19c29..5bcdc9013e89 100644
--- a/sw/source/uibase/inc/conttree.hxx
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -100,6 +100,7 @@ class SwContentTree final : public SfxListener
     o3tl::enumarray<ContentTypeId,std::unique_ptr<SwContentType>>  
m_aHiddenContentArr;
     OUString            m_aContextStrings[CONTEXT_COUNT + 1];
     OUString            m_sInvisible;
+    OUString            m_sSelectedItem;  // last selected item (only 
bookmarks yet)
 
     SwWrtShell*         m_pHiddenShell;   // dropped Doc
     SwWrtShell*         m_pActiveShell;   // the active or a const. open view
diff --git a/sw/source/uibase/utlui/content.cxx 
b/sw/source/uibase/utlui/content.cxx
index 806b207d4d1a..9d9732a2ecd4 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -3917,6 +3917,7 @@ void SwContentTree::UpdateTracking()
             if (pCursor && ppBookmark != pMarkAccess->getBookmarksEnd() &&
                     !(m_bIsRoot && m_nRootType != ContentTypeId::BOOKMARK))
             {
+                OUString sBookmarkName;
                 SwPosition* pCursorPoint = pCursor->GetPoint();
                 while (ppBookmark != pMarkAccess->getBookmarksEnd())
                 {
@@ -3924,13 +3925,32 @@ void SwContentTree::UpdateTracking()
                             *pCursorPoint >= (*ppBookmark)->GetMarkStart() &&
                             *pCursorPoint <= (*ppBookmark)->GetMarkEnd())
                     {
-                        lcl_SelectByContentTypeAndName(this, *m_xTreeView,
-                                                       
SwResId(STR_CONTENT_TYPE_BOOKMARK),
-                                                       
(*ppBookmark)->GetName());
-                        return;
+                        sBookmarkName = (*ppBookmark)->GetName();
+                        // keep previously selected bookmark instead
+                        // of selecting a different bookmark inside of it
+                        if (sBookmarkName == m_sSelectedItem)
+                            break;
+                    }
+                    else if (!sBookmarkName.isEmpty() &&
+                        *pCursorPoint < (*ppBookmark)->GetMarkStart())
+                    {
+                        // don't search a different bookmark inside the
+                        // previous one, if the starting position of the next 
bookmarks
+                        // is after the cursor position (assuming that the
+                        // bookmark iterator jumps inside the same text by 
positions)
+                        break;
                     }
                     ++ppBookmark;
                 }
+
+                if (!sBookmarkName.isEmpty())
+                {
+                    // select the bookmark
+                    lcl_SelectByContentTypeAndName(this, *m_xTreeView,
+                                                       
SwResId(STR_CONTENT_TYPE_BOOKMARK),
+                                                       sBookmarkName);
+                    return;
+                }
             }
         }
         // references
@@ -5342,6 +5362,7 @@ void SwContentTree::CopyOutlineSelections()
 void SwContentTree::GotoContent(const SwContent* pCnt)
 {
     m_nLastGotoContentWasOutlinePos = SwOutlineNodes::npos;
+    m_sSelectedItem = "";
     lcl_AssureStdModeAtShell(m_pActiveShell);
     switch(m_nLastSelType = pCnt->GetParent()->GetType())
     {
@@ -5376,6 +5397,7 @@ void SwContentTree::GotoContent(const SwContent* pCnt)
             m_pActiveShell->StartAction();
             m_pActiveShell->GotoMark(pCnt->GetName());
             m_pActiveShell->EndAction();
+            m_sSelectedItem = pCnt->GetName();
         }
         break;
         case ContentTypeId::REGION    :

Reply via email to