summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorJim Raykowski <raykowj@gmail.com>2021-10-01 15:51:08 -0800
committerJim Raykowski <raykowj@gmail.com>2021-10-04 01:18:20 +0200
commitfc44168ebe840fa2e772f034232fed15460e4977 (patch)
tree5795099f450e47607f789e6ab9d822d1e6b95373 /sw
parent47d7ce6de04625b0a9045c2ca6dd25da0e70d886 (diff)
tdf#144788 SwNavigator: Add footnotes and endnotes to content tree
This patch introduces lcl_SelectByContentTypeAndAddress function which is useful for content types that can have non unique string entries which can be selected incorrectly by use of the lcl_SelectByContentTypeAndName function. Although footnotes and endnotes names are always unique, lcl_SelectByContentTypeAndAddress is used here in preference of lcl_SelectByContentTypeAndName. Change-Id: Ia118f717f72877cddb932ef19f6d155a7227845d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122970 Tested-by: Jenkins Reviewed-by: Jim Raykowski <raykowj@gmail.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/bitmaps.hlst1
-rw-r--r--sw/inc/crsrsh.hxx3
-rw-r--r--sw/inc/strings.hrc4
-rw-r--r--sw/source/core/crsr/crstrvl.cxx18
-rw-r--r--sw/source/uibase/inc/content.hxx16
-rw-r--r--sw/source/uibase/inc/swcont.hxx5
-rw-r--r--sw/source/uibase/inc/wrtsh.hxx4
-rw-r--r--sw/source/uibase/utlui/content.cxx127
-rw-r--r--sw/source/uibase/wrtsh/move.cxx8
9 files changed, 179 insertions, 7 deletions
diff --git a/sw/inc/bitmaps.hlst b/sw/inc/bitmaps.hlst
index 7643989dd2e9..b3353862bee0 100644
--- a/sw/inc/bitmaps.hlst
+++ b/sw/inc/bitmaps.hlst
@@ -88,6 +88,7 @@
#define RID_BMP_NAVI_POSTIT "sw/res/nc20010.png"
#define RID_BMP_NAVI_DRAWOBJECT "sw/res/nc20011.png"
#define RID_BMP_NAVI_TEXTFIELD "sw/res/nc20005.png"
+#define RID_BMP_NAVI_FOOTNOTE "sw/res/nc20000.png"
#define RID_BMP_DROP_REGION "sw/res/sc20235.png"
#define RID_BMP_DROP_LINK "sw/res/sc20238.png"
#define RID_BMP_DROP_COPY "sw/res/sc20239.png"
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 9f60a87345d5..14507f20097c 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -55,6 +55,7 @@ class SwRangeRedline;
class SwBlockCursor;
class SwPostItField;
class SwTextField;
+class SwTextFootnote;
namespace i18nutil {
struct SearchOptions2;
@@ -812,6 +813,8 @@ public:
const SwRangeRedline* SelPrevRedline();
const SwRangeRedline* GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect );
+ bool GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote);
+
SAL_DLLPRIVATE SvxFrameDirection GetTextDirection( const Point* pPt = nullptr ) const;
// is cursor or the point in/over a vertical formatted text?
bool IsInVerticalText( const Point* pPt = nullptr ) const;
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 359e25b49312..395cfc63bd53 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -371,6 +371,7 @@
#define STR_CONTENT_TYPE_INDEX NC_("STR_CONTENT_TYPE_INDEX", "Indexes")
#define STR_CONTENT_TYPE_DRAWOBJECT NC_("STR_CONTENT_TYPE_DRAWOBJECT", "Drawing objects")
#define STR_CONTENT_TYPE_TEXTFIELD NC_("STR_CONTENT_TYPE_TEXTFIELD", "Fields")
+#define STR_CONTENT_TYPE_FOOTNOTE NC_("STR_CONTENT_TYPE_FOOTNOTE", "Footnotes and Endnotes")
#define STR_CONTENT_TYPE_POSTIT NC_("STR_CONTENT_TYPE_POSTIT", "Comments")
#define STR_IDXEXAMPLE_IDXTXT_HEADING1 NC_("STR_IDXEXAMPLE_IDXTXT_HEADING1", "Heading 1")
#define STR_IDXEXAMPLE_IDXTXT_ENTRY1 NC_("STR_IDXEXAMPLE_IDXTXT_ENTRY1", "This is the content from the first chapter. This is a user directory entry.")
@@ -400,6 +401,9 @@
#define STR_CONTENT_TYPE_SINGLE_POSTIT NC_("STR_CONTENT_TYPE_SINGLE_POSTIT", "Comment")
#define STR_CONTENT_TYPE_SINGLE_DRAWOBJECT NC_("STR_CONTENT_TYPE_SINGLE_DRAWOBJECT", "Draw object")
#define STR_CONTENT_TYPE_SINGLE_TEXTFIELD NC_("STR_CONTENT_TYPE_SINGLE_TEXTFIELD", "Field")
+#define STR_CONTENT_TYPE_SINGLE_FOOTNOTE NC_("STR_CONTENT_TYPE_SINGLE_FOOTNOTE", "Footnote or Endnote")
+#define STR_CONTENT_FOOTNOTE NC_("STR_CONTENT_FOOTNOTE", "Footnote")
+#define STR_CONTENT_ENDNOTE NC_("STR_CONTENT_ENDNOTE", "Endnote")
#define STR_DEFINE_NUMBERFORMAT NC_("STR_DEFINE_NUMBERFORMAT", "Additional formats...")
#define RID_STR_SYSTEM NC_("RID_STR_SYSTEM", "[System]")
#define STR_MULT_INTERACT_HYPH_WARN NC_("STR_MULT_INTERACT_HYPH_WARN", "The interactive hyphenation is already active\nin a different document")
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index 87ab068e6ded..03f94624aae2 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -831,6 +831,24 @@ bool SwCursorShell::MoveFieldType(
return bRet;
}
+bool SwCursorShell::GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote)
+{
+ bool bRet = false;
+ SwCursor* pCursor = getShellCursor(true);
+
+ CurrShell aCurr(this);
+ SwCallLink aLk(*this); // watch Cursor-Moves
+ SwCursorSaveState aSaveState(*pCursor);
+
+ pCursor->GetPoint()->nNode = rTextFootnote.GetTextNode();
+ pCursor->GetPoint()->nContent.Assign(const_cast<SwTextNode*>(&rTextFootnote.GetTextNode()),
+ rTextFootnote.GetStart());
+ bRet = !pCursor->IsSelOvr();
+ if (bRet)
+ UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
+ return bRet;
+}
+
bool SwCursorShell::GotoFormatField( const SwFormatField& rField )
{
bool bRet = false;
diff --git a/sw/source/uibase/inc/content.hxx b/sw/source/uibase/inc/content.hxx
index 64b1e265f10b..195dfd5ff6f3 100644
--- a/sw/source/uibase/inc/content.hxx
+++ b/sw/source/uibase/inc/content.hxx
@@ -31,6 +31,7 @@ class SwFormatField;
class SwTextINetFormat;
class SwTOXBase;
class SwRangeRedline;
+class SwTextFootnote;
// helper classes
@@ -104,6 +105,21 @@ public:
virtual bool IsProtect() const override;
};
+class SwTextFootnoteContent final : public SwContent
+{
+ const SwTextFootnote* m_pTextFootnote;
+public:
+ SwTextFootnoteContent(const SwContentType* pCnt,
+ const OUString& rName,
+ const SwTextFootnote* pTextFootnote,
+ tools::Long nYPos)
+ : SwContent(pCnt, rName, nYPos),
+ m_pTextFootnote(pTextFootnote)
+ {}
+
+ const SwTextFootnote* GetTextFootnote() const {return m_pTextFootnote;}
+};
+
class SwPostItContent final : public SwContent
{
const SwFormatField* pField;
diff --git a/sw/source/uibase/inc/swcont.hxx b/sw/source/uibase/inc/swcont.hxx
index d65c4fa59aca..2e32944efb48 100644
--- a/sw/source/uibase/inc/swcont.hxx
+++ b/sw/source/uibase/inc/swcont.hxx
@@ -40,8 +40,9 @@ enum class ContentTypeId
INDEX = 9,
POSTIT = 10,
DRAWOBJECT = 11,
- TEXTFIELD = 12,
- LAST = TEXTFIELD,
+ TEXTFIELD = 12,
+ FOOTNOTE = 13,
+ LAST = FOOTNOTE,
UNKNOWN = -1
};
diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx
index 727d4cfb64c9..8e2573916e8b 100644
--- a/sw/source/uibase/inc/wrtsh.hxx
+++ b/sw/source/uibase/inc/wrtsh.hxx
@@ -114,7 +114,7 @@ private:
SELECTFUNC m_fnKillSel = &SwWrtShell::Ignore;
public:
-
+ using SwCursorShell::GotoFootnoteAnchor;
using SwEditShell::Insert;
tools::Long CallSetCursor(const Point* pPt, bool bProp) { return (this->*m_fnSetCursor)(pPt, bProp); }
@@ -486,7 +486,7 @@ typedef bool (SwWrtShell::*FNSimpleMove)();
void GotoFormatField( const SwFormatField& rField );
const SwRangeRedline* GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect);
bool GotoDrawingObject(std::u16string_view rName);
-
+ void GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote);
void ChangeHeaderOrFooter(std::u16string_view rStyleName, bool bHeader, bool bOn, bool bShowWarning);
virtual void SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow ) override;
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 8f8e1531f45c..f6caf32c5aed 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -103,6 +103,10 @@
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextRangeCompare.hpp>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+
#define CTYPE_CNT 0
#define CTYPE_CTT 1
@@ -258,7 +262,8 @@ const TranslateId STR_CONTENT_TYPE_ARY[] =
STR_CONTENT_TYPE_INDEX,
STR_CONTENT_TYPE_POSTIT,
STR_CONTENT_TYPE_DRAWOBJECT,
- STR_CONTENT_TYPE_TEXTFIELD
+ STR_CONTENT_TYPE_TEXTFIELD,
+ STR_CONTENT_TYPE_FOOTNOTE
};
const TranslateId STR_CONTENT_TYPE_SINGLE_ARY[] =
@@ -275,7 +280,8 @@ const TranslateId STR_CONTENT_TYPE_SINGLE_ARY[] =
STR_CONTENT_TYPE_SINGLE_INDEX,
STR_CONTENT_TYPE_SINGLE_POSTIT,
STR_CONTENT_TYPE_SINGLE_DRAWOBJECT,
- STR_CONTENT_TYPE_SINGLE_TEXTFIELD
+ STR_CONTENT_TYPE_SINGLE_TEXTFIELD,
+ STR_CONTENT_TYPE_SINGLE_FOOTNOTE
};
namespace
@@ -409,6 +415,16 @@ void SwContentType::Init(bool* pbInvalidateWindow)
}
}
break;
+ case ContentTypeId::FOOTNOTE:
+ {
+ m_nMemberCount = 0;
+ m_sTypeToken.clear();
+ m_bEdit = true;
+ m_bDelete = false;
+ const SwFootnoteIdxs& rFootnoteIdxs = m_pWrtShell->GetDoc()->GetFootnoteIdxs();
+ m_nMemberCount = rFootnoteIdxs.size();
+ }
+ break;
case ContentTypeId::BOOKMARK:
{
IDocumentMarkAccess* const pMarkAccess = m_pWrtShell->getIDocumentMarkAccess();
@@ -845,7 +861,26 @@ void SwContentType::FillMemberList(bool* pbLevelOrVisibilityChanged)
m_nMemberCount = m_pMember->size();
}
break;
-
+ case ContentTypeId::FOOTNOTE:
+ {
+ const SwFootnoteIdxs& rFootnoteIdxs = m_pWrtShell->GetDoc()->GetFootnoteIdxs();
+ for (SwTextFootnote* pTextFootnote : rFootnoteIdxs)
+ {
+ const SwFormatFootnote& rFormatFootnote = pTextFootnote->GetFootnote();
+ const OUString& sText =
+ rFormatFootnote.GetViewNumStr(*m_pWrtShell->GetDoc(),
+ m_pWrtShell->GetLayout(), true) + " " +
+ rFormatFootnote.GetFootnoteText(*m_pWrtShell->GetLayout());
+ std::unique_ptr<SwTextFootnoteContent> pCnt(new SwTextFootnoteContent(
+ this, sText, pTextFootnote,
+ rFormatFootnote.GetNumber()));
+ if (!pTextFootnote->GetTextNode().getLayoutFrame(m_pWrtShell->GetLayout()))
+ pCnt->SetInvisible();
+ m_pMember->insert(std::move(pCnt));
+ }
+ m_nMemberCount = m_pMember->size();
+ }
+ break;
case ContentTypeId::REGION :
{
m_nMemberCount = m_pWrtShell->GetSectionFormatCount();
@@ -2122,6 +2157,9 @@ namespace
case ContentTypeId::TEXTFIELD:
sResId = RID_BMP_NAVI_TEXTFIELD;
break;
+ case ContentTypeId::FOOTNOTE:
+ sResId = RID_BMP_NAVI_FOOTNOTE;
+ break;
case ContentTypeId::UNKNOWN:
SAL_WARN("sw.ui", "ContentTypeId::UNKNOWN has no bitmap preview");
break;
@@ -3283,6 +3321,66 @@ void SwContentTree::HideTree()
m_xTreeView->hide();
}
+static void lcl_SelectByContentTypeAndAddress(SwContentTree* pThis, weld::TreeView& rContentTree,
+ ContentTypeId nType, const void* ptr)
+{
+ if (!ptr)
+ return;
+
+ // find content type entry
+ std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator());
+
+ bool bFoundEntry = rContentTree.get_iter_first(*xIter);
+ while (bFoundEntry)
+ {
+ void* pUserData = reinterpret_cast<void*>(rContentTree.get_id(*xIter).toInt64());
+ assert(dynamic_cast<SwContentType*>(static_cast<SwTypeNumber*>(pUserData)));
+ if (nType == static_cast<SwContentType*>(pUserData)->GetType())
+ break;
+ bFoundEntry = rContentTree.iter_next_sibling(*xIter);
+ }
+
+ if (bFoundEntry)
+ {
+ // assure content type entry is expanded
+ rContentTree.expand_row(*xIter);
+
+ // find content type content entry and select it
+ const void* p = nullptr;
+ while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
+ {
+ void* pUserData = reinterpret_cast<void*>(rContentTree.get_id(*xIter).toInt64());
+ switch( nType )
+ {
+ case ContentTypeId::FOOTNOTE:
+ {
+ assert(dynamic_cast<SwTextFootnoteContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ SwTextFootnoteContent* pCnt = static_cast<SwTextFootnoteContent*>(pUserData);
+ p = pCnt->GetTextFootnote();
+ break;
+ }
+ default:
+ break;
+ }
+ if (ptr == p)
+ {
+ // get first selected for comparison
+ std::unique_ptr<weld::TreeIter> xFirstSelected(rContentTree.make_iterator());
+ if (!rContentTree.get_selected(xFirstSelected.get()))
+ xFirstSelected.reset();
+ if (rContentTree.count_selected_rows() != 1 ||
+ rContentTree.iter_compare(*xIter, *xFirstSelected) != 0)
+ {
+ // unselect all entries and make passed entry visible and selected
+ rContentTree.set_cursor(*xIter);
+ pThis->Select();
+ }
+ return;
+ }
+ }
+ }
+}
+
static void lcl_SelectByContentTypeAndName(SwContentTree* pThis, weld::TreeView& rContentTree,
std::u16string_view rContentTypeName, std::u16string_view rName)
{
@@ -3400,6 +3498,15 @@ void SwContentTree::UpdateTracking()
return;
}
+ // footnotes and endnotes
+ if (SwContentAtPos aContentAtPos(IsAttrAtPos::Ftn);
+ m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos) &&
+ !(m_bIsRoot && m_nRootType != ContentTypeId::FOOTNOTE))
+ {
+ lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::FOOTNOTE,
+ aContentAtPos.pFndTextAttr);
+ return;
+ }
// bookmarks - track first bookmark at cursor
SwDoc* pDoc = m_pActiveShell->GetDoc();
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(pDoc->GetDocShell()->GetBaseModel(),
@@ -4080,6 +4187,12 @@ IMPL_LINK(SwContentTree, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUStrin
}
}
break;
+ case ContentTypeId::FOOTNOTE:
+ assert(dynamic_cast<SwTextFootnoteContent*>(static_cast<SwTypeNumber*>(pUserData)));
+ sEntry = static_cast<SwTextFootnoteContent*>(pUserData)->GetTextFootnote()->
+ GetFootnote().IsEndNote() ? SwResId(STR_CONTENT_ENDNOTE) :
+ SwResId(STR_CONTENT_FOOTNOTE);
+ break;
default: break;
}
if(static_cast<SwContent*>(pUserData)->IsInvisible())
@@ -4658,6 +4771,10 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode)
else if(nMode == EditEntryMode::RENAME)
nSlot = FN_NAME_SHAPE;
break;
+ case ContentTypeId::FOOTNOTE:
+ if (EditEntryMode::EDIT == nMode)
+ nSlot = FN_FORMAT_FOOTNOTE_DLG;
+ break;
default: break;
}
if(nSlot)
@@ -4788,6 +4905,10 @@ void SwContentTree::GotoContent(const SwContent* pCnt)
m_pActiveShell->GotoDrawingObject(pCnt->GetName());
}
break;
+ case ContentTypeId::FOOTNOTE:
+ m_pActiveShell->GotoFootnoteAnchor(
+ *static_cast<const SwTextFootnoteContent*>(pCnt)->GetTextFootnote());
+ break;
default: break;
}
diff --git a/sw/source/uibase/wrtsh/move.cxx b/sw/source/uibase/wrtsh/move.cxx
index 95443ba16ca7..a5f10d5f8800 100644
--- a/sw/source/uibase/wrtsh/move.cxx
+++ b/sw/source/uibase/wrtsh/move.cxx
@@ -706,6 +706,14 @@ void SwWrtShell::GotoFormatField( const SwFormatField& rField ) {
m_aNavigationMgr.addEntry(aPos);
}
+void SwWrtShell::GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote)
+{
+ SwPosition aPos = *GetCursor()->GetPoint();
+ bool bRet = SwCursorShell::GotoFootnoteAnchor(rTextFootnote);
+ if (bRet)
+ m_aNavigationMgr.addEntry(aPos);
+}
+
const SwRangeRedline* SwWrtShell::GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect ) {
SwPosition aPos = *GetCursor()->GetPoint();
const SwRangeRedline *pRedline = SwCursorShell::GotoRedline(nArrPos, bSelect);