Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/uibase/utlui/content.cxx
Warning:line 3037, column 17
Although the value stored to 'bListEntry' is used in the enclosing expression, the value is never actually read from 'bListEntry'

Annotated Source Code

Press '?' to see keyboard shortcuts

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