/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-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/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/* Symbolic name representations of numeric values used for the Outline Content Visibility popup menu item ids. The numbers are chosen arbitrarily to not over overlap other menu item ids. see: SwContentTree::ExecuteContextMenuAction, navigatorcontextmenu.ui
1512 toggle outline content visibility of the selected outline entry 1513 make the outline content of the selected outline entry and children not visible 1514 make the outline content of the selected entry and children visible
*/ const sal_uInt32 TOGGLE_OUTLINE_CONTENT_VISIBILITY = 1512; const sal_uInt32 HIDE_OUTLINE_CONTENT_VISIBILITY = 1513; const sal_uInt32 SHOW_OUTLINE_CONTENT_VISIBILITY = 1514;
constexpr char NAVI_BOOKMARK_DELIM = '\x01';
}
class SwContentArr
: public o3tl::sorted_vector<std::unique_ptr<SwContent>, o3tl::less_ptr_to,
o3tl::find_partialorder_ptrequals>
{
};
void getAnchorPos(SwPosition& rPos)
{ // get the top most anchor position of the position if (SwFrameFormat* pFlyFormat = rPos.GetNode().GetFlyFormat())
{
SwNode* pAnchorNode;
SwFrameFormat* pTmp = pFlyFormat; while (pTmp && (pAnchorNode = pTmp->GetAnchor().GetAnchorNode()) &&
(pTmp = pAnchorNode->GetFlyFormat()))
{
pFlyFormat = pTmp;
} if (const SwPosition* pPos = pFlyFormat->GetAnchor().GetContentAnchor())
rPos = *pPos;
}
}
returnfalse;
} // Gets "YPos" for content, i.e. a number used to sort content members in Navigator's list
sal_Int32 getYPos(const SwNode& rNode)
{
SwNodeOffset nIndex = rNode.GetIndex(); if (rNode.GetNodes().GetEndOfExtras().GetIndex() >= nIndex)
{ // Not a node of BodyText // Are we in a fly? if (constauto pFlyFormat = rNode.GetFlyFormat())
{ // Get node index of anchor if (SwNode* pAnchorNode = pFlyFormat->GetAnchor().GetAnchorNode())
{ return getYPos(*pAnchorNode);
}
}
} return sal_Int32(nIndex);
}
} // end of anonymous namespace
// tdf#157250 Show deleted headings tracked changes in the Navigator only when show // tracked changes is on if (m_pWrtShell->GetLayout()->IsHideRedlines()
&& pNode->GetRedlineMergeFlag() != SwNode::Merge::None && aEntry.isEmpty()) continue;
auto pCnt(std::make_unique<SwOutlineContent>(this, aEntry, i, nLevel,
m_pWrtShell->IsOutlineMovable(i), nYPos)); if (!pNode->getLayoutFrame(m_pWrtShell->GetLayout()))
pCnt->SetInvisible();
m_pMember->insert(std::move(pCnt));
}
// need to check level and equal entry number after creation due to possible outline // nodes in frames, headers, footers if (pOldMember)
{
assert(pbContentChanged && "pbContentChanged is always set if pOldMember is"); if (pOldMember->size() != m_pMember->size())
{
*pbContentChanged = true; break;
} for (size_t i = 0; i < pOldMember->size(); i++)
{ if (static_cast<SwOutlineContent*>((*pOldMember)[i].get())->GetOutlineLevel() != static_cast<SwOutlineContent*>((*m_pMember)[i].get())->GetOutlineLevel())
{
*pbContentChanged = true; break;
}
}
}
} break; case ContentTypeId::TABLE :
{ const size_t nCount = m_pWrtShell->GetTableFrameFormatCount(true); const sw::TableFrameFormats* pFrameFormats = m_pWrtShell->GetDoc()->GetTableFrameFormats(); for(size_t n = 0, i = 0; i < nCount + n; ++i)
{ const SwTableFormat& rTableFormat = *(*pFrameFormats)[i]; if(!rTableFormat.IsUsed()) // skip deleted tables
{
n++; continue;
}
tools::Long nYPos = 0; if (!m_bAlphabeticSort)
{ if (SwTable* pTable = SwTable::FindTable(&rTableFormat))
nYPos = getYPos(*pTable->GetTableNode());
} auto pCnt = std::make_unique<SwContent>(this, rTableFormat.GetName().toString(), nYPos); if(!rTableFormat.IsVisible())
pCnt->SetInvisible();
m_pMember->insert(std::move(pCnt));
}
if (pOldMember)
{ // need to check visibility (and equal entry number) after // creation due to a sorted list being used here (before, // entries with same index were compared already at creation // time what worked before a sorted list was used)
*pbContentChanged = checkVisibilityChanged(
*pOldMember,
*m_pMember);
}
} break; case ContentTypeId::OLE : case ContentTypeId::FRAME : case ContentTypeId::GRAPHIC :
{
FlyCntType eType = FLYCNTTYPE_FRM; if(m_nContentType == ContentTypeId::OLE)
eType = FLYCNTTYPE_OLE; elseif(m_nContentType == ContentTypeId::GRAPHIC)
eType = FLYCNTTYPE_GRF;
Point aNullPt;
size_t nCount = m_pWrtShell->GetFlyCount(eType, /*bIgnoreTextBoxes=*/true);
std::vector<SwFrameFormat const*> formats(m_pWrtShell->GetFlyFrameFormats(eType, /*bIgnoreTextBoxes=*/true));
SAL_WARN_IF(nCount != formats.size(), "sw.ui", "Count differs");
nCount = formats.size(); for (size_t i = 0; i < nCount; ++i)
{
SwFrameFormat const*const pFrameFormat = formats[i]; const UIName sFrameName = pFrameFormat->GetName();
auto pCnt(std::make_unique<SwRegionContent>(this, sSectionName.toString(), nLevel,
m_bAlphabeticSort ? 0 : getYPos(pNodeIndex->GetNode()),
pFormat));
if (!pFormat->IsVisible() || pSection->IsHidden())
pCnt->SetInvisible();
m_pMember->insert(std::move(pCnt));
}
if (pOldMember)
{ // need to check visibility (and equal entry number) after // creation due to a sorted list being used here (before, // entries with same index were compared already at creation // time what worked before a sorted list was used)
assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
*pbContentChanged = checkVisibilityChanged(
*pOldMember,
*m_pMember);
}
}
} break; case ContentTypeId::REFERENCE:
{
std::vector<OUString> aRefMarks;
m_pWrtShell->GetRefMarks( &aRefMarks );
if (m_bAlphabeticSort)
{ for (auto& r : aArr)
{ auto pCnt(std::make_unique<SwURLFieldContent>(this, r.sText, INetURLObject::decode(
r.rINetAttr.GetINetFormat().GetValue(),
INetURLObject::DecodeMechanism::Unambiguous),
&r.rINetAttr, 0));
m_pMember->insert(std::move(pCnt));
} break;
}
// use stable sort array to list hyperlinks in document order const SwNodeOffset nEndOfExtrasIndex = m_pWrtShell->GetNodes().GetEndOfExtras().GetIndex(); bool bHasEntryInFly = false;
std::vector<SwGetINetAttr*> aStableSortINetAttrsArray;
for (SwGetINetAttr& r : aArr)
{
aStableSortINetAttrsArray.emplace_back(&r); if (!bHasEntryInFly)
{ if (nEndOfExtrasIndex >= r.rINetAttr.GetTextNode().GetIndex())
{ // Not a node of BodyText // Are we in a fly? if (r.rINetAttr.GetTextNode().GetFlyFormat())
bHasEntryInFly = true;
}
}
}
// When there are hyperlinks in text frames do an additional sort using the text frame // anchor position to place entries in the order of document layout appearance. if (bHasEntryInFly)
{
std::stable_sort(aStableSortINetAttrsArray.begin(), aStableSortINetAttrsArray.end(),
[nEndOfExtrasIndex](const SwGetINetAttr* a, const SwGetINetAttr* b){ const SwTextNode& aTextNode = a->rINetAttr.GetTextNode(); const SwTextNode& bTextNode = b->rINetAttr.GetTextNode();
SwPosition aPos(aTextNode, a->rINetAttr.GetStart());
SwPosition bPos(bTextNode, b->rINetAttr.GetStart()); // use anchor position for entries that are located in flys if (nEndOfExtrasIndex >= aTextNode.GetIndex()) if (auto pFlyFormat = aTextNode.GetFlyFormat()) if (const SwPosition* pPos = pFlyFormat->GetAnchor().GetContentAnchor())
aPos = *pPos; if (nEndOfExtrasIndex >= bTextNode.GetIndex()) if (auto pFlyFormat = bTextNode.GetFlyFormat()) if (const SwPosition* pPos = pFlyFormat->GetAnchor().GetContentAnchor())
bPos = *pPos; return aPos < bPos;});
}
SwGetINetAttrs::size_type n = 0; for (auto p : aStableSortINetAttrsArray)
{ auto pCnt = std::make_unique<SwURLFieldContent>(this, p->sText,
INetURLObject::decode(p->rINetAttr.GetINetFormat().GetValue(),
INetURLObject::DecodeMechanism::Unambiguous),
&p->rINetAttr, ++n);
m_pMember->insert(std::move(pCnt));
}
} break; case ContentTypeId::INDEX:
{ const sal_uInt16 nCount = m_pWrtShell->GetTOXCount();
m_pMember->insert( std::unique_ptr<SwContent>(pCnt) ); const size_t nPos = m_pMember->size() - 1; if (pOldMember)
{
assert(pbContentChanged && "pbContentChanged is always set if pOldMember is"); if (!*pbContentChanged && nOldMemberCount > nPos &&
(*pOldMember)[nPos]->IsInvisible() != pCnt->IsInvisible())
*pbContentChanged = true;
}
}
} break; case ContentTypeId::POSTIT:
{
SwPostItMgr* aMgr = m_pWrtShell->GetView().GetPostItMgr(); if (aMgr)
{
tools::Long nYPos = 0; for(SwPostItMgr::const_iterator i = aMgr->begin(); i != aMgr->end(); ++i)
{ if (const SwFormatField* pFormatField = dynamic_cast<const SwFormatField *>((*i)->GetBroadcaster())) // SwPostit
{ if (pFormatField->GetTextField() && pFormatField->IsFieldInDoc())
{
OUString sEntry = pFormatField->GetField()->GetPar2();
sEntry = RemoveNewline(sEntry);
std::unique_ptr<SwPostItContent> pCnt(new SwPostItContent( this,
sEntry,
pFormatField,
nYPos)); if (!pFormatField->GetTextField()->GetTextNode().getLayoutFrame(
m_pWrtShell->GetLayout()))
pCnt->SetInvisible(); if (pOldMember)
{
assert(pbContentChanged && "pbContentChanged is always set if pOldMember is"); if (!*pbContentChanged &&
nOldMemberCount > o3tl::make_unsigned(nYPos) &&
(*pOldMember)[nYPos]->IsInvisible() != pCnt->IsInvisible())
*pbContentChanged = true;
}
m_pMember->insert(std::move(pCnt));
nYPos++;
}
}
}
}
} break; case ContentTypeId::DRAWOBJECT:
{
IDocumentDrawModelAccess& rIDDMA = m_pWrtShell->getIDocumentDrawModelAccess();
SwDrawModel* pModel = rIDDMA.GetDrawModel(); if(pModel)
{
SdrPage* pPage = pModel->GetPage(0); for (const rtl::Reference<SdrObject>& pTemp : *pPage)
{ // #i51726# - all drawing objects can be named now if (!pTemp->IsVirtualObj() && !pTemp->GetName().isEmpty())
{
tools::Long nYPos = LONG_MIN; constbool bIsVisible = rIDDMA.IsVisibleLayerId(pTemp->GetLayer()); if (bIsVisible)
nYPos = m_bAlphabeticSort ? 0 : pTemp->GetLogicRect().Top(); auto pCnt(std::make_unique<SwContent>(this, pTemp->GetName(), nYPos)); if (!bIsVisible)
pCnt->SetInvisible();
m_pMember->insert(std::move(pCnt));
}
}
if (pOldMember)
{ // need to check visibility (and equal entry number) after // creation due to a sorted list being used here (before, // entries with same index were compared already at creation // time what worked before a sorted list was used)
assert(pbContentChanged && "pbContentChanged is always set if pOldMember is");
*pbContentChanged = checkVisibilityChanged(
*pOldMember,
*m_pMember);
}
}
} break; default: break;
}
m_nMemberCount = m_pMember->size(); if (pOldMember)
{
assert(pbContentChanged && "pbContentChanged is always set if pOldMember is"); if (!*pbContentChanged && pOldMember->size() != m_nMemberCount)
*pbContentChanged = true;
}
IMPL_LINK(SwContentTree, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
{ // Prevent trying to bring entry to attention when handling document change. The mouse over // entry might not be valid, for example, when the mouse pointer is on an entry that is deleted // in the document by an undo/redo. if (m_bDocHasChanged) returnfalse; if (m_eState == State::HIDDEN) returnfalse; if (std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
m_xTreeView->get_dest_row_at_pos(rMEvt.GetPosPixel(), xEntry.get(), false, false) &&
!rMEvt.IsLeaveWindow())
{ if (!m_xOverlayCompareEntry)
m_xOverlayCompareEntry.reset(m_xTreeView->make_iterator().release()); elseif (m_xTreeView->iter_compare(*xEntry, *m_xOverlayCompareEntry) == 0) returnfalse; // The entry under the mouse has not changed.
m_xTreeView->copy_iterator(*xEntry, *m_xOverlayCompareEntry);
BringEntryToAttention(*xEntry);
} else
{ if (m_xOverlayCompareEntry)
m_xOverlayCompareEntry.reset();
m_aOverlayObjectDelayTimer.Stop(); if (m_xOverlayObject && m_xOverlayObject->getOverlayManager())
{
m_xOverlayObject->getOverlayManager()->remove(*m_xOverlayObject);
m_xOverlayObject.reset();
}
} returnfalse;
}
if (nAccept != DND_ACTION_NONE)
{ // to enable the autoscroll when we're close to the edges
weld::TreeView& rWidget = m_rTreeView.get_widget();
rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
}
if (m_nRootType == ContentTypeId::OUTLINE)
{ if (xDropEntry && lcl_IsContent(*xDropEntry, *m_xTreeView))
{
assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xDropEntry))));
SwOutlineContent* pOutlineContent = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xDropEntry));
assert(pOutlineContent);
void* key = lcl_GetOutlineKey(*this, pOutlineContent);
assert(key); if (!mOutLineNodeMap[key])
{ while (m_xTreeView->iter_has_child(*xDropEntry))
{
std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(xDropEntry.get())); bool bChildEntry = m_xTreeView->iter_children(*xChildEntry); while (bChildEntry)
{
m_xTreeView->copy_iterator(*xChildEntry, *xDropEntry);
bChildEntry = m_xTreeView->iter_next_sibling(*xChildEntry);
}
}
}
}
SwOutlineNodes::size_type nTargetPos = 0; if (!xDropEntry)
{ // dropped in blank space -> move to bottom
nTargetPos = GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() - 1;
} elseif (!lcl_IsContent(*xDropEntry, *m_xTreeView))
{ // dropped on "heading" parent -> move to start
nTargetPos = SwOutlineNodes::npos;
} else
{
assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xDropEntry))));
nTargetPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xDropEntry))->GetOutlinePos();
}
if( MAXLEVEL > m_nOutlineLevel && // Not all layers are displayed.
nTargetPos != SwOutlineNodes::npos)
{
std::unique_ptr<weld::TreeIter> xNext(m_xTreeView->make_iterator(xDropEntry.get())); bool bNext = m_xTreeView->iter_next(*xNext); if (bNext)
{
assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xNext))));
nTargetPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xNext))->GetOutlinePos() - 1;
} else
nTargetPos = GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() - 1;
}
// remove the drop highlight before we change the contents of the tree so we don't // try and dereference a removed entry in post-processing drop
m_xTreeView->unset_drag_dest_row();
MoveOutline(nTargetPos);
do
{ if (rContentTree.iter_has_child(*xChild) || rContentTree.get_children_on_demand(*xChild))
{ if (!IsAllExpanded(rContentTree, *xChild)) returnfalse;
}
} while (rContentTree.iter_next_sibling(*xChild)); returntrue;
}
// test for content in outline node
aIdx.Assign(*pSttNd); if (SwNodes::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 (SwNodes::GoNext(&aIdx) != pEndNd) break;
nPos++;
}
// select clicked entry or limit selection to root entry if needed if (std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
rCEvt.IsMouseEvent() && m_xTreeView->get_dest_row_at_pos(
rCEvt.GetMousePosPixel(), xEntry.get(), false))
{ // if clicked entry is not currently selected then clear selections and select it if (!m_xTreeView->is_selected(*xEntry))
m_xTreeView->set_cursor(*xEntry); // if root entry is selected then clear selections and select it elseif (m_xTreeView->is_selected(0))
m_xTreeView->set_cursor(0);
}
if (bRemoveToggleExpandEntry)
xPop->remove(OUString::number(800));
if (bRemoveGotoEntry)
xPop->remove(OUString::number(900));
if (bRemoveSelectEntry)
xPop->remove(OUString::number(805));
if (bRemoveChapterEntries)
{
xPop->remove(OUString::number(801));
xPop->remove(OUString::number(802));
xPop->remove(OUString::number(803));
xPop->remove(OUString::number(804));
}
if (bRemoveSendOutlineEntry)
xPop->remove(OUString::number(700));
if (bRemovePostItEntries)
{
xPop->remove(u"showcomments"_ustr);
xPop->remove(u"showresolvedcomments"_ustr);
}
if (bRemoveDeleteChapterEntry)
xPop->remove(u"deletechapter"_ustr); if (bRemoveDeleteAllTablesEntry)
xPop->remove(u"deletealltables"_ustr); if (bRemoveDeleteTableEntry)
xPop->remove(u"deletetable"_ustr); if (bRemoveDeleteAllFramesEntry)
xPop->remove(u"deleteallframes"_ustr); if (bRemoveDeleteFrameEntry)
xPop->remove(u"deleteframe"_ustr); if (bRemoveDeleteAllImagesEntry)
xPop->remove(u"deleteallimages"_ustr); if (bRemoveDeleteImageEntry)
xPop->remove(u"deleteimage"_ustr); if (bRemoveDeleteAllOLEObjectsEntry)
xPop->remove(u"deletealloleobjects"_ustr); if (bRemoveDeleteOLEObjectEntry)
xPop->remove(u"deleteoleobject"_ustr); if (bRemoveDeleteAllBookmarksEntry)
xPop->remove(u"deleteallbookmarks"_ustr); if (bRemoveDeleteBookmarkEntry)
xPop->remove(u"deletebookmark"_ustr); if (bRemoveDeleteAllRegionsEntry)
xPop->remove(u"deleteallregions"_ustr); if (bRemoveDeleteRegionEntry)
xPop->remove(u"deleteregion"_ustr); if (bRemoveDeleteAllHyperlinksEntry)
xPop->remove(u"deleteallhyperlinks"_ustr); if (bRemoveDeleteHyperlinkEntry)
xPop->remove(u"deletehyperlink"_ustr); if (bRemoveDeleteAllReferencesEntry)
xPop->remove(u"deleteallreferences"_ustr); if (bRemoveDeleteReferenceEntry)
xPop->remove(u"deletereference"_ustr); if (bRemoveDeleteAllIndexesEntry)
xPop->remove(u"deleteallindexes"_ustr); if (bRemoveDeleteIndexEntry)
xPop->remove(u"deleteindex"_ustr); if (bRemoveDeleteAllCommentsEntry)
xPop->remove(u"deleteallcomments"_ustr); if (bRemoveDeleteCommentEntry)
xPop->remove(u"deletecomment"_ustr); if (bRemoveDeleteAllDrawingObjectsEntry)
xPop->remove(u"deletealldrawingobjects"_ustr); if (bRemoveDeleteDrawingObjectEntry)
xPop->remove(u"deletedrawingobject"_ustr); if (bRemoveDeleteAllFieldsEntry)
xPop->remove(u"deleteallfields"_ustr); if (bRemoveDeleteFieldEntry)
xPop->remove(u"deletefield"_ustr); if (bRemoveDeleteAllFootnotesEntry)
xPop->remove(u"deleteallfootnotes"_ustr); if (bRemoveDeleteFootnoteEntry)
xPop->remove(u"deletefootnote"_ustr); if (bRemoveDeleteAllEndnotesEntry)
xPop->remove(u"deleteallendnotes"_ustr); if (bRemoveDeleteEndnoteEntry)
xPop->remove(u"deleteendnote"_ustr);
if (bRemoveMakeAllFootnotesEndnotesEntry)
xPop->remove(u"makeallfootnotesendnotes"_ustr); if (bRemoveMakeAllEndnotesFootnotesEntry)
xPop->remove(u"makeallendnotesfootnotes"_ustr);
if (!bOutline)
{
xSubPop1.reset();
xPop->remove(OUString::number(1)); // outline level menu
} if (!bOutline || State::HIDDEN == m_eState)
{
xSubPopOutlineTracking.reset();
xPop->remove(OUString::number(4)); // outline tracking menu
} if (!bOutline || State::HIDDEN == m_eState ||
!m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton() ||
m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() == 0)
{
xSubPopOutlineContent.reset();
xPop->remove(OUString::number(5)); // outline folding menu
xPop->remove(u"separator3"_ustr);
}
if (bRemoveTableTracking)
xPop->remove(u"tabletracking"_ustr); if (bRemoveSectionTracking)
xPop->remove(u"sectiontracking"_ustr); if (bRemoveFrameTracking)
xPop->remove(u"frametracking"_ustr); if (bRemoveImageTracking)
xPop->remove(u"imagetracking"_ustr); if (bRemoveOLEobjectTracking)
xPop->remove(u"oleobjecttracking"_ustr); if (bRemoveBookmarkTracking)
xPop->remove(u"bookmarktracking"_ustr); if (bRemoveHyperlinkTracking)
xPop->remove(u"hyperlinktracking"_ustr); if (bRemoveReferenceTracking)
xPop->remove(u"referencetracking"_ustr); if (bRemoveIndexTracking)
xPop->remove(u"indextracking"_ustr); if (bRemoveCommentTracking)
xPop->remove(u"commenttracking"_ustr); if (bRemoveDrawingObjectTracking)
xPop->remove(u"drawingobjecttracking"_ustr); if (bRemoveFieldTracking)
xPop->remove(u"fieldtracking"_ustr); if (bRemoveFootnoteTracking)
xPop->remove(u"footnotetracking"_ustr); if (bRemoveEndnoteTracking)
xPop->remove(u"endnotetracking"_ustr); if (bRemoveSortEntry)
xPop->remove(u"sort"_ustr); if (bRemoveProtectSection)
xPop->remove(u"protectsection"_ustr); if (bRemoveHideSection)
xPop->remove(u"hidesection"_ustr);
// Content will be integrated into the Box only on demand. bool SwContentTree::RequestingChildren(const weld::TreeIter& rParent)
{ // Does the parent already have children or is it not a 'children on demand' node? if (m_xTreeView->iter_has_child(rParent) || !m_xTreeView->get_children_on_demand(rParent)) returnfalse;
// Is this a content type? if (lcl_IsContentType(rParent, *m_xTreeView))
{
std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator();
// if there is a preceding outline node candidate with a lower outline level // use that as a parent, otherwise use the root node auto aFind = std::find_if(aParentCandidates.rbegin(),
aParentCandidates.rend(), lambda); if (aFind != aParentCandidates.rend())
insert(aFind->get(), sEntry, sId, false, xChild.get()); else
insert(&rParent, sEntry, sId, false, xChild.get());
m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
m_xTreeView->set_extra_row_indent(
*xChild, nLevel + 1 - m_xTreeView->get_iter_depth(*xChild));
// remove any parent candidates equal to or higher than this node
std::erase_if(aParentCandidates, std::not_fn(lambda));
// add this node as a parent candidate for any following nodes at a higher // outline level
aParentCandidates.emplace_back(m_xTreeView->make_iterator(xChild.get()));
}
}
}
} elseif (pCntType->GetType() == ContentTypeId::REGION)
{ if (pCntType->IsAlphabeticSort())
{ for(size_t i = 0; i < nCount; ++i)
{ const SwRegionContent* pCnt = static_cast<const SwRegionContent*>(pCntType->GetMember(i));
// if there is a preceding region node candidate with a lower region level use // that as a parent, otherwise use the root node auto aFind = std::find_if(aParentCandidates.rbegin(), aParentCandidates.rend(), lambda); if (aFind != aParentCandidates.rend())
insert(aFind->get(), sEntry, sId, false, xChild.get()); else
insert(&rParent, sEntry, sId, false, xChild.get());
m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
// remove any parent candidates equal to or higher than this node
std::erase_if(aParentCandidates, std::not_fn(lambda));
// add this node as a parent candidate for any following nodes at a higher region level
aParentCandidates.emplace_back(m_xTreeView->make_iterator(xChild.get()));
}
}
} elseif (pCntType->GetType() == ContentTypeId::POSTIT)
{
std::vector<std::unique_ptr<weld::TreeIter>> aParentCandidates; for(size_t i = 0; i < nCount; ++i)
{ const SwPostItContent* pCnt = static_cast<const SwPostItContent*>(pCntType->GetMember(i));
// if a parent candidate is not found use the passed root node auto aFind = std::find_if(aParentCandidates.rbegin(), aParentCandidates.rend(), lambda); if (aFind != aParentCandidates.rend())
insert(aFind->get(), sEntry, sId, false, xChild.get()); else
insert(&rParent, sEntry, sId, false, xChild.get());
// clear parent candidates when encountering a postit that doesn't have a parent // following postits can't have a parent that is in these candidates if (pPostItField->GetParentPostItId() == 0)
aParentCandidates.clear();
// pNodesToExpand is used by the Display function to restore the trees expand structure for // hierarchical content types, e.g., OUTLINE and REGION. if (pNodesToExpand)
pNodesToExpand->emplace_back(m_xTreeView->make_iterator(&rParent));
// rParentId is a string representation of a pointer to SwContentType or SwContent const OUString aParentId = m_xTreeView->get_id(rParent); // bParentIsContentType tells if the passed rParent tree entry is a content type or content constbool bParentIsContentType = lcl_IsContentType(rParent, *m_xTreeView); // eParentContentTypeId is the content type of the passed rParent tree entry const ContentTypeId eParentContentTypeId =
bParentIsContentType ? weld::fromId<SwContentType*>(aParentId)->GetType() :
weld::fromId<SwContent*>(aParentId)->GetParent()->GetType();
if (m_nRootType == ContentTypeId::UNKNOWN && bParentIsContentType)
{ // m_nActiveBlock and m_nHiddenBlock are used to persist the content type expand state for // the all content view mode constint nShift = static_cast<int>(eParentContentTypeId);
SAL_WARN_IF(nShift < 0, "sw.ui", "ContentTypeId::UNKNOWN negative shift"); if (nShift >= 0)
{ const sal_Int32 nOr = 1 << nShift; //linear -> Bitposition if (State::HIDDEN != m_eState)
{
m_nActiveBlock |= nOr;
m_pConfig->SetActiveBlock(m_nActiveBlock);
} else
m_nHiddenBlock |= nOr;
}
}
if (!sForbiddenChars.isEmpty())
{ for (int i = 0; i < sForbiddenChars.getLength(); i++)
{ if (sNewName.indexOf(sForbiddenChars[i]) != -1)
{
m_bEditing = false; returnfalse;
}
}
}
if (xNameAccess.is())
{ if (xNameAccess->hasByName(sNewName) || (xSecond.is() && xSecond->hasByName(sNewName))
|| (xThird.is() && xThird->hasByName(sNewName)))
{
m_bEditing = false; returnfalse;
}
if (lcl_IsContentType(rParent, *m_xTreeView))
{ if (m_bIsRoot)
{ // collapse to children of root node
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(&rParent)); if (m_xTreeView->iter_children(*xEntry))
{ do
{
m_xTreeView->collapse_row(*xEntry);
} while (m_xTreeView->iter_next(*xEntry));
} returnfalse; // return false to notify caller not to do collapse
}
ContentTypeId eContentTypeId =
weld::fromId<SwContentType*>(m_xTreeView->get_id(rParent))->GetType(); constint nShift = static_cast<int>(eContentTypeId);
SAL_WARN_IF(nShift < 0, "sw.ui", "ContentTypeId::UNKNOWN negative shift"); if (nShift >= 0)
{ const sal_Int32 nAnd = ~(1 << nShift); if (State::HIDDEN != m_eState)
{
m_nActiveBlock &= nAnd;
m_pConfig->SetActiveBlock(m_nActiveBlock);
} else
m_nHiddenBlock &= nAnd;
}
} else// content entry
{
SwWrtShell* pShell = GetWrtShell();
ContentTypeId eContentTypeId =
weld::fromId<SwContent*>(m_xTreeView->get_id(rParent))->GetParent()->GetType(); if (eContentTypeId == ContentTypeId::OUTLINE)
{
assert(dynamic_cast<SwOutlineContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent)))); autoconst nPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(rParent))->GetOutlinePos(); void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
mOutLineNodeMap[key] = false;
} elseif(eContentTypeId == ContentTypeId::REGION)
{
assert(dynamic_cast<SwRegionContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent)))); constvoid* key = static_cast<constvoid*>(weld::fromId<SwRegionContent*>(m_xTreeView->get_id(rParent))->GetSectionFormat());
m_aRegionNodeExpandMap[key] = false;
} elseif(eContentTypeId == ContentTypeId::POSTIT)
{
assert(dynamic_cast<SwPostItContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(rParent)))); constvoid* key = static_cast<constvoid*>(weld::fromId<SwPostItContent*>(m_xTreeView->get_id(rParent))->GetPostIt());
m_aPostItNodeExpandMap[key] = false;
}
}
returntrue;
}
// Also on double click will be initially opened only.
IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
{ if (m_nRowActivateEventId)
Application::RemoveUserEvent(m_nRowActivateEventId); // post the event to process row activate after mouse press event to be able to set key // modifier for selection feature (tdf#154211)
m_nRowActivateEventId
= Application::PostUserEvent(LINK(this, SwContentTree, AsyncContentDoubleClickHdl));
bool bConsumed = false;
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator()); if (m_xTreeView->get_cursor(xEntry.get()) && lcl_IsContent(*xEntry, *m_xTreeView) &&
(State::HIDDEN != m_eState))
{
SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry));
assert(pCnt && "no UserData"); if (pCnt && !pCnt->IsInvisible())
{ // fdo#36308 don't expand outlines on double-click
bConsumed = pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE;
}
}
return bConsumed; // false/true == allow/disallow more to be done, i.e. expand/collapse children
}
size_t nCount = 0; auto nRefDepth = m_xTreeView->get_iter_depth(*xParent); auto nActDepth = nRefDepth; do
{ if (!m_xTreeView->iter_next(*xParent))
xParent.reset(); else
nActDepth = m_xTreeView->get_iter_depth(*xParent);
nCount++;
} while(xParent && nRefDepth < nActDepth);
nCount--; return nCount;
}
std::unique_ptr<weld::TreeIter> SwContentTree::GetEntryAtAbsPos(size_t nAbsPos) const
{
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator()); if (!m_xTreeView->get_iter_first(*xEntry))
xEntry.reset();
while (nAbsPos && xEntry)
{ if (!m_xTreeView->iter_next(*xEntry))
xEntry.reset();
nAbsPos--;
} return xEntry;
}
void SwContentTree::Display( bool bActive )
{ // First read the selected entry to select it later again if necessary // -> the user data here are no longer valid!
std::unique_ptr<weld::TreeIter> xOldSelEntry(m_xTreeView->make_iterator()); if (!m_xTreeView->get_selected(xOldSelEntry.get()))
xOldSelEntry.reset();
size_t nEntryRelPos = 0; // relative position to their parent
size_t nOldEntryCount = GetEntryCount();
sal_Int32 nOldScrollPos = 0; if (xOldSelEntry)
{
UpdateLastSelType();
nOldScrollPos = m_xTreeView->vadjustment_get_value();
std::unique_ptr<weld::TreeIter> xParentEntry = m_xTreeView->make_iterator(xOldSelEntry.get()); while (m_xTreeView->get_iter_depth(*xParentEntry))
m_xTreeView->iter_parent(*xParentEntry); if (m_xTreeView->get_iter_depth(*xOldSelEntry))
nEntryRelPos = GetAbsPos(*xOldSelEntry) - GetAbsPos(*xParentEntry);
}
if (!bChOnDemand)
InsertContent(*xEntry); else
{ // fill contents of to-be expanded entries while frozen
Expand(*xEntry, &aNodesToExpand);
m_xTreeView->set_children_on_demand(*xEntry, false);
}
if (bChOnDemand)
{ // restore visual expanded tree state for (constauto& rNode : aNodesToExpand)
m_xTreeView->expand_row(*rNode);
} else
m_xTreeView->expand_row(*xEntry);
}
// Reselect the old selected entry. If it is not available, select the entry at the old // selected entry position unless that entry position is now a content type or is past the // end of the member list then select the entry at the previous entry position. if (xOldSelEntry)
{
std::unique_ptr<weld::TreeIter> xSelEntry = m_xTreeView->make_iterator(xCntTypeEntry.get()); if (nEntryRelPos)
{
std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator(xCntTypeEntry.get()));
std::unique_ptr<weld::TreeIter> xTemp(m_xTreeView->make_iterator(xIter.get()));
sal_uLong nPos = 1; bool bNext; while ((bNext = m_xTreeView->iter_next(*xIter) && lcl_IsContent(*xIter, *m_xTreeView)))
{ if (nPos == nEntryRelPos)
{
m_xTreeView->copy_iterator(*xIter, *xSelEntry); break;
}
m_xTreeView->copy_iterator(*xIter, *xTemp); // note previous entry
nPos++;
} if (!bNext)
xSelEntry = std::move(xTemp);
} // set_cursor unselects all entries, makes passed entry visible, and selects it
m_xTreeView->set_cursor(*xSelEntry);
}
UpdateContentFunctionsToolbar();
}
if (!m_bIgnoreDocChange && GetEntryCount() == nOldEntryCount)
{
m_xTreeView->vadjustment_set_value(nOldScrollPos);
}
}
// make sure outline may actually be copied if( pWrtShell->IsOutlineCopyable( nPos ) )
{ const SwNumRule* pOutlRule = pWrtShell->GetOutlineNumRule(); const SwTextNode* pTextNd =
pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNode(nPos); if (pTextNd && pOutlRule && pTextNd->IsNumbered(pWrtShell->GetLayout()))
{
SwNumberTree::tNumberVector aNumVector =
pTextNd->GetNumberVector(pWrtShell->GetLayout()); for( int nLevel = 0;
nLevel <= pTextNd->GetActualListLevel();
nLevel++ )
{ const SwNumberTree::tSwNumTreeNumber nVal = aNumVector[nLevel] + 1;
sEntry += OUString::number( nVal - pOutlRule->Get(nLevel).GetStart() ) + ".";
}
}
sEntry += pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(nPos, pWrtShell->GetLayout(), false);
sOutlineText = pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(nPos, pWrtShell->GetLayout());
m_bIsOutlineMoveable = static_cast<SwOutlineContent*>(pCnt)->IsMoveable();
}
} break; case ContentTypeId::BOOKMARK:
sEntry = m_xTreeView->get_text(*xEntry); break; case ContentTypeId::TABLE: case ContentTypeId::FRAME: case ContentTypeId::REGION:
bCrossRef = false;
sEntry = m_xTreeView->get_text(*xEntry); break; // content types that cannot be inserted, as URL, section, or reference case ContentTypeId::POSTIT: case ContentTypeId::INDEX: returnfalse; // content types than can only be inserted as a cross-reference case ContentTypeId::REFERENCE: case ContentTypeId::TEXTFIELD: case ContentTypeId::FOOTNOTE: case ContentTypeId::ENDNOTE:
bUrl = false;
sEntry = m_xTreeView->get_text(*xEntry); break; // content types that can only be inserted as a hyperlink case ContentTypeId::URLFIELD:
sUrl = static_cast<SwURLFieldContent*>(pCnt)->GetURL();
[[fallthrough]]; case ContentTypeId::OLE: case ContentTypeId::GRAPHIC: case ContentTypeId::DRAWOBJECT:
bCrossRef = false;
sEntry = m_xTreeView->get_text(*xEntry); break; default: returnfalse;
}
if(!sEntry.isEmpty())
{ const SwDocShell* pDocShell = pWrtShell->GetView().GetDocShell(); if (bUrl && sUrl.isEmpty())
{ if(pDocShell->HasName())
{
SfxMedium* pMedium = pDocShell->GetMedium();
sUrl = pMedium->GetURLObject().GetURLNoMark();
} elseif (SwView* pView = GetActiveView(); State::CONSTANT == m_eState
&& (!pView || m_pActiveShell != pView->GetWrtShellPtr()))
{ // Urls of inactive views cannot dragged without // file names, also. returnfalse;
} elseif (eActType != ContentTypeId::REGION && eActType != ContentTypeId::BOOKMARK)
{ // For sections and bookmarks a link is also allowed // without a filename into its own document. returnfalse;
}
sCrossRef = OUString::number(static_cast<int>(eReferenceSubType)) + u"|"
+ sEntry + u"|" + sVal;
} elseif (eActType == ContentTypeId::OUTLINE)
{
sEntry = sOutlineText; const SwOutlineNodes::size_type nPos = static_cast<SwOutlineContent*>(pCnt)->GetOutlinePos(); const SwTextNode* pTextNode =
pWrtShell->GetNodes().GetOutLineNds()[nPos]->GetTextNode();
sw::mark::MarkBase const * const pMark =
pWrtShell->getIDocumentMarkAccess()->getMarkForTextNode(
*pTextNode, IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK); // REFERENCESUBTYPE_OUTLINE is changed to REFERENCESUBTYPE::BOOKMARK in // SwWrtShell::NavigatorPaste. It is used to differentiate between a // headings reference and a regular bookmark reference to show different // options in the reference mark type popup menu.
sCrossRef = OUString::number(static_cast<int>(REFERENCESUBTYPE::REF_OUTLINE))
+ u"|" + pMark->GetName().toString();
}
}
// An INetBookmark must a be delivered to foreign DocShells if (bUrl && pDocShell->HasName())
{
INetBookmark aBkmk( sUrl, sEntry );
rTransfer.CopyINetBookmark( aBkmk );
}
}
returntrue;
}
void SwContentTree::ToggleToRoot()
{ if(!m_bIsRoot)
{
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator()); bool bEntry = m_xTreeView->get_cursor(xEntry.get()); if (bEntry)
{ const SwContentType* pCntType; if (lcl_IsContentType(*xEntry, *m_xTreeView))
{
assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
pCntType = weld::fromId<SwContentType*>(m_xTreeView->get_id(*xEntry));
} else
{
assert(dynamic_cast<SwContent*>(weld::fromId<SwTypeNumber*>(m_xTreeView->get_id(*xEntry))));
pCntType = weld::fromId<SwContent*>(m_xTreeView->get_id(*xEntry))->GetParent();
}
m_nRootType = pCntType->GetType();
m_bIsRoot = true; if (m_nRootType == ContentTypeId::OUTLINE || m_nRootType == ContentTypeId::DRAWOBJECT)
{
m_xTreeView->set_selection_mode(SelectionMode::Multiple);
}
Display(State::HIDDEN != m_eState);
}
} else
{
m_xTreeView->set_selection_mode(SelectionMode::Single);
m_nLastSelType = m_nRootType;
m_nRootType = ContentTypeId::UNKNOWN;
m_bIsRoot = false; // Other content type member data could have changed while in root view. Fill the content // member lists excluding the toggled from root content which should already have the most // recent data. if (State::HIDDEN != m_eState)
{ for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
{ if (i != m_nLastSelType && m_aActiveContentArr[i])
m_aActiveContentArr[i]->FillMemberList();
}
}
Display(State::HIDDEN != m_eState);
}
m_pConfig->SetRootType( m_nRootType );
weld::Toolbar* pBox = GetParentWindow()->m_xContent5ToolBox.get();
pBox->set_item_active(u"root"_ustr, m_bIsRoot);
}
bool SwContentTree::HasContentChanged()
{ if (m_bEditing)
{ returnfalse;
}
bool bContentChanged = false;
// - Run through the local array and the Treelistbox in parallel. // - Are the records not expanded, they are discarded only in the array // and the content type will be set as the new UserData. // - Is the root mode is active only this will be updated.
// Valid for the displayed content types is: // the Memberlist will be erased and the membercount will be updated // If content will be checked, the memberlists will be replenished // at the same time. Once a difference occurs it will be only replenished // no longer checked. Finally, the box is filled again.
if (State::HIDDEN == m_eState)
{ for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
{ if(m_aActiveContentArr[i])
m_aActiveContentArr[i]->Invalidate();
} returnfalse;
}
// single content type navigation view if(m_bIsRoot)
{
std::unique_ptr<weld::TreeIter> xRootEntry(m_xTreeView->make_iterator()); if (!m_xTreeView->get_iter_first(*xRootEntry)) returntrue;
pArrType->FillMemberList(&bContentChanged); if (bContentChanged) returntrue;
// FillMemberList tests if member count in old member array equals member count in new // member array. Test here for member count difference between array and tree. const size_t nChildCount = GetChildCount(*xRootEntry); if (nChildCount != pArrType->GetMemberCount()) returntrue;
// FillMemberList clears the content type member list and refills with new data. // Treeview entry user data is set here to the string representation of the pointer to // the member data in the array. The Display function will clear and recreate the // treeview from the content type member arrays if content change is detected. const SwContent* pCnt = pArrType->GetMember(j);
if (pCnt->IsInvisible() != m_xTreeView->get_sensitive(*xEntry, 0)) returntrue;
// Set_id needs to be done here because FillMemberList clears the content type member // list and refills with new data making the previously set id invalid. If there is no // content change detected the Display function will not be called and the tree entry // user data will not be set to the new content member pointer address.
OUString sSubId(weld::toId(pCnt));
m_xTreeView->set_id(*xEntry, sSubId);
}
} // all content types navigation view else
{ // Fill member list for each content type and check for content change. If content change // is detected only fill member lists for remaining content types. The Display function // will clear and recreate the treeview from the content type member arrays if content has // changed.
if (comphelper::LibreOfficeKit::isActive())
{ // In case of LOK, empty contentTypes are hidden, even in all content view // so it is not enough to check only the m_xTreeView. bool bCountChanged = false; bool bHasContentChanged = false; for (ContentTypeId i : o3tl::enumrange<ContentTypeId>())
{ if (m_aActiveContentArr[i])
{ auto nLastTMCount = m_aActiveContentArr[i]->GetMemberCount(); if (i == ContentTypeId::OUTLINE) // this is required for checking if header level is changed
m_aActiveContentArr[i]->FillMemberList(&bHasContentChanged); else
m_aActiveContentArr[i]->FillMemberList(); // If the member count of a type is changed, then the content is surely changed if (m_aActiveContentArr[i]->GetMemberCount() != nLastTMCount)
bCountChanged = true; if (bHasContentChanged)
bContentChanged = true;
}
} if (bCountChanged || bContentChanged) returntrue;
}
// lambda function to find the next content type entry auto lcl_nextContentTypeEntry = [this, &xEntry](){ while (m_xTreeView->get_iter_depth(*xEntry))
m_xTreeView->iter_parent(*xEntry); return m_xTreeView->iter_next_sibling(*xEntry);
};
if (!pArrType)
{
bContentChanged = true; continue;
}
// all content type member lists must be filled! if (bContentChanged)
{ // If content change has already been detected there is no need to detect // other content change so no argument is supplied here to FillMemberList.
pArrType->FillMemberList(); continue;
}
pArrType->FillMemberList(&bContentChanged); if (bContentChanged) continue;
// does entry have children? if (m_xTreeView->get_row_expanded(*xEntry))
{ const size_t nChildCount = GetChildCount(*xEntry); if(nChildCount != pArrType->GetMemberCount())
{
bContentChanged = true; continue;
}
// If clear is called by TimerUpdate: // Only for root can the validity of the UserData be guaranteed.
m_xTreeView->all_foreach([this](weld::TreeIter& rEntry){
m_xTreeView->set_id(rEntry, u""_ustr); returnfalse;
});
}
// tdf#148432 in LTR UI override the navigator treeview direction based on // the first page directionality if (m_pActiveShell && !AllSettings::GetLayoutRTL())
{ const SwPageDesc& rDesc = m_pActiveShell->GetPageDesc(0); const SvxFrameDirectionItem& rFrameDir = rDesc.GetMaster().GetFrameDir();
m_xTreeView->set_direction(rFrameDir.GetValue() == SvxFrameDirection::Horizontal_RL_TB);
}
// Only if it is the active view, the array will be deleted and // the screen filled new. if (State::ACTIVE == m_eState && bClear)
{ if (m_pActiveShell)
StartListening(*m_pActiveShell->GetView().GetDocShell());
FindActiveTypeAndRemoveUserData(); for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
{
m_aActiveContentArr[i].reset();
}
Display(true);
}
}
m_xTreeView->selected_foreach([&](weld::TreeIter& rEntry){ // it's possible to select the root node too which is a really bad idea if (lcl_IsContentType(rEntry, *m_xTreeView)) returnfalse; // filter out children of selected parents so they don't get promoted // or moved twice (except if there is Ctrl modifier, since in that // case children are re-parented) if ((bLeftRight || bOutlineWithChildren) && !selected.empty())
{
std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry)); for (bool bParent = m_xTreeView->iter_parent(*xParent); bParent; bParent = m_xTreeView->iter_parent(*xParent))
{ if (m_xTreeView->iter_compare(*selected.back(), *xParent) == 0)
{ returnfalse;
}
}
}
selected.emplace_back(m_xTreeView->make_iterator(&rEntry));
// Use the outline node position in the SwOutlineNodes array. Bad things // happen if the tree entry position is used and it doesn't match the node position // in SwOutlineNodes, which is usually the case for outline nodes in frames. const SwOutlineNodes::size_type nPos
= weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(rEntry))->GetOutlinePos(); if (nPos < nOutlineNdsSize)
{
SwNode* pNode = rNodes.GetOutLineNds()[ nPos ]; if (pNode)
{
selectedOutlineNodes.push_back(pNode->GetTextNode());
}
} returnfalse;
});
if (!selected.size()) return;
if (bUpDown && !bUp)
{ // to move down, start at the end!
std::reverse(selected.begin(), selected.end());
}
// get first regular document content node outline node position in outline nodes array
SwOutlineNodes::size_type nFirstRegularDocContentOutlineNodePos = SwOutlineNodes::npos;
SwNodeOffset nEndOfExtrasIndex = rNodes.GetEndOfExtras().GetIndex();
sal_Int32 nHasInlineHeading = 0; for (SwOutlineNodes::size_type nPos = 0; nPos < nOutlineNdsSize; nPos++)
{ if (rOutlineNodes[nPos]->GetIndex() > nEndOfExtrasIndex)
{
nFirstRegularDocContentOutlineNodePos = nPos; break;
} if ( bUpDown && rOutlineNodes[nPos] != SwOutlineNodes::GetRootNode(rOutlineNodes[nPos]) )
++nHasInlineHeading;
}
for (autoconst& pCurrentEntry : selected)
{
nActPos = weld::fromId<SwOutlineContent*>(
m_xTreeView->get_id(*pCurrentEntry))->GetOutlinePos();
// outline nodes in frames and tables are not up/down moveable if (nActPos == SwOutlineNodes::npos ||
(bUpDown && (!pShell->IsOutlineMovable(nActPos) ||
nFirstRegularDocContentOutlineNodePos == SwOutlineNodes::npos)))
{ // except inline headings, i.e. Inline Heading frames with // single outlines, and anchored as characters, which headings // are movable with their anchor node, if they are // 1) not in other frames or 2) not in tables and 3) not protected const SwNode* pRootNode = nHasInlineHeading > 0
? SwOutlineNodes::GetRootNode(rOutlineNodes[nActPos])
: nullptr; if ( !pRootNode || pRootNode == rOutlineNodes[nActPos] ||
pRootNode != SwOutlineNodes::GetRootNode(pRootNode) || // frame in frame
pRootNode->FindTableNode() || // frame in table
pRootNode->IsProtect() ) // write protection
{ continue;
}
}
// move outline position up/down (outline position promote/demote)
SwOutlineNodes::difference_type nDir = bUp ? -1 : 1;
SwOutlineNodesInline::size_type nActPosInline;
aOutlineNodesInline.Seek_Entry(rOutlineNodes[nActPos], &nActPosInline); if ( (nDir == -1 && nActPosInline > 0) ||
(nDir == 1 && nActPosInline < nOutlineNdsSizeInline - 1) )
{ // make outline selection for use by MoveOutlinePara
pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren, true, &aOutlineNodesInline);
int nActPosOutlineLevel =
rOutlineNodes[nActPos]->GetTextNode()->GetAttrOutlineLevel(); // search for sorted position
SwOutlineNodesInline::size_type nPos;
aOutlineNodesInline.Seek_Entry_By_Anchor(SwOutlineNodes::GetRootNode(rOutlineNodes[nActPos]), &nPos); if (!bUp)
{ // move down int nPosOutlineLevel = -1; while (++nPos < nOutlineNdsSizeInline)
{
nPosOutlineLevel = aOutlineNodesInline[nPos]->GetTextNode()->GetAttrOutlineLevel();
// discontinue if moving out of parent or equal level is found if (nPosOutlineLevel <= nActPosOutlineLevel)
{ break;
} // count the children of the node when they are not included in the move if (!bOutlineWithChildren)
nDir++;
} if (nPosOutlineLevel >= nActPosOutlineLevel)
{ // move past children while (++nPos < nOutlineNdsSizeInline)
{
nPosOutlineLevel = aOutlineNodesInline[nPos]->GetTextNode()->GetAttrOutlineLevel(); // discontinue if moving out of parent or equal level is found if (nPosOutlineLevel <= nActPosOutlineLevel) break;
nDir++;
}
}
} else
{ // move up while (nPos && --nPos >= nFirstRegularDocContentOutlineNodePos - nHasInlineHeading)
{ int nPosOutlineLevel =
aOutlineNodesInline[nPos]->GetTextNode()->GetAttrOutlineLevel(); // discontinue if equal level is found if (nPosOutlineLevel == nActPosOutlineLevel)
{ break;
} // discontinue if moving out of parent if (nPosOutlineLevel < nActPosOutlineLevel)
{ // Required for expected chapter placement when the chapter being moved // up has an outline level less than the outline level of chapters it // is being moved above and then encounters a chapter with an outline // level that is greater before reaching a chapter with the same // outline level as itself. if (nDir < -1)
nDir++; break;
}
nDir--;
}
}
pShell->MoveOutlinePara(nDir, &aOutlineNodesInline);
}
pShell->ClearMark();
} elseif (bUpDown)
{ // move outline position up/down (outline position promote/demote)
SwOutlineNodes::difference_type nDir = bUp ? -1 : 1; if ((nDir == -1 && nActPos > 0) || (nDir == 1 && nActPos < nOutlineNdsSize - 1))
{ // make outline selection for use by MoveOutlinePara
pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren);
int nActPosOutlineLevel =
rOutlineNodes[nActPos]->GetTextNode()->GetAttrOutlineLevel();
SwOutlineNodes::size_type nPos = nActPos; if (!bUp)
{ // move down int nPosOutlineLevel = -1; while (++nPos < nOutlineNdsSize)
{
nPosOutlineLevel =
rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineLevel(); // discontinue if moving out of parent or equal level is found if (nPosOutlineLevel <= nActPosOutlineLevel) break; // count the children of the node when they are not included in the move if (!bOutlineWithChildren)
nDir++;
} if (nPosOutlineLevel >= nActPosOutlineLevel)
{ // move past children while (++nPos < nOutlineNdsSize)
{
nPosOutlineLevel =
rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineLevel(); // discontinue if moving out of parent or equal level is found if (nPosOutlineLevel <= nActPosOutlineLevel) break;
nDir++;
}
}
} else
{ // move up while (nPos && --nPos >= nFirstRegularDocContentOutlineNodePos)
{ int nPosOutlineLevel =
rOutlineNodes[nPos]->GetTextNode()->GetAttrOutlineLevel(); // discontinue if equal level is found if (nPosOutlineLevel == nActPosOutlineLevel) break; // discontinue if moving out of parent if (nPosOutlineLevel < nActPosOutlineLevel)
{ // Required for expected chapter placement when the chapter being moved // up has an outline level less than the outline level of chapters it // is being moved above and then encounters a chapter with an outline // level that is greater before reaching a chapter with the same // outline level as itself. if (nDir < -1)
nDir++; break;
}
nDir--;
}
}
pShell->MoveOutlinePara(nDir);
}
pShell->ClearMark();
} else
{ // move outline left/right (outline level promote/demote) if (!pShell->IsProtectedOutlinePara())
{ bool bAllow = true; const SwOutlineNodes& rOutlNds = pShell->GetDoc()->GetNodes().GetOutLineNds(); constint 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->Pop(SwCursorShell::PopMode::DeleteCurrent); // Cursor is now back at the current heading.
}
if (bStartedAction)
{
pShell->EndUndo();
pShell->EndAllAction(); if (m_aActiveContentArr[ContentTypeId::OUTLINE])
m_aActiveContentArr[ContentTypeId::OUTLINE]->Invalidate();
// tdf#143547 LO Writer: navigator should stand still on promoting and demoting // In addition to m_bIgnoreDocChange being true, selections are cleared before the Display // call. Either of these conditions disable restore of scroll position happening in the // Display function so it needs to be done here. auto nOldScrollPos = m_xTreeView->vadjustment_get_value();
// clear all selections to prevent the Display function from trying to reselect selected entries
m_xTreeView->unselect_all();
Display(true);
m_xTreeView->vadjustment_set_value(nOldScrollPos);
if (m_bIsRoot)
{ // reselect entries, do this only when in outline content navigation mode const SwOutlineNodes& rOutlineNds = pShell->GetNodes().GetOutLineNds(); for (SwTextNode* pNode : selectedOutlineNodes)
{
m_xTreeView->all_foreach([this, &rOutlineNds, pNode](weld::TreeIter& rEntry){ if (lcl_IsContentType(rEntry, *m_xTreeView)) returnfalse;
SwOutlineNodes::size_type nPos = weld::fromId<SwOutlineContent*>(
m_xTreeView->get_id(rEntry))->GetOutlinePos(); if (pNode == rOutlineNds[nPos]->GetTextNode())
{
std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry)); if (m_xTreeView->iter_parent(*xParent)
&& !m_xTreeView->get_row_expanded(*xParent))
{
m_xTreeView->expand_row(*xParent);
}
m_xTreeView->select(rEntry); returntrue;
} returnfalse;
});
}
UpdateContentFunctionsToolbar();
} else
{
m_pActiveShell->GetView().GetEditWin().GrabFocus();
m_bIgnoreDocChange = false;
UpdateTracking();
grab_focus();
}
}
m_bIgnoreDocChange = false;
}
// find content type entry
std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator()); bool bFoundEntry = rContentTree.get_iter_first(*xIter); while (bFoundEntry && rContentTypeName != rContentTree.get_text(*xIter))
bFoundEntry = rContentTree.iter_next_sibling(*xIter); // find content type content entry and select it if (!bFoundEntry) return;
rContentTree.expand_row(*xIter); // assure content type entry is expanded while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
{ if (rName == rContentTree.get_text(*xIter))
{ // 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 || !xFirstSelected ||
rContentTree.iter_compare(*xIter, *xFirstSelected) != 0)
{ // unselect all entries and make passed entry visible and selected
rContentTree.set_cursor(*xIter);
pThis->UpdateContentFunctionsToolbar();
} break;
}
}
}
// find content type entry
std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator()); bool bFoundEntry = rContentTree.get_iter_first(*xIter); while (bFoundEntry && SwResId(STR_CONTENT_TYPE_DRAWOBJECT) != rContentTree.get_text(*xIter))
bFoundEntry = rContentTree.iter_next_sibling(*xIter); // find content type content entry and select it if (bFoundEntry)
{
rContentTree.expand_row(*xIter); // assure content type entry is expanded while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
{ if (rName == rContentTree.get_text(*xIter))
{ if (!rContentTree.is_selected(*xIter))
{
rContentTree.select(*xIter);
rContentTree.scroll_to_row(*xIter);
pThis->UpdateContentFunctionsToolbar();
} break;
}
}
}
}
/** No idle with focus or while dragging */
IMPL_LINK_NOARG(SwContentTree, TimerUpdate, Timer *, void)
{ // No need to update if content tree is not visible if (!m_xTreeView->is_visible()) return;
// No update while focus is not in document. // No update while drag and drop. // Query view because the Navigator is cleared too late.
SwView* pView = GetParentWindow()->GetCreateView();
void SwContentTree::UpdateTracking()
{ if (State::HIDDEN == m_eState || !m_pActiveShell) return;
// only when treeview or treeview context menu does not have focus if (m_xTreeView->has_focus() || m_xTreeView->has_child_focus()) return;
// m_bIgnoreDocChange is set on delete and outline visibility toggle if (m_bIgnoreDocChange)
{
m_bIgnoreDocChange = false; return;
}
// bTrack is used to disallow tracking after jumping to an outline until the outline position // that was jumped to is no longer the current outline position. bool bTrack = true; if (m_nLastGotoContentWasOutlinePos != SwOutlineNodes::npos)
{ if (m_pActiveShell->GetOutlinePos() == m_nLastGotoContentWasOutlinePos)
bTrack = false; else
m_nLastGotoContentWasOutlinePos = SwOutlineNodes::npos;
}
if (bTrack)
{ // graphic, frame, and ole if (m_pActiveShell->GetSelectionType() &
(SelectionType::Graphic | SelectionType::Frame | SelectionType::Ole))
{
OUString aContentTypeName; if (m_pActiveShell->GetSelectionType() == SelectionType::Graphic &&
!(m_bIsRoot && m_nRootType != ContentTypeId::GRAPHIC))
{ if (!mTrackContentType[ContentTypeId::GRAPHIC]) return;
aContentTypeName = SwResId(STR_CONTENT_TYPE_GRAPHIC);
} elseif (m_pActiveShell->GetSelectionType() == SelectionType::Frame &&
!(m_bIsRoot && m_nRootType != ContentTypeId::FRAME))
{ if (!mTrackContentType[ContentTypeId::FRAME]) return;
aContentTypeName = SwResId(STR_CONTENT_TYPE_FRAME);
} elseif (m_pActiveShell->GetSelectionType() == SelectionType::Ole &&
!(m_bIsRoot && m_nRootType != ContentTypeId::OLE))
{ if (!mTrackContentType[ContentTypeId::OLE]) return;
aContentTypeName = SwResId(STR_CONTENT_TYPE_OLE);
} if (!aContentTypeName.isEmpty())
{
UIName aName(m_pActiveShell->GetFlyName());
lcl_SelectByContentTypeAndName(this, *m_xTreeView, aContentTypeName, aName.toString()); return;
}
} // drawing if ((m_pActiveShell->GetSelectionType() & (SelectionType::DrawObject |
SelectionType::DrawObjectEditMode |
SelectionType::DbForm)) &&
!(m_bIsRoot && m_nRootType != ContentTypeId::DRAWOBJECT))
{ if (mTrackContentType[ContentTypeId::DRAWOBJECT])
{ // Multiple selection is possible when in root content navigation view so unselect all // selected entries before reselecting. This causes a bit of an annoyance when the treeview // scroll bar is used and focus is in the document by causing the last selected entry to // scroll back into view. if (m_bIsRoot)
m_xTreeView->unselect_all();
SdrView* pSdrView = m_pActiveShell->GetDrawView(); if (pSdrView)
{ for (size_t nIdx(0); nIdx < pSdrView->GetMarkedObjectList().GetMarkCount(); nIdx++)
{
SdrObject* pSelected = pSdrView->GetMarkedObjectList().GetMark(nIdx)->GetMarkedSdrObj();
OUString aName(pSelected->GetName()); if (!aName.isEmpty())
lcl_SelectDrawObjectByName(this, *m_xTreeView, aName);
}
} else
{ // clear treeview selections
m_xTreeView->unselect_all();
UpdateContentFunctionsToolbar();
}
} return;
} // footnotes and endnotes if (SwContentAtPos aContentAtPos(IsAttrAtPos::Footnote);
m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos)
&& aContentAtPos.pFndTextAttr &&
!(m_bIsRoot && (m_nRootType != ContentTypeId::FOOTNOTE &&
m_nRootType != ContentTypeId::ENDNOTE)))
{ if (!aContentAtPos.pFndTextAttr->GetFootnote().IsEndNote())
{ if (mTrackContentType[ContentTypeId::FOOTNOTE])
lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::FOOTNOTE,
aContentAtPos.pFndTextAttr);
} elseif (mTrackContentType[ContentTypeId::ENDNOTE])
lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::ENDNOTE,
aContentAtPos.pFndTextAttr); return;
} // references if (SwContentAtPos aContentAtPos(IsAttrAtPos::RefMark);
m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos) &&
aContentAtPos.pFndTextAttr &&
!(m_bIsRoot && m_nRootType != ContentTypeId::REFERENCE))
{ if (mTrackContentType[ContentTypeId::REFERENCE])
{ const SwFormatRefMark& rRefMark = aContentAtPos.pFndTextAttr->GetRefMark();
lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_REFERENCE),
rRefMark.GetRefName().toString());
} return;
} // hyperlinks // not in ToxContent tdf#148312 if (const SwSection* pSection = m_pActiveShell->GetCurrSection(); !pSection
|| (pSection && pSection->GetType() != SectionType::ToxContent))
{ if (SwContentAtPos aContentAtPos(IsAttrAtPos::InetAttr);
m_pActiveShell->GetContentAtPos(m_pActiveShell->GetCursorDocPos(), aContentAtPos)
&& (!m_bIsRoot || m_nRootType == ContentTypeId::URLFIELD))
{ // Because hyperlink item names do not need to be unique, finding the corresponding // item in the tree by name may result in incorrect selection. Find the item in the // tree by comparing the SwTextINetFormat pointer at the document cursor position to // that stored in the item SwURLFieldContent. if (mTrackContentType[ContentTypeId::URLFIELD])
lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::URLFIELD,
aContentAtPos.pFndTextAttr); return;
}
} // fields, comments if (SwField* pField = m_pActiveShell->GetCurField(); pField &&
!(m_bIsRoot &&
m_nRootType != ContentTypeId::TEXTFIELD &&
m_nRootType != ContentTypeId::POSTIT))
{
ContentTypeId eCntTypeId =
pField->GetTypeId() == SwFieldTypesEnum::Postit ? ContentTypeId::POSTIT :
ContentTypeId::TEXTFIELD; if (mTrackContentType[eCntTypeId])
lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, eCntTypeId, pField); return;
} if (SwPostItMgr* pPostItMgr = m_pActiveShell->GetPostItMgr();
pPostItMgr && pPostItMgr->HasActiveAnnotationWin()
&& !(m_bIsRoot && m_nRootType != ContentTypeId::POSTIT))
{ if (mTrackContentType[ContentTypeId::POSTIT])
{ if (const SwField* pField = pPostItMgr->GetActiveSidebarWin()->GetPostItField())
lcl_SelectByContentTypeAndAddress(this, *m_xTreeView, ContentTypeId::POSTIT,
pField);
} return;
} // table if (m_pActiveShell->IsCursorInTable() &&
!(m_bIsRoot && m_nRootType != ContentTypeId::TABLE))
{ if (mTrackContentType[ContentTypeId::TABLE] && m_pActiveShell->GetTableFormat())
{
UIName aName = m_pActiveShell->GetTableFormat()->GetName();
lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_TABLE),
aName.toString()); return;
}
} // indexes if (const SwTOXBase* pTOX = m_pActiveShell->GetCurTOX(); pTOX &&
!(m_bIsRoot && m_nRootType != ContentTypeId::INDEX))
{ if (mTrackContentType[ContentTypeId::INDEX])
lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_INDEX),
pTOX->GetTOXName().toString()); return;
} // section if (const SwSection* pSection = m_pActiveShell->GetCurrSection(); pSection &&
!(m_bIsRoot && m_nRootType != ContentTypeId::REGION))
{ if (mTrackContentType[ContentTypeId::REGION])
{
lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_REGION),
pSection->GetSectionName().toString()); return;
} else
{ // prevent fall through to outline tracking when section tracking is off and the last // GotoContent is the current section if (m_nLastSelType == ContentTypeId::REGION &&
m_xTreeView->get_selected_text() == pSection->GetSectionName()) return;
} // fall through to outline tracking when section tracking is off and the last GotoContent // is not the current section
}
} // find out where the cursor is const SwOutlineNodes::size_type nActPos = GetWrtShell()->GetOutlinePos(MAXLEVEL); 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
std::unique_ptr<weld::TreeIter> xFirstEntry(m_xTreeView->make_iterator()); if (m_xTreeView->get_iter_first(*xFirstEntry))
m_xTreeView->expand_row(*xFirstEntry);
m_xTreeView->all_foreach([this, nActPos](weld::TreeIter& rEntry){ bool bRet = false; if (lcl_IsContent(rEntry, *m_xTreeView) && weld::fromId<SwContent*>(
m_xTreeView->get_id(rEntry))->GetParent()->GetType() ==
ContentTypeId::OUTLINE)
{ if (weld::fromId<SwOutlineContent*>(
m_xTreeView->get_id(rEntry))->GetOutlinePos() == nActPos)
{
std::unique_ptr<weld::TreeIter> xFirstSelected(
m_xTreeView->make_iterator()); if (!m_xTreeView->get_selected(xFirstSelected.get()))
xFirstSelected.reset(); // only select if not already selected or tree has multiple entries selected if (m_xTreeView->count_selected_rows() != 1 || !xFirstSelected ||
m_xTreeView->iter_compare(rEntry, *xFirstSelected) != 0)
{ if (m_nOutlineTracking == 2) // focused outline tracking
{ // collapse to children of root node
std::unique_ptr<weld::TreeIter> xChildEntry(
m_xTreeView->make_iterator()); if (m_xTreeView->get_iter_first(*xChildEntry) &&
m_xTreeView->iter_children(*xChildEntry))
{ do
{ if (weld::fromId<SwContent*>(
m_xTreeView->get_id(*xChildEntry))->
GetParent()->GetType() == ContentTypeId::OUTLINE)
m_xTreeView->collapse_row(*xChildEntry); else break;
} while (m_xTreeView->iter_next(*xChildEntry));
}
} // unselect all entries, make pEntry visible, and select
m_xTreeView->set_cursor(rEntry);
UpdateContentFunctionsToolbar();
// tdf#149279 show at least two outline entries before the set cursor entry
std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator(&rEntry)); for (int i = 0; i < 2; i++)
{ if (m_xTreeView->get_iter_depth(*xIter) == 0) break; if (!m_xTreeView->iter_previous(*xIter)) break; while (!weld::IsEntryVisible(*m_xTreeView, *xIter))
m_xTreeView->iter_parent(*xIter);
} // Assure the scroll to row is collapsed after scrolling if it was collapsed // before. This is required here to make gtkinst scroll_to_row behave like // salinst. constbool bRowExpanded = m_xTreeView->get_row_expanded(*xIter);
m_xTreeView->scroll_to_row(*xIter); if (!bRowExpanded)
m_xTreeView->collapse_row(*xIter);
}
bRet = true;
}
} else
{ // use of this break assumes outline content type is first in tree if (lcl_IsContentType(rEntry, *m_xTreeView) &&
weld::fromId<SwContentType*>(
m_xTreeView->get_id(rEntry))->GetType() !=
ContentTypeId::OUTLINE)
bRet = true;
} return bRet;
}); return;
}
// 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))
{
SwPaM* pCursor = m_pActiveShell->GetCursor();
IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess(); auto ppBookmark = pMarkAccess->getBookmarksBegin(); if (pCursor && ppBookmark != pMarkAccess->getBookmarksEnd()
&& !(m_bIsRoot && m_nRootType != ContentTypeId::BOOKMARK))
{
SwMarkName 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;
} elseif (!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.toString()); return;
}
}
}
// find content type entry bool bFoundEntry = rContentTree.get_iter_first(*xIter); while (bFoundEntry)
{
assert(dynamic_cast<SwContentType*>(weld::fromId<SwTypeNumber*>(rContentTree.get_id(*xIter))));
SwContentType* pContentType = weld::fromId<SwContentType*>(rContentTree.get_id(*xIter)); if (eContentType == pContentType->GetType()) break;
bFoundEntry = rContentTree.iter_next_sibling(*xIter);
}
if (!bFoundEntry) returnfalse;
// find content type content entry and compare it to the passed entry while (rContentTree.iter_next(*xIter))
{ if (rName == rContentTree.get_text(*xIter))
{ if (rContentTree.iter_compare(*xIter, rEntry) == 0) returntrue;
}
} returnfalse;
}
// Done on the first selection move if (bFirstMove) // only do once
{ if (nTargetPos == SwOutlineNodes::npos || nSourcePos > nTargetPos)
{ // Up moves // The first up move sets the up move amount for the remaining selected outlines to be moved if (nTargetPos != SwOutlineNodes::npos)
nPrevTargetPosOrOffset = nSourcePos - nTargetPos; else
nPrevTargetPosOrOffset = nSourcePos + 1;
} elseif (nSourcePos < nTargetPos)
{ // Down moves // The first down move sets the source and target positions for the remaining selected outlines to be moved
nPrevSourcePos = nSourcePos;
nPrevTargetPosOrOffset = nTargetPos;
}
bFirstMove = false;
} else
{ if (nTargetPos == SwOutlineNodes::npos || nSourcePos > nTargetPos)
{ // Move up
nTargetPos = nSourcePos - nPrevTargetPosOrOffset;
} elseif (nSourcePos < nTargetPos)
{ // Move down
nSourcePos = nPrevSourcePos;
nTargetPos = nPrevTargetPosOrOffset;
}
}
GetParentWindow()->MoveOutline(nSourcePos, nTargetPos);
}
}
} for (const rtl::Reference<SdrObject>& pTemp : *pPage)
{ bool bMark = pDrawView->IsObjMarked(pTemp.get()); switch( pTemp->GetObjIdentifier() )
{ case SdrObjKind::Group: case SdrObjKind::Text: case SdrObjKind::Line: case SdrObjKind::Rectangle: case SdrObjKind::CircleOrEllipse: case SdrObjKind::CircleSection: case SdrObjKind::CircleArc: case SdrObjKind::CircleCut: case SdrObjKind::Polygon: case SdrObjKind::PolyLine: case SdrObjKind::PathLine: case SdrObjKind::PathFill: case SdrObjKind::FreehandLine: case SdrObjKind::FreehandFill: case SdrObjKind::PathPoly: case SdrObjKind::PathPolyLine: case SdrObjKind::Caption: case SdrObjKind::CustomShape: if( bMark )
hasObjectMarked = true; break; default: if ( bMark )
{
SdrPageView* pPV = pDrawView->GetSdrPageView/*GetPageViewPvNum*/(/*0*/); if (pPV)
{
pDrawView->MarkObj(pTemp.get(), pPV, true);
}
}
} //mod end
} if ( !hasObjectMarked )
{
SwEditWin& rEditWindow = m_pActiveShell->GetView().GetEditWin();
vcl::KeyCode tempKeycode( KEY_ESCAPE );
KeyEvent rKEvt( 0 , tempKeycode ); static_cast<vcl::Window*>(&rEditWindow)->KeyInput( rKEvt );
}
}
}
IMPL_LINK(SwContentTree, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString)
{ // Prevent tool tip handling when handling document change. The entry that was present when // the tooltip signal was fired might no longer be valid by the time it gets here. For example, // when the mouse pointer is on an entry in the tree that is deleted in the document by an // undo/redo. Please see similar note in MouseMoveHdl. if (m_bDocHasChanged) return OUString();
// tdf#163646 - Show in the tooltip for heading entries in Writer Navigator the // outline word and character count of the heading including the outline word and // character count of all sub headings int nEntryDepth = m_xTreeView->get_iter_depth(rEntry);
std::unique_ptr<weld::TreeIter> xIter = m_xTreeView->make_iterator(&rEntry); int nIterDepth; while (m_xTreeView->iter_next(*xIter)
&& (nIterDepth = m_xTreeView->get_iter_depth(*xIter)))
{ if (nIterDepth <= nEntryDepth)
{
pOutlineContent
= weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xIter));
pEndNode = rOutlineNodes[pOutlineContent->GetOutlinePos()]; break;
}
}
std::unique_ptr<weld::TreeIter> xFirst(m_xTreeView->make_iterator()); if (!m_xTreeView->get_selected(xFirst.get())) return; // this shouldn't happen, but better to be safe than ...
// 1. Get the position of the bit in the block where the value of the alphabetical sort // setting is persistently stored for the content type. constint nShift = static_cast<int>(pCntType->GetType());
assert(nShift > -1);
// 2. Create a bit mask to use to filter the sort value from the persistent block. const sal_Int32 nMask = 1 << nShift;
// 3. Toggle the persistent sort value only when it is different than the instance sort // value. These may already be the same if both the floating and sidebar version of the // Navigator are open. const sal_Int32 nBlock = m_pConfig->GetSortAlphabeticallyBlock(); bool bConfigSortValue = ~nBlock & nMask; bool bInstanceSortValue = pCntType->IsAlphabeticSort(); if (bConfigSortValue != bInstanceSortValue)
m_pConfig->SetSortAlphabeticallyBlock(nBlock ^ nMask);
// 4. Always toggle the instance value.
pCntType->SetAlphabeticSort(!bInstanceSortValue);
auto nSelectedPopupEntry = rSelectedPopupEntry.toUInt32(); switch (nSelectedPopupEntry)
{ case TOGGLE_OUTLINE_CONTENT_VISIBILITY: case HIDE_OUTLINE_CONTENT_VISIBILITY: case SHOW_OUTLINE_CONTENT_VISIBILITY:
{
m_pActiveShell->EnterStdMode();
m_bIgnoreDocChange = true;
SwOutlineContent* pCntFirst = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(*xFirst));
// toggle the outline node outline content visible attribute if (nSelectedPopupEntry == TOGGLE_OUTLINE_CONTENT_VISIBILITY)
{
SwNode* pNode = m_pActiveShell->GetDoc()->GetNodes().GetOutLineNds()[pCntFirst->GetOutlinePos()];
pNode->GetTextNode()->SetAttrOutlineContentVisible(
!m_pActiveShell->GetAttrOutlineContentVisible(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 bShow(nSelectedPopupEntry == SHOW_OUTLINE_CONTENT_VISIBILITY); do
{ if (m_pActiveShell->IsOutlineContentVisible(nPos) != bShow)
m_pActiveShell->GetDoc()->GetNodes().GetOutLineNds()[nPos]->GetTextNode()->SetAttrOutlineContentVisible(bShow);
} while (++nPos < nOutlineNodesCount
&& (nLevel == -1 || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel));
}
m_pActiveShell->InvalidateOutlineContentVisibility(); // show in the document what was toggled if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
m_pActiveShell->GotoPage(1, true); else
m_pActiveShell->GotoOutline(pCntFirst->GetOutlinePos());
grab_focus();
m_bIgnoreDocChange = false;
m_pActiveShell->SetModified();
m_pActiveShell->GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
} break; case 11: case 12: case 13:
nSelectedPopupEntry -= 10; if(m_nOutlineTracking != nSelectedPopupEntry)
SetOutlineTracking(static_cast<sal_uInt8>(nSelectedPopupEntry)); break; //Outlinelevel case 101: case 102: case 103: case 104: case 105: case 106: case 107: case 108: case 109: case 110:
nSelectedPopupEntry -= 100; if(m_nOutlineLevel != nSelectedPopupEntry )
SetOutlineLevel(static_cast<sal_Int8>(nSelectedPopupEntry)); break; case 402:
EditEntry(*xFirst, EditEntryMode::UPD_IDX); break; // Edit entry case 403:
EditEntry(*xFirst, EditEntryMode::EDIT); break; case 404:
EditEntry(*xFirst, EditEntryMode::UNPROTECT_TABLE); break; case 405 :
{ const SwTOXBase* pBase = weld::fromId<SwTOXBaseContent*>(m_xTreeView->get_id(*xFirst))
->GetTOXBase();
m_pActiveShell->SetTOXBaseReadonly(*pBase, !SwEditShell::IsTOXBaseReadonly(*pBase));
} break; case 502 :
EditEntry(*xFirst, EditEntryMode::RENAME); break; case 700:
{
m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_OUTLINE_TO_CLIPBOARD); break;
} case 800:
ExpandOrCollapseAll(*m_xTreeView, *xFirst); break; case 801:
ExecCommand(u"chapterup", true); break; case 802:
ExecCommand(u"chapterdown", true); break; case 803:
ExecCommand(u"promote", true); break; case 804:
ExecCommand(u"demote", true); break; case 805: // select document content
{
m_pActiveShell->KillPams();
m_pActiveShell->ClearMark();
m_pActiveShell->EnterAddMode();
SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xFirst)); const ContentTypeId eTypeId = pCnt->GetParent()->GetType(); if (eTypeId == ContentTypeId::OUTLINE)
{
SwOutlineNodes::size_type nActPos = weld::fromId<SwOutlineContent*>(
m_xTreeView->get_id(*xFirst))->GetOutlinePos();
m_pActiveShell->GotoOutline(nActPos);
m_xTreeView->selected_foreach([this](weld::TreeIter& rEntry){
SwOutlineNodes::size_type nPos = weld::fromId<SwOutlineContent*>(
m_xTreeView->get_id(rEntry))->GetOutlinePos();
m_pActiveShell->SttSelect(); // select children if not expanded and don't kill PaMs
m_pActiveShell->MakeOutlineSel(nPos, nPos,
!m_xTreeView->get_row_expanded(rEntry), false);
m_pActiveShell->EndSelect(); returnfalse;
});
} elseif (eTypeId == ContentTypeId::TABLE)
{
m_pActiveShell->GotoTable(UIName(pCnt->GetName()));
m_pActiveShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_TABLE_SELECT_ALL);
} elseif (eTypeId == ContentTypeId::REGION)
{
m_pActiveShell->EnterStdMode();
m_pActiveShell->GotoRegion(pCnt->GetName());
GotoCurrRegionAndSkip(m_pActiveShell->GetCurrentShellCursor(), fnRegionEnd, m_pActiveShell->IsReadOnlyAvailable());
m_pActiveShell->SttSelect();
GotoCurrRegionAndSkip(m_pActiveShell->GetCurrentShellCursor(), fnRegionStart, m_pActiveShell->IsReadOnlyAvailable());
m_pActiveShell->EndSelect();
m_pActiveShell->UpdateCursor();
}
m_pActiveShell->LeaveAddMode();
} break; case 900:
{
SwContent* pCnt = weld::fromId<SwContent*>(m_xTreeView->get_id(*xFirst));
GotoContent(pCnt);
} break; //Display default: if(nSelectedPopupEntry > 300 && nSelectedPopupEntry < 400)
{
nSelectedPopupEntry -= 300;
SwView *pView = SwModule::GetFirstView(); while (pView)
{
nSelectedPopupEntry --; if(nSelectedPopupEntry == 0)
{
SetConstantShell(&pView->GetWrtShell()); break;
}
pView = SwModule::GetNextView(pView);
} if(nSelectedPopupEntry)
{
m_bViewHasChanged = nSelectedPopupEntry == 1;
m_eState = (nSelectedPopupEntry == 1) ? State::ACTIVE : State::HIDDEN;
Display(nSelectedPopupEntry == 1);
}
GetParentWindow()->UpdateListBox();
}
}
}
void SwContentTree::DeleteOutlineSelections()
{ const SwOutlineNodes& rOutlineNodes = m_pActiveShell->GetNodes().GetOutLineNds(); auto nChapters(0);
m_pActiveShell->StartAction();
m_pActiveShell->EnterAddMode();
m_xTreeView->selected_foreach([this, &rOutlineNodes, &nChapters](weld::TreeIter& rEntry){
++nChapters; if (m_xTreeView->iter_has_child(rEntry) &&
!m_xTreeView->get_row_expanded(rEntry)) // only count children if not expanded
{
nChapters += m_xTreeView->iter_n_children(rEntry);
}
SwOutlineNodes::size_type nActPos = weld::fromId<SwOutlineContent*>(m_xTreeView->get_id(rEntry))->GetOutlinePos(); if (m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton())
{ // make folded content visible so it can be selected if (!m_pActiveShell->IsOutlineContentVisible(nActPos))
m_pActiveShell->MakeOutlineContentVisible(nActPos); if (!m_xTreeView->get_row_expanded(rEntry))
{ // include children
SwNode* pNode = rOutlineNodes[nActPos]; constint nLevel = pNode->GetTextNode()->GetAttrOutlineLevel() - 1; for (auto nPos = nActPos + 1; nPos < rOutlineNodes.size(); ++nPos)
{
pNode = rOutlineNodes[nPos]; constint nNextLevel = pNode->GetTextNode()->GetAttrOutlineLevel() - 1; if (nNextLevel <= nLevel) break; if (!m_pActiveShell->IsOutlineContentVisible(nNextLevel))
m_pActiveShell->MakeOutlineContentVisible(nNextLevel);
}
}
}
m_pActiveShell->SttSelect();
m_pActiveShell->MakeOutlineSel(nActPos, nActPos, !m_xTreeView->get_row_expanded(rEntry), false); // select children if not expanded // The outline selection may already be to the start of the following outline paragraph // as happens when a table is the last content of the to be deleted outline. In this case // do not extend the to be deleted selection right or the first character of the following // outline paragraph will be removed. Also check if no selection was made which indicates // an empty paragraph and selection right is needed. if (!m_pActiveShell->IsSttPara() || !m_pActiveShell->HasSelection())
m_pActiveShell->Right(SwCursorSkipMode::Chars, true, 1, false);
m_pActiveShell->EndSelect(); returnfalse;
});
m_pActiveShell->LeaveAddMode();
// Mode Change: Show active view // only called from IMPL_LINK(SwNavigationPI, DocListBoxSelectHdl, weld::ComboBox&, rBox, void) void SwContentTree::ShowActualView()
{ if (SwView* pView = m_pDialog->GetCreateView())
{
SetConstantShell(pView->GetWrtShellPtr());
m_pDialog->UpdateListBox();
}
}
IMPL_LINK_NOARG(SwContentTree, SelectHdl, weld::TreeView&, void)
{ if (m_pConfig->IsNavigateOnSelect())
{
ContentDoubleClickHdl(*m_xTreeView);
grab_focus();
}
UpdateContentFunctionsToolbar(); if (m_bIsRoot) return; // Select the content type in the Navigate By control
std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator()); if (!m_xTreeView->get_selected(xEntry.get())) return; while (m_xTreeView->get_iter_depth(*xEntry))
m_xTreeView->iter_parent(*xEntry);
m_pDialog->SelectNavigateByContentType(m_xTreeView->get_text(*xEntry));
}
void SwContentTree::CopyOutlineSelections()
{
m_pActiveShell->LockView(true);
{
MakeAllOutlineContentTemporarilyVisible a(m_pActiveShell->GetDoc());
m_pActiveShell->AssureStdMode();
m_pActiveShell->EnterAddMode();
size_t nCount = m_xTreeView->get_selected_rows().size();
m_xTreeView->selected_foreach([this, &nCount](weld::TreeIter& rEntry){
SwOutlineNodes::size_type nOutlinePos = reinterpret_cast<SwOutlineContent*>(
m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos();
m_pActiveShell->SttSelect();
m_pActiveShell->MakeOutlineSel(nOutlinePos, nOutlinePos,
!m_xTreeView->get_row_expanded(rEntry), false); // don't move if this is the last selected outline or the cursor is at start of para if (--nCount && !m_pActiveShell->IsSttPara())
m_pActiveShell->Right(SwCursorSkipMode::Chars, true, 1, false);
m_pActiveShell->EndSelect(); returnfalse;
});
m_pActiveShell->LeaveAddMode();
m_pActiveShell->GetView().GetViewFrame().GetBindings().Execute(SID_COPY);
}
m_pActiveShell->LockView(false);
}
void SwContentTree::GotoContent(const SwContent* pCnt)
{ if (pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE)
{ // Maybe the outline node doesn't have a layout frame to go to. const SwOutlineNodes::size_type nPos = static_cast<const SwOutlineContent*>(pCnt)->GetOutlinePos(); const SwNodes& rNds = m_pActiveShell->GetDoc()->GetNodes();
SwTextNode* pTextNd = rNds.GetOutLineNds()[nPos]->GetTextNode(); if (!pTextNd->getLayoutFrame(m_pActiveShell->GetLayout())) return;
}
if (m_bSelectTo)
{ if (m_pActiveShell->IsCursorInTable() ||
(m_pActiveShell->GetCursor()->GetPoint()->nNode.GetIndex() <=
m_pActiveShell->GetDoc()->GetNodes().GetEndOfExtras().GetIndex()))
{
m_bSelectTo = false;
m_pActiveShell->GetView().GetEditWin().GrabFocus(); return;
}
}
std::optional<SwPosition> oPosition; if (m_bSelectTo)
oPosition.emplace(m_pActiveShell->GetCursor()->GetPoint()->nNode,
m_pActiveShell->GetCursor()->GetPoint()->nContent);
switch(m_nLastSelType = pCnt->GetParent()->GetType())
{ case ContentTypeId::TEXTFIELD:
{
m_pActiveShell->GotoFormatField(
*static_cast<const SwTextFieldContent*>(pCnt)->GetFormatField());
} break; case ContentTypeId::OUTLINE :
{ const SwOutlineNodes::size_type nPos = static_cast<const SwOutlineContent*>(pCnt)->GetOutlinePos();
m_pActiveShell->GotoOutline(nPos);
m_nLastGotoContentWasOutlinePos = nPos;
} break; case ContentTypeId::TABLE :
{
m_pActiveShell->GotoTable(UIName(pCnt->GetName()));
} break; case ContentTypeId::FRAME : case ContentTypeId::GRAPHIC : case ContentTypeId::OLE :
{
m_pActiveShell->GotoFly(UIName(pCnt->GetName()));
} break; case ContentTypeId::BOOKMARK:
{
m_pActiveShell->StartAction();
m_pActiveShell->GotoMark(SwMarkName(pCnt->GetName()));
m_pActiveShell->EndAction();
m_sSelectedItem = pCnt->GetName();
// If the hidden title of SwNavigatorPanel was emptied via UNO XPanel interface, // store the name of the selected bookmark there. This allows to query the // selected bookmark using UNO e.g. in add-ons, i.e. to disambiguate when // multiple bookmarks are there on the selected text range. // Note: this is a workaround because getDialog() of XPanel is not implemented // for SwNavigatorPanel.
rtl::Reference< SwXTextDocument > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
Reference<frame::XController2> xController( xModel->getCurrentController(), uno::UNO_QUERY); if ( !xController.is() ) break;
Reference<ui::XSidebarProvider> xSidebarProvider = xController->getSidebar(); if ( !xSidebarProvider.is() ) break;
Reference<ui::XDecks> xDecks = xSidebarProvider->getDecks(); if ( !xDecks.is() ) break;
if (!xDecks->hasByName(u"NavigatorDeck"_ustr)) break;
Reference<ui::XDeck> xDeck ( xDecks->getByName(u"NavigatorDeck"_ustr), uno::UNO_QUERY); if ( !xDeck.is() ) break;
Reference<ui::XPanels> xPanels = xDeck->getPanels(); if ( !xPanels.is() ) break;
if (xPanels->hasByName(u"SwNavigatorPanel"_ustr))
{
Reference<ui::XPanel> xPanel ( xPanels->getByName(u"SwNavigatorPanel"_ustr), uno::UNO_QUERY); if ( !xPanel.is() || !xPanel->getTitle().isEmpty() ) break;
xPanel->setTitle( pCnt->GetName() );
}
} break; case ContentTypeId::REGION :
{
m_pActiveShell->GotoRegion(pCnt->GetName());
} break; case ContentTypeId::URLFIELD:
{ if(m_pActiveShell->GotoINetAttr(
*static_cast<const SwURLFieldContent*>(pCnt)->GetINetAttr() ))
{
m_pActiveShell->Right(SwCursorSkipMode::Chars, false, 1, false);
}
} break; case ContentTypeId::REFERENCE:
{
m_pActiveShell->GotoRefMark(SwMarkName(pCnt->GetName()));
} break; case ContentTypeId::INDEX:
{ const UIName sName(pCnt->GetName()); if (!m_pActiveShell->GotoNextTOXBase(&sName))
m_pActiveShell->GotoPrevTOXBase(&sName);
} break; case ContentTypeId::POSTIT: if (SwFormatField const*const pField{static_cast<const SwPostItContent*>(pCnt)->GetPostIt()})
{
m_pActiveShell->GotoFormatField(*pField);
} break; case ContentTypeId::DRAWOBJECT:
{
m_pActiveShell->GotoDrawingObject(pCnt->GetName());
} break; case ContentTypeId::FOOTNOTE: case ContentTypeId::ENDNOTE:
{ const SwTextFootnote* pFootnote = static_cast<const SwTextFootnoteContent*>(pCnt)->GetTextFootnote(); if (!pFootnote) return;
m_pActiveShell->GotoFootnoteAnchor(*pFootnote);
} break; default: break;
}
if (m_bSelectTo)
{
m_pActiveShell->SttCursorMove(); while (m_pActiveShell->IsCursorInTable())
{
m_pActiveShell->MoveTable(GotoCurrTable, fnTableStart); if (!m_pActiveShell->Left(SwCursorSkipMode::Chars, false, 1, false)) break; // Table is at the beginning of the document. It can't be selected this way.
}
m_pActiveShell->EndCursorMove();
// Assure cursor is in visible view area. // (tdf#147041) Always show the navigated outline at the top of the visible view area. if (pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE ||
(!m_pActiveShell->IsCursorVisible() && !m_pActiveShell->IsFrameSelected() &&
!m_pActiveShell->GetSelectedObjCount()))
{
Point aPoint(rView.GetVisArea().getX(), m_pActiveShell->GetCursorDocPos().getY());
rView.SetVisArea(aPoint);
}
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.262Bemerkung:
(vorverarbeitet am 2026-05-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.