1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/string.hxx>
21 #include <editeng/frmdiritem.hxx>
22 #include <svl/urlbmk.hxx>
23 #include <osl/thread.h>
24 #include <sal/log.hxx>
25 #include <tools/urlobj.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/event.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <o3tl/enumrange.hxx>
31 #include <o3tl/sorted_vector.hxx>
33 #include <vcl/commandevent.hxx>
34 #include <vcl/weldutils.hxx>
35 #include <sot/formats.hxx>
36 #include <o3tl/string_view.hxx>
37 #include <uiitems.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmtinfmt.hxx>
40 #include <txtinet.hxx>
42 #include <swmodule.hxx>
46 #include <drawdoc.hxx>
47 #include <content.hxx>
52 #include <section.hxx>
55 #include <navicont.hxx>
56 #include <navicfg.hxx>
59 #include <IDocumentSettingAccess.hxx>
60 #include <IDocumentDrawModelAccess.hxx>
61 #include <IDocumentOutlineNodes.hxx>
62 #include <unotxvw.hxx>
65 #include <strings.hrc>
66 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
67 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
68 #include <com/sun/star/text/XTextTablesSupplier.hpp>
69 #include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
70 #include <com/sun/star/text/XDocumentIndex.hpp>
71 #include <com/sun/star/text/XBookmarksSupplier.hpp>
72 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
73 #include <com/sun/star/text/XTextFramesSupplier.hpp>
74 #include <com/sun/star/ui/XSidebarProvider.hpp>
75 #include <com/sun/star/ui/XDecks.hpp>
76 #include <com/sun/star/ui/XDeck.hpp>
77 #include <com/sun/star/ui/XPanels.hpp>
78 #include <com/sun/star/ui/XPanel.hpp>
79 #include <svx/svdpage.hxx>
80 #include <svx/svdview.hxx>
81 #include <SwRewriter.hxx>
83 #include <numrule.hxx>
86 #include <PostItMgr.hxx>
87 #include <postithelper.hxx>
89 #include <swabstdlg.hxx>
90 #include <bitmaps.hlst>
92 #include <AnnotationWin.hxx>
95 #include <fmtcntnt.hxx>
96 #include <docstat.hxx>
98 #include <viewopt.hxx>
100 #include <IDocumentFieldsAccess.hxx>
101 #include <txtfld.hxx>
102 #include <fldmgr.hxx>
104 #include <frameformats.hxx>
106 #include <ftnidx.hxx>
107 #include <txtftn.hxx>
108 #include <fmtftn.hxx>
110 #include <txtannotationfld.hxx>
111 #include <txtfrm.hxx>
112 #include <txtrfmrk.hxx>
113 #include <svx/sdr/overlay/overlayselection.hxx>
114 #include <svx/sdr/overlay/overlayobject.hxx>
115 #include <svx/sdr/overlay/overlaymanager.hxx>
116 #include <svx/sdrpaintwindow.hxx>
117 #include <node2lay.hxx>
122 using namespace ::com::sun::star
;
123 using namespace ::com::sun::star::text
;
124 using namespace ::com::sun::star::uno
;
125 using namespace ::com::sun::star::container
;
130 Symbolic name representations of numeric values used for the Outline Content Visibility popup
131 menu item ids. The numbers are chosen arbitrarily to not over overlap other menu item ids.
132 see: SwContentTree::ExecuteContextMenuAction, navigatorcontextmenu.ui
134 1512 toggle outline content visibility of the selected outline entry
135 1513 make the outline content of the selected outline entry and children not visible
136 1514 make the outline content of the selected entry and children visible
138 const sal_uInt32 TOGGLE_OUTLINE_CONTENT_VISIBILITY
= 1512;
139 const sal_uInt32 HIDE_OUTLINE_CONTENT_VISIBILITY
= 1513;
140 const sal_uInt32 SHOW_OUTLINE_CONTENT_VISIBILITY
= 1514;
142 constexpr char NAVI_BOOKMARK_DELIM
= '\x01';
147 : public o3tl::sorted_vector
<std::unique_ptr
<SwContent
>, o3tl::less_uniqueptr_to
<SwContent
>,
148 o3tl::find_partialorder_ptrequals
>
154 std::map
<OUString
, std::map
<void*, bool>> lcl_DocOutLineExpandStateMap
;
156 bool lcl_IsContent(const weld::TreeIter
& rEntry
, const weld::TreeView
& rTreeView
)
158 return weld::fromId
<const SwTypeNumber
*>(rTreeView
.get_id(rEntry
))->GetTypeId() == CTYPE_CNT
;
161 bool lcl_IsContentType(const weld::TreeIter
& rEntry
, const weld::TreeView
& rTreeView
)
163 return weld::fromId
<const SwTypeNumber
*>(rTreeView
.get_id(rEntry
))->GetTypeId() == CTYPE_CTT
;
166 bool lcl_IsLowerOutlineContent(const weld::TreeIter
& rEntry
, const weld::TreeView
& rTreeView
, sal_uInt8 nLevel
)
168 return weld::fromId
<const SwOutlineContent
*>(rTreeView
.get_id(rEntry
))->GetOutlineLevel() < nLevel
;
171 bool lcl_FindShell(SwWrtShell
const * pShell
)
174 SwView
*pView
= SwModule::GetFirstView();
177 if(pShell
== &pView
->GetWrtShell())
182 pView
= SwModule::GetNextView(pView
);
187 bool lcl_IsUiVisibleBookmark(const ::sw::mark::IMark
* pMark
)
189 return IDocumentMarkAccess::GetType(*pMark
) == IDocumentMarkAccess::MarkType::BOOKMARK
;
192 OUString
lcl_GetFootnoteText(const SwTextFootnote
& rTextFootnote
)
194 SwNodeIndex
aIdx(*rTextFootnote
.GetStartNode(), 1);
195 SwContentNode
* pCNd
= aIdx
.GetNode().GetTextNode();
197 pCNd
= aIdx
.GetNodes().GoNext(&aIdx
);
198 return pCNd
->IsTextNode() ? static_cast<SwTextNode
*>(pCNd
)->GetText() : OUString();
202 // Content, contains names and reference at the content type.
204 SwContent::SwContent(const SwContentType
* pCnt
, OUString aName
, double nYPos
) :
205 SwTypeNumber(CTYPE_CNT
),
207 m_sContentName(std::move(aName
)),
214 SwTypeNumber::~SwTypeNumber()
218 bool SwContent::IsProtect() const
223 bool SwTextFieldContent::IsProtect() const
225 return m_pFormatField
->IsProtect();
228 bool SwPostItContent::IsProtect() const
230 return m_pField
->IsProtect();
233 bool SwURLFieldContent::IsProtect() const
235 return m_pINetAttr
->IsProtect();
238 SwGraphicContent::~SwGraphicContent()
242 SwTOXBaseContent::~SwTOXBaseContent()
246 const TranslateId STR_CONTENT_TYPE_ARY
[] =
248 STR_CONTENT_TYPE_OUTLINE
,
249 STR_CONTENT_TYPE_TABLE
,
250 STR_CONTENT_TYPE_FRAME
,
251 STR_CONTENT_TYPE_GRAPHIC
,
252 STR_CONTENT_TYPE_OLE
,
253 STR_CONTENT_TYPE_BOOKMARK
,
254 STR_CONTENT_TYPE_REGION
,
255 STR_CONTENT_TYPE_URLFIELD
,
256 STR_CONTENT_TYPE_REFERENCE
,
257 STR_CONTENT_TYPE_INDEX
,
258 STR_CONTENT_TYPE_POSTIT
,
259 STR_CONTENT_TYPE_DRAWOBJECT
,
260 STR_CONTENT_TYPE_TEXTFIELD
,
261 STR_CONTENT_TYPE_FOOTNOTE
,
262 STR_CONTENT_TYPE_ENDNOTE
265 const TranslateId STR_CONTENT_TYPE_SINGLE_ARY
[] =
267 STR_CONTENT_TYPE_SINGLE_OUTLINE
,
268 STR_CONTENT_TYPE_SINGLE_TABLE
,
269 STR_CONTENT_TYPE_SINGLE_FRAME
,
270 STR_CONTENT_TYPE_SINGLE_GRAPHIC
,
271 STR_CONTENT_TYPE_SINGLE_OLE
,
272 STR_CONTENT_TYPE_SINGLE_BOOKMARK
,
273 STR_CONTENT_TYPE_SINGLE_REGION
,
274 STR_CONTENT_TYPE_SINGLE_URLFIELD
,
275 STR_CONTENT_TYPE_SINGLE_REFERENCE
,
276 STR_CONTENT_TYPE_SINGLE_INDEX
,
277 STR_CONTENT_TYPE_SINGLE_POSTIT
,
278 STR_CONTENT_TYPE_SINGLE_DRAWOBJECT
,
279 STR_CONTENT_TYPE_SINGLE_TEXTFIELD
,
280 STR_CONTENT_TYPE_SINGLE_FOOTNOTE
,
281 STR_CONTENT_TYPE_SINGLE_ENDNOTE
286 bool checkVisibilityChanged(
287 const SwContentArr
& rSwContentArrA
,
288 const SwContentArr
& rSwContentArrB
)
290 if(rSwContentArrA
.size() != rSwContentArrB
.size())
295 for(size_t a(0); a
< rSwContentArrA
.size(); a
++)
297 if(rSwContentArrA
[a
]->IsInvisible() != rSwContentArrB
[a
]->IsInvisible())
305 // Gets "YPos" for content, i.e. a number used to sort content members in Navigator's list
306 sal_Int32
getYPos(const SwNode
& rNode
)
308 SwNodeOffset nIndex
= rNode
.GetIndex();
309 if (rNode
.GetNodes().GetEndOfExtras().GetIndex() >= nIndex
)
311 // Not a node of BodyText
313 if (const auto pFlyFormat
= rNode
.GetFlyFormat())
315 // Get node index of anchor
316 if (SwNode
* pAnchorNode
= pFlyFormat
->GetAnchor().GetAnchorNode())
318 return getYPos(*pAnchorNode
);
322 return sal_Int32(nIndex
);
324 } // end of anonymous namespace
326 SwContentType::SwContentType(SwWrtShell
* pShell
, ContentTypeId nType
, sal_uInt8 nLevel
) :
327 SwTypeNumber(CTYPE_CTT
),
329 m_sContentTypeName(SwResId(STR_CONTENT_TYPE_ARY
[static_cast<int>(nType
)])),
330 m_sSingleContentTypeName(SwResId(STR_CONTENT_TYPE_SINGLE_ARY
[static_cast<int>(nType
)])),
332 m_nContentType(nType
),
333 m_nOutlineLevel(nLevel
),
338 switch(m_nContentType
)
340 case ContentTypeId::OUTLINE
:
341 m_sTypeToken
= "outline";
343 case ContentTypeId::TABLE
:
344 m_sTypeToken
= "table";
347 case ContentTypeId::FRAME
:
348 m_sTypeToken
= "frame";
351 case ContentTypeId::GRAPHIC
:
352 m_sTypeToken
= "graphic";
355 case ContentTypeId::OLE
:
356 m_sTypeToken
= "ole";
359 case ContentTypeId::TEXTFIELD
:
363 case ContentTypeId::FOOTNOTE
:
364 case ContentTypeId::ENDNOTE
:
368 case ContentTypeId::BOOKMARK
:
370 const bool bProtectedBM
= m_pWrtShell
->getIDocumentSettingAccess().get(
371 DocumentSettingId::PROTECT_BOOKMARKS
);
373 m_bDelete
= !bProtectedBM
;
376 case ContentTypeId::REGION
:
377 m_sTypeToken
= "region";
381 case ContentTypeId::INDEX
:
385 case ContentTypeId::REFERENCE
:
389 case ContentTypeId::URLFIELD
:
393 case ContentTypeId::POSTIT
:
396 case ContentTypeId::DRAWOBJECT
:
397 m_sTypeToken
= "drawingobject";
405 SwContentType::~SwContentType()
409 const SwContent
* SwContentType::GetMember(size_t nIndex
)
411 if(!m_bDataValid
|| !m_pMember
)
415 if(nIndex
< m_pMember
->size())
416 return (*m_pMember
)[nIndex
].get();
421 void SwContentType::Invalidate()
423 m_bDataValid
= false;
426 void SwContentType::FillMemberList(bool* pbContentChanged
)
428 std::unique_ptr
<SwContentArr
> pOldMember
;
429 size_t nOldMemberCount
= 0;
430 if(m_pMember
&& pbContentChanged
)
432 pOldMember
= std::move(m_pMember
);
433 nOldMemberCount
= pOldMember
->size();
434 m_pMember
.reset( new SwContentArr
);
435 *pbContentChanged
= false;
438 m_pMember
.reset( new SwContentArr
);
441 switch(m_nContentType
)
443 case ContentTypeId::OUTLINE
:
445 const SwNodeOffset nEndOfExtrasIndex
= m_pWrtShell
->GetNodes().GetEndOfExtras().GetIndex();
446 // provide for up to 99999 outline nodes in frames to be sorted in document layout order
447 double nOutlinesInFramesIndexAdjustment
= 0.00001;
448 const SwOutlineNodes
& rOutlineNodes(m_pWrtShell
->GetNodes().GetOutLineNds());
449 const size_t nOutlineCount
= rOutlineNodes
.size();
451 for (size_t i
= 0; i
< nOutlineCount
; ++i
)
453 SwTextNode
* pNode
= rOutlineNodes
[i
]->GetTextNode();
454 const sal_uInt8 nLevel
= pNode
->GetAttrOutlineLevel() - 1;
455 if (nLevel
>= m_nOutlineLevel
|| !pNode
->getLayoutFrame(m_pWrtShell
->GetLayout()))
457 double nYPos
= m_bAlphabeticSort
? 0 : static_cast<double>(getYPos(*pNode
));
458 if (nEndOfExtrasIndex
>= pNode
->GetIndex() && pNode
->GetFlyFormat())
460 nYPos
+= nOutlinesInFramesIndexAdjustment
;
461 nOutlinesInFramesIndexAdjustment
+= 0.00001;
463 OUString
aEntry(comphelper::string::stripStart(
464 m_pWrtShell
->getIDocumentOutlineNodesAccess()->getOutlineText(
465 i
, m_pWrtShell
->GetLayout(), true, false, false), ' '));
466 aEntry
= SwNavigationPI::CleanEntry(aEntry
);
467 auto pCnt(std::make_unique
<SwOutlineContent
>(this, aEntry
, i
, nLevel
,
468 m_pWrtShell
->IsOutlineMovable(i
), nYPos
));
469 m_pMember
->insert(std::move(pCnt
));
472 // need to check level and equal entry number after creation due to possible outline
473 // nodes in frames, headers, footers
476 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
477 if (pOldMember
->size() != m_pMember
->size())
479 *pbContentChanged
= true;
482 for (size_t i
= 0; i
< pOldMember
->size(); i
++)
484 if (static_cast<SwOutlineContent
*>((*pOldMember
)[i
].get())->GetOutlineLevel() !=
485 static_cast<SwOutlineContent
*>((*m_pMember
)[i
].get())->GetOutlineLevel())
487 *pbContentChanged
= true;
494 case ContentTypeId::TABLE
:
496 const size_t nCount
= m_pWrtShell
->GetTableFrameFormatCount(true);
497 const sw::TableFrameFormats
* pFrameFormats
= m_pWrtShell
->GetDoc()->GetTableFrameFormats();
498 SwAutoFormatGetDocNode
aGetHt(&m_pWrtShell
->GetNodes());
499 for(size_t n
= 0, i
= 0; i
< nCount
+ n
; ++i
)
501 const SwTableFormat
& rTableFormat
= *(*pFrameFormats
)[i
];
502 if (rTableFormat
.GetInfo(aGetHt
)) // skip deleted tables
507 tools::Long nYPos
= 0;
508 if (!m_bAlphabeticSort
)
510 if (SwTable
* pTable
= SwTable::FindTable(&rTableFormat
))
511 nYPos
= getYPos(*pTable
->GetTableNode());
513 auto pCnt
= std::make_unique
<SwContent
>(this, rTableFormat
.GetName(), nYPos
);
514 if(!rTableFormat
.IsVisible())
515 pCnt
->SetInvisible();
516 m_pMember
->insert(std::move(pCnt
));
521 // need to check visibility (and equal entry number) after
522 // creation due to a sorted list being used here (before,
523 // entries with same index were compared already at creation
524 // time what worked before a sorted list was used)
525 *pbContentChanged
= checkVisibilityChanged(
531 case ContentTypeId::OLE
:
532 case ContentTypeId::FRAME
:
533 case ContentTypeId::GRAPHIC
:
535 FlyCntType eType
= FLYCNTTYPE_FRM
;
536 if(m_nContentType
== ContentTypeId::OLE
)
537 eType
= FLYCNTTYPE_OLE
;
538 else if(m_nContentType
== ContentTypeId::GRAPHIC
)
539 eType
= FLYCNTTYPE_GRF
;
541 size_t nCount
= m_pWrtShell
->GetFlyCount(eType
, /*bIgnoreTextBoxes=*/true);
542 std::vector
<SwFrameFormat
const*> formats(m_pWrtShell
->GetFlyFrameFormats(eType
, /*bIgnoreTextBoxes=*/true));
543 SAL_WARN_IF(nCount
!= formats
.size(), "sw.ui", "Count differs");
544 nCount
= formats
.size();
545 for (size_t i
= 0; i
< nCount
; ++i
)
547 SwFrameFormat
const*const pFrameFormat
= formats
[i
];
548 const OUString sFrameName
= pFrameFormat
->GetName();
552 m_bAlphabeticSort
? 0 : pFrameFormat
->FindLayoutRect(false, &aNullPt
).Top();
553 if(ContentTypeId::GRAPHIC
== m_nContentType
)
556 m_pWrtShell
->GetGrfNms( &sLink
, nullptr, static_cast<const SwFlyFrameFormat
*>( pFrameFormat
));
557 pCnt
= new SwGraphicContent(this, sFrameName
, INetURLObject::decode(sLink
,
558 INetURLObject::DecodeMechanism::Unambiguous
), nYPos
);
562 pCnt
= new SwContent(this, sFrameName
, nYPos
);
564 if(!pFrameFormat
->IsVisible())
565 pCnt
->SetInvisible();
566 m_pMember
->insert(std::unique_ptr
<SwContent
>(pCnt
));
571 // need to check visibility (and equal entry number) after
572 // creation due to a sorted list being used here (before,
573 // entries with same index were compared already at creation
574 // time what worked before a sorted list was used)
575 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
576 *pbContentChanged
= checkVisibilityChanged(
582 case ContentTypeId::BOOKMARK
:
584 tools::Long nYPos
= 0;
585 IDocumentMarkAccess
* const pMarkAccess
= m_pWrtShell
->getIDocumentMarkAccess();
586 for(IDocumentMarkAccess::const_iterator_t ppBookmark
= pMarkAccess
->getBookmarksBegin();
587 ppBookmark
!= pMarkAccess
->getBookmarksEnd();
590 if(lcl_IsUiVisibleBookmark(*ppBookmark
))
592 const OUString
& rBkmName
= (*ppBookmark
)->GetName();
593 //nYPos from 0 -> text::Bookmarks will be sorted alphabetically
594 auto pCnt(std::make_unique
<SwContent
>(this, rBkmName
,
595 m_bAlphabeticSort
? 0 : nYPos
++));
596 m_pMember
->insert(std::move(pCnt
));
601 case ContentTypeId::TEXTFIELD
:
603 std::vector
<SwTextField
*> aArr
;
604 const SwFieldTypes
& rFieldTypes
=
605 *m_pWrtShell
->GetDoc()->getIDocumentFieldsAccess().GetFieldTypes();
606 const size_t nSize
= rFieldTypes
.size();
607 for (size_t i
= 0; i
< nSize
; ++i
)
609 const SwFieldType
* pFieldType
= rFieldTypes
[i
].get();
610 if (pFieldType
->Which() == SwFieldIds::Postit
)
612 std::vector
<SwFormatField
*> vFields
;
613 pFieldType
->GatherFields(vFields
);
614 for (SwFormatField
* pFormatField
: vFields
)
616 if (SwTextField
* pTextField
= pFormatField
->GetTextField())
618 // fields in header footer don't behave well, skip them
619 if (m_pWrtShell
->GetDoc()->IsInHeaderFooter(pTextField
->GetTextNode()))
621 aArr
.emplace_back(pTextField
);
625 if (!m_bAlphabeticSort
)
627 const SwNodeOffset nEndOfExtrasIndex
= m_pWrtShell
->GetNodes().GetEndOfExtras().GetIndex();
628 bool bHasEntryInFly
= false;
630 // use stable sort array to list fields in document model order
631 std::stable_sort(aArr
.begin(), aArr
.end(),
632 [](const SwTextField
* a
, const SwTextField
* b
){
633 SwPosition
aPos(a
->GetTextNode(), a
->GetStart());
634 SwPosition
bPos(b
->GetTextNode(), b
->GetStart());
635 return aPos
< bPos
;});
637 // determine if there is a text field in a fly frame
638 for (SwTextField
* pTextField
: aArr
)
642 if (nEndOfExtrasIndex
>= pTextField
->GetTextNode().GetIndex())
644 // Not a node of BodyText
646 if (pTextField
->GetTextNode().GetFlyFormat())
648 bHasEntryInFly
= true;
655 // When there are fields in fly frames do an additional sort using the fly frame
656 // anchor position to place field entries in order of document layout appearance.
659 std::stable_sort(aArr
.begin(), aArr
.end(),
660 [nEndOfExtrasIndex
](const SwTextField
* a
, const SwTextField
* b
){
661 SwTextNode
& aTextNode
= a
->GetTextNode();
662 SwTextNode
& bTextNode
= b
->GetTextNode();
663 SwPosition
aPos(aTextNode
, a
->GetStart());
664 SwPosition
bPos(bTextNode
, b
->GetStart());
665 // use anchor position for entries that are located in flys
666 if (nEndOfExtrasIndex
>= aTextNode
.GetIndex())
667 if (auto pFlyFormat
= aTextNode
.GetFlyFormat())
668 if (const SwPosition
* pPos
= pFlyFormat
->GetAnchor().GetContentAnchor())
670 if (nEndOfExtrasIndex
>= bTextNode
.GetIndex())
671 if (auto pFlyFormat
= bTextNode
.GetFlyFormat())
672 if (const SwPosition
* pPos
= pFlyFormat
->GetAnchor().GetContentAnchor())
674 return aPos
< bPos
;});
677 std::vector
<OUString
> aDocumentStatisticsSubTypesList
;
678 tools::Long nYPos
= 0;
679 for (SwTextField
* pTextField
: aArr
)
681 const SwField
* pField
= pTextField
->GetFormatField().GetField();
682 OUString sExpandField
= pField
->ExpandField(true, m_pWrtShell
->GetLayout());
683 if (!sExpandField
.isEmpty())
684 sExpandField
= u
" - " + sExpandField
;
686 if (pField
->GetTypeId() == SwFieldTypesEnum::DocumentStatistics
)
688 if (aDocumentStatisticsSubTypesList
.empty())
689 SwFieldMgr(m_pWrtShell
).GetSubTypes(SwFieldTypesEnum::DocumentStatistics
,
690 aDocumentStatisticsSubTypesList
);
692 if (pField
->GetSubType() < aDocumentStatisticsSubTypesList
.size())
693 sSubType
= u
" - " + aDocumentStatisticsSubTypesList
[pField
->GetSubType()];
694 sText
= pField
->GetDescription() + u
" - " + pField
->GetFieldName() + sSubType
+
697 else if (pField
->GetTypeId() == SwFieldTypesEnum::GetRef
)
699 assert(dynamic_cast<const SwGetRefField
*>(pField
));
700 const SwGetRefField
* pRefField(static_cast<const SwGetRefField
*>(pField
));
701 if (pRefField
->IsRefToHeadingCrossRefBookmark() ||
702 pRefField
->IsRefToNumItemCrossRefBookmark())
704 OUString sExpandedTextOfReferencedTextNode
=
705 pRefField
->GetExpandedTextOfReferencedTextNode(
706 *m_pWrtShell
->GetLayout());
707 if (sExpandedTextOfReferencedTextNode
.getLength() > 80)
709 sExpandedTextOfReferencedTextNode
= OUString::Concat(
710 sExpandedTextOfReferencedTextNode
.subView(0, 80)) + u
"...";
712 sText
= pField
->GetDescription() + u
" - "
713 + sExpandedTextOfReferencedTextNode
+ sExpandField
;
717 OUString sFieldSubTypeOrName
;
718 auto nSubType
= pField
->GetSubType();
719 if (nSubType
== REF_FOOTNOTE
)
720 sFieldSubTypeOrName
= SwResId(STR_FLDREF_FOOTNOTE
);
721 else if (nSubType
== REF_ENDNOTE
)
722 sFieldSubTypeOrName
= SwResId(STR_FLDREF_ENDNOTE
);
724 sFieldSubTypeOrName
= pField
->GetFieldName();
725 sText
= pField
->GetDescription() + u
" - " + sFieldSubTypeOrName
730 sText
= pField
->GetDescription() + u
" - " + pField
->GetFieldName()
732 auto pCnt(std::make_unique
<SwTextFieldContent
>(this, sText
,
733 &pTextField
->GetFormatField(),
734 m_bAlphabeticSort
? 0 : nYPos
++));
735 if (!pTextField
->GetTextNode().getLayoutFrame(m_pWrtShell
->GetLayout()))
736 pCnt
->SetInvisible();
737 m_pMember
->insert(std::move(pCnt
));
741 // We will separate footnotes and endnotes here.
742 case ContentTypeId::FOOTNOTE
:
743 case ContentTypeId::ENDNOTE
:
745 const SwFootnoteIdxs
& rFootnoteIdxs
= m_pWrtShell
->GetDoc()->GetFootnoteIdxs();
746 if (rFootnoteIdxs
.size() == 0)
748 // insert footnotes and endnotes
749 tools::Long nPos
= 0;
750 for (const SwTextFootnote
* pTextFootnote
: rFootnoteIdxs
)
752 if ((!pTextFootnote
->GetFootnote().IsEndNote()
753 && m_nContentType
== ContentTypeId::FOOTNOTE
)
754 || (pTextFootnote
->GetFootnote().IsEndNote()
755 && m_nContentType
== ContentTypeId::ENDNOTE
))
757 const SwFormatFootnote
& rFormatFootnote
= pTextFootnote
->GetFootnote();
758 const OUString
& sText
759 = rFormatFootnote
.GetViewNumStr(*m_pWrtShell
->GetDoc(),
760 m_pWrtShell
->GetLayout(), true)
761 + " " + lcl_GetFootnoteText(*pTextFootnote
);
762 auto pCnt(std::make_unique
<SwTextFootnoteContent
>(
763 this, sText
, pTextFootnote
, ++nPos
));
764 if (!pTextFootnote
->GetTextNode().getLayoutFrame(m_pWrtShell
->GetLayout()))
765 pCnt
->SetInvisible();
766 m_pMember
->insert(std::move(pCnt
));
771 case ContentTypeId::REGION
:
773 size_t nCount
= m_pWrtShell
->GetSectionFormatCount();
774 for (size_t i
= 0; i
< nCount
; ++i
)
776 const SwSectionFormat
* pFormat
= &m_pWrtShell
->GetSectionFormat(i
);
777 if (!pFormat
->IsInNodesArr())
779 const SwSection
* pSection
= pFormat
->GetSection();
780 if (SectionType eTmpType
= pSection
->GetType();
781 eTmpType
== SectionType::ToxContent
|| eTmpType
== SectionType::ToxHeader
)
783 const SwNodeIndex
* pNodeIndex
= pFormat
->GetContent().GetContentIdx();
786 const OUString
& sSectionName
= pSection
->GetSectionName();
788 sal_uInt8 nLevel
= 0;
789 SwSectionFormat
* pParentFormat
= pFormat
->GetParent();
793 pParentFormat
= pParentFormat
->GetParent();
796 std::unique_ptr
<SwContent
> pCnt(new SwRegionContent(this, sSectionName
,
797 nLevel
, m_bAlphabeticSort
? 0 : getYPos(pNodeIndex
->GetNode())));
798 if(!pFormat
->IsVisible())
799 pCnt
->SetInvisible();
800 m_pMember
->insert(std::move(pCnt
));
805 // need to check visibility (and equal entry number) after
806 // creation due to a sorted list being used here (before,
807 // entries with same index were compared already at creation
808 // time what worked before a sorted list was used)
809 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
810 *pbContentChanged
= checkVisibilityChanged(
817 case ContentTypeId::REFERENCE
:
819 std::vector
<OUString
> aRefMarks
;
820 m_pWrtShell
->GetRefMarks( &aRefMarks
);
822 tools::Long nYPos
= 0;
823 for (const auto& rRefMark
: aRefMarks
)
825 m_pMember
->insert(std::make_unique
<SwContent
>(this, rRefMark
,
826 m_bAlphabeticSort
? 0 : nYPos
++));
830 case ContentTypeId::URLFIELD
:
833 m_pWrtShell
->GetINetAttrs(aArr
, false);
835 if (m_bAlphabeticSort
)
839 auto pCnt(std::make_unique
<SwURLFieldContent
>(this, r
.sText
, INetURLObject::decode(
840 r
.rINetAttr
.GetINetFormat().GetValue(),
841 INetURLObject::DecodeMechanism::Unambiguous
),
843 m_pMember
->insert(std::move(pCnt
));
848 // use stable sort array to list hyperlinks in document order
849 const SwNodeOffset nEndOfExtrasIndex
= m_pWrtShell
->GetNodes().GetEndOfExtras().GetIndex();
850 bool bHasEntryInFly
= false;
851 std::vector
<SwGetINetAttr
*> aStableSortINetAttrsArray
;
853 for (SwGetINetAttr
& r
: aArr
)
855 aStableSortINetAttrsArray
.emplace_back(&r
);
858 if (nEndOfExtrasIndex
>= r
.rINetAttr
.GetTextNode().GetIndex())
860 // Not a node of BodyText
862 if (r
.rINetAttr
.GetTextNode().GetFlyFormat())
863 bHasEntryInFly
= true;
868 std::stable_sort(aStableSortINetAttrsArray
.begin(), aStableSortINetAttrsArray
.end(),
869 [](const SwGetINetAttr
* a
, const SwGetINetAttr
* b
){
870 SwPosition
aSwPos(a
->rINetAttr
.GetTextNode(),
871 a
->rINetAttr
.GetStart());
872 SwPosition
bSwPos(b
->rINetAttr
.GetTextNode(),
873 b
->rINetAttr
.GetStart());
874 return aSwPos
< bSwPos
;});
876 // When there are hyperlinks in text frames do an additional sort using the text frame
877 // anchor position to place entries in the order of document layout appearance.
880 std::stable_sort(aStableSortINetAttrsArray
.begin(), aStableSortINetAttrsArray
.end(),
881 [nEndOfExtrasIndex
](const SwGetINetAttr
* a
, const SwGetINetAttr
* b
){
882 const SwTextNode
& aTextNode
= a
->rINetAttr
.GetTextNode();
883 const SwTextNode
& bTextNode
= b
->rINetAttr
.GetTextNode();
884 SwPosition
aPos(aTextNode
, a
->rINetAttr
.GetStart());
885 SwPosition
bPos(bTextNode
, b
->rINetAttr
.GetStart());
886 // use anchor position for entries that are located in flys
887 if (nEndOfExtrasIndex
>= aTextNode
.GetIndex())
888 if (auto pFlyFormat
= aTextNode
.GetFlyFormat())
889 if (const SwPosition
* pPos
= pFlyFormat
->GetAnchor().GetContentAnchor())
891 if (nEndOfExtrasIndex
>= bTextNode
.GetIndex())
892 if (auto pFlyFormat
= bTextNode
.GetFlyFormat())
893 if (const SwPosition
* pPos
= pFlyFormat
->GetAnchor().GetContentAnchor())
895 return aPos
< bPos
;});
898 SwGetINetAttrs::size_type n
= 0;
899 for (auto p
: aStableSortINetAttrsArray
)
901 auto pCnt
= std::make_unique
<SwURLFieldContent
>(this, p
->sText
,
902 INetURLObject::decode(p
->rINetAttr
.GetINetFormat().GetValue(),
903 INetURLObject::DecodeMechanism::Unambiguous
),
905 m_pMember
->insert(std::move(pCnt
));
909 case ContentTypeId::INDEX
:
911 const sal_uInt16 nCount
= m_pWrtShell
->GetTOXCount();
913 for ( sal_uInt16 nTox
= 0; nTox
< nCount
; nTox
++ )
915 const SwTOXBase
* pBase
= m_pWrtShell
->GetTOX( nTox
);
916 OUString
sTOXNm( pBase
->GetTOXName() );
918 SwContent
* pCnt
= new SwTOXBaseContent(
919 this, sTOXNm
, m_bAlphabeticSort
? 0 : nTox
, *pBase
);
921 if(pBase
&& !pBase
->IsVisible())
922 pCnt
->SetInvisible();
924 m_pMember
->insert( std::unique_ptr
<SwContent
>(pCnt
) );
925 const size_t nPos
= m_pMember
->size() - 1;
928 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
929 if (!*pbContentChanged
&& nOldMemberCount
> nPos
&&
930 (*pOldMember
)[nPos
]->IsInvisible() != pCnt
->IsInvisible())
931 *pbContentChanged
= true;
936 case ContentTypeId::POSTIT
:
938 SwPostItMgr
* aMgr
= m_pWrtShell
->GetView().GetPostItMgr();
941 tools::Long nYPos
= 0;
942 for(SwPostItMgr::const_iterator i
= aMgr
->begin(); i
!= aMgr
->end(); ++i
)
944 if (const SwFormatField
* pFormatField
= dynamic_cast<const SwFormatField
*>((*i
)->GetBroadcaster())) // SwPostit
946 if (pFormatField
->GetTextField() && pFormatField
->IsFieldInDoc())
948 OUString sEntry
= pFormatField
->GetField()->GetPar2();
949 sEntry
= RemoveNewline(sEntry
);
950 std::unique_ptr
<SwPostItContent
> pCnt(new SwPostItContent(
955 if (!pFormatField
->GetTextField()->GetTextNode().getLayoutFrame(
956 m_pWrtShell
->GetLayout()))
957 pCnt
->SetInvisible();
960 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
961 if (!*pbContentChanged
&&
962 nOldMemberCount
> o3tl::make_unsigned(nYPos
) &&
963 (*pOldMember
)[nYPos
]->IsInvisible() != pCnt
->IsInvisible())
964 *pbContentChanged
= true;
966 m_pMember
->insert(std::move(pCnt
));
974 case ContentTypeId::DRAWOBJECT
:
976 IDocumentDrawModelAccess
& rIDDMA
= m_pWrtShell
->getIDocumentDrawModelAccess();
977 SwDrawModel
* pModel
= rIDDMA
.GetDrawModel();
980 SdrPage
* pPage
= pModel
->GetPage(0);
981 const size_t nCount
= pPage
->GetObjCount();
982 for( size_t i
=0; i
<nCount
; ++i
)
984 SdrObject
* pTemp
= pPage
->GetObj(i
);
985 // #i51726# - all drawing objects can be named now
986 if (!pTemp
->GetName().isEmpty())
988 tools::Long nYPos
= LONG_MIN
;
989 const bool bIsVisible
= rIDDMA
.IsVisibleLayerId(pTemp
->GetLayer());
991 nYPos
= m_bAlphabeticSort
? 0 : pTemp
->GetLogicRect().Top();
992 auto pCnt(std::make_unique
<SwContent
>(this, pTemp
->GetName(), nYPos
));
994 pCnt
->SetInvisible();
995 m_pMember
->insert(std::move(pCnt
));
1001 // need to check visibility (and equal entry number) after
1002 // creation due to a sorted list being used here (before,
1003 // entries with same index were compared already at creation
1004 // time what worked before a sorted list was used)
1005 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
1006 *pbContentChanged
= checkVisibilityChanged(
1015 m_nMemberCount
= m_pMember
->size();
1018 assert(pbContentChanged
&& "pbContentChanged is always set if pOldMember is");
1019 if (!*pbContentChanged
&& pOldMember
->size() != m_nMemberCount
)
1020 *pbContentChanged
= true;
1023 m_bDataValid
= true;
1028 enum STR_CONTEXT_IDX
1030 IDX_STR_OUTLINE_LEVEL
= 0,
1031 IDX_STR_DRAGMODE
= 1,
1032 IDX_STR_HYPERLINK
= 2,
1033 IDX_STR_LINK_REGION
= 3,
1034 IDX_STR_COPY_REGION
= 4,
1035 IDX_STR_DISPLAY
= 5,
1036 IDX_STR_ACTIVE_VIEW
= 6,
1039 IDX_STR_INACTIVE
= 9,
1040 IDX_STR_EDIT_ENTRY
= 10,
1041 IDX_STR_DELETE_ENTRY
= 11,
1042 IDX_STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY
= 12,
1043 IDX_STR_OUTLINE_TRACKING
= 13,
1044 IDX_STR_OUTLINE_TRACKING_DEFAULT
= 14,
1045 IDX_STR_OUTLINE_TRACKING_FOCUS
= 15,
1046 IDX_STR_OUTLINE_TRACKING_OFF
= 16
1051 const TranslateId STR_CONTEXT_ARY
[] =
1065 STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY
,
1066 STR_OUTLINE_TRACKING
,
1067 STR_OUTLINE_TRACKING_DEFAULT
,
1068 STR_OUTLINE_TRACKING_FOCUS
,
1069 STR_OUTLINE_TRACKING_OFF
1072 SwContentTree::SwContentTree(std::unique_ptr
<weld::TreeView
> xTreeView
, SwNavigationPI
* pDialog
)
1073 : m_xTreeView(std::move(xTreeView
))
1074 , m_aDropTargetHelper(*this)
1075 , m_pDialog(pDialog
)
1076 , m_sSpace(OUString(" "))
1077 , m_aUpdTimer("SwContentTree m_aUpdTimer")
1078 , m_aOverlayObjectDelayTimer("SwContentTree m_aOverlayObjectDelayTimer")
1079 , m_sInvisible(SwResId(STR_INVISIBLE
))
1080 , m_pHiddenShell(nullptr)
1081 , m_pActiveShell(nullptr)
1082 , m_pConfig(SW_MOD()->GetNavigationConfig())
1086 , m_nRootType(ContentTypeId::UNKNOWN
)
1087 , m_nLastSelType(ContentTypeId::UNKNOWN
)
1088 , m_nOutlineLevel(MAXLEVEL
)
1089 , m_eState(State::ACTIVE
)
1091 , m_bIsIdleClear(false)
1092 , m_bIsLastReadOnly(false)
1093 , m_bIsOutlineMoveable(true)
1094 , m_bViewHasChanged(false)
1096 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 30,
1097 m_xTreeView
->get_text_height() * 14);
1099 m_xTreeView
->set_help_id(HID_NAVIGATOR_TREELIST
);
1101 m_xTreeView
->connect_expanding(LINK(this, SwContentTree
, ExpandHdl
));
1102 m_xTreeView
->connect_collapsing(LINK(this, SwContentTree
, CollapseHdl
));
1103 m_xTreeView
->connect_row_activated(LINK(this, SwContentTree
, ContentDoubleClickHdl
));
1104 m_xTreeView
->connect_changed(LINK(this, SwContentTree
, SelectHdl
));
1105 m_xTreeView
->connect_focus_in(LINK(this, SwContentTree
, FocusInHdl
));
1106 m_xTreeView
->connect_key_press(LINK(this, SwContentTree
, KeyInputHdl
));
1107 m_xTreeView
->connect_popup_menu(LINK(this, SwContentTree
, CommandHdl
));
1108 m_xTreeView
->connect_query_tooltip(LINK(this, SwContentTree
, QueryTooltipHdl
));
1109 m_xTreeView
->connect_drag_begin(LINK(this, SwContentTree
, DragBeginHdl
));
1110 m_xTreeView
->connect_mouse_move(LINK(this, SwContentTree
, MouseMoveHdl
));
1111 m_xTreeView
->connect_mouse_press(LINK(this, SwContentTree
, MousePressHdl
));
1113 for (ContentTypeId i
: o3tl::enumrange
<ContentTypeId
>())
1115 if (i
!= ContentTypeId::OUTLINE
)
1116 mTrackContentType
[i
] = true;
1117 m_aActiveContentArr
[i
] = nullptr;
1118 m_aHiddenContentArr
[i
] = nullptr;
1120 for (int i
= 0; i
< CONTEXT_COUNT
; ++i
)
1122 m_aContextStrings
[i
] = SwResId(STR_CONTEXT_ARY
[i
]);
1124 m_nActiveBlock
= m_pConfig
->GetActiveBlock();
1126 // Restore outline headings expand state (same session persistence only)
1127 if (SwView
* pView
= GetActiveView(); pView
&& pView
->GetDocShell())
1129 OUString sDocTitle
= pView
->GetDocShell()->GetTitle();
1130 if (lcl_DocOutLineExpandStateMap
.find(sDocTitle
) != lcl_DocOutLineExpandStateMap
.end())
1131 mOutLineNodeMap
= lcl_DocOutLineExpandStateMap
[sDocTitle
];
1134 m_aUpdTimer
.SetInvokeHandler(LINK(this, SwContentTree
, TimerUpdate
));
1135 m_aUpdTimer
.SetTimeout(1000);
1136 m_aOverlayObjectDelayTimer
.SetInvokeHandler(LINK(this, SwContentTree
, OverlayObjectDelayTimerHdl
));
1137 m_aOverlayObjectDelayTimer
.SetTimeout(500);
1140 SwContentTree::~SwContentTree()
1142 if (SwView
* pView
= GetActiveView(); pView
&& pView
->GetDocShell())
1144 OUString sDocTitle
= pView
->GetDocShell()->GetTitle();
1145 lcl_DocOutLineExpandStateMap
[sDocTitle
] = mOutLineNodeMap
;
1147 clear(); // If applicable erase content types previously.
1149 SetActiveShell(nullptr);
1152 IMPL_LINK(SwContentTree
, MousePressHdl
, const MouseEvent
&, rMEvt
, bool)
1154 m_bSelectTo
= rMEvt
.IsShift() && (m_pConfig
->IsNavigateOnSelect() || rMEvt
.GetClicks() == 2);
1158 IMPL_LINK(SwContentTree
, MouseMoveHdl
, const MouseEvent
&, rMEvt
, bool)
1160 if (m_eState
== State::HIDDEN
)
1162 if (std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
1163 m_xTreeView
->get_dest_row_at_pos(rMEvt
.GetPosPixel(), xEntry
.get(), false, false) &&
1164 !rMEvt
.IsLeaveWindow())
1166 if (!m_xOverlayCompareEntry
)
1167 m_xOverlayCompareEntry
.reset(m_xTreeView
->make_iterator().release());
1168 else if (m_xTreeView
->iter_compare(*xEntry
, *m_xOverlayCompareEntry
) == 0)
1169 return false; // The entry under the mouse has not changed.
1170 m_xTreeView
->copy_iterator(*xEntry
, *m_xOverlayCompareEntry
);
1171 BringEntryToAttention(*xEntry
);
1175 if (m_xOverlayCompareEntry
)
1176 m_xOverlayCompareEntry
.reset();
1177 m_aOverlayObjectDelayTimer
.Stop();
1178 if (m_xOverlayObject
&& m_xOverlayObject
->getOverlayManager())
1180 m_xOverlayObject
->getOverlayManager()->remove(*m_xOverlayObject
);
1181 m_xOverlayObject
.reset();
1187 // Drag&Drop methods
1188 IMPL_LINK(SwContentTree
, DragBeginHdl
, bool&, rUnsetDragIcon
, bool)
1190 rUnsetDragIcon
= true;
1192 bool bDisallow
= true;
1194 // don't allow if tree root is selected
1195 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
1196 bool bEntry
= m_xTreeView
->get_selected(xEntry
.get());
1197 if (!bEntry
|| lcl_IsContentType(*xEntry
, *m_xTreeView
))
1199 return true; // disallow
1202 rtl::Reference
<TransferDataContainer
> xContainer
= new TransferDataContainer
;
1203 sal_Int8 nDragMode
= DND_ACTION_COPYMOVE
| DND_ACTION_LINK
;
1205 if (FillTransferData(*xContainer
, nDragMode
))
1208 if (m_bIsRoot
&& m_nRootType
== ContentTypeId::OUTLINE
)
1210 // Only move drag entry and continuous selected siblings:
1211 m_aDndOutlinesSelected
.clear();
1213 std::unique_ptr
<weld::TreeIter
> xScratch(m_xTreeView
->make_iterator());
1215 // Find first selected of continuous siblings
1218 m_xTreeView
->copy_iterator(*xEntry
, *xScratch
);
1219 if (!m_xTreeView
->iter_previous_sibling(*xScratch
))
1221 if (!m_xTreeView
->is_selected(*xScratch
))
1223 m_xTreeView
->copy_iterator(*xScratch
, *xEntry
);
1225 // Record continuous selected siblings
1228 m_aDndOutlinesSelected
.push_back(m_xTreeView
->make_iterator(xEntry
.get()));
1230 while (m_xTreeView
->iter_next_sibling(*xEntry
) && m_xTreeView
->is_selected(*xEntry
));
1235 m_xTreeView
->enable_drag_source(xContainer
, nDragMode
);
1239 SwContentTreeDropTarget::SwContentTreeDropTarget(SwContentTree
& rTreeView
)
1240 : DropTargetHelper(rTreeView
.get_widget().get_drop_target())
1241 , m_rTreeView(rTreeView
)
1245 sal_Int8
SwContentTreeDropTarget::AcceptDrop(const AcceptDropEvent
& rEvt
)
1247 sal_Int8 nAccept
= m_rTreeView
.AcceptDrop(rEvt
);
1249 if (nAccept
!= DND_ACTION_NONE
)
1251 // to enable the autoscroll when we're close to the edges
1252 weld::TreeView
& rWidget
= m_rTreeView
.get_widget();
1253 rWidget
.get_dest_row_at_pos(rEvt
.maPosPixel
, nullptr, true);
1259 bool SwContentTree::IsInDrag() const
1261 return m_xTreeView
->get_drag_source() == m_xTreeView
.get();
1264 // QueryDrop will be executed in the navigator
1265 sal_Int8
SwContentTree::AcceptDrop(const AcceptDropEvent
& rEvt
)
1267 sal_Int8 nRet
= DND_ACTION_NONE
;
1270 if( m_bIsOutlineMoveable
)
1271 nRet
= rEvt
.mnAction
;
1273 else if (!IsInDrag())
1274 nRet
= GetParentWindow()->AcceptDrop();
1278 // Drop will be executed in the navigator
1279 static void* lcl_GetOutlineKey(SwContentTree
& rTree
, SwOutlineContent
const * pContent
)
1281 void* key
= nullptr;
1284 SwWrtShell
* pShell
= rTree
.GetWrtShell();
1285 auto const nPos
= pContent
->GetOutlinePos();
1287 key
= static_cast<void*>(pShell
->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos
));
1292 sal_Int8
SwContentTreeDropTarget::ExecuteDrop(const ExecuteDropEvent
& rEvt
)
1294 return m_rTreeView
.ExecuteDrop(rEvt
);
1297 sal_Int8
SwContentTree::ExecuteDrop(const ExecuteDropEvent
& rEvt
)
1299 std::unique_ptr
<weld::TreeIter
> xDropEntry(m_xTreeView
->make_iterator());
1300 if (!m_xTreeView
->get_dest_row_at_pos(rEvt
.maPosPixel
, xDropEntry
.get(), true))
1303 if (m_nRootType
== ContentTypeId::OUTLINE
)
1305 if (xDropEntry
&& lcl_IsContent(*xDropEntry
, *m_xTreeView
))
1307 assert(dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xDropEntry
))));
1308 SwOutlineContent
* pOutlineContent
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(*xDropEntry
));
1309 assert(pOutlineContent
);
1311 void* key
= lcl_GetOutlineKey(*this, pOutlineContent
);
1313 if (!mOutLineNodeMap
[key
])
1315 while (m_xTreeView
->iter_has_child(*xDropEntry
))
1317 std::unique_ptr
<weld::TreeIter
> xChildEntry(m_xTreeView
->make_iterator(xDropEntry
.get()));
1318 bool bChildEntry
= m_xTreeView
->iter_children(*xChildEntry
);
1321 m_xTreeView
->copy_iterator(*xChildEntry
, *xDropEntry
);
1322 bChildEntry
= m_xTreeView
->iter_next_sibling(*xChildEntry
);
1328 SwOutlineNodes::size_type nTargetPos
= 0;
1331 // dropped in blank space -> move to bottom
1332 nTargetPos
= GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() - 1;
1334 else if (!lcl_IsContent(*xDropEntry
, *m_xTreeView
))
1336 // dropped on "heading" parent -> move to start
1337 nTargetPos
= SwOutlineNodes::npos
;
1341 assert(dynamic_cast<SwOutlineContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xDropEntry
))));
1342 nTargetPos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(*xDropEntry
))->GetOutlinePos();
1345 if( MAXLEVEL
> m_nOutlineLevel
&& // Not all layers are displayed.
1346 nTargetPos
!= SwOutlineNodes::npos
)
1348 std::unique_ptr
<weld::TreeIter
> xNext(m_xTreeView
->make_iterator(xDropEntry
.get()));
1349 bool bNext
= m_xTreeView
->iter_next(*xNext
);
1352 assert(dynamic_cast<SwOutlineContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xNext
))));
1353 nTargetPos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(*xNext
))->GetOutlinePos() - 1;
1356 nTargetPos
= GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() - 1;
1359 // remove the drop highlight before we change the contents of the tree so we don't
1360 // try and dereference a removed entry in post-processing drop
1361 m_xTreeView
->unset_drag_dest_row();
1362 MoveOutline(nTargetPos
);
1365 return IsInDrag() ? DND_ACTION_NONE
: GetParentWindow()->ExecuteDrop(rEvt
);
1370 bool IsAllExpanded(const weld::TreeView
& rContentTree
, const weld::TreeIter
& rEntry
)
1372 if (!rContentTree
.get_row_expanded(rEntry
))
1375 if (!rContentTree
.iter_has_child(rEntry
))
1378 std::unique_ptr
<weld::TreeIter
> xChild(rContentTree
.make_iterator(&rEntry
));
1379 (void)rContentTree
.iter_children(*xChild
);
1383 if (rContentTree
.iter_has_child(*xChild
) || rContentTree
.get_children_on_demand(*xChild
))
1385 if (!IsAllExpanded(rContentTree
, *xChild
))
1389 while (rContentTree
.iter_next_sibling(*xChild
));
1393 void ExpandOrCollapseAll(weld::TreeView
& rContentTree
, weld::TreeIter
& rEntry
)
1395 bool bExpand
= !IsAllExpanded(rContentTree
, rEntry
);
1396 bExpand
? rContentTree
.expand_row(rEntry
) : rContentTree
.collapse_row(rEntry
);
1397 int nRefDepth
= rContentTree
.get_iter_depth(rEntry
);
1398 while (rContentTree
.iter_next(rEntry
) && rContentTree
.get_iter_depth(rEntry
) > nRefDepth
)
1400 if (rContentTree
.iter_has_child(rEntry
))
1401 bExpand
? rContentTree
.expand_row(rEntry
) : rContentTree
.collapse_row(rEntry
);
1406 // Handler for Dragging and ContextMenu
1407 static bool lcl_InsertExpandCollapseAllItem(const weld::TreeView
& rContentTree
, const weld::TreeIter
& rEntry
, weld::Menu
& rPop
)
1409 if (rContentTree
.iter_has_child(rEntry
) || rContentTree
.get_children_on_demand(rEntry
))
1411 rPop
.set_label(OUString::number(800), IsAllExpanded(rContentTree
, rEntry
) ? SwResId(STR_COLLAPSEALL
) : SwResId(STR_EXPANDALL
));
1417 static void lcl_SetOutlineContentEntriesSensitivities(SwContentTree
* pThis
, const weld::TreeView
& rContentTree
, const weld::TreeIter
& rEntry
, weld::Menu
& rPop
)
1419 rPop
.set_sensitive(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY
), false);
1420 rPop
.set_sensitive(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY
), false);
1421 rPop
.set_sensitive(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY
), false);
1423 // todo: multi selection
1424 if (rContentTree
.count_selected_rows() > 1)
1427 bool bIsRoot
= lcl_IsContentType(rEntry
, rContentTree
);
1429 if (const SwWrtShell
* pSh
= pThis
->GetActiveWrtShell())
1431 if (pSh
->GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
1434 rPop
.set_sensitive(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY
), true);
1439 const SwNodes
& rNodes
= pThis
->GetWrtShell()->GetNodes();
1440 const SwOutlineNodes
& rOutlineNodes
= rNodes
.GetOutLineNds();
1441 size_t nOutlinePos
= weld::GetAbsPos(rContentTree
, rEntry
);
1446 if (nOutlinePos
>= rOutlineNodes
.size())
1449 int nFirstLevel
= pThis
->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos
);
1451 // determine if any concerned outline node has content
1452 bool bHasContent(false);
1453 size_t nPos
= nOutlinePos
;
1454 SwNode
* pSttNd
= rOutlineNodes
[nPos
];
1455 SwNode
* pEndNd
= &rNodes
.GetEndOfContent();
1456 if (rOutlineNodes
.size() > nPos
+ 1)
1457 pEndNd
= rOutlineNodes
[nPos
+ 1];
1460 SwNodeIndex
aIdx(*pSttNd
);
1461 if (rNodes
.GoNext(&aIdx
) != pEndNd
)
1465 if (!bHasContent
&& (rContentTree
.iter_has_child(rEntry
) || rContentTree
.get_children_on_demand(rEntry
)))
1467 while (++nPos
< rOutlineNodes
.size() &&
1468 (bIsRoot
|| pThis
->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos
) > nFirstLevel
))
1470 pSttNd
= rOutlineNodes
[nPos
];
1471 pEndNd
= &rNodes
.GetEndOfContent();
1472 if (rOutlineNodes
.size() > nPos
+ 1)
1473 pEndNd
= rOutlineNodes
[nPos
+ 1];
1475 // test for content in outline node
1476 aIdx
.Assign(*pSttNd
);
1477 if (rNodes
.GoNext(&aIdx
) != pEndNd
)
1486 return; // no content in any of the concerned outline nodes
1489 // determine for subs if all are folded or unfolded or if they are mixed
1490 if (rContentTree
.iter_has_child(rEntry
) || rContentTree
.get_children_on_demand(rEntry
))
1492 // skip no content nodes
1493 // we know there is content from results above so this is presumably safe
1494 size_t nPos
= nOutlinePos
;
1497 SwNode
* pSttNd
= rOutlineNodes
[nPos
];
1498 SwNode
* pEndNd
= rOutlineNodes
.back();
1499 if (!bIsRoot
&& rOutlineNodes
.size() > nPos
+ 1)
1500 pEndNd
= rOutlineNodes
[nPos
+ 1];
1502 SwNodeIndex
aIdx(*pSttNd
);
1503 if (rNodes
.GoNext(&aIdx
) != pEndNd
)
1508 bool bHasFolded(!pThis
->GetWrtShell()->IsOutlineContentVisible(nPos
));
1509 bool bHasUnfolded(!bHasFolded
);
1511 while ((++nPos
< pThis
->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount()) &&
1512 (bIsRoot
|| pThis
->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos
) > nFirstLevel
))
1515 SwNode
* pSttNd
= rOutlineNodes
[nPos
];
1516 SwNode
* pEndNd
= &rNodes
.GetEndOfContent();
1517 if (rOutlineNodes
.size() > nPos
+ 1)
1518 pEndNd
= rOutlineNodes
[nPos
+ 1];
1520 SwNodeIndex
aIdx(*pSttNd
);
1521 if (rNodes
.GoNext(&aIdx
) == pEndNd
)
1522 continue; // skip if no content
1524 if (!pThis
->GetWrtShell()->IsOutlineContentVisible(nPos
))
1527 bHasUnfolded
= true;
1529 if (bHasFolded
&& bHasUnfolded
)
1530 break; // mixed so no need to continue
1533 rPop
.set_sensitive(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY
), bHasUnfolded
);
1534 rPop
.set_sensitive(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY
), bHasFolded
);
1537 rPop
.set_sensitive(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY
), !bIsRoot
);
1540 IMPL_LINK(SwContentTree
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
1542 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1547 // select clicked entry or limit selection to root entry if needed
1548 if (std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
1549 rCEvt
.IsMouseEvent() && m_xTreeView
->get_dest_row_at_pos(
1550 rCEvt
.GetMousePosPixel(), xEntry
.get(), false))
1552 // if clicked entry is not currently selected then clear selections and select it
1553 if (!m_xTreeView
->is_selected(*xEntry
))
1554 m_xTreeView
->set_cursor(*xEntry
);
1555 // if root entry is selected then clear selections and select it
1556 else if (m_xTreeView
->is_selected(0))
1557 m_xTreeView
->set_cursor(0);
1560 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(m_xTreeView
.get(), "modules/swriter/ui/navigatorcontextmenu.ui"));
1561 std::unique_ptr
<weld::Menu
> xPop
= xBuilder
->weld_menu("navmenu");
1563 bool bOutline(false);
1564 std::unique_ptr
<weld::Menu
> xSubPop1
= xBuilder
->weld_menu("outlinelevel");
1565 std::unique_ptr
<weld::Menu
> xSubPop2
= xBuilder
->weld_menu("dragmodemenu");
1566 std::unique_ptr
<weld::Menu
> xSubPop3
= xBuilder
->weld_menu("displaymenu");
1567 std::unique_ptr
<weld::Menu
> xSubPopOutlineTracking
= xBuilder
->weld_menu("outlinetracking");
1569 std::unique_ptr
<weld::Menu
> xSubPopOutlineContent
= xBuilder
->weld_menu("outlinecontent");
1571 xSubPopOutlineContent
->append(OUString::number(TOGGLE_OUTLINE_CONTENT_VISIBILITY
),
1572 SwResId(STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE
));
1573 xSubPopOutlineContent
->append(OUString::number(HIDE_OUTLINE_CONTENT_VISIBILITY
),
1574 SwResId(STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL
));
1575 xSubPopOutlineContent
->append(OUString::number(SHOW_OUTLINE_CONTENT_VISIBILITY
),
1576 SwResId(STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL
));
1578 for(int i
= 1; i
<= 3; ++i
)
1579 xSubPopOutlineTracking
->append_radio(OUString::number(i
+ 10), m_aContextStrings
[IDX_STR_OUTLINE_TRACKING
+ i
]);
1580 xSubPopOutlineTracking
->set_active(OUString::number(10 + m_nOutlineTracking
), true);
1582 for (int i
= 1; i
<= MAXLEVEL
; ++i
)
1583 xSubPop1
->append_radio(OUString::number(i
+ 100), OUString::number(i
));
1584 xSubPop1
->set_active(OUString::number(100 + m_nOutlineLevel
), true);
1586 for (int i
=0; i
< 3; ++i
)
1587 xSubPop2
->append_radio(OUString::number(i
+ 201), m_aContextStrings
[IDX_STR_HYPERLINK
+ i
]);
1588 xSubPop2
->set_active(OUString::number(201 + static_cast<int>(GetParentWindow()->GetRegionDropMode())), true);
1590 // Insert the list of the open files
1592 sal_uInt16 nId
= 301;
1593 SwView
*pView
= SwModule::GetFirstView();
1596 OUString sInsert
= pView
->GetDocShell()->GetTitle() + " (" +
1597 m_aContextStrings
[pView
== GetActiveView() ? IDX_STR_ACTIVE
:
1598 IDX_STR_INACTIVE
] + ")";
1599 xSubPop3
->append_radio(OUString::number(nId
), sInsert
);
1600 if (State::CONSTANT
== m_eState
&& m_pActiveShell
== &pView
->GetWrtShell())
1601 xSubPop3
->set_active(OUString::number(nId
), true);
1602 pView
= SwModule::GetNextView(pView
);
1605 xSubPop3
->append_radio(OUString::number(nId
++), m_aContextStrings
[IDX_STR_ACTIVE_VIEW
]);
1606 if (m_pHiddenShell
) // can have only one hidden shell
1608 OUString sHiddenEntry
= m_pHiddenShell
->GetView().GetDocShell()->GetTitle() +
1610 m_aContextStrings
[IDX_STR_HIDDEN
] +
1612 xSubPop3
->append_radio(OUString::number(nId
), sHiddenEntry
);
1614 if (State::ACTIVE
== m_eState
)
1615 xSubPop3
->set_active(OUString::number(--nId
), true);
1616 else if (State::HIDDEN
== m_eState
)
1617 xSubPop3
->set_active(OUString::number(nId
), true);
1620 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
1621 if (!m_xTreeView
->get_selected(xEntry
.get()))
1624 bool bRemoveGotoEntry
= false;
1625 if (State::HIDDEN
== m_eState
|| !xEntry
|| !lcl_IsContent(*xEntry
, *m_xTreeView
) ||
1626 weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
))->IsInvisible())
1627 bRemoveGotoEntry
= true;
1629 bool bRemovePostItEntries
= true;
1630 bool bRemoveIndexEntries
= true;
1631 bool bRemoveCopyEntry
= true;
1632 bool bRemoveEditEntry
= true;
1633 bool bRemoveUnprotectEntry
= true;
1634 bool bRemoveDeleteChapterEntry
= true,
1635 bRemoveDeleteTableEntry
= true,
1636 bRemoveDeleteFrameEntry
= true,
1637 bRemoveDeleteImageEntry
= true,
1638 bRemoveDeleteOLEObjectEntry
= true,
1639 bRemoveDeleteBookmarkEntry
= true,
1640 bRemoveDeleteHyperlinkEntry
= true,
1641 bRemoveDeleteReferenceEntry
= true,
1642 bRemoveDeleteIndexEntry
= true,
1643 bRemoveDeleteCommentEntry
= true,
1644 bRemoveDeleteDrawingObjectEntry
= true,
1645 bRemoveDeleteFieldEntry
= true;
1646 bool bRemoveRenameEntry
= true;
1647 bool bRemoveSelectEntry
= true;
1648 bool bRemoveToggleExpandEntry
= true;
1649 bool bRemoveChapterEntries
= true;
1650 bool bRemoveSendOutlineEntry
= true;
1652 bool bRemoveTableTracking
= true;
1653 bool bRemoveSectionTracking
= true;
1654 bool bRemoveFrameTracking
= true;
1655 bool bRemoveImageTracking
= true;
1656 bool bRemoveOLEobjectTracking
= true;
1657 bool bRemoveBookmarkTracking
= true;
1658 bool bRemoveHyperlinkTracking
= true;
1659 bool bRemoveReferenceTracking
= true;
1660 bool bRemoveIndexTracking
= true;
1661 bool bRemoveCommentTracking
= true;
1662 bool bRemoveDrawingObjectTracking
= true;
1663 bool bRemoveFieldTracking
= true;
1664 bool bRemoveFootnoteTracking
= true;
1665 bool bRemoveEndnoteTracking
= true;
1667 bool bRemoveSortEntry
= true;
1671 const SwContentType
* pType
;
1672 if (lcl_IsContentType(*xEntry
, *m_xTreeView
))
1673 pType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(*xEntry
));
1675 pType
= weld::fromId
<SwContent
*>(
1676 m_xTreeView
->get_id(*xEntry
))->GetParent();
1677 const ContentTypeId nContentType
= pType
->GetType();
1679 if (nContentType
!= ContentTypeId::FOOTNOTE
&& nContentType
!= ContentTypeId::ENDNOTE
1680 && nContentType
!= ContentTypeId::POSTIT
)
1682 bRemoveSortEntry
= false;
1683 xPop
->set_active("sort", pType
->GetSortType());
1687 switch (nContentType
)
1689 case ContentTypeId::TABLE
:
1690 aIdent
= "tabletracking";
1691 bRemoveTableTracking
= false;
1693 case ContentTypeId::REGION
:
1694 aIdent
= "sectiontracking";
1695 bRemoveSectionTracking
= false;
1697 case ContentTypeId::FRAME
:
1698 aIdent
= "frametracking";
1699 bRemoveFrameTracking
= false;
1701 case ContentTypeId::GRAPHIC
:
1702 aIdent
= "imagetracking";
1703 bRemoveImageTracking
= false;
1705 case ContentTypeId::OLE
:
1706 aIdent
= "oleobjecttracking";
1707 bRemoveOLEobjectTracking
= false;
1709 case ContentTypeId::BOOKMARK
:
1710 aIdent
= "bookmarktracking";
1711 bRemoveBookmarkTracking
= false;
1713 case ContentTypeId::URLFIELD
:
1714 aIdent
= "hyperlinktracking";
1715 bRemoveHyperlinkTracking
= false;
1717 case ContentTypeId::REFERENCE
:
1718 aIdent
= "referencetracking";
1719 bRemoveReferenceTracking
= false;
1721 case ContentTypeId::INDEX
:
1722 aIdent
= "indextracking";
1723 bRemoveIndexTracking
= false;
1725 case ContentTypeId::POSTIT
:
1726 aIdent
= "commenttracking";
1727 bRemoveCommentTracking
= false;
1729 case ContentTypeId::DRAWOBJECT
:
1730 aIdent
= "drawingobjecttracking";
1731 bRemoveDrawingObjectTracking
= false;
1733 case ContentTypeId::TEXTFIELD
:
1734 aIdent
= "fieldtracking";
1735 bRemoveFieldTracking
= false;
1737 case ContentTypeId::FOOTNOTE
:
1738 aIdent
= "footnotetracking";
1739 bRemoveFootnoteTracking
= false;
1741 case ContentTypeId::ENDNOTE
:
1742 aIdent
= "endnotetracking";
1743 bRemoveEndnoteTracking
= false;
1747 if (!aIdent
.isEmpty())
1748 xPop
->set_active(aIdent
, mTrackContentType
[nContentType
]);
1750 // Edit only if the shown content is coming from the current view.
1751 if (State::HIDDEN
!= m_eState
&&
1752 (State::ACTIVE
== m_eState
|| (GetActiveView() && m_pActiveShell
== GetActiveView()->GetWrtShellPtr()))
1753 && lcl_IsContent(*xEntry
, *m_xTreeView
))
1755 const bool bReadonly
= m_pActiveShell
->GetView().GetDocShell()->IsReadOnly();
1756 const bool bVisible
= !weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
))->IsInvisible();
1757 const bool bProtected
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
))->IsProtect();
1758 const bool bProtectBM
= (ContentTypeId::BOOKMARK
== nContentType
)
1759 && m_pActiveShell
->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS
);
1760 const bool bEditable
= pType
->IsEditable() &&
1761 ((bVisible
&& !bProtected
) || ContentTypeId::REGION
== nContentType
);
1762 const bool bDeletable
= pType
->IsDeletable() &&
1763 ((bVisible
&& !bProtected
&& !bProtectBM
) || ContentTypeId::REGION
== nContentType
);
1764 const bool bRenamable
= bEditable
&& !bReadonly
&&
1765 (ContentTypeId::TABLE
== nContentType
||
1766 ContentTypeId::FRAME
== nContentType
||
1767 ContentTypeId::GRAPHIC
== nContentType
||
1768 ContentTypeId::OLE
== nContentType
||
1769 (ContentTypeId::BOOKMARK
== nContentType
&& !bProtectBM
) ||
1770 ContentTypeId::REGION
== nContentType
||
1771 ContentTypeId::INDEX
== nContentType
||
1772 ContentTypeId::DRAWOBJECT
== nContentType
);
1773 // Choose which Delete entry to show.
1776 switch (nContentType
)
1778 case ContentTypeId::OUTLINE
:
1779 bRemoveDeleteChapterEntry
= false;
1781 case ContentTypeId::TABLE
:
1782 bRemoveDeleteTableEntry
= false;
1784 case ContentTypeId::FRAME
:
1785 bRemoveDeleteFrameEntry
= false;
1787 case ContentTypeId::GRAPHIC
:
1788 bRemoveDeleteImageEntry
= false;
1790 case ContentTypeId::OLE
:
1791 bRemoveDeleteOLEObjectEntry
= false;
1793 case ContentTypeId::BOOKMARK
:
1794 bRemoveDeleteBookmarkEntry
= false;
1796 case ContentTypeId::URLFIELD
:
1797 bRemoveDeleteHyperlinkEntry
= false;
1799 case ContentTypeId::REFERENCE
:
1800 bRemoveDeleteReferenceEntry
= false;
1802 case ContentTypeId::INDEX
:
1803 bRemoveDeleteIndexEntry
= false;
1805 case ContentTypeId::POSTIT
:
1806 bRemoveDeleteCommentEntry
= false;
1808 case ContentTypeId::DRAWOBJECT
:
1809 bRemoveDeleteDrawingObjectEntry
= false;
1811 case ContentTypeId::TEXTFIELD
:
1812 bRemoveDeleteFieldEntry
= false;
1817 if (ContentTypeId::FOOTNOTE
== nContentType
|| ContentTypeId::ENDNOTE
== nContentType
)
1819 void* pUserData
= weld::fromId
<void*>(m_xTreeView
->get_id(*xEntry
));
1820 const SwTextFootnote
* pFootnote
=
1821 static_cast<const SwTextFootnoteContent
*>(pUserData
)->GetTextFootnote();
1823 bRemoveGotoEntry
= true;
1825 else if(ContentTypeId::OUTLINE
== nContentType
)
1828 lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView
, *xEntry
, *xSubPopOutlineContent
);
1829 bRemoveToggleExpandEntry
= lcl_InsertExpandCollapseAllItem(*m_xTreeView
, *xEntry
, *xPop
);
1832 bRemoveSelectEntry
= false;
1833 bRemoveChapterEntries
= false;
1835 bRemoveCopyEntry
= false;
1837 else if (!bReadonly
&& bEditable
)
1839 if(ContentTypeId::INDEX
== nContentType
)
1841 bRemoveIndexEntries
= false;
1843 const SwTOXBase
* pBase
= weld::fromId
<SwTOXBaseContent
*>(m_xTreeView
->get_id(*xEntry
))->GetTOXBase();
1844 if (!pBase
->IsTOXBaseInReadonly())
1845 bRemoveEditEntry
= false;
1847 xPop
->set_active(OUString::number(405), SwEditShell::IsTOXBaseReadonly(*pBase
));
1849 else if(ContentTypeId::TABLE
== nContentType
)
1851 bRemoveSelectEntry
= false;
1852 bRemoveEditEntry
= false;
1853 bRemoveUnprotectEntry
= false;
1855 OUString sTableName
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
))->GetName();
1856 bool bProt
= m_pActiveShell
->HasTableAnyProtection( &sTableName
, &bFull
);
1857 xPop
->set_sensitive(OUString::number(403), !bFull
);
1858 xPop
->set_sensitive(OUString::number(404), bProt
);
1860 else if(ContentTypeId::REGION
== nContentType
)
1862 bRemoveSelectEntry
= false;
1863 bRemoveEditEntry
= false;
1866 bRemoveEditEntry
= false;
1869 bRemoveRenameEntry
= false;
1874 if (lcl_IsContentType(*xEntry
, *m_xTreeView
))
1875 pType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(*xEntry
));
1877 pType
= weld::fromId
<SwContent
*>(
1878 m_xTreeView
->get_id(*xEntry
))->GetParent();
1881 if (ContentTypeId::OUTLINE
== nContentType
)
1884 if (State::HIDDEN
!= m_eState
)
1886 lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView
, *xEntry
,
1887 *xSubPopOutlineContent
);
1888 bRemoveSendOutlineEntry
= false;
1890 bRemoveToggleExpandEntry
= lcl_InsertExpandCollapseAllItem(*m_xTreeView
, *xEntry
,
1893 else if (State::HIDDEN
!= m_eState
&&
1894 nContentType
== ContentTypeId::POSTIT
&&
1895 !m_pActiveShell
->GetView().GetDocShell()->IsReadOnly() &&
1896 pType
->GetMemberCount() > 0)
1897 bRemovePostItEntries
= false;
1902 if (bRemoveToggleExpandEntry
)
1903 xPop
->remove(OUString::number(800));
1905 if (bRemoveGotoEntry
)
1906 xPop
->remove(OUString::number(900));
1908 if (bRemoveSelectEntry
)
1909 xPop
->remove(OUString::number(805));
1911 if (bRemoveChapterEntries
)
1913 xPop
->remove(OUString::number(801));
1914 xPop
->remove(OUString::number(802));
1915 xPop
->remove(OUString::number(803));
1916 xPop
->remove(OUString::number(804));
1919 if (bRemoveSendOutlineEntry
)
1920 xPop
->remove(OUString::number(700));
1922 if (bRemovePostItEntries
)
1924 xPop
->remove(OUString::number(600));
1925 xPop
->remove(OUString::number(601));
1926 xPop
->remove(OUString::number(602));
1929 if (bRemoveDeleteChapterEntry
)
1930 xPop
->remove("deletechapter");
1931 if (bRemoveDeleteTableEntry
)
1932 xPop
->remove("deletetable");
1933 if (bRemoveDeleteFrameEntry
)
1934 xPop
->remove("deleteframe");
1935 if (bRemoveDeleteImageEntry
)
1936 xPop
->remove("deleteimage");
1937 if (bRemoveDeleteOLEObjectEntry
)
1938 xPop
->remove("deleteoleobject");
1939 if (bRemoveDeleteBookmarkEntry
)
1940 xPop
->remove("deletebookmark");
1941 if (bRemoveDeleteHyperlinkEntry
)
1942 xPop
->remove("deletehyperlink");
1943 if (bRemoveDeleteReferenceEntry
)
1944 xPop
->remove("deletereference");
1945 if (bRemoveDeleteIndexEntry
)
1946 xPop
->remove("deleteindex");
1947 if (bRemoveDeleteCommentEntry
)
1948 xPop
->remove("deletecomment");
1949 if (bRemoveDeleteDrawingObjectEntry
)
1950 xPop
->remove("deletedrawingobject");
1951 if (bRemoveDeleteFieldEntry
)
1952 xPop
->remove("deletefield");
1954 bool bRemoveDeleteEntry
=
1955 bRemoveDeleteChapterEntry
&&
1956 bRemoveDeleteTableEntry
&&
1957 bRemoveDeleteFrameEntry
&&
1958 bRemoveDeleteImageEntry
&&
1959 bRemoveDeleteOLEObjectEntry
&&
1960 bRemoveDeleteBookmarkEntry
&&
1961 bRemoveDeleteHyperlinkEntry
&&
1962 bRemoveDeleteReferenceEntry
&&
1963 bRemoveDeleteIndexEntry
&&
1964 bRemoveDeleteCommentEntry
&&
1965 bRemoveDeleteDrawingObjectEntry
&&
1966 bRemoveDeleteFieldEntry
;
1968 if (bRemoveRenameEntry
)
1969 xPop
->remove(OUString::number(502));
1971 if (bRemoveIndexEntries
)
1973 xPop
->remove(OUString::number(401));
1974 xPop
->remove(OUString::number(402));
1975 xPop
->remove(OUString::number(405));
1978 if (bRemoveUnprotectEntry
)
1979 xPop
->remove(OUString::number(404));
1981 if (bRemoveEditEntry
)
1982 xPop
->remove(OUString::number(403));
1984 if (bRemoveToggleExpandEntry
&&
1985 bRemoveSendOutlineEntry
)
1986 xPop
->remove("separator1");
1988 if (bRemoveCopyEntry
)
1989 xPop
->remove("copy");
1991 if (bRemoveGotoEntry
&&
1993 bRemoveSelectEntry
&&
1994 bRemoveDeleteEntry
&&
1995 bRemoveChapterEntries
&&
1996 bRemovePostItEntries
&&
1997 bRemoveRenameEntry
&&
1998 bRemoveIndexEntries
&&
1999 bRemoveUnprotectEntry
&&
2001 xPop
->remove("separator2");
2006 xPop
->remove(OUString::number(1)); // outline level menu
2008 if (!bOutline
|| State::HIDDEN
== m_eState
)
2010 xSubPopOutlineTracking
.reset();
2011 xPop
->remove(OUString::number(4)); // outline tracking menu
2013 if (!bOutline
|| State::HIDDEN
== m_eState
||
2014 !m_pActiveShell
->GetViewOptions()->IsShowOutlineContentVisibilityButton() ||
2015 m_pActiveShell
->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() == 0)
2017 xSubPopOutlineContent
.reset();
2018 xPop
->remove(OUString::number(5)); // outline folding menu
2019 xPop
->remove("separator3");
2022 if (bRemoveTableTracking
)
2023 xPop
->remove("tabletracking");
2024 if (bRemoveSectionTracking
)
2025 xPop
->remove("sectiontracking");
2026 if (bRemoveFrameTracking
)
2027 xPop
->remove("frametracking");
2028 if (bRemoveImageTracking
)
2029 xPop
->remove("imagetracking");
2030 if (bRemoveOLEobjectTracking
)
2031 xPop
->remove("oleobjecttracking");
2032 if (bRemoveBookmarkTracking
)
2033 xPop
->remove("bookmarktracking");
2034 if (bRemoveHyperlinkTracking
)
2035 xPop
->remove("hyperlinktracking");
2036 if (bRemoveReferenceTracking
)
2037 xPop
->remove("referencetracking");
2038 if (bRemoveIndexTracking
)
2039 xPop
->remove("indextracking");
2040 if (bRemoveCommentTracking
)
2041 xPop
->remove("commenttracking");
2042 if (bRemoveDrawingObjectTracking
)
2043 xPop
->remove("drawingobjecttracking");
2044 if (bRemoveFieldTracking
)
2045 xPop
->remove("fieldtracking");
2046 if (bRemoveFootnoteTracking
)
2047 xPop
->remove("footnotetracking");
2048 if (bRemoveEndnoteTracking
)
2049 xPop
->remove("endnotetracking");
2050 if (bRemoveSortEntry
)
2051 xPop
->remove("sort");
2053 bool bSetSensitiveCollapseAllCategories
= false;
2054 if (!m_bIsRoot
&& xEntry
)
2056 bool bEntry
= m_xTreeView
->get_iter_first(*xEntry
);
2059 if (m_xTreeView
->get_row_expanded(*xEntry
))
2061 bSetSensitiveCollapseAllCategories
= true;
2064 bEntry
= m_xTreeView
->iter_next_sibling(*xEntry
);
2067 xPop
->set_sensitive("collapseallcategories", bSetSensitiveCollapseAllCategories
);
2069 OUString sCommand
= xPop
->popup_at_rect(m_xTreeView
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1)));
2070 if (!sCommand
.isEmpty())
2071 ExecuteContextMenuAction(sCommand
);
2076 void SwContentTree::InsertContent(const weld::TreeIter
& rParent
)
2078 assert(dynamic_cast<SwContentType
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(rParent
))));
2079 SwContentType
* pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(rParent
));
2080 bool bGraphic
= pCntType
->GetType() == ContentTypeId::GRAPHIC
;
2081 bool bRegion
= pCntType
->GetType() == ContentTypeId::REGION
;
2082 std::unique_ptr
<weld::TreeIter
> xChild
= m_xTreeView
->make_iterator();
2083 const size_t nCount
= pCntType
->GetMemberCount();
2084 for(size_t i
= 0; i
< nCount
; ++i
)
2086 const SwContent
* pCnt
= pCntType
->GetMember(i
);
2089 OUString sEntry
= pCnt
->GetName();
2090 if (sEntry
.isEmpty())
2092 OUString
sId(weld::toId(pCnt
));
2093 insert(&rParent
, sEntry
, sId
, false, xChild
.get());
2094 m_xTreeView
->set_sensitive(*xChild
, !pCnt
->IsInvisible());
2095 if (bGraphic
&& !static_cast<const SwGraphicContent
*>(pCnt
)->GetLink().isEmpty())
2096 m_xTreeView
->set_image(*xChild
, RID_BMP_NAVI_GRAPHIC_LINK
);
2098 m_xTreeView
->set_extra_row_indent(*xChild
,
2099 static_cast<const SwRegionContent
*>(pCnt
)->GetRegionLevel());
2104 void SwContentTree::insert(const weld::TreeIter
* pParent
, const OUString
& rStr
, const OUString
& rId
,
2105 bool bChildrenOnDemand
, weld::TreeIter
* pRet
)
2107 m_xTreeView
->insert(pParent
, -1, &rStr
, &rId
, nullptr, nullptr, bChildrenOnDemand
, pRet
);
2111 void SwContentTree::remove(const weld::TreeIter
& rIter
)
2113 if (m_xTreeView
->iter_has_child(rIter
))
2115 std::unique_ptr
<weld::TreeIter
> xChild
= m_xTreeView
->make_iterator(&rIter
);
2116 (void)m_xTreeView
->iter_children(*xChild
);
2119 m_xTreeView
->remove(rIter
);
2123 // Content will be integrated into the Box only on demand.
2124 bool SwContentTree::RequestingChildren(const weld::TreeIter
& rParent
)
2126 // Does the parent already have children or is it not a 'children on demand' node?
2127 if (m_xTreeView
->iter_has_child(rParent
) || !m_xTreeView
->get_children_on_demand(rParent
))
2130 // Is this a content type?
2131 if (lcl_IsContentType(rParent
, *m_xTreeView
))
2133 std::unique_ptr
<weld::TreeIter
> xChild
= m_xTreeView
->make_iterator();
2135 assert(dynamic_cast<SwContentType
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(rParent
))));
2136 SwContentType
* pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(rParent
));
2138 const size_t nCount
= pCntType
->GetMemberCount();
2139 // Add for outline plus/minus
2140 if (pCntType
->GetType() == ContentTypeId::OUTLINE
)
2142 std::vector
<std::unique_ptr
<weld::TreeIter
>> aParentCandidates
;
2143 for(size_t i
= 0; i
< nCount
; ++i
)
2145 const SwContent
* pCnt
= pCntType
->GetMember(i
);
2148 const auto nLevel
= static_cast<const SwOutlineContent
*>(pCnt
)->GetOutlineLevel();
2149 OUString sEntry
= pCnt
->GetName();
2150 if(sEntry
.isEmpty())
2152 OUString
sId(weld::toId(pCnt
));
2154 auto lambda
= [nLevel
, this](const std::unique_ptr
<weld::TreeIter
>& entry
)
2156 return lcl_IsLowerOutlineContent(*entry
, *m_xTreeView
, nLevel
);
2159 // if there is a preceding outline node candidate with a lower outline level use
2160 // that as a parent, otherwise use the root node
2161 auto aFind
= std::find_if(aParentCandidates
.rbegin(), aParentCandidates
.rend(), lambda
);
2162 if (aFind
!= aParentCandidates
.rend())
2163 insert(aFind
->get(), sEntry
, sId
, false, xChild
.get());
2165 insert(&rParent
, sEntry
, sId
, false, xChild
.get());
2166 m_xTreeView
->set_sensitive(*xChild
, !pCnt
->IsInvisible());
2167 m_xTreeView
->set_extra_row_indent(*xChild
, nLevel
+ 1 - m_xTreeView
->get_iter_depth(*xChild
));
2169 // remove any parent candidates equal to or higher than this node
2170 aParentCandidates
.erase(std::remove_if(aParentCandidates
.begin(), aParentCandidates
.end(),
2171 std::not_fn(lambda
)), aParentCandidates
.end());
2173 // add this node as a parent candidate for any following nodes at a higher outline level
2174 aParentCandidates
.emplace_back(m_xTreeView
->make_iterator(xChild
.get()));
2179 InsertContent(rParent
);
2187 SdrObject
* SwContentTree::GetDrawingObjectsByContent(const SwContent
*pCnt
)
2189 SdrObject
*pRetObj
= nullptr;
2190 switch(pCnt
->GetParent()->GetType())
2192 case ContentTypeId::DRAWOBJECT
:
2194 SdrView
* pDrawView
= m_pActiveShell
->GetDrawView();
2197 SwDrawModel
* pDrawModel
= m_pActiveShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
2198 SdrPage
* pPage
= pDrawModel
->GetPage(0);
2199 const size_t nCount
= pPage
->GetObjCount();
2201 for( size_t i
=0; i
<nCount
; ++i
)
2203 SdrObject
* pTemp
= pPage
->GetObj(i
);
2204 if( pTemp
->GetName() == pCnt
->GetName())
2219 void SwContentTree::Expand(const weld::TreeIter
& rParent
, std::vector
<std::unique_ptr
<weld::TreeIter
>>* pNodesToExpand
)
2221 if (!(m_xTreeView
->iter_has_child(rParent
) || m_xTreeView
->get_children_on_demand(rParent
)))
2225 || (lcl_IsContentType(rParent
, *m_xTreeView
) &&
2226 weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(rParent
))->GetType() == ContentTypeId::OUTLINE
)
2227 || (m_nRootType
== ContentTypeId::OUTLINE
))
2229 if (lcl_IsContentType(rParent
, *m_xTreeView
))
2231 SwContentType
* pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(rParent
));
2232 const sal_Int32 nOr
= 1 << static_cast<int>(pCntType
->GetType()); //linear -> Bitposition
2233 if (State::HIDDEN
!= m_eState
)
2235 m_nActiveBlock
|= nOr
;
2236 m_pConfig
->SetActiveBlock(m_nActiveBlock
);
2239 m_nHiddenBlock
|= nOr
;
2240 if (pCntType
->GetType() == ContentTypeId::OUTLINE
)
2242 std::map
< void*, bool > aCurrOutLineNodeMap
;
2244 SwWrtShell
* pShell
= GetWrtShell();
2245 bool bParentHasChild
= RequestingChildren(rParent
);
2247 pNodesToExpand
->emplace_back(m_xTreeView
->make_iterator(&rParent
));
2248 if (bParentHasChild
)
2250 std::unique_ptr
<weld::TreeIter
> xChild(m_xTreeView
->make_iterator(&rParent
));
2251 bool bChild
= m_xTreeView
->iter_next(*xChild
);
2252 while (bChild
&& lcl_IsContent(*xChild
, *m_xTreeView
))
2254 if (m_xTreeView
->iter_has_child(*xChild
))
2256 assert(dynamic_cast<SwOutlineContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xChild
))));
2257 auto const nPos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(*xChild
))->GetOutlinePos();
2258 void* key
= static_cast<void*>(pShell
->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos
));
2259 aCurrOutLineNodeMap
.emplace( key
, false );
2260 std::map
<void*, bool>::iterator iter
= mOutLineNodeMap
.find( key
);
2261 if( iter
!= mOutLineNodeMap
.end() && mOutLineNodeMap
[key
])
2263 aCurrOutLineNodeMap
[key
] = true;
2264 RequestingChildren(*xChild
);
2266 pNodesToExpand
->emplace_back(m_xTreeView
->make_iterator(xChild
.get()));
2267 m_xTreeView
->set_children_on_demand(*xChild
, false);
2270 bChild
= m_xTreeView
->iter_next(*xChild
);
2273 mOutLineNodeMap
= aCurrOutLineNodeMap
;
2279 if (lcl_IsContent(rParent
, *m_xTreeView
))
2281 SwWrtShell
* pShell
= GetWrtShell();
2282 // paranoid assert now that outline type is checked
2283 assert(dynamic_cast<SwOutlineContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(rParent
))));
2284 auto const nPos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(rParent
))->GetOutlinePos();
2285 void* key
= static_cast<void*>(pShell
->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos
));
2286 mOutLineNodeMap
[key
] = true;
2291 RequestingChildren(rParent
);
2293 pNodesToExpand
->emplace_back(m_xTreeView
->make_iterator(&rParent
));
2296 IMPL_LINK(SwContentTree
, ExpandHdl
, const weld::TreeIter
&, rParent
, bool)
2298 Expand(rParent
, nullptr);
2302 IMPL_LINK(SwContentTree
, CollapseHdl
, const weld::TreeIter
&, rParent
, bool)
2304 if (!m_xTreeView
->iter_has_child(rParent
) || m_xTreeView
->get_children_on_demand(rParent
))
2307 if (lcl_IsContentType(rParent
, *m_xTreeView
))
2311 // collapse to children of root node
2312 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator(&rParent
));
2313 if (m_xTreeView
->iter_children(*xEntry
))
2317 m_xTreeView
->collapse_row(*xEntry
);
2319 while (m_xTreeView
->iter_next(*xEntry
));
2321 return false; // return false to notify caller not to do collapse
2323 SwContentType
* pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(rParent
));
2324 const sal_Int32 nAnd
= ~(1 << static_cast<int>(pCntType
->GetType()));
2325 if (State::HIDDEN
!= m_eState
)
2327 m_nActiveBlock
&= nAnd
;
2328 m_pConfig
->SetActiveBlock(m_nActiveBlock
);
2331 m_nHiddenBlock
&= nAnd
;
2333 else if (lcl_IsContent(rParent
, *m_xTreeView
))
2335 SwWrtShell
* pShell
= GetWrtShell();
2336 assert(dynamic_cast<SwOutlineContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(rParent
))));
2337 auto const nPos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(rParent
))->GetOutlinePos();
2338 void* key
= static_cast<void*>(pShell
->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos
));
2339 mOutLineNodeMap
[key
] = false;
2345 // Also on double click will be initially opened only.
2346 IMPL_LINK_NOARG(SwContentTree
, ContentDoubleClickHdl
, weld::TreeView
&, bool)
2348 if (m_nRowActivateEventId
)
2349 Application::RemoveUserEvent(m_nRowActivateEventId
);
2350 // post the event to process row activate after mouse press event to be able to set key
2351 // modifier for selection feature (tdf#154211)
2352 m_nRowActivateEventId
2353 = Application::PostUserEvent(LINK(this, SwContentTree
, AsyncContentDoubleClickHdl
));
2355 bool bConsumed
= false;
2357 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
2358 if (m_xTreeView
->get_cursor(xEntry
.get()) && lcl_IsContent(*xEntry
, *m_xTreeView
) &&
2359 (State::HIDDEN
!= m_eState
))
2361 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
));
2362 assert(pCnt
&& "no UserData");
2363 if (pCnt
&& !pCnt
->IsInvisible())
2365 // fdo#36308 don't expand outlines on double-click
2366 bConsumed
= pCnt
->GetParent()->GetType() == ContentTypeId::OUTLINE
;
2370 return bConsumed
; // false/true == allow/disallow more to be done, i.e. expand/collapse children
2373 IMPL_LINK_NOARG(SwContentTree
, AsyncContentDoubleClickHdl
, void*, void)
2375 m_nRowActivateEventId
= nullptr;
2377 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
2378 bool bEntry
= m_xTreeView
->get_cursor(xEntry
.get());
2379 // Is it a content type?
2380 OSL_ENSURE(bEntry
, "no current entry!");
2383 if (lcl_IsContentType(*xEntry
, *m_xTreeView
) && !m_xTreeView
->iter_has_child(*xEntry
))
2385 RequestingChildren(*xEntry
);
2386 m_xTreeView
->set_children_on_demand(*xEntry
, false);
2388 else if (!lcl_IsContentType(*xEntry
, *m_xTreeView
) && (State::HIDDEN
!= m_eState
))
2390 assert(dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
))));
2391 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
));
2392 assert(pCnt
&& "no UserData");
2393 if (pCnt
&& !pCnt
->IsInvisible())
2395 if (State::CONSTANT
== m_eState
)
2397 m_pActiveShell
->GetView().GetViewFrame().GetWindow().ToTop();
2399 //Jump to content type:
2408 OUString
GetImageIdForContentTypeId(ContentTypeId eType
)
2414 case ContentTypeId::OUTLINE
:
2415 sResId
= RID_BMP_NAVI_OUTLINE
;
2417 case ContentTypeId::TABLE
:
2418 sResId
= RID_BMP_NAVI_TABLE
;
2420 case ContentTypeId::FRAME
:
2421 sResId
= RID_BMP_NAVI_FRAME
;
2423 case ContentTypeId::GRAPHIC
:
2424 sResId
= RID_BMP_NAVI_GRAPHIC
;
2426 case ContentTypeId::OLE
:
2427 sResId
= RID_BMP_NAVI_OLE
;
2429 case ContentTypeId::BOOKMARK
:
2430 sResId
= RID_BMP_NAVI_BOOKMARK
;
2432 case ContentTypeId::REGION
:
2433 sResId
= RID_BMP_NAVI_REGION
;
2435 case ContentTypeId::URLFIELD
:
2436 sResId
= RID_BMP_NAVI_URLFIELD
;
2438 case ContentTypeId::REFERENCE
:
2439 sResId
= RID_BMP_NAVI_REFERENCE
;
2441 case ContentTypeId::INDEX
:
2442 sResId
= RID_BMP_NAVI_INDEX
;
2444 case ContentTypeId::POSTIT
:
2445 sResId
= RID_BMP_NAVI_POSTIT
;
2447 case ContentTypeId::DRAWOBJECT
:
2448 sResId
= RID_BMP_NAVI_DRAWOBJECT
;
2450 case ContentTypeId::TEXTFIELD
:
2451 sResId
= RID_BMP_NAVI_TEXTFIELD
;
2453 case ContentTypeId::FOOTNOTE
:
2454 sResId
= RID_BMP_NAVI_FOOTNOTE
;
2456 case ContentTypeId::ENDNOTE
:
2457 sResId
= RID_BMP_NAVI_ENDNOTE
;
2459 case ContentTypeId::UNKNOWN
:
2460 SAL_WARN("sw.ui", "ContentTypeId::UNKNOWN has no bitmap preview");
2468 size_t SwContentTree::GetAbsPos(const weld::TreeIter
& rIter
)
2470 return weld::GetAbsPos(*m_xTreeView
, rIter
);
2473 size_t SwContentTree::GetEntryCount() const
2475 return m_nEntryCount
;
2478 size_t SwContentTree::GetChildCount(const weld::TreeIter
& rParent
) const
2480 if (!m_xTreeView
->iter_has_child(rParent
))
2483 std::unique_ptr
<weld::TreeIter
> xParent(m_xTreeView
->make_iterator(&rParent
));
2486 auto nRefDepth
= m_xTreeView
->get_iter_depth(*xParent
);
2487 auto nActDepth
= nRefDepth
;
2490 if (!m_xTreeView
->iter_next(*xParent
))
2493 nActDepth
= m_xTreeView
->get_iter_depth(*xParent
);
2495 } while(xParent
&& nRefDepth
< nActDepth
);
2501 std::unique_ptr
<weld::TreeIter
> SwContentTree::GetEntryAtAbsPos(size_t nAbsPos
) const
2503 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
2504 if (!m_xTreeView
->get_iter_first(*xEntry
))
2507 while (nAbsPos
&& xEntry
)
2509 if (!m_xTreeView
->iter_next(*xEntry
))
2516 void SwContentTree::Display( bool bActive
)
2518 // First read the selected entry to select it later again if necessary
2519 // -> the user data here are no longer valid!
2520 std::unique_ptr
<weld::TreeIter
> xOldSelEntry(m_xTreeView
->make_iterator());
2521 if (!m_xTreeView
->get_selected(xOldSelEntry
.get()))
2522 xOldSelEntry
.reset();
2523 OUString sOldSelEntryId
;
2524 size_t nEntryRelPos
= 0; // relative position to their parent
2525 size_t nOldEntryCount
= GetEntryCount();
2526 sal_Int32 nOldScrollPos
= 0;
2529 UpdateLastSelType();
2530 sOldSelEntryId
= m_xTreeView
->get_id(*xOldSelEntry
);
2531 nOldScrollPos
= m_xTreeView
->vadjustment_get_value();
2532 std::unique_ptr
<weld::TreeIter
> xParentEntry
= m_xTreeView
->make_iterator(xOldSelEntry
.get());
2533 while (m_xTreeView
->get_iter_depth(*xParentEntry
))
2534 m_xTreeView
->iter_parent(*xParentEntry
);
2535 if (m_xTreeView
->get_iter_depth(*xOldSelEntry
))
2536 nEntryRelPos
= GetAbsPos(*xOldSelEntry
) - GetAbsPos(*xParentEntry
);
2543 m_aOverlayObjectDelayTimer
.Stop();
2544 if (m_xOverlayObject
&& m_xOverlayObject
->getOverlayManager())
2546 m_xOverlayObject
->getOverlayManager()->remove(*m_xOverlayObject
);
2547 m_xOverlayObject
.reset();
2549 m_eState
= State::HIDDEN
;
2551 else if (State::HIDDEN
== m_eState
)
2552 m_eState
= State::ACTIVE
;
2553 SwWrtShell
* pShell
= GetWrtShell();
2554 const bool bReadOnly
= !pShell
|| pShell
->GetView().GetDocShell()->IsReadOnly();
2555 if(bReadOnly
!= m_bIsLastReadOnly
)
2557 m_bIsLastReadOnly
= bReadOnly
;
2558 bool bDisable
= pShell
== nullptr || bReadOnly
;
2559 SwNavigationPI
* pNavi
= GetParentWindow();
2560 pNavi
->m_xContent6ToolBox
->set_item_sensitive("chapterup", !bDisable
);
2561 pNavi
->m_xContent6ToolBox
->set_item_sensitive("chapterdown", !bDisable
);
2562 pNavi
->m_xContent6ToolBox
->set_item_sensitive("promote", !bDisable
);
2563 pNavi
->m_xContent6ToolBox
->set_item_sensitive("demote", !bDisable
);
2564 pNavi
->m_xContent5ToolBox
->set_item_sensitive("reminder", !bDisable
);
2569 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xTreeView
->make_iterator();
2570 std::unique_ptr
<weld::TreeIter
> xCntTypeEntry
;
2571 std::vector
<std::unique_ptr
<weld::TreeIter
>> aNodesToExpand
;
2572 // all content navigation view
2573 if(m_nRootType
== ContentTypeId::UNKNOWN
)
2575 m_xTreeView
->freeze();
2577 for( ContentTypeId nCntType
: o3tl::enumrange
<ContentTypeId
>() )
2579 std::unique_ptr
<SwContentType
>& rpContentT
= bActive
?
2580 m_aActiveContentArr
[nCntType
] :
2581 m_aHiddenContentArr
[nCntType
];
2583 rpContentT
.reset(new SwContentType(pShell
, nCntType
, m_nOutlineLevel
));
2585 OUString
aImage(GetImageIdForContentTypeId(nCntType
));
2586 bool bChOnDemand
= 0 != rpContentT
->GetMemberCount();
2587 OUString
sId(weld::toId(rpContentT
.get()));
2588 insert(nullptr, rpContentT
->GetName(), sId
, bChOnDemand
, xEntry
.get());
2589 m_xTreeView
->set_image(*xEntry
, aImage
);
2591 m_xTreeView
->set_sensitive(*xEntry
, bChOnDemand
);
2593 if (nCntType
== m_nLastSelType
)
2594 xCntTypeEntry
= m_xTreeView
->make_iterator(xEntry
.get());
2596 sal_Int32 nExpandOptions
= (State::HIDDEN
== m_eState
)
2599 if (nExpandOptions
& (1 << static_cast<int>(nCntType
)))
2601 // fill contents of to-be expanded entries while frozen
2602 Expand(*xEntry
, &aNodesToExpand
);
2603 m_xTreeView
->set_children_on_demand(*xEntry
, false);
2607 m_xTreeView
->thaw();
2609 // restore visual expanded tree state
2610 for (const auto& rNode
: aNodesToExpand
)
2611 m_xTreeView
->expand_row(*rNode
);
2613 // root content navigation view
2616 m_xTreeView
->freeze();
2618 std::unique_ptr
<SwContentType
>& rpRootContentT
= bActive
?
2619 m_aActiveContentArr
[m_nRootType
] :
2620 m_aHiddenContentArr
[m_nRootType
];
2622 rpRootContentT
.reset(new SwContentType(pShell
, m_nRootType
, m_nOutlineLevel
));
2623 OUString
aImage(GetImageIdForContentTypeId(m_nRootType
));
2624 bool bChOnDemand
= m_nRootType
== ContentTypeId::OUTLINE
;
2625 OUString
sId(weld::toId(rpRootContentT
.get()));
2626 insert(nullptr, rpRootContentT
->GetName(), sId
, bChOnDemand
, xEntry
.get());
2627 m_xTreeView
->set_image(*xEntry
, aImage
);
2629 xCntTypeEntry
= m_xTreeView
->make_iterator(xEntry
.get());
2632 InsertContent(*xEntry
);
2635 // fill contents of to-be expanded entries while frozen
2636 Expand(*xEntry
, &aNodesToExpand
);
2637 m_xTreeView
->set_children_on_demand(*xEntry
, false);
2640 m_xTreeView
->set_sensitive(*xEntry
, m_xTreeView
->iter_has_child(*xEntry
));
2642 m_xTreeView
->thaw();
2646 // restore visual expanded tree state
2647 for (const auto& rNode
: aNodesToExpand
)
2648 m_xTreeView
->expand_row(*rNode
);
2651 m_xTreeView
->expand_row(*xEntry
);
2654 // Reselect the old selected entry. If it is not available, select the entry at the old
2655 // selected entry position unless that entry position is now a content type or is past the
2656 // end of the member list then select the entry at the previous entry position.
2659 std::unique_ptr
<weld::TreeIter
> xSelEntry
= m_xTreeView
->make_iterator(xCntTypeEntry
.get());
2662 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator(xCntTypeEntry
.get()));
2663 std::unique_ptr
<weld::TreeIter
> xTemp(m_xTreeView
->make_iterator(xIter
.get()));
2666 while ((bNext
= m_xTreeView
->iter_next(*xIter
) && lcl_IsContent(*xIter
, *m_xTreeView
)))
2668 if (m_xTreeView
->get_id(*xIter
) == sOldSelEntryId
|| nPos
== nEntryRelPos
)
2670 m_xTreeView
->copy_iterator(*xIter
, *xSelEntry
);
2673 m_xTreeView
->copy_iterator(*xIter
, *xTemp
); // note previous entry
2677 xSelEntry
= std::move(xTemp
);
2679 // set_cursor unselects all entries, makes passed entry visible, and selects it
2680 m_xTreeView
->set_cursor(*xSelEntry
);
2685 if (!m_bIgnoreDocChange
&& GetEntryCount() == nOldEntryCount
)
2687 m_xTreeView
->vadjustment_set_value(nOldScrollPos
);
2691 void SwContentTree::clear()
2693 m_xTreeView
->freeze();
2694 m_xTreeView
->clear();
2696 m_xTreeView
->thaw();
2699 bool SwContentTree::FillTransferData( TransferDataContainer
& rTransfer
,
2700 sal_Int8
& rDragMode
)
2703 SwWrtShell
* pWrtShell
= GetWrtShell();
2704 OSL_ENSURE(pWrtShell
, "no Shell!");
2706 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
2707 bool bEntry
= m_xTreeView
->get_cursor(xEntry
.get());
2708 if (!bEntry
|| lcl_IsContentType(*xEntry
, *m_xTreeView
) || !pWrtShell
)
2711 assert(dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
))));
2712 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
));
2714 const ContentTypeId nActType
= pCnt
->GetParent()->GetType();
2716 bool bOutline
= false;
2717 OUString sOutlineText
;
2720 case ContentTypeId::OUTLINE
:
2722 const SwOutlineNodes::size_type nPos
= static_cast<SwOutlineContent
*>(pCnt
)->GetOutlinePos();
2723 OSL_ENSURE(nPos
< pWrtShell
->getIDocumentOutlineNodesAccess()->getOutlineNodesCount(),
2724 "outlinecnt changed");
2726 // make sure outline may actually be copied
2727 if( pWrtShell
->IsOutlineCopyable( nPos
) )
2729 const SwNumRule
* pOutlRule
= pWrtShell
->GetOutlineNumRule();
2730 const SwTextNode
* pTextNd
=
2731 pWrtShell
->getIDocumentOutlineNodesAccess()->getOutlineNode(nPos
);
2732 if (pTextNd
&& pOutlRule
&& pTextNd
->IsNumbered(pWrtShell
->GetLayout()))
2734 SwNumberTree::tNumberVector aNumVector
=
2735 pTextNd
->GetNumberVector(pWrtShell
->GetLayout());
2736 for( int nLevel
= 0;
2737 nLevel
<= pTextNd
->GetActualListLevel();
2740 const SwNumberTree::tSwNumTreeNumber nVal
= aNumVector
[nLevel
] + 1;
2741 sEntry
+= OUString::number( nVal
- pOutlRule
->Get(nLevel
).GetStart() ) + ".";
2744 sEntry
+= pWrtShell
->getIDocumentOutlineNodesAccess()->getOutlineText(nPos
, pWrtShell
->GetLayout(), false);
2745 sOutlineText
= pWrtShell
->getIDocumentOutlineNodesAccess()->getOutlineText(nPos
, pWrtShell
->GetLayout());
2746 m_bIsOutlineMoveable
= static_cast<SwOutlineContent
*>(pCnt
)->IsMoveable();
2751 case ContentTypeId::POSTIT
:
2752 case ContentTypeId::INDEX
:
2753 case ContentTypeId::REFERENCE
:
2754 case ContentTypeId::TEXTFIELD
:
2755 case ContentTypeId::FOOTNOTE
:
2756 case ContentTypeId::ENDNOTE
:
2757 // cannot be inserted, neither as URL nor as section
2759 case ContentTypeId::URLFIELD
:
2760 sUrl
= static_cast<SwURLFieldContent
*>(pCnt
)->GetURL();
2762 case ContentTypeId::OLE
:
2763 case ContentTypeId::GRAPHIC
:
2764 if(GetParentWindow()->GetRegionDropMode() != RegionMode::NONE
)
2767 rDragMode
&= ~( DND_ACTION_MOVE
| DND_ACTION_LINK
);
2770 sEntry
= m_xTreeView
->get_text(*xEntry
);
2773 if(!sEntry
.isEmpty())
2775 const SwDocShell
* pDocShell
= pWrtShell
->GetView().GetDocShell();
2778 if(pDocShell
->HasName())
2780 SfxMedium
* pMedium
= pDocShell
->GetMedium();
2781 sUrl
= pMedium
->GetURLObject().GetURLNoMark();
2782 // only if a primarily link shall be integrated.
2785 else if ( nActType
== ContentTypeId::REGION
|| nActType
== ContentTypeId::BOOKMARK
)
2787 // For field and bookmarks a link is also allowed
2788 // without a filename into its own document.
2791 else if (State::CONSTANT
== m_eState
&&
2792 ( !::GetActiveView() ||
2793 m_pActiveShell
!= ::GetActiveView()->GetWrtShellPtr()))
2795 // Urls of inactive views cannot dragged without
2796 // file names, also.
2801 bRet
= GetParentWindow()->GetRegionDropMode() == RegionMode::NONE
;
2802 rDragMode
= DND_ACTION_MOVE
;
2805 const OUString
& rToken
= pCnt
->GetParent()->GetTypeToken();
2806 sUrl
+= "#" + sEntry
;
2807 if(!rToken
.isEmpty())
2809 sUrl
+= OUStringChar(cMarkSeparator
) + rToken
;
2817 // In Outlines of heading text must match
2818 // the real number into the description.
2820 sEntry
= sOutlineText
;
2823 NaviContentBookmark
aBmk( sUrl
, sEntry
,
2824 GetParentWindow()->GetRegionDropMode(),
2826 aBmk
.Copy( rTransfer
);
2829 // An INetBookmark must a be delivered to foreign DocShells
2830 if( pDocShell
->HasName() )
2832 INetBookmark
aBkmk( sUrl
, sEntry
);
2833 rTransfer
.CopyINetBookmark( aBkmk
);
2840 void SwContentTree::ToggleToRoot()
2844 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
2845 bool bEntry
= m_xTreeView
->get_cursor(xEntry
.get());
2848 const SwContentType
* pCntType
;
2849 if (lcl_IsContentType(*xEntry
, *m_xTreeView
))
2851 assert(dynamic_cast<SwContentType
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
))));
2852 pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(*xEntry
));
2856 assert(dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
))));
2857 pCntType
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
))->GetParent();
2859 m_nRootType
= pCntType
->GetType();
2861 if (m_nRootType
== ContentTypeId::OUTLINE
|| m_nRootType
== ContentTypeId::DRAWOBJECT
)
2863 m_xTreeView
->set_selection_mode(SelectionMode::Multiple
);
2865 Display(State::HIDDEN
!= m_eState
);
2870 m_xTreeView
->set_selection_mode(SelectionMode::Single
);
2871 m_nLastSelType
= m_nRootType
;
2872 m_nRootType
= ContentTypeId::UNKNOWN
;
2874 // Other content type member data could have changed while in root view. Fill the content
2875 // member lists excluding the toggled from root content which should already have the most
2877 if (State::HIDDEN
!= m_eState
)
2879 for (ContentTypeId i
: o3tl::enumrange
<ContentTypeId
>())
2881 if (i
!= m_nLastSelType
&& m_aActiveContentArr
[i
])
2882 m_aActiveContentArr
[i
]->FillMemberList();
2885 Display(State::HIDDEN
!= m_eState
);
2887 m_pConfig
->SetRootType( m_nRootType
);
2888 weld::Toolbar
* pBox
= GetParentWindow()->m_xContent5ToolBox
.get();
2889 pBox
->set_item_active("root", m_bIsRoot
);
2892 bool SwContentTree::HasContentChanged()
2894 bool bContentChanged
= false;
2896 // - Run through the local array and the Treelistbox in parallel.
2897 // - Are the records not expanded, they are discarded only in the array
2898 // and the content type will be set as the new UserData.
2899 // - Is the root mode is active only this will be updated.
2901 // Valid for the displayed content types is:
2902 // the Memberlist will be erased and the membercount will be updated
2903 // If content will be checked, the memberlists will be replenished
2904 // at the same time. Once a difference occurs it will be only replenished
2905 // no longer checked. Finally, the box is filled again.
2907 if (State::HIDDEN
== m_eState
)
2909 for(ContentTypeId i
: o3tl::enumrange
<ContentTypeId
>())
2911 if(m_aActiveContentArr
[i
])
2912 m_aActiveContentArr
[i
]->Invalidate();
2917 // root content navigation view
2920 std::unique_ptr
<weld::TreeIter
> xRootEntry(m_xTreeView
->make_iterator());
2921 if (!m_xTreeView
->get_iter_first(*xRootEntry
))
2924 assert(dynamic_cast<SwContentType
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xRootEntry
))));
2925 const ContentTypeId nType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(*xRootEntry
))->GetType();
2926 SwContentType
* pArrType
= m_aActiveContentArr
[nType
].get();
2927 assert(weld::toId(pArrType
) == m_xTreeView
->get_id(*xRootEntry
));
2931 pArrType
->FillMemberList(&bContentChanged
);
2932 if (bContentChanged
)
2935 // FillMemberList tests if member count in old member array equals member count in new
2936 // member array. Test here for member count difference between array and tree.
2937 const size_t nChildCount
= GetChildCount(*xRootEntry
);
2938 if (nChildCount
!= pArrType
->GetMemberCount())
2941 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator(xRootEntry
.get()));
2942 for (size_t j
= 0; j
< nChildCount
; ++j
)
2944 if (!m_xTreeView
->iter_next(*xEntry
))
2946 SAL_WARN("sw.ui", "unexpected missing entry");
2950 // FillMemberList clears the content type member list and refills with new data.
2951 // Treeview entry user data is set here to the string representation of the pointer to
2952 // the member data in the array. The Display function will clear and recreate the
2953 // treeview from the content type member arrays if content change is detected.
2954 const SwContent
* pCnt
= pArrType
->GetMember(j
);
2955 OUString
sSubId(weld::toId(pCnt
));
2956 m_xTreeView
->set_id(*xEntry
, sSubId
);
2958 OUString sEntryText
= m_xTreeView
->get_text(*xEntry
);
2959 if (sEntryText
!= pCnt
->GetName() &&
2960 !(sEntryText
== m_sSpace
&& pCnt
->GetName().isEmpty()))
2966 // all content navigation view
2969 // Fill member list for each content type and check for content change. If content change
2970 // is detected only fill member lists for remaining content types. The Display function
2971 // will clear and recreate the treeview from the content type member arrays if content has
2973 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
2975 // lambda function to find the next content type entry
2976 auto lcl_nextContentTypeEntry
= [this, &xEntry
](){
2977 while (m_xTreeView
->get_iter_depth(*xEntry
))
2978 m_xTreeView
->iter_parent(*xEntry
);
2979 return m_xTreeView
->iter_next_sibling(*xEntry
);
2982 for (bool bEntry
= m_xTreeView
->get_iter_first(*xEntry
); bEntry
;
2983 bEntry
= lcl_nextContentTypeEntry())
2985 assert(dynamic_cast<SwContentType
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
))));
2986 SwContentType
* pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(*xEntry
));
2987 const size_t nCntCount
= pCntType
->GetMemberCount();
2988 const ContentTypeId nType
= pCntType
->GetType();
2989 SwContentType
* pArrType
= m_aActiveContentArr
[nType
].get();
2990 assert(weld::toId(pArrType
) == m_xTreeView
->get_id(*xEntry
));
2994 bContentChanged
= true;
2998 // all content type member lists must be filled!
2999 if (bContentChanged
)
3001 // If content change has already been detected there is no need to detect
3002 // other content change so no argument is supplied here to FillMemberList.
3003 pArrType
->FillMemberList();
3007 pArrType
->FillMemberList(&bContentChanged
);
3008 if (bContentChanged
)
3011 // does entry have children?
3012 if (m_xTreeView
->get_row_expanded(*xEntry
))
3014 const size_t nChildCount
= GetChildCount(*xEntry
);
3015 if(nChildCount
!= pArrType
->GetMemberCount())
3017 bContentChanged
= true;
3021 for(size_t j
= 0; j
< nChildCount
; ++j
)
3023 if (!m_xTreeView
->iter_next(*xEntry
))
3025 SAL_WARN("sw.ui", "unexpected missing entry");
3026 bContentChanged
= true;
3030 const SwContent
* pCnt
= pArrType
->GetMember(j
);
3031 OUString
sSubId(weld::toId(pCnt
));
3032 m_xTreeView
->set_id(*xEntry
, sSubId
);
3034 OUString sEntryText
= m_xTreeView
->get_text(*xEntry
);
3035 if( sEntryText
!= pCnt
->GetName() &&
3036 !(sEntryText
== m_sSpace
&& pCnt
->GetName().isEmpty()))
3038 bContentChanged
= true;
3043 // not expanded and has children
3044 else if (m_xTreeView
->iter_has_child(*xEntry
))
3046 bool bRemoveChildren
= false;
3047 const size_t nOldChildCount
= GetChildCount(*xEntry
);
3048 const size_t nNewChildCount
= pArrType
->GetMemberCount();
3049 if (nOldChildCount
!= nNewChildCount
)
3051 bRemoveChildren
= true;
3055 std::unique_ptr
<weld::TreeIter
> xChild(m_xTreeView
->make_iterator(xEntry
.get()));
3056 (void)m_xTreeView
->iter_children(*xChild
);
3057 for (size_t j
= 0; j
< nOldChildCount
; ++j
)
3059 const SwContent
* pCnt
= pArrType
->GetMember(j
);
3060 OUString
sSubId(weld::toId(pCnt
));
3061 m_xTreeView
->set_id(*xChild
, sSubId
);
3062 OUString sEntryText
= m_xTreeView
->get_text(*xChild
);
3063 if( sEntryText
!= pCnt
->GetName() &&
3064 !(sEntryText
== m_sSpace
&& pCnt
->GetName().isEmpty()))
3066 bRemoveChildren
= true;
3068 (void)m_xTreeView
->iter_next(*xChild
);
3071 if (bRemoveChildren
)
3073 std::unique_ptr
<weld::TreeIter
> xRemove(m_xTreeView
->make_iterator(xEntry
.get()));
3074 while (m_xTreeView
->iter_children(*xRemove
))
3077 m_xTreeView
->copy_iterator(*xEntry
, *xRemove
);
3079 m_xTreeView
->set_children_on_demand(*xEntry
, nNewChildCount
!= 0);
3082 else if((nCntCount
!= 0)
3083 != (pArrType
->GetMemberCount()!=0))
3085 bContentChanged
= true;
3091 return bContentChanged
;
3094 void SwContentTree::UpdateLastSelType()
3096 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
3097 if (m_xTreeView
->get_selected(xEntry
.get()))
3099 while (m_xTreeView
->get_iter_depth(*xEntry
))
3100 m_xTreeView
->iter_parent(*xEntry
);
3101 void* pId
= weld::fromId
<void*>(m_xTreeView
->get_id(*xEntry
));
3102 if (pId
&& lcl_IsContentType(*xEntry
, *m_xTreeView
))
3104 assert(dynamic_cast<SwContentType
*>(static_cast<SwTypeNumber
*>(pId
)));
3105 m_nLastSelType
= static_cast<SwContentType
*>(pId
)->GetType();
3110 void SwContentTree::FindActiveTypeAndRemoveUserData()
3112 UpdateLastSelType();
3114 // If clear is called by TimerUpdate:
3115 // Only for root can the validity of the UserData be guaranteed.
3116 m_xTreeView
->all_foreach([this](weld::TreeIter
& rEntry
){
3117 m_xTreeView
->set_id(rEntry
, "");
3122 void SwContentTree::SetHiddenShell(SwWrtShell
* pSh
)
3124 m_pHiddenShell
= pSh
;
3125 m_eState
= State::HIDDEN
;
3126 FindActiveTypeAndRemoveUserData();
3127 for(ContentTypeId i
: o3tl::enumrange
<ContentTypeId
>())
3129 m_aHiddenContentArr
[i
].reset();
3133 GetParentWindow()->UpdateListBox();
3136 void SwContentTree::SetActiveShell(SwWrtShell
* pSh
)
3138 bool bClear
= m_pActiveShell
!= pSh
;
3139 if (State::ACTIVE
== m_eState
&& bClear
)
3142 m_pActiveShell
= pSh
;
3143 FindActiveTypeAndRemoveUserData();
3146 else if (State::CONSTANT
== m_eState
)
3149 m_pActiveShell
= pSh
;
3150 m_eState
= State::ACTIVE
;
3154 // tdf#148432 in LTR UI override the navigator treeview direction based on
3155 // the first page directionality
3156 if (m_pActiveShell
&& !AllSettings::GetLayoutRTL())
3158 const SwPageDesc
& rDesc
= m_pActiveShell
->GetPageDesc(0);
3159 const SvxFrameDirectionItem
& rFrameDir
= rDesc
.GetMaster().GetFrameDir();
3160 m_xTreeView
->set_direction(rFrameDir
.GetValue() == SvxFrameDirection::Horizontal_RL_TB
);
3163 // Only if it is the active view, the array will be deleted and
3164 // the screen filled new.
3165 if (State::ACTIVE
== m_eState
&& bClear
)
3168 StartListening(*m_pActiveShell
->GetView().GetDocShell());
3169 FindActiveTypeAndRemoveUserData();
3170 for(ContentTypeId i
: o3tl::enumrange
<ContentTypeId
>())
3172 m_aActiveContentArr
[i
].reset();
3178 void SwContentTree::SetConstantShell(SwWrtShell
* pSh
)
3181 m_pActiveShell
= pSh
;
3182 m_eState
= State::CONSTANT
;
3183 StartListening(*m_pActiveShell
->GetView().GetDocShell());
3184 FindActiveTypeAndRemoveUserData();
3185 for(ContentTypeId i
: o3tl::enumrange
<ContentTypeId
>())
3187 m_aActiveContentArr
[i
].reset();
3192 void SwContentTree::Notify(SfxBroadcaster
& rBC
, SfxHint
const& rHint
)
3194 SfxViewEventHint
const*const pVEHint(dynamic_cast<SfxViewEventHint
const*>(&rHint
));
3195 SwXTextView
* pDyingShell
= nullptr;
3196 if (m_pActiveShell
&& pVEHint
&& pVEHint
->GetEventName() == "OnViewClosed")
3197 pDyingShell
= dynamic_cast<SwXTextView
*>(pVEHint
->GetController().get());
3198 if (pDyingShell
&& pDyingShell
->GetView() == &m_pActiveShell
->GetView())
3200 SetActiveShell(nullptr); // our view is dying, clear our pointers to it
3204 SfxListener::Notify(rBC
, rHint
);
3206 switch (rHint
.GetId())
3208 case SfxHintId::SwNavigatorUpdateTracking
:
3211 case SfxHintId::SwNavigatorSelectOutlinesWithSelections
:
3213 if (m_nRootType
== ContentTypeId::OUTLINE
)
3215 SelectOutlinesWithSelection();
3216 // make first selected entry visible
3217 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
3218 if (xEntry
&& m_xTreeView
->get_selected(xEntry
.get()))
3219 m_xTreeView
->scroll_to_row(*xEntry
);
3221 else if (m_nRootType
== ContentTypeId::UNKNOWN
)
3222 m_xTreeView
->unselect_all();
3225 case SfxHintId::DocChanged
:
3226 if (!m_bIgnoreDocChange
)
3228 m_bDocHasChanged
= true;
3229 TimerUpdate(&m_aUpdTimer
);
3232 case SfxHintId::ModeChanged
:
3233 if (SwWrtShell
* pShell
= GetWrtShell())
3235 const bool bReadOnly
= pShell
->GetView().GetDocShell()->IsReadOnly();
3236 if (bReadOnly
!= m_bIsLastReadOnly
)
3238 m_bIsLastReadOnly
= bReadOnly
;
3240 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
3241 if (m_xTreeView
->get_cursor(xEntry
.get()))
3243 m_xTreeView
->select(*xEntry
);
3247 m_xTreeView
->unselect_all();
3256 // Handler for outline entry up/down left/right movement
3257 void SwContentTree::ExecCommand(std::u16string_view rCmd
, bool bOutlineWithChildren
)
3259 if (m_xTreeView
->count_selected_rows() == 0)
3262 const bool bUp
= rCmd
== u
"chapterup";
3263 const bool bUpDown
= bUp
|| rCmd
== u
"chapterdown";
3264 const bool bLeft
= rCmd
== u
"promote";
3265 const bool bLeftRight
= bLeft
|| rCmd
== u
"demote";
3266 if (!bUpDown
&& !bLeftRight
)
3268 if (GetWrtShell()->GetView().GetDocShell()->IsReadOnly() ||
3269 (State::ACTIVE
!= m_eState
&&
3270 (State::CONSTANT
!= m_eState
|| m_pActiveShell
!= GetParentWindow()->GetCreateView()->GetWrtShellPtr())))
3275 SwWrtShell
*const pShell
= GetWrtShell();
3277 const SwNodes
& rNodes
= pShell
->GetNodes();
3278 const SwOutlineNodes
& rOutlineNodes
= rNodes
.GetOutLineNds();
3279 const SwOutlineNodes::size_type nOutlineNdsSize
= rOutlineNodes
.size();
3281 std::vector
<SwTextNode
*> selectedOutlineNodes
;
3282 std::vector
<std::unique_ptr
<weld::TreeIter
>> selected
;
3284 m_xTreeView
->selected_foreach([&](weld::TreeIter
& rEntry
){
3285 // it's possible to select the root node too which is a really bad idea
3286 if (lcl_IsContentType(rEntry
, *m_xTreeView
))
3288 // filter out children of selected parents so they don't get promoted
3289 // or moved twice (except if there is Ctrl modifier, since in that
3290 // case children are re-parented)
3291 if ((bLeftRight
|| bOutlineWithChildren
) && !selected
.empty())
3293 std::unique_ptr
<weld::TreeIter
> xParent(m_xTreeView
->make_iterator(&rEntry
));
3294 for (bool bParent
= m_xTreeView
->iter_parent(*xParent
); bParent
; bParent
= m_xTreeView
->iter_parent(*xParent
))
3296 if (m_xTreeView
->iter_compare(*selected
.back(), *xParent
) == 0)
3302 selected
.emplace_back(m_xTreeView
->make_iterator(&rEntry
));
3304 // Use the outline node position in the SwOutlineNodes array. Bad things
3305 // happen if the tree entry position is used and it doesn't match the node position
3306 // in SwOutlineNodes, which is usually the case for outline nodes in frames.
3307 const SwOutlineNodes::size_type nPos
3308 = weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(rEntry
))->GetOutlinePos();
3309 if (nPos
< nOutlineNdsSize
)
3311 SwNode
* pNode
= rNodes
.GetOutLineNds()[ nPos
];
3314 selectedOutlineNodes
.push_back(pNode
->GetTextNode());
3320 if (!selected
.size())
3323 if (bUpDown
&& !bUp
)
3324 { // to move down, start at the end!
3325 std::reverse(selected
.begin(), selected
.end());
3328 m_bIgnoreDocChange
= true;
3330 SwOutlineNodes::size_type nActPos
;
3331 bool bStartedAction
= false;
3333 MakeAllOutlineContentTemporarilyVisible
a(GetWrtShell()->GetDoc());
3335 // get first regular document content node outline node position in outline nodes array
3336 SwOutlineNodes::size_type nFirstRegularDocContentOutlineNodePos
= SwOutlineNodes::npos
;
3337 SwNodeOffset nEndOfExtrasIndex
= rNodes
.GetEndOfExtras().GetIndex();
3338 for (SwOutlineNodes::size_type nPos
= 0; nPos
< nOutlineNdsSize
; nPos
++)
3340 if (rOutlineNodes
[nPos
]->GetIndex() > nEndOfExtrasIndex
)
3342 nFirstRegularDocContentOutlineNodePos
= nPos
;
3347 for (auto const& pCurrentEntry
: selected
)
3349 nActPos
= weld::fromId
<SwOutlineContent
*>(
3350 m_xTreeView
->get_id(*pCurrentEntry
))->GetOutlinePos();
3352 // outline nodes in frames and tables are not up/down moveable
3353 if (nActPos
== SwOutlineNodes::npos
||
3354 (bUpDown
&& (!pShell
->IsOutlineMovable(nActPos
) ||
3355 nFirstRegularDocContentOutlineNodePos
== SwOutlineNodes::npos
)))
3360 if (!bStartedAction
)
3362 pShell
->StartAllAction();
3363 pShell
->StartUndo(bLeftRight
? SwUndoId::OUTLINE_LR
: SwUndoId::OUTLINE_UD
);
3364 bStartedAction
= true;
3367 pShell
->GotoOutline( nActPos
); // If text selection != box selection
3372 // move outline position up/down (outline position promote/demote)
3373 SwOutlineNodes::difference_type nDir
= bUp
? -1 : 1;
3374 if ((nDir
== -1 && nActPos
> 0) || (nDir
== 1 && nActPos
< nOutlineNdsSize
- 1))
3376 // make outline selection for use by MoveOutlinePara
3377 pShell
->MakeOutlineSel(nActPos
, nActPos
, bOutlineWithChildren
);
3379 int nActPosOutlineLevel
=
3380 rOutlineNodes
[nActPos
]->GetTextNode()->GetAttrOutlineLevel();
3381 SwOutlineNodes::size_type nPos
= nActPos
;
3385 int nPosOutlineLevel
= -1;
3386 while (++nPos
< nOutlineNdsSize
)
3389 rOutlineNodes
[nPos
]->GetTextNode()->GetAttrOutlineLevel();
3390 // discontinue if moving out of parent or equal level is found
3391 if (nPosOutlineLevel
<= nActPosOutlineLevel
)
3393 // count the children of the node when they are not included in the move
3394 if (!bOutlineWithChildren
)
3397 if (nPosOutlineLevel
>= nActPosOutlineLevel
)
3399 // move past children
3400 while (++nPos
< nOutlineNdsSize
)
3403 rOutlineNodes
[nPos
]->GetTextNode()->GetAttrOutlineLevel();
3404 // discontinue if moving out of parent or equal level is found
3405 if (nPosOutlineLevel
<= nActPosOutlineLevel
)
3414 while (nPos
&& --nPos
>= nFirstRegularDocContentOutlineNodePos
)
3416 int nPosOutlineLevel
=
3417 rOutlineNodes
[nPos
]->GetTextNode()->GetAttrOutlineLevel();
3418 // discontinue if equal level is found
3419 if (nPosOutlineLevel
== nActPosOutlineLevel
)
3421 // discontinue if moving out of parent
3422 if (nPosOutlineLevel
< nActPosOutlineLevel
)
3424 // Required for expected chapter placement when the chapter being moved
3425 // up has an outline level less than the outline level of chapters it
3426 // is being moved above and then encounters a chapter with an outline
3427 // level that is greater before reaching a chapter with the same
3428 // outline level as itself.
3436 pShell
->MoveOutlinePara(nDir
);
3438 pShell
->ClearMark();
3442 // move outline left/right (outline level promote/demote)
3443 if (!pShell
->IsProtectedOutlinePara())
3446 const SwOutlineNodes
& rOutlNds
= pShell
->GetDoc()->GetNodes().GetOutLineNds();
3447 const int nActLevel
= rOutlNds
[nActPos
]->GetTextNode()->GetAttrOutlineLevel();
3450 // disallow if any outline node to demote will exceed MAXLEVEL
3451 SwOutlineNodes::size_type nPos
= nActPos
;
3454 int nLevel
= rOutlNds
[nPos
]->GetTextNode()->GetAttrOutlineLevel();
3455 if (nLevel
== MAXLEVEL
)
3460 } while (bOutlineWithChildren
&& ++nPos
< rOutlNds
.size() &&
3461 rOutlNds
[nPos
]->GetTextNode()->GetAttrOutlineLevel() > nActLevel
);
3465 // disallow if trying to promote outline of level 1
3471 SwOutlineNodes::size_type nPos
= nActPos
;
3474 pShell
->SwCursorShell::GotoOutline(nPos
);
3475 pShell
->OutlineUpDown(bLeft
? -1 : 1);
3476 } while (bOutlineWithChildren
&& ++nPos
< rOutlNds
.size() &&
3477 rOutlNds
[nPos
]->GetTextNode()->GetAttrOutlineLevel() > nActLevel
);
3482 pShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
); // Cursor is now back at the current heading.
3488 pShell
->EndAllAction();
3489 if (m_aActiveContentArr
[ContentTypeId::OUTLINE
])
3490 m_aActiveContentArr
[ContentTypeId::OUTLINE
]->Invalidate();
3492 // tdf#143547 LO Writer: navigator should stand still on promoting and demoting
3493 // In addition to m_bIgnoreDocChange being true, selections are cleared before the Display
3494 // call. Either of these conditions disable restore of scroll position happening in the
3495 // Display function so it needs to be done here.
3496 auto nOldScrollPos
= m_xTreeView
->vadjustment_get_value();
3498 // clear all selections to prevent the Display function from trying to reselect selected entries
3499 m_xTreeView
->unselect_all();
3501 m_xTreeView
->vadjustment_set_value(nOldScrollPos
);
3505 // reselect entries, do this only when in outline content navigation mode
3506 const SwOutlineNodes
& rOutlineNds
= pShell
->GetNodes().GetOutLineNds();
3507 for (SwTextNode
* pNode
: selectedOutlineNodes
)
3509 m_xTreeView
->all_foreach([this, &rOutlineNds
, pNode
](weld::TreeIter
& rEntry
){
3510 if (lcl_IsContentType(rEntry
, *m_xTreeView
))
3512 SwOutlineNodes::size_type nPos
= weld::fromId
<SwOutlineContent
*>(
3513 m_xTreeView
->get_id(rEntry
))->GetOutlinePos();
3514 if (pNode
== rOutlineNds
[nPos
]->GetTextNode())
3516 std::unique_ptr
<weld::TreeIter
> xParent(m_xTreeView
->make_iterator(&rEntry
));
3517 if (m_xTreeView
->iter_parent(*xParent
)
3518 && !m_xTreeView
->get_row_expanded(*xParent
))
3520 m_xTreeView
->expand_row(*xParent
);
3522 m_xTreeView
->select(rEntry
);
3531 m_pActiveShell
->GetView().GetEditWin().GrabFocus();
3532 m_bIgnoreDocChange
= false;
3537 m_bIgnoreDocChange
= false;
3540 void SwContentTree::ShowTree()
3542 m_xTreeView
->show();
3543 m_aUpdTimer
.Start();
3546 void SwContentTree::HideTree()
3548 // folded together will not be idled
3550 m_xTreeView
->hide();
3553 static void lcl_SelectByContentTypeAndAddress(SwContentTree
* pThis
, weld::TreeView
& rContentTree
,
3554 ContentTypeId nType
, const void* ptr
)
3558 rContentTree
.set_cursor(-1);
3563 // find content type entry
3564 std::unique_ptr
<weld::TreeIter
> xIter(rContentTree
.make_iterator());
3566 bool bFoundEntry
= rContentTree
.get_iter_first(*xIter
);
3569 void* pUserData
= weld::fromId
<void*>(rContentTree
.get_id(*xIter
));
3570 assert(dynamic_cast<SwContentType
*>(static_cast<SwTypeNumber
*>(pUserData
)));
3571 if (nType
== static_cast<SwContentType
*>(pUserData
)->GetType())
3573 bFoundEntry
= rContentTree
.iter_next_sibling(*xIter
);
3578 rContentTree
.set_cursor(-1);
3583 // assure content type entry is expanded
3584 rContentTree
.expand_row(*xIter
);
3586 // find content type content entry and select it
3587 const void* p
= nullptr;
3588 while (rContentTree
.iter_next(*xIter
) && lcl_IsContent(*xIter
, rContentTree
))
3590 void* pUserData
= weld::fromId
<void*>(rContentTree
.get_id(*xIter
));
3593 case ContentTypeId::FOOTNOTE
:
3594 case ContentTypeId::ENDNOTE
:
3596 assert(dynamic_cast<SwTextFootnoteContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
3597 SwTextFootnoteContent
* pCnt
= static_cast<SwTextFootnoteContent
*>(pUserData
);
3598 p
= pCnt
->GetTextFootnote();
3601 case ContentTypeId::URLFIELD
:
3603 assert(dynamic_cast<SwURLFieldContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
3604 SwURLFieldContent
* pCnt
= static_cast<SwURLFieldContent
*>(pUserData
);
3605 p
= static_cast<const SwTextAttr
*>(pCnt
->GetINetAttr());
3608 case ContentTypeId::TEXTFIELD
:
3610 assert(dynamic_cast<SwTextFieldContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
3611 SwTextFieldContent
* pCnt
= static_cast<SwTextFieldContent
*>(pUserData
);
3612 p
= pCnt
->GetFormatField()->GetField();
3615 case ContentTypeId::POSTIT
:
3617 assert(dynamic_cast<SwPostItContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
3618 SwPostItContent
* pCnt
= static_cast<SwPostItContent
*>(pUserData
);
3619 p
= pCnt
->GetPostIt()->GetField();
3627 // get first selected for comparison
3628 std::unique_ptr
<weld::TreeIter
> xFirstSelected(rContentTree
.make_iterator());
3629 if (!rContentTree
.get_selected(xFirstSelected
.get()))
3630 xFirstSelected
.reset();
3631 if (rContentTree
.count_selected_rows() != 1 || !xFirstSelected
||
3632 rContentTree
.iter_compare(*xIter
, *xFirstSelected
) != 0)
3634 // unselect all entries and make passed entry visible and selected
3635 rContentTree
.set_cursor(*xIter
);
3642 rContentTree
.set_cursor(-1);
3647 static void lcl_SelectByContentTypeAndName(SwContentTree
* pThis
, weld::TreeView
& rContentTree
,
3648 std::u16string_view rContentTypeName
, std::u16string_view rName
)
3653 // find content type entry
3654 std::unique_ptr
<weld::TreeIter
> xIter(rContentTree
.make_iterator());
3655 bool bFoundEntry
= rContentTree
.get_iter_first(*xIter
);
3656 while (bFoundEntry
&& rContentTypeName
!= rContentTree
.get_text(*xIter
))
3657 bFoundEntry
= rContentTree
.iter_next_sibling(*xIter
);
3658 // find content type content entry and select it
3662 rContentTree
.expand_row(*xIter
); // assure content type entry is expanded
3663 while (rContentTree
.iter_next(*xIter
) && lcl_IsContent(*xIter
, rContentTree
))
3665 if (rName
== rContentTree
.get_text(*xIter
))
3667 // get first selected for comparison
3668 std::unique_ptr
<weld::TreeIter
> xFirstSelected(rContentTree
.make_iterator());
3669 if (!rContentTree
.get_selected(xFirstSelected
.get()))
3670 xFirstSelected
.reset();
3671 if (rContentTree
.count_selected_rows() != 1 || !xFirstSelected
||
3672 rContentTree
.iter_compare(*xIter
, *xFirstSelected
) != 0)
3674 // unselect all entries and make passed entry visible and selected
3675 rContentTree
.set_cursor(*xIter
);
3683 static void lcl_SelectDrawObjectByName(weld::TreeView
& rContentTree
, std::u16string_view rName
)
3688 // find content type entry
3689 std::unique_ptr
<weld::TreeIter
> xIter(rContentTree
.make_iterator());
3690 bool bFoundEntry
= rContentTree
.get_iter_first(*xIter
);
3691 while (bFoundEntry
&& SwResId(STR_CONTENT_TYPE_DRAWOBJECT
) != rContentTree
.get_text(*xIter
))
3692 bFoundEntry
= rContentTree
.iter_next_sibling(*xIter
);
3693 // find content type content entry and select it
3696 rContentTree
.expand_row(*xIter
); // assure content type entry is expanded
3697 while (rContentTree
.iter_next(*xIter
) && lcl_IsContent(*xIter
, rContentTree
))
3699 if (rName
== rContentTree
.get_text(*xIter
))
3701 if (!rContentTree
.is_selected(*xIter
))
3703 rContentTree
.select(*xIter
);
3704 rContentTree
.scroll_to_row(*xIter
);
3712 /** No idle with focus or while dragging */
3713 IMPL_LINK_NOARG(SwContentTree
, TimerUpdate
, Timer
*, void)
3715 // No need to update if content tree is not visible
3716 if (!m_xTreeView
->is_visible())
3719 // No update while focus is not in document.
3720 // No update while drag and drop.
3721 // Query view because the Navigator is cleared too late.
3722 SwView
* pView
= GetParentWindow()->GetCreateView();
3724 SwWrtShell
* pActShell
= pView
? pView
->GetWrtShellPtr() : nullptr;
3725 if(pActShell
&& pActShell
->GetWin() &&
3726 (pActShell
->GetWin()->HasFocus() || m_bDocHasChanged
|| m_bViewHasChanged
) &&
3727 !IsInDrag() && !pActShell
->ActionPend())
3729 if (m_bDocHasChanged
|| m_bViewHasChanged
)
3731 if (State::CONSTANT
== m_eState
&& !lcl_FindShell(m_pActiveShell
))
3733 SetActiveShell(pActShell
);
3734 GetParentWindow()->UpdateListBox();
3736 if (State::ACTIVE
== m_eState
&& pActShell
!= GetWrtShell())
3738 SetActiveShell(pActShell
);
3740 else if ((State::ACTIVE
== m_eState
|| (State::CONSTANT
== m_eState
&& pActShell
== GetWrtShell())) &&
3741 HasContentChanged())
3743 FindActiveTypeAndRemoveUserData();
3748 m_bIsIdleClear
= false;
3749 m_bDocHasChanged
= false;
3750 m_bViewHasChanged
= false;
3752 else if (!pView
&& State::ACTIVE
== m_eState
&& !m_bIsIdleClear
) // this block seems never to be entered
3756 SetActiveShell(nullptr);
3759 m_bIsIdleClear
= true;
3763 void SwContentTree::UpdateTracking()
3765 if (State::HIDDEN
== m_eState
|| !m_pActiveShell
)
3768 // only when treeview or treeview context menu does not have focus
3769 if (m_xTreeView
->has_focus() || m_xTreeView
->has_child_focus())
3772 // m_bIgnoreDocChange is set on delete and outline visibility toggle
3773 if (m_bIgnoreDocChange
)
3775 m_bIgnoreDocChange
= false;
3779 // bTrack is used to disallow tracking after jumping to an outline until the outline position
3780 // that was jumped to is no longer the current outline position.
3782 if (m_nLastGotoContentWasOutlinePos
!= SwOutlineNodes::npos
)
3784 if (m_pActiveShell
->GetOutlinePos() == m_nLastGotoContentWasOutlinePos
)
3787 m_nLastGotoContentWasOutlinePos
= SwOutlineNodes::npos
;
3792 // graphic, frame, and ole
3793 if (m_pActiveShell
->GetSelectionType() &
3794 (SelectionType::Graphic
| SelectionType::Frame
| SelectionType::Ole
))
3796 OUString aContentTypeName
;
3797 if (m_pActiveShell
->GetSelectionType() == SelectionType::Graphic
&&
3798 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::GRAPHIC
))
3800 if (!mTrackContentType
[ContentTypeId::GRAPHIC
]) return;
3801 aContentTypeName
= SwResId(STR_CONTENT_TYPE_GRAPHIC
);
3803 else if (m_pActiveShell
->GetSelectionType() == SelectionType::Frame
&&
3804 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::FRAME
))
3806 if (!mTrackContentType
[ContentTypeId::FRAME
]) return;
3807 aContentTypeName
= SwResId(STR_CONTENT_TYPE_FRAME
);
3809 else if (m_pActiveShell
->GetSelectionType() == SelectionType::Ole
&&
3810 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::OLE
))
3812 if (!mTrackContentType
[ContentTypeId::OLE
]) return;
3813 aContentTypeName
= SwResId(STR_CONTENT_TYPE_OLE
);
3815 if (!aContentTypeName
.isEmpty())
3817 OUString
aName(m_pActiveShell
->GetFlyName());
3818 lcl_SelectByContentTypeAndName(this, *m_xTreeView
, aContentTypeName
, aName
);
3823 if ((m_pActiveShell
->GetSelectionType() & (SelectionType::DrawObject
|
3824 SelectionType::DrawObjectEditMode
|
3825 SelectionType::DbForm
)) &&
3826 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::DRAWOBJECT
))
3828 if (mTrackContentType
[ContentTypeId::DRAWOBJECT
])
3830 // Multiple selection is possible when in root content navigation view so unselect all
3831 // selected entries before reselecting. This causes a bit of an annoyance when the treeview
3832 // scroll bar is used and focus is in the document by causing the last selected entry to
3833 // scroll back into view.
3835 m_xTreeView
->unselect_all();
3836 SdrView
* pSdrView
= m_pActiveShell
->GetDrawView();
3839 for (size_t nIdx(0); nIdx
< pSdrView
->GetMarkedObjectCount(); nIdx
++)
3841 SdrObject
* pSelected
= pSdrView
->GetMarkedObjectByIndex(nIdx
);
3842 OUString
aName(pSelected
->GetName());
3843 if (!aName
.isEmpty())
3844 lcl_SelectDrawObjectByName(*m_xTreeView
, aName
);
3849 // clear treeview selections
3850 m_xTreeView
->unselect_all();
3856 // footnotes and endnotes
3857 if (SwContentAtPos
aContentAtPos(IsAttrAtPos::Ftn
);
3858 m_pActiveShell
->GetContentAtPos(m_pActiveShell
->GetCursorDocPos(), aContentAtPos
)
3859 && aContentAtPos
.pFndTextAttr
&&
3860 !(m_bIsRoot
&& (m_nRootType
!= ContentTypeId::FOOTNOTE
&&
3861 m_nRootType
!= ContentTypeId::ENDNOTE
)))
3863 if (!aContentAtPos
.pFndTextAttr
->GetFootnote().IsEndNote())
3865 if (mTrackContentType
[ContentTypeId::FOOTNOTE
])
3866 lcl_SelectByContentTypeAndAddress(this, *m_xTreeView
, ContentTypeId::FOOTNOTE
,
3867 aContentAtPos
.pFndTextAttr
);
3869 else if (mTrackContentType
[ContentTypeId::ENDNOTE
])
3870 lcl_SelectByContentTypeAndAddress(this, *m_xTreeView
, ContentTypeId::ENDNOTE
,
3871 aContentAtPos
.pFndTextAttr
);
3874 // bookmarks - track first bookmark at cursor
3875 if (mTrackContentType
[ContentTypeId::BOOKMARK
] &&
3876 (m_pActiveShell
->GetSelectionType() & SelectionType::Text
))
3878 SwPaM
* pCursor
= m_pActiveShell
->GetCursor();
3879 IDocumentMarkAccess
* const pMarkAccess
= m_pActiveShell
->getIDocumentMarkAccess();
3880 IDocumentMarkAccess::const_iterator_t ppBookmark
= pMarkAccess
->getBookmarksBegin();
3881 if (pCursor
&& ppBookmark
!= pMarkAccess
->getBookmarksEnd() &&
3882 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::BOOKMARK
))
3884 OUString sBookmarkName
;
3885 SwPosition
* pCursorPoint
= pCursor
->GetPoint();
3886 while (ppBookmark
!= pMarkAccess
->getBookmarksEnd())
3888 if (lcl_IsUiVisibleBookmark(*ppBookmark
) &&
3889 *pCursorPoint
>= (*ppBookmark
)->GetMarkStart() &&
3890 *pCursorPoint
<= (*ppBookmark
)->GetMarkEnd())
3892 sBookmarkName
= (*ppBookmark
)->GetName();
3893 // keep previously selected bookmark instead
3894 // of selecting a different bookmark inside of it
3895 if (sBookmarkName
== m_sSelectedItem
)
3898 else if (!sBookmarkName
.isEmpty() &&
3899 *pCursorPoint
< (*ppBookmark
)->GetMarkStart())
3901 // don't search a different bookmark inside the
3902 // previous one, if the starting position of the next bookmarks
3903 // is after the cursor position (assuming that the
3904 // bookmark iterator jumps inside the same text by positions)
3910 if (!sBookmarkName
.isEmpty())
3912 // select the bookmark
3913 lcl_SelectByContentTypeAndName(this, *m_xTreeView
,
3914 SwResId(STR_CONTENT_TYPE_BOOKMARK
),
3921 if (SwContentAtPos
aContentAtPos(IsAttrAtPos::RefMark
);
3922 m_pActiveShell
->GetContentAtPos(m_pActiveShell
->GetCursorDocPos(), aContentAtPos
) &&
3923 aContentAtPos
.pFndTextAttr
&&
3924 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::REFERENCE
))
3926 if (mTrackContentType
[ContentTypeId::REFERENCE
])
3928 const SwFormatRefMark
& rRefMark
= aContentAtPos
.pFndTextAttr
->GetRefMark();
3929 lcl_SelectByContentTypeAndName(this, *m_xTreeView
, SwResId(STR_CONTENT_TYPE_REFERENCE
),
3930 rRefMark
.GetRefName());
3935 // not in ToxContent tdf#148312
3936 if (const SwSection
* pSection
= m_pActiveShell
->GetCurrSection(); !pSection
3937 || (pSection
&& pSection
->GetType() != SectionType::ToxContent
))
3939 if (SwContentAtPos
aContentAtPos(IsAttrAtPos::InetAttr
);
3940 m_pActiveShell
->GetContentAtPos(m_pActiveShell
->GetCursorDocPos(), aContentAtPos
)
3941 && (!m_bIsRoot
|| m_nRootType
== ContentTypeId::URLFIELD
))
3943 // Because hyperlink item names do not need to be unique, finding the corresponding
3944 // item in the tree by name may result in incorrect selection. Find the item in the
3945 // tree by comparing the SwTextINetFormat pointer at the document cursor position to
3946 // that stored in the item SwURLFieldContent.
3947 if (mTrackContentType
[ContentTypeId::URLFIELD
])
3948 lcl_SelectByContentTypeAndAddress(this, *m_xTreeView
, ContentTypeId::URLFIELD
,
3949 aContentAtPos
.pFndTextAttr
);
3954 if (SwField
* pField
= m_pActiveShell
->GetCurField(); pField
&&
3956 m_nRootType
!= ContentTypeId::TEXTFIELD
&&
3957 m_nRootType
!= ContentTypeId::POSTIT
))
3959 ContentTypeId eCntTypeId
=
3960 pField
->GetTypeId() == SwFieldTypesEnum::Postit
? ContentTypeId::POSTIT
:
3961 ContentTypeId::TEXTFIELD
;
3962 if (mTrackContentType
[eCntTypeId
])
3963 lcl_SelectByContentTypeAndAddress(this, *m_xTreeView
, eCntTypeId
, pField
);
3967 if (m_pActiveShell
->IsCursorInTable() &&
3968 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::TABLE
))
3970 if (mTrackContentType
[ContentTypeId::TABLE
] && m_pActiveShell
->GetTableFormat())
3972 OUString aName
= m_pActiveShell
->GetTableFormat()->GetName();
3973 lcl_SelectByContentTypeAndName(this, *m_xTreeView
, SwResId(STR_CONTENT_TYPE_TABLE
),
3979 if (const SwTOXBase
* pTOX
= m_pActiveShell
->GetCurTOX(); pTOX
&&
3980 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::INDEX
))
3982 if (mTrackContentType
[ContentTypeId::INDEX
])
3983 lcl_SelectByContentTypeAndName(this, *m_xTreeView
, SwResId(STR_CONTENT_TYPE_INDEX
),
3984 pTOX
->GetTOXName());
3988 if (const SwSection
* pSection
= m_pActiveShell
->GetCurrSection(); pSection
&&
3989 !(m_bIsRoot
&& m_nRootType
!= ContentTypeId::REGION
))
3991 if (mTrackContentType
[ContentTypeId::REGION
])
3993 lcl_SelectByContentTypeAndName(this, *m_xTreeView
, SwResId(STR_CONTENT_TYPE_REGION
),
3994 pSection
->GetSectionName());
3999 // prevent fall through to outline tracking when section tracking is off and the last
4000 // GotoContent is the current section
4001 if (m_nLastSelType
== ContentTypeId::REGION
&&
4002 m_xTreeView
->get_selected_text() == pSection
->GetSectionName())
4005 // fall through to outline tracking when section tracking is off and the last GotoContent
4006 // is not the current section
4010 if (m_nOutlineTracking
== 3)
4012 // find out where the cursor is
4013 const SwOutlineNodes::size_type nActPos
= GetWrtShell()->GetOutlinePos(MAXLEVEL
);
4014 if (!((m_bIsRoot
&& m_nRootType
!= ContentTypeId::OUTLINE
) || nActPos
== SwOutlineNodes::npos
))
4016 // assure outline content type is expanded
4017 // this assumes outline content type is first in treeview
4018 std::unique_ptr
<weld::TreeIter
> xFirstEntry(m_xTreeView
->make_iterator());
4019 if (m_xTreeView
->get_iter_first(*xFirstEntry
))
4020 m_xTreeView
->expand_row(*xFirstEntry
);
4022 m_xTreeView
->all_foreach([this, nActPos
](weld::TreeIter
& rEntry
){
4024 if (lcl_IsContent(rEntry
, *m_xTreeView
) && weld::fromId
<SwContent
*>(
4025 m_xTreeView
->get_id(rEntry
))->GetParent()->GetType() ==
4026 ContentTypeId::OUTLINE
)
4028 if (weld::fromId
<SwOutlineContent
*>(
4029 m_xTreeView
->get_id(rEntry
))->GetOutlinePos() == nActPos
)
4031 std::unique_ptr
<weld::TreeIter
> xFirstSelected(
4032 m_xTreeView
->make_iterator());
4033 if (!m_xTreeView
->get_selected(xFirstSelected
.get()))
4034 xFirstSelected
.reset();
4035 // only select if not already selected or tree has multiple entries selected
4036 if (m_xTreeView
->count_selected_rows() != 1 || !xFirstSelected
||
4037 m_xTreeView
->iter_compare(rEntry
, *xFirstSelected
) != 0)
4039 if (m_nOutlineTracking
== 2) // focused outline tracking
4041 // collapse to children of root node
4042 std::unique_ptr
<weld::TreeIter
> xChildEntry(
4043 m_xTreeView
->make_iterator());
4044 if (m_xTreeView
->get_iter_first(*xChildEntry
) &&
4045 m_xTreeView
->iter_children(*xChildEntry
))
4049 if (weld::fromId
<SwContent
*>(
4050 m_xTreeView
->get_id(*xChildEntry
))->
4051 GetParent()->GetType() == ContentTypeId::OUTLINE
)
4052 m_xTreeView
->collapse_row(*xChildEntry
);
4056 while (m_xTreeView
->iter_next(*xChildEntry
));
4059 // unselect all entries, make pEntry visible, and select
4060 m_xTreeView
->set_cursor(rEntry
);
4063 // tdf#149279 show at least two outline entries before the set cursor entry
4064 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator(&rEntry
));
4065 for (int i
= 0; i
< 2; i
++)
4067 if (m_xTreeView
->get_iter_depth(*xIter
) == 0)
4069 if (!m_xTreeView
->iter_previous(*xIter
))
4071 while (!weld::IsEntryVisible(*m_xTreeView
, *xIter
))
4072 m_xTreeView
->iter_parent(*xIter
);
4074 // Assure the scroll to row is collapsed after scrolling if it was collapsed
4075 // before. This is required here to make gtkinst scroll_to_row behave like
4077 const bool bRowExpanded
= m_xTreeView
->get_row_expanded(*xIter
);
4078 m_xTreeView
->scroll_to_row(*xIter
);
4080 m_xTreeView
->collapse_row(*xIter
);
4087 // use of this break assumes outline content type is first in tree
4088 if (lcl_IsContentType(rEntry
, *m_xTreeView
) &&
4089 weld::fromId
<SwContentType
*>(
4090 m_xTreeView
->get_id(rEntry
))->GetType() !=
4091 ContentTypeId::OUTLINE
)
4099 // clear treeview selections
4100 if (m_xTreeView
->count_selected_rows() > 0)
4102 m_xTreeView
->unselect_all();
4103 m_xTreeView
->set_cursor(-1);
4109 void SwContentTree::SelectOutlinesWithSelection()
4111 SwCursor
* pFirstCursor
= m_pActiveShell
->GetCursor();
4112 SwCursor
* pCursor
= pFirstCursor
;
4113 std::vector
<SwOutlineNodes::size_type
> aOutlinePositions
;
4118 if (pCursor
->HasMark())
4120 aOutlinePositions
.push_back(m_pActiveShell
->GetOutlinePos(UCHAR_MAX
, pCursor
));
4122 pCursor
= pCursor
->GetNext();
4124 } while (pCursor
&& pCursor
!= pFirstCursor
);
4126 if (aOutlinePositions
.empty())
4129 // remove duplicates before selecting
4130 aOutlinePositions
.erase(std::unique(aOutlinePositions
.begin(), aOutlinePositions
.end()),
4131 aOutlinePositions
.end());
4133 m_xTreeView
->unselect_all();
4135 for (auto nOutlinePosition
: aOutlinePositions
)
4137 m_xTreeView
->all_foreach([this, nOutlinePosition
](const weld::TreeIter
& rEntry
){
4138 if (lcl_IsContent(rEntry
, *m_xTreeView
) &&
4139 weld::fromId
<SwContent
*>(
4140 m_xTreeView
->get_id(rEntry
))->GetParent()->GetType() ==
4141 ContentTypeId::OUTLINE
)
4143 if (weld::fromId
<SwOutlineContent
*>(
4144 m_xTreeView
->get_id(rEntry
))->GetOutlinePos() ==
4147 std::unique_ptr
<weld::TreeIter
> xParent
=
4148 m_xTreeView
->make_iterator(&rEntry
);
4149 if (m_xTreeView
->iter_parent(*xParent
) &&
4150 !m_xTreeView
->get_row_expanded(*xParent
))
4151 m_xTreeView
->expand_row(*xParent
);
4152 m_xTreeView
->select(rEntry
);
4163 void SwContentTree::MoveOutline(SwOutlineNodes::size_type nTargetPos
)
4165 MakeAllOutlineContentTemporarilyVisible
a(GetWrtShell()->GetDoc());
4167 SwWrtShell
*const pShell
= GetWrtShell();
4168 pShell
->StartAllAction();
4169 pShell
->StartUndo(SwUndoId::OUTLINE_UD
);
4171 SwOutlineNodes::size_type nPrevSourcePos
= SwOutlineNodes::npos
;
4172 SwOutlineNodes::size_type nPrevTargetPosOrOffset
= SwOutlineNodes::npos
;
4174 bool bFirstMove
= true;
4176 for (const auto& source
: m_aDndOutlinesSelected
)
4178 SwOutlineNodes::size_type nSourcePos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(*source
))->GetOutlinePos();
4180 // Done on the first selection move
4181 if (bFirstMove
) // only do once
4183 if (nTargetPos
== SwOutlineNodes::npos
|| nSourcePos
> nTargetPos
)
4186 // The first up move sets the up move amount for the remaining selected outlines to be moved
4187 if (nTargetPos
!= SwOutlineNodes::npos
)
4188 nPrevTargetPosOrOffset
= nSourcePos
- nTargetPos
;
4190 nPrevTargetPosOrOffset
= nSourcePos
+ 1;
4192 else if (nSourcePos
< nTargetPos
)
4195 // The first down move sets the source and target positions for the remaining selected outlines to be moved
4196 nPrevSourcePos
= nSourcePos
;
4197 nPrevTargetPosOrOffset
= nTargetPos
;
4203 if (nTargetPos
== SwOutlineNodes::npos
|| nSourcePos
> nTargetPos
)
4206 nTargetPos
= nSourcePos
- nPrevTargetPosOrOffset
;
4208 else if (nSourcePos
< nTargetPos
)
4211 nSourcePos
= nPrevSourcePos
;
4212 nTargetPos
= nPrevTargetPosOrOffset
;
4215 GetParentWindow()->MoveOutline(nSourcePos
, nTargetPos
);
4219 pShell
->EndAllAction();
4220 m_aActiveContentArr
[ContentTypeId::OUTLINE
]->Invalidate();
4222 m_aDndOutlinesSelected
.clear();
4225 // Update immediately
4226 IMPL_LINK_NOARG(SwContentTree
, FocusInHdl
, weld::Widget
&, void)
4228 SwView
* pActView
= GetParentWindow()->GetCreateView();
4231 SwWrtShell
* pActShell
= pActView
->GetWrtShellPtr();
4232 if (State::CONSTANT
== m_eState
&& !lcl_FindShell(m_pActiveShell
))
4234 SetActiveShell(pActShell
);
4237 if (State::ACTIVE
== m_eState
&& pActShell
!= GetWrtShell())
4238 SetActiveShell(pActShell
);
4239 // Only call HasContentChanged() if the document has changed since last called
4240 else if ((State::ACTIVE
== m_eState
|| (State::CONSTANT
== m_eState
&& pActShell
== GetWrtShell())) &&
4243 if (HasContentChanged())
4245 m_bDocHasChanged
= false;
4248 else if (State::ACTIVE
== m_eState
)
4252 IMPL_LINK(SwContentTree
, KeyInputHdl
, const KeyEvent
&, rEvent
, bool)
4254 bool bConsumed
= true;
4256 const vcl::KeyCode aCode
= rEvent
.GetKeyCode();
4257 if (aCode
.GetCode() == KEY_MULTIPLY
&& aCode
.IsMod1())
4259 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4260 if (m_xTreeView
->get_selected(xEntry
.get()))
4261 ExpandOrCollapseAll(*m_xTreeView
, *xEntry
);
4263 else if (aCode
.GetCode() == KEY_RETURN
)
4265 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4266 if (m_xTreeView
->get_selected(xEntry
.get()))
4268 switch(aCode
.GetModifier())
4272 GetParentWindow()->ToggleTree();
4279 if (lcl_IsContentType(*xEntry
, *m_xTreeView
))
4281 m_xTreeView
->get_row_expanded(*xEntry
) ? m_xTreeView
->collapse_row(*xEntry
)
4282 : m_xTreeView
->expand_row(*xEntry
);
4285 ContentDoubleClickHdl(*m_xTreeView
);
4289 ContentDoubleClickHdl(*m_xTreeView
);
4294 else if(aCode
.GetCode() == KEY_DELETE
&& 0 == aCode
.GetModifier())
4296 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4297 if (m_xTreeView
->get_selected(xEntry
.get()) && lcl_IsContent(*xEntry
, *m_xTreeView
))
4299 assert(dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
))));
4300 if (weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xEntry
))->GetParent()->IsDeletable() &&
4301 !m_pActiveShell
->GetView().GetDocShell()->IsReadOnly())
4303 EditEntry(*xEntry
, EditEntryMode::DELETE
);
4307 //Make KEY_SPACE has same function as DoubleClick, and realize
4309 else if (aCode
.GetCode() == KEY_SPACE
&& 0 == aCode
.GetModifier())
4311 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4312 if (m_xTreeView
->get_cursor(xEntry
.get()))
4314 if (State::HIDDEN
!= m_eState
)
4316 if (State::CONSTANT
== m_eState
)
4318 m_pActiveShell
->GetView().GetViewFrame().GetWindow().ToTop();
4321 SwContent
* pCnt
= dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
)));
4323 if (pCnt
&& pCnt
->GetParent()->GetType() == ContentTypeId::DRAWOBJECT
)
4325 SdrView
* pDrawView
= m_pActiveShell
->GetDrawView();
4328 pDrawView
->SdrEndTextEdit();
4330 SwDrawModel
* pDrawModel
= m_pActiveShell
->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
4331 SdrPage
* pPage
= pDrawModel
->GetPage(0);
4332 const size_t nCount
= pPage
->GetObjCount();
4333 bool hasObjectMarked
= false;
4335 if (SdrObject
* pObject
= GetDrawingObjectsByContent(pCnt
))
4337 SdrPageView
* pPV
= pDrawView
->GetSdrPageView
/*GetPageViewPvNum*/(/*0*/);
4340 bool bUnMark
= pDrawView
->IsObjMarked(pObject
);
4341 pDrawView
->MarkObj( pObject
, pPV
, bUnMark
);
4345 for( size_t i
=0; i
<nCount
; ++i
)
4347 SdrObject
* pTemp
= pPage
->GetObj(i
);
4348 bool bMark
= pDrawView
->IsObjMarked(pTemp
);
4349 switch( pTemp
->GetObjIdentifier() )
4351 case SdrObjKind::Group
:
4352 case SdrObjKind::Text
:
4353 case SdrObjKind::Line
:
4354 case SdrObjKind::Rectangle
:
4355 case SdrObjKind::CircleOrEllipse
:
4356 case SdrObjKind::CircleSection
:
4357 case SdrObjKind::CircleArc
:
4358 case SdrObjKind::CircleCut
:
4359 case SdrObjKind::Polygon
:
4360 case SdrObjKind::PolyLine
:
4361 case SdrObjKind::PathLine
:
4362 case SdrObjKind::PathFill
:
4363 case SdrObjKind::FreehandLine
:
4364 case SdrObjKind::FreehandFill
:
4365 case SdrObjKind::PathPoly
:
4366 case SdrObjKind::PathPolyLine
:
4367 case SdrObjKind::Caption
:
4368 case SdrObjKind::CustomShape
:
4370 hasObjectMarked
= true;
4375 SdrPageView
* pPV
= pDrawView
->GetSdrPageView
/*GetPageViewPvNum*/(/*0*/);
4378 pDrawView
->MarkObj(pTemp
, pPV
, true);
4384 if ( !hasObjectMarked
)
4386 SwEditWin
& rEditWindow
= m_pActiveShell
->GetView().GetEditWin();
4387 vcl::KeyCode
tempKeycode( KEY_ESCAPE
);
4388 KeyEvent
rKEvt( 0 , tempKeycode
);
4389 static_cast<vcl::Window
*>(&rEditWindow
)->KeyInput( rKEvt
);
4394 m_bViewHasChanged
= true;
4400 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4401 if (m_xTreeView
->get_cursor(xEntry
.get()))
4403 SwContent
* pCnt
= dynamic_cast<SwContent
*>(weld::fromId
<SwTypeNumber
*>(m_xTreeView
->get_id(*xEntry
)));
4404 if (pCnt
&& pCnt
->GetParent()->GetType() == ContentTypeId::OUTLINE
)
4406 if (m_bIsRoot
&& aCode
.GetCode() == KEY_LEFT
&& aCode
.GetModifier() == 0)
4408 m_xTreeView
->unselect_all();
4411 else if (aCode
.IsMod1())
4413 if (aCode
.GetCode() == KEY_LEFT
)
4414 ExecCommand(u
"promote", !aCode
.IsShift());
4415 else if (aCode
.GetCode() == KEY_RIGHT
)
4416 ExecCommand(u
"demote", !aCode
.IsShift());
4417 else if (aCode
.GetCode() == KEY_UP
)
4418 ExecCommand(u
"chapterup", !aCode
.IsShift());
4419 else if (aCode
.GetCode() == KEY_DOWN
)
4420 ExecCommand(u
"chapterdown", !aCode
.IsShift());
4421 else if (aCode
.GetCode() == KEY_C
)
4422 CopyOutlineSelections();
4438 IMPL_LINK(SwContentTree
, QueryTooltipHdl
, const weld::TreeIter
&, rEntry
, OUString
)
4440 ContentTypeId nType
;
4441 bool bContent
= false;
4442 void* pUserData
= weld::fromId
<void*>(m_xTreeView
->get_id(rEntry
));
4443 if (lcl_IsContentType(rEntry
, *m_xTreeView
))
4445 assert(dynamic_cast<SwContentType
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4446 nType
= static_cast<SwContentType
*>(pUserData
)->GetType();
4450 assert(dynamic_cast<SwContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4451 nType
= static_cast<SwContent
*>(pUserData
)->GetParent()->GetType();
4459 case ContentTypeId::URLFIELD
:
4460 assert(dynamic_cast<SwURLFieldContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4461 sEntry
= static_cast<SwURLFieldContent
*>(pUserData
)->GetURL();
4464 case ContentTypeId::POSTIT
:
4465 assert(dynamic_cast<SwPostItContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4466 sEntry
= static_cast<SwPostItContent
*>(pUserData
)->GetName();
4468 case ContentTypeId::OUTLINE
:
4469 assert(dynamic_cast<SwOutlineContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4470 sEntry
= static_cast<SwOutlineContent
*>(pUserData
)->GetName();
4472 case ContentTypeId::GRAPHIC
:
4473 assert(dynamic_cast<SwGraphicContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4474 sEntry
= static_cast<SwGraphicContent
*>(pUserData
)->GetLink();
4476 case ContentTypeId::REGION
:
4478 assert(dynamic_cast<SwRegionContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4479 sEntry
= static_cast<SwRegionContent
*>(pUserData
)->GetName();
4480 const SwSectionFormats
& rFormats
= GetWrtShell()->GetDoc()->GetSections();
4481 for (SwSectionFormats::size_type n
= rFormats
.size(); n
;)
4483 const SwNodeIndex
* pIdx
= nullptr;
4484 const SwSectionFormat
* pFormat
= rFormats
[--n
];
4485 const SwSection
* pSect
;
4486 if (nullptr != (pSect
= pFormat
->GetSection()) &&
4487 pSect
->GetSectionName() == sEntry
&&
4488 nullptr != (pIdx
= pFormat
->GetContent().GetContentIdx()) &&
4489 pIdx
->GetNode().GetNodes().IsDocNodes())
4492 SwPaM
aPaM(pIdx
->GetNode(), *pIdx
->GetNode().EndOfSectionNode());
4493 SwDoc::CountWords(aPaM
, aDocStat
);
4494 sEntry
= SwResId(STR_REGION_DEFNAME
) + ": " + sEntry
+ "\n" +
4495 SwResId(FLD_STAT_WORD
) + ": " + OUString::number(aDocStat
.nWord
) + "\n" +
4496 SwResId(FLD_STAT_CHAR
) + ": " + OUString::number(aDocStat
.nChar
);
4502 case ContentTypeId::FOOTNOTE
:
4503 case ContentTypeId::ENDNOTE
:
4505 assert(dynamic_cast<SwTextFootnoteContent
*>(static_cast<SwTypeNumber
*>(pUserData
)));
4506 const SwTextFootnote
* pFootnote
=
4507 static_cast<const SwTextFootnoteContent
*>(pUserData
)->GetTextFootnote();
4509 sEntry
= pFootnote
->GetFootnote().IsEndNote() ? SwResId(STR_CONTENT_ENDNOTE
) :
4510 SwResId(STR_CONTENT_FOOTNOTE
);
4515 if(static_cast<SwContent
*>(pUserData
)->IsInvisible())
4517 if(!sEntry
.isEmpty())
4519 sEntry
+= m_sInvisible
;
4524 size_t nMemberCount
= static_cast<SwContentType
*>(pUserData
)->GetMemberCount();
4525 sEntry
= OUString::number(nMemberCount
) + " " +
4527 ? static_cast<SwContentType
*>(pUserData
)->GetSingleName()
4528 : static_cast<SwContentType
*>(pUserData
)->GetName());
4534 void SwContentTree::ExecuteContextMenuAction(const OUString
& rSelectedPopupEntry
)
4536 if (rSelectedPopupEntry
== "copy")
4538 CopyOutlineSelections();
4541 if (rSelectedPopupEntry
== "collapseallcategories")
4543 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xTreeView
->make_iterator();
4544 bool bEntry
= m_xTreeView
->get_iter_first(*xEntry
);
4547 m_xTreeView
->collapse_row(*xEntry
);
4548 bEntry
= m_xTreeView
->iter_next_sibling(*xEntry
);
4554 std::map
<OUString
, ContentTypeId
> mPopupEntryToContentTypeId
4556 {"tabletracking", ContentTypeId::TABLE
},
4557 {"frametracking", ContentTypeId::FRAME
},
4558 {"imagetracking", ContentTypeId::GRAPHIC
},
4559 {"oleobjecttracking", ContentTypeId::OLE
},
4560 {"bookmarktracking", ContentTypeId::BOOKMARK
},
4561 {"sectiontracking", ContentTypeId::REGION
},
4562 {"hyperlinktracking", ContentTypeId::URLFIELD
},
4563 {"referencetracking", ContentTypeId::REFERENCE
},
4564 {"indextracking", ContentTypeId::INDEX
},
4565 {"commenttracking", ContentTypeId::POSTIT
},
4566 {"drawingobjecttracking", ContentTypeId::DRAWOBJECT
},
4567 {"fieldtracking", ContentTypeId::TEXTFIELD
},
4568 {"footnotetracking", ContentTypeId::FOOTNOTE
},
4569 {"endnotetracking", ContentTypeId::ENDNOTE
}
4572 if (mPopupEntryToContentTypeId
.count(rSelectedPopupEntry
))
4574 ContentTypeId eCntTypeId
= mPopupEntryToContentTypeId
[rSelectedPopupEntry
];
4575 SetContentTypeTracking(eCntTypeId
, !mTrackContentType
[eCntTypeId
]);
4580 std::unique_ptr
<weld::TreeIter
> xFirst(m_xTreeView
->make_iterator());
4581 if (!m_xTreeView
->get_selected(xFirst
.get()))
4582 return; // this shouldn't happen, but better to be safe than ...
4584 if (rSelectedPopupEntry
== "sort")
4586 SwContentType
* pCntType
;
4587 const OUString
& rId(m_xTreeView
->get_id(*xFirst
));
4588 if (lcl_IsContentType(*xFirst
, *m_xTreeView
))
4589 pCntType
= weld::fromId
<SwContentType
*>(rId
);
4591 pCntType
= const_cast<SwContentType
*>(weld::fromId
<SwContent
*>(rId
)->GetParent());
4592 pCntType
->SetSortType(!pCntType
->GetSortType());
4593 pCntType
->FillMemberList();
4597 else if (rSelectedPopupEntry
== "deletechapter" ||
4598 rSelectedPopupEntry
== "deletetable" ||
4599 rSelectedPopupEntry
== "deleteframe" ||
4600 rSelectedPopupEntry
== "deleteimage" ||
4601 rSelectedPopupEntry
== "deleteoleobject" ||
4602 rSelectedPopupEntry
== "deletebookmark" ||
4603 rSelectedPopupEntry
== "deletehyperlink" ||
4604 rSelectedPopupEntry
== "deletereference" ||
4605 rSelectedPopupEntry
== "deleteindex" ||
4606 rSelectedPopupEntry
== "deletecomment" ||
4607 rSelectedPopupEntry
== "deletedrawingobject" ||
4608 rSelectedPopupEntry
== "deletefield")
4610 EditEntry(*xFirst
, EditEntryMode::DELETE
);
4614 auto nSelectedPopupEntry
= rSelectedPopupEntry
.toUInt32();
4615 switch (nSelectedPopupEntry
)
4617 case TOGGLE_OUTLINE_CONTENT_VISIBILITY
:
4618 case HIDE_OUTLINE_CONTENT_VISIBILITY
:
4619 case SHOW_OUTLINE_CONTENT_VISIBILITY
:
4621 m_pActiveShell
->EnterStdMode();
4622 m_bIgnoreDocChange
= true;
4623 SwOutlineContent
* pCntFirst
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(*xFirst
));
4625 // toggle the outline node outline content visible attribute
4626 if (nSelectedPopupEntry
== TOGGLE_OUTLINE_CONTENT_VISIBILITY
)
4628 SwNode
* pNode
= m_pActiveShell
->GetDoc()->GetNodes().GetOutLineNds()[pCntFirst
->GetOutlinePos()];
4629 pNode
->GetTextNode()->SetAttrOutlineContentVisible(
4630 !m_pActiveShell
->GetAttrOutlineContentVisible(pCntFirst
->GetOutlinePos()));
4635 SwOutlineNodes::size_type nPos
= pCntFirst
->GetOutlinePos();
4636 if (lcl_IsContentType(*xFirst
, *m_xTreeView
)) // Headings root entry
4637 nPos
= SwOutlineNodes::npos
;
4638 SwOutlineNodes::size_type nOutlineNodesCount
= m_pActiveShell
->getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
4640 if (nPos
!= SwOutlineNodes::npos
) // not root
4641 nLevel
= m_pActiveShell
->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos
);
4644 bool bShow(nSelectedPopupEntry
== SHOW_OUTLINE_CONTENT_VISIBILITY
);
4647 if (m_pActiveShell
->IsOutlineContentVisible(nPos
) != bShow
)
4648 m_pActiveShell
->GetDoc()->GetNodes().GetOutLineNds()[nPos
]->GetTextNode()->SetAttrOutlineContentVisible(bShow
);
4649 } while (++nPos
< nOutlineNodesCount
4650 && (nLevel
== -1 || m_pActiveShell
->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos
) > nLevel
));
4652 m_pActiveShell
->InvalidateOutlineContentVisibility();
4653 // show in the document what was toggled
4654 if (lcl_IsContentType(*xFirst
, *m_xTreeView
)) // Headings root entry
4655 m_pActiveShell
->GotoPage(1, true);
4657 m_pActiveShell
->GotoOutline(pCntFirst
->GetOutlinePos());
4659 m_bIgnoreDocChange
= false;
4660 m_pActiveShell
->SetModified();
4661 m_pActiveShell
->GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged
));
4667 nSelectedPopupEntry
-= 10;
4668 if(m_nOutlineTracking
!= nSelectedPopupEntry
)
4669 SetOutlineTracking(static_cast<sal_uInt8
>(nSelectedPopupEntry
));
4682 nSelectedPopupEntry
-= 100;
4683 if(m_nOutlineLevel
!= nSelectedPopupEntry
)
4684 SetOutlineLevel(static_cast<sal_Int8
>(nSelectedPopupEntry
));
4689 GetParentWindow()->SetRegionDropMode(static_cast<RegionMode
>(nSelectedPopupEntry
- 201));
4693 EditEntry(*xFirst
, nSelectedPopupEntry
== 401 ? EditEntryMode::RMV_IDX
: EditEntryMode::UPD_IDX
);
4697 EditEntry(*xFirst
, EditEntryMode::EDIT
);
4700 EditEntry(*xFirst
, EditEntryMode::UNPROTECT_TABLE
);
4704 const SwTOXBase
* pBase
= weld::fromId
<SwTOXBaseContent
*>(m_xTreeView
->get_id(*xFirst
))
4706 m_pActiveShell
->SetTOXBaseReadonly(*pBase
, !SwEditShell::IsTOXBaseReadonly(*pBase
));
4710 EditEntry(*xFirst
, EditEntryMode::RENAME
);
4713 m_pActiveShell
->GetView().GetPostItMgr()->Show();
4716 m_pActiveShell
->GetView().GetPostItMgr()->Hide();
4720 m_pActiveShell
->GetView().GetPostItMgr()->SetActiveSidebarWin(nullptr);
4721 m_pActiveShell
->GetView().GetPostItMgr()->Delete();
4726 m_pActiveShell
->GetView().GetViewFrame().GetDispatcher()->Execute(FN_OUTLINE_TO_CLIPBOARD
);
4730 ExpandOrCollapseAll(*m_xTreeView
, *xFirst
);
4733 ExecCommand(u
"chapterup", true);
4736 ExecCommand(u
"chapterdown", true);
4739 ExecCommand(u
"promote", true);
4742 ExecCommand(u
"demote", true);
4744 case 805: // select document content
4746 m_pActiveShell
->KillPams();
4747 m_pActiveShell
->ClearMark();
4748 m_pActiveShell
->EnterAddMode();
4749 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xFirst
));
4750 const ContentTypeId eTypeId
= pCnt
->GetParent()->GetType();
4751 if (eTypeId
== ContentTypeId::OUTLINE
)
4753 SwOutlineNodes::size_type nActPos
= weld::fromId
<SwOutlineContent
*>(
4754 m_xTreeView
->get_id(*xFirst
))->GetOutlinePos();
4755 m_pActiveShell
->GotoOutline(nActPos
);
4756 m_xTreeView
->selected_foreach([this](weld::TreeIter
& rEntry
){
4757 SwOutlineNodes::size_type nPos
= weld::fromId
<SwOutlineContent
*>(
4758 m_xTreeView
->get_id(rEntry
))->GetOutlinePos();
4759 m_pActiveShell
->SttSelect();
4760 // select children if not expanded and don't kill PaMs
4761 m_pActiveShell
->MakeOutlineSel(nPos
, nPos
,
4762 !m_xTreeView
->get_row_expanded(rEntry
), false);
4763 m_pActiveShell
->EndSelect();
4767 else if (eTypeId
== ContentTypeId::TABLE
)
4769 m_pActiveShell
->GotoTable(pCnt
->GetName());
4770 m_pActiveShell
->GetView().GetViewFrame().GetDispatcher()->Execute(FN_TABLE_SELECT_ALL
);
4772 else if (eTypeId
== ContentTypeId::REGION
)
4774 m_pActiveShell
->EnterStdMode();
4775 m_pActiveShell
->GotoRegion(pCnt
->GetName());
4776 GotoCurrRegionAndSkip(m_pActiveShell
->GetCurrentShellCursor(), fnRegionEnd
, m_pActiveShell
->IsReadOnlyAvailable());
4777 m_pActiveShell
->SttSelect();
4778 GotoCurrRegionAndSkip(m_pActiveShell
->GetCurrentShellCursor(), fnRegionStart
, m_pActiveShell
->IsReadOnlyAvailable());
4779 m_pActiveShell
->EndSelect();
4780 m_pActiveShell
->UpdateCursor();
4782 m_pActiveShell
->LeaveAddMode();
4787 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(*xFirst
));
4793 if(nSelectedPopupEntry
> 300 && nSelectedPopupEntry
< 400)
4795 nSelectedPopupEntry
-= 300;
4796 SwView
*pView
= SwModule::GetFirstView();
4799 nSelectedPopupEntry
--;
4800 if(nSelectedPopupEntry
== 0)
4802 SetConstantShell(&pView
->GetWrtShell());
4805 pView
= SwModule::GetNextView(pView
);
4807 if(nSelectedPopupEntry
)
4809 m_bViewHasChanged
= nSelectedPopupEntry
== 1;
4810 m_eState
= (nSelectedPopupEntry
== 1) ? State::ACTIVE
: State::HIDDEN
;
4811 Display(nSelectedPopupEntry
== 1);
4813 GetParentWindow()->UpdateListBox();
4818 void SwContentTree::DeleteOutlineSelections()
4822 m_pActiveShell
->StartAction();
4824 m_pActiveShell
->EnterAddMode();
4825 m_xTreeView
->selected_foreach([this, &nChapters
](weld::TreeIter
& rEntry
){
4827 if (m_xTreeView
->iter_has_child(rEntry
) &&
4828 !m_xTreeView
->get_row_expanded(rEntry
)) // only count children if not expanded
4830 nChapters
+= m_xTreeView
->iter_n_children(rEntry
);
4832 SwOutlineNodes::size_type nActPos
= weld::fromId
<SwOutlineContent
*>(m_xTreeView
->get_id(rEntry
))->GetOutlinePos();
4833 m_pActiveShell
->SttSelect();
4834 m_pActiveShell
->MakeOutlineSel(nActPos
, nActPos
, !m_xTreeView
->get_row_expanded(rEntry
), false); // select children if not expanded
4835 // The outline selection may already be to the start of the following outline paragraph
4836 // as happens when a table is the last content of the to be deleted outline. In this case
4837 // do not extend the to be deleted selection right or the first character of the following
4838 // outline paragraph will be removed. Also check if no selection was made which indicates
4839 // an empty paragraph and selection right is needed.
4840 if (!m_pActiveShell
->IsSttPara() || !m_pActiveShell
->HasSelection())
4841 m_pActiveShell
->Right(SwCursorSkipMode::Chars
, true, 1, false);
4842 m_pActiveShell
->EndSelect();
4845 m_pActiveShell
->LeaveAddMode();
4847 SwRewriter aRewriter
;
4848 aRewriter
.AddRule(UndoArg1
, SwResId(STR_CHAPTERS
, nChapters
));
4849 m_pActiveShell
->StartUndo(SwUndoId::DELETE
, &aRewriter
);
4850 m_pActiveShell
->Delete(false);
4851 m_pActiveShell
->EndUndo();
4853 m_pActiveShell
->EndAction();
4856 void SwContentTree::SetOutlineLevel(sal_uInt8 nSet
)
4858 if (nSet
== m_nOutlineLevel
)
4860 m_nOutlineLevel
= nSet
;
4861 m_pConfig
->SetOutlineLevel( m_nOutlineLevel
);
4862 std::unique_ptr
<SwContentType
>& rpContentT
= (State::ACTIVE
== m_eState
)
4863 ? m_aActiveContentArr
[ContentTypeId::OUTLINE
]
4864 : m_aHiddenContentArr
[ContentTypeId::OUTLINE
];
4867 rpContentT
->SetOutlineLevel(m_nOutlineLevel
);
4868 rpContentT
->FillMemberList();
4870 Display(State::ACTIVE
== m_eState
);
4873 void SwContentTree::SetOutlineTracking(sal_uInt8 nSet
)
4875 m_nOutlineTracking
= nSet
;
4876 m_pConfig
->SetOutlineTracking(m_nOutlineTracking
);
4879 void SwContentTree::SetContentTypeTracking(ContentTypeId eCntTypeId
, bool bSet
)
4881 mTrackContentType
[eCntTypeId
] = bSet
;
4882 m_pConfig
->SetContentTypeTrack(eCntTypeId
, bSet
);
4885 // Mode Change: Show dropped Doc
4886 void SwContentTree::ShowHiddenShell()
4890 m_eState
= State::HIDDEN
;
4895 // Mode Change: Show active view
4896 void SwContentTree::ShowActualView()
4898 m_eState
= State::ACTIVE
;
4900 GetParentWindow()->UpdateListBox();
4903 IMPL_LINK_NOARG(SwContentTree
, SelectHdl
, weld::TreeView
&, void)
4905 if (m_pConfig
->IsNavigateOnSelect())
4907 ContentDoubleClickHdl(*m_xTreeView
);
4913 // Select the content type in the Navigate By control
4914 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4915 if (!m_xTreeView
->get_selected(xEntry
.get()))
4917 while (m_xTreeView
->get_iter_depth(*xEntry
))
4918 m_xTreeView
->iter_parent(*xEntry
);
4919 m_pDialog
->SelectNavigateByContentType(m_xTreeView
->get_text(*xEntry
));
4922 // Here the buttons for moving outlines are en-/disabled.
4923 void SwContentTree::Select()
4925 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
4926 if (!m_xTreeView
->get_selected(xEntry
.get()))
4929 bool bEnable
= false;
4930 std::unique_ptr
<weld::TreeIter
> xParentEntry(m_xTreeView
->make_iterator(xEntry
.get()));
4931 bool bParentEntry
= m_xTreeView
->iter_parent(*xParentEntry
);
4932 while (bParentEntry
&& (!lcl_IsContentType(*xParentEntry
, *m_xTreeView
)))
4933 bParentEntry
= m_xTreeView
->iter_parent(*xParentEntry
);
4934 if (!m_bIsLastReadOnly
)
4936 if (!m_xTreeView
->get_visible())
4938 else if (bParentEntry
)
4940 if ((m_bIsRoot
&& m_nRootType
== ContentTypeId::OUTLINE
) ||
4941 (lcl_IsContent(*xEntry
, *m_xTreeView
) &&
4942 weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(*xParentEntry
))->GetType() == ContentTypeId::OUTLINE
))
4949 SwNavigationPI
* pNavi
= GetParentWindow();
4950 pNavi
->m_xContent6ToolBox
->set_item_sensitive("chapterup", bEnable
);
4951 pNavi
->m_xContent6ToolBox
->set_item_sensitive("chapterdown", bEnable
);
4952 pNavi
->m_xContent6ToolBox
->set_item_sensitive("promote", bEnable
);
4953 pNavi
->m_xContent6ToolBox
->set_item_sensitive("demote", bEnable
);
4956 void SwContentTree::SetRootType(ContentTypeId nType
)
4958 m_nRootType
= nType
;
4960 m_pConfig
->SetRootType( m_nRootType
);
4963 OUString
SwContentType::RemoveNewline(const OUString
& rEntry
)
4965 if (rEntry
.isEmpty())
4968 OUStringBuffer
aEntry(rEntry
);
4969 for (sal_Int32 i
= 0; i
< rEntry
.getLength(); ++i
)
4970 if(aEntry
[i
] == 10 || aEntry
[i
] == 13)
4973 return aEntry
.makeStringAndClear();
4976 void SwContentTree::EditEntry(const weld::TreeIter
& rEntry
, EditEntryMode nMode
)
4978 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(rEntry
));
4980 const ContentTypeId nType
= pCnt
->GetParent()->GetType();
4981 sal_uInt16 nSlot
= 0;
4983 if(EditEntryMode::DELETE
== nMode
)
4984 m_bIgnoreDocChange
= true;
4986 uno::Reference
< container::XNameAccess
> xNameAccess
, xSecond
, xThird
;
4989 case ContentTypeId::OUTLINE
:
4990 if(nMode
== EditEntryMode::DELETE
)
4992 DeleteOutlineSelections();
4996 case ContentTypeId::TABLE
:
4997 if(nMode
== EditEntryMode::UNPROTECT_TABLE
)
4999 m_pActiveShell
->GetView().GetDocShell()->
5000 GetDoc()->UnProtectCells( pCnt
->GetName());
5002 else if(nMode
== EditEntryMode::DELETE
)
5004 m_pActiveShell
->StartAction();
5005 OUString sTable
= SwResId(STR_TABLE_NAME
);
5006 SwRewriter aRewriterTableName
;
5007 aRewriterTableName
.AddRule(UndoArg1
, SwResId(STR_START_QUOTE
));
5008 aRewriterTableName
.AddRule(UndoArg2
, pCnt
->GetName());
5009 aRewriterTableName
.AddRule(UndoArg3
, SwResId(STR_END_QUOTE
));
5010 sTable
= aRewriterTableName
.Apply(sTable
);
5012 SwRewriter aRewriter
;
5013 aRewriter
.AddRule(UndoArg1
, sTable
);
5014 m_pActiveShell
->StartUndo(SwUndoId::DELETE
, &aRewriter
);
5015 m_pActiveShell
->GetView().GetViewFrame().GetDispatcher()->Execute(FN_TABLE_SELECT_ALL
);
5016 m_pActiveShell
->DeleteRow();
5017 m_pActiveShell
->EndUndo();
5018 m_pActiveShell
->EndAction();
5020 else if(nMode
== EditEntryMode::RENAME
)
5022 uno::Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5023 uno::Reference
< text::XTextTablesSupplier
> xTables(xModel
, uno::UNO_QUERY
);
5024 xNameAccess
= xTables
->getTextTables();
5027 nSlot
= FN_FORMAT_TABLE_DLG
;
5030 case ContentTypeId::GRAPHIC
:
5031 if(nMode
== EditEntryMode::DELETE
)
5033 m_pActiveShell
->DelRight();
5035 else if(nMode
== EditEntryMode::RENAME
)
5037 uno::Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5038 uno::Reference
< text::XTextGraphicObjectsSupplier
> xGraphics(xModel
, uno::UNO_QUERY
);
5039 xNameAccess
= xGraphics
->getGraphicObjects();
5040 uno::Reference
< text::XTextFramesSupplier
> xFrames(xModel
, uno::UNO_QUERY
);
5041 xSecond
= xFrames
->getTextFrames();
5042 uno::Reference
< text::XTextEmbeddedObjectsSupplier
> xObjs(xModel
, uno::UNO_QUERY
);
5043 xThird
= xObjs
->getEmbeddedObjects();
5046 nSlot
= FN_FORMAT_GRAFIC_DLG
;
5049 case ContentTypeId::FRAME
:
5050 case ContentTypeId::OLE
:
5051 if(nMode
== EditEntryMode::DELETE
)
5053 m_pActiveShell
->DelRight();
5055 else if(nMode
== EditEntryMode::RENAME
)
5057 uno::Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5058 uno::Reference
< text::XTextFramesSupplier
> xFrames(xModel
, uno::UNO_QUERY
);
5059 uno::Reference
< text::XTextEmbeddedObjectsSupplier
> xObjs(xModel
, uno::UNO_QUERY
);
5060 if(ContentTypeId::FRAME
== nType
)
5062 xNameAccess
= xFrames
->getTextFrames();
5063 xSecond
= xObjs
->getEmbeddedObjects();
5067 xNameAccess
= xObjs
->getEmbeddedObjects();
5068 xSecond
= xFrames
->getTextFrames();
5070 uno::Reference
< text::XTextGraphicObjectsSupplier
> xGraphics(xModel
, uno::UNO_QUERY
);
5071 xThird
= xGraphics
->getGraphicObjects();
5074 nSlot
= FN_FORMAT_FRAME_DLG
;
5076 case ContentTypeId::BOOKMARK
:
5077 if(nMode
== EditEntryMode::DELETE
)
5079 assert(!m_pActiveShell
->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS
));
5080 IDocumentMarkAccess
* const pMarkAccess
= m_pActiveShell
->getIDocumentMarkAccess();
5081 pMarkAccess
->deleteMark(pMarkAccess
->findMark(pCnt
->GetName()), false);
5083 else if(nMode
== EditEntryMode::RENAME
)
5085 assert(!m_pActiveShell
->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS
));
5086 uno::Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5087 uno::Reference
< text::XBookmarksSupplier
> xBkms(xModel
, uno::UNO_QUERY
);
5088 xNameAccess
= xBkms
->getBookmarks();
5092 // allowed despite PROTECT_BOOKMARKS: the dialog itself enforces it
5093 SfxStringItem
const name(FN_EDIT_BOOKMARK
, pCnt
->GetName());
5094 SfxPoolItem
const* args
[2] = { &name
, nullptr };
5095 m_pActiveShell
->GetView().GetViewFrame().
5096 GetDispatcher()->Execute(FN_EDIT_BOOKMARK
, SfxCallMode::SYNCHRON
, args
);
5100 case ContentTypeId::REGION
:
5101 if(nMode
== EditEntryMode::RENAME
)
5103 uno::Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5104 uno::Reference
< text::XTextSectionsSupplier
> xSects(xModel
, uno::UNO_QUERY
);
5105 xNameAccess
= xSects
->getTextSections();
5108 nSlot
= FN_EDIT_REGION
;
5111 case ContentTypeId::URLFIELD
:
5112 if (nMode
== EditEntryMode::DELETE
)
5113 nSlot
= SID_REMOVE_HYPERLINK
;
5115 nSlot
= SID_EDIT_HYPERLINK
;
5117 case ContentTypeId::REFERENCE
:
5119 if(nMode
== EditEntryMode::DELETE
)
5121 const OUString
& rName
= pCnt
->GetName();
5122 for (SfxPoolItem
* pItem
:
5123 m_pActiveShell
->GetDoc()->GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK
))
5125 assert(dynamic_cast<const SwFormatRefMark
*>(pItem
));
5126 const auto pFormatRefMark
= static_cast<const SwFormatRefMark
*>(pItem
);
5127 if (!pFormatRefMark
)
5129 const SwTextRefMark
* pTextRef
= pFormatRefMark
->GetTextRefMark();
5130 if (pTextRef
&& &pTextRef
->GetTextNode().GetNodes() ==
5131 &m_pActiveShell
->GetNodes() && rName
== pFormatRefMark
->GetRefName())
5133 m_pActiveShell
->GetDoc()->DeleteFormatRefMark(pFormatRefMark
);
5134 m_pActiveShell
->SwViewShell::UpdateFields();
5141 case ContentTypeId::TEXTFIELD
:
5143 if (nMode
== EditEntryMode::DELETE
)
5145 const SwTextFieldContent
* pTextFieldCnt
=
5146 static_cast<const SwTextFieldContent
*>(pCnt
);
5147 const SwTextField
* pTextField
= pTextFieldCnt
->GetFormatField()->GetTextField();
5148 SwTextField::DeleteTextField(*pTextField
);
5151 nSlot
= FN_EDIT_FIELD
;
5154 case ContentTypeId::POSTIT
:
5156 auto& rView
= m_pActiveShell
->GetView();
5157 auto pPostItMgr
= rView
.GetPostItMgr();
5158 pPostItMgr
->AssureStdModeAtShell();
5159 pPostItMgr
->SetActiveSidebarWin(nullptr);
5160 rView
.GetEditWin().GrabFocus();
5161 if(nMode
== EditEntryMode::DELETE
)
5162 m_pActiveShell
->DelRight();
5167 case ContentTypeId::INDEX
:
5169 const SwTOXBase
* pBase
= static_cast<SwTOXBaseContent
*>(pCnt
)->GetTOXBase();
5172 case EditEntryMode::EDIT
:
5175 SwPtrItem
aPtrItem( FN_INSERT_MULTI_TOX
, const_cast<SwTOXBase
*>(pBase
));
5176 m_pActiveShell
->GetView().GetViewFrame().
5177 GetDispatcher()->ExecuteList(FN_INSERT_MULTI_TOX
,
5178 SfxCallMode::ASYNCHRON
, { &aPtrItem
});
5182 case EditEntryMode::RMV_IDX
:
5183 case EditEntryMode::DELETE
:
5186 m_pActiveShell
->DeleteTOX(*pBase
, EditEntryMode::DELETE
== nMode
);
5189 case EditEntryMode::UPD_IDX
:
5190 case EditEntryMode::RENAME
:
5192 Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5193 Reference
< XDocumentIndexesSupplier
> xIndexes(xModel
, UNO_QUERY
);
5194 Reference
< XIndexAccess
> xIdxAcc(xIndexes
->getDocumentIndexes());
5195 Reference
< XNameAccess
>xLocalNameAccess(xIdxAcc
, UNO_QUERY
);
5196 if(EditEntryMode::RENAME
== nMode
)
5197 xNameAccess
= xLocalNameAccess
;
5198 else if(xLocalNameAccess
.is() && xLocalNameAccess
->hasByName(pBase
->GetTOXName()))
5200 Any aIdx
= xLocalNameAccess
->getByName(pBase
->GetTOXName());
5201 Reference
< XDocumentIndex
> xIdx
;
5211 case ContentTypeId::DRAWOBJECT
:
5212 if(EditEntryMode::DELETE
== nMode
)
5214 else if(nMode
== EditEntryMode::RENAME
)
5215 nSlot
= FN_NAME_SHAPE
;
5216 else if (nMode
== EditEntryMode::EDIT
)
5218 vcl::KeyCode
aKeyCode(KEY_RETURN
, false, false, false, false);
5219 KeyEvent
aKeyEvent(0, aKeyCode
);
5220 m_pActiveShell
->GetWin()->KeyInput(aKeyEvent
);
5223 case ContentTypeId::FOOTNOTE
:
5224 case ContentTypeId::ENDNOTE
:
5225 if (EditEntryMode::EDIT
== nMode
)
5226 nSlot
= FN_FORMAT_FOOTNOTE_DLG
;
5231 m_pActiveShell
->GetView().GetViewFrame().
5232 GetDispatcher()->Execute(nSlot
, SfxCallMode::SYNCHRON
);
5233 else if(xNameAccess
.is())
5235 uno::Any aObj
= xNameAccess
->getByName(pCnt
->GetName());
5236 uno::Reference
< uno::XInterface
> xTmp
;
5238 uno::Reference
< container::XNamed
> xNamed(xTmp
, uno::UNO_QUERY
);
5239 SwAbstractDialogFactory
* pFact
= SwAbstractDialogFactory::Create();
5240 ScopedVclPtr
<AbstractSwRenameXNamedDlg
> pDlg(pFact
->CreateSwRenameXNamedDlg(m_xTreeView
.get(), xNamed
, xNameAccess
));
5242 pDlg
->SetAlternativeAccess( xSecond
, xThird
);
5244 OUString sForbiddenChars
;
5245 if(ContentTypeId::BOOKMARK
== nType
)
5247 sForbiddenChars
= "/\\@:*?\";,.#";
5249 else if(ContentTypeId::TABLE
== nType
)
5251 sForbiddenChars
= " .<>";
5253 pDlg
->SetForbiddenChars(sForbiddenChars
);
5256 if(EditEntryMode::DELETE
== nMode
)
5258 auto nPos
= m_xTreeView
->vadjustment_get_value();
5259 m_bViewHasChanged
= true;
5260 TimerUpdate(&m_aUpdTimer
);
5262 m_xTreeView
->vadjustment_set_value(nPos
);
5266 static void lcl_AssureStdModeAtShell(SwWrtShell
* pWrtShell
)
5268 // deselect any drawing or frame and leave editing mode
5269 if (SdrView
* pSdrView
= pWrtShell
->GetDrawView())
5271 if (pSdrView
->IsTextEdit())
5273 bool bLockView
= pWrtShell
->IsViewLocked();
5274 pWrtShell
->LockView(true);
5275 pWrtShell
->EndTextEdit();
5276 pWrtShell
->LockView(bLockView
);
5278 // go out of the frame
5279 Point
aPt(LONG_MIN
, LONG_MIN
);
5280 pWrtShell
->SelectObj(aPt
, SW_LEAVE_FRAME
);
5283 if (pWrtShell
->IsSelFrameMode() || pWrtShell
->IsObjSelected())
5285 pWrtShell
->UnSelectFrame();
5286 pWrtShell
->LeaveSelFrameMode();
5287 pWrtShell
->GetView().LeaveDrawCreate();
5288 pWrtShell
->EnterStdMode();
5289 pWrtShell
->DrawSelChanged();
5290 pWrtShell
->GetView().StopShellTimer();
5293 pWrtShell
->EnterStdMode();
5296 void SwContentTree::CopyOutlineSelections()
5298 m_pActiveShell
->LockView(true);
5300 MakeAllOutlineContentTemporarilyVisible
a(m_pActiveShell
->GetDoc());
5301 lcl_AssureStdModeAtShell(m_pActiveShell
);
5302 m_pActiveShell
->EnterAddMode();
5303 size_t nCount
= m_xTreeView
->get_selected_rows().size();
5304 m_xTreeView
->selected_foreach([this, &nCount
](weld::TreeIter
& rEntry
){
5305 SwOutlineNodes::size_type nOutlinePos
= reinterpret_cast<SwOutlineContent
*>(
5306 m_xTreeView
->get_id(rEntry
).toInt64())->GetOutlinePos();
5307 m_pActiveShell
->SttSelect();
5308 m_pActiveShell
->MakeOutlineSel(nOutlinePos
, nOutlinePos
,
5309 !m_xTreeView
->get_row_expanded(rEntry
), false);
5310 // don't move if this is the last selected outline or the cursor is at start of para
5311 if (--nCount
&& !m_pActiveShell
->IsSttPara())
5312 m_pActiveShell
->Right(SwCursorSkipMode::Chars
, true, 1, false);
5313 m_pActiveShell
->EndSelect();
5316 m_pActiveShell
->LeaveAddMode();
5317 m_pActiveShell
->GetView().GetViewFrame().GetBindings().Execute(SID_COPY
);
5319 m_pActiveShell
->LockView(false);
5322 void SwContentTree::GotoContent(const SwContent
* pCnt
)
5326 if (m_pActiveShell
->IsCursorInTable() ||
5327 (m_pActiveShell
->GetCursor()->GetPoint()->nNode
.GetIndex() <=
5328 m_pActiveShell
->GetDoc()->GetNodes().GetEndOfExtras().GetIndex()))
5330 m_bSelectTo
= false;
5331 m_pActiveShell
->GetView().GetEditWin().GrabFocus();
5336 m_nLastGotoContentWasOutlinePos
= SwOutlineNodes::npos
;
5337 m_sSelectedItem
= "";
5338 lcl_AssureStdModeAtShell(m_pActiveShell
);
5340 std::optional
<std::unique_ptr
<SwPosition
>> oPosition
;
5342 oPosition
.emplace(new SwPosition(m_pActiveShell
->GetCursor()->GetPoint()->nNode
,
5343 m_pActiveShell
->GetCursor()->GetPoint()->nContent
));
5345 switch(m_nLastSelType
= pCnt
->GetParent()->GetType())
5347 case ContentTypeId::TEXTFIELD
:
5349 m_pActiveShell
->GotoFormatField(
5350 *static_cast<const SwTextFieldContent
*>(pCnt
)->GetFormatField());
5353 case ContentTypeId::OUTLINE
:
5355 const SwOutlineNodes::size_type nPos
=
5356 static_cast<const SwOutlineContent
*>(pCnt
)->GetOutlinePos();
5357 m_pActiveShell
->GotoOutline(nPos
);
5358 m_nLastGotoContentWasOutlinePos
= nPos
;
5361 case ContentTypeId::TABLE
:
5363 m_pActiveShell
->GotoTable(pCnt
->GetName());
5366 case ContentTypeId::FRAME
:
5367 case ContentTypeId::GRAPHIC
:
5368 case ContentTypeId::OLE
:
5370 m_pActiveShell
->GotoFly(pCnt
->GetName());
5373 case ContentTypeId::BOOKMARK
:
5375 m_pActiveShell
->StartAction();
5376 m_pActiveShell
->GotoMark(pCnt
->GetName());
5377 m_pActiveShell
->EndAction();
5378 m_sSelectedItem
= pCnt
->GetName();
5380 // If the hidden title of SwNavigatorPanel was emptied via UNO XPanel interface,
5381 // store the name of the selected bookmark there. This allows to query the
5382 // selected bookmark using UNO e.g. in add-ons, i.e. to disambiguate when
5383 // multiple bookmarks are there on the selected text range.
5384 // Note: this is a workaround because getDialog() of XPanel is not implemented
5385 // for SwNavigatorPanel.
5386 uno::Reference
< frame::XModel
> xModel
= m_pActiveShell
->GetView().GetDocShell()->GetBaseModel();
5388 Reference
<frame::XController2
> xController( xModel
->getCurrentController(), uno::UNO_QUERY
);
5389 if ( !xController
.is() )
5392 Reference
<ui::XSidebarProvider
> xSidebarProvider
= xController
->getSidebar();
5393 if ( !xSidebarProvider
.is() )
5396 Reference
<ui::XDecks
> xDecks
= xSidebarProvider
->getDecks();
5400 if (!xDecks
->hasByName("NavigatorDeck"))
5403 Reference
<ui::XDeck
> xDeck ( xDecks
->getByName("NavigatorDeck"), uno::UNO_QUERY
);
5407 Reference
<ui::XPanels
> xPanels
= xDeck
->getPanels();
5408 if ( !xPanels
.is() )
5411 if (xPanels
->hasByName("SwNavigatorPanel"))
5413 Reference
<ui::XPanel
> xPanel ( xPanels
->getByName("SwNavigatorPanel"), uno::UNO_QUERY
);
5414 if ( !xPanel
.is() || !xPanel
->getTitle().isEmpty() )
5417 xPanel
->setTitle( pCnt
->GetName() );
5421 case ContentTypeId::REGION
:
5423 m_pActiveShell
->GotoRegion(pCnt
->GetName());
5426 case ContentTypeId::URLFIELD
:
5428 if(m_pActiveShell
->GotoINetAttr(
5429 *static_cast<const SwURLFieldContent
*>(pCnt
)->GetINetAttr() ))
5431 m_pActiveShell
->Right( SwCursorSkipMode::Chars
, true, 1, false);
5432 m_pActiveShell
->SwCursorShell::SelectTextAttr( RES_TXTATR_INETFMT
, true );
5436 case ContentTypeId::REFERENCE
:
5438 m_pActiveShell
->GotoRefMark(pCnt
->GetName());
5441 case ContentTypeId::INDEX
:
5443 const OUString
& sName(pCnt
->GetName());
5444 if (!m_pActiveShell
->GotoNextTOXBase(&sName
))
5445 m_pActiveShell
->GotoPrevTOXBase(&sName
);
5448 case ContentTypeId::POSTIT
:
5449 m_pActiveShell
->GotoFormatField(*static_cast<const SwPostItContent
*>(pCnt
)->GetPostIt());
5451 case ContentTypeId::DRAWOBJECT
:
5453 m_pActiveShell
->GotoDrawingObject(pCnt
->GetName());
5456 case ContentTypeId::FOOTNOTE
:
5457 case ContentTypeId::ENDNOTE
:
5459 const SwTextFootnote
* pFootnote
=
5460 static_cast<const SwTextFootnoteContent
*>(pCnt
)->GetTextFootnote();
5463 m_pActiveShell
->GotoFootnoteAnchor(*pFootnote
);
5471 m_pActiveShell
->SttCursorMove();
5472 while (m_pActiveShell
->IsCursorInTable())
5474 m_pActiveShell
->MoveTable(GotoCurrTable
, fnTableStart
);
5475 if (!m_pActiveShell
->Left(SwCursorSkipMode::Chars
, false, 1, false))
5476 break; // Table is at the beginning of the document. It can't be selected this way.
5478 m_pActiveShell
->EndCursorMove();
5480 lcl_AssureStdModeAtShell(m_pActiveShell
);
5482 m_pActiveShell
->SetMark();
5483 m_pActiveShell
->GetCursor()->GetMark()->nNode
= oPosition
.value()->nNode
;
5484 m_pActiveShell
->GetCursor()->GetMark()->nContent
= oPosition
.value()->nContent
;
5485 m_pActiveShell
->UpdateCursor();
5487 m_pActiveShell
->GetView().GetEditWin().GrabFocus();
5489 m_bSelectTo
= false;
5493 if (m_pActiveShell
->IsFrameSelected() || m_pActiveShell
->IsObjSelected())
5495 m_pActiveShell
->HideCursor();
5496 m_pActiveShell
->EnterSelFrameMode();
5499 SwView
& rView
= m_pActiveShell
->GetView();
5500 rView
.StopShellTimer();
5501 rView
.GetPostItMgr()->SetActiveSidebarWin(nullptr);
5502 rView
.GetEditWin().GrabFocus();
5504 // Assure cursor is in visible view area.
5505 // (tdf#147041) Always show the navigated outline at the top of the visible view area.
5506 if (pCnt
->GetParent()->GetType() == ContentTypeId::OUTLINE
||
5507 (!m_pActiveShell
->IsCursorVisible() && !m_pActiveShell
->IsFrameSelected() &&
5508 !m_pActiveShell
->IsObjSelected()))
5510 Point
aPoint(rView
.GetVisArea().getX(), m_pActiveShell
->GetCursorDocPos().getY());
5511 rView
.SetVisArea(aPoint
);
5516 // Now even the matching text::Bookmark
5517 NaviContentBookmark::NaviContentBookmark()
5520 m_nDefaultDrag( RegionMode::NONE
)
5524 NaviContentBookmark::NaviContentBookmark( OUString aUrl
,
5526 RegionMode nDragType
,
5527 const SwDocShell
* pDocSh
) :
5528 m_aUrl(std::move( aUrl
)),
5529 m_aDescription(std::move(aDesc
)),
5530 m_nDocSh(reinterpret_cast<sal_IntPtr
>(pDocSh
)),
5531 m_nDefaultDrag( nDragType
)
5535 void NaviContentBookmark::Copy( TransferDataContainer
& rData
) const
5537 rtl_TextEncoding eSysCSet
= osl_getThreadTextEncoding();
5539 OString
sStrBuf(OUStringToOString(m_aUrl
, eSysCSet
) + OStringChar(NAVI_BOOKMARK_DELIM
) +
5540 OUStringToOString(m_aDescription
, eSysCSet
) + OStringChar(NAVI_BOOKMARK_DELIM
) +
5541 OString::number(static_cast<int>(m_nDefaultDrag
)) + OStringChar(NAVI_BOOKMARK_DELIM
) +
5542 OString::number(m_nDocSh
));
5543 rData
.CopyByteString(SotClipboardFormatId::SONLK
, sStrBuf
);
5546 bool NaviContentBookmark::Paste( const TransferableDataHelper
& rData
)
5549 bool bRet
= rData
.GetString( SotClipboardFormatId::SONLK
, sStr
);
5553 m_aUrl
= sStr
.getToken(0, NAVI_BOOKMARK_DELIM
, nPos
);
5554 m_aDescription
= sStr
.getToken(0, NAVI_BOOKMARK_DELIM
, nPos
);
5555 m_nDefaultDrag
= static_cast<RegionMode
>( o3tl::toInt32(o3tl::getToken(sStr
, 0, NAVI_BOOKMARK_DELIM
, nPos
)) );
5556 m_nDocSh
= o3tl::toInt32(o3tl::getToken(sStr
, 0, NAVI_BOOKMARK_DELIM
, nPos
));
5561 SwNavigationPI
* SwContentTree::GetParentWindow()
5566 void SwContentTree::SelectContentType(std::u16string_view rContentTypeName
)
5568 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator());
5569 if (!m_xTreeView
->get_iter_first(*xIter
))
5573 if (m_xTreeView
->get_text(*xIter
) == rContentTypeName
)
5575 m_xTreeView
->set_cursor(*xIter
);
5579 } while (m_xTreeView
->iter_next_sibling(*xIter
));
5582 IMPL_LINK_NOARG(SwContentTree
, OverlayObjectDelayTimerHdl
, Timer
*, void)
5584 m_aOverlayObjectDelayTimer
.Stop();
5585 if (m_xOverlayObject
)
5587 if (SdrView
* pView
= m_pActiveShell
->GetDrawView())
5589 if (SdrPaintWindow
* pPaintWindow
= pView
->GetPaintWindow(0))
5591 const rtl::Reference
<sdr::overlay::OverlayManager
>& xOverlayManager
=
5592 pPaintWindow
->GetOverlayManager();
5593 xOverlayManager
->add(*m_xOverlayObject
);
5599 void SwContentTree::OverlayObject(std::vector
<basegfx::B2DRange
>&& aRanges
)
5601 m_aOverlayObjectDelayTimer
.Stop();
5602 if (m_xOverlayObject
&& m_xOverlayObject
->getOverlayManager())
5603 m_xOverlayObject
->getOverlayManager()->remove(*m_xOverlayObject
);
5604 if (aRanges
.empty())
5605 m_xOverlayObject
.reset();
5608 m_xOverlayObject
.reset(new sdr::overlay::OverlaySelection(
5609 sdr::overlay::OverlayType::Invert
,
5610 Color(), std::move(aRanges
), true/*unused for Invert type*/));
5611 m_aOverlayObjectDelayTimer
.Start();
5615 void SwContentTree::BringEntryToAttention(const weld::TreeIter
& rEntry
)
5617 if (lcl_IsContent(rEntry
, *m_xTreeView
)) // content entry
5619 SwContent
* pCnt
= weld::fromId
<SwContent
*>(m_xTreeView
->get_id(rEntry
));
5620 if (pCnt
->IsInvisible())
5624 const ContentTypeId nType
= pCnt
->GetParent()->GetType();
5625 if (nType
== ContentTypeId::OUTLINE
)
5627 BringTypesWithFlowFramesToAttention({m_pActiveShell
->GetNodes().
5628 GetOutLineNds()[static_cast<SwOutlineContent
*>(pCnt
)->GetOutlinePos()]});
5630 else if (nType
== ContentTypeId::TABLE
)
5632 if (const sw::TableFrameFormats
* pFrameFormats
= m_pActiveShell
->GetDoc()->GetTableFrameFormats())
5633 if (const SwTableFormat
* pFrameFormat
= pFrameFormats
->FindFrameFormatByName(pCnt
->GetName()))
5635 SwTable
* pTable
= SwTable::FindTable(pFrameFormat
);
5637 BringTypesWithFlowFramesToAttention({pTable
->GetTableNode()});
5640 else if (nType
== ContentTypeId::FRAME
|| nType
== ContentTypeId::GRAPHIC
||
5641 nType
== ContentTypeId::OLE
)
5643 SwNodeType eNodeType
= SwNodeType::Text
;
5644 if(nType
== ContentTypeId::GRAPHIC
)
5645 eNodeType
= SwNodeType::Grf
;
5646 else if(nType
== ContentTypeId::OLE
)
5647 eNodeType
= SwNodeType::Ole
;
5648 if (const SwFrameFormat
* pFrameFormat
=
5649 m_pActiveShell
->GetDoc()->FindFlyByName(pCnt
->GetName(), eNodeType
))
5650 BringFramesToAttention(std::vector
<const SwFrameFormat
*> {pFrameFormat
});
5652 else if (nType
== ContentTypeId::BOOKMARK
)
5654 BringBookmarksToAttention(std::vector
<OUString
> {pCnt
->GetName()});
5656 else if (nType
== ContentTypeId::REGION
|| nType
== ContentTypeId::INDEX
)
5658 const SwSectionFormats
& rFormats
= m_pActiveShell
->GetDoc()->GetSections();
5659 const SwSectionFormat
* pFormat
= rFormats
.FindFormatByName(pCnt
->GetName());
5661 BringTypesWithFlowFramesToAttention({pFormat
->GetSectionNode()});
5663 else if (nType
== ContentTypeId::URLFIELD
)
5665 BringURLFieldsToAttention(SwGetINetAttrs
{SwGetINetAttr(pCnt
->GetName(),
5666 *static_cast<SwURLFieldContent
*>(pCnt
)->GetINetAttr())});
5668 else if (nType
== ContentTypeId::REFERENCE
)
5670 if (const SwTextAttr
* pTextAttr
=
5671 m_pActiveShell
->GetDoc()->GetRefMark(pCnt
->GetName())->GetTextRefMark())
5673 std::vector
<const SwTextAttr
*> aTextAttrArr
{pTextAttr
};
5674 BringReferencesToAttention(aTextAttrArr
);
5677 else if (nType
== ContentTypeId::POSTIT
)
5679 if (const SwTextAttr
* pTextAttr
=
5680 static_cast<SwPostItContent
*>(pCnt
)->GetPostIt()->GetTextField())
5682 std::vector
<const SwTextAttr
*> aTextAttrArr
{pTextAttr
};
5683 BringPostItFieldsToAttention(aTextAttrArr
);
5686 else if (nType
== ContentTypeId::DRAWOBJECT
)
5688 std::vector
<const SdrObject
*> aSdrObjectArr
{GetDrawingObjectsByContent(pCnt
)};
5689 BringDrawingObjectsToAttention(aSdrObjectArr
);
5691 else if (nType
== ContentTypeId::TEXTFIELD
)
5693 if (const SwTextAttr
* pTextAttr
=
5694 static_cast<SwTextFieldContent
*>(pCnt
)->GetFormatField()->GetTextField())
5696 std::vector
<const SwTextAttr
*> aTextAttrArr
{pTextAttr
};
5697 BringTextFieldsToAttention(aTextAttrArr
);
5700 else if (nType
== ContentTypeId::FOOTNOTE
|| nType
== ContentTypeId::ENDNOTE
)
5702 if (const SwTextAttr
* pTextAttr
=
5703 static_cast<SwTextFootnoteContent
*> (pCnt
)->GetTextFootnote())
5705 std::vector
<const SwTextAttr
*> aTextAttrArr
{pTextAttr
};
5706 BringFootnotesToAttention(aTextAttrArr
);
5711 else // content type entry
5713 SwContentType
* pCntType
= weld::fromId
<SwContentType
*>(m_xTreeView
->get_id(rEntry
));
5714 if (pCntType
->GetMemberCount() == 0)
5718 const ContentTypeId nType
= pCntType
->GetType();
5719 if (nType
== ContentTypeId::OUTLINE
)
5721 std::vector
<const SwNode
*> aNodesArr(
5722 m_pActiveShell
->GetNodes().GetOutLineNds().begin(),
5723 m_pActiveShell
->GetNodes().GetOutLineNds().end());
5724 BringTypesWithFlowFramesToAttention(aNodesArr
);
5726 else if (nType
== ContentTypeId::TABLE
)
5728 std::vector
<const SwNode
*> aNodesArr
;
5729 const size_t nCount
= m_pActiveShell
->GetTableFrameFormatCount(false);
5730 const sw::TableFrameFormats
& rTableFormats
= *m_pActiveShell
->GetDoc()->GetTableFrameFormats();
5731 SwAutoFormatGetDocNode
aGetHt(&m_pActiveShell
->GetNodes());
5732 for(size_t i
= 0; i
< nCount
; ++i
)
5734 if (const SwTableFormat
* pTableFormat
= rTableFormats
[i
])
5735 if (!pTableFormat
->GetInfo(aGetHt
)) // skip deleted tables
5737 SwTable
* pTable
= SwTable::FindTable(pTableFormat
);
5739 aNodesArr
.push_back(pTable
->GetTableNode());
5742 BringTypesWithFlowFramesToAttention(aNodesArr
);
5744 else if (nType
== ContentTypeId::FRAME
|| nType
== ContentTypeId::GRAPHIC
||
5745 nType
== ContentTypeId::OLE
)
5747 FlyCntType eType
= FLYCNTTYPE_FRM
;
5748 if(nType
== ContentTypeId::GRAPHIC
)
5749 eType
= FLYCNTTYPE_GRF
;
5750 else if(nType
== ContentTypeId::OLE
)
5751 eType
= FLYCNTTYPE_OLE
;
5752 BringFramesToAttention(m_pActiveShell
->GetFlyFrameFormats(eType
, true));
5754 else if (nType
== ContentTypeId::BOOKMARK
)
5756 std::vector
<OUString
> aNames
;
5757 const auto nCount
= pCntType
->GetMemberCount();
5758 for (size_t i
= 0; i
< nCount
; i
++)
5760 const SwContent
* pMember
= pCntType
->GetMember(i
);
5761 if (pMember
&& !pMember
->IsInvisible())
5762 aNames
.push_back(pMember
->GetName());
5764 BringBookmarksToAttention(aNames
);
5766 else if (nType
== ContentTypeId::REGION
|| nType
== ContentTypeId::INDEX
)
5768 std::vector
<const SwNode
*> aNodesArr
;
5769 const SwSectionFormats
& rFormats
= m_pActiveShell
->GetDoc()->GetSections();
5770 const size_t nSize
= rFormats
.size();
5771 for (SwSectionFormats::size_type n
= nSize
; n
;)
5773 const SwSectionFormat
* pSectionFormat
= rFormats
[--n
];
5774 if (pSectionFormat
&& pSectionFormat
->IsInNodesArr())
5776 const SwSection
* pSection
= pSectionFormat
->GetSection();
5777 if (pSection
&& !pSection
->IsHiddenFlag())
5779 const SectionType eSectionType
= pSection
->GetType();
5780 if (nType
== ContentTypeId::REGION
&&
5781 (eSectionType
== SectionType::ToxContent
||
5782 eSectionType
== SectionType::ToxHeader
))
5784 if (nType
== ContentTypeId::INDEX
&&
5785 eSectionType
!= SectionType::ToxContent
)
5787 if (const SwNode
* pNode
= pSectionFormat
->GetSectionNode())
5788 aNodesArr
.push_back(pNode
);
5792 BringTypesWithFlowFramesToAttention(aNodesArr
);
5794 else if (nType
== ContentTypeId::URLFIELD
)
5796 SwGetINetAttrs aINetAttrsArr
;
5797 m_pActiveShell
->GetINetAttrs(aINetAttrsArr
, false);
5798 BringURLFieldsToAttention(aINetAttrsArr
);
5800 else if (nType
== ContentTypeId::REFERENCE
)
5802 std::vector
<const SwTextAttr
*> aTextAttrArr
;
5803 for (const SfxPoolItem
* pItem
:
5804 m_pActiveShell
->GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK
))
5806 if (const auto pRefMark
= dynamic_cast<const SwFormatRefMark
*>(pItem
))
5808 const SwTextRefMark
* pTextRef
= pRefMark
->GetTextRefMark();
5809 if (pTextRef
&& &pTextRef
->GetTextNode().GetNodes() ==
5810 &m_pActiveShell
->GetNodes())
5811 aTextAttrArr
.push_back(pTextRef
);
5814 BringReferencesToAttention(aTextAttrArr
);
5816 else if (nType
== ContentTypeId::POSTIT
)
5818 std::vector
<const SwTextAttr
*> aTextAttrArr
;
5819 const auto nCount
= pCntType
->GetMemberCount();
5820 for (size_t i
= 0; i
< nCount
; i
++)
5822 const SwPostItContent
* pPostItContent
= static_cast<const SwPostItContent
*>(
5823 pCntType
->GetMember(i
));
5824 if (pPostItContent
&& !pPostItContent
->IsInvisible())
5825 if (const SwFormatField
* pFormatField
= pPostItContent
->GetPostIt())
5826 if (const SwTextAttr
* pTextAttr
= pFormatField
->GetTextField())
5827 aTextAttrArr
.push_back(pTextAttr
);
5829 BringPostItFieldsToAttention(aTextAttrArr
);
5831 else if (nType
== ContentTypeId::DRAWOBJECT
)
5833 IDocumentDrawModelAccess
& rIDDMA
= m_pActiveShell
->getIDocumentDrawModelAccess();
5834 if (const SwDrawModel
* pModel
= rIDDMA
.GetDrawModel())
5836 if (const SdrPage
* pPage
= pModel
->GetPage(0))
5838 if (const size_t nCount
= pPage
->GetObjCount())
5840 std::vector
<const SdrObject
*> aSdrObjectArr
;
5841 for (size_t i
= 0; i
< nCount
; ++i
)
5843 const SdrObject
* pObject
= pPage
->GetObj(i
);
5844 if (pObject
&& !pObject
->GetName().isEmpty() &&
5845 rIDDMA
.IsVisibleLayerId(pObject
->GetLayer()))
5846 aSdrObjectArr
.push_back(pObject
);
5848 BringDrawingObjectsToAttention(aSdrObjectArr
);
5853 else if (nType
== ContentTypeId::TEXTFIELD
)
5855 std::vector
<const SwTextAttr
*> aTextAttrArr
;
5856 const auto nCount
= pCntType
->GetMemberCount();
5857 for (size_t i
= 0; i
< nCount
; i
++)
5859 const SwTextFieldContent
* pTextFieldCnt
=
5860 static_cast<const SwTextFieldContent
*>(pCntType
->GetMember(i
));
5861 if (pTextFieldCnt
&& !pTextFieldCnt
->IsInvisible())
5862 if (const SwFormatField
* pFormatField
= pTextFieldCnt
->GetFormatField())
5863 if (const SwTextAttr
* pTextAttr
= pFormatField
->GetTextField())
5864 aTextAttrArr
.push_back(pTextAttr
);
5866 BringTextFieldsToAttention(aTextAttrArr
);
5868 else if (nType
== ContentTypeId::FOOTNOTE
|| nType
== ContentTypeId::ENDNOTE
)
5870 std::vector
<const SwTextAttr
*> aTextAttrArr
;
5871 const auto nCount
= pCntType
->GetMemberCount();
5872 for (size_t i
= 0; i
< nCount
; i
++)
5874 const SwTextFootnoteContent
* pTextFootnoteCnt
=
5875 static_cast<const SwTextFootnoteContent
*>(pCntType
->GetMember(i
));
5876 if (pTextFootnoteCnt
&& !pTextFootnoteCnt
->IsInvisible())
5877 if (const SwTextAttr
* pTextAttr
= pTextFootnoteCnt
->GetTextFootnote())
5878 aTextAttrArr
.push_back(pTextAttr
);
5880 BringFootnotesToAttention(aTextAttrArr
);
5886 static void lcl_CalcOverlayRanges(const SwTextFrame
* pStartFrame
, const SwTextFrame
* pEndFrame
,
5887 const SwPosition
& aStartPos
, const SwPosition
& aEndPos
,
5888 std::vector
<basegfx::B2DRange
>& aRanges
)
5890 if (pStartFrame
&& pEndFrame
)
5892 SwRect aStartCharRect
;
5893 pStartFrame
->GetCharRect(aStartCharRect
, aStartPos
);
5894 SwRect aEndCharRect
;
5895 pEndFrame
->GetCharRect(aEndCharRect
, aEndPos
);
5896 if (aStartCharRect
.Top() == aEndCharRect
.Top())
5898 // single line range
5899 aRanges
.emplace_back(aStartCharRect
.Left(), aStartCharRect
.Top(),
5900 aEndCharRect
.Right() + 1, aEndCharRect
.Bottom() + 1);
5905 SwRect aFrameRect
= pStartFrame
->getFrameArea();
5906 aRanges
.emplace_back(aStartCharRect
.Left(), aStartCharRect
.Top(),
5907 aFrameRect
.Right(), aStartCharRect
.Bottom() + 1);
5908 if (aStartCharRect
.Bottom() + 1 != aEndCharRect
.Top())
5909 aRanges
.emplace_back(aFrameRect
.Left(), aStartCharRect
.Bottom() + 1,
5910 aFrameRect
.Right(), aEndCharRect
.Top() + 1);
5911 aRanges
.emplace_back(aFrameRect
.Left(), aEndCharRect
.Top() + 1,
5912 aEndCharRect
.Right() + 1, aEndCharRect
.Bottom() + 1);
5917 void SwContentTree::BringFramesToAttention(const std::vector
<const SwFrameFormat
*>& rFrameFormats
)
5919 std::vector
<basegfx::B2DRange
> aRanges
;
5920 for (const SwFrameFormat
* pFrameFormat
: rFrameFormats
)
5924 SwRect aFrameRect
= pFrameFormat
->FindLayoutRect();
5925 if (!aFrameRect
.IsEmpty())
5926 aRanges
.emplace_back(aFrameRect
.Left(), aFrameRect
.Top(), aFrameRect
.Right(),
5927 aFrameRect
.Bottom());
5929 OverlayObject(std::move(aRanges
));
5932 void SwContentTree::BringBookmarksToAttention(const std::vector
<OUString
>& rNames
)
5934 std::vector
<basegfx::B2DRange
> aRanges
;
5935 IDocumentMarkAccess
* const pMarkAccess
= m_pActiveShell
->getIDocumentMarkAccess();
5936 for (const auto& rName
: rNames
)
5938 IDocumentMarkAccess::const_iterator_t ppBkmk
= pMarkAccess
->findBookmark(rName
);
5939 if (ppBkmk
== pMarkAccess
->getBookmarksEnd())
5941 SwPosition aMarkStart
= (*ppBkmk
)->GetMarkStart();
5942 const SwTextNode
* pMarkStartTextNode
= aMarkStart
.GetNode().GetTextNode();
5943 if (!pMarkStartTextNode
)
5945 const SwTextFrame
* pMarkStartFrame
= static_cast<const SwTextFrame
*>(
5946 pMarkStartTextNode
->getLayoutFrame(m_pActiveShell
->GetLayout()));
5947 if (!pMarkStartFrame
)
5949 SwPosition aMarkEnd
= (*ppBkmk
)->GetMarkEnd();
5950 const SwTextNode
* pMarkEndTextNode
= aMarkEnd
.GetNode().GetTextNode();
5951 if (!pMarkEndTextNode
)
5953 const SwTextFrame
* pMarkEndFrame
= static_cast<const SwTextFrame
*>(
5954 pMarkEndTextNode
->getLayoutFrame(m_pActiveShell
->GetLayout()));
5957 // adjust span when mark start equals mark end
5958 if (aMarkStart
== aMarkEnd
)
5960 if (aMarkEnd
.GetContentIndex() < pMarkEndTextNode
->Len() - 1)
5961 aMarkEnd
.AdjustContent(+1);
5962 else if (aMarkStart
.GetContentIndex() > 0)
5963 aMarkStart
.AdjustContent(-1);
5965 lcl_CalcOverlayRanges(pMarkStartFrame
, pMarkEndFrame
, aMarkStart
, aMarkEnd
, aRanges
);
5967 OverlayObject(std::move(aRanges
));
5970 void SwContentTree::BringTypesWithFlowFramesToAttention(const std::vector
<const SwNode
*>& rNodes
)
5972 std::vector
<basegfx::B2DRange
> aRanges
;
5973 for (const auto* pNode
: rNodes
)
5977 SwNode2Layout
aTmp(*pNode
, pNode
->GetIndex() - 1);
5978 SwFrame
* pFrame
= aTmp
.NextFrame();
5981 const SwRect
& rFrameRect
= pFrame
->getFrameArea();
5982 if (!rFrameRect
.IsEmpty())
5983 aRanges
.emplace_back(rFrameRect
.Left(), rFrameRect
.Top(), rFrameRect
.Right(),
5984 rFrameRect
.Bottom());
5985 if (!pFrame
->IsFlowFrame())
5987 SwFlowFrame
*pFollow
= SwFlowFrame::CastFlowFrame(pFrame
)->GetFollow();
5990 pFrame
= &pFollow
->GetFrame();
5993 OverlayObject(std::move(aRanges
));
5996 void SwContentTree::BringURLFieldsToAttention(const SwGetINetAttrs
& rINetAttrsArr
)
5998 std::vector
<basegfx::B2DRange
> aRanges
;
5999 for (const auto& r
: rINetAttrsArr
)
6001 const SwTextNode
& rTextNode
= r
.rINetAttr
.GetTextNode();
6002 if (SwTextFrame
* pFrame
= static_cast<SwTextFrame
*>(
6003 rTextNode
.getLayoutFrame(m_pActiveShell
->GetLayout())))
6005 auto nStart
= r
.rINetAttr
.GetStart();
6006 auto nEnd
= r
.rINetAttr
.GetAnyEnd();
6007 SwPosition
aStartPos(rTextNode
, nStart
), aEndPos(rTextNode
, nEnd
);
6008 lcl_CalcOverlayRanges(pFrame
, pFrame
, aStartPos
, aEndPos
, aRanges
);
6011 OverlayObject(std::move(aRanges
));
6014 void SwContentTree::BringReferencesToAttention(std::vector
<const SwTextAttr
*>& rTextAttrsArr
)
6016 std::vector
<basegfx::B2DRange
> aRanges
;
6017 for (const SwTextAttr
* p
: rTextAttrsArr
)
6021 const SwTextRefMark
* pTextRefMark
= p
->GetRefMark().GetTextRefMark();
6024 const SwTextNode
& rTextNode
= pTextRefMark
->GetTextNode();
6025 if (SwTextFrame
* pFrame
= static_cast<SwTextFrame
*>(
6026 rTextNode
.getLayoutFrame(m_pActiveShell
->GetLayout())))
6028 auto nStart
= p
->GetStart();
6029 auto nEnd
= p
->GetAnyEnd();
6030 SwPosition
aStartPos(rTextNode
, nStart
), aEndPos(rTextNode
, nEnd
);
6031 lcl_CalcOverlayRanges(pFrame
, pFrame
, aStartPos
, aEndPos
, aRanges
);
6034 OverlayObject(std::move(aRanges
));
6037 void SwContentTree::BringPostItFieldsToAttention(std::vector
<const SwTextAttr
*>& rTextAttrsArr
)
6039 std::vector
<basegfx::B2DRange
> aRanges
;
6040 for (const SwTextAttr
* p
: rTextAttrsArr
)
6044 const SwTextField
* pTextField
= p
->GetFormatField().GetTextField();
6047 // use as a fallback when there is no mark
6048 SwTextNode
& rTextNode
= pTextField
->GetTextNode();
6049 if (!rTextNode
.getLayoutFrame(m_pActiveShell
->GetLayout()))
6051 assert(dynamic_cast<const SwTextAnnotationField
*>(pTextField
));
6052 const SwTextAnnotationField
* pTextAnnotationField
=
6053 static_cast<const SwTextAnnotationField
*>(pTextField
);
6054 const ::sw::mark::IMark
* pAnnotationMark
= pTextAnnotationField
->GetAnnotationMark();
6055 const SwPosition aMarkStart
= pAnnotationMark
? pAnnotationMark
->GetMarkStart()
6056 : SwPosition(rTextNode
, p
->GetStart());
6057 const SwPosition aMarkEnd
= pAnnotationMark
? pAnnotationMark
->GetMarkEnd()
6058 : SwPosition(rTextNode
, p
->GetAnyEnd());
6059 const SwTextFrame
* pMarkStartFrame
= static_cast<SwTextFrame
*>(
6060 aMarkStart
.GetNode().GetTextNode()->getLayoutFrame(m_pActiveShell
->GetLayout()));
6061 const SwTextFrame
* pMarkEndFrame
= static_cast<SwTextFrame
*>(
6062 aMarkEnd
.GetNode().GetTextNode()->getLayoutFrame(m_pActiveShell
->GetLayout()));
6063 if (!pMarkStartFrame
|| !pMarkEndFrame
)
6065 lcl_CalcOverlayRanges(pMarkStartFrame
, pMarkEndFrame
, aMarkStart
,
6068 OverlayObject(std::move(aRanges
));
6071 void SwContentTree::BringFootnotesToAttention(std::vector
<const SwTextAttr
*>& rTextAttrsArr
)
6073 std::vector
<basegfx::B2DRange
> aRanges
;
6074 for (const SwTextAttr
* p
: rTextAttrsArr
)
6078 const SwTextFootnote
* pTextFootnote
= p
->GetFootnote().GetTextFootnote();
6081 const SwTextNode
& rTextNode
= pTextFootnote
->GetTextNode();
6082 if (SwTextFrame
* pFrame
= static_cast<SwTextFrame
*>(
6083 rTextNode
.getLayoutFrame(m_pActiveShell
->GetLayout())))
6085 auto nStart
= p
->GetStart();
6086 auto nEnd
= nStart
+ 1;
6087 SwPosition
aStartPos(rTextNode
, nStart
), aEndPos(rTextNode
, nEnd
);
6088 lcl_CalcOverlayRanges(pFrame
, pFrame
, aStartPos
, aEndPos
, aRanges
);
6091 OverlayObject(std::move(aRanges
));
6094 void SwContentTree::BringDrawingObjectsToAttention(std::vector
<const SdrObject
*>& rDrawingObjectsArr
)
6096 std::vector
<basegfx::B2DRange
> aRanges
;
6097 for (const SdrObject
* pObject
: rDrawingObjectsArr
)
6101 tools::Rectangle
aRect(pObject
->GetLogicRect());
6102 if (!aRect
.IsEmpty())
6103 aRanges
.emplace_back(aRect
.Left(), aRect
.Top(), aRect
.Right(), aRect
.Bottom());
6106 OverlayObject(std::move(aRanges
));
6109 void SwContentTree::BringTextFieldsToAttention(std::vector
<const SwTextAttr
*>& rTextAttrsArr
)
6111 std::vector
<basegfx::B2DRange
> aRanges
;
6112 std::shared_ptr
<SwPaM
> pPamForTextField
;
6113 for (const SwTextAttr
* p
: rTextAttrsArr
)
6117 const SwTextField
* pTextField
= p
->GetFormatField().GetTextField();
6120 if (SwTextFrame
* pFrame
= static_cast<SwTextFrame
*>(
6121 pTextField
->GetTextNode().getLayoutFrame(m_pActiveShell
->GetLayout())))
6123 SwTextField::GetPamForTextField(*pTextField
, pPamForTextField
);
6124 if (!pPamForTextField
)
6126 SwPosition
aStartPos(*pPamForTextField
->GetMark());
6127 SwPosition
aEndPos(*pPamForTextField
->GetPoint());
6128 lcl_CalcOverlayRanges(pFrame
, pFrame
, aStartPos
, aEndPos
, aRanges
);
6131 OverlayObject(std::move(aRanges
));
6134 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */