LibreOffice Module sc (master) 1
content.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
24#include <svx/svditer.hxx>
25#include <svx/svdobj.hxx>
26#include <svx/svdview.hxx>
27#include <sfx2/linkmgr.hxx>
28#include <sfx2/docfile.hxx>
29#include <sfx2/viewfrm.hxx>
30#include <vcl/commandevent.hxx>
31#include <vcl/svapp.hxx>
32#include <osl/diagnose.h>
33#include <tools/urlobj.hxx>
34#include <sal/log.hxx>
36
37#include <content.hxx>
38#include <navipi.hxx>
39#include <global.hxx>
40#include <docsh.hxx>
41#include <scmod.hxx>
42#include <rangenam.hxx>
43#include <dbdata.hxx>
44#include <tablink.hxx>
45#include <drwlayer.hxx>
46#include <transobj.hxx>
47#include <drwtrans.hxx>
48#include <lnktrans.hxx>
49#include <strings.hrc>
50#include <scresid.hxx>
51#include <bitmaps.hlst>
52#include <arealink.hxx>
53#include <navicfg.hxx>
54#include <navsett.hxx>
55#include <postit.hxx>
56#include <tabvwsh.hxx>
57#include <drawview.hxx>
58#include <clipparam.hxx>
59#include <markdata.hxx>
60
61using namespace com::sun::star;
62
63// order of the categories in navigator -------------------------------------
64
66{
67 ScContentId::ROOT, // ROOT (0) has to be at the front
76};
77
78constexpr rtl::OUStringConstExpr aContentBmps[]=
79{
80 RID_BMP_CONTENT_TABLE,
81 RID_BMP_CONTENT_RANGENAME,
82 RID_BMP_CONTENT_DBAREA,
83 RID_BMP_CONTENT_GRAPHIC,
84 RID_BMP_CONTENT_OLEOBJECT,
85 RID_BMP_CONTENT_NOTE,
86 RID_BMP_CONTENT_AREALINK,
87 RID_BMP_CONTENT_DRAWING
88};
89
91{
92 ScDocShell* pSh = nullptr;
93 if ( !aManualDoc.isEmpty() )
94 {
95 SfxObjectShell* pObjSh = SfxObjectShell::GetFirst( checkSfxObjectShell<ScDocShell> );
96 while ( pObjSh && !pSh )
97 {
98 if ( pObjSh->GetTitle() == aManualDoc )
99 pSh = dynamic_cast<ScDocShell*>( pObjSh );
100 pObjSh = SfxObjectShell::GetNext( *pObjSh, checkSfxObjectShell<ScDocShell> );
101 }
102 }
103 else
104 {
105 // only current when manual isn't set
106 // (so it's detected when the documents don't exists any longer)
107
109 if ( pViewSh )
110 {
111 SfxObjectShell* pObjSh = pViewSh->GetViewFrame().GetObjectShell();
112 pSh = dynamic_cast<ScDocShell*>( pObjSh );
113 }
114 }
115
116 return pSh;
117}
118
119// ScContentTree
120
121ScContentTree::ScContentTree(std::unique_ptr<weld::TreeView> xTreeView, ScNavigatorDlg* pNavigatorDlg)
122 : m_xTreeView(std::move(xTreeView))
123 , m_xScratchIter(m_xTreeView->make_iterator())
124 , m_xTransferObj(new ScLinkTransferObj)
125 , pParentWindow(pNavigatorDlg)
126 , nRootType(ScContentId::ROOT)
127 , bHiddenDoc(false)
128 , pHiddenDocument(nullptr)
129 , bIsInNavigatorDlg(false)
130 , m_bFreeze(false)
131 , m_nAsyncMouseReleaseId(nullptr)
132{
133 for (sal_uInt16 i = 0; i <= int(ScContentId::LAST); ++i)
134 pPosList[pTypeList[i]] = i; // inverse for searching
135
137 for (sal_uInt16 i = 1; i < int(ScContentId::LAST); ++i)
138 InitRoot(static_cast<ScContentId>(i));
139
140 m_xTreeView->connect_row_activated(LINK(this, ScContentTree, ContentDoubleClickHdl));
141 m_xTreeView->connect_mouse_release(LINK(this, ScContentTree, MouseReleaseHdl));
142 m_xTreeView->connect_key_press(LINK(this, ScContentTree, KeyInputHdl));
143 m_xTreeView->connect_popup_menu(LINK(this, ScContentTree, CommandHdl));
144 m_xTreeView->connect_query_tooltip(LINK(this, ScContentTree, QueryTooltipHdl));
145
147 m_xTreeView->enable_drag_source(xHelper, DND_ACTION_COPY | DND_ACTION_LINK);
148
149 m_xTreeView->connect_drag_begin(LINK(this, ScContentTree, DragBeginHdl));
150
151 m_xTreeView->set_selection_mode( SelectionMode::Single );
152
153 m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 30,
154 m_xTreeView->get_text_height() * 13);
155}
156
158{
160 {
162 m_nAsyncMouseReleaseId = nullptr;
163 }
164}
165
167{
168 SCSTR_CONTENT_ROOT,
169 SCSTR_CONTENT_TABLE,
170 SCSTR_CONTENT_RANGENAME,
171 SCSTR_CONTENT_DBAREA,
172 SCSTR_CONTENT_GRAPHIC,
173 SCSTR_CONTENT_OLEOBJECT,
174 SCSTR_CONTENT_NOTE,
175 SCSTR_CONTENT_AREALINK,
176 SCSTR_CONTENT_DRAWING
177};
178
180{
181 if ( nType == ScContentId::ROOT )
182 return;
183
184 if ( nRootType != ScContentId::ROOT && nRootType != nType ) // hidden ?
185 {
186 m_aRootNodes[nType] = nullptr;
187 return;
188 }
189
190 auto const aImage(aContentBmps[static_cast<int>(nType) - 1]);
191 OUString aName(ScResId(SCSTR_CONTENT_ARY[static_cast<int>(nType)]));
192 // back to the correct position:
193 sal_uInt16 nPos = nRootType != ScContentId::ROOT ? 0 : pPosList[nType]-1;
194 m_aRootNodes[nType] = m_xTreeView->make_iterator();
195 m_xTreeView->insert(nullptr, nPos, &aName, nullptr, nullptr, nullptr, false, m_aRootNodes[nType].get());
196 m_xTreeView->set_image(*m_aRootNodes[nType], OUString(aImage));
197}
198
200{
201 //There are one method in Control::SetUpdateMode(), and one override method SvTreeListBox::SetUpdateMode(). Here although
202 //SvTreeListBox::SetUpdateMode() is called in refresh method, it only call SvTreeListBox::SetUpdateMode(), not Control::SetUpdateMode().
203 //In m_xTreeView->clear(), Broadcast( LISTACTION_CLEARED ) will be called and finally, it will be trapped into the event yield() loop. And
204 //the InitRoot() method won't be called. Then if a user click or press key to update the navigator tree, crash happens.
205 //So the solution is to disable the UpdateMode of Control, then call Clear(), then recover the update mode
206 bool bWasFrozen = m_bFreeze;
207 if (!bWasFrozen)
208 freeze();
209 m_xTreeView->clear();
210 if (!bWasFrozen)
211 thaw();
212 for (sal_uInt16 i=1; i<=int(ScContentId::LAST); i++)
213 InitRoot(static_cast<ScContentId>(i));
214}
215
217{
219 ClearAll();
220 else
221 {
222 weld::TreeIter* pParent = m_aRootNodes[nType].get();
223 if (!pParent || m_xTreeView->iter_has_child(*pParent)) // not if no children existing
224 {
225 if (pParent)
226 m_xTreeView->remove(*pParent); // with all children
227 InitRoot( nType ); // if needed insert anew
228 }
229 }
230}
231
232void ScContentTree::InsertContent( ScContentId nType, const OUString& rValue )
233{
234 weld::TreeIter* pParent = m_aRootNodes[nType].get();
235 if (pParent)
236 {
237 m_xTreeView->insert(pParent, -1, &rValue, nullptr, nullptr, nullptr, false, m_xScratchIter.get());
238 m_xTreeView->set_sensitive(*m_xScratchIter, true);
239 }
240 else
241 {
242 OSL_FAIL("InsertContent without parent");
243 }
244}
245
246void ScContentTree::GetEntryIndexes(ScContentId& rnRootIndex, sal_uLong& rnChildIndex, const weld::TreeIter* pEntry) const
247{
248 rnRootIndex = ScContentId::ROOT;
249 rnChildIndex = SC_CONTENT_NOCHILD;
250
251 if( !pEntry )
252 return;
253
254 std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(pEntry));
255 if (!m_xTreeView->iter_parent(*xParent))
256 xParent.reset();
257 bool bFound = false;
258 for( int i = 1; !bFound && (i <= int(ScContentId::LAST)); ++i )
259 {
260 ScContentId nRoot = static_cast<ScContentId>(i);
261 if (!m_aRootNodes[nRoot])
262 continue;
263 if (m_xTreeView->iter_compare(*pEntry, *m_aRootNodes[nRoot]) == 0)
264 {
265 rnRootIndex = nRoot;
266 rnChildIndex = ~0UL;
267 bFound = true;
268 }
269 else if (xParent && m_xTreeView->iter_compare(*xParent, *m_aRootNodes[nRoot]) == 0)
270 {
271 rnRootIndex = nRoot;
272
273 // search the entry in all child entries of the parent
274 sal_uLong nEntry = 0;
275 std::unique_ptr<weld::TreeIter> xIterEntry(m_xTreeView->make_iterator(xParent.get()));
276 bool bIterEntry = m_xTreeView->iter_children(*xIterEntry);
277 while (!bFound && bIterEntry)
278 {
279 if (m_xTreeView->iter_compare(*pEntry, *xIterEntry) == 0)
280 {
281 rnChildIndex = nEntry;
282 bFound = true; // exit the while loop
283 }
284 bIterEntry = m_xTreeView->iter_next_sibling(*xIterEntry);
285 ++nEntry;
286 }
287
288 bFound = true; // exit the for loop
289 }
290 }
291}
292
294{
295 ScContentId nRoot;
296 sal_uLong nChild;
297 GetEntryIndexes(nRoot, nChild, pEntry);
298 return nChild;
299}
300
301static OUString lcl_GetDBAreaRange( const ScDocument* pDoc, const OUString& rDBName )
302{
303 OUString aRet;
304 if (pDoc)
305 {
306 ScDBCollection* pDbNames = pDoc->GetDBCollection();
307 const ScDBData* pData = pDbNames->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rDBName));
308 if (pData)
309 {
310 ScRange aRange;
311 pData->GetArea(aRange);
312 aRet = aRange.Format(*pDoc, ScRefFlags::RANGE_ABS_3D);
313 }
314 }
315 return aRet;
316}
317
318IMPL_LINK_NOARG(ScContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
319{
321 sal_uLong nChild;
322 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
323 if (!m_xTreeView->get_cursor(xEntry.get()))
324 xEntry.reset();
325 GetEntryIndexes(nType, nChild, xEntry.get());
326
327 if (xEntry && (nType != ScContentId::ROOT) && (nChild != SC_CONTENT_NOCHILD))
328 {
329 if ( bHiddenDoc )
330 return false;
331
332 OUString aText(m_xTreeView->get_text(*xEntry));
333
334 if ( !aManualDoc.isEmpty() )
335 pParentWindow->SetCurrentDoc( aManualDoc );
336
337 switch( nType )
338 {
340 {
341 // tdf#133159 store current config before changing sheet
342 // plausible that this should be done for all cases, but this
343 // is the known case that needs it
344 StoreNavigatorSettings();
345 pParentWindow->SetCurrentTableStr( aText );
346 }
347 break;
348
350 pParentWindow->SetCurrentCellStr( aText );
351 break;
352
354 {
355 // If the same names of area and DB exists, then
356 // SID_CURRENTCELL takes the area name.
357 // Therefore for DB areas access them directly via address.
358
359 OUString aRangeStr = lcl_GetDBAreaRange( GetSourceDocument(), aText );
360 if (!aRangeStr.isEmpty())
361 pParentWindow->SetCurrentCellStr( aRangeStr );
362 }
363 break;
364
368 pParentWindow->SetCurrentObject( aText );
369 break;
370
372 {
373 ScAddress aPos = GetNotePos( nChild );
374 pParentWindow->SetCurrentTable( aPos.Tab() );
375 pParentWindow->SetCurrentCell( aPos.Col(), aPos.Row() );
376 }
377 break;
378
380 {
381 const ScAreaLink* pLink = GetLink(nChild);
382 ScDocument* pSrcDoc = GetSourceDocument();
383 if (pLink && pSrcDoc)
384 {
385 const ScRange& aRange = pLink->GetDestArea();
386 OUString aRangeStr(aRange.Format(*pSrcDoc, ScRefFlags::RANGE_ABS_3D, pSrcDoc->GetAddressConvention()));
387 pParentWindow->SetCurrentCellStr( aRangeStr );
388 }
389 }
390 break;
391 default: break;
392 }
393
394 ScNavigatorDlg::ReleaseFocus(); // set focus into document
395 }
396
397 return false;
398}
399
401{
403 m_nAsyncMouseReleaseId = Application::PostUserEvent(LINK(this, ScContentTree, AsyncStoreNavigatorSettings));
404}
405
406IMPL_LINK_NOARG(ScContentTree, MouseReleaseHdl, const MouseEvent&, bool)
407{
408 LaunchAsyncStoreNavigatorSettings();
409 return false;
410}
411
412IMPL_LINK_NOARG(ScContentTree, AsyncStoreNavigatorSettings, void*, void)
413{
414 m_nAsyncMouseReleaseId = nullptr;
415 StoreNavigatorSettings();
416}
417
418IMPL_LINK(ScContentTree, KeyInputHdl, const KeyEvent&, rKEvt, bool)
419{
420 bool bUsed = false;
421
422 const vcl::KeyCode aCode = rKEvt.GetKeyCode();
423 if (aCode.GetCode() == KEY_RETURN)
424 {
425 switch (aCode.GetModifier())
426 {
427 case KEY_MOD1:
428 ToggleRoot(); // toggle root mode (as in Writer)
429 bUsed = true;
430 break;
431 case 0:
432 {
433 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
434 if (!m_xTreeView->get_cursor(xEntry.get()))
435 xEntry.reset();
436 if (xEntry)
437 {
439 sal_uLong nChild;
440 GetEntryIndexes(nType, nChild, xEntry.get());
441
442 if (nType != ScContentId::ROOT && nChild == SC_CONTENT_NOCHILD)
443 {
444 if (m_xTreeView->get_row_expanded(*xEntry))
445 m_xTreeView->collapse_row(*xEntry);
446 else
447 m_xTreeView->expand_row(*xEntry);
448 }
449 else
450 ContentDoubleClickHdl(*m_xTreeView); // select content as if double clicked
451 }
452
453 bUsed = true;
454 }
455 break;
456 }
457 }
458 //Make KEY_SPACE has same function as DoubleClick, and realize
459 //multi-selection.
460 if ( bIsInNavigatorDlg )
461 {
462 if(aCode.GetCode() == KEY_SPACE )
463 {
464 bUsed = true;
466 sal_uLong nChild;
467 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
468 if (!m_xTreeView->get_cursor(xEntry.get()))
469 xEntry.reset();
470 GetEntryIndexes(nType, nChild, xEntry.get());
471
472 if (xEntry && (nType != ScContentId::ROOT) && (nChild != SC_CONTENT_NOCHILD))
473 {
474 if ( bHiddenDoc )
475 return true;
476 OUString aText(m_xTreeView->get_text(*xEntry));
477 if (!aManualDoc.isEmpty())
478 pParentWindow->SetCurrentDoc( aManualDoc );
479 switch (nType)
480 {
484 {
485 ScDrawView* pScDrawView = nullptr;
487 if (pScTabViewShell)
488 pScDrawView = pScTabViewShell->GetViewData().GetScDrawView();
489 if (pScDrawView)
490 {
491 pScDrawView->SelectCurrentViewObject(aText);
492 bool bHasMakredObject = false;
493 weld::TreeIter* pParent = m_aRootNodes[nType].get();
494 std::unique_ptr<weld::TreeIter> xBeginEntry(m_xTreeView->make_iterator(pParent));
495 bool bBeginEntry = false;
496 if (pParent)
497 bBeginEntry = m_xTreeView->iter_children(*xBeginEntry);
498 while (bBeginEntry)
499 {
500 OUString aTempText(m_xTreeView->get_text(*xBeginEntry));
501 if( pScDrawView->GetObjectIsMarked( pScDrawView->GetObjectByName( aTempText ) ) )
502 {
503 bHasMakredObject = true;
504 break;
505 }
506 bBeginEntry = m_xTreeView->iter_next(*xBeginEntry);
507 }
508 if (!bHasMakredObject && pScTabViewShell)
509 pScTabViewShell->SetDrawShell(false);
510 }
511 break;
512 }
513 default:
514 break;
515 }
516 }
517 }
518 }
519
520 if (!bUsed)
521 {
522 if (aCode.GetCode() == KEY_F5)
523 StoreNavigatorSettings();
524 else
525 LaunchAsyncStoreNavigatorSettings();
526 }
527
528 return bUsed;
529}
530
531IMPL_LINK(ScContentTree, CommandHdl, const CommandEvent&, rCEvt, bool)
532{
533 bool bDone = false;
534
535 switch ( rCEvt.GetCommand() )
536 {
537 case CommandEventId::ContextMenu:
538 {
539 // drag-and-drop mode
540 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/scalc/ui/dropmenu.ui"));
541 std::unique_ptr<weld::Menu> xPop(xBuilder->weld_menu("contextmenu"));
542 std::unique_ptr<weld::Menu> xDropMenu(xBuilder->weld_menu("dragmodesubmenu"));
543
544 switch (pParentWindow->GetDropMode())
545 {
546 case 0:
547 xDropMenu->set_active("hyperlink", true);
548 break;
549 case 1:
550 xDropMenu->set_active("link", true);
551 break;
552 case 2:
553 xDropMenu->set_active("copy", true);
554 break;
555 }
556
557 // displayed document
558 std::unique_ptr<weld::Menu> xDocMenu(xBuilder->weld_menu("displaymenu"));
559 sal_uInt16 i=0;
560 OUString sActive;
561 OUString sId;
562 // loaded documents
563 ScDocShell* pCurrentSh = dynamic_cast<ScDocShell*>( SfxObjectShell::Current() );
565 while ( pSh )
566 {
567 if ( dynamic_cast<const ScDocShell*>( pSh) != nullptr )
568 {
569 OUString aName = pSh->GetTitle();
570 OUString aEntry = aName;
571 if ( pSh == pCurrentSh )
572 aEntry += pParentWindow->aStrActive;
573 else
574 aEntry += pParentWindow->aStrNotActive;
575 ++i;
576 sId = "document" + OUString::number(i);
577 xDocMenu->append_radio(sId, aEntry);
578 if ( !bHiddenDoc && aName == aManualDoc )
579 sActive = sId;
580 }
581 pSh = SfxObjectShell::GetNext( *pSh );
582 }
583 // "active window"
584 ++i;
585 sId = "document" + OUString::number(i);
586 xDocMenu->append_radio(sId, pParentWindow->aStrActiveWin);
587 if (!bHiddenDoc && aManualDoc.isEmpty())
588 sActive = sId;
589 // hidden document
590 if ( !aHiddenTitle.isEmpty() )
591 {
592 OUString aEntry = aHiddenTitle + pParentWindow->aStrHidden;
593 ++i;
594 sId = "document" + OUString::number(i);
595 xDocMenu->append_radio(sId, aEntry);
596 if (bHiddenDoc)
597 sActive = sId;
598 }
599 xDocMenu->set_active(sActive, true);
600
601 OUString sIdent = xPop->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1, 1)));
602 if (sIdent == "hyperlink")
603 pParentWindow->SetDropMode(0);
604 else if (sIdent == "link")
605 pParentWindow->SetDropMode(1);
606 else if (sIdent == "copy")
607 pParentWindow->SetDropMode(2);
608 else if (sIdent.startsWith("document"))
609 {
610 OUString aName = xDocMenu->get_label(sIdent);
611 SelectDoc(aName);
612 }
613 }
614 break;
615 default: break;
616 }
617
618 return bDone;
619}
620
621IMPL_LINK(ScContentTree, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString)
622{
623 OUString aHelpText;
624
625 std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(&rEntry));
626 if (!m_xTreeView->iter_parent(*xParent))
627 xParent.reset();
628
629 if (!xParent) // Top-Level ?
630 {
631 aHelpText = OUString::number(m_xTreeView->iter_n_children(rEntry)) +
632 " " + m_xTreeView->get_text(rEntry);
633 }
634 else if (m_aRootNodes[ScContentId::NOTE] && m_xTreeView->iter_compare(*xParent, *m_aRootNodes[ScContentId::NOTE]) == 0)
635 {
636 aHelpText = m_xTreeView->get_text(rEntry); // notes as help text
637 }
638 else if (m_aRootNodes[ScContentId::AREALINK] && m_xTreeView->iter_compare(*xParent, *m_aRootNodes[ScContentId::AREALINK]) == 0)
639 {
640 auto nIndex = GetChildIndex(&rEntry);
642 {
643 const ScAreaLink* pLink = GetLink(nIndex);
644 if (pLink)
645 {
646 aHelpText = pLink->GetFile(); // source file as help text
647 }
648 }
649 }
650
651 return aHelpText;
652}
653
655{
656 if (bHiddenDoc)
657 return pHiddenDocument;
658 else
659 {
661 if (pSh)
662 return &pSh->GetDocument();
663
664 }
665 return nullptr;
666}
667
669{
670 if ( bHiddenDoc && !pHiddenDocument )
671 return; // other document displayed
672
673 // if nothing has changed the cancel right away (against flicker)
674
675 if ( nType == ScContentId::NOTE )
676 if (!NoteStringsChanged())
677 return;
680 return;
683 return;
686 return;
687
688 freeze();
689
690 ClearType( nType );
691
695 GetAreaNames();
697 GetDbNames();
701 GetOleNames();
707 GetLinkNames();
708
709 thaw();
710
712}
713
715{
716 if ( nRootType != ScContentId::ROOT && nRootType != ScContentId::TABLE ) // hidden ?
717 return;
718
720 if (!pDoc)
721 return;
722
723 OUString aName;
724 SCTAB nCount = pDoc->GetTableCount();
725 for ( SCTAB i=0; i<nCount; i++ )
726 {
727 pDoc->GetName( i, aName );
729 }
730}
731
732namespace {
733
734OUString createLocalRangeName(std::u16string_view rName, std::u16string_view rTableName)
735{
736 return OUString::Concat(rName) + " (" + rTableName + ")";
737}
738}
739
741{
743 return;
744
746 if (!pDoc)
747 return;
748
749 ScRange aDummy;
750 std::set<OUString> aSet;
751 ScRangeName* pRangeNames = pDoc->GetRangeName();
752 for (const auto& rEntry : *pRangeNames)
753 {
754 if (rEntry.second->IsValidReference(aDummy))
755 aSet.insert(rEntry.second->GetName());
756 }
757 for (SCTAB i = 0; i < pDoc->GetTableCount(); ++i)
758 {
759 ScRangeName* pLocalRangeName = pDoc->GetRangeName(i);
760 if (pLocalRangeName && !pLocalRangeName->empty())
761 {
762 OUString aTableName;
763 pDoc->GetName(i, aTableName);
764 for (const auto& rEntry : *pLocalRangeName)
765 {
766 if (rEntry.second->IsValidReference(aDummy))
767 aSet.insert(createLocalRangeName(rEntry.second->GetName(), aTableName));
768 }
769 }
770 }
771
772 for (const auto& rItem : aSet)
773 {
775 }
776}
777
779{
780 if ( nRootType != ScContentId::ROOT && nRootType != ScContentId::DBAREA ) // hidden ?
781 return;
782
784 if (!pDoc)
785 return;
786
787 ScDBCollection* pDbNames = pDoc->GetDBCollection();
788 const ScDBCollection::NamedDBs& rDBs = pDbNames->getNamedDBs();
789 for (const auto& rxDB : rDBs)
790 {
791 const OUString& aStrName = rxDB->GetName();
793 }
794}
795
796bool ScContentTree::IsPartOfType( ScContentId nContentType, SdrObjKind nObjIdentifier )
797{
798 bool bRet = false;
799 switch ( nContentType )
800 {
802 bRet = ( nObjIdentifier == SdrObjKind::Graphic );
803 break;
805 bRet = ( nObjIdentifier == SdrObjKind::OLE2 );
806 break;
808 bRet = ( nObjIdentifier != SdrObjKind::Graphic && nObjIdentifier != SdrObjKind::OLE2 ); // everything else
809 break;
810 default:
811 OSL_FAIL("unknown content type");
812 }
813 return bRet;
814}
815
816constexpr int MAX_TREE_NODES = 1000;
817
819{
821 return;
822
823 if ( nRootType != ScContentId::ROOT && nRootType != nType ) // hidden ?
824 return;
825
827 if (!pDoc)
828 return;
829
830 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
831 if (!pDrawLayer)
832 return;
833
834 SfxObjectShell* pShell = pDoc->GetDocumentShell();
835 if (!pShell)
836 return;
837
838 // iterate in flat mode for groups
839 SdrIterMode eIter = ( nType == ScContentId::DRAWING ) ? SdrIterMode::Flat : SdrIterMode::DeepNoGroups;
840
841 std::vector<OUString> aNames;
842 SCTAB nTabCount = pDoc->GetTableCount();
843 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
844 {
845 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
846 OSL_ENSURE(pPage,"Page ?");
847 if (!pPage)
848 continue;
849 SdrObjListIter aIter(pPage, eIter);
850 SdrObject* pObject = aIter.Next();
851 while (pObject)
852 {
853 if (IsPartOfType(nType, pObject->GetObjIdentifier()))
854 {
856 if (!aName.isEmpty())
857 aNames.push_back(aName);
858 if (aNames.size() > MAX_TREE_NODES)
859 {
860 SAL_WARN("sc", "too many tree nodes, ignoring the rest");
861 break;
862 }
863 }
864 pObject = aIter.Next();
865 }
866 }
867
868 weld::TreeIter* pParent = m_aRootNodes[nType].get();
869 assert(pParent && "InsertContent without parent");
870 // insert all of these in one go under pParent
871 m_xTreeView->bulk_insert_for_each(aNames.size(), [this, &aNames](weld::TreeIter& rIter, int nIndex) {
872 m_xTreeView->set_text(rIter, aNames[nIndex], 0);
873 m_xTreeView->set_sensitive(rIter, true);
874 }, pParent);
875}
876
878{
880}
881
883{
885}
886
888{
890}
891
893{
895 return;
896
898 if (!pDoc)
899 return;
900
901 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
902 OSL_ENSURE(pLinkManager, "no LinkManager on document?");
903 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
904 sal_uInt16 nCount = rLinks.size();
905 for (sal_uInt16 i=0; i<nCount; i++)
906 {
907 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
908 if (auto pScAreaLink = dynamic_cast<const ScAreaLink*>( pBase))
909 InsertContent( ScContentId::AREALINK, pScAreaLink->GetSource() );
910
911 // insert in list the names of source areas
912 }
913}
914
916{
918 if (!pDoc)
919 return nullptr;
920
921 sal_uLong nFound = 0;
922 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
923 OSL_ENSURE(pLinkManager, "no LinkManager on document?");
924 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
925 sal_uInt16 nCount = rLinks.size();
926 for (sal_uInt16 i=0; i<nCount; i++)
927 {
928 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
929 if (auto pAreaLink = dynamic_cast<const ScAreaLink*>( pBase))
930 {
931 if (nFound == nIndex)
932 return pAreaLink;
933 ++nFound;
934 }
935 }
936
937 OSL_FAIL("link not found");
938 return nullptr;
939}
940
941static OUString lcl_NoteString( const ScPostIt& rNote )
942{
943 return rNote.GetText().replace('\n', ' ');
944}
945
947{
948 if ( nRootType != ScContentId::ROOT && nRootType != ScContentId::NOTE ) // hidden ?
949 return;
950
952 if (!pDoc)
953 return;
954
955 // loop over cell notes
956 std::vector<sc::NoteEntry> aEntries;
959 for (const auto& rEntry : aEntries)
960 {
961 OUString aValue = lcl_NoteString(*rEntry.mpNote);
962 m_xTreeView->insert(pParent, -1, &aValue, nullptr, nullptr, nullptr, false, m_xScratchIter.get());
963 m_xTreeView->set_sensitive(*m_xScratchIter, true);
964 }
965}
966
968{
970 if (!pDoc)
971 return ScAddress();
972
973 return pDoc->GetNotePosition(nIndex);
974}
975
977{
979 if (!pDoc)
980 return false;
981
983 if (!pParent)
984 return false;
985
986 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(pParent));
987 bool bEntry = m_xTreeView->iter_children(*xEntry);
988
989 std::vector<sc::NoteEntry> aEntries;
991 for (const auto& rEntry : aEntries)
992 {
993 const ScPostIt* pNote = rEntry.mpNote;
994 if (!bEntry)
995 return true;
996
997 if (lcl_NoteString(*pNote) != m_xTreeView->get_text(*xEntry))
998 return true;
999
1000 bEntry = m_xTreeView->iter_next_sibling(*xEntry);
1001 }
1002
1003 return bEntry;
1004}
1005
1007{
1008 ScDocument* pDoc = GetSourceDocument();
1009 if (!pDoc)
1010 return false;
1011
1012 weld::TreeIter* pParent = m_aRootNodes[nType].get();
1013 if (!pParent)
1014 return false;
1015
1016 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(pParent));
1017 bool bEntry = m_xTreeView->iter_children(*xEntry);
1018
1019 // iterate in flat mode for groups
1020 SdrIterMode eIter = ( nType == ScContentId::DRAWING ) ? SdrIterMode::Flat : SdrIterMode::DeepNoGroups;
1021
1022 bool bEqual = true;
1023 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
1024 SfxObjectShell* pShell = pDoc->GetDocumentShell();
1025 if (pDrawLayer && pShell)
1026 {
1027 SCTAB nTabCount = pDoc->GetTableCount();
1028 for (SCTAB nTab=0; nTab<nTabCount && bEqual; nTab++)
1029 {
1030 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
1031 OSL_ENSURE(pPage,"Page ?");
1032 if (pPage)
1033 {
1034 SdrObjListIter aIter( pPage, eIter );
1035 SdrObject* pObject = aIter.Next();
1036 while (pObject && bEqual)
1037 {
1038 if ( IsPartOfType( nType, pObject->GetObjIdentifier() ) )
1039 {
1040 if ( !bEntry )
1041 bEqual = false;
1042 else
1043 {
1044 if (ScDrawLayer::GetVisibleName(pObject) != m_xTreeView->get_text(*xEntry))
1045 bEqual = false;
1046
1047 bEntry = m_xTreeView->iter_next_sibling(*xEntry);
1048 }
1049 }
1050 pObject = aIter.Next();
1051 }
1052 }
1053 }
1054 }
1055
1056 if ( bEntry )
1057 bEqual = false; // anything else
1058
1059 return !bEqual;
1060}
1061
1062static bool lcl_GetRange( const ScDocument& rDoc, ScContentId nType, const OUString& rName, ScRange& rRange )
1063{
1064 bool bFound = false;
1065
1067 {
1068 ScRangeName* pList = rDoc.GetRangeName();
1069 if (pList)
1070 {
1071 const ScRangeData* p = pList->findByUpperName(ScGlobal::getCharClass().uppercase(rName));
1072 if (p && p->IsValidReference(rRange))
1073 bFound = true;
1074 }
1075 }
1076 else if ( nType == ScContentId::DBAREA )
1077 {
1078 ScDBCollection* pList = rDoc.GetDBCollection();
1079 if (pList)
1080 {
1081 const ScDBData* p = pList->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rName));
1082 if (p)
1083 {
1084 SCTAB nTab;
1085 SCCOL nCol1, nCol2;
1086 SCROW nRow1, nRow2;
1087 p->GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
1088 rRange = ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
1089 bFound = true;
1090 }
1091 }
1092 }
1093
1094 return bFound;
1095}
1096
1097static bool lcl_DoDragObject( ScDocShell* pSrcShell, std::u16string_view rName, ScContentId nType, weld::TreeView& rTreeView )
1098{
1099 bool bDisallow = true;
1100
1101 ScDocument& rSrcDoc = pSrcShell->GetDocument();
1102 ScDrawLayer* pModel = rSrcDoc.GetDrawLayer();
1103 if (pModel)
1104 {
1105 bool bOle = ( nType == ScContentId::OLEOBJECT );
1106 bool bGraf = ( nType == ScContentId::GRAPHIC );
1107 SdrObjKind nDrawId = bOle ? SdrObjKind::OLE2 : ( bGraf ? SdrObjKind::Graphic : SdrObjKind::Group );
1108 SCTAB nTab = 0;
1109 SdrObject* pObject = pModel->GetNamedObject( rName, nDrawId, nTab );
1110 if (pObject)
1111 {
1112 SdrView aEditView(*pModel);
1113 aEditView.ShowSdrPage(aEditView.GetModel().GetPage(nTab));
1114 SdrPageView* pPV = aEditView.GetSdrPageView();
1115 aEditView.MarkObj(pObject, pPV);
1116
1117 // tdf125520 this is a D&D-start potentially with an OLE object. If
1118 // so, we need to do similar as e.g. in ScDrawView::BeginDrag so that
1119 // the temporary SdrModel for transfer does have a GetPersist() so
1120 // that the EmbeddedObjectContainer gets copied. We need no CheckOle
1121 // here, test is simpler.
1122 ScDocShellRef aDragShellRef;
1123 if(SdrObjKind::OLE2 == pObject->GetObjIdentifier())
1124 {
1125 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
1126 aDragShellRef->DoInitNew();
1127 }
1128
1129 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef.get());
1130 std::unique_ptr<SdrModel> pDragModel(aEditView.CreateMarkedObjModel());
1132
1134 pSrcShell->FillTransferableObjectDescriptor( aObjDesc );
1135 aObjDesc.maDisplayName = pSrcShell->GetMedium()->GetURLObject().GetURLNoPass();
1136 // maSize is set in ScDrawTransferObj ctor
1137
1138 rtl::Reference<ScDrawTransferObj> pTransferObj = new ScDrawTransferObj( std::move(pDragModel), pSrcShell, std::move(aObjDesc) );
1139
1140 pTransferObj->SetDragSourceObj( *pObject, nTab );
1141 pTransferObj->SetDragSourceFlags(ScDragSrc::Navigator);
1142
1143 SC_MOD()->SetDragObject( nullptr, pTransferObj.get() );
1144
1145 rtl::Reference<TransferDataContainer> xHelper(pTransferObj);
1147
1148 bDisallow = false;
1149 }
1150 }
1151
1152 return bDisallow;
1153}
1154
1155static bool lcl_DoDragCells( ScDocShell* pSrcShell, const ScRange& rRange, ScDragSrc nFlags, weld::TreeView& rTreeView )
1156{
1157 bool bDisallow = true;
1158
1159 ScDocument& rSrcDoc = pSrcShell->GetDocument();
1160 ScMarkData aMark(rSrcDoc.GetSheetLimits());
1161 aMark.SelectTable( rRange.aStart.Tab(), true );
1162 aMark.SetMarkArea( rRange );
1163
1164 if ( !rSrcDoc.HasSelectedBlockMatrixFragment( rRange.aStart.Col(), rRange.aStart.Row(),
1165 rRange.aEnd.Col(), rRange.aEnd.Row(),
1166 aMark ) )
1167 {
1169 ScClipParam aClipParam(rRange, false);
1170 rSrcDoc.CopyToClip(aClipParam, pClipDoc.get(), &aMark, false, false);
1171 // pClipDoc->ExtendMerge( rRange, sal_True );
1172
1174 pSrcShell->FillTransferableObjectDescriptor( aObjDesc );
1175 aObjDesc.maDisplayName = pSrcShell->GetMedium()->GetURLObject().GetURLNoPass();
1176 // maSize is set in ScTransferObj ctor
1177
1178 rtl::Reference<ScTransferObj> pTransferObj = new ScTransferObj( std::move(pClipDoc), std::move(aObjDesc) );
1179
1180 pTransferObj->SetDragSource( pSrcShell, aMark );
1181 pTransferObj->SetDragSourceFlags( nFlags );
1182
1183 SC_MOD()->SetDragObject( pTransferObj.get(), nullptr ); // for internal D&D
1184
1185 rtl::Reference<TransferDataContainer> xHelper(pTransferObj);
1187
1188 bDisallow = false;
1189 }
1190
1191 return bDisallow;
1192}
1193
1194IMPL_LINK(ScContentTree, DragBeginHdl, bool&, rUnsetDragIcon, bool)
1195{
1196 rUnsetDragIcon = true;
1197
1198 StoreNavigatorSettings();
1199
1200 bool bDisallow = true;
1201
1202 std::unique_ptr<ScDocumentLoader> pDocLoader;
1203
1204 ScModule* pScMod = SC_MOD();
1205
1207 sal_uLong nChild;
1208
1209 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
1210 if (!m_xTreeView->get_cursor(xEntry.get()))
1211 xEntry.reset();
1212
1213 GetEntryIndexes(nType, nChild, xEntry.get());
1214
1215 if( xEntry &&
1216 (nChild != SC_CONTENT_NOCHILD) &&
1217 (nType != ScContentId::ROOT) &&
1218 (nType != ScContentId::NOTE) &&
1220 {
1221 OUString aText(m_xTreeView->get_text(*xEntry));
1222
1223 ScDocument* pLocalDoc = nullptr; // for URL drop
1224 OUString aDocName;
1225 if (bHiddenDoc)
1226 aDocName = aHiddenName;
1227 else
1228 {
1229 ScDocShell* pDocSh = GetManualOrCurrent();
1230 if (pDocSh)
1231 {
1232 if (pDocSh->HasName())
1233 aDocName = pDocSh->GetMedium()->GetName();
1234 else
1235 pLocalDoc = &pDocSh->GetDocument(); // drop only in this document
1236 }
1237 }
1238
1239 bool bDoLinkTrans = false; // use ScLinkTransferObj
1240 OUString aLinkURL; // for ScLinkTransferObj
1241 OUString aLinkText;
1242
1243 sal_uInt16 nDropMode = pParentWindow->GetDropMode();
1244 switch ( nDropMode )
1245 {
1246 case SC_DROPMODE_URL:
1247 {
1248 OUString aUrl = aDocName + "#" + aText;
1249
1250 pScMod->SetDragJump( pLocalDoc, aUrl, aText );
1251
1252 if (!aDocName.isEmpty())
1253 {
1254 // provide URL to outside only if the document has a name
1255 // (without name, only internal D&D via SetDragJump)
1256
1257 aLinkURL = aUrl;
1258 aLinkText = aText;
1259 }
1260 bDoLinkTrans = true;
1261 }
1262 break;
1263 case SC_DROPMODE_LINK:
1264 {
1265 if ( !aDocName.isEmpty() ) // link only to named documents
1266 {
1267 // for internal D&D, set flag to insert a link
1268
1269 switch ( nType )
1270 {
1271 case ScContentId::TABLE:
1272 pScMod->SetDragLink( aDocName, aText, OUString() );
1273 bDoLinkTrans = true;
1274 break;
1277 pScMod->SetDragLink( aDocName, OUString(), aText );
1278 bDoLinkTrans = true;
1279 break;
1280
1281 // other types cannot be linked
1282 default: break;
1283 }
1284 }
1285 }
1286 break;
1287 case SC_DROPMODE_COPY:
1288 {
1289 ScDocShell* pSrcShell = nullptr;
1290 if ( bHiddenDoc )
1291 {
1292 OUString aFilter, aOptions;
1293 OUString aURL = aHiddenName;
1294 pDocLoader.reset(new ScDocumentLoader( aURL, aFilter, aOptions ));
1295 if (!pDocLoader->IsError())
1296 pSrcShell = pDocLoader->GetDocShell();
1297 }
1298 else
1299 pSrcShell = GetManualOrCurrent();
1300
1301 if ( pSrcShell )
1302 {
1303 ScDocument& rSrcDoc = pSrcShell->GetDocument();
1305 {
1306 ScRange aRange;
1307 if ( lcl_GetRange( rSrcDoc, nType, aText, aRange ) )
1308 {
1309 bDisallow = lcl_DoDragCells( pSrcShell, aRange, ScDragSrc::Navigator, *m_xTreeView );
1310 }
1311 }
1312 else if ( nType == ScContentId::TABLE )
1313 {
1314 SCTAB nTab;
1315 if ( rSrcDoc.GetTable( aText, nTab ) )
1316 {
1317 ScRange aRange(0, 0, nTab, rSrcDoc.MaxCol(), rSrcDoc.MaxRow(), nTab);
1318 bDisallow = lcl_DoDragCells( pSrcShell, aRange, (ScDragSrc::Navigator | ScDragSrc::Table), *m_xTreeView );
1319 }
1320 }
1323 {
1324 bDisallow = lcl_DoDragObject( pSrcShell, aText, nType, *m_xTreeView );
1325
1326 // during ExecuteDrag the navigator can be deleted
1327 // -> don't access member anymore !!!
1328 }
1329 }
1330 }
1331 break;
1332 }
1333
1334 if (bDoLinkTrans)
1335 {
1336 if (!aLinkURL.isEmpty())
1337 m_xTransferObj->SetLinkURL(aLinkURL, aLinkText);
1338
1339 rtl::Reference<TransferDataContainer> xHelper(m_xTransferObj);
1340 m_xTreeView->enable_drag_source(xHelper, DND_ACTION_COPY | DND_ACTION_LINK);
1341
1342 bDisallow = false;
1343 }
1344 }
1345
1346 return bDisallow;
1347}
1348
1349void ScContentTree::LoadFile( const OUString& rUrl )
1350{
1351 OUString aDocName = rUrl;
1352 sal_Int32 nPos = aDocName.indexOf('#');
1353 if ( nPos != -1 )
1354 aDocName = aDocName.copy(0, nPos); // only the name without #...
1355
1356 OUString aURL = aDocName;
1357 OUString aFilter, aOptions;
1358 ScDocumentLoader aLoader( aURL, aFilter, aOptions );
1359 if ( aLoader.IsError() )
1360 return;
1361
1362 bHiddenDoc = true;
1363 aHiddenName = aDocName;
1364 aHiddenTitle = aLoader.GetTitle();
1365 pHiddenDocument = aLoader.GetDocument();
1366
1367 Refresh(); // get content from loaded document
1368
1369 pHiddenDocument = nullptr;
1370
1371 pParentWindow->GetDocNames( &aHiddenTitle ); // fill list
1372
1373 // document is closed again by ScDocumentLoader in dtor
1374}
1375
1377{
1378 if ( nNew != nRootType )
1379 {
1380 nRootType = nNew;
1381 Refresh();
1382
1383 ScNavipiCfg& rCfg = SC_MOD()->GetNavipiCfg();
1384 rCfg.SetRootType( nRootType );
1385 }
1386}
1387
1388void ScContentTree::ToggleRoot() // after selection
1389{
1392 {
1393 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
1394 if (m_xTreeView->get_cursor(xEntry.get()))
1395 {
1396 std::unique_ptr<weld::TreeIter> xParent(m_xTreeView->make_iterator(xEntry.get()));
1397 if (!m_xTreeView->iter_parent(*xParent))
1398 xParent.reset();
1399
1400 for (sal_uInt16 i=1; i<=int(ScContentId::LAST); i++)
1401 {
1402 if (!m_aRootNodes[static_cast<ScContentId>(i)])
1403 continue;
1404 if ((m_xTreeView->iter_compare(*xEntry, *m_aRootNodes[static_cast<ScContentId>(i)]) == 0) ||
1405 (xParent && m_xTreeView->iter_compare(*xParent, *m_aRootNodes[static_cast<ScContentId>(i)]) == 0))
1406 {
1407 nNew = static_cast<ScContentId>(i);
1408 }
1409 }
1410 }
1411 }
1412
1413 SetRootType( nNew );
1414}
1415
1417{
1418 aManualDoc.clear();
1419 bHiddenDoc = false;
1420
1422}
1423
1425{
1426 bool bRefreshed = false;
1427
1428 if ( !bHiddenDoc && aManualDoc.isEmpty() )
1429 {
1430 Refresh(); // content only if automatic
1431 bRefreshed = true;
1432 }
1433
1434 // if flag active Listbox must be updated
1435
1436 OUString aCurrent;
1437 if ( bHiddenDoc )
1438 aCurrent = aHiddenTitle;
1439 else
1440 {
1442 if (pSh)
1443 aCurrent = pSh->GetTitle();
1444 else
1445 {
1446 // document is no longer available
1447
1448 aManualDoc.clear(); // again automatically
1449 Refresh();
1450 bRefreshed = true;
1451 pSh = GetManualOrCurrent(); // should be active now
1452 if (pSh)
1453 aCurrent = pSh->GetTitle();
1454 }
1455 }
1456 pParentWindow->GetDocNames( &aCurrent ); // select
1457
1458 return bRefreshed;
1459}
1460
1461void ScContentTree::SetManualDoc(const OUString& rName)
1462{
1463 aManualDoc = rName;
1464 if (!bHiddenDoc)
1465 {
1466 Refresh();
1467 pParentWindow->GetDocNames( &aManualDoc ); // select
1468 }
1469}
1470
1471void ScContentTree::SelectDoc(const OUString& rName) // rName like shown in Menu/Listbox
1472{
1473 if ( rName == pParentWindow->aStrActiveWin )
1474 {
1476 return;
1477 }
1478
1479 // omit "active" or "inactive"
1480
1481 OUString aRealName = rName;
1482 sal_Int32 nLen = rName.getLength();
1483 sal_Int32 nActiveStart = nLen - pParentWindow->aStrActive.getLength();
1484 if ( rName.subView( nActiveStart ) == pParentWindow->aStrActive )
1485 aRealName = rName.copy( 0, nActiveStart );
1486 sal_Int32 nNotActiveStart = nLen - pParentWindow->aStrNotActive.getLength();
1487 if ( rName.subView( nNotActiveStart ) == pParentWindow->aStrNotActive )
1488 aRealName = rName.copy( 0, nNotActiveStart );
1489
1490 bool bLoaded = false;
1491
1492 // Is it a normally loaded document?
1493
1495 while ( pSh && !bLoaded )
1496 {
1497 if ( dynamic_cast<const ScDocShell*>( pSh) != nullptr )
1498 if ( pSh->GetTitle() == aRealName )
1499 bLoaded = true;
1500 pSh = SfxObjectShell::GetNext( *pSh );
1501 }
1502
1503 if (bLoaded)
1504 {
1505 bHiddenDoc = false;
1506 SetManualDoc(aRealName);
1507 }
1508 else if (!aHiddenTitle.isEmpty()) // hidden selected
1509 {
1510 if (!bHiddenDoc)
1512 }
1513 else
1514 {
1515 OSL_FAIL("SelectDoc: not found");
1516 }
1517}
1518
1519void ScContentTree::SelectEntryByName(const ScContentId nRoot, std::u16string_view rName)
1520{
1521 weld::TreeIter* pParent = m_aRootNodes[nRoot].get();
1522
1523 if (pParent || !m_xTreeView->iter_has_child(*pParent))
1524 return;
1525
1526 std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(pParent));
1527 bool bEntry = m_xTreeView->iter_children(*xEntry);
1528
1529 while (bEntry)
1530 {
1531 if (m_xTreeView->get_text(*xEntry) == rName)
1532 {
1533 m_xTreeView->select(*xEntry);
1534 m_xTreeView->set_cursor(*xEntry);
1535
1536 // Scroll to the selected item
1537 m_xTreeView->scroll_to_row(*xEntry);
1538
1540
1541 return;
1542 }
1543 bEntry = m_xTreeView->iter_next(*xEntry);
1544 }
1545}
1546
1548{
1550 if( !pSettings )
1551 return;
1552
1553 ScContentId nRootSel = pSettings->GetRootSelected();
1554 auto nChildSel = pSettings->GetChildSelected();
1555
1556 // tdf#133079 ensure Sheet root is selected if nothing
1557 // else would be
1558 if (nRootSel == ScContentId::ROOT)
1559 {
1560 nRootSel = ScContentId::TABLE;
1561 nChildSel = SC_CONTENT_NOCHILD;
1562 }
1563
1564 for( int i = 1; i <= int(ScContentId::LAST); ++i )
1565 {
1566 ScContentId nEntry = static_cast<ScContentId>(i);
1567 if( m_aRootNodes[ nEntry ] )
1568 {
1569 // gray or ungray
1570 if (!m_xTreeView->iter_has_child(*m_aRootNodes[nEntry]))
1571 m_xTreeView->set_sensitive(*m_aRootNodes[nEntry], false);
1572 else
1573 m_xTreeView->set_sensitive(*m_aRootNodes[nEntry], true);
1574
1575 // expand
1576 bool bExp = pSettings->IsExpanded( nEntry );
1577 if (bExp != m_xTreeView->get_row_expanded(*m_aRootNodes[nEntry]))
1578 {
1579 if( bExp )
1580 m_xTreeView->expand_row(*m_aRootNodes[nEntry]);
1581 else
1582 m_xTreeView->collapse_row(*m_aRootNodes[nEntry]);
1583 }
1584
1585 // select
1586 if( nRootSel == nEntry )
1587 {
1588 std::unique_ptr<weld::TreeIter> xEntry;
1589 if (bExp && (nChildSel != SC_CONTENT_NOCHILD))
1590 {
1591 xEntry = m_xTreeView->make_iterator(m_aRootNodes[nEntry].get());
1592 if (!m_xTreeView->iter_children(*xEntry) || !m_xTreeView->iter_nth_sibling(*xEntry, nChildSel))
1593 xEntry.reset();
1594 }
1595 m_xTreeView->select(xEntry ? *xEntry : *m_aRootNodes[nEntry]);
1596 m_xTreeView->set_cursor(xEntry ? *xEntry : *m_aRootNodes[nEntry]);
1597 }
1598 }
1599 }
1600}
1601
1603{
1605 {
1607 m_nAsyncMouseReleaseId = nullptr;
1608 }
1609
1611 if( !pSettings )
1612 return;
1613
1614 for( int i = 1; i <= int(ScContentId::LAST); ++i )
1615 {
1616 ScContentId nEntry = static_cast<ScContentId>(i);
1617 bool bExp = m_aRootNodes[nEntry] && m_xTreeView->get_row_expanded(*m_aRootNodes[nEntry]);
1618 pSettings->SetExpanded( nEntry, bExp );
1619 }
1620
1621 std::unique_ptr<weld::TreeIter> xCurEntry(m_xTreeView->make_iterator());
1622 if (!m_xTreeView->get_cursor(xCurEntry.get()))
1623 xCurEntry.reset();
1624
1625 ScContentId nRoot;
1626 sal_uLong nChild;
1627 GetEntryIndexes(nRoot, nChild, xCurEntry.get());
1628
1629 pSettings->SetRootSelected( nRoot );
1630 pSettings->SetChildSelected( nChild );
1631}
1632
1633/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
static std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false, sal_uInt64 nLOKWindowId=0)
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
OUString GetURLNoPass(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
SCTAB Tab() const
Definition: address.hxx:283
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
void SelectEntryByName(const ScContentId nRoot, std::u16string_view rName)
Definition: content.cxx:1519
ScDocument * pHiddenDocument
Definition: content.hxx:55
const ScAreaLink * GetLink(sal_uLong nIndex)
Definition: content.cxx:915
ScContentTree(std::unique_ptr< weld::TreeView > xTreeView, ScNavigatorDlg *pNavigatorDlg)
Definition: content.cxx:121
void GetLinkNames()
Definition: content.cxx:892
std::unique_ptr< weld::TreeIter > m_xScratchIter
Definition: content.hxx:46
void ToggleRoot()
Definition: content.cxx:1388
void GetNoteStrings()
Definition: content.cxx:946
void freeze()
Definition: content.hxx:100
void ClearType(ScContentId nType)
Definition: content.cxx:216
void thaw()
Definition: content.hxx:106
std::unique_ptr< weld::TreeView > m_xTreeView
Definition: content.hxx:45
void GetOleNames()
Definition: content.cxx:882
bool bHiddenDoc
Definition: content.hxx:52
void LaunchAsyncStoreNavigatorSettings()
Definition: content.cxx:400
ImplSVEvent * m_nAsyncMouseReleaseId
Definition: content.hxx:58
void StoreNavigatorSettings()
Stores the current listbox state in the navigator settings.
Definition: content.cxx:1602
void GetDrawNames(ScContentId nType)
Definition: content.cxx:818
void ApplyNavigatorSettings()
Applies the navigator settings to the listbox.
Definition: content.cxx:1547
bool NoteStringsChanged()
Definition: content.cxx:976
void GetTableNames()
Definition: content.cxx:714
bool ActiveDocChanged()
Definition: content.cxx:1424
void InsertContent(ScContentId nType, const OUString &rValue)
Definition: content.cxx:232
void Refresh(ScContentId nType=ScContentId::ROOT)
Definition: content.cxx:668
void GetDrawingNames()
Definition: content.cxx:887
OUString aHiddenName
Definition: content.hxx:53
o3tl::enumarray< ScContentId, sal_uInt16 > pPosList
Definition: content.hxx:60
OUString aManualDoc
Definition: content.hxx:51
bool bIsInNavigatorDlg
Definition: content.hxx:56
void SelectDoc(const OUString &rName)
Definition: content.cxx:1471
sal_uLong GetChildIndex(const weld::TreeIter *pEntry) const
Returns the child index of the specified listbox entry.
Definition: content.cxx:293
o3tl::enumarray< ScContentId, std::unique_ptr< weld::TreeIter > > m_aRootNodes
Definition: content.hxx:49
ScDocShell * GetManualOrCurrent()
Definition: content.cxx:90
void ClearAll()
Definition: content.cxx:199
void SetRootType(ScContentId nNew)
Definition: content.cxx:1376
static bool IsPartOfType(ScContentId nContentType, SdrObjKind nObjIdentifier)
Definition: content.cxx:796
rtl::Reference< ScLinkTransferObj > m_xTransferObj
Definition: content.hxx:47
ScContentId nRootType
Definition: content.hxx:50
void GetAreaNames()
Definition: content.cxx:740
void SetManualDoc(const OUString &rName)
Definition: content.cxx:1461
void GetDbNames()
Definition: content.cxx:778
ScNavigatorDlg * pParentWindow
Definition: content.hxx:48
void InitRoot(ScContentId nType)
Definition: content.cxx:179
void GetGraphicNames()
Definition: content.cxx:877
void GetEntryIndexes(ScContentId &rnRootIndex, sal_uLong &rnChildIndex, const weld::TreeIter *pEntry) const
Returns the indexes of the specified listbox entry.
Definition: content.cxx:246
ScDocument * GetSourceDocument()
Definition: content.cxx:654
void LoadFile(const OUString &rUrl)
Definition: content.cxx:1349
OUString aHiddenTitle
Definition: content.hxx:54
ScAddress GetNotePos(sal_uLong nIndex)
Definition: content.cxx:967
bool DrawNamesChanged(ScContentId nType)
Definition: content.cxx:1006
bool m_bFreeze
Definition: content.hxx:57
void ResetManualDoc()
Definition: content.cxx:1416
Stores global named database ranges.
Definition: dbdata.hxx:243
ScDBData * findByUpperName(const OUString &rName)
Definition: dbdata.cxx:1221
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:324
const ScDocument & GetDocument() const
Definition: docsh.hxx:219
bool IsError() const
Definition: tablink.cxx:577
OUString GetTitle() const
Definition: tablink.cxx:585
ScDocument * GetDocument()
Definition: tablink.cxx:572
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:898
SC_DLLPUBLIC bool GetTable(const OUString &rName, SCTAB &rTab) const
Definition: document.cxx:244
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:492
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:893
SC_DLLPUBLIC void CopyToClip(const ScClipParam &rClipParam, ScDocument *pClipDoc, const ScMarkData *pMarks, bool bKeepScenarioFlags, bool bIncludeObjects)
Definition: document.cxx:2142
SC_DLLPUBLIC void GetAllNoteEntries(std::vector< sc::NoteEntry > &rNotes) const
Definition: document.cxx:6837
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1084
ScAddress GetNotePosition(size_t nIndex) const
Definition: document.cxx:6775
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:827
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1083
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:171
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:231
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:204
bool HasSelectedBlockMatrixFragment(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScMarkData &rMark) const
Definition: document.cxx:5395
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:297
static OUString GetVisibleName(const SdrObject *pObj)
Definition: drwlayer.cxx:2424
static void SetGlobalDrawPersist(SfxObjectShell *pPersist)
Definition: drwlayer.cxx:2927
SdrObject * GetNamedObject(std::u16string_view rName, SdrObjKind nId, SCTAB &rFoundTab) const
Definition: drwlayer.cxx:2450
void SelectCurrentViewObject(std::u16string_view rName)
Definition: drawview.cxx:674
SdrObject * GetObjectByName(std::u16string_view rName)
Definition: drawview.cxx:643
bool GetObjectIsMarked(const SdrObject *pObject)
Definition: drawview.cxx:787
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1064
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
void SelectTable(SCTAB nTab, bool bNew)
Definition: markdata.cxx:157
void SetMarkArea(const ScRange &rRange)
Definition: markdata.cxx:92
void SetDragLink(const OUString &rDoc, const OUString &rTab, const OUString &rArea)
Definition: scmod.cxx:651
void SetDragJump(ScDocument *pLocalDoc, const OUString &rTarget, const OUString &rText)
Definition: scmod.cxx:669
static ScNavigatorSettings * GetNavigatorSettings()
Definition: navipi.cxx:708
OUString aStrActiveWin
Definition: navipi.hxx:115
OUString aStrNotActive
Definition: navipi.hxx:113
static ScTabViewShell * GetTabViewShell()
Definition: navipi.cxx:703
void GetDocNames(const OUString *pSelEntry)
Definition: navipi.cxx:850
OUString aStrActive
Definition: navipi.hxx:112
static void ReleaseFocus()
Definition: navipi.cxx:64
Contains settings of the navigator listbox.
Definition: navsett.hxx:30
bool IsExpanded(ScContentId nIndex) const
Definition: navsett.hxx:40
ScContentId GetRootSelected() const
Definition: navsett.hxx:43
sal_uLong GetChildSelected() const
Definition: navsett.hxx:46
void SetRootSelected(ScContentId nIndex)
Definition: navsett.hxx:42
void SetChildSelected(sal_uLong nIndex)
Definition: navsett.hxx:45
void SetExpanded(ScContentId nIndex, bool bExpand)
Definition: navsett.hxx:39
void SetRootType(ScContentId nNew)
Definition: navicfg.cxx:51
Additional class containing cell annotation data.
Definition: postit.hxx:58
OUString GetText() const
Returns the caption text of this note.
Definition: postit.cxx:527
bool empty() const
Definition: rangenam.hxx:249
SC_DLLPUBLIC ScRangeData * findByUpperName(const OUString &rName)
Definition: rangenam.cxx:704
SC_DLLPUBLIC bool insert(ScRangeData *p, bool bReuseFreeIndex=true)
Insert object into set.
Definition: rangenam.cxx:802
OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2170
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
void SetDrawShell(bool bActive)
Definition: tabvwsh4.cxx:613
ScViewData & GetViewData()
Definition: tabview.hxx:344
ScDrawView * GetScDrawView()
Definition: viewdata.cxx:3174
virtual std::unique_ptr< SdrModel > CreateMarkedObjModel() const
bool MarkObj(const Point &rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false)
const SdrPage * GetPage(sal_uInt16 nPgNum) const
SdrPageView * ShowSdrPage(SdrPage *pPage) override
SdrObject * Next()
SdrPageView * GetSdrPageView() const
SdrModel & GetModel() const
const INetURLObject & GetURLObject() const
const OUString & GetName() const
void FillTransferableObjectDescriptor(TransferableObjectDescriptor &rDesc) const
bool HasName() const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * GetNext(const SfxObjectShell &rPrev, const std::function< bool(const SfxObjectShell *)> &isObjectShell=nullptr, bool bOnlyVisible=true)
SfxMedium * GetMedium() const
OUString GetTitle(sal_uInt16 nMaxLen=0) const
static SAL_WARN_UNUSED_RESULT SfxObjectShell * GetFirst(const std::function< bool(const SfxObjectShell *)> &isObjectShell=nullptr, bool bOnlyVisible=true)
static SAL_WARN_UNUSED_RESULT SfxObjectShell * Current()
virtual SfxObjectShell * GetObjectShell() override
SfxViewFrame & GetViewFrame() const
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
const SvBaseLinks & GetLinks() const
T * get() const
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
virtual void enable_drag_source(rtl::Reference< TransferDataContainer > &rTransferable, sal_uInt8 eDNDConstants)=0
constexpr rtl::OUStringConstExpr aContentBmps[]
Definition: content.cxx:78
IMPL_LINK_NOARG(ScContentTree, ContentDoubleClickHdl, weld::TreeView &, bool)
Definition: content.cxx:318
static OUString lcl_GetDBAreaRange(const ScDocument *pDoc, const OUString &rDBName)
Definition: content.cxx:301
const ScContentId pTypeList[int(ScContentId::LAST)+1]
Definition: content.cxx:65
static bool lcl_DoDragObject(ScDocShell *pSrcShell, std::u16string_view rName, ScContentId nType, weld::TreeView &rTreeView)
Definition: content.cxx:1097
const TranslateId SCSTR_CONTENT_ARY[]
Definition: content.cxx:166
IMPL_LINK(ScContentTree, KeyInputHdl, const KeyEvent &, rKEvt, bool)
Definition: content.cxx:418
static OUString lcl_NoteString(const ScPostIt &rNote)
Definition: content.cxx:941
constexpr int MAX_TREE_NODES
Definition: content.cxx:816
static bool lcl_GetRange(const ScDocument &rDoc, ScContentId nType, const OUString &rName, ScRange &rRange)
Definition: content.cxx:1062
static bool lcl_DoDragCells(ScDocShell *pSrcShell, const ScRange &rRange, ScDragSrc nFlags, weld::TreeView &rTreeView)
Definition: content.cxx:1155
ScContentId
Definition: content.hxx:35
const sal_uLong SC_CONTENT_NOCHILD
Definition: content.hxx:41
int nCount
URL aURL
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2720
@ SCDOCMODE_CLIP
Definition: document.hxx:257
ScXMLEditAttributeMap::Entry const aEntries[]
EmbeddedObjectRef * pObject
sal_Int32 nIndex
OUString aName
void * p
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_MOD1
constexpr sal_uInt16 KEY_F5
constexpr sal_uInt16 KEY_SPACE
sal_uInt16 nPos
SvBaseLink * pLink
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
ROOT
#define SC_DROPMODE_COPY
Definition: navipi.hxx:41
#define SC_DROPMODE_URL
Definition: navipi.hxx:39
#define SC_DROPMODE_LINK
Definition: navipi.hxx:40
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
#define SC_MOD()
Definition: scmod.hxx:247
sal_uIntPtr sal_uLong
This struct stores general clipboard parameters associated with a ScDocument instance created in clip...
Definition: clipparam.hxx:31
SdrIterMode
SdrObjKind
#define DND_ACTION_COPY
#define DND_ACTION_LINK
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
OUString sId
ScDragSrc
Definition: viewdata.hxx:91