tdf#159428 Prefer heading over bookmarks in Navigator
When a bookmark is in a heading, highlighting the heading
is more important than highlighting the bookmark.
Change-Id: I6348e42b14ece226a25961bd3145193645972e79
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162694
Tested-by: Jenkins
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
diff --git a/sw/qa/uitest/data/tdf159428.odt b/sw/qa/uitest/data/tdf159428.odt
new file mode 100644
index 0000000..6b30d6bf
--- /dev/null
+++ b/sw/qa/uitest/data/tdf159428.odt
Binary files differ
diff --git a/sw/qa/uitest/navigator/tdf159428.py b/sw/qa/uitest/navigator/tdf159428.py
new file mode 100644
index 0000000..3a8634a
--- /dev/null
+++ b/sw/qa/uitest/navigator/tdf159428.py
@@ -0,0 +1,49 @@
# -*- 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, get_url_for_data_file
class tdf159428(UITestCase):
def test_tdf159428(self):
global selectionChangedResult
with self.ui_test.load_file(get_url_for_data_file('tdf159428.odt')):
xWriterDoc = self.xUITest.getTopFocusWindow()
xWriterEdit = xWriterDoc.getChild("writer_edit")
self.xUITest.executeCommand(".uno:Sidebar")
xWriterEdit.executeAction("SIDEBAR", mkPropertyValues({"PANEL": "SwNavigatorPanel"}))
xNavigatorPanel = self.ui_test.wait_until_child_is_available('NavigatorPanel')
xContentTree = xNavigatorPanel.getChild("contenttree")
# select fist bookmark - Heading "H1" should be tracked
self.xUITest.executeCommand(".uno:GoToNextPara")
self.xUITest.executeCommand(".uno:GoToNextPara")
xWriterEdit.executeAction("SELECT", mkPropertyValues({"START_POS": "111", "END_POS": "119"}))
self.ui_test.wait_until_property_is_updated(xContentTree, "SelectEntryText", "H1")
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "H1")
# select second bookmark - Heading "H1 mit Lesezeichen" should be tracked
self.xUITest.executeCommand(".uno:GoToNextPara")
xWriterEdit.executeAction("SELECT", mkPropertyValues({"START_POS": "0", "END_POS": "18"}))
self.ui_test.wait_until_property_is_updated(xContentTree, "SelectEntryText", "H1 mit Lesezeichen")
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "H1 mit Lesezeichen")
# select third bookmark - no heading tracked
self.xUITest.executeCommand(".uno:GoToPrevPara")
self.xUITest.executeCommand(".uno:GoToPrevPara")
self.xUITest.executeCommand(".uno:GoToPrevPara")
xWriterEdit.executeAction("SELECT", mkPropertyValues({"START_POS": "141", "END_POS": "146"}))
self.ui_test.wait_until_property_is_updated(xContentTree, "SelectEntryText", "Lesezeichen 3")
self.assertEqual(get_state_as_dict(xContentTree)["SelectEntryText"], "Lesezeichen 3")
# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 5655b67..b058cf4 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -4305,52 +4305,6 @@ void SwContentTree::UpdateTracking()
aContentAtPos.pFndTextAttr);
return;
}
// bookmarks - track first bookmark at cursor
if (mTrackContentType[ContentTypeId::BOOKMARK] &&
(m_pActiveShell->GetSelectionType() & SelectionType::Text))
{
SwPaM* pCursor = m_pActiveShell->GetCursor();
IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess();
IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
if (pCursor && ppBookmark != pMarkAccess->getBookmarksEnd() &&
!(m_bIsRoot && m_nRootType != ContentTypeId::BOOKMARK))
{
OUString sBookmarkName;
SwPosition* pCursorPoint = pCursor->GetPoint();
while (ppBookmark != pMarkAccess->getBookmarksEnd())
{
if (lcl_IsUiVisibleBookmark(*ppBookmark) &&
*pCursorPoint >= (*ppBookmark)->GetMarkStart() &&
*pCursorPoint <= (*ppBookmark)->GetMarkEnd())
{
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
if (SwContentAtPos aContentAtPos(IsAttrAtPos::RefMark);
m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos) &&
@@ -4440,12 +4394,11 @@ void SwContentTree::UpdateTracking()
// is not the current section
}
}
// outline
if (m_nOutlineTracking == 3)
return;
// find out where the cursor is
const SwOutlineNodes::size_type nActPos = GetWrtShell()->GetOutlinePos(MAXLEVEL);
if (!((m_bIsRoot && m_nRootType != ContentTypeId::OUTLINE) || nActPos == SwOutlineNodes::npos))
if (m_nOutlineTracking != 3
&& !((m_bIsRoot && m_nRootType != ContentTypeId::OUTLINE)
|| nActPos == SwOutlineNodes::npos))
{
// assure outline content type is expanded
// this assumes outline content type is first in treeview
@@ -4527,17 +4480,63 @@ void SwContentTree::UpdateTracking()
}
return bRet;
});
return;
}
else
// bookmarks - track first bookmark at cursor
// tdf#159428 Only when no outline found. Showing the outline is more important than
// showing a bookmark at the cursor position.
if (mTrackContentType[ContentTypeId::BOOKMARK] &&
(m_pActiveShell->GetSelectionType() & SelectionType::Text))
{
// clear treeview selections
if (m_xTreeView->count_selected_rows() > 0)
SwPaM* pCursor = m_pActiveShell->GetCursor();
IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess();
IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
if (pCursor && ppBookmark != pMarkAccess->getBookmarksEnd()
&& !(m_bIsRoot && m_nRootType != ContentTypeId::BOOKMARK))
{
m_xTreeView->unselect_all();
m_xTreeView->set_cursor(-1);
Select();
OUString sBookmarkName;
SwPosition* pCursorPoint = pCursor->GetPoint();
while (ppBookmark != pMarkAccess->getBookmarksEnd())
{
if (lcl_IsUiVisibleBookmark(*ppBookmark)
&& *pCursorPoint >= (*ppBookmark)->GetMarkStart()
&& *pCursorPoint <= (*ppBookmark)->GetMarkEnd())
{
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;
}
}
}
// clear treeview selections
if (m_xTreeView->count_selected_rows() > 0)
{
m_xTreeView->unselect_all();
m_xTreeView->set_cursor(-1);
Select();
}
}
void SwContentTree::SelectOutlinesWithSelection()