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