[Libreoffice-commits] core.git: sw/inc sw/source sw/uiconfig

Jim Raykowski (via logerrit) logerrit at kemper.freedesktop.org
Thu Jul 30 10:05:46 UTC 2020


 sw/inc/strings.hrc                             |    4 
 sw/source/uibase/inc/conttree.hxx              |    2 
 sw/source/uibase/utlui/content.cxx             |  178 ++++++++++++++++++++++++-
 sw/uiconfig/swriter/ui/navigatorcontextmenu.ui |   20 ++
 4 files changed, 199 insertions(+), 5 deletions(-)

New commits:
commit dce97e84f2bb748e4403841593bb7b0b92ea44c4
Author:     Jim Raykowski <raykowj at gmail.com>
AuthorDate: Mon Jul 27 21:03:58 2020 -0800
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Thu Jul 30 12:04:56 2020 +0200

    tdf#38093 Writer outline folding - Navigator UI
    
    Patch 5/6 that breaks down https://gerrit.libreoffice.org/c/core/+/96672
    
    Adds submenu 'Outline Content Visibilty' and action handling for submenu
    items to Navigator Headings context menu.
    
    Change-Id: Iccdcbc7518a83cc1b2e2e75f3052f8dbbffb1338
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99656
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 20d45f5cc19b..a9b2ab36d587 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -647,6 +647,10 @@
 #define STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT   NC_("STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT", "hold Ctrl or right-click to include sub levels")
 #define STR_ClICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY     NC_("STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY", "Click to Toggle Outline Content Visibility")
 #define STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT NC_("STR_CLICK_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT", "right-click to include sub levels")
+#define STR_OUTLINE_CONTENT_VISIBILITY          NC_("STR_OUTLINE_CONTENT", "Outline Content Visibility")
+#define STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE   NC_("STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE", "Toggle")
+#define STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL NC_("STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL", "Show All")
+#define STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL NC_("STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL", "Hide All")
 
 #define STR_EXPANDALL                           NC_("STR_EXPANDALL", "Expand All")
 #define STR_COLLAPSEALL                         NC_("STR_COLLAPSEALL", "Collapse All")
diff --git a/sw/source/uibase/inc/conttree.hxx b/sw/source/uibase/inc/conttree.hxx
index 0a090a1d18f0..6f65b1984523 100644
--- a/sw/source/uibase/inc/conttree.hxx
+++ b/sw/source/uibase/inc/conttree.hxx
@@ -121,7 +121,7 @@ class SwContentTree final : public SfxListener
     // outline root mode drag & drop
     std::vector<std::unique_ptr<weld::TreeIter>> m_aDndOutlinesSelected;
 
