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