LibreOffice Module sw (master)  1
content.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <comphelper/string.hxx>
21 #include <svl/urlbmk.hxx>
22 #include <osl/thread.h>
23 #include <sal/log.hxx>
24 #include <tools/urlobj.hxx>
25 #include <sfx2/docfile.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/event.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <o3tl/enumrange.hxx>
30 #include <o3tl/sorted_vector.hxx>
31 #include <vcl/commandevent.hxx>
32 #include <vcl/weldutils.hxx>
33 #include <sot/formats.hxx>
34 #include <uiitems.hxx>
35 #include <fmtinfmt.hxx>
36 #include <txtinet.hxx>
37 #include <fmtfld.hxx>
38 #include <swmodule.hxx>
39 #include <wrtsh.hxx>
40 #include <view.hxx>
41 #include <docsh.hxx>
42 #include <drawdoc.hxx>
43 #include <content.hxx>
44 #include <frmfmt.hxx>
45 #include <fldbas.hxx>
46 #include <IMark.hxx>
47 #include <section.hxx>
48 #include <tox.hxx>
49 #include <navipi.hxx>
50 #include <navicont.hxx>
51 #include <navicfg.hxx>
52 #include <edtwin.hxx>
53 #include <doc.hxx>
57 #include <unotxvw.hxx>
58 #include <cmdid.h>
59 #include <helpids.h>
60 #include <strings.hrc>
61 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
62 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
63 #include <com/sun/star/text/XTextTablesSupplier.hpp>
64 #include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
65 #include <com/sun/star/text/XDocumentIndex.hpp>
66 #include <com/sun/star/text/XBookmarksSupplier.hpp>
67 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
68 #include <com/sun/star/text/XTextFramesSupplier.hpp>
69 #include <dcontact.hxx>
70 #include <svx/svdpage.hxx>
71 #include <svx/svdview.hxx>
72 #include <SwRewriter.hxx>
73 #include <hints.hxx>
74 #include <numrule.hxx>
75 #include <swundo.hxx>
76 #include <ndtxt.hxx>
77 #include <PostItMgr.hxx>
78 #include <postithelper.hxx>
79 
80 #include <swabstdlg.hxx>
81 #include <bitmaps.hlst>
82 
83 #include <navmgr.hxx>
84 #include <AnnotationWin.hxx>
85 #include <memory>
86 
87 #include <fmtcntnt.hxx>
88 #include <docstat.hxx>
89 
90 #include <viewopt.hxx>
91 
92 #define CTYPE_CNT 0
93 #define CTYPE_CTT 1
94 
95 using namespace ::std;
96 using namespace ::com::sun::star;
97 using namespace ::com::sun::star::text;
98 using namespace ::com::sun::star::uno;
99 using namespace ::com::sun::star::container;
100 
101 namespace {
102 
103 constexpr char NAVI_BOOKMARK_DELIM = '\x01';
104 
105 }
106 
108  : public o3tl::sorted_vector<std::unique_ptr<SwContent>, o3tl::less_uniqueptr_to<SwContent>,
109  o3tl::find_partialorder_ptrequals>
110 {
111 };
112 
113 namespace
114 {
115  bool lcl_IsContent(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView)
116  {
117  return reinterpret_cast<const SwTypeNumber*>(rTreeView.get_id(rEntry).toInt64())->GetTypeId() == CTYPE_CNT;
118  }
119 
120  bool lcl_IsContentType(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView)
121  {
122  return reinterpret_cast<const SwTypeNumber*>(rTreeView.get_id(rEntry).toInt64())->GetTypeId() == CTYPE_CTT;
123  }
124 
125  bool lcl_FindShell(SwWrtShell const * pShell)
126  {
127  bool bFound = false;
128  SwView *pView = SwModule::GetFirstView();
129  while (pView)
130  {
131  if(pShell == &pView->GetWrtShell())
132  {
133  bFound = true;
134  break;
135  }
136  pView = SwModule::GetNextView(pView);
137  }
138  return bFound;
139  }
140 
141  bool lcl_IsUiVisibleBookmark(const ::sw::mark::IMark* pMark)
142  {
144  }
145 
146  size_t lcl_InsertURLFieldContent(
147  SwContentArr *pMember,
148  SwWrtShell* pWrtShell,
149  const SwContentType *pCntType)
150  {
152  pWrtShell->GetINetAttrs( aArr );
153  const SwGetINetAttrs::size_type nCount {aArr.size()};
154  for( SwGetINetAttrs::size_type n = 0; n < nCount; ++n )
155  {
156  SwGetINetAttr* p = &aArr[ n ];
157  std::unique_ptr<SwURLFieldContent> pCnt(new SwURLFieldContent(
158  pCntType,
159  p->sText,
163  &p->rINetAttr,
164  n ));
165  pMember->insert( std::move(pCnt) );
166  }
167  return nCount;
168  }
169 }
170 
171 // Content, contains names and reference at the content type.
172 
173 SwContent::SwContent(const SwContentType* pCnt, const OUString& rName, tools::Long nYPos) :
175  pParent(pCnt),
176  sContentName(rName),
177  nYPosition(nYPos),
178  bInvisible(false)
179 {
180 }
181 
182 
184 {
185 }
186 
188 {
189  return false;
190 }
191 
193 {
194  return pField->IsProtect();
195 }
196 
198 {
199  return pINetAttr->IsProtect();
200 }
201 
203 {
204 }
205 
207 {
208 }
209 
210 static const char* STR_CONTENT_TYPE_ARY[] =
211 {
212  STR_CONTENT_TYPE_OUTLINE,
213  STR_CONTENT_TYPE_TABLE,
214  STR_CONTENT_TYPE_FRAME,
215  STR_CONTENT_TYPE_GRAPHIC,
216  STR_CONTENT_TYPE_OLE,
217  STR_CONTENT_TYPE_BOOKMARK,
218  STR_CONTENT_TYPE_REGION,
219  STR_CONTENT_TYPE_URLFIELD,
220  STR_CONTENT_TYPE_REFERENCE,
221  STR_CONTENT_TYPE_INDEX,
222  STR_CONTENT_TYPE_POSTIT,
223  STR_CONTENT_TYPE_DRAWOBJECT
224 };
225 
226 static const char* STR_CONTENT_TYPE_SINGLE_ARY[] =
227 {
228  STR_CONTENT_TYPE_SINGLE_OUTLINE,
229  STR_CONTENT_TYPE_SINGLE_TABLE,
230  STR_CONTENT_TYPE_SINGLE_FRAME,
231  STR_CONTENT_TYPE_SINGLE_GRAPHIC,
232  STR_CONTENT_TYPE_SINGLE_OLE,
233  STR_CONTENT_TYPE_SINGLE_BOOKMARK,
234  STR_CONTENT_TYPE_SINGLE_REGION,
235  STR_CONTENT_TYPE_SINGLE_URLFIELD,
236  STR_CONTENT_TYPE_SINGLE_REFERENCE,
237  STR_CONTENT_TYPE_SINGLE_INDEX,
238  STR_CONTENT_TYPE_SINGLE_POSTIT,
239  STR_CONTENT_TYPE_SINGLE_DRAWOBJECT
240 };
241 
242 namespace
243 {
244  bool checkVisibilityChanged(
245  const SwContentArr& rSwContentArrA,
246  const SwContentArr& rSwContentArrB)
247  {
248  if(rSwContentArrA.size() != rSwContentArrB.size())
249  {
250  return true;
251  }
252 
253  for(size_t a(0); a < rSwContentArrA.size(); a++)
254  {
255  if(rSwContentArrA[a]->IsInvisible() != rSwContentArrB[a]->IsInvisible())
256  {
257  return true;
258  }
259  }
260 
261  return false;
262  }
263 } // end of anonymous namespace
264 
267  m_pWrtShell(pShell),
268  m_sContentTypeName(SwResId(STR_CONTENT_TYPE_ARY[static_cast<int>(nType)])),
269  m_sSingleContentTypeName(SwResId(STR_CONTENT_TYPE_SINGLE_ARY[static_cast<int>(nType)])),
270  m_nMemberCount(0),
271  m_nContentType(nType),
272  m_nOutlineLevel(nLevel),
273  m_bDataValid(false),
274  m_bEdit(false),
275  m_bDelete(true)
276 {
277  Init();
278 }
279 
280 void SwContentType::Init(bool* pbInvalidateWindow)
281 {
282  // if the MemberCount is changing ...
283  size_t nOldMemberCount = m_nMemberCount;
284  m_nMemberCount = 0;
285  switch(m_nContentType)
286  {
288  {
289  m_sTypeToken = "outline";
291  if (m_nMemberCount < MAXLEVEL)
292  {
293  const size_t nOutlineCount = m_nMemberCount;
294  for(size_t j = 0; j < nOutlineCount; ++j)
295  {
298  {
299  m_nMemberCount --;
300  }
301  }
302  }
303  }
304  break;
305 
306  case ContentTypeId::TABLE :
307  m_sTypeToken = "table";
309  m_bEdit = true;
310  break;
311 
312  case ContentTypeId::FRAME :
314  case ContentTypeId::OLE :
315  {
317  m_sTypeToken = "frame";
319  {
320  eType = FLYCNTTYPE_OLE;
321  m_sTypeToken = "ole";
322  }
324  {
325  eType = FLYCNTTYPE_GRF;
326  m_sTypeToken = "graphic";
327  }
328  m_nMemberCount = m_pWrtShell->GetFlyCount(eType, /*bIgnoreTextBoxes=*/true);
329  m_bEdit = true;
330  }
331  break;
333  {
335  m_nMemberCount = count_if(
336  pMarkAccess->getBookmarksBegin(),
337  pMarkAccess->getBookmarksEnd(),
338  &lcl_IsUiVisibleBookmark);
339  m_sTypeToken.clear();
341  m_bEdit = !bProtectedBM;
342  m_bDelete = !bProtectedBM;
343  }
344  break;
345  case ContentTypeId::REGION :
346  {
347  std::unique_ptr<SwContentArr> pOldMember;
348  if(!m_pMember)
349  m_pMember.reset( new SwContentArr );
350  else if(!m_pMember->empty())
351  {
352  pOldMember = std::move(m_pMember);
353  m_pMember.reset( new SwContentArr );
354  }
355  const Point aNullPt;
357  for(size_t i = 0; i < m_nMemberCount; ++i)
358  {
359  const SwSectionFormat* pFormat;
360  SectionType eTmpType;
361  if( (pFormat = &m_pWrtShell->GetSectionFormat(i))->IsInNodesArr() &&
362  (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent
363  && SectionType::ToxHeader != eTmpType )
364  {
365  const OUString& rSectionName =
366  pFormat->GetSection()->GetSectionName();
367  sal_uInt8 nLevel = 0;
368  SwSectionFormat* pParentFormat = pFormat->GetParent();
369  while(pParentFormat)
370  {
371  nLevel++;
372  pParentFormat = pParentFormat->GetParent();
373  }
374 
375  std::unique_ptr<SwContent> pCnt(new SwRegionContent(this, rSectionName,
376  nLevel,
377  pFormat->FindLayoutRect( false, &aNullPt ).Top()));
378 
379  SwPtrMsgPoolItem aAskItem( RES_CONTENT_VISIBLE, nullptr );
380  if( !pFormat->GetInfo( aAskItem ) &&
381  !aAskItem.pObject ) // not visible
382  pCnt->SetInvisible();
383  m_pMember->insert(std::move(pCnt));
384  }
385  }
386  m_nMemberCount = m_pMember->size();
387  m_sTypeToken = "region";
388  m_bEdit = true;
389  m_bDelete = false;
390  if(pOldMember)
391  {
392  if(nullptr != pbInvalidateWindow)
393  {
394  // need to check visibility (and equal entry number) after
395  // creation due to a sorted list being used here (before,
396  // entries with same index were compared already at creation
397  // time what worked before a sorted list was used)
398  *pbInvalidateWindow = checkVisibilityChanged(
399  *pOldMember,
400  *m_pMember);
401  }
402  }
403  }
404  break;
406  {
408  m_bEdit = true;
409  m_bDelete = false;
410  }
411  break;
413  {
415  m_bDelete = false;
416  }
417  break;
419  {
420  m_nMemberCount = 0;
421  if(!m_pMember)
422  m_pMember.reset( new SwContentArr );
423  else
424  m_pMember->clear();
425 
426  m_nMemberCount = lcl_InsertURLFieldContent(m_pMember.get(), m_pWrtShell, this);
427 
428  m_bEdit = true;
429  nOldMemberCount = m_nMemberCount;
430  m_bDelete = true;
431  }
432  break;
434  {
435  m_nMemberCount = 0;
436  if(!m_pMember)
437  m_pMember.reset( new SwContentArr );
438  else
439  m_pMember->clear();
440 
442  if (aMgr)
443  {
444  for(SwPostItMgr::const_iterator i = aMgr->begin(); i != aMgr->end(); ++i)
445  {
446  if (const SwFormatField* pFormatField = dynamic_cast<const SwFormatField *>((*i)->GetBroadcaster())) // SwPostit
447  {
448  if (pFormatField->GetTextField() && pFormatField->IsFieldInDoc() &&
449  (*i)->mLayoutStatus!=SwPostItHelper::INVISIBLE )
450  {
451  OUString sEntry = pFormatField->GetField()->GetPar2();
452  sEntry = RemoveNewline(sEntry);
453  std::unique_ptr<SwPostItContent> pCnt(new SwPostItContent(
454  this,
455  sEntry,
456  pFormatField,
457  m_nMemberCount));
458  m_pMember->insert(std::move(pCnt));
459  m_nMemberCount++;
460  }
461  }
462  }
463  }
464  m_sTypeToken.clear();
465  m_bEdit = true;
466  nOldMemberCount = m_nMemberCount;
467  }
468  break;
470  {
471  m_sTypeToken.clear();
472  m_bEdit = true;
473  m_nMemberCount = 0;
475  if(pModel)
476  {
477  SdrPage* pPage = pModel->GetPage(0);
478  const size_t nCount = pPage->GetObjCount();
479  for( size_t i=0; i<nCount; ++i )
480  {
481  SdrObject* pTemp = pPage->GetObj(i);
482  // #i51726# - all drawing objects can be named now
483  if (!pTemp->GetName().isEmpty())
484  m_nMemberCount++;
485  }
486  }
487  }
488  break;
489  default: break;
490  }
491  // ... then, the data can also no longer be valid,
492  // apart from those which have already been corrected,
493  // then nOldMemberCount is nevertheless not so old.
494  if( nOldMemberCount != m_nMemberCount )
495  m_bDataValid = false;
496 }
497 
499 {
500 }
501 
502 const SwContent* SwContentType::GetMember(size_t nIndex)
503 {
504  if(!m_bDataValid || !m_pMember)
505  {
506  FillMemberList();
507  }
508  if(nIndex < m_pMember->size())
509  return (*m_pMember)[nIndex].get();
510 
511  return nullptr;
512 }
513 
515 {
516  m_bDataValid = false;
517 }
518 
519 void SwContentType::FillMemberList(bool* pbLevelOrVisibilityChanged)
520 {
521  std::unique_ptr<SwContentArr> pOldMember;
522  size_t nOldMemberCount = 0;
523  SwPtrMsgPoolItem aAskItem( RES_CONTENT_VISIBLE, nullptr );
524  if(m_pMember && pbLevelOrVisibilityChanged)
525  {
526  pOldMember = std::move(m_pMember);
527  nOldMemberCount = pOldMember->size();
528  m_pMember.reset( new SwContentArr );
529  *pbLevelOrVisibilityChanged = false;
530  }
531  else if(!m_pMember)
532  m_pMember.reset( new SwContentArr );
533  else
534  m_pMember->clear();
535  switch(m_nContentType)
536  {
538  {
539  const size_t nOutlineCount = m_nMemberCount =
541 
542  size_t nPos = 0;
543  for (size_t i = 0; i < nOutlineCount; ++i)
544  {
546  if(nLevel >= m_nOutlineLevel )
547  m_nMemberCount--;
548  else
549  {
551  {
552  --m_nMemberCount;
553  continue; // don't hide it, just skip it
554  }
555  OUString aEntry(comphelper::string::stripStart(
557  aEntry = SwNavigationPI::CleanEntry(aEntry);
558  std::unique_ptr<SwOutlineContent> pCnt(new SwOutlineContent(this, aEntry, i, nLevel,
559  m_pWrtShell->IsOutlineMovable( i ), nPos ));
560  m_pMember->insert(std::move(pCnt));
561  // with the same number and existing "pOldMember" the
562  // old one is compared with the new OutlinePos.
563  if (nOldMemberCount > nPos && static_cast<SwOutlineContent*>((*pOldMember)[nPos].get())->GetOutlineLevel() != nLevel)
564  *pbLevelOrVisibilityChanged = true;
565 
566  nPos++;
567  }
568  }
569 
570  }
571  break;
572  case ContentTypeId::TABLE :
573  {
574  const size_t nCount = m_pWrtShell->GetTableFrameFormatCount(true);
575  OSL_ENSURE(m_nMemberCount == nCount, "MemberCount differs");
576  Point aNullPt;
577  m_nMemberCount = nCount;
578  for(size_t i = 0; i < m_nMemberCount; ++i)
579  {
580  const SwFrameFormat& rTableFormat = m_pWrtShell->GetTableFrameFormat(i, true);
581  const OUString& sTableName( rTableFormat.GetName() );
582 
583  SwContent* pCnt = new SwContent(this, sTableName,
584  rTableFormat.FindLayoutRect(false, &aNullPt).Top() );
585  if( !rTableFormat.GetInfo( aAskItem ) &&
586  !aAskItem.pObject ) // not visible
587  pCnt->SetInvisible();
588 
589  m_pMember->insert(std::unique_ptr<SwContent>(pCnt));
590  }
591 
592  if (nullptr != pbLevelOrVisibilityChanged)
593  {
594  assert(pOldMember);
595  // need to check visibility (and equal entry number) after
596  // creation due to a sorted list being used here (before,
597  // entries with same index were compared already at creation
598  // time what worked before a sorted list was used)
599  *pbLevelOrVisibilityChanged = checkVisibilityChanged(
600  *pOldMember,
601  *m_pMember);
602  }
603  }
604  break;
605  case ContentTypeId::OLE :
606  case ContentTypeId::FRAME :
608  {
611  eType = FLYCNTTYPE_OLE;
613  eType = FLYCNTTYPE_GRF;
614  Point aNullPt;
615  m_nMemberCount = m_pWrtShell->GetFlyCount(eType, /*bIgnoreTextBoxes=*/true);
616  std::vector<SwFrameFormat const*> formats(m_pWrtShell->GetFlyFrameFormats(eType, /*bIgnoreTextBoxes=*/true));
617  SAL_WARN_IF(m_nMemberCount != formats.size(), "sw.ui", "MemberCount differs");
618  m_nMemberCount = formats.size();
619  for (size_t i = 0; i < m_nMemberCount; ++i)
620  {
621  SwFrameFormat const*const pFrameFormat = formats[i];
622  const OUString sFrameName = pFrameFormat->GetName();
623 
624  SwContent* pCnt;
626  {
627  OUString sLink;
628  m_pWrtShell->GetGrfNms( &sLink, nullptr, static_cast<const SwFlyFrameFormat*>( pFrameFormat));
629  pCnt = new SwGraphicContent(this, sFrameName,
630  INetURLObject::decode( sLink,
632  pFrameFormat->FindLayoutRect(false, &aNullPt).Top());
633  }
634  else
635  {
636  pCnt = new SwContent(this, sFrameName,
637  pFrameFormat->FindLayoutRect(false, &aNullPt).Top() );
638  }
639  if( !pFrameFormat->GetInfo( aAskItem ) &&
640  !aAskItem.pObject ) // not visible
641  pCnt->SetInvisible();
642  m_pMember->insert(std::unique_ptr<SwContent>(pCnt));
643  }
644 
645  if(nullptr != pbLevelOrVisibilityChanged)
646  {
647  assert(pOldMember);
648  // need to check visibility (and equal entry number) after
649  // creation due to a sorted list being used here (before,
650  // entries with same index were compared already at creation
651  // time what worked before a sorted list was used)
652  *pbLevelOrVisibilityChanged = checkVisibilityChanged(
653  *pOldMember,
654  *m_pMember);
655  }
656  }
657  break;
659  {
661  for(IDocumentMarkAccess::const_iterator_t ppBookmark = pMarkAccess->getBookmarksBegin();
662  ppBookmark != pMarkAccess->getBookmarksEnd();
663  ++ppBookmark)
664  {
665  if(lcl_IsUiVisibleBookmark(*ppBookmark))
666  {
667  const OUString& rBkmName = (*ppBookmark)->GetName();
668  //nYPos from 0 -> text::Bookmarks will be sorted alphabetically
669  std::unique_ptr<SwContent> pCnt(new SwContent(this, rBkmName, 0));
670  m_pMember->insert(std::move(pCnt));
671  }
672  }
673  }
674  break;
675  case ContentTypeId::REGION :
676  {
677  const Point aNullPt;
679  for(size_t i = 0; i < m_nMemberCount; ++i)
680  {
681  const SwSectionFormat* pFormat;
682  SectionType eTmpType;
683  if( (pFormat = &m_pWrtShell->GetSectionFormat(i))->IsInNodesArr() &&
684  (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent
685  && SectionType::ToxHeader != eTmpType )
686  {
687  OUString sSectionName = pFormat->GetSection()->GetSectionName();
688 
689  sal_uInt8 nLevel = 0;
690  SwSectionFormat* pParentFormat = pFormat->GetParent();
691  while(pParentFormat)
692  {
693  nLevel++;
694  pParentFormat = pParentFormat->GetParent();
695  }
696 
697  std::unique_ptr<SwContent> pCnt(new SwRegionContent(this, sSectionName,
698  nLevel,
699  pFormat->FindLayoutRect( false, &aNullPt ).Top()));
700  if( !pFormat->GetInfo( aAskItem ) &&
701  !aAskItem.pObject ) // not visible
702  pCnt->SetInvisible();
703  m_pMember->insert(std::move(pCnt));
704  }
705 
706  if(nullptr != pbLevelOrVisibilityChanged)
707  {
708  assert(pOldMember);
709  // need to check visibility (and equal entry number) after
710  // creation due to a sorted list being used here (before,
711  // entries with same index were compared already at creation
712  // time what worked before a sorted list was used)
713  *pbLevelOrVisibilityChanged = checkVisibilityChanged(
714  *pOldMember,
715  *m_pMember);
716  }
717  }
718  m_nMemberCount = m_pMember->size();
719  }
720  break;
722  {
723  std::vector<OUString> aRefMarks;
724  m_nMemberCount = m_pWrtShell->GetRefMarks( &aRefMarks );
725 
726  for (const auto& rRefMark : aRefMarks)
727  {
728  // References sorted alphabetically
729  m_pMember->insert(std::make_unique<SwContent>(this, rRefMark, 0));
730  }
731  }
732  break;
734  m_nMemberCount = lcl_InsertURLFieldContent(m_pMember.get(), m_pWrtShell, this);
735  break;
737  {
738 
739  const sal_uInt16 nCount = m_pWrtShell->GetTOXCount();
740  m_nMemberCount = nCount;
741  for ( sal_uInt16 nTox = 0; nTox < nCount; nTox++ )
742  {
743  const SwTOXBase* pBase = m_pWrtShell->GetTOX( nTox );
744  OUString sTOXNm( pBase->GetTOXName() );
745 
746  SwContent* pCnt = new SwTOXBaseContent(
747  this, sTOXNm, nTox, *pBase);
748 
749  if(pBase && !pBase->IsVisible())
750  pCnt->SetInvisible();
751 
752  m_pMember->insert( std::unique_ptr<SwContent>(pCnt) );
753  const size_t nPos = m_pMember->size() - 1;
754  if(nOldMemberCount > nPos &&
755  (*pOldMember)[nPos]->IsInvisible()
756  != pCnt->IsInvisible())
757  *pbLevelOrVisibilityChanged = true;
758  }
759  }
760  break;
762  {
763  m_nMemberCount = 0;
764  m_pMember->clear();
766  if (aMgr)
767  {
768  for(SwPostItMgr::const_iterator i = aMgr->begin(); i != aMgr->end(); ++i)
769  {
770  if (const SwFormatField* pFormatField = dynamic_cast<const SwFormatField *>((*i)->GetBroadcaster())) // SwPostit
771  {
772  if (pFormatField->GetTextField() && pFormatField->IsFieldInDoc() &&
773  (*i)->mLayoutStatus!=SwPostItHelper::INVISIBLE )
774  {
775  OUString sEntry = pFormatField->GetField()->GetPar2();
776  sEntry = RemoveNewline(sEntry);
777  std::unique_ptr<SwPostItContent> pCnt(new SwPostItContent(
778  this,
779  sEntry,
780  pFormatField,
781  m_nMemberCount));
782  m_pMember->insert(std::move(pCnt));
783  m_nMemberCount++;
784  }
785  }
786  }
787  }
788  }
789  break;
791  {
792  m_nMemberCount = 0;
793  m_pMember->clear();
794 
796  SwDrawModel* pModel = rIDDMA.GetDrawModel();
797  if(pModel)
798  {
799  SdrPage* pPage = pModel->GetPage(0);
800  const size_t nCount = pPage->GetObjCount();
801  for( size_t i=0; i<nCount; ++i )
802  {
803  SdrObject* pTemp = pPage->GetObj(i);
804  // #i51726# - all drawing objects can be named now
805  if (!pTemp->GetName().isEmpty())
806  {
807  SwContact* pContact = static_cast<SwContact*>(pTemp->GetUserCall());
808  tools::Long nYPos = 0;
809  const Point aNullPt;
810  if(pContact && pContact->GetFormat())
811  nYPos = pContact->GetFormat()->FindLayoutRect(false, &aNullPt).Top();
812  SwContent* pCnt = new SwContent(
813  this,
814  pTemp->GetName(),
815  nYPos);
816  if(!rIDDMA.IsVisibleLayerId(pTemp->GetLayer()))
817  pCnt->SetInvisible();
818  m_pMember->insert(std::unique_ptr<SwContent>(pCnt));
819  m_nMemberCount++;
820  }
821  }
822 
823  if (nullptr != pbLevelOrVisibilityChanged)
824  {
825  assert(pOldMember);
826  // need to check visibility (and equal entry number) after
827  // creation due to a sorted list being used here (before,
828  // entries with same index were compared already at creation
829  // time what worked before a sorted list was used)
830  *pbLevelOrVisibilityChanged = checkVisibilityChanged(
831  *pOldMember,
832  *m_pMember);
833  }
834  }
835  }
836  break;
837  default: break;
838  }
839  m_bDataValid = true;
840 }
841 
842 namespace {
843 
845 {
846  IDX_STR_OUTLINE_LEVEL = 0,
847  IDX_STR_DRAGMODE = 1,
848  IDX_STR_HYPERLINK = 2,
849  IDX_STR_LINK_REGION = 3,
850  IDX_STR_COPY_REGION = 4,
851  IDX_STR_DISPLAY = 5,
852  IDX_STR_ACTIVE_VIEW = 6,
853  IDX_STR_HIDDEN = 7,
854  IDX_STR_ACTIVE = 8,
855  IDX_STR_INACTIVE = 9,
856  IDX_STR_EDIT_ENTRY = 10,
857  IDX_STR_DELETE_ENTRY = 11,
858  IDX_STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY = 12,
859  IDX_STR_OUTLINE_TRACKING = 13,
860  IDX_STR_OUTLINE_TRACKING_DEFAULT = 14,
861  IDX_STR_OUTLINE_TRACKING_FOCUS = 15,
862  IDX_STR_OUTLINE_TRACKING_OFF = 16
863 };
864 
865 }
866 
867 static const char* STR_CONTEXT_ARY[] =
868 {
869  STR_OUTLINE_LEVEL,
870  STR_DRAGMODE,
871  STR_HYPERLINK,
872  STR_LINK_REGION,
873  STR_COPY_REGION,
874  STR_DISPLAY,
875  STR_ACTIVE_VIEW,
876  STR_HIDDEN,
877  STR_ACTIVE,
878  STR_INACTIVE,
879  STR_EDIT_ENTRY,
880  STR_DELETE_ENTRY,
881  STR_SEND_OUTLINE_TO_CLIPBOARD_ENTRY,
882  STR_OUTLINE_TRACKING,
883  STR_OUTLINE_TRACKING_DEFAULT,
884  STR_OUTLINE_TRACKING_FOCUS,
885  STR_OUTLINE_TRACKING_OFF
886 };
887 
888 SwContentTree::SwContentTree(std::unique_ptr<weld::TreeView> xTreeView, SwNavigationPI* pDialog)
889  : m_xTreeView(std::move(xTreeView))
890  , m_xScratchIter(m_xTreeView->make_iterator())
891  , m_aDropTargetHelper(*this)
892  , m_xDialog(pDialog)
893  , m_sSpace(OUString(" "))
894  , m_sInvisible(SwResId(STR_INVISIBLE))
895  , m_pHiddenShell(nullptr)
896  , m_pActiveShell(nullptr)
897  , m_pConfig(SW_MOD()->GetNavigationConfig())
898  , m_nActiveBlock(0)
899  , m_nHiddenBlock(0)
900  , m_nEntryCount(0)
901  , m_nRootType(ContentTypeId::UNKNOWN)
902  , m_nLastSelType(ContentTypeId::UNKNOWN)
903  , m_nOutlineLevel(MAXLEVEL)
904  , m_eState(State::ACTIVE)
905  , m_bIsRoot(false)
906  , m_bIsIdleClear(false)
907  , m_bIsLastReadOnly(false)
908  , m_bIsOutlineMoveable(true)
909  , m_bViewHasChanged(false)
910 {
911  Size aSize(m_xDialog->LogicToPixel(Size(110, 112), MapMode(MapUnit::MapAppFont)));
912  m_xTreeView->set_size_request(aSize.Width(), aSize.Height());
913 
914  m_xTreeView->set_help_id(HID_NAVIGATOR_TREELIST);
915 
916  m_xTreeView->connect_expanding(LINK(this, SwContentTree, ExpandHdl));
917  m_xTreeView->connect_collapsing(LINK(this, SwContentTree, CollapseHdl));
918  m_xTreeView->connect_row_activated(LINK(this, SwContentTree, ContentDoubleClickHdl));
919  m_xTreeView->connect_changed(LINK(this, SwContentTree, SelectHdl));
920  m_xTreeView->connect_focus_in(LINK(this, SwContentTree, FocusHdl));
921  m_xTreeView->connect_key_press(LINK(this, SwContentTree, KeyInputHdl));
922  m_xTreeView->connect_popup_menu(LINK(this, SwContentTree, CommandHdl));
923  m_xTreeView->connect_query_tooltip(LINK(this, SwContentTree, QueryTooltipHdl));
924  m_xTreeView->connect_drag_begin(LINK(this, SwContentTree, DragBeginHdl));
925 
927  {
928  m_aActiveContentArr[i] = nullptr;
929  m_aHiddenContentArr[i] = nullptr;
930  }
931  for (int i = 0; i < CONTEXT_COUNT; ++i)
932  {
933  m_aContextStrings[i] = SwResId(STR_CONTEXT_ARY[i]);
934  }
936  m_aUpdTimer.SetInvokeHandler(LINK(this, SwContentTree, TimerUpdate));
937  m_aUpdTimer.SetTimeout(1000);
938 }
939 
941 {
942  clear(); // If applicable erase content types previously.
943  m_aUpdTimer.Stop();
944  SetActiveShell(nullptr);
945  m_xDialog.clear();
946 }
947 
948 // Drag&Drop methods
949 IMPL_LINK(SwContentTree, DragBeginHdl, bool&, rUnsetDragIcon, bool)
950 {
951  rUnsetDragIcon = true;
952 
953  bool bDisallow = true;
954 
955  // don't allow if tree root is selected
956  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
957  bool bEntry = m_xTreeView->get_selected(xEntry.get());
958  if (!bEntry || lcl_IsContentType(*xEntry, *m_xTreeView))
959  {
960  return true; // disallow
961  }
962 
965 
966  if (FillTransferData(*xContainer, nDragMode))
967  bDisallow = false;
968 
969  if (m_bIsRoot && m_nRootType == ContentTypeId::OUTLINE)
970  {
971  // Only move drag entry and continuous selected siblings:
972  m_aDndOutlinesSelected.clear();
973 
974  std::unique_ptr<weld::TreeIter> xScratch(m_xTreeView->make_iterator());
975 
976  // Find first selected of continuous siblings
977  while (true)
978  {
979  m_xTreeView->copy_iterator(*xEntry, *xScratch);
980  if (!m_xTreeView->iter_previous_sibling(*xScratch))
981  break;
982  if (!m_xTreeView->is_selected(*xScratch))
983  break;
984  m_xTreeView->copy_iterator(*xScratch, *xEntry);
985  }
986  // Record continuous selected siblings
987  do
988  {
989  m_aDndOutlinesSelected.push_back(m_xTreeView->make_iterator(xEntry.get()));
990  }
991  while (m_xTreeView->iter_next_sibling(*xEntry) && m_xTreeView->is_selected(*xEntry));
992  bDisallow = false;
993  }
994 
995  if (!bDisallow)
996  m_xTreeView->enable_drag_source(xContainer, nDragMode);
997  return bDisallow;
998 }
999 
1001  : DropTargetHelper(rTreeView.get_widget().get_drop_target())
1002  , m_rTreeView(rTreeView)
1003 {
1004 }
1005 
1007 {
1008  sal_Int8 nAccept = m_rTreeView.AcceptDrop(rEvt);
1009 
1010  if (nAccept != DND_ACTION_NONE)
1011  {
1012  // to enable the autoscroll when we're close to the edges
1013  weld::TreeView& rWidget = m_rTreeView.get_widget();
1014  rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr, true);
1015  }
1016 
1017  return nAccept;
1018 }
1019 
1021 {
1022  return m_xTreeView->get_drag_source() == m_xTreeView.get();
1023 }
1024 
1025 // QueryDrop will be executed in the navigator
1027 {
1028  sal_Int8 nRet = DND_ACTION_NONE;
1029  if( m_bIsRoot )
1030  {
1031  if( m_bIsOutlineMoveable )
1032  nRet = rEvt.mnAction;
1033  }
1034  else if (!IsInDrag())
1035  nRet = GetParentWindow()->AcceptDrop();
1036  return nRet;
1037 }
1038 
1039 // Drop will be executed in the navigator
1040 static void* lcl_GetOutlineKey(SwContentTree& rTree, SwOutlineContent const * pContent)
1041 {
1042  void* key = nullptr;
1043  if (pContent)
1044  {
1045  SwWrtShell* pShell = rTree.GetWrtShell();
1046  auto const nPos = pContent->GetOutlinePos();
1047 
1048  key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
1049  }
1050  return key;
1051 }
1052 
1054 {
1055  return m_rTreeView.ExecuteDrop(rEvt);
1056 }
1057 
1059 {
1060  std::unique_ptr<weld::TreeIter> xDropEntry(m_xTreeView->make_iterator());
1061  if (!m_xTreeView->get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get(), true))
1062  xDropEntry.reset();
1063 
1065  {
1066  if (xDropEntry && lcl_IsContent(*xDropEntry, *m_xTreeView))
1067  {
1068  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xDropEntry).toInt64())));
1069  SwOutlineContent* pOutlineContent = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xDropEntry).toInt64());
1070  assert(pOutlineContent);
1071 
1072  void* key = lcl_GetOutlineKey(*this, pOutlineContent);
1073  assert(key);
1074  if (!mOutLineNodeMap[key])
1075  {
1076  while (m_xTreeView->iter_has_child(*xDropEntry))
1077  {
1078  std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator(xDropEntry.get()));
1079  bool bChildEntry = m_xTreeView->iter_children(*xChildEntry);
1080  while (bChildEntry)
1081  {
1082  m_xTreeView->copy_iterator(*xChildEntry, *xDropEntry);
1083  bChildEntry = m_xTreeView->iter_next_sibling(*xChildEntry);
1084  }
1085  }
1086  }
1087  }
1088 
1089  SwOutlineNodes::size_type nTargetPos = 0;
1090  if (!xDropEntry)
1091  {
1092  // dropped in blank space -> move to bottom
1094  }
1095  else if (!lcl_IsContent(*xDropEntry, *m_xTreeView))
1096  {
1097  // dropped on "heading" parent -> move to start
1098  nTargetPos = SwOutlineNodes::npos;
1099  }
1100  else
1101  {
1102  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xDropEntry).toInt64())));
1103  nTargetPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xDropEntry).toInt64())->GetOutlinePos();
1104  }
1105 
1106  if( MAXLEVEL > m_nOutlineLevel && // Not all layers are displayed.
1107  nTargetPos != SwOutlineNodes::npos)
1108  {
1109  std::unique_ptr<weld::TreeIter> xNext(m_xTreeView->make_iterator(xDropEntry.get()));
1110  bool bNext = m_xTreeView->iter_next(*xNext);
1111  if (bNext)
1112  {
1113  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xNext).toInt64())));
1114  nTargetPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xNext).toInt64())->GetOutlinePos() - 1;
1115  }
1116  else
1118  }
1119 
1120  // remove the drop highlight before we change the contents of the tree so we don't
1121  // try and dereference a removed entry in post-processing drop
1122  m_xTreeView->unset_drag_dest_row();
1123  MoveOutline(nTargetPos);
1124 
1125  }
1126  return IsInDrag() ? DND_ACTION_NONE : GetParentWindow()->ExecuteDrop(rEvt);
1127 }
1128 
1129 namespace
1130 {
1131  bool IsAllExpanded(const weld::TreeView& rContentTree, const weld::TreeIter& rEntry)
1132  {
1133  if (!rContentTree.get_row_expanded(rEntry))
1134  return false;
1135 
1136  if (!rContentTree.iter_has_child(rEntry))
1137  return false;
1138 
1139  std::unique_ptr<weld::TreeIter> xChild(rContentTree.make_iterator(&rEntry));
1140  (void)rContentTree.iter_children(*xChild);
1141 
1142  do
1143  {
1144  if (rContentTree.iter_has_child(*xChild) || rContentTree.get_children_on_demand(*xChild))
1145  {
1146  if (!IsAllExpanded(rContentTree, *xChild))
1147  return false;
1148  }
1149  }
1150  while (rContentTree.iter_next_sibling(*xChild));
1151  return true;
1152  }
1153 
1154  void ExpandOrCollapseAll(weld::TreeView& rContentTree, weld::TreeIter& rEntry)
1155  {
1156  bool bExpand = !IsAllExpanded(rContentTree, rEntry);
1157  bExpand ? rContentTree.expand_row(rEntry) : rContentTree.collapse_row(rEntry);
1158  int nRefDepth = rContentTree.get_iter_depth(rEntry);
1159  while (rContentTree.iter_next(rEntry) && rContentTree.get_iter_depth(rEntry) > nRefDepth)
1160  {
1161  if (rContentTree.iter_has_child(rEntry))
1162  bExpand ? rContentTree.expand_row(rEntry) : rContentTree.collapse_row(rEntry);
1163  }
1164  }
1165 }
1166 
1167 // Handler for Dragging and ContextMenu
1168 static bool lcl_InsertExpandCollapseAllItem(const weld::TreeView& rContentTree, const weld::TreeIter& rEntry, weld::Menu& rPop)
1169 {
1170  if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry))
1171  {
1172  rPop.set_label(OString::number(800), IsAllExpanded(rContentTree, rEntry) ? SwResId(STR_COLLAPSEALL) : SwResId(STR_EXPANDALL));
1173  return false;
1174  }
1175  return true;
1176 }
1177 
1178 static void lcl_SetOutlineContentEntriesSensitivities(SwContentTree* pThis, const weld::TreeView& rContentTree, const weld::TreeIter& rEntry, weld::Menu& rPop)
1179 {
1180  rPop.set_sensitive(OString::number(1512), false);
1181  rPop.set_sensitive(OString::number(1513), false);
1182  rPop.set_sensitive(OString::number(1514), false);
1183 
1185  return;
1186 
1187  // todo: multi selection
1188  if (rContentTree.count_selected_rows() > 1)
1189  return;
1190 
1191  const SwNodes& rNodes = pThis->GetWrtShell()->GetNodes();
1192  const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
1193  size_t nOutlinePos = weld::GetAbsPos(rContentTree, rEntry);
1194 
1195  bool bIsRoot = lcl_IsContentType(rEntry, rContentTree);
1196 
1197  if (!bIsRoot)
1198  --nOutlinePos;
1199 
1200  if (nOutlinePos >= rOutlineNodes.size())
1201  return;
1202 
1203  int nFirstLevel = pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos);
1204  {
1205  // determine if any concerned outline node has content
1206  bool bHasContent(false);
1207  size_t nPos = nOutlinePos;
1208  SwNode* pSttNd = rOutlineNodes[nPos];
1209  SwNode* pEndNd = &rNodes.GetEndOfContent();
1210  if (rOutlineNodes.size() > nPos + 1)
1211  pEndNd = rOutlineNodes[nPos + 1];
1212 
1213  // selected
1214  SwNodeIndex aIdx(*pSttNd);
1215  if (rNodes.GoNext(&aIdx) != pEndNd)
1216  bHasContent = true;
1217 
1218  // descendants
1219  if (!bHasContent && (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry)))
1220  {
1221  while (++nPos < rOutlineNodes.size() &&
1222  (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
1223  {
1224  pSttNd = rOutlineNodes[nPos];
1225  pEndNd = &rNodes.GetEndOfContent();
1226  if (rOutlineNodes.size() > nPos + 1)
1227  pEndNd = rOutlineNodes[nPos + 1];
1228 
1229  // test for content in outline node
1230  aIdx.Assign(*pSttNd);
1231  if (rNodes.GoNext(&aIdx) != pEndNd)
1232  {
1233  bHasContent = true;
1234  break;
1235  }
1236  }
1237  }
1238 
1239  if (!bHasContent)
1240  return; // no content in any of the concerned outline nodes
1241  }
1242 
1243  // determine for subs if all are folded or unfolded or if they are mixed
1244  if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry))
1245  {
1246  // skip no content nodes
1247  // we know there is content from results above so this is presumably safe
1248  size_t nPos = nOutlinePos;
1249  while (true)
1250  {
1251  SwNode* pSttNd = rOutlineNodes[nPos];
1252  SwNode* pEndNd = rOutlineNodes.back();
1253  if (!bIsRoot && rOutlineNodes.size() > nPos + 1)
1254  pEndNd = rOutlineNodes[nPos + 1];
1255 
1256  SwNodeIndex aIdx(*pSttNd);
1257  if (rNodes.GoNext(&aIdx) != pEndNd)
1258  break;
1259  nPos++;
1260  }
1261 
1262  bool bHasFolded(pThis->GetWrtShell()->IsOutlineContentFolded(nPos));
1263  bool bHasUnfolded(!bHasFolded);
1264 
1265  while ((++nPos < pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineNodesCount()) &&
1266  (bIsRoot || pThis->GetWrtShell()->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nFirstLevel))
1267  {
1268 
1269  SwNode* pSttNd = rOutlineNodes[nPos];
1270  SwNode* pEndNd = &rNodes.GetEndOfContent();
1271  if (rOutlineNodes.size() > nPos + 1)
1272  pEndNd = rOutlineNodes[nPos + 1];
1273 
1274  SwNodeIndex aIdx(*pSttNd);
1275  if (rNodes.GoNext(&aIdx) == pEndNd)
1276  continue; // skip if no content
1277 
1278  if (pThis->GetWrtShell()->IsOutlineContentFolded(nPos))
1279  bHasFolded = true;
1280  else
1281  bHasUnfolded = true;
1282 
1283  if (bHasFolded && bHasUnfolded)
1284  break; // mixed so no need to continue
1285  }
1286 
1287  rPop.set_sensitive(OString::number(1513), bHasUnfolded);
1288  rPop.set_sensitive(OString::number(1514), bHasFolded);
1289  }
1290 
1291  bIsRoot ? rPop.remove(OString::number(1512)) : rPop.set_sensitive(OString::number(1512), true);
1292 }
1293 
1294 IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
1295 {
1296  if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
1297  return false;
1298 
1299  std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/swriter/ui/navigatorcontextmenu.ui"));
1300  std::unique_ptr<weld::Menu> xPop = xBuilder->weld_menu("navmenu");
1301 
1302  bool bOutline(false);
1303  std::unique_ptr<weld::Menu> xSubPop1 = xBuilder->weld_menu("outlinelevel");
1304  std::unique_ptr<weld::Menu> xSubPop2 = xBuilder->weld_menu("dragmodemenu");
1305  std::unique_ptr<weld::Menu> xSubPop3 = xBuilder->weld_menu("displaymenu");
1306  std::unique_ptr<weld::Menu> xSubPopOutlineTracking = xBuilder->weld_menu("outlinetracking");
1307 
1308  std::unique_ptr<weld::Menu> xSubPopOutlineContent = xBuilder->weld_menu("outlinecontent");
1309  xSubPopOutlineContent->append(OUString::number(1512), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_TOGGLE));
1310  xSubPopOutlineContent->append(OUString::number(1513), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_HIDE_ALL));
1311  xSubPopOutlineContent->append(OUString::number(1514), SwResId(STR_OUTLINE_CONTENT_VISIBILITY_SHOW_ALL));
1312 
1313  for(int i = 1; i <= 3; ++i)
1314  xSubPopOutlineTracking->append_radio(OUString::number(i + 10), m_aContextStrings[IDX_STR_OUTLINE_TRACKING + i]);
1315  xSubPopOutlineTracking->set_active(OString::number(10 + m_nOutlineTracking), true);
1316 
1317  for (int i = 1; i <= MAXLEVEL; ++i)
1318  xSubPop1->append_radio(OUString::number(i + 100), OUString::number(i));
1319  xSubPop1->set_active(OString::number(100 + m_nOutlineLevel), true);
1320 
1321  for (int i=0; i < 3; ++i)
1322  xSubPop2->append_radio(OUString::number(i + 201), m_aContextStrings[IDX_STR_HYPERLINK + i]);
1323  xSubPop2->set_active(OString::number(201 + static_cast<int>(GetParentWindow()->GetRegionDropMode())), true);
1324 
1325  // Insert the list of the open files
1326  sal_uInt16 nId = 301;
1327  const SwView* pActiveView = ::GetActiveView();
1328  SwView *pView = SwModule::GetFirstView();
1329  while (pView)
1330  {
1331  OUString sInsert = pView->GetDocShell()->GetTitle();
1332  if (pView == pActiveView)
1333  {
1334  sInsert += "(" +
1335  m_aContextStrings[IDX_STR_ACTIVE] +
1336  ")";
1337  }
1338  xSubPop3->append_radio(OUString::number(nId), sInsert);
1339  if (State::CONSTANT == m_eState && m_pActiveShell == &pView->GetWrtShell())
1340  xSubPop3->set_active(OString::number(nId), true);
1341  pView = SwModule::GetNextView(pView);
1342  nId++;
1343  }
1344  xSubPop3->append_radio(OUString::number(nId++), m_aContextStrings[IDX_STR_ACTIVE_VIEW]);
1345  if (m_pHiddenShell)
1346  {
1347  OUString sHiddenEntry = m_pHiddenShell->GetView().GetDocShell()->GetTitle() +
1348  " ( " +
1349  m_aContextStrings[IDX_STR_HIDDEN] +
1350  " )";
1351  xSubPop3->append_radio(OUString::number(nId), sHiddenEntry);
1352  }
1353 
1354  if (State::ACTIVE == m_eState)
1355  xSubPop3->set_active(OString::number(--nId), true);
1356  else if (State::HIDDEN == m_eState)
1357  xSubPop3->set_active(OString::number(nId), true);
1358 
1359  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
1360  if (!m_xTreeView->get_selected(xEntry.get()))
1361  xEntry.reset();
1362 
1363  if (State::HIDDEN == m_eState || !xEntry || !lcl_IsContent(*xEntry, *m_xTreeView))
1364  xPop->remove(OString::number(900)); // go to
1365 
1366  bool bRemovePostItEntries = true;
1367  bool bRemoveIndexEntries = true;
1368  bool bRemoveEditEntry = true;
1369  bool bRemoveUnprotectEntry = true;
1370  bool bRemoveDeleteEntry = true;
1371  bool bRemoveRenameEntry = true;
1372  bool bRemoveSelectEntry = true;
1373  bool bRemoveToggleExpandEntry = true;
1374  bool bRemoveChapterEntries = true;
1375  bool bRemoveSendOutlineEntry = true;
1376 
1377  // Edit only if the shown content is coming from the current view.
1378  if (State::HIDDEN != m_eState &&
1379  (State::ACTIVE == m_eState || m_pActiveShell == pActiveView->GetWrtShellPtr())
1380  && xEntry && lcl_IsContent(*xEntry, *m_xTreeView))
1381  {
1382  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
1383  const SwContentType* pContType = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetParent();
1384  const ContentTypeId nContentType = pContType->GetType();
1385  const bool bReadonly = m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
1386  const bool bVisible = !reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64())->IsInvisible();
1387  const bool bProtected = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64())->IsProtect();
1388  const bool bProtectBM = (ContentTypeId::BOOKMARK == nContentType)
1389  && m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS);
1390  const bool bEditable = pContType->IsEditable() &&
1391  ((bVisible && !bProtected && !bProtectBM) || ContentTypeId::REGION == nContentType);
1392  const bool bDeletable = pContType->IsDeletable() &&
1393  ((bVisible && !bProtected && !bProtectBM) || ContentTypeId::REGION == nContentType);
1394  const bool bRenamable = bEditable && !bReadonly &&
1395  (ContentTypeId::TABLE == nContentType ||
1396  ContentTypeId::FRAME == nContentType ||
1397  ContentTypeId::GRAPHIC == nContentType ||
1398  ContentTypeId::OLE == nContentType ||
1399  (ContentTypeId::BOOKMARK == nContentType && !bProtectBM) ||
1400  ContentTypeId::REGION == nContentType ||
1401  ContentTypeId::INDEX == nContentType ||
1402  ContentTypeId::DRAWOBJECT == nContentType);
1403 
1404  if(ContentTypeId::OUTLINE == nContentType)
1405  {
1406  bOutline = true;
1407  lcl_SetOutlineContentEntriesSensitivities(this, *m_xTreeView, *xEntry, *xSubPopOutlineContent);
1408  bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop);
1409  if (!bReadonly)
1410  {
1411  bRemoveSelectEntry = false;
1412  bRemoveChapterEntries = false;
1413  }
1414  }
1415  else if (!bReadonly && (bEditable || bDeletable))
1416  {
1417  if(ContentTypeId::INDEX == nContentType)
1418  {
1419  bRemoveIndexEntries = false;
1420 
1421  const SwTOXBase* pBase = reinterpret_cast<SwTOXBaseContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetTOXBase();
1422  if (!pBase->IsTOXBaseInReadonly())
1423  bRemoveEditEntry = false;
1424 
1425  xPop->set_active(OString::number(405), SwEditShell::IsTOXBaseReadonly(*pBase));
1426  bRemoveDeleteEntry = false;
1427  }
1428  else if(ContentTypeId::TABLE == nContentType)
1429  {
1430  bRemoveSelectEntry = false;
1431  bRemoveEditEntry = false;
1432  bRemoveUnprotectEntry = false;
1433  bool bFull = false;
1434  OUString sTableName = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetName();
1435  bool bProt = m_pActiveShell->HasTableAnyProtection( &sTableName, &bFull );
1436  xPop->set_sensitive(OString::number(403), !bFull);
1437  xPop->set_sensitive(OString::number(404), bProt);
1438  bRemoveDeleteEntry = false;
1439  }
1440  else if(ContentTypeId::DRAWOBJECT == nContentType)
1441  {
1442  bRemoveDeleteEntry = false;
1443  }
1444  else if(ContentTypeId::REGION == nContentType)
1445  {
1446  bRemoveSelectEntry = false;
1447  bRemoveEditEntry = false;
1448  }
1449  else
1450  {
1451  if (bEditable && bDeletable)
1452  {
1453  bRemoveEditEntry = false;
1454  bRemoveDeleteEntry = false;
1455  }
1456  else if (bEditable)
1457  bRemoveEditEntry = false;
1458  else if (bDeletable)
1459  {
1460  bRemoveDeleteEntry = false;
1461  }
1462  }
1463  //Rename object
1464  if (bRenamable)
1465  bRemoveRenameEntry = false;
1466  }
1467  }
1468  else if (xEntry)
1469  {
1470  const SwContentType* pType;
1471  if (lcl_IsContentType(*xEntry, *m_xTreeView))
1472  pType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xEntry).toInt64());
1473  else
1474  pType = reinterpret_cast<SwContent*>(
1475  m_xTreeView->get_id(*xEntry).toInt64())->GetParent();
1476  if (pType)
1477  {
1478  if (ContentTypeId::OUTLINE == pType->GetType())
1479  {
1480  bOutline = true;
1481  if (State::HIDDEN != m_eState)
1482  {
1484  *xSubPopOutlineContent);
1485  bRemoveSendOutlineEntry = false;
1486  }
1487  bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry,
1488  *xPop);
1489  }
1490  if (State::HIDDEN != m_eState &&
1491  pType->GetType() == ContentTypeId::POSTIT &&
1492  !m_pActiveShell->GetView().GetDocShell()->IsReadOnly() &&
1493  pType->GetMemberCount() > 0)
1494  bRemovePostItEntries = false;
1495  }
1496  }
1497 
1498  if (bRemoveToggleExpandEntry)
1499  {
1500  xPop->remove("separator3");
1501  xPop->remove(OString::number(800));
1502  }
1503 
1504  if (bRemoveSelectEntry)
1505  xPop->remove(OString::number(805));
1506 
1507  if (bRemoveChapterEntries)
1508  {
1509  xPop->remove("separator2");
1510  xPop->remove(OString::number(806));
1511  xPop->remove(OString::number(801));
1512  xPop->remove(OString::number(802));
1513  xPop->remove(OString::number(803));
1514  xPop->remove(OString::number(804));
1515  }
1516 
1517  if (bRemoveSendOutlineEntry)
1518  xPop->remove(OString::number(700));
1519 
1520  if (bRemovePostItEntries)
1521  {
1522  xPop->remove(OString::number(600));
1523  xPop->remove(OString::number(601));
1524  xPop->remove(OString::number(602));
1525  }
1526 
1527  if (bRemoveDeleteEntry)
1528  xPop->remove(OString::number(501));
1529 
1530  if (bRemoveRenameEntry)
1531  xPop->remove(OString::number(502));
1532 
1533  if (bRemoveIndexEntries)
1534  {
1535  xPop->remove(OString::number(401));
1536  xPop->remove(OString::number(402));
1537  xPop->remove(OString::number(405));
1538  }
1539 
1540  if (bRemoveUnprotectEntry)
1541  xPop->remove(OString::number(404));
1542 
1543  if (bRemoveEditEntry)
1544  xPop->remove(OString::number(403));
1545 
1546  if (bRemoveToggleExpandEntry &&
1547  bRemoveSelectEntry &&
1548  bRemoveChapterEntries &&
1549  bRemoveSendOutlineEntry &&
1550  bRemovePostItEntries &&
1551  bRemoveDeleteEntry &&
1552  bRemoveRenameEntry &&
1553  bRemoveIndexEntries &&
1554  bRemoveUnprotectEntry &&
1555  bRemoveEditEntry)
1556  {
1557  xPop->remove("separator1");
1558  }
1559 
1560  if (!bOutline)
1561  {
1562  xSubPop1.reset();
1563  xPop->remove(OString::number(1)); // outline level menu
1564  }
1565  if (!bOutline || State::HIDDEN == m_eState)
1566  {
1567  xSubPopOutlineTracking.reset();
1568  xPop->remove(OString::number(4)); // outline tracking menu
1569  }
1570  if (!bOutline || State::HIDDEN == m_eState ||
1571  !m_pActiveShell->GetViewOptions()->IsShowOutlineContentVisibilityButton() ||
1572  m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount() == 0)
1573  {
1574  xSubPopOutlineContent.reset();
1575  xPop->remove(OString::number(5)); // outline content menu
1576  xPop->remove("separator1511");
1577  }
1578 
1579  OString sCommand = xPop->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
1580  if (!sCommand.isEmpty())
1581  ExecuteContextMenuAction(sCommand);
1582 
1583  return true;
1584 }
1585 
1586 void SwContentTree::insert(const weld::TreeIter* pParent, const OUString& rStr, const OUString& rId,
1587  bool bChildrenOnDemand, weld::TreeIter* pRet)
1588 {
1589  m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, bChildrenOnDemand, pRet);
1590  ++m_nEntryCount;
1591 }
1592 
1594 {
1595  if (m_xTreeView->iter_has_child(rIter))
1596  {
1597  std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator(&rIter);
1598  (void)m_xTreeView->iter_children(*xChild);
1599  remove(*xChild);
1600  }
1601  m_xTreeView->remove(rIter);
1602  --m_nEntryCount;
1603 }
1604 
1605 // Content will be integrated into the Box only on demand.
1607 {
1608  bool bChild = m_xTreeView->iter_has_child(rParent);
1609  if (bChild || !m_xTreeView->get_children_on_demand(rParent))
1610  return bChild;
1611 
1612  // Is this a content type?
1613  if (lcl_IsContentType(rParent, *m_xTreeView))
1614  {
1615  std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator();
1616 
1617  assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(rParent).toInt64())));
1618  SwContentType* pCntType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(rParent).toInt64());
1619 
1620  const size_t nCount = pCntType->GetMemberCount();
1621  // Add for outline plus/minus
1622  if (pCntType->GetType() == ContentTypeId::OUTLINE)
1623  {
1624  for(size_t i = 0; i < nCount; ++i)
1625  {
1626  const SwContent* pCnt = pCntType->GetMember(i);
1627  if(pCnt)
1628  {
1629  const auto nLevel = static_cast<const SwOutlineContent*>(pCnt)->GetOutlineLevel();
1630  OUString sEntry = pCnt->GetName();
1631  if(sEntry.isEmpty())
1632  sEntry = m_sSpace;
1633  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
1634  if (!bChild || (nLevel == 0))
1635  {
1636  insert(&rParent, sEntry, sId, false, xChild.get());
1637  m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
1638  m_xTreeView->set_extra_row_indent(*xChild, nLevel + 1 - m_xTreeView->get_iter_depth(*xChild));
1639  bChild = true;
1640  }
1641  else
1642  {
1643  //back search parent.
1644  if(static_cast<const SwOutlineContent*>(pCntType->GetMember(i-1))->GetOutlineLevel() < nLevel)
1645  {
1646  insert(xChild.get(), sEntry, sId, false, xChild.get());
1647  m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
1648  m_xTreeView->set_extra_row_indent(*xChild, nLevel + 1 - m_xTreeView->get_iter_depth(*xChild));
1649  bChild = true;
1650  }
1651  else
1652  {
1653  bChild = m_xTreeView->iter_previous(*xChild);
1654  assert(!bChild || lcl_IsContentType(*xChild, *m_xTreeView) || dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xChild).toInt64())));
1655  while (bChild &&
1656  lcl_IsContent(*xChild, *m_xTreeView) &&
1657  (reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xChild).toInt64())->GetOutlineLevel() >= nLevel)
1658  )
1659  {
1660  bChild = m_xTreeView->iter_previous(*xChild);
1661  }
1662  if (bChild)
1663  {
1664  insert(xChild.get(), sEntry, sId, false, xChild.get());
1665  m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
1666  m_xTreeView->set_extra_row_indent(*xChild, nLevel + 1 - m_xTreeView->get_iter_depth(*xChild));
1667  }
1668  }
1669  }
1670  }
1671  }
1672  }
1673  else
1674  {
1675  bool bRegion = pCntType->GetType() == ContentTypeId::REGION;
1676  for(size_t i = 0; i < nCount; ++i)
1677  {
1678  const SwContent* pCnt = pCntType->GetMember(i);
1679  if (pCnt)
1680  {
1681  OUString sEntry = pCnt->GetName();
1682  if (sEntry.isEmpty())
1683  sEntry = m_sSpace;
1684  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
1685  insert(&rParent, sEntry, sId, false, xChild.get());
1686  m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
1687  if (bRegion)
1688  m_xTreeView->set_extra_row_indent(*xChild, static_cast<const SwRegionContent*>(pCnt)->GetRegionLevel());
1689  bChild = true;
1690  }
1691  }
1692  }
1693  }
1694 
1695  return bChild;
1696 }
1697 
1699 {
1700  SdrObject *pRetObj = nullptr;
1701  switch(pCnt->GetParent()->GetType())
1702  {
1704  {
1705  SdrView* pDrawView = m_pActiveShell->GetDrawView();
1706  if (pDrawView)
1707  {
1709  SdrPage* pPage = pDrawModel->GetPage(0);
1710  const size_t nCount = pPage->GetObjCount();
1711 
1712  for( size_t i=0; i<nCount; ++i )
1713  {
1714  SdrObject* pTemp = pPage->GetObj(i);
1715  if( pTemp->GetName() == pCnt->GetName())
1716  {
1717  pRetObj = pTemp;
1718  break;
1719  }
1720  }
1721  }
1722  break;
1723  }
1724  default:
1725  pRetObj = nullptr;
1726  }
1727  return pRetObj;
1728 }
1729 
1730 void SwContentTree::Expand(const weld::TreeIter& rParent, std::vector<std::unique_ptr<weld::TreeIter>>* pNodesToExpand)
1731 {
1732  if (!(m_xTreeView->iter_has_child(rParent) || m_xTreeView->get_children_on_demand(rParent)))
1733  return;
1734 
1735  if (!m_bIsRoot
1736  || (lcl_IsContentType(rParent, *m_xTreeView) &&
1737  reinterpret_cast<SwContentType*>(m_xTreeView->get_id(rParent).toInt64())->GetType() == ContentTypeId::OUTLINE)
1739  {
1740  if (lcl_IsContentType(rParent, *m_xTreeView))
1741  {
1742  SwContentType* pCntType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(rParent).toInt64());
1743  const sal_Int32 nOr = 1 << static_cast<int>(pCntType->GetType()); //linear -> Bitposition
1744  if (State::HIDDEN != m_eState)
1745  {
1746  m_nActiveBlock |= nOr;
1748  }
1749  else
1750  m_nHiddenBlock |= nOr;
1751  if (pCntType->GetType() == ContentTypeId::OUTLINE)
1752  {
1753  std::map< void*, bool > aCurrOutLineNodeMap;
1754 
1755  SwWrtShell* pShell = GetWrtShell();
1756  bool bParentHasChild = RequestingChildren(rParent);
1757  if (pNodesToExpand)
1758  pNodesToExpand->emplace_back(m_xTreeView->make_iterator(&rParent));
1759  if (bParentHasChild)
1760  {
1761  std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(&rParent));
1762  bool bChild = m_xTreeView->iter_next(*xChild);
1763  while (bChild && lcl_IsContent(*xChild, *m_xTreeView))
1764  {
1765  if (m_xTreeView->iter_has_child(*xChild))
1766  {
1767  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xChild).toInt64())));
1768  auto const nPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xChild).toInt64())->GetOutlinePos();
1769  void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
1770  aCurrOutLineNodeMap.emplace( key, false );
1771  std::map<void*, bool>::iterator iter = mOutLineNodeMap.find( key );
1772  if( iter != mOutLineNodeMap.end() && mOutLineNodeMap[key])
1773  {
1774  aCurrOutLineNodeMap[key] = true;
1775  RequestingChildren(*xChild);
1776  if (pNodesToExpand)
1777  pNodesToExpand->emplace_back(m_xTreeView->make_iterator(xChild.get()));
1778  m_xTreeView->set_children_on_demand(*xChild, false);
1779  }
1780  }
1781  bChild = m_xTreeView->iter_next(*xChild);
1782  }
1783  }
1784  mOutLineNodeMap = aCurrOutLineNodeMap;
1785  return;
1786  }
1787  }
1788  else
1789  {
1790  if (lcl_IsContent(rParent, *m_xTreeView))
1791  {
1792  SwWrtShell* pShell = GetWrtShell();
1793  // paranoid assert now that outline type is checked
1794  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(rParent).toInt64())));
1795  auto const nPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(rParent).toInt64())->GetOutlinePos();
1796  void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
1797  mOutLineNodeMap[key] = true;
1798  }
1799  }
1800  }
1801 
1802  RequestingChildren(rParent);
1803  if (pNodesToExpand)
1804  pNodesToExpand->emplace_back(m_xTreeView->make_iterator(&rParent));
1805 }
1806 
1807 IMPL_LINK(SwContentTree, ExpandHdl, const weld::TreeIter&, rParent, bool)
1808 {
1809  Expand(rParent, nullptr);
1810  return true;
1811 }
1812 
1813 IMPL_LINK(SwContentTree, CollapseHdl, const weld::TreeIter&, rParent, bool)
1814 {
1815  if (!m_xTreeView->iter_has_child(rParent) || m_xTreeView->get_children_on_demand(rParent))
1816  return true;
1817 
1818  if (lcl_IsContentType(rParent, *m_xTreeView))
1819  {
1820  if (m_bIsRoot)
1821  {
1822  // collapse to children of root node
1823  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(&rParent));
1824  if (m_xTreeView->iter_children(*xEntry))
1825  {
1826  do
1827  {
1828  m_xTreeView->collapse_row(*xEntry);
1829  }
1830  while (m_xTreeView->iter_next(*xEntry));
1831  }
1832  return false; // return false to notify caller not to do collapse
1833  }
1834  SwContentType* pCntType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(rParent).toInt64());
1835  const sal_Int32 nAnd = ~(1 << static_cast<int>(pCntType->GetType()));
1836  if (State::HIDDEN != m_eState)
1837  {
1838  m_nActiveBlock &= nAnd;
1839  m_pConfig->SetActiveBlock(m_nActiveBlock);
1840  }
1841  else
1842  m_nHiddenBlock &= nAnd;
1843  }
1844  else if (lcl_IsContent(rParent, *m_xTreeView))
1845  {
1846  SwWrtShell* pShell = GetWrtShell();
1847  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(rParent).toInt64())));
1848  auto const nPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(rParent).toInt64())->GetOutlinePos();
1849  void* key = static_cast<void*>(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos ));
1850  mOutLineNodeMap[key] = false;
1851  }
1852 
1853  return true;
1854 }
1855 
1856 // Also on double click will be initially opened only.
1857 IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
1858 {
1859  bool bConsumed = false;
1860 
1861  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
1862  bool bEntry = m_xTreeView->get_cursor(xEntry.get());
1863  // Is it a content type?
1864  OSL_ENSURE(bEntry, "no current entry!");
1865  if (bEntry)
1866  {
1867  if (lcl_IsContentType(*xEntry, *m_xTreeView) && !m_xTreeView->iter_has_child(*xEntry))
1868  {
1869  RequestingChildren(*xEntry);
1870  m_xTreeView->set_children_on_demand(*xEntry, false);
1871  }
1872  else if (!lcl_IsContentType(*xEntry, *m_xTreeView) && (State::HIDDEN != m_eState))
1873  {
1874  if (State::CONSTANT == m_eState)
1875  {
1876  m_pActiveShell->GetView().GetViewFrame()->GetWindow().ToTop();
1877  }
1878  //Jump to content type:
1879  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
1880  SwContent* pCnt = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64());
1881  assert(pCnt && "no UserData");
1882  GotoContent(pCnt);
1883  // fdo#36308 don't expand outlines on double-click
1884  bConsumed = pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE;
1885  }
1886  }
1887 
1888  return bConsumed; // false/true == allow/disallow more to be done, i.e. expand/collapse children
1889 }
1890 
1891 namespace
1892 {
1893  OUString GetImageIdForContentTypeId(ContentTypeId eType)
1894  {
1895  OUString sResId;
1896 
1897  switch (eType)
1898  {
1900  sResId = RID_BMP_NAVI_OUTLINE;
1901  break;
1902  case ContentTypeId::TABLE:
1903  sResId = RID_BMP_NAVI_TABLE;
1904  break;
1905  case ContentTypeId::FRAME:
1906  sResId = RID_BMP_NAVI_FRAME;
1907  break;
1909  sResId = RID_BMP_NAVI_GRAPHIC;
1910  break;
1911  case ContentTypeId::OLE:
1912  sResId = RID_BMP_NAVI_OLE;
1913  break;
1915  sResId = RID_BMP_NAVI_BOOKMARK;
1916  break;
1917  case ContentTypeId::REGION:
1918  sResId = RID_BMP_NAVI_REGION;
1919  break;
1921  sResId = RID_BMP_NAVI_URLFIELD;
1922  break;
1924  sResId = RID_BMP_NAVI_REFERENCE;
1925  break;
1926  case ContentTypeId::INDEX:
1927  sResId = RID_BMP_NAVI_INDEX;
1928  break;
1929  case ContentTypeId::POSTIT:
1930  sResId = RID_BMP_NAVI_POSTIT;
1931  break;
1933  sResId = RID_BMP_NAVI_DRAWOBJECT;
1934  break;
1936  SAL_WARN("sw.ui", "ContentTypeId::UNKNOWN has no bitmap preview");
1937  break;
1938  }
1939 
1940  return sResId;
1941  };
1942 }
1943 
1945 {
1946  return weld::GetAbsPos(*m_xTreeView, rIter);
1947 }
1948 
1950 {
1951  return m_nEntryCount;
1952 }
1953 
1954 size_t SwContentTree::GetChildCount(const weld::TreeIter& rParent) const
1955 {
1956  if (!m_xTreeView->iter_has_child(rParent))
1957  return 0;
1958 
1959  std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rParent));
1960 
1961  size_t nCount = 0;
1962  auto nRefDepth = m_xTreeView->get_iter_depth(*xParent);
1963  auto nActDepth = nRefDepth;
1964  do
1965  {
1966  if (!m_xTreeView->iter_next(*xParent))
1967  xParent.reset();
1968  else
1969  nActDepth = m_xTreeView->get_iter_depth(*xParent);
1970  nCount++;
1971  } while(xParent && nRefDepth < nActDepth);
1972 
1973  nCount--;
1974  return nCount;
1975 }
1976 
1977 std::unique_ptr<weld::TreeIter> SwContentTree::GetEntryAtAbsPos(size_t nAbsPos) const
1978 {
1979  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
1980  if (!m_xTreeView->get_iter_first(*xEntry))
1981  xEntry.reset();
1982 
1983  while (nAbsPos && xEntry)
1984  {
1985  if (!m_xTreeView->iter_next(*xEntry))
1986  xEntry.reset();
1987  nAbsPos--;
1988  }
1989  return xEntry;
1990 }
1991 
1992 void SwContentTree::Display( bool bActive )
1993 {
1994  // First read the selected entry to select it later again if necessary
1995  // -> the user data here are no longer valid!
1996  std::unique_ptr<weld::TreeIter> xOldSelEntry(m_xTreeView->make_iterator());
1997  if (!m_xTreeView->get_selected(xOldSelEntry.get()))
1998  xOldSelEntry.reset();
1999  OUString sEntryName; // Name of the entry
2000  size_t nEntryRelPos = 0; // relative position to their parent
2001  size_t nOldEntryCount = GetEntryCount();
2002  sal_Int32 nOldScrollPos = 0;
2003  if (xOldSelEntry)
2004  {
2006 
2007  nOldScrollPos = m_xTreeView->vadjustment_get_value();
2008  sEntryName = m_xTreeView->get_text(*xOldSelEntry);
2009  std::unique_ptr<weld::TreeIter> xParentEntry = m_xTreeView->make_iterator(xOldSelEntry.get());
2010  while (m_xTreeView->get_iter_depth(*xParentEntry))
2011  m_xTreeView->iter_parent(*xParentEntry);
2012  if (m_xTreeView->get_iter_depth(*xOldSelEntry))
2013  nEntryRelPos = GetAbsPos(*xOldSelEntry) - GetAbsPos(*xParentEntry);
2014  }
2015 
2016  clear();
2017 
2018  if (!bActive)
2020  else if (State::HIDDEN == m_eState)
2022  SwWrtShell* pShell = GetWrtShell();
2023  const bool bReadOnly = !pShell || pShell->GetView().GetDocShell()->IsReadOnly();
2024  if(bReadOnly != m_bIsLastReadOnly)
2025  {
2026  m_bIsLastReadOnly = bReadOnly;
2027  bool bDisable = pShell == nullptr || bReadOnly;
2028  SwNavigationPI* pNavi = GetParentWindow();
2029  pNavi->m_xContent6ToolBox->set_item_sensitive("chapterup", !bDisable);
2030  pNavi->m_xContent6ToolBox->set_item_sensitive("chapterdown", !bDisable);
2031  pNavi->m_xContent6ToolBox->set_item_sensitive("promote", !bDisable);
2032  pNavi->m_xContent6ToolBox->set_item_sensitive("demote", !bDisable);
2033  pNavi->m_xContent5ToolBox->set_item_sensitive("reminder", !bDisable);
2034  }
2035 
2036  if (pShell)
2037  {
2038  std::unique_ptr<weld::TreeIter> xEntry = m_xTreeView->make_iterator();
2039  std::unique_ptr<weld::TreeIter> xSelEntry;
2040  std::vector<std::unique_ptr<weld::TreeIter>> aNodesToExpand;
2041  // all content navigation view
2043  {
2044  m_xTreeView->freeze();
2045 
2046  for( ContentTypeId nCntType : o3tl::enumrange<ContentTypeId>() )
2047  {
2048  std::unique_ptr<SwContentType>& rpContentT = bActive ?
2049  m_aActiveContentArr[nCntType] :
2050  m_aHiddenContentArr[nCntType];
2051  if(!rpContentT)
2052  rpContentT.reset(new SwContentType(pShell, nCntType, m_nOutlineLevel ));
2053 
2054  OUString aImage(GetImageIdForContentTypeId(nCntType));
2055  bool bChOnDemand = 0 != rpContentT->GetMemberCount();
2056  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(rpContentT.get())));
2057  insert(nullptr, rpContentT->GetName(), sId, bChOnDemand, xEntry.get());
2058  m_xTreeView->set_image(*xEntry, aImage);
2059 
2060  m_xTreeView->set_sensitive(*xEntry, bChOnDemand);
2061 
2062  if (nCntType == m_nLastSelType)
2063  xSelEntry = m_xTreeView->make_iterator(xEntry.get());
2064  sal_Int32 nExpandOptions = (State::HIDDEN == m_eState)
2065  ? m_nHiddenBlock
2066  : m_nActiveBlock;
2067  if (nExpandOptions & (1 << static_cast<int>(nCntType)))
2068  {
2069  // fill contents of to-be expanded entries while frozen
2070  Expand(*xEntry, &aNodesToExpand);
2071  m_xTreeView->set_children_on_demand(*xEntry, false);
2072  }
2073  }
2074 
2075  m_xTreeView->thaw();
2076 
2077  // restore visual expanded tree state
2078  for (const auto& rNode : aNodesToExpand)
2079  m_xTreeView->expand_row(*rNode);
2080 
2081  (void)m_xTreeView->get_iter_first(*xEntry);
2083  {
2084  sal_Int32 nExpandOptions = (State::HIDDEN == m_eState)
2085  ? m_nHiddenBlock
2086  : m_nActiveBlock;
2087  if (nExpandOptions & (1 << static_cast<int>(nCntType)))
2088  {
2089  if (nEntryRelPos && nCntType == m_nLastSelType)
2090  {
2091  // reselect the entry
2092  std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(xEntry.get()));
2093  std::unique_ptr<weld::TreeIter> xTemp;
2094  sal_uLong nPos = 1;
2095  while (m_xTreeView->iter_next(*xChild))
2096  {
2097  // The old text will be slightly favored
2098  if (sEntryName == m_xTreeView->get_text(*xChild) ||
2099  nPos == nEntryRelPos)
2100  {
2101  m_xTreeView->copy_iterator(*xChild, *xSelEntry);
2102  break;
2103  }
2104  xTemp = m_xTreeView->make_iterator(xChild.get());
2105  nPos++;
2106  }
2107  if (!xSelEntry || lcl_IsContentType(*xSelEntry, *m_xTreeView))
2108  xSelEntry = std::move(xTemp);
2109  }
2110  }
2111 
2112  (void)m_xTreeView->iter_next_sibling(*xEntry);
2113  }
2114 
2115  if (!xSelEntry)
2116  {
2117  nOldScrollPos = 0;
2118  xSelEntry = m_xTreeView->make_iterator();
2119  if (!m_xTreeView->get_iter_first(*xSelEntry))
2120  xSelEntry.reset();
2121  }
2122 
2123  if (xSelEntry)
2124  {
2125  m_xTreeView->set_cursor(*xSelEntry);
2126  Select();
2127  }
2128  }
2129  // root content navigation view
2130  else
2131  {
2132  m_xTreeView->freeze();
2133 
2134  std::unique_ptr<SwContentType>& rpRootContentT = bActive ?
2137  if(!rpRootContentT)
2138  rpRootContentT.reset(new SwContentType(pShell, m_nRootType, m_nOutlineLevel ));
2139  OUString aImage(GetImageIdForContentTypeId(m_nRootType));
2140  bool bChOnDemand = m_nRootType == ContentTypeId::OUTLINE;
2141  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(rpRootContentT.get())));
2142  insert(nullptr, rpRootContentT->GetName(), sId, bChOnDemand, xEntry.get());
2143  m_xTreeView->set_image(*xEntry, aImage);
2144 
2145  if (!bChOnDemand)
2146  {
2147  bool bRegion = rpRootContentT->GetType() == ContentTypeId::REGION;
2148 
2149  std::unique_ptr<weld::TreeIter> xChild = m_xTreeView->make_iterator();
2150  for (size_t i = 0; i < rpRootContentT->GetMemberCount(); ++i)
2151  {
2152  const SwContent* pCnt = rpRootContentT->GetMember(i);
2153  if (pCnt)
2154  {
2155  OUString sEntry = pCnt->GetName();
2156  if(sEntry.isEmpty())
2157  sEntry = m_sSpace;
2158  OUString sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
2159  insert(xEntry.get(), sEntry, sSubId, false, xChild.get());
2160  m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible());
2161  if (bRegion)
2162  m_xTreeView->set_extra_row_indent(*xChild, static_cast<const SwRegionContent*>(pCnt)->GetRegionLevel());
2163  }
2164  }
2165  }
2166  else
2167  {
2168  // fill contents of to-be expanded entries while frozen
2169  Expand(*xEntry, &aNodesToExpand);
2170  m_xTreeView->set_children_on_demand(*xEntry, false);
2171  }
2172 
2173  m_xTreeView->set_sensitive(*xEntry, m_xTreeView->iter_has_child(*xEntry));
2174 
2175  m_xTreeView->thaw();
2176 
2177  if (bChOnDemand)
2178  {
2179  // restore visual expanded tree state
2180  for (const auto& rNode : aNodesToExpand)
2181  m_xTreeView->expand_row(*rNode);
2182  }
2183  else
2184  m_xTreeView->expand_row(*xEntry);
2185 
2186  // reselect the entry
2187  if (nEntryRelPos)
2188  {
2189  std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(xEntry.get()));
2190  sal_uLong nPos = 1;
2191  while (m_xTreeView->iter_next(*xChild))
2192  {
2193  // The old text will be slightly favored
2194  if (sEntryName == m_xTreeView->get_text(*xChild) || nPos == nEntryRelPos)
2195  {
2196  xSelEntry = std::move(xChild);
2197  break;
2198  }
2199  nPos++;
2200  }
2201  if (xSelEntry)
2202  {
2203  m_xTreeView->set_cursor(*xSelEntry); // unselect all entries, make pSelEntry visible, and select
2204  Select();
2205  }
2206  }
2207  else
2208  {
2209  m_xTreeView->set_cursor(*xEntry);
2210  Select();
2211  }
2212  }
2213  }
2214 
2215  if (!m_bIgnoreViewChange && GetEntryCount() == nOldEntryCount)
2216  {
2217  m_xTreeView->vadjustment_set_value(nOldScrollPos);
2218  }
2219 }
2220 
2222 {
2223  m_xTreeView->freeze();
2224  m_xTreeView->clear();
2225  m_nEntryCount = 0;
2226  m_xTreeView->thaw();
2227 }
2228 
2230  sal_Int8& rDragMode )
2231 {
2232  bool bRet = false;
2233  SwWrtShell* pWrtShell = GetWrtShell();
2234  OSL_ENSURE(pWrtShell, "no Shell!");
2235 
2236  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
2237  bool bEntry = m_xTreeView->get_cursor(xEntry.get());
2238  if (!bEntry || lcl_IsContentType(*xEntry, *m_xTreeView) || !pWrtShell)
2239  return false;
2240  OUString sEntry;
2241  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2242  SwContent* pCnt = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64());
2243 
2244  const ContentTypeId nActType = pCnt->GetParent()->GetType();
2245  OUString sUrl;
2246  bool bOutline = false;
2247  OUString sOutlineText;
2248  switch( nActType )
2249  {
2251  {
2252  const SwOutlineNodes::size_type nPos = static_cast<SwOutlineContent*>(pCnt)->GetOutlinePos();
2253  OSL_ENSURE(nPos < pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount(),
2254  "outlinecnt changed");
2255 
2256  // make sure outline may actually be copied
2257  if( pWrtShell->IsOutlineCopyable( nPos ) )
2258  {
2259  const SwNumRule* pOutlRule = pWrtShell->GetOutlineNumRule();
2260  const SwTextNode* pTextNd =
2261  pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNode(nPos);
2262  if (pTextNd && pOutlRule && pTextNd->IsNumbered(pWrtShell->GetLayout()))
2263  {
2264  SwNumberTree::tNumberVector aNumVector =
2265  pTextNd->GetNumberVector(pWrtShell->GetLayout());
2266  for( int nLevel = 0;
2267  nLevel <= pTextNd->GetActualListLevel();
2268  nLevel++ )
2269  {
2270  const SwNumberTree::tSwNumTreeNumber nVal = aNumVector[nLevel] + 1;
2271  sEntry += OUString::number( nVal - pOutlRule->Get(nLevel).GetStart() ) + ".";
2272  }
2273  }
2274  sEntry += pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(nPos, pWrtShell->GetLayout(), false);
2275  sOutlineText = pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(nPos, pWrtShell->GetLayout());
2276  m_bIsOutlineMoveable = static_cast<SwOutlineContent*>(pCnt)->IsMoveable();
2277  bOutline = true;
2278  }
2279  }
2280  break;
2281  case ContentTypeId::POSTIT:
2282  case ContentTypeId::INDEX:
2284  // cannot be inserted, neither as URL nor as section
2285  break;
2287  sUrl = static_cast<SwURLFieldContent*>(pCnt)->GetURL();
2288  [[fallthrough]];
2289  case ContentTypeId::OLE:
2292  break;
2293  else
2294  rDragMode &= ~( DND_ACTION_MOVE | DND_ACTION_LINK );
2295  [[fallthrough]];
2296  default:
2297  sEntry = m_xTreeView->get_text(*xEntry);
2298  }
2299 
2300  if(!sEntry.isEmpty())
2301  {
2302  const SwDocShell* pDocShell = pWrtShell->GetView().GetDocShell();
2303  if(sUrl.isEmpty())
2304  {
2305  if(pDocShell->HasName())
2306  {
2307  SfxMedium* pMedium = pDocShell->GetMedium();
2308  sUrl = pMedium->GetURLObject().GetURLNoMark();
2309  // only if a primarily link shall be integrated.
2310  bRet = true;
2311  }
2312  else if ( nActType == ContentTypeId::REGION || nActType == ContentTypeId::BOOKMARK )
2313  {
2314  // For field and bookmarks a link is also allowed
2315  // without a filename into its own document.
2316  bRet = true;
2317  }
2318  else if (State::CONSTANT == m_eState &&
2319  ( !::GetActiveView() ||
2320  m_pActiveShell != ::GetActiveView()->GetWrtShellPtr()))
2321  {
2322  // Urls of inactive views cannot dragged without
2323  // file names, also.
2324  bRet = false;
2325  }
2326  else
2327  {
2329  rDragMode = DND_ACTION_MOVE;
2330  }
2331 
2332  const OUString& rToken = pCnt->GetParent()->GetTypeToken();
2333  sUrl += "#" + sEntry;
2334  if(!rToken.isEmpty())
2335  {
2336  sUrl += OUStringChar(cMarkSeparator) + rToken;
2337  }
2338  }
2339  else
2340  bRet = true;
2341 
2342  if( bRet )
2343  {
2344  // In Outlines of heading text must match
2345  // the real number into the description.
2346  if(bOutline)
2347  sEntry = sOutlineText;
2348 
2349  {
2350  NaviContentBookmark aBmk( sUrl, sEntry,
2351  GetParentWindow()->GetRegionDropMode(),
2352  pDocShell);
2353  aBmk.Copy( rTransfer );
2354  }
2355 
2356  // An INetBookmark must a be delivered to foreign DocShells
2357  if( pDocShell->HasName() )
2358  {
2359  INetBookmark aBkmk( sUrl, sEntry );
2360  rTransfer.CopyINetBookmark( aBkmk );
2361  }
2362  }
2363  }
2364  return bRet;
2365 }
2366 
2368 {
2369  if(!m_bIsRoot)
2370  {
2371  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
2372  bool bEntry = m_xTreeView->get_cursor(xEntry.get());
2373  if (bEntry)
2374  {
2375  const SwContentType* pCntType;
2376  if (lcl_IsContentType(*xEntry, *m_xTreeView))
2377  {
2378  assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2379  pCntType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xEntry).toInt64());
2380  }
2381  else
2382  {
2383  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2384  pCntType = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetParent();
2385  }
2386  m_nRootType = pCntType->GetType();
2387  m_bIsRoot = true;
2390  {
2391  m_xTreeView->set_selection_mode(SelectionMode::Multiple);
2392  }
2393  }
2394  }
2395  else
2396  {
2397  m_xTreeView->set_selection_mode(SelectionMode::Single);
2399  m_bIsRoot = false;
2402  }
2405  pBox->set_item_active("root", m_bIsRoot);
2406 }
2407 
2409 {
2410  bool bContentChanged = false;
2411 
2412 // - Run through the local array and the Treelistbox in parallel.
2413 // - Are the records not expanded, they are discarded only in the array
2414 // and the content type will be set as the new UserData.
2415 // - Is the root mode is active only this will be updated.
2416 
2417 // Valid for the displayed content types is:
2418 // the Memberlist will be erased and the membercount will be updated
2419 // If content will be checked, the memberlists will be replenished
2420 // at the same time. Once a difference occurs it will be only replenished
2421 // no longer checked. Finally, the box is filled again.
2422 
2423  // bVisibilityChanged gets set to true if some element, like a section,
2424  // changed visibility and should have its name rerendered with a new
2425  // grayed-out state
2426  bool bVisibilityChanged = false;
2427 
2428  if (State::HIDDEN == m_eState)
2429  {
2431  {
2432  if(m_aActiveContentArr[i])
2433  m_aActiveContentArr[i]->Invalidate();
2434  }
2435  }
2436  // root content navigation view
2437  else if(m_bIsRoot)
2438  {
2439  std::unique_ptr<weld::TreeIter> xRootEntry(m_xTreeView->make_iterator());
2440  if (!m_xTreeView->get_iter_first(*xRootEntry))
2441  bContentChanged = true;
2442  else
2443  {
2444  assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xRootEntry).toInt64())));
2445  const ContentTypeId nType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xRootEntry).toInt64())->GetType();
2446  SwContentType* pArrType = m_aActiveContentArr[nType].get();
2447  if (!pArrType)
2448  bContentChanged = true;
2449  else
2450  {
2451  // start check if first selected outline level has changed
2452  bool bCheckChanged = m_nRootType == ContentTypeId::OUTLINE && !m_xTreeView->has_focus();
2453  if (bCheckChanged)
2454  {
2455  std::unique_ptr<weld::TreeIter> xFirstSel(m_xTreeView->make_iterator());
2456  bool bFirstSel = m_xTreeView->get_selected(xFirstSel.get());
2457  if (bFirstSel && lcl_IsContent(*xFirstSel, *m_xTreeView))
2458  {
2459  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xFirstSel).toInt64())));
2460  const auto nSelLevel = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xFirstSel).toInt64())->GetOutlineLevel();
2461  SwWrtShell* pSh = GetWrtShell();
2462  const SwOutlineNodes::size_type nOutlinePos = pSh->GetOutlinePos(MAXLEVEL);
2463  if (nOutlinePos != SwOutlineNodes::npos && pSh->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos) != nSelLevel)
2464  bContentChanged = true;
2465  }
2466  }
2467  // end check if first selected outline level has changed
2468 
2469  pArrType->Init(&bVisibilityChanged);
2470  pArrType->FillMemberList();
2471  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pArrType)));
2472  m_xTreeView->set_id(*xRootEntry, sId);
2473  if (!bContentChanged)
2474  {
2475  const size_t nChildCount = GetChildCount(*xRootEntry);
2476  if (nChildCount != pArrType->GetMemberCount())
2477  bContentChanged = true;
2478  else
2479  {
2480  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(xRootEntry.get()));
2481  for (size_t j = 0; j < nChildCount; ++j)
2482  {
2483  m_xTreeView->iter_next(*xEntry);
2484  const SwContent* pCnt = pArrType->GetMember(j);
2485  OUString sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
2486  m_xTreeView->set_id(*xEntry, sSubId);
2487  OUString sEntryText = m_xTreeView->get_text(*xEntry);
2488  if( sEntryText != pCnt->GetName() &&
2489  !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
2490  bContentChanged = true;
2491  }
2492  }
2493  }
2494  }
2495  }
2496  }
2497  // all content navigation view
2498  else
2499  {
2500  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
2501  bool bEntry = m_xTreeView->get_iter_first(*xEntry);
2502  while (bEntry)
2503  {
2504  bool bNext = true; // at least a next must be
2505  assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2506  SwContentType* pCntType = reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xEntry).toInt64());
2507  const size_t nCntCount = pCntType->GetMemberCount();
2508  const ContentTypeId nType = pCntType->GetType();
2509  SwContentType* pArrType = m_aActiveContentArr[nType].get();
2510  if (!pArrType)
2511  bContentChanged = true;
2512  else
2513  {
2514  pArrType->Init(&bVisibilityChanged);
2515  OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pArrType)));
2516  m_xTreeView->set_id(*xEntry, sId);
2517  if (m_xTreeView->get_row_expanded(*xEntry))
2518  {
2519  bool bLevelOrVisibilityChanged = false;
2520  // bLevelOrVisibilityChanged is set if outlines have changed their level
2521  // or if the visibility of objects (frames, sections, tables) has changed
2522  // i.e. in header/footer
2523  pArrType->FillMemberList(&bLevelOrVisibilityChanged);
2524  const size_t nChildCount = GetChildCount(*xEntry);
2525  if (bLevelOrVisibilityChanged)
2526  {
2527  if (nType == ContentTypeId::OUTLINE)
2528  bContentChanged = true;
2529  else
2530  bVisibilityChanged = true;
2531  }
2532 
2533  if(nChildCount != pArrType->GetMemberCount())
2534  bContentChanged = true;
2535  else
2536  {
2537  for(size_t j = 0; j < nChildCount; ++j)
2538  {
2539  bEntry = m_xTreeView->iter_next(*xEntry);
2540  bNext = false;
2541  const SwContent* pCnt = pArrType->GetMember(j);
2542  OUString sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
2543  m_xTreeView->set_id(*xEntry, sSubId);
2544  OUString sEntryText = m_xTreeView->get_text(*xEntry);
2545  if( sEntryText != pCnt->GetName() &&
2546  !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
2547  bContentChanged = true;
2548  }
2549  }
2550  }
2551  // not expanded and has children
2552  else if (m_xTreeView->iter_has_child(*xEntry))
2553  {
2554  // was the entry once opened, then must also the
2555  // invisible records be examined.
2556  // At least the user data must be updated.
2557  bool bLevelOrVisibilityChanged = false;
2558  // bLevelOrVisibilityChanged is set if outlines have changed their level
2559  // or if the visibility of objects (frames, sections, tables) has changed
2560  // i.e. in header/footer
2561  pArrType->FillMemberList(&bLevelOrVisibilityChanged);
2562  bool bRemoveChildren = false;
2563  const size_t nOldChildCount = GetChildCount(*xEntry);
2564  const size_t nNewChildCount = pArrType->GetMemberCount();
2565  if (nOldChildCount != nNewChildCount)
2566  {
2567  bRemoveChildren = true;
2568  }
2569  else
2570  {
2571  std::unique_ptr<weld::TreeIter> xChild(m_xTreeView->make_iterator(xEntry.get()));
2572  (void)m_xTreeView->iter_children(*xChild);
2573  for (size_t j = 0; j < nOldChildCount; ++j)
2574  {
2575  const SwContent* pCnt = pArrType->GetMember(j);
2576  OUString sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
2577  m_xTreeView->set_id(*xChild, sSubId);
2578  OUString sEntryText = m_xTreeView->get_text(*xChild);
2579  if( sEntryText != pCnt->GetName() &&
2580  !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
2581  bRemoveChildren = true;
2582  (void)m_xTreeView->iter_next(*xChild);
2583  }
2584  }
2585  if (bRemoveChildren)
2586  {
2587  std::unique_ptr<weld::TreeIter> xRemove(m_xTreeView->make_iterator(xEntry.get()));
2588  while (m_xTreeView->iter_children(*xRemove))
2589  {
2590  remove(*xRemove);
2591  m_xTreeView->copy_iterator(*xEntry, *xRemove);
2592  }
2593  m_xTreeView->set_children_on_demand(*xEntry, nNewChildCount != 0);
2594  }
2595  }
2596  else if((nCntCount != 0)
2597  != (pArrType->GetMemberCount()!=0))
2598  {
2599  bContentChanged = true;
2600  }
2601  }
2602  // The Root-Entry has to be found now
2603  while (bEntry && (bNext || m_xTreeView->get_iter_depth(*xEntry)))
2604  {
2605  bEntry = m_xTreeView->iter_next(*xEntry);
2606  bNext = false;
2607  }
2608  }
2609  }
2610 
2611  if (!bContentChanged && bVisibilityChanged)
2612  m_aUpdTimer.Start();
2613 
2614  return bContentChanged || bVisibilityChanged;
2615 }
2616 
2618 {
2619  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
2620  if (m_xTreeView->get_selected(xEntry.get()))
2621  {
2622  while (m_xTreeView->get_iter_depth(*xEntry))
2623  m_xTreeView->iter_parent(*xEntry);
2624  sal_Int64 nId = m_xTreeView->get_id(*xEntry).toInt64();
2625  if (nId && lcl_IsContentType(*xEntry, *m_xTreeView))
2626  {
2627  assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(nId)));
2628  m_nLastSelType = reinterpret_cast<SwContentType*>(nId)->GetType();
2629  }
2630  }
2631 }
2632 
2634 {
2636 
2637  // If clear is called by TimerUpdate:
2638  // Only for root can the validity of the UserData be guaranteed.
2639  m_xTreeView->all_foreach([this](weld::TreeIter& rEntry){
2640  m_xTreeView->set_id(rEntry, "");
2641  return false;
2642  });
2643 }
2644 
2646 {
2647  m_pHiddenShell = pSh;
2651  {
2652  m_aHiddenContentArr[i].reset();
2653  }
2654  Display(false);
2655 
2657 }
2658 
2660 {
2661  bool bClear = m_pActiveShell != pSh;
2662  if (State::ACTIVE == m_eState && bClear)
2663  {
2664  if (m_pActiveShell)
2666  m_pActiveShell = pSh;
2668  clear();
2669  }
2670  else if (State::CONSTANT == m_eState)
2671  {
2672  if (m_pActiveShell)
2674  m_pActiveShell = pSh;
2676  bClear = true;
2677  }
2678  // Only if it is the active view, the array will be deleted and
2679  // the screen filled new.
2680  if (State::ACTIVE == m_eState && bClear)
2681  {
2682  if (m_pActiveShell)
2686  {
2687  m_aActiveContentArr[i].reset();
2688  }
2689  Display(true);
2690  }
2691 }
2692 
2694 {
2695  if (m_pActiveShell)
2697  m_pActiveShell = pSh;
2699  StartListening(*m_pActiveShell->GetView().GetDocShell());
2702  {
2703  m_aActiveContentArr[i].reset();
2704  }
2705  Display(true);
2706 }
2707 
2709 {
2710  SfxViewEventHint const*const pVEHint(dynamic_cast<SfxViewEventHint const*>(&rHint));
2711  SwXTextView* pDyingShell = nullptr;
2712  if (m_pActiveShell && pVEHint && pVEHint->GetEventName() == "OnViewClosed")
2713  pDyingShell = dynamic_cast<SwXTextView*>(pVEHint->GetController().get());
2714  if (pDyingShell && pDyingShell->GetView() == &m_pActiveShell->GetView())
2715  {
2716  SetActiveShell(nullptr); // our view is dying, clear our pointers to it
2717  }
2718  else
2719  {
2720  SfxListener::Notify(rBC, rHint);
2721  }
2722  switch (rHint.GetId())
2723  {
2724  case SfxHintId::SwNavigatorUpdateTracking:
2725  UpdateTracking();
2726  break;
2727  case SfxHintId::SwNavigatorSelectOutlinesWithSelections:
2728  {
2730  {
2732  // make first selected entry visible
2733  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
2734  if (xEntry && m_xTreeView->get_selected(xEntry.get()))
2735  m_xTreeView->scroll_to_row(*xEntry);
2736  }
2737  else if (m_nRootType == ContentTypeId::UNKNOWN)
2738  m_xTreeView->unselect_all();
2739  break;
2740  }
2741  case SfxHintId::DocChanged:
2742  if (!m_bIgnoreViewChange)
2743  {
2744  m_bViewHasChanged = true;
2745  TimerUpdate(&m_aUpdTimer);
2746  }
2747  break;
2748  case SfxHintId::ModeChanged:
2749  if (SwWrtShell* pShell = GetWrtShell())
2750  {
2751  const bool bReadOnly = pShell->GetView().GetDocShell()->IsReadOnly();
2752  if (bReadOnly != m_bIsLastReadOnly)
2753  {
2754  m_bIsLastReadOnly = bReadOnly;
2755 
2756  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
2757  if (m_xTreeView->get_cursor(xEntry.get()))
2758  {
2759  m_xTreeView->select(*xEntry);
2760  Select();
2761  }
2762  else
2763  m_xTreeView->unselect_all();
2764  }
2765  }
2766  break;
2767  default:
2768  break;
2769  }
2770 }
2771 
2772 void SwContentTree::ExecCommand(std::string_view rCmd, bool bOutlineWithChildren)
2773 {
2774  const bool bUp = rCmd == "chapterup";
2775  const bool bUpDown = bUp || rCmd == "chapterdown";
2776  const bool bLeft = rCmd == "promote";
2777  const bool bLeftRight = bLeft || rCmd == "demote";
2778  if (!bUpDown && !bLeftRight)
2779  return;
2780  if (GetWrtShell()->GetView().GetDocShell()->IsReadOnly() ||
2781  (State::ACTIVE != m_eState &&
2782  (State::CONSTANT != m_eState || m_pActiveShell != GetParentWindow()->GetCreateView()->GetWrtShellPtr())))
2783  {
2784  return;
2785  }
2786 
2787  m_bIgnoreViewChange = true;
2788 
2789  SwWrtShell *const pShell = GetWrtShell();
2790  sal_Int8 nActOutlineLevel = m_nOutlineLevel;
2791  SwOutlineNodes::size_type nActPos = pShell->GetOutlinePos(nActOutlineLevel);
2792 
2793  std::vector<SwTextNode*> selectedOutlineNodes;
2794  std::vector<std::unique_ptr<weld::TreeIter>> selected;
2795 
2796  m_xTreeView->selected_foreach([this, pShell, &bLeftRight, &bOutlineWithChildren, &selected, &selectedOutlineNodes](weld::TreeIter& rEntry){
2797  // it's possible to select the root node too which is a really bad idea
2798  bool bSkip = lcl_IsContentType(rEntry, *m_xTreeView);
2799  // filter out children of selected parents so they don't get promoted
2800  // or moved twice (except if there is Ctrl modifier, since in that
2801  // case children are re-parented)
2802  if ((bLeftRight || bOutlineWithChildren) && !selected.empty())
2803  {
2804  std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
2805  for (bool bParent = m_xTreeView->iter_parent(*xParent); bParent; bParent = m_xTreeView->iter_parent(*xParent))
2806  {
2807  if (m_xTreeView->iter_compare(*selected.back(), *xParent) == 0)
2808  {
2809  bSkip = true;
2810  break;
2811  }
2812  }
2813  }
2814  if (!bSkip)
2815  {
2816  selected.emplace_back(m_xTreeView->make_iterator(&rEntry));
2817  const SwNodes& rNodes = pShell->GetNodes();
2818  const size_t nPos = GetAbsPos(rEntry) - 1;
2819  if (nPos < rNodes.GetOutLineNds().size())
2820  {
2821  SwNode* pNode = rNodes.GetOutLineNds()[ nPos ];
2822  if (pNode)
2823  {
2824  selectedOutlineNodes.push_back(pNode->GetTextNode());
2825  }
2826  }
2827  }
2828  return false;
2829  });
2830 
2831  if (bUpDown && !bUp)
2832  { // to move down, start at the end!
2833  std::reverse(selected.begin(), selected.end());
2834  }
2835 
2836  SwOutlineNodes::difference_type nDirLast = bUp ? -1 : 1;
2837  bool bStartedAction = false;
2838  for (auto const& pCurrentEntry : selected)
2839  {
2840  assert(pCurrentEntry && lcl_IsContent(*pCurrentEntry, *m_xTreeView));
2841  if (lcl_IsContent(*pCurrentEntry, *m_xTreeView))
2842  {
2843  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*pCurrentEntry).toInt64())));
2845  reinterpret_cast<SwContent*>(m_xTreeView->get_id(*pCurrentEntry).toInt64())->GetParent()->GetType()
2847  {
2848  nActPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*pCurrentEntry).toInt64())->GetOutlinePos();
2849  }
2850  }
2851  if (nActPos == SwOutlineNodes::npos || (bUpDown && !pShell->IsOutlineMovable(nActPos)))
2852  {
2853  continue;
2854  }
2855 
2856  if (!bStartedAction)
2857  {
2858  pShell->StartAllAction();
2859  pShell->StartUndo(bLeftRight ? SwUndoId::OUTLINE_LR : SwUndoId::OUTLINE_UD);
2860  bStartedAction = true;
2861  }
2862  pShell->GotoOutline( nActPos); // If text selection != box selection
2863  pShell->Push();
2864  pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren);
2865  if (bUpDown)
2866  {
2867  const size_t nEntryAbsPos(GetAbsPos(*pCurrentEntry));
2868  SwOutlineNodes::difference_type nDir = bUp ? -1 : 1;
2869  if (!bOutlineWithChildren && ((nDir == -1 && nActPos > 0) ||
2870  (nDir == 1 && nEntryAbsPos < GetEntryCount() - 2)))
2871  {
2872  pShell->MoveOutlinePara( nDir );
2873  // Set cursor back to the current position
2874  pShell->GotoOutline( nActPos + nDir);
2875  }
2876  else if (bOutlineWithChildren)
2877  {
2878  SwOutlineNodes::size_type nActEndPos = nActPos;
2879  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(pCurrentEntry.get()));
2880  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*pCurrentEntry).toInt64())));
2881  const auto nActLevel = reinterpret_cast<SwOutlineContent*>(
2882  m_xTreeView->get_id(*pCurrentEntry).toInt64())->GetOutlineLevel();
2883  bool bEntry = m_xTreeView->iter_next(*xEntry);
2884  while (bEntry && lcl_IsContent(*xEntry, *m_xTreeView))
2885  {
2886  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2887  if (nActLevel >= reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlineLevel())
2888  break;
2889  nActEndPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos();
2890  bEntry = m_xTreeView->iter_next(*xEntry);
2891  }
2892  if (nDir == 1) // move down
2893  {
2894  std::unique_ptr<weld::TreeIter> xNextSibling(m_xTreeView->make_iterator(pCurrentEntry.get()));
2895  if (m_xTreeView->iter_next_sibling(*xNextSibling) && m_xTreeView->is_selected(*xNextSibling))
2896  nDir = nDirLast;
2897  else
2898  {
2899  // If the last entry is to be moved we're done
2900  if (bEntry && lcl_IsContent(*xEntry, *m_xTreeView))
2901  {
2902  // xEntry now points to the entry following the last
2903  // selected entry.
2904  SwOutlineNodes::size_type nDest = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos();
2905  // here needs to found the next entry after next.
2906  // The selection must be inserted in front of that.
2907  while (bEntry)
2908  {
2909  bEntry = m_xTreeView->iter_next(*xEntry);
2910  assert(!bEntry || !lcl_IsContent(*xEntry, *m_xTreeView)||
2911  dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2912  // nDest++ may only executed if bEntry
2913  if (bEntry)
2914  {
2915  if (!lcl_IsContent(*xEntry, *m_xTreeView))
2916  break;
2917  else if (nActLevel >= reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlineLevel())
2918  {
2919  // nDest needs adjusted if there are selected entries (including ancestral lineage)
2920  // immediately before the current moved entry.
2921  std::unique_ptr<weld::TreeIter> xTmp(m_xTreeView->make_iterator(xEntry.get()));
2922  bool bTmp = m_xTreeView->iter_previous(*xTmp);
2923  while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) &&
2924  nActLevel < reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel())
2925  {
2926  while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) && !m_xTreeView->is_selected(*xTmp) &&
2927  nActLevel < reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel())
2928  {
2929  bTmp = m_xTreeView->iter_parent(*xTmp);
2930  }
2931  if (!bTmp || !m_xTreeView->is_selected(*xTmp))
2932  break;
2933  bTmp = m_xTreeView->iter_previous(*xTmp);
2934  nDest = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlinePos();
2935  }
2936  std::unique_ptr<weld::TreeIter> xPrevSibling(m_xTreeView->make_iterator(xEntry.get()));
2937  if (!m_xTreeView->iter_previous_sibling(*xPrevSibling) || !m_xTreeView->is_selected(*xPrevSibling))
2938  break;
2939  }
2940  else
2941  {
2942  nDest = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos();
2943  }
2944  }
2945  }
2946  nDirLast = nDir = nDest - nActEndPos;
2947  // If no entry was found that allows insertion before
2948  // it, we just move it to the end.
2949  }
2950  else
2951  nDirLast = nDir = 0;
2952  }
2953  }
2954  else // move up
2955  {
2956  std::unique_ptr<weld::TreeIter> xPrevSibling(m_xTreeView->make_iterator(pCurrentEntry.get()));
2957  if (m_xTreeView->iter_previous_sibling(*xPrevSibling) && m_xTreeView->is_selected(*xPrevSibling))
2958  nDir = nDirLast;
2959  else
2960  {
2961  SwOutlineNodes::size_type nDest = nActPos;
2962  bEntry = true;
2963  m_xTreeView->copy_iterator(*pCurrentEntry, *xEntry);
2964  while (bEntry && nDest)
2965  {
2966  bEntry = m_xTreeView->iter_previous(*xEntry);
2967  assert(!bEntry || !lcl_IsContent(*xEntry, *m_xTreeView) ||
2968  dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
2969  if (bEntry && lcl_IsContent(*xEntry, *m_xTreeView))
2970  {
2971  nDest = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos();
2972  }
2973  else
2974  {
2975  nDest = 0; // presumably?
2976  }
2977  if (bEntry)
2978  {
2979  if (!lcl_IsContent(*xEntry, *m_xTreeView))
2980  break;
2981  else if (nActLevel >= reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlineLevel())
2982  {
2983  // nDest needs adjusted if there are selected entries immediately
2984  // after the level change.
2985  std::unique_ptr<weld::TreeIter> xTmp(m_xTreeView->make_iterator(xEntry.get()));
2986  bool bTmp = m_xTreeView->iter_next(*xTmp);
2987  while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) &&
2988  nActLevel < reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel() &&
2989  m_xTreeView->is_selected(*xTmp))
2990  {
2991  nDest = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlinePos();
2992  const auto nLevel = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel();
2993  // account for selected entries' descendent lineage
2994  bTmp = m_xTreeView->iter_next(*xTmp);
2995  while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) &&
2996  nLevel < reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel())
2997  {
2998  nDest = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlinePos();
2999  bTmp = m_xTreeView->iter_next(*xTmp);
3000  }
3001  }
3002  break;
3003  }
3004  }
3005  }
3006  nDirLast = nDir = nDest - nActPos;
3007  }
3008  }
3009  if (nDir)
3010  {
3011  pShell->MoveOutlinePara( nDir );
3012  // Set cursor back to the current position
3013  pShell->GotoOutline(nActPos + nDir);
3014  }
3015  }
3016  }
3017  else
3018  {
3019  if (!pShell->IsProtectedOutlinePara())
3020  pShell->OutlineUpDown(bLeft ? -1 : 1);
3021  }
3022 
3023  pShell->ClearMark();
3024  pShell->Pop(SwCursorShell::PopMode::DeleteCurrent); // Cursor is now back at the current heading.
3025  }
3026 
3027  if (bStartedAction)
3028  {
3029  pShell->EndUndo();
3030  pShell->EndAllAction();
3033 
3034  // clear all selections to prevent the Display function from trying to reselect selected entries
3035  m_xTreeView->unselect_all();
3036  Display(true);
3037 
3038  // reselect entries
3039  const SwOutlineNodes::size_type nCurrPos = pShell->GetOutlinePos(MAXLEVEL);
3040  std::unique_ptr<weld::TreeIter> xListEntry(m_xTreeView->make_iterator());
3041  bool bListEntry = m_xTreeView->get_iter_first(*xListEntry);
3042  while ((bListEntry = m_xTreeView->iter_next(*xListEntry)) && lcl_IsContent(*xListEntry, *m_xTreeView))
3043  {
3044  assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xListEntry).toInt64())));
3045  if (reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xListEntry).toInt64())->GetOutlinePos() == nCurrPos)
3046  {
3047  std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(xListEntry.get()));
3048  if (m_xTreeView->iter_parent(*xParent) && !m_xTreeView->get_row_expanded(*xParent))
3049  m_xTreeView->expand_row(*xParent);
3050  m_xTreeView->set_cursor(*xListEntry); // unselect all entries, make entry visible, set focus, and select
3051  Select();
3052  break;
3053  }
3054  }
3055 
3056  if (m_bIsRoot)
3057  {
3058  const SwOutlineNodes& rOutLineNds = pShell->GetNodes().GetOutLineNds();
3059  for (SwTextNode* pNode : selectedOutlineNodes)
3060  {
3061  SwOutlineNodes::const_iterator aFndIt = rOutLineNds.find(pNode);
3062  if(aFndIt == rOutLineNds.end())
3063  continue;
3064  const size_t nFndPos = aFndIt - rOutLineNds.begin();
3065  std::unique_ptr<weld::TreeIter> xEntry = GetEntryAtAbsPos(nFndPos + 1);
3066  if (xEntry)
3067  {
3068  m_xTreeView->select(*xEntry);
3069  std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(xEntry.get()));
3070  if (m_xTreeView->iter_parent(*xParent) && !m_xTreeView->get_row_expanded(*xParent))
3071  m_xTreeView->expand_row(*xParent);
3072  }
3073  }
3074  }
3075  }
3076  m_bIgnoreViewChange = false;
3077 }
3078 
3080 {
3081  m_xTreeView->show();
3082  m_aUpdTimer.Start();
3083 }
3084 
3086 {
3087  // folded together will not be idled
3088  m_aUpdTimer.Stop();
3089  m_xTreeView->hide();
3090 }
3091 
3093  std::u16string_view rContentTypeName, std::u16string_view rName)
3094 {
3095  if (!rName.empty())
3096  {
3097  // find content type entry
3098  std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator());
3099  bool bFoundEntry = rContentTree.get_iter_first(*xIter);
3100  while (bFoundEntry && rContentTypeName != rContentTree.get_text(*xIter))
3101  bFoundEntry = rContentTree.iter_next_sibling(*xIter);
3102  // find content type content entry and select it
3103  if (bFoundEntry)
3104  {
3105  rContentTree.expand_row(*xIter); // assure content type entry is expanded
3106  while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
3107  {
3108  if (rName == rContentTree.get_text(*xIter))
3109  {
3110  // get first selected for comparison
3111  std::unique_ptr<weld::TreeIter> xFirstSelected(rContentTree.make_iterator());
3112  if (!rContentTree.get_selected(xFirstSelected.get()))
3113  xFirstSelected.reset();
3114  if (rContentTree.count_selected_rows() != 1 ||
3115  rContentTree.iter_compare(*xIter, *xFirstSelected) != 0)
3116  {
3117  // unselect all entries and make passed entry visible and selected
3118  rContentTree.set_cursor(*xIter);
3119  pThis->Select();
3120  }
3121  break;
3122  }
3123  }
3124  }
3125  }
3126 }
3127 
3129 IMPL_LINK_NOARG(SwContentTree, TimerUpdate, Timer *, void)
3130 {
3131  // No update while focus is not in document.
3132  // No update while drag and drop.
3133  // Query view because the Navigator is cleared too late.
3134  SwView* pView = GetParentWindow()->GetCreateView();
3135  if(pView && pView->GetWrtShellPtr() && pView->GetWrtShellPtr()->GetWin() &&
3136  (pView->GetWrtShellPtr()->GetWin()->HasFocus() || m_bViewHasChanged) &&
3137  !IsInDrag() && !pView->GetWrtShellPtr()->ActionPend())
3138  {
3139  m_bViewHasChanged = false;
3140  m_bIsIdleClear = false;
3141  SwWrtShell* pActShell = pView->GetWrtShellPtr();
3142  if (State::CONSTANT == m_eState && !lcl_FindShell(m_pActiveShell))
3143  {
3144  SetActiveShell(pActShell);
3145  GetParentWindow()->UpdateListBox();
3146  }
3147 
3148  if (State::ACTIVE == m_eState && pActShell != GetWrtShell())
3149  {
3150  SetActiveShell(pActShell);
3151  }
3152  else if ((State::ACTIVE == m_eState || (State::CONSTANT == m_eState && pActShell == GetWrtShell())) &&
3153  HasContentChanged())
3154  {
3155  FindActiveTypeAndRemoveUserData();
3156  Display(true);
3157  }
3158 
3159  UpdateTracking();
3160  }
3161  else if (!pView && State::ACTIVE == m_eState && !m_bIsIdleClear)
3162  {
3163  if(m_pActiveShell)
3164  {
3165  SetActiveShell(nullptr);
3166  }
3167  clear();
3168  m_bIsIdleClear = true;
3169  }
3170 }
3171 
3173 {
3174  if (State::HIDDEN == m_eState)
3175  return;
3176 
3177  // m_bIgnoreViewChange is set on delete
3178  if (m_bIgnoreViewChange)
3179  {
3180  m_bIgnoreViewChange = false;
3181  return;
3182  }
3183 
3184  // drawing
3189  {
3190  SdrView* pSdrView = m_pActiveShell->GetDrawView();
3191  if(pSdrView && 1 == pSdrView->GetMarkedObjectCount())
3192  {
3193  SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(0);
3194  OUString aName(pSelected->GetName());
3196  SwResId(STR_CONTENT_TYPE_DRAWOBJECT), aName);
3197  }
3198  return;
3199  }
3200  // graphic, frame, and ole
3201  OUString aContentTypeName;
3204  aContentTypeName = SwResId(STR_CONTENT_TYPE_GRAPHIC);
3207  aContentTypeName = SwResId(STR_CONTENT_TYPE_FRAME);
3210  aContentTypeName = SwResId(STR_CONTENT_TYPE_OLE);
3211  if (!aContentTypeName.isEmpty())
3212  {
3213  OUString aName(m_pActiveShell->GetFlyName());
3214  lcl_SelectByContentTypeAndName(this, *m_xTreeView, aContentTypeName, aName);
3215  return;
3216  }
3217  // table
3220  {
3222  {
3223  OUString aName = m_pActiveShell->GetTableFormat()->GetName();
3224  lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_TABLE),
3225  aName);
3226  }
3227  return;
3228  }
3229  // outline
3230  // find out where the cursor is
3233  m_nOutlineTracking == 3 || nActPos == SwOutlineNodes::npos))
3234  {
3235  // assure outline content type is expanded
3236  // this assumes outline content type is first in treeview
3237  std::unique_ptr<weld::TreeIter> xFirstEntry(m_xTreeView->make_iterator());
3238  if (m_xTreeView->get_iter_first(*xFirstEntry))
3239  m_xTreeView->expand_row(*xFirstEntry);
3240 
3241  m_xTreeView->all_foreach([this, nActPos](weld::TreeIter& rEntry){
3242  bool bRet = false;
3243  if (lcl_IsContent(rEntry, *m_xTreeView) && reinterpret_cast<SwContent*>(
3244  m_xTreeView->get_id(rEntry).toInt64())->GetParent()->GetType() ==
3246  {
3247  if (reinterpret_cast<SwOutlineContent*>(
3248  m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos() == nActPos)
3249  {
3250  std::unique_ptr<weld::TreeIter> xFirstSelected(
3251  m_xTreeView->make_iterator());
3252  if (!m_xTreeView->get_selected(xFirstSelected.get()))
3253  xFirstSelected.reset();
3254  // only select if not already selected or tree has multiple entries selected
3255  if (m_xTreeView->count_selected_rows() != 1 ||
3256  m_xTreeView->iter_compare(rEntry, *xFirstSelected) != 0)
3257  {
3258  if (m_nOutlineTracking == 2) // focused outline tracking
3259  {
3260  // collapse to children of root node
3261  std::unique_ptr<weld::TreeIter> xChildEntry(
3262  m_xTreeView->make_iterator());
3263  if (m_xTreeView->get_iter_first(*xChildEntry) &&
3264  m_xTreeView->iter_children(*xChildEntry))
3265  {
3266  do
3267  {
3268  if (reinterpret_cast<SwContent*>(
3269  m_xTreeView->get_id(*xChildEntry).toInt64())->
3270  GetParent()->GetType() == ContentTypeId::OUTLINE)
3271  m_xTreeView->collapse_row(*xChildEntry);
3272  else
3273  break;
3274  }
3275  while (m_xTreeView->iter_next(*xChildEntry));
3276  }
3277  }
3278  // unselect all entries, make pEntry visible, and select
3279  m_xTreeView->set_cursor(rEntry);
3280  Select();
3281  }
3282  bRet = true;
3283  }
3284  }
3285  else
3286  {
3287  // use of this break assumes outline content type is first in tree
3288  if (lcl_IsContentType(rEntry, *m_xTreeView) &&
3289  reinterpret_cast<SwContentType*>(
3290  m_xTreeView->get_id(rEntry).toInt64())->GetType() !=
3292  bRet = true;
3293  }
3294  return bRet;
3295  });
3296  }
3297  else
3298  {
3299  // clear treeview selections
3300  m_xTreeView->unselect_all();
3301  Select();
3302  }
3303 }
3304 
3306 {
3307  SwCursor* pFirstCursor = m_pActiveShell->GetSwCursor();
3308  SwCursor* pCursor = pFirstCursor;
3309  std::vector<SwOutlineNodes::size_type> aOutlinePositions;
3310  do
3311  {
3312  if (pCursor)
3313  {
3314  if (pCursor->HasMark())
3315  {
3316  aOutlinePositions.push_back(m_pActiveShell->GetOutlinePos(UCHAR_MAX, pCursor));
3317  }
3318  pCursor = pCursor->GetNext();
3319  }
3320  } while (pCursor && pCursor != pFirstCursor);
3321 
3322  if (!aOutlinePositions.empty())
3323  {
3324  // remove duplicates before selecting
3325  aOutlinePositions.erase(std::unique(aOutlinePositions.begin(), aOutlinePositions.end()),
3326  aOutlinePositions.end());
3327 
3328  m_xTreeView->unselect_all();
3329 
3330  for (auto nOutlinePosition : aOutlinePositions)
3331  {
3332  m_xTreeView->all_foreach([this, nOutlinePosition](const weld::TreeIter& rEntry){
3333  if (lcl_IsContent(rEntry, *m_xTreeView) &&
3334  reinterpret_cast<SwContent*>(
3335  m_xTreeView->get_id(rEntry).toInt64())->GetParent()->GetType() ==
3337  {
3338  if (reinterpret_cast<SwOutlineContent*>(
3339  m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos() ==
3340  nOutlinePosition)
3341  {
3342  std::unique_ptr<weld::TreeIter> xParent =
3343  m_xTreeView->make_iterator(&rEntry);
3344  if (m_xTreeView->iter_parent(*xParent) &&
3345  !m_xTreeView->get_row_expanded(*xParent))
3346  m_xTreeView->expand_row(*xParent);
3347  m_xTreeView->select(rEntry);
3348  return true;
3349  }
3350  }
3351  return false;
3352  });
3353  }
3354 
3355  Select();
3356  }
3357 }
3358 
3360 {
3361  SwWrtShell *const pShell = GetWrtShell();
3362  pShell->StartAllAction();
3364 
3366  SwOutlineNodes::size_type nPrevTargetPosOrOffset = SwOutlineNodes::npos;
3367 
3368  bool bFirstMove = true;
3369 
3370  for (const auto& source : m_aDndOutlinesSelected)
3371  {
3372  SwOutlineNodes::size_type nSourcePos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*source).toInt64())->GetOutlinePos();
3373 
3374  // Done on the first selection move
3375  if (bFirstMove) // only do once
3376  {
3377  if (nTargetPos == SwOutlineNodes::npos || nSourcePos > nTargetPos)
3378  {
3379  // Up moves
3380  // The first up move sets the up move amount for the remaining selected outlines to be moved
3381  if (nTargetPos != SwOutlineNodes::npos)
3382  nPrevTargetPosOrOffset = nSourcePos - nTargetPos;
3383  else
3384  nPrevTargetPosOrOffset = nSourcePos + 1;
3385  }
3386  else if (nSourcePos < nTargetPos)
3387  {
3388  // Down moves
3389  // The first down move sets the source and target positions for the remaining selected outlines to be moved
3390  nPrevSourcePos = nSourcePos;
3391  nPrevTargetPosOrOffset = nTargetPos;
3392  }
3393  bFirstMove = false;
3394  }
3395  else
3396  {
3397  if (nTargetPos == SwOutlineNodes::npos || nSourcePos > nTargetPos)
3398  {
3399  // Move up
3400  nTargetPos = nSourcePos - nPrevTargetPosOrOffset;
3401  }
3402  else if (nSourcePos < nTargetPos)
3403  {
3404  // Move down
3405  nSourcePos = nPrevSourcePos;
3406  nTargetPos = nPrevTargetPosOrOffset;
3407  }
3408  }
3409  GetParentWindow()->MoveOutline(nSourcePos, nTargetPos);
3410  }
3411 
3412  pShell->EndUndo();
3413  pShell->EndAllAction();
3415  Display(true);
3416  m_aDndOutlinesSelected.clear();
3417 }
3418 
3419 // Update immediately
3421 {
3422  SwView* pActView = GetParentWindow()->GetCreateView();
3423  if(pActView)
3424  {
3425  SwWrtShell* pActShell = pActView->GetWrtShellPtr();
3426  if (State::CONSTANT == m_eState && !lcl_FindShell(m_pActiveShell))
3427  {
3428  SetActiveShell(pActShell);
3429  }
3430 
3431  if (State::ACTIVE == m_eState && pActShell != GetWrtShell())
3432  SetActiveShell(pActShell);
3433  else if ((State::ACTIVE == m_eState || (State::CONSTANT == m_eState && pActShell == GetWrtShell())) &&
3434  HasContentChanged())
3435  {
3436  Display(true);
3437  }
3438  }
3439  else if (State::ACTIVE == m_eState)
3440  clear();
3441 }
3442 
3443 IMPL_LINK(SwContentTree, KeyInputHdl, const KeyEvent&, rEvent, bool)
3444 {
3445  bool bConsumed = true;
3446 
3447  const vcl::KeyCode aCode = rEvent.GetKeyCode();
3448  if (aCode.GetCode() == KEY_MULTIPLY && aCode.IsMod1())
3449  {
3450  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
3451  if (m_xTreeView->get_selected(xEntry.get()))
3452  ExpandOrCollapseAll(*m_xTreeView, *xEntry);
3453  }
3454  else if (aCode.GetCode() == KEY_RETURN)
3455  {
3456  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
3457  if (m_xTreeView->get_selected(xEntry.get()))
3458  {
3459  switch(aCode.GetModifier())
3460  {
3461  case KEY_MOD2:
3462  // Switch boxes
3463  GetParentWindow()->ToggleTree();
3464  break;
3465  case KEY_MOD1:
3466  // Switch RootMode
3467  ToggleToRoot();
3468  break;
3469  case 0:
3470  if (lcl_IsContentType(*xEntry, *m_xTreeView))
3471  {
3472  m_xTreeView->get_row_expanded(*xEntry) ? m_xTreeView->collapse_row(*xEntry)
3473  : m_xTreeView->expand_row(*xEntry);
3474  }
3475  else
3476  ContentDoubleClickHdl(*m_xTreeView);
3477  break;
3478  }
3479  }
3480  }
3481  else if(aCode.GetCode() == KEY_DELETE && 0 == aCode.GetModifier())
3482  {
3483  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
3484  if (m_xTreeView->get_selected(xEntry.get()) && lcl_IsContent(*xEntry, *m_xTreeView))
3485  {
3486  assert(dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
3487  if (reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64())->GetParent()->IsDeletable() &&
3488  !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
3489  {
3490  EditEntry(*xEntry, EditEntryMode::DELETE);
3491  }
3492  }
3493  }
3494  //Make KEY_SPACE has same function as DoubleClick ,
3495  //and realize multi-selection .
3496  else if (aCode.GetCode() == KEY_SPACE && 0 == aCode.GetModifier())
3497  {
3498  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
3499  if (m_xTreeView->get_cursor(xEntry.get()))
3500  {
3501  if (State::HIDDEN != m_eState)
3502  {
3503  if (State::CONSTANT == m_eState)
3504  {
3505  m_pActiveShell->GetView().GetViewFrame()->GetWindow().ToTop();
3506  }
3507 
3508  SwContent* pCnt = dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64()));
3509 
3510  if (pCnt && pCnt->GetParent()->GetType() == ContentTypeId::DRAWOBJECT)
3511  {
3512  SdrView* pDrawView = m_pActiveShell->GetDrawView();
3513  if (pDrawView)
3514  {
3515  pDrawView->SdrEndTextEdit();
3516 
3517  SwDrawModel* pDrawModel = m_pActiveShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
3518  SdrPage* pPage = pDrawModel->GetPage(0);
3519  const size_t nCount = pPage->GetObjCount();
3520  bool hasObjectMarked = false;
3521 
3522  if (SdrObject* pObject = GetDrawingObjectsByContent(pCnt))
3523  {
3524  SdrPageView* pPV = pDrawView->GetSdrPageView/*GetPageViewPvNum*/(/*0*/);
3525  if( pPV )
3526  {
3527  bool bUnMark = pDrawView->IsObjMarked(pObject);
3528  pDrawView->MarkObj( pObject, pPV, bUnMark);
3529 
3530  }
3531  }
3532  for( size_t i=0; i<nCount; ++i )
3533  {
3534  SdrObject* pTemp = pPage->GetObj(i);
3535  bool bMark = pDrawView->IsObjMarked(pTemp);
3536  switch( pTemp->GetObjIdentifier() )
3537  {
3538  case OBJ_GRUP:
3539  case OBJ_TEXT:
3540  case OBJ_LINE:
3541  case OBJ_RECT:
3542  case OBJ_CIRC:
3543  case OBJ_SECT:
3544  case OBJ_CARC:
3545  case OBJ_CCUT:
3546  case OBJ_POLY:
3547  case OBJ_PLIN:
3548  case OBJ_PATHLINE:
3549  case OBJ_PATHFILL:
3550  case OBJ_FREELINE:
3551  case OBJ_FREEFILL:
3552  case OBJ_PATHPOLY:
3553  case OBJ_PATHPLIN:
3554  case OBJ_CAPTION:
3555  case OBJ_CUSTOMSHAPE:
3556  if( bMark )
3557  hasObjectMarked = true;
3558  break;
3559  default:
3560  if ( bMark )
3561  {
3562  SdrPageView* pPV = pDrawView->GetSdrPageView/*GetPageViewPvNum*/(/*0*/);
3563  if (pPV)
3564  {
3565  pDrawView->MarkObj(pTemp, pPV, true);
3566  }
3567  }
3568  }
3569  //mod end
3570  }
3571  if ( !hasObjectMarked )
3572  {
3573  SwEditWin& rEditWindow = m_pActiveShell->GetView().GetEditWin();
3574  vcl::KeyCode tempKeycode( KEY_ESCAPE );
3575  KeyEvent rKEvt( 0 , tempKeycode );
3576  static_cast<vcl::Window*>(&rEditWindow)->KeyInput( rKEvt );
3577  }
3578  }
3579  }
3580 
3581  m_bViewHasChanged = true;
3582  }
3583  }
3584  }
3585  else
3586  {
3587  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
3588  if (m_xTreeView->get_cursor(xEntry.get()))
3589  {
3590  SwContent* pCnt = dynamic_cast<SwContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64()));
3591  if (pCnt && pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE)
3592  {
3593  if (m_bIsRoot && aCode.GetCode() == KEY_LEFT && aCode.GetModifier() == 0)
3594  {
3595  m_xTreeView->unselect_all();
3596  bConsumed = false;
3597  }
3598  else if (aCode.IsMod1())
3599  {
3600  if (aCode.GetCode() == KEY_LEFT)
3601  ExecCommand("promote", !aCode.IsShift());
3602  else if (aCode.GetCode() == KEY_RIGHT)
3603  ExecCommand("demote", !aCode.IsShift());
3604  else if (aCode.GetCode() == KEY_UP)
3605  ExecCommand("chapterup", !aCode.IsShift());
3606  else if (aCode.GetCode() == KEY_DOWN)
3607  ExecCommand("chapterdown", !aCode.IsShift());
3608  else
3609  bConsumed = false;
3610  }
3611  else
3612  bConsumed = false;
3613  }
3614  else
3615  bConsumed = false;
3616  }
3617  else
3618  bConsumed = false;
3619  }
3620  return bConsumed;
3621 }
3622 
3623 IMPL_LINK(SwContentTree, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString)
3624 {
3626  bool bContent = false;
3627  void* pUserData = reinterpret_cast<void*>(m_xTreeView->get_id(rEntry).toInt64());
3628  if (lcl_IsContentType(rEntry, *m_xTreeView))
3629  {
3630  assert(dynamic_cast<SwContentType*>(static_cast<SwTypeNumber*>(pUserData)));
3631  nType = static_cast<SwContentType*>(pUserData)->GetType();
3632  }
3633  else
3634  {
3635  assert(dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pUserData)));
3636  nType = static_cast<SwContent*>(pUserData)->GetParent()->GetType();
3637  bContent = true;
3638  }
3639  OUString sEntry;
3640  if(bContent)
3641  {
3642  switch( nType )
3643  {
3645  assert(dynamic_cast<SwURLFieldContent*>(static_cast<SwTypeNumber*>(pUserData)));
3646  sEntry = static_cast<SwURLFieldContent*>(pUserData)->GetURL();
3647  break;
3648 
3649  case ContentTypeId::POSTIT:
3650  assert(dynamic_cast<SwPostItContent*>(static_cast<SwTypeNumber*>(pUserData)));
3651  sEntry = static_cast<SwPostItContent*>(pUserData)->GetName();
3652  break;
3654  assert(dynamic_cast<SwOutlineContent*>(static_cast<SwTypeNumber*>(pUserData)));
3655  sEntry = static_cast<SwOutlineContent*>(pUserData)->GetName();
3656  break;
3658  assert(dynamic_cast<SwGraphicContent*>(static_cast<SwTypeNumber*>(pUserData)));
3659  sEntry = static_cast<SwGraphicContent*>(pUserData)->GetLink();
3660  break;
3661  case ContentTypeId::REGION:
3662  {
3663  assert(dynamic_cast<SwRegionContent*>(static_cast<SwTypeNumber*>(pUserData)));
3664  sEntry = static_cast<SwRegionContent*>(pUserData)->GetName();
3665  const SwSectionFormats& rFormats = GetWrtShell()->GetDoc()->GetSections();
3666  for (SwSectionFormats::size_type n = rFormats.size(); n;)
3667  {
3668  const SwNodeIndex* pIdx = nullptr;
3669  const SwSectionFormat* pFormat = rFormats[--n];
3670  const SwSection* pSect;
3671  if (nullptr != (pSect = pFormat->GetSection()) &&
3672  pSect->GetSectionName() == sEntry &&
3673  nullptr != (pIdx = pFormat->GetContent().GetContentIdx()) &&
3674  pIdx->GetNode().GetNodes().IsDocNodes())
3675  {
3676  SwDocStat aDocStat;
3677  SwPaM aPaM(*pIdx, *pIdx->GetNode().EndOfSectionNode());
3678  SwDoc::CountWords(aPaM, aDocStat);
3679  sEntry = SwResId(STR_REGION_DEFNAME) + ": " + sEntry + "\n" +
3680  SwResId(FLD_STAT_WORD) + ": " + OUString::number(aDocStat.nWord) + "\n" +
3681  SwResId(FLD_STAT_CHAR) + ": " + OUString::number(aDocStat.nChar);
3682  break;
3683  }
3684  }
3685  }
3686  break;
3687  default: break;
3688  }
3689  if(static_cast<SwContent*>(pUserData)->IsInvisible())
3690  {
3691  if(!sEntry.isEmpty())
3692  sEntry += ", ";
3693  sEntry += m_sInvisible;
3694  }
3695  }
3696  else
3697  {
3698  const size_t nMemberCount = static_cast<SwContentType*>(pUserData)->GetMemberCount();
3699  sEntry = OUString::number(nMemberCount) + " " +
3700  (nMemberCount == 1
3701  ? static_cast<SwContentType*>(pUserData)->GetSingleName()
3702  : static_cast<SwContentType*>(pUserData)->GetName());
3703  }
3704 
3705  return sEntry;
3706 }
3707 
3708 void SwContentTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry)
3709 {
3710  std::unique_ptr<weld::TreeIter> xFirst(m_xTreeView->make_iterator());
3711  if (!m_xTreeView->get_selected(xFirst.get()))
3712  xFirst.reset();
3713 
3714  auto nSelectedPopupEntry = rSelectedPopupEntry.toUInt32();
3715  switch (nSelectedPopupEntry)
3716  {
3717  case 1512: // fold or unfold outline content of selected entry
3718  case 1513: // fold outline content of selected entry and descendants
3719  case 1514: // unfold outline content of selected entry and descendants
3720  {
3722  m_bIgnoreViewChange = true;
3723  SwOutlineContent* pCntFirst = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xFirst).toInt64());
3724  if (nSelectedPopupEntry == 1512)
3725  {
3727  }
3728  else
3729  {
3730  // with subs
3732  if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
3733  nPos = SwOutlineNodes::npos;
3735  int nLevel = -1;
3736  if (nPos != SwOutlineNodes::npos) // not root
3738  else
3739  nPos = 0;
3740  bool bFold(nSelectedPopupEntry == 1514);
3741  do
3742  {
3743  if (m_pActiveShell->IsOutlineContentFolded(nPos) == bFold)
3745  } while (++nPos < nOutlineNodesCount
3746  && (nLevel == -1 || m_pActiveShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel));
3747  }
3748  if (lcl_IsContentType(*xFirst, *m_xTreeView)) // Headings root entry
3749  m_pActiveShell->GotoPage(1, true);
3750  else
3751  GotoContent(pCntFirst);
3752  grab_focus();
3753  m_bIgnoreViewChange = false;
3754  }
3755  break;
3756  case 11:
3757  case 12:
3758  case 13:
3759  nSelectedPopupEntry -= 10;
3760  if(m_nOutlineTracking != nSelectedPopupEntry)
3761  m_nOutlineTracking = nSelectedPopupEntry;
3762  break;
3763  //Outlinelevel
3764  case 101:
3765  case 102:
3766  case 103:
3767  case 104:
3768  case 105:
3769  case 106:
3770  case 107:
3771  case 108:
3772  case 109:
3773  case 110:
3774  nSelectedPopupEntry -= 100;
3775  if(m_nOutlineLevel != nSelectedPopupEntry )
3776  SetOutlineLevel(static_cast<sal_Int8>(nSelectedPopupEntry));
3777  break;
3778  case 201:
3779  case 202:
3780  case 203:
3781  GetParentWindow()->SetRegionDropMode(static_cast<RegionMode>(nSelectedPopupEntry - 201));
3782  break;
3783  case 401:
3784  case 402:
3785  EditEntry(*xFirst, nSelectedPopupEntry == 401 ? EditEntryMode::RMV_IDX : EditEntryMode::UPD_IDX);
3786  break;
3787  // Edit entry
3788  case 403:
3789  EditEntry(*xFirst, EditEntryMode::EDIT);
3790  break;
3791  case 404:
3793  break;
3794  case 405 :
3795  {
3796  const SwTOXBase* pBase = reinterpret_cast<SwTOXBaseContent*>(m_xTreeView->get_id(*xFirst).toInt64())
3797  ->GetTOXBase();
3799  }
3800  break;
3801  case 4:
3802  break;
3803  case 501:
3804  EditEntry(*xFirst, EditEntryMode::DELETE);
3805  break;
3806  case 502 :
3807  EditEntry(*xFirst, EditEntryMode::RENAME);
3808  break;
3809  case 600:
3811  break;
3812  case 601:
3814  break;
3815  case 602:
3816  {
3819  break;
3820  }
3821  case 700:
3822  {
3824  break;
3825  }
3826  case 800:
3827  ExpandOrCollapseAll(*m_xTreeView, *xFirst);
3828  break;
3829  case 801:
3830  ExecCommand("chapterup", true);
3831  break;
3832  case 802:
3833  ExecCommand("chapterdown", true);
3834  break;
3835  case 803:
3836  ExecCommand("promote", true);
3837  break;
3838  case 804:
3839  ExecCommand("demote", true);
3840  break;
3841  case 805:
3842  {
3846  SwContent* pCnt = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xFirst).toInt64());
3847  const ContentTypeId eTypeId = pCnt->GetParent()->GetType();
3848  if (eTypeId == ContentTypeId::OUTLINE)
3849  {
3850  m_xTreeView->selected_foreach([this](weld::TreeIter& rEntry){
3852  SwOutlineNodes::size_type nActPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos();
3853  m_pActiveShell->MakeOutlineSel(nActPos, nActPos, !m_xTreeView->get_row_expanded(rEntry), false); // select children if not expanded
3855  return false;
3856  });
3857  }
3858  else if (eTypeId == ContentTypeId::TABLE)
3859  {
3860  m_pActiveShell->GotoTable(pCnt->GetName());
3862  }
3863  else if (eTypeId == ContentTypeId::REGION)
3864  {
3866  m_pActiveShell->GotoRegion(pCnt->GetName());
3872  }
3874  }
3875  break;
3876  case 806:
3877  // Delete outline selections
3878  EditEntry(*xFirst, EditEntryMode::DELETE);
3879  break;
3880  case 900:
3881  {
3882  SwContent* pCnt = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xFirst).toInt64());
3883  GotoContent(pCnt);
3884  }
3885  break;
3886  //Display
3887  default:
3888  if(nSelectedPopupEntry > 300 && nSelectedPopupEntry < 400)
3889  {
3890  nSelectedPopupEntry -= 300;
3891  SwView *pView = SwModule::GetFirstView();
3892  while (pView)
3893  {
3894  nSelectedPopupEntry --;
3895  if(nSelectedPopupEntry == 0)
3896  {
3897  SetConstantShell(&pView->GetWrtShell());
3898  break;
3899  }
3900  pView = SwModule::GetNextView(pView);
3901  }
3902  if(nSelectedPopupEntry)
3903  {
3904  m_bViewHasChanged = nSelectedPopupEntry == 1;
3905  m_eState = (nSelectedPopupEntry == 1) ? State::ACTIVE : State::HIDDEN;
3906  Display(nSelectedPopupEntry == 1);
3907  }
3908  }
3909  }
3911 }
3912 
3914 {
3917  auto nChapters(0);
3918 
3919  m_xTreeView->selected_foreach([this, &nChapters](weld::TreeIter& rEntry){
3920  ++nChapters;
3921  if (m_xTreeView->iter_has_child(rEntry) &&
3922  !m_xTreeView->get_row_expanded(rEntry)) // only count children if not expanded
3923  {
3924  nChapters += m_xTreeView->iter_n_children(rEntry);
3925  }
3927  SwOutlineNodes::size_type nActPos = reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos();
3928  m_pActiveShell->MakeOutlineSel(nActPos, nActPos, !m_xTreeView->get_row_expanded(rEntry), false); // select children if not expanded
3930  return false;
3931  });
3933  SwRewriter aRewriter;
3934  aRewriter.AddRule(UndoArg1, SwResId(STR_CHAPTERS, nChapters));
3941 }
3942 
3944 {
3945  m_nOutlineLevel = nSet;
3947  std::unique_ptr<SwContentType>& rpContentT = (State::ACTIVE == m_eState)
3950  if(rpContentT)
3951  {
3952  rpContentT->SetOutlineLevel(m_nOutlineLevel);
3953  rpContentT->Init();
3954  }
3956 }
3957 
3958 // Mode Change: Show dropped Doc
3960 {
3961  if(m_pHiddenShell)
3962  {
3964  Display(false);
3965  }
3966 }
3967 
3968 // Mode Change: Show active view
3970 {
3972  Display(true);
3974 }
3975 
3977 {
3978  Select();
3979 }
3980 
3981 // Here the buttons for moving outlines are en-/disabled.
3983 {
3984  std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
3985  if (!m_xTreeView->get_selected(xEntry.get()))
3986  return;
3987 
3988  bool bEnable = false;
3989  std::unique_ptr<weld::TreeIter> xParentEntry(m_xTreeView->make_iterator(xEntry.get()));
3990  bool bParentEntry = m_xTreeView->iter_parent(*xParentEntry);
3991  while (bParentEntry && (!lcl_IsContentType(*xParentEntry, *m_xTreeView)))
3992  bParentEntry = m_xTreeView->iter_parent(*xParentEntry);
3993  if (!m_bIsLastReadOnly)
3994  {
3995  if (!m_xTreeView->get_visible())
3996  bEnable = true;
3997  else if (bParentEntry)
3998  {
4000  (lcl_IsContent(*xEntry, *m_xTreeView) &&
4001  reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xParentEntry).toInt64())->GetType() == ContentTypeId::OUTLINE))
4002  {
4003  bEnable = true;
4004  }
4005  }
4006  }
4007  SwNavigationPI* pNavi = GetParentWindow();
4008  pNavi->m_xContent6ToolBox->set_item_sensitive("chapterup", bEnable);
4009  pNavi->m_xContent6ToolBox->set_item_sensitive("chapterdown", bEnable);
4010  pNavi->m_xContent6ToolBox->set_item_sensitive("promote", bEnable);
4011  pNavi->m_xContent6ToolBox->set_item_sensitive("demote", bEnable);
4012 }
4013 
4015 {
4016  m_nRootType = nType;
4017  m_bIsRoot = true;
4019 }
4020 
4021 OUString SwContentType::RemoveNewline(const OUString& rEntry)
4022 {
4023  if (rEntry.isEmpty())
4024  return rEntry;
4025 
4026  OUStringBuffer aEntry(rEntry);
4027  for (sal_Int32 i = 0; i < rEntry.getLength(); ++i)
4028  if(aEntry[i] == 10 || aEntry[i] == 13)
4029  aEntry[i] = 0x20;
4030 
4031  return aEntry.makeStringAndClear();
4032 }
4033 
4035 {
4036  SwContent* pCnt = reinterpret_cast<SwContent*>(m_xTreeView->get_id(rEntry).toInt64());
4037  GotoContent(pCnt);
4038  const ContentTypeId nType = pCnt->GetParent()->GetType();
4039  sal_uInt16 nSlot = 0;
4040 
4041  if(EditEntryMode::DELETE == nMode)
4042  m_bIgnoreViewChange = true;
4043 
4044  uno::Reference< container::XNameAccess > xNameAccess, xSecond, xThird;
4045  switch(nType)
4046  {
4047  case ContentTypeId::OUTLINE :
4048  if(nMode == EditEntryMode::DELETE)
4049  {
4051  }
4052  break;
4053 
4054  case ContentTypeId::TABLE :
4055  if(nMode == EditEntryMode::UNPROTECT_TABLE)
4056  {
4058  GetDoc()->UnProtectCells( pCnt->GetName());
4059  }
4060  else if(nMode == EditEntryMode::DELETE)
4061  {
4063  OUString sTable = SwResId(STR_TABLE_NAME);
4064  SwRewriter aRewriterTableName;
4065  aRewriterTableName.AddRule(UndoArg1, SwResId(STR_START_QUOTE));
4066  aRewriterTableName.AddRule(UndoArg2, pCnt->GetName());
4067  aRewriterTableName.AddRule(UndoArg3, SwResId(STR_END_QUOTE));
4068  sTable = aRewriterTableName.Apply(sTable);
4069 
4070  SwRewriter aRewriter;
4071  aRewriter.AddRule(UndoArg1, sTable);
4077  }
4078  else if(nMode == EditEntryMode::RENAME)
4079  {
4080  uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
4081  uno::Reference< text::XTextTablesSupplier > xTables(xModel, uno::UNO_QUERY);
4082  xNameAccess = xTables->getTextTables();
4083  }
4084  else
4085  nSlot = FN_FORMAT_TABLE_DLG;
4086  break;
4087 
4088  case ContentTypeId::GRAPHIC :
4089  if(nMode == EditEntryMode::DELETE)
4090  {
4092  }
4093  else if(nMode == EditEntryMode::RENAME)
4094  {
4095  uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
4096  uno::Reference< text::XTextGraphicObjectsSupplier > xGraphics(xModel, uno::UNO_QUERY);
4097  xNameAccess = xGraphics->getGraphicObjects();
4098  uno::Reference< text::XTextFramesSupplier > xFrames(xModel, uno::UNO_QUERY);
4099  xSecond = xFrames->getTextFrames();
4100  uno::Reference< text::XTextEmbeddedObjectsSupplier > xObjs(xModel, uno::UNO_QUERY);
4101  xThird = xObjs->getEmbeddedObjects();
4102  }
4103  else
4104  nSlot = FN_FORMAT_GRAFIC_DLG;
4105  break;
4106 
4107  case ContentTypeId::FRAME :
4108  case ContentTypeId::OLE :
4109  if(nMode == EditEntryMode::DELETE)
4110  {
4112  }
4113  else if(nMode == EditEntryMode::RENAME)
4114  {
4115  uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
4116  uno::Reference< text::XTextFramesSupplier > xFrames(xModel, uno::UNO_QUERY);
4117  uno::Reference< text::XTextEmbeddedObjectsSupplier > xObjs(xModel, uno::UNO_QUERY);
4118  if(ContentTypeId::FRAME == nType)
4119  {
4120  xNameAccess = xFrames->getTextFrames();
4121  xSecond = xObjs->getEmbeddedObjects();
4122  }
4123  else
4124  {
4125  xNameAccess = xObjs->getEmbeddedObjects();
4126  xSecond = xFrames->getTextFrames();
4127  }
4128  uno::Reference< text::XTextGraphicObjectsSupplier > xGraphics(xModel, uno::UNO_QUERY);
4129  xThird = xGraphics->getGraphicObjects();
4130  }
4131  else
4132  nSlot = FN_FORMAT_FRAME_DLG;
4133  break;
4136  if(nMode == EditEntryMode::DELETE)
4137  {
4139  pMarkAccess->deleteMark( pMarkAccess->findMark(pCnt->GetName()) );
4140  }
4141  else if(nMode == EditEntryMode::RENAME)
4142  {
4143  uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
4144  uno::Reference< text::XBookmarksSupplier > xBkms(xModel, uno::UNO_QUERY);
4145  xNameAccess = xBkms->getBookmarks();
4146  }
4147  else
4148  nSlot = FN_INSERT_BOOKMARK;
4149  break;
4150 
4151  case ContentTypeId::REGION :
4152  if(nMode == EditEntryMode::RENAME)
4153  {
4154  uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel();
4155  uno::Reference< text::XTextSectionsSupplier > xSects(xModel, uno::UNO_QUERY);
4156  xNameAccess = xSects->getTextSections();
4157  }
4158  else
4159  nSlot = FN_EDIT_REGION;
4160  break;
4161 
4163  if (nMode == EditEntryMode::DELETE)
4164  nSlot = SID_REMOVE_HYPERLINK;
4165  else
4166  nSlot = SID_EDIT_HYPERLINK;
4167  break;
4169  nSlot = FN_EDIT_FIELD;
4170  break;
4171 
4172  case ContentTypeId::POSTIT:
4174  if(nMode == EditEntryMode::DELETE)
4175  {
4178  }
4179  else
4180  {
4181  nSlot = FN_POSTIT;
4182  }
4183  break;
4184  case ContentTypeId::INDEX:
4185  {
4186  const SwTOXBase* pBase = static_cast<SwTOXBaseContent*>(pCnt)->GetTOXBase();
4187  switch(nMode)
4188  {
4189  case EditEntryMode::EDIT:
4190  if(pBase)
4191  {
4192  SwPtrItem aPtrItem( FN_INSERT_MULTI_TOX, const_cast<SwTOXBase *>(pBase));
4195  SfxCallMode::ASYNCHRON, { &aPtrItem });
4196 
4197  }
4198  break;
4200  case EditEntryMode::DELETE:
4201  {
4202  if( pBase )
4203  m_pActiveShell->DeleteTOX(*pBase, EditEntryMode::DELETE == nMode);
4204  }
4205  break;
4207  case EditEntryMode::RENAME:
4208  {
4210  Reference< XDocumentIndexesSupplier > xIndexes(xModel, UNO_QUERY);
4211  Reference< XIndexAccess> xIdxAcc(xIndexes->getDocumentIndexes());
4212  Reference< XNameAccess >xLocalNameAccess(xIdxAcc, UNO_QUERY);
4213  if(EditEntryMode::RENAME == nMode)
4214  xNameAccess = xLocalNameAccess;
4215  else if(xLocalNameAccess.is() && xLocalNameAccess->hasByName(pBase->GetTOXName()))
4216  {
4217  Any aIdx = xLocalNameAccess->getByName(pBase->GetTOXName());
4218  Reference< XDocumentIndex> xIdx;
4219  if(aIdx >>= xIdx)
4220  xIdx->update();
4221  }
4222  }
4223  break;
4224  default: break;
4225  }
4226  }
4227  break;
4229  if(EditEntryMode::DELETE == nMode)
4230  nSlot = SID_DELETE;
4231  else if(nMode == EditEntryMode::RENAME)
4232  nSlot = FN_NAME_SHAPE;
4233  break;
4234  default: break;
4235  }
4236  if(nSlot)
4238  GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON);
4239  else if(xNameAccess.is())
4240  {
4241  uno::Any aObj = xNameAccess->getByName(pCnt->GetName());
4242  uno::Reference< uno::XInterface > xTmp;
4243  aObj >>= xTmp;
4244  uno::Reference< container::XNamed > xNamed(xTmp, uno::UNO_QUERY);
4247  if(xSecond.is())
4248  pDlg->SetAlternativeAccess( xSecond, xThird);
4249 
4250  OUString sForbiddenChars;
4251  if(ContentTypeId::BOOKMARK == nType)
4252  {
4253  sForbiddenChars = "/\\@:*?\";,.#";
4254  }
4255  else if(ContentTypeId::TABLE == nType)
4256  {
4257  sForbiddenChars = " .<>";
4258  }
4259  pDlg->SetForbiddenChars(sForbiddenChars);
4260  pDlg->Execute();
4261  }
4262  if(EditEntryMode::DELETE == nMode)
4263  {
4264  m_bViewHasChanged = true;
4266  TimerUpdate(&m_aUpdTimer);
4267  grab_focus();
4268  }
4269 }
4270 
4271 static void lcl_AssureStdModeAtShell(SwWrtShell* pWrtShell)
4272 {
4273  // deselect any drawing or frame and leave editing mode
4274  SdrView* pSdrView = pWrtShell->GetDrawView();
4275  if (pSdrView && pSdrView->IsTextEdit() )
4276  {
4277  bool bLockView = pWrtShell->IsViewLocked();
4278  pWrtShell->LockView(true);
4279  pWrtShell->EndTextEdit();
4280  pWrtShell->LockView(bLockView);
4281  }
4282 
4283  if (pWrtShell->IsSelFrameMode() || pWrtShell->IsObjSelected())
4284  {
4285  pWrtShell->UnSelectFrame();
4286  pWrtShell->LeaveSelFrameMode();
4287  pWrtShell->GetView().LeaveDrawCreate();
4288  pWrtShell->EnterStdMode();
4289  pWrtShell->DrawSelChanged();
4290  pWrtShell->GetView().StopShellTimer();
4291  }
4292  else
4293  pWrtShell->EnterStdMode();
4294 }
4295 
4297 {
4299 
4300  bool bSel = false;
4301  switch(pCnt->GetParent()->GetType())
4302  {
4303  case ContentTypeId::OUTLINE :
4304  {
4305  m_pActiveShell->GotoOutline(static_cast<const SwOutlineContent*>(pCnt)->GetOutlinePos());
4306  }
4307  break;
4308  case ContentTypeId::TABLE :
4309  {
4310  m_pActiveShell->GotoTable(pCnt->GetName());
4311  }
4312  break;
4313  case ContentTypeId::FRAME :
4314  case ContentTypeId::GRAPHIC :
4315  case ContentTypeId::OLE :
4316  {
4317  if(m_pActiveShell->GotoFly(pCnt->GetName()))
4318  bSel = true;
4319  }
4320  break;
4322  {
4323  m_pActiveShell->GotoMark(pCnt->GetName());
4324  }
4325  break;
4326  case ContentTypeId::REGION :
4327  {
4328  m_pActiveShell->GotoRegion(pCnt->GetName());
4329  }
4330  break;
4332  {
4334  *static_cast<const SwURLFieldContent*>(pCnt)->GetINetAttr() ))
4335  {
4336  m_pActiveShell->Right( CRSR_SKIP_CHARS, true, 1, false);
4337  m_pActiveShell->SwCursorShell::SelectTextAttr( RES_TXTATR_INETFMT, true );
4338  }
4339 
4340  }
4341  break;
4343  {
4345  }
4346  break;
4347  case ContentTypeId::INDEX:
4348  {
4349  const OUString& sName(pCnt->GetName());
4352  }
4353  break;
4354  case ContentTypeId::POSTIT:
4355  m_pActiveShell->GotoFormatField(*static_cast<const SwPostItContent*>(pCnt)->GetPostIt());
4356  break;
4358  {
4360  SdrView* pDrawView = m_pActiveShell->GetDrawView();
4361  if (pDrawView)
4362  {
4363  pDrawView->SdrEndTextEdit();
4364  pDrawView->UnmarkAll();
4366  SdrPage* pPage = _pModel->GetPage(0);
4367  const size_t nCount = pPage->GetObjCount();
4368  for( size_t i=0; i<nCount; ++i )
4369  {
4370  SdrObject* pTemp = pPage->GetObj(i);
4371  if (pTemp->GetName() == pCnt->GetName())
4372  {
4373  SdrPageView* pPV = pDrawView->GetSdrPageView();
4374  if( pPV )
4375  {
4376  pDrawView->MarkObj( pTemp, pPV );
4377  }
4378  }
4379  }
4382  bSel = true;
4383  }
4384  }
4385  break;
4386  default: break;
4387  }
4388  if(bSel)
4389  {
4392  }
4393  SwView& rView = m_pActiveShell->GetView();
4394  rView.StopShellTimer();
4395  rView.GetPostItMgr()->SetActiveSidebarWin(nullptr);
4396  rView.GetEditWin().GrabFocus();
4397 
4398  // force scroll to cursor position when navigating to inactive document
4399  if(!bSel)
4400  {
4401  Point rPoint = m_pActiveShell->GetCursorDocPos();
4402  rPoint.setX(0);
4403  rView.SetVisArea(rPoint);
4404  }
4405 }
4406 
4407 // Now even the matching text::Bookmark
4409  :
4410  nDocSh(0),
4411  nDefDrag( RegionMode::NONE )
4412 {
4413 }
4414 
4416  const OUString& rDesc,
4417  RegionMode nDragType,
4418  const SwDocShell* pDocSh ) :
4419  aUrl( rUrl ),
4420  aDescr(rDesc),
4421  nDocSh(reinterpret_cast<sal_IntPtr>(pDocSh)),
4422  nDefDrag( nDragType )
4423 {
4424 }
4425 
4427 {
4428  rtl_TextEncoding eSysCSet = osl_getThreadTextEncoding();
4429 
4430  OString sStrBuf(OUStringToOString(aUrl, eSysCSet) + OStringChar(NAVI_BOOKMARK_DELIM) +
4431  OUStringToOString(aDescr, eSysCSet) + OStringChar(NAVI_BOOKMARK_DELIM) +
4432  OString::number(static_cast<int>(nDefDrag)) + OStringChar(NAVI_BOOKMARK_DELIM) +
4433  OString::number(nDocSh));
4434  rData.CopyByteString(SotClipboardFormatId::SONLK, sStrBuf);
4435 }
4436 
4438 {
4439  OUString sStr;
4440  bool bRet = rData.GetString( SotClipboardFormatId::SONLK, sStr );
4441  if( bRet )
4442  {
4443  sal_Int32 nPos = 0;
4444  aUrl = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos );
4445  aDescr = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos );
4446  nDefDrag= static_cast<RegionMode>( sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos ).toInt32() );
4447  nDocSh = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos ).toInt32();
4448  }
4449  return bRet;
4450 }
4451 
4453 {
4454  return m_xDialog;
4455 }
4456 
4457 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static const char * STR_CONTENT_TYPE_ARY[]
Definition: content.cxx:210
SfxViewFrame * GetViewFrame() const
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:685
void StopShellTimer()
Definition: view.cxx:1751
static void lcl_AssureStdModeAtShell(SwWrtShell *pWrtShell)
Definition: content.cxx:4271
Base class for the following contact objects (frame + draw objects).
Definition: dcontact.hxx:66
void FillMemberList(bool *pbLevelChanged=nullptr)
Fill the List of contents.
Definition: content.cxx:519
bool RequestingChildren(const weld::TreeIter &rParent)
Definition: content.cxx:1606
void Init(bool *pbInvalidateWindow=nullptr)
Definition: content.cxx:280
void DeleteOutlineSelections()
Definition: content.cxx:3913
ContentTypeId
Definition: swcont.hxx:29
virtual bool IsProtect() const override
Definition: content.cxx:197
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
bool Right(sal_uInt16 nMode, bool bSelect, sal_uInt16 nCount, bool bBasicCall, bool bVisual=false)
Definition: move.cxx:123
void KillPams()
Definition: crsrsh.cxx:1021
OBJ_PATHPOLY
SAL_DLLPRIVATE void UpdateCursor(sal_uInt16 eFlags=SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE, bool bIdleEnd=false)
Definition: crsrsh.cxx:1567
const Value & back() const
OUString sText
Definition: editsh.hxx:119
void CopyINetBookmark(const INetBookmark &rBkmk)
OBJ_RECT
virtual void set_sensitive(const OString &rIdent, bool bSensitive)=0
bool bVisible
size_t GetTableFrameFormatCount(bool bUsed=false) const
TABLE.
Definition: edfmt.cxx:101
#define FN_EDIT_REGION
Definition: cmdid.h:108
OUString m_sTypeToken
Definition: content.hxx:146
Marks a position in the document model.
Definition: pam.hxx:35
OBJ_PATHPLIN
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
const SwNodes & GetNodes() const
Definition: viewsh.cxx:2089
virtual int count_selected_rows() const =0
virtual void DrawSelChanged() override
Definition: wrtsh3.cxx:104
constexpr sal_uInt16 KEY_MOD1
SdrView * GetDrawView()
Definition: vnew.cxx:375
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:190
size_t GetChildCount(const weld::TreeIter &rParent) const
Definition: content.cxx:1954
ContentTypeId m_nRootType
Definition: conttree.hxx:110
OUString GetTitle(sal_uInt16 nMaxLen=0) const
SwView * GetActiveView()
Definition: swmodul1.cxx:115
SwContentTreeDropTarget(SwContentTree &rTreeView)
Definition: content.cxx:1000
void SetRegionDropMode(RegionMode nNewMode)
Definition: navipi.cxx:991
size_t GetAbsPos(const weld::TreeView &rTreeView, const weld::TreeIter &rIter)
void SetHiddenShell(SwWrtShell *pSh)
After a file is dropped on the Navigator, the new shell will be set.
Definition: content.cxx:2645
bool IsProtect() const
Definition: atrfld.cxx:399
virtual OUString getOutlineText(const tSortedOutlineNodeList::size_type nIdx, SwRootFrame const *pLayout, const bool bWithNumber=true, const bool bWithSpacesForLevel=false, const bool bWithFootnote=true) const =0
OUString m_aContextStrings[CONTEXT_COUNT+1]
Definition: conttree.hxx:98
OBJ_GRUP
signed char sal_Int8
SwContent(const SwContentType *pCnt, const OUString &rName, tools::Long nYPos)
Definition: content.cxx:173
OBJ_CIRC
void ShowActualView()
Definition: content.cxx:3969
std::vector< SwNode * >::difference_type difference_type
SwWrtShell * m_pHiddenShell
Definition: conttree.hxx:101
const SwView & GetView() const
Definition: edtwin.hxx:244
const IDocumentOutlineNodes * getIDocumentOutlineNodesAccess() const
Definition: viewsh.cxx:2689
SfxDispatcher * GetDispatcher()
wrapper iterator: wraps iterator of implementation while hiding MarkBase class; only IMark instances ...
const_iterator begin() const
Definition: PostItMgr.hxx:178
IMPL_LINK(SwContentTree, DragBeginHdl, bool &, rUnsetDragIcon, bool)
Definition: content.cxx:949
bool HasContentChanged()
Check if the displayed content is valid.
Definition: content.cxx:2408
sal_uIntPtr sal_uLong
long Long
void SetOutlineLevel(sal_Int32 nSet)
Definition: navicfg.hxx:57
void UpdateLastSelType()
Definition: content.cxx:2617
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:475
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2687
OBJ_LINE
bool Pop(SwCursorShell::PopMode=SwCursorShell::PopMode::DeleteStack)
Definition: wrtsh1.cxx:1715
void Select()
Definition: content.cxx:3982
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
sal_Int64 n
SwContentTree(std::unique_ptr< weld::TreeView > xTreeView, SwNavigationPI *pDialog)
Definition: content.cxx:888
Provides access to the marks of a document.
SdrObject * GetObj(size_t nNum) const
SwCursor * GetSwCursor() const
Definition: crsrsh.hxx:868
void ExecCommand(std::string_view rCmd, bool bModifier)
Execute commands of the Navigator.
Definition: content.cxx:2772
#define FN_FORMAT_TABLE_DLG
Definition: cmdid.h:320
size_t GetObjCount() const
OBJ_POLY
sal_uLong nChar
Definition: docstat.hxx:37
void GotoFormatField(const SwFormatField &rField)
Definition: move.cxx:664
bool addEntry(const SwPosition &rPos)
Definition: navmgr.cxx:170
static weld::Builder * CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false)
sal_Int16 nId
std::unique_ptr< weld::Toolbar > m_xContent6ToolBox
Definition: navipi.hxx:61
static void lcl_SelectByContentTypeAndName(SwContentTree *pThis, weld::TreeView &rContentTree, std::u16string_view rContentTypeName, std::u16string_view rName)
Definition: content.cxx:3092
bool GotoINetAttr(const SwTextINetFormat &rAttr)
Definition: move.cxx:603
SwUndoId EndUndo(SwUndoId eUndoId=SwUndoId::EMPTY, const SwRewriter *pRewriter=nullptr)
Closes parenthesis of nUndoId, not used by UI.
Definition: edws.cxx:234
const_iterator find(const Value &x) const
const IDocumentSettingAccess & getIDocumentSettingAccess() const
Provides access to the document setting interface.
Definition: viewsh.cxx:2662
#define DND_ACTION_COPYMOVE
OBJ_CARC
sal_uInt16 GetCode() const
SwNode & GetNode() const
Definition: ndindex.hxx:119
void SetActiveSidebarWin(sw::annotation::SwAnnotationWin *p)
Definition: PostItMgr.cxx:2183
void CopyByteString(SotClipboardFormatId nFormatId, const OString &rStr)
void EnterStdMode()
Definition: select.cxx:550
SwEditWin & GetEditWin()
Definition: view.hxx:402
sal_Int8 ExecuteDrop(const ExecuteDropEvent &rEvt)
Definition: navipi.cxx:950
VclPtr< SwNavigationPI > m_xDialog
Definition: conttree.hxx:92
bool IsTOXBaseInReadonly() const
Definition: doctxm.cxx:2014
const SwDoc & GetDoc() const
Definition: drawdoc.hxx:35
constexpr sal_uInt16 KEY_SPACE
virtual SdrObjKind GetObjIdentifier() const
bool bReadOnly
#define FN_FORMAT_GRAFIC_DLG
Definition: cmdid.h:319
EmbeddedObjectRef * pObject
sal_uInt8 GetOutlineLevel() const
Definition: conttree.hxx:213
void EndAllAction()
Definition: edws.cxx:97
void HideTree()
Definition: content.cxx:3085
virtual bool GetInfo(SfxPoolItem &) const override
Definition: calbck.cxx:188
#define FN_EDIT_FIELD
Definition: cmdid.h:70
void UpdateTracking()
Definition: content.cxx:3172
bool GotoTable(const OUString &rName)
Definition: move.cxx:655
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4081
SfxHintId GetId() const
weld::TreeView & get_widget()
Definition: conttree.hxx:273
constexpr sal_uInt16 KEY_UP
static bool IsTOXBaseReadonly(const SwTOXBase &rTOXBase)
Definition: edtox.cxx:91
void EditEntry(const weld::TreeIter &rEntry, EditEntryMode nMode)
Definition: content.cxx:4034
void UpdateListBox()
Definition: navipi.cxx:809
bool IsProtect() const
Definition: txtatr2.cxx:185
void SetVisArea(const tools::Rectangle &, bool bUpdateScrollbar=true)
Definition: viewport.cxx:195
void ExecuteContextMenuAction(const OString &rSelectedPopupEntry)
Definition: content.cxx:3708
bool DelRight()
Definition: delete.cxx:292
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const =0
SwWrtShell & GetWrtShell() const
Definition: view.hxx:399
bool MakeOutlineSel(SwOutlineNodes::size_type nSttPos, SwOutlineNodes::size_type nEndPos, bool bWithChildren, bool bKillPams=true)
Definition: crstrvl.cxx:1157
void GetINetAttrs(SwGetINetAttrs &rArr)
Definition: editsh.cxx:688
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:155
Array of Undo-history.
Definition: docary.hxx:197
OBJ_SECT
#define DND_ACTION_MOVE
SwNavigationMgr & GetNavigationMgr()
Definition: wrtsh.hxx:470
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_CONTENT_VISIBLE(183)
sal_uInt16 GetRefMarks(std::vector< OUString > *=nullptr) const
get the names of all references in a Doc
Definition: editsh.cxx:448
bool IsOutlineContentFolded(const size_t nPos)
Definition: wrtsh1.cxx:1992
Used by the UI to modify the document model.
Definition: wrtsh.hxx:90
ContentTypeId GetType() const
Definition: content.hxx:165
sal_uInt8 m_nOutlineLevel
Definition: conttree.hxx:112
static const char * STR_CONTEXT_ARY[]
Definition: content.cxx:867
std::vector< SwFrameFormat const * > GetFlyFrameFormats(FlyCntType eType, bool bIgnoreTextBoxes)
Definition: feshview.cxx:2576
const OUString & GetValue() const
Definition: fmtinfmt.hxx:75
void FindActiveTypeAndRemoveUserData()
Before any data will be deleted, the last active entry has to be found.
Definition: content.cxx:2633
virtual bool IsVisibleLayerId(SdrLayerID _nLayerId) const =0
method to determine, if a layer ID belongs to the visible ones.
bool GotoFly(const OUString &rName, FlyCntType eType=FLYCNTTYPE_ALL, bool bSelFrame=true)
Definition: move.cxx:594
const SwView & GetView() const
Definition: wrtsh.hxx:428
bool GotoNextTOXBase(const OUString *pName=nullptr)
Definition: move.cxx:646
void ToggleOutlineContentVisibility(SwNode *pNd, bool bForceFold=false)
Definition: wrtsh1.cxx:2010
virtual const_iterator_t findMark(const OUString &rMark) const =0
Finds a mark by name.
#define FN_TABLE_SELECT_ALL
Definition: cmdid.h:359
SwContentType(SwWrtShell *pParent, ContentTypeId nType, sal_uInt8 nLevel)
Definition: content.cxx:265
std::unique_ptr< weld::TreeIter > GetEntryAtAbsPos(size_t nAbsPos) const
Definition: content.cxx:1977
SwView * GetView()
Definition: unotxvw.hxx:140
#define FN_INSERT_BOOKMARK
Definition: cmdid.h:194
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
constexpr OUStringLiteral IsReadOnly(u"IsReadOnly")
void LeaveAddMode()
Definition: select.cxx:640
bool IsProtectedOutlinePara() const
Definition: ednumber.cxx:582
bool IsOutlineMovable(SwOutlineNodes::size_type nIdx) const
May an outline be moved or copied? Check whether it's in text body, not in table, and not read-only (...
Definition: ednumber.cxx:652
ContentTypeId m_nContentType
Definition: content.hxx:148
virtual void set_label(const OString &rIdent, const OUString &rLabel)=0
const OUString & GetName() const
Definition: format.hxx:111
std::vector< SwGetINetAttr > SwGetINetAttrs
Definition: editsh.hxx:126
bool Paste(TransferableDataHelper &rData)
Definition: content.cxx:4437
sal_Int32 GetActiveBlock() const
Definition: navicfg.hxx:74
int nCount
bool GotoPrevTOXBase(const OUString *=nullptr)
jump to previous index
Definition: crstrvl.cxx:315
#define DND_ACTION_NONE
const SwTOXBase * GetTOX(sal_uInt16 nPos) const
Definition: edtox.cxx:225
TreeListBox for content indicator.
Definition: conttree.hxx:87
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
SwMoveFnCollection const & fnRegionEnd
Definition: paminit.cxx:56
virtual OUString get_id(int pos) const =0
size_t GetMemberCount() const
Definition: content.hxx:163
sal_uInt16 GetModifier() const
SwOutlineNodes::size_type GetOutlinePos() const
Definition: content.hxx:52
SwDoc * GetDoc() const
Definition: viewsh.hxx:281
void GetGrfNms(OUString *pGrfName, OUString *pFltName, const SwFlyFrameFormat *=nullptr) const
Returns the name and the filter name of a graphic if the pointer is on a graphic. ...
Definition: editsh.cxx:305
const IDocumentMarkAccess * getIDocumentMarkAccess() const
Provides access to the document bookmark interface.
Definition: viewsh.cxx:2666
void SetOutlineLevel(sal_uInt8 nSet)
Definition: content.cxx:3943
void MoveOutline(SwOutlineNodes::size_type nTargetPos)
Definition: content.cxx:3359
void UnmarkAll()
const IDocumentDrawModelAccess & getIDocumentDrawModelAccess() const
Provides access to the document draw model interface.
Definition: viewsh.cxx:2668
size_type size() const
sal_Int8 AcceptDrop()
Definition: navipi.cxx:935
css::uno::Reference< css::frame::XModel > GetBaseModel() const
const SwSectionFormat & GetSectionFormat(size_t nFormat) const
Definition: edsect.cxx:142
UNKNOWN
const char * sName
sal_Int32 m_nActiveBlock
Definition: conttree.hxx:107
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
void ToggleToRoot()
Switch the display to Root.
Definition: content.cxx:2367
sal_Int32 m_nHiddenBlock
Definition: conttree.hxx:108
const SwWrtShell * GetActiveWrtShell() const
Definition: conttree.hxx:226
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:163
const css::uno::Reference< css::frame::XController2 > & GetController() const
DocumentType eType
void SetActiveShell(SwWrtShell *pSh)
Document change - set new Shell.
Definition: content.cxx:2659
bool IsShowOutlineContentVisibilityButton() const
Definition: viewopt.cxx:99
virtual std::unique_ptr< ILazyDeleter > deleteMark(const IDocumentMarkAccess::const_iterator_t &ppMark)=0
Deletes a mark.
sal_Int8 AcceptDrop(const AcceptDropEvent &rEvt)
Definition: content.cxx:1026
size_t GetFlyCount(FlyCntType eType, bool bIgnoreTextBoxes=false) const
Iterate over flys - for Basic-collections.
Definition: feshview.cxx:2566
constexpr sal_uInt16 KEY_DOWN
weld::Window * GetFrameWeld(const SfxFrame *pF