-    bool m_bIsInPromoteDemote = false;
+    bool m_bIgnoreViewChange = false;
 
     /**
      * Before any data will be deleted, the last active entry has to be found.
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 1fcd1873d8f3..e92cddc641ef 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -1152,6 +1152,122 @@ static bool lcl_InsertExpandCollapseAllItem(weld::TreeView& rContentTree, weld::
     return true;
 }
 
+static void lcl_SetOutlineContentEntriesSensitivities(SwContentTree* pThis, weld::TreeView& rContentTree, weld::TreeIter& rEntry, weld::Menu& rPop)
+{
+    rPop.set_sensitive(OString::number(1512), false);
+    rPop.set_sensitive(OString::number(1513), false);
+    rPop.set_sensitive(OString::number(1514), false);
+
+    if (!pThis->GetActiveWrtShell()->GetViewOptions()->IsShowOutlineContentVisibilityButton())
+        return;
+
+    // todo: multi selection
+    if (rContentTree.count_selected_rows() > 1)
+        return;
+
+    const SwNodes& rNodes = pThis->GetWrtShell()->GetNodes();
+    const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
+    size_t nOutlinePos = weld::GetAbsPos(rContentTree, rEntry);
+
+    bool bIsRoot = lcl_IsContentType(rEntry, rContentTree);
+
+    if (!bIsRoot)
+        --nOutlinePos;
+
+    if (nOutlinePos >= rOutlineNodes.size())
+         return;
+
+    int nFirstLevel = pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
+    {
+        // determine if any concerned outline node has content
+        bool bHasContent(false);
+        size_t nPos = nOutlinePos;
+        SwNode* pSttNd = rOutlineNodes[nPos];
+        SwNode* pEndNd = &rNodes.GetEndOfContent();
+        if (rOutlineNodes.size() > nPos + 1)
+            pEndNd = rOutlineNodes[nPos + 1];
+
+        // selected
+        SwNodeIndex aIdx(*pSttNd);
+        if (rNodes.GoNext(&aIdx) != pEndNd)
+            bHasContent = true;
+
+        // decendants
+        if (!bHasContent && (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry)))
+        {
+            while (++nPos < rOutlineNodes.size() &&
+                  (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
+            {
+                pSttNd = rOutlineNodes[nPos];
+                pEndNd = &rNodes.GetEndOfContent();
+                if (rOutlineNodes.size() > nPos + 1)
+                    pEndNd = rOutlineNodes[nPos + 1];
+
+                // test for content in outline node
+                aIdx.Assign(*pSttNd);
+                if (rNodes.GoNext(&aIdx) != pEndNd)
+                {
+                    bHasContent = true;
+                    break;
+                }
+            }
+        }
+
+        if (!bHasContent)
+            return; // no content in any of the concerned outline nodes
+    }
+
+    // determine for subs if all are folded or unfolded or if they are mixed
+    if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry))
+    {
+        // skip no content nodes
+        // we know there is content from results above so this is presumably safe
+        size_t nPos = nOutlinePos;
+        while (true)
+        {
+            SwNode* pSttNd = rOutlineNodes[nPos];
+            SwNode* pEndNd = rOutlineNodes.back();
+            if (!bIsRoot && rOutlineNodes.size() > nPos + 1)
+                pEndNd = rOutlineNodes[nPos + 1];
+
+            SwNodeIndex aIdx(*pSttNd);
+            if (rNodes.GoNext(&aIdx) != pEndNd)
+                break;
+            nPos++;
+        }
+
+        bool bHasFolded(pThis->GetWrtShell()->IsOutlineContentFolded(nPos));
+        bool bHasUnfolded(!bHasFolded);
+
+        while ((++nPos < pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount()) &&
+               (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
+        {
+
+            SwNode* pSttNd = rOutlineNodes[nPos];
+            SwNode* pEndNd = &rNodes.GetEndOfContent();
+            if (rOutlineNodes.size() > nPos + 1)
+                pEndNd = rOutlineNodes[nPos + 1];
+
+            SwNodeIndex aIdx(*pSttNd);
+            if (rNodes.GoNext(&aIdx) == pEndNd)
+                continue; // skip if no content
+
+            if (pThis->GetWrtShell()->IsOutlineContentFolded(nPos))
+                bHasFolded = true;
+            else
+                bHasUnfolded = true;
+
+            if (bHasFolded && bHasUnfolded)
+                break; // mixed so no need to continue
+        }
+
+        rPop.set_sensitive(OString::number(1513), bHasUnfolded);
+        rPop.set_sensitive(OString::number(1514), bHasFolded);
+    }
+
+    bIsRoot ? rPop.remove(OString::number(1512)) : rPop.set_sensitive(OString::number(1512), true);
+}
+
 IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
 {
     if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
@@ -1166,6 +1282,11 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
     std::unique_ptr<weld::Menu> xSubPop3 = xBuilder->weld_menu("displaymenu");
     std::unique_ptr<weld::Menu> xSubPopOutlineTracking = xBuilder->weld_menu("outlinetracking");
 
+    std::unique_ptr<weld::Menu> xSubPopOutlineContent = xBuilder->weld_menu("outlinecontent");
+    xSubPopOutlineContent->append(OUString::number(1512), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE));
+    xSubPopOutlineContent->append(OUString::number(1513), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL));
+    xSubPopOutlineContent->append(OUString::number(1514), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL));
+
     for(int i = 1; i <= 3; ++i)
         xSubPopOutlineTracking->append_radio(OUString::number(i + 10), m_aContextStrings[IDX_STR_OUTLINE_TRACKING + i]);
     xSubPopOutlineTracking->set_active(OString::number(10 + m_nOutlineTracking), true);
@@ -1259,6 +1380,7 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
         if(ContentTypeId::OUTLINE == nContentType)
         {
             bOutline = true;
+            lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
             bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop);
             if (!bReadonly)
             {
@@ -1326,6 +1448,7 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
         if (ContentTypeId::OUTLINE == pType->GetType())
         {
             bOutline = true;
+            lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
             bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop);
             bRemoveSendOutlineEntry = false;
         }
@@ -1402,6 +1525,14 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
         xSubPopOutlineTracking.reset();
         xPop->remove(OString::number(4)); // outline tracking menu
     }
+    if (!bOutline
+            || !m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton()
+            || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() == 0)
+    {
+        xSubPopOutlineContent.reset();
+        xPop->remove(OString::number(5)); // outline content menu
+        xPop->remove("separator1511");
+    }
 
     OString sCommand = xPop->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
     if (!sCommand.isEmpty())
@@ -2036,7 +2167,7 @@ void SwContentTree::Display( bool bActive )
         }
     }
 
-    if (!m_bIsInPromoteDemote && GetEntryCount() == nOldEntryCount)
+    if (!m_bIgnoreViewChange && GetEntryCount() == nOldEntryCount)
     {
         m_xTreeView->vadjustment_set_value(nOldScrollPos);
     }
@@ -2545,7 +2676,7 @@ void SwContentTree::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
     switch (rHint.GetId())
     {
         case SfxHintId::DocChanged:
-            if (!m_bIsInPromoteDemote)
+            if (!m_bIgnoreViewChange)
             {
                 m_bViewHasChanged = true;
                 TimerUpdate(&m_aUpdTimer);
@@ -2590,7 +2721,7 @@ void SwContentTree::ExecCommand(const OString& rCmd, bool bOutlineWithChildren)
         return;
     }
 
-    m_bIsInPromoteDemote = true;
+    m_bIgnoreViewChange = true;
 
     SwWrtShell *const pShell = GetWrtShell();
     sal_Int8 nActOutlineLevel = m_nOutlineLevel;
@@ -2911,7 +3042,7 @@ void SwContentTree::ExecCommand(const OString& rCmd, bool bOutlineWithChildren)
             }
         }
     }
-    m_bIsInPromoteDemote = false;
+    m_bIgnoreViewChange = false;
 }
 
 void SwContentTree::ShowTree()
@@ -3421,6 +3552,45 @@ void SwContentTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry)
     auto nSelectedPopupEntry = rSelectedPopupEntry.toUInt32();
     switch (nSelectedPopupEntry)
     {
+        case 1512: // fold or unfold outline content of selected entry
+        case 1513: // fold outline content of selected entry and decendents
+        case 1514: // unfold outline content of selected entry and decendents
+        {
+            m_pActiveShell->EnterStdMode();
+            m_bIgnoreViewChange = true;
+            SwOutlineContent* pCntFirst = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xFirst).toInt64());
+            if (nSelectedPopupEntry == 1512)
+            {
+                m_pActiveShell->ToggleOutlineContentVisibility(pCntFirst->GetOutlinePos());
+            }
+            else
+            {
+                // with subs
+                SwOutlineNodes::size_type nPos = pCntFirst->GetOutlinePos();
+                if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
+                    nPos = SwOutlineNodes::npos;
+                SwOutlineNodes::size_type nOutlineNodesCount = m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+                int nLevel = -1;
+                if (nPos != SwOutlineNodes::npos) // not root
+                    nLevel = m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos);
+                else
+                    nPos = 0;
+                bool bFold(nSelectedPopupEntry == 1514);
+                do
+                {
+                    if (m_pActiveShell->IsOutlineContentFolded(nPos) == bFold)
+                        m_pActiveShell->ToggleOutlineContentVisibility(nPos);
+                } while (++nPos < nOutlineNodesCount
+                         && (nLevel == -1 || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel));
+            }
+            if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
+                m_pActiveShell->GotoPage(1, true);
+            else
+                GotoContent(pCntFirst);
+            grab_focus();
+            m_bIgnoreViewChange = false;
+        }
+        break;
         case 11:
         case 12:
         case 13:
diff --git a/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui b/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui
index b324c1a26c74..aecbc2cb1852 100644
--- a/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui
+++ b/sw/uiconfig/swriter/ui/navigatorcontextmenu.ui
@@ -182,6 +182,26 @@
         <property name="can_focus">False</property>
       </object>
     </child>
+    <child>
+      <object class="GtkMenuItem" id="5">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes" context="navigatorcontextmenu|STR_OUTLINE_CONTENT">Outline Content Visibility</property>
+        <property name="use_underline">True</property>
+        <child type="submenu">
+          <object class="GtkMenu" id="outlinecontent">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkSeparatorMenuItem" id="separator1511">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+    </child>
     <child>
       <object class="GtkMenuItem" id="4">
         <property name="visible">True</property>


More information about the Libreoffice-commits mailing list