tdf#137741 SW: Add fields content type to Navigator
also makes Comments category be tracked
Change-Id: I038ba87d6ae0b96bae2d7a213ec5df92ac7d566d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112560
Tested-by: Jenkins
Reviewed-by: Jim Raykowski <raykowj@gmail.com>
diff --git a/sw/inc/bitmaps.hlst b/sw/inc/bitmaps.hlst
index a486eb3..7643989 100644
--- a/sw/inc/bitmaps.hlst
+++ b/sw/inc/bitmaps.hlst
@@ -87,6 +87,7 @@
#define RID_BMP_NAVI_INDEX "sw/res/nc20009.png"
#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_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/strings.hrc b/sw/inc/strings.hrc
index ade1728..e45a3ed 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -370,6 +370,7 @@
#define STR_CONTENT_TYPE_REFERENCE NC_("STR_CONTENT_TYPE_REFERENCE", "References")
#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_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.")
@@ -398,6 +399,7 @@
#define STR_CONTENT_TYPE_SINGLE_INDEX NC_("STR_CONTENT_TYPE_SINGLE_INDEX", "Index")
#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_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/uibase/inc/content.hxx b/sw/source/uibase/inc/content.hxx
index dfb1350a..69f9696 100644
--- a/sw/source/uibase/inc/content.hxx
+++ b/sw/source/uibase/inc/content.hxx
@@ -88,6 +88,22 @@ public:
const SwTextINetFormat* GetINetAttr() const { return pINetAttr; }
};
class SwTextFieldContent final : public SwContent
{
const SwFormatField* m_pFormatField;
public:
SwTextFieldContent(const SwContentType* pCnt,
const OUString& rName,
const SwFormatField* pFormatField,
tools::Long nYPos)
: SwContent(pCnt, rName, nYPos),
m_pFormatField(pFormatField)
{}
const SwFormatField* GetFormatField() const {return m_pFormatField;}
virtual bool IsProtect() const override;
};
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 9b8d95d..d65c4fa 100644
--- a/sw/source/uibase/inc/swcont.hxx
+++ b/sw/source/uibase/inc/swcont.hxx
@@ -40,7 +40,8 @@ enum class ContentTypeId
INDEX = 9,
POSTIT = 10,
DRAWOBJECT = 11,
LAST = DRAWOBJECT,
TEXTFIELD = 12,
LAST = TEXTFIELD,
UNKNOWN = -1
};
diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index 2b3b057..d648671 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -89,6 +89,15 @@
#include <viewopt.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <ndtxt.hxx>
#include <docfld.hxx>
#include <txtfld.hxx>
#include <expfld.hxx>
#include <fldmgr.hxx>
#include <docufld.hxx>
#define CTYPE_CNT 0
#define CTYPE_CTT 1
@@ -202,6 +211,11 @@ bool SwContent::IsProtect() const
return false;
}
bool SwTextFieldContent::IsProtect() const
{
return m_pFormatField->IsProtect();
}
bool SwPostItContent::IsProtect() const
{
return pField->IsProtect();
@@ -233,7 +247,8 @@ static const char* STR_CONTENT_TYPE_ARY[] =
STR_CONTENT_TYPE_REFERENCE,
STR_CONTENT_TYPE_INDEX,
STR_CONTENT_TYPE_POSTIT,
STR_CONTENT_TYPE_DRAWOBJECT
STR_CONTENT_TYPE_DRAWOBJECT,
STR_CONTENT_TYPE_TEXTFIELD
};
static const char* STR_CONTENT_TYPE_SINGLE_ARY[] =
@@ -249,7 +264,8 @@ static const char* STR_CONTENT_TYPE_SINGLE_ARY[] =
STR_CONTENT_TYPE_SINGLE_REFERENCE,
STR_CONTENT_TYPE_SINGLE_INDEX,
STR_CONTENT_TYPE_SINGLE_POSTIT,
STR_CONTENT_TYPE_SINGLE_DRAWOBJECT
STR_CONTENT_TYPE_SINGLE_DRAWOBJECT,
STR_CONTENT_TYPE_SINGLE_TEXTFIELD
};
namespace
@@ -362,6 +378,33 @@ void SwContentType::Init(bool* pbInvalidateWindow)
m_bEdit = true;
}
break;
case ContentTypeId::TEXTFIELD:
{
m_nMemberCount = 0;
m_sTypeToken.clear();
m_bEdit = true;
m_bDelete = true;
const SwFieldTypes& rFieldTypes = *m_pWrtShell->GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
const size_t nSize = rFieldTypes.size();
for (size_t i = 0; i < nSize; ++i)
{
const SwFieldType* pFieldType = rFieldTypes[i].get();
std::vector<SwFormatField*> vFields;
pFieldType->GatherFields(vFields);
for (SwFormatField* pFormatField: vFields)
{
if (SwTextField* pTextField = pFormatField->GetTextField())
{
const SwTextNode& rTextNode = pTextField->GetTextNode();
const SwContentFrame* pCFrame =
rTextNode.getLayoutFrame(rTextNode.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout());
if (pCFrame)
m_nMemberCount++;
}
}
}
}
break;
case ContentTypeId::BOOKMARK:
{
IDocumentMarkAccess* const pMarkAccess = m_pWrtShell->getIDocumentMarkAccess();
@@ -446,7 +489,8 @@ void SwContentType::Init(bool* pbInvalidateWindow)
case ContentTypeId::REFERENCE:
{
m_nMemberCount = m_pWrtShell->GetRefMarks();
m_bDelete = false;
m_bEdit = true;
m_bDelete = true;
}
break;
case ContentTypeId::URLFIELD:
@@ -706,6 +750,62 @@ void SwContentType::FillMemberList(bool* pbLevelOrVisibilityChanged)
}
}
break;
case ContentTypeId::TEXTFIELD:
{
// sorted list of all fields - meaning in the order they are in the document model
SetGetExpFields aSrtLst;
const SwFieldTypes& rFieldTypes = *m_pWrtShell->GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
const size_t nSize = rFieldTypes.size();
for (size_t i = 0; i < nSize; ++i)
{
const SwFieldType* pFieldType = rFieldTypes[i].get();
std::vector<SwFormatField*> vFields;
pFieldType->GatherFields(vFields);
for (SwFormatField* pFormatField: vFields)
{
if (SwTextField* pTextField = pFormatField->GetTextField())
{
const SwTextNode& rTextNode = pTextField->GetTextNode();
const SwContentFrame* pCFrame =
rTextNode.getLayoutFrame(rTextNode.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout());
if (pCFrame)
{
std::unique_ptr<SetGetExpField> pNew(new SetGetExpField(SwNodeIndex(rTextNode), pTextField));
aSrtLst.insert(std::move(pNew));
}
}
}
}
for (size_t i = 0; i < aSrtLst.size(); ++i)
{
const SwTextField* pTextField = aSrtLst[i]->GetTextField();
const SwFormatField& rFormatField = pTextField->GetFormatField();
const SwField* pField = rFormatField.GetField();
OUString sFieldName = pField->GetFieldName();
if (pField->GetTypeId() == SwFieldTypesEnum::Postit)
{
OUString sEntry(static_cast<const SwPostItField*>(pField)->GetText());
sEntry = RemoveNewline(sEntry);
sFieldName = sFieldName + " - " + sEntry;
}
else if (pField->GetTypeId() == SwFieldTypesEnum::DocumentStatistics)
{
SwFieldMgr aFieldMgr(m_pWrtShell);
std::vector<OUString> aLst;
aFieldMgr.GetSubTypes(SwFieldTypesEnum::DocumentStatistics, aLst);
const SwDocStatField* pDocStatField = static_cast<const SwDocStatField*>(pField);
OUString sSubType;
if (pDocStatField->GetSubType() < aLst.size())
sSubType = aLst[pDocStatField->GetSubType()] + " - ";
sFieldName = sFieldName + " - " + sSubType + pDocStatField->ExpandField(true, nullptr);
}
std::unique_ptr<SwTextFieldContent> pCnt(new SwTextFieldContent(this, sFieldName, &rFormatField, i));
m_pMember->insert(std::move(pCnt));
}
m_nMemberCount = m_pMember->size();
}
break;
case ContentTypeId::REGION :
{
m_nMemberCount = m_pWrtShell->GetSectionFormatCount();
@@ -1444,7 +1544,12 @@ IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
ContentTypeId::INDEX == nContentType ||
ContentTypeId::DRAWOBJECT == nContentType);
if(ContentTypeId::OUTLINE == nContentType)
if (ContentTypeId::TEXTFIELD == nContentType || ContentTypeId::REFERENCE == nContentType)
{
bRemoveEditEntry = false;
bRemoveDeleteEntry = false;
}
else if(ContentTypeId::OUTLINE == nContentType)
{
bOutline = true;
lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
@@ -1975,6 +2080,9 @@ namespace
case ContentTypeId::DRAWOBJECT:
sResId = RID_BMP_NAVI_DRAWOBJECT;
break;
case ContentTypeId::TEXTFIELD:
sResId = RID_BMP_NAVI_TEXTFIELD;
break;
case ContentTypeId::UNKNOWN:
SAL_WARN("sw.ui", "ContentTypeId::UNKNOWN has no bitmap preview");
break;
@@ -2324,6 +2432,7 @@ bool SwContentTree::FillTransferData( TransferDataContainer& rTransfer,
case ContentTypeId::POSTIT:
case ContentTypeId::INDEX:
case ContentTypeId::REFERENCE :
case ContentTypeId::TEXTFIELD:
// cannot be inserted, neither as URL nor as section
break;
case ContentTypeId::URLFIELD:
@@ -3257,6 +3366,43 @@ void SwContentTree::UpdateTracking()
return;
}
// fields
if (SwField* pField = m_pActiveShell->GetCurField())
{
OUString sContentType(SwResId(STR_CONTENT_TYPE_TEXTFIELD));
if (pField->GetTypeId() == SwFieldTypesEnum::Postit)
sContentType = SwResId(STR_CONTENT_TYPE_POSTIT);
// find content type entry
std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator());
bool bFoundEntry = m_xTreeView->get_iter_first(*xIter);
while (bFoundEntry && sContentType != m_xTreeView->get_text(*xIter))
bFoundEntry = m_xTreeView->iter_next_sibling(*xIter);
// find content type content entry and select it
if (bFoundEntry)
{
m_xTreeView->expand_row(*xIter); // assure content type entry is expanded
while (m_xTreeView->iter_next(*xIter) && lcl_IsContent(*xIter, *m_xTreeView))
{
SwTextFieldContent* pCnt = reinterpret_cast<SwTextFieldContent*>(m_xTreeView->get_id(*xIter).toInt64());
if (pCnt && pField == pCnt->GetFormatField()->GetField())
{
// get first selected for comparison
std::unique_ptr<weld::TreeIter> xFirstSelected(m_xTreeView->make_iterator());
if (!m_xTreeView->get_selected(xFirstSelected.get()))
xFirstSelected.reset();
if (m_xTreeView->count_selected_rows() != 1 ||
m_xTreeView->iter_compare(*xIter, *xFirstSelected) != 0)
{
// unselect all entries and make passed entry visible and selected
m_xTreeView->set_cursor(*xIter);
Select();
}
break;
}
}
}
return;
}
// drawing
if ((m_pActiveShell->GetSelectionType() & (SelectionType::DrawObject |
SelectionType::DrawObjectEditMode |
@@ -4285,10 +4431,25 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode)
else
nSlot = SID_EDIT_HYPERLINK;
break;
case ContentTypeId::TEXTFIELD:
case ContentTypeId::REFERENCE:
nSlot = FN_EDIT_FIELD;
break;
{
const SwTextFieldContent* pTextFieldCnt = static_cast<const SwTextFieldContent*>(pCnt);
if (nMode == EditEntryMode::DELETE)
{
const SwTextField* pTextField = pTextFieldCnt->GetFormatField()->GetTextField();
SwTextField::DeleteTextField(*pTextField);
}
else
{
if (pTextFieldCnt->GetFormatField()->GetField()->GetTypeId() != SwFieldTypesEnum::Postit)
{
nSlot = FN_EDIT_FIELD;
break;
}
}
[[fallthrough]]; // execute FN_POSTIT assuring standard mode first
}
case ContentTypeId::POSTIT:
m_pActiveShell->GetView().GetPostItMgr()->AssureStdModeAtShell();
if(nMode == EditEntryMode::DELETE)
@@ -4418,6 +4579,12 @@ void SwContentTree::GotoContent(const SwContent* pCnt)
lcl_AssureStdModeAtShell(m_pActiveShell);
switch(pCnt->GetParent()->GetType())
{
case ContentTypeId::TEXTFIELD:
{
m_pActiveShell->GotoFormatField(
*static_cast<const SwTextFieldContent*>(pCnt)->GetFormatField());
}
break;
case ContentTypeId::OUTLINE :
{
m_pActiveShell->GotoOutline(static_cast<const SwOutlineContent*>(pCnt)->GetOutlinePos());