sw/qa/uitest/data/tdf151051.odt     |binary
 sw/qa/uitest/navigator/tdf151051.py |   52 ++++++++++++++++++++++++++++++++++++
 sw/source/uibase/utlui/content.cxx  |   41 +++++++++++++++++++++++++++-
 3 files changed, 91 insertions(+), 2 deletions(-)

New commits:
commit 5a06b3b789063e77afe7395226359c6ce8aad156
Author:     Jim Raykowski <rayk...@gmail.com>
AuthorDate: Mon Sep 19 00:44:04 2022 -0800
Commit:     Jim Raykowski <rayk...@gmail.com>
CommitDate: Sat Dec 31 03:49:18 2022 +0000

    tdf#151051 Fix promote/demote outline-level promotes/demotes both
    
    outline nodes for outline nodes with table content as last content
    followed immediately by an outline node
    
    SwCursorShell::MakeOutlineSel function, currently used to select the
    range of outline nodes for outline-level promote/demote, makes a
    cursor selection of outline nodes to the start of the next outline
    node past the outline nodes to be promoted/demoted. The selection is
    then adjusted to the end content of the previous node. When the
    previous node is a table, the selection does not move into the table,
    but remains at the start of outline node that is one node after the
    wanted range. This patch avoids use of the MakeOutlineSel function
    for outline-level promote/demote.
    
    Change-Id: Ida505df6ec172681868e86570ae523494ed7929e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141128
    Tested-by: Jenkins
    Reviewed-by: Jim Raykowski <rayk...@gmail.com>

diff --git a/sw/qa/uitest/data/tdf151051.odt b/sw/qa/uitest/data/tdf151051.odt
new file mode 100644
index 000000000000..d5b680b6bdc2
Binary files /dev/null and b/sw/qa/uitest/data/tdf151051.odt differ
diff --git a/sw/qa/uitest/navigator/tdf151051.py 
b/sw/qa/uitest/navigator/tdf151051.py
new file mode 100644
index 000000000000..1778cc94fe68
--- /dev/null
+++ b/sw/qa/uitest/navigator/tdf151051.py
@@ -0,0 +1,52 @@
+# -*- 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 tdf151051(UITestCase):
+
+    def test_tdf151051(self):
+
+        with self.ui_test.load_file(get_url_for_data_file('tdf151051.odt')):
+            xWriterDoc = self.xUITest.getTopFocusWindow()
+            xWriterEdit = xWriterDoc.getChild('writer_edit')
+
+            self.xUITest.executeCommand('.uno:Sidebar')
+            xWriterEdit.executeAction('SIDEBAR', mkPropertyValues({'PANEL': 
'SwNavigatorPanel'}))
+
+            # wait until the navigator panel is available
+            xNavigatorPanel = 
self.ui_test.wait_until_child_is_available('NavigatorPanel')
+
+            xContentTree = xNavigatorPanel.getChild("contenttree")
+
+            xHeadings = xContentTree.getChild('0')
+            xHeadings.executeAction("EXPAND", tuple())
+
+            xChild = xHeadings.getChild('0')
+            self.assertEqual('0', get_state_as_dict(xChild)['Children'])
+
+            xNavigatorPanel = xWriterEdit.getChild("NavigatorPanel")
+            xToolBar = xNavigatorPanel.getChild("content6")
+            xToolBar.executeAction("CLICK", mkPropertyValues({"POS": "2"})) # 
'promote' button
+
+            xHeadings = xContentTree.getChild('0')
+            xHeadings.executeAction("EXPAND", tuple())
+
+            xChild = xHeadings.getChild('0')
+            xChild.executeAction("EXPAND", tuple())
+
+            # Without the fix in place, this test would have failed with
+            # AssertionError: '1' != '0'
+            self.assertEqual('1', get_state_as_dict(xChild)['Children'])
+
+            self.xUITest.executeCommand('.uno:Sidebar')
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/utlui/content.cxx 
b/sw/source/uibase/utlui/content.cxx
index c2220ad77f19..7b71b5acb08d 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -3599,9 +3599,10 @@ void SwContentTree::ExecCommand(std::string_view rCmd, 
bool bOutlineWithChildren
         }
         pShell->GotoOutline( nActPos); // If text selection != box selection
         pShell->Push();
-        pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren);
         if (bUpDown)
         {
+            // move outline position up/down (outline position promote/demote)
+            pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren);
             const size_t nEntryAbsPos(GetAbsPos(*pCurrentEntry));
             SwOutlineNodes::difference_type nDir = bUp ? -1 : 1;
             if (!bOutlineWithChildren && ((nDir == -1 && nActPos > 0) ||
@@ -3754,8 +3755,44 @@ void SwContentTree::ExecCommand(std::string_view rCmd, 
bool bOutlineWithChildren
         }
         else
         {
+            // move outline left/right (outline level promote/demote)
             if (!pShell->IsProtectedOutlinePara())
-                pShell->OutlineUpDown(bLeft ? -1 : 1);
+            {
+                bool bAllow = true;
+                const SwOutlineNodes& rOutlNds = 
pShell->GetDoc()->GetNodes().GetOutLineNds();
+                const int nActLevel = 
rOutlNds[nActPos]->GetTextNode()->GetAttrOutlineLevel();
+                if (!bLeft)
+                {
+                    // disallow if any outline node to demote will exceed 
MAXLEVEL
+                    SwOutlineNodes::size_type nPos = nActPos;
+                    do
+                    {
+                        int nLevel = 
rOutlNds[nPos]->GetTextNode()->GetAttrOutlineLevel();
+                        if (nLevel == MAXLEVEL)
+                        {
+                            bAllow = false;
+                            break;
+                        }
+                    } while (bOutlineWithChildren && ++nPos < rOutlNds.size() 
&&
+                             
rOutlNds[nPos]->GetTextNode()->GetAttrOutlineLevel() > nActLevel);
+                }
+                else
+                {
+                    // disallow if trying to promote outline of level 1
+                    if (nActLevel == 1)
+                        bAllow = false;
+                }
+                if (bAllow)
+                {
+                    SwOutlineNodes::size_type nPos = nActPos;
+                    do
+                    {
+                        pShell->SwCursorShell::GotoOutline(nPos);
+                        pShell->OutlineUpDown(bLeft ? -1 : 1);
+                    } while (bOutlineWithChildren && ++nPos < rOutlNds.size() 
&&
+                             
rOutlNds[nPos]->GetTextNode()->GetAttrOutlineLevel() > nActLevel);
+                }
+            }
         }
 
         pShell->ClearMark();

Reply via email to