1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <string_view>
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>
35 #include <unotools/charclass.hxx>
37 #include <content.hxx>
41 #include <docfunc.hxx>
43 #include <rangenam.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>
56 #include <tabvwsh.hxx>
57 #include <drawview.hxx>
58 #include <clipparam.hxx>
59 #include <markdata.hxx>
61 using namespace com::sun::star
;
63 // order of the categories in navigator -------------------------------------
65 const ScContentId pTypeList
[int(ScContentId::LAST
) + 1] =
67 ScContentId::ROOT
, // ROOT (0) has to be at the front
69 ScContentId::RANGENAME
,
71 ScContentId::AREALINK
,
73 ScContentId::OLEOBJECT
,
78 constexpr OUString aContentBmps
[]=
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
,
86 RID_BMP_CONTENT_AREALINK
,
87 RID_BMP_CONTENT_DRAWING
90 ScDocShell
* ScContentTree::GetManualOrCurrent()
92 ScDocShell
* pSh
= nullptr;
93 if ( !aManualDoc
.isEmpty() )
95 SfxObjectShell
* pObjSh
= SfxObjectShell::GetFirst( checkSfxObjectShell
<ScDocShell
> );
96 while ( pObjSh
&& !pSh
)
98 if ( pObjSh
->GetTitle() == aManualDoc
)
99 pSh
= dynamic_cast<ScDocShell
*>( pObjSh
);
100 pObjSh
= SfxObjectShell::GetNext( *pObjSh
, checkSfxObjectShell
<ScDocShell
> );
105 // only current when manual isn't set
106 // (so it's detected when the documents don't exists any longer)
108 SfxViewShell
* pViewSh
= SfxViewShell::Current();
111 SfxObjectShell
* pObjSh
= pViewSh
->GetViewFrame().GetObjectShell();
112 pSh
= dynamic_cast<ScDocShell
*>( pObjSh
);
121 ScContentTree::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 , bIsInNavigatorDlg(false)
129 , m_nAsyncMouseReleaseId(nullptr)
131 for (sal_uInt16 i
= 0; i
<= int(ScContentId::LAST
); ++i
)
132 pPosList
[pTypeList
[i
]] = i
; // inverse for searching
134 m_aRootNodes
[ScContentId::ROOT
] = nullptr;
135 for (sal_uInt16 i
= 1; i
< int(ScContentId::LAST
); ++i
)
136 InitRoot(static_cast<ScContentId
>(i
));
138 m_xTreeView
->connect_row_activated(LINK(this, ScContentTree
, ContentDoubleClickHdl
));
139 m_xTreeView
->connect_mouse_release(LINK(this, ScContentTree
, MouseReleaseHdl
));
140 m_xTreeView
->connect_key_press(LINK(this, ScContentTree
, KeyInputHdl
));
141 m_xTreeView
->connect_popup_menu(LINK(this, ScContentTree
, CommandHdl
));
142 m_xTreeView
->connect_query_tooltip(LINK(this, ScContentTree
, QueryTooltipHdl
));
144 rtl::Reference
<TransferDataContainer
> xHelper(m_xTransferObj
);
145 m_xTreeView
->enable_drag_source(xHelper
, DND_ACTION_COPY
| DND_ACTION_LINK
);
147 m_xTreeView
->connect_drag_begin(LINK(this, ScContentTree
, DragBeginHdl
));
149 m_xTreeView
->set_selection_mode( SelectionMode::Single
);
151 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 30,
152 m_xTreeView
->get_text_height() * 13);
155 ScContentTree::~ScContentTree()
157 if (m_nAsyncMouseReleaseId
)
159 Application::RemoveUserEvent(m_nAsyncMouseReleaseId
);
160 m_nAsyncMouseReleaseId
= nullptr;
164 const TranslateId SCSTR_CONTENT_ARY
[] =
168 SCSTR_CONTENT_RANGENAME
,
169 SCSTR_CONTENT_DBAREA
,
170 SCSTR_CONTENT_GRAPHIC
,
171 SCSTR_CONTENT_OLEOBJECT
,
173 SCSTR_CONTENT_AREALINK
,
174 SCSTR_CONTENT_DRAWING
177 void ScContentTree::InitRoot( ScContentId nType
)
179 if ( nType
== ScContentId::ROOT
)
182 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= nType
) // hidden ?
184 m_aRootNodes
[nType
] = nullptr;
188 auto const & aImage
= aContentBmps
[static_cast<int>(nType
) - 1];
191 if(comphelper::LibreOfficeKit::isActive())
193 //In case of LOK we may have many different ScContentTrees in different languages.
194 //At creation time, we store what language we use, and then use it later too.
195 //It does not work in the constructor, that is why it is here.
196 if (!m_pResLocaleForLOK
)
198 m_pResLocaleForLOK
= std::make_unique
<std::locale
>(ScModule::get()->GetResLocale());
200 aName
= Translate::get(SCSTR_CONTENT_ARY
[static_cast<int>(nType
)], *m_pResLocaleForLOK
);
204 aName
= ScResId(SCSTR_CONTENT_ARY
[static_cast<int>(nType
)]);
206 // back to the correct position:
207 sal_uInt16 nPos
= nRootType
!= ScContentId::ROOT
? 0 : pPosList
[nType
]-1;
208 m_aRootNodes
[nType
] = m_xTreeView
->make_iterator();
209 m_xTreeView
->insert(nullptr, nPos
, &aName
, nullptr, nullptr, nullptr, false, m_aRootNodes
[nType
].get());
210 m_xTreeView
->set_image(*m_aRootNodes
[nType
], aImage
);
213 void ScContentTree::ClearAll()
215 //There are one method in Control::SetUpdateMode(), and one override method SvTreeListBox::SetUpdateMode(). Here although
216 //SvTreeListBox::SetUpdateMode() is called in refresh method, it only call SvTreeListBox::SetUpdateMode(), not Control::SetUpdateMode().
217 //In m_xTreeView->clear(), Broadcast( LISTACTION_CLEARED ) will be called and finally, it will be trapped into the event yield() loop. And
218 //the InitRoot() method won't be called. Then if a user click or press key to update the navigator tree, crash happens.
219 //So the solution is to disable the UpdateMode of Control, then call Clear(), then recover the update mode
220 bool bWasFrozen
= m_bFreeze
;
223 m_xTreeView
->clear();
226 for (sal_uInt16 i
=1; i
<=int(ScContentId::LAST
); i
++)
227 InitRoot(static_cast<ScContentId
>(i
));
230 void ScContentTree::ClearType(ScContentId nType
)
232 if (nType
== ScContentId::ROOT
)
236 weld::TreeIter
* pParent
= m_aRootNodes
[nType
].get();
237 if (!pParent
|| m_xTreeView
->iter_has_child(*pParent
)) // not if no children existing
240 m_xTreeView
->remove(*pParent
); // with all children
241 InitRoot( nType
); // if needed insert anew
246 void ScContentTree::InsertContent( ScContentId nType
, const OUString
& rValue
)
248 weld::TreeIter
* pParent
= m_aRootNodes
[nType
].get();
251 m_xTreeView
->insert(pParent
, -1, &rValue
, nullptr, nullptr, nullptr, false, m_xScratchIter
.get());
252 m_xTreeView
->set_sensitive(*m_xScratchIter
, true);
256 OSL_FAIL("InsertContent without parent");
260 void ScContentTree::GetEntryIndexes(ScContentId
& rnRootIndex
, sal_uLong
& rnChildIndex
, const weld::TreeIter
* pEntry
) const
262 rnRootIndex
= ScContentId::ROOT
;
263 rnChildIndex
= SC_CONTENT_NOCHILD
;
268 std::unique_ptr
<weld::TreeIter
> xParent(m_xTreeView
->make_iterator(pEntry
));
269 if (!m_xTreeView
->iter_parent(*xParent
))
272 for( int i
= 1; !bFound
&& (i
<= int(ScContentId::LAST
)); ++i
)
274 ScContentId nRoot
= static_cast<ScContentId
>(i
);
275 if (!m_aRootNodes
[nRoot
])
277 if (m_xTreeView
->iter_compare(*pEntry
, *m_aRootNodes
[nRoot
]) == 0)
283 else if (xParent
&& m_xTreeView
->iter_compare(*xParent
, *m_aRootNodes
[nRoot
]) == 0)
287 // search the entry in all child entries of the parent
288 sal_uLong nEntry
= 0;
289 std::unique_ptr
<weld::TreeIter
> xIterEntry(m_xTreeView
->make_iterator(xParent
.get()));
290 bool bIterEntry
= m_xTreeView
->iter_children(*xIterEntry
);
291 while (!bFound
&& bIterEntry
)
293 if (m_xTreeView
->iter_compare(*pEntry
, *xIterEntry
) == 0)
295 rnChildIndex
= nEntry
;
296 bFound
= true; // exit the while loop
298 bIterEntry
= m_xTreeView
->iter_next_sibling(*xIterEntry
);
302 bFound
= true; // exit the for loop
307 sal_uLong
ScContentTree::GetChildIndex(const weld::TreeIter
* pEntry
) const
311 GetEntryIndexes(nRoot
, nChild
, pEntry
);
315 static OUString
lcl_GetDBAreaRange( const ScDocument
* pDoc
, const OUString
& rDBName
)
320 ScDBCollection
* pDbNames
= pDoc
->GetDBCollection();
321 const ScDBData
* pData
= pDbNames
->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rDBName
));
325 pData
->GetArea(aRange
);
326 aRet
= aRange
.Format(*pDoc
, ScRefFlags::RANGE_ABS_3D
);
332 IMPL_LINK_NOARG(ScContentTree
, ContentDoubleClickHdl
, weld::TreeView
&, bool)
336 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
337 if (!m_xTreeView
->get_cursor(xEntry
.get()))
339 GetEntryIndexes(nType
, nChild
, xEntry
.get());
341 if (xEntry
&& (nType
!= ScContentId::ROOT
) && (nChild
!= SC_CONTENT_NOCHILD
))
343 OUString
aText(m_xTreeView
->get_text(*xEntry
));
345 if ( !aManualDoc
.isEmpty() )
346 pParentWindow
->SetCurrentDoc( aManualDoc
);
350 case ScContentId::TABLE
:
352 // tdf#133159 store current config before changing sheet
353 // plausible that this should be done for all cases, but this
354 // is the known case that needs it
355 StoreNavigatorSettings();
356 pParentWindow
->SetCurrentTableStr( aText
);
360 case ScContentId::RANGENAME
:
361 pParentWindow
->SetCurrentCellStr( aText
);
364 case ScContentId::DBAREA
:
366 // If the same names of area and DB exists, then
367 // SID_CURRENTCELL takes the area name.
368 // Therefore for DB areas access them directly via address.
370 OUString aRangeStr
= lcl_GetDBAreaRange( GetSourceDocument(), aText
);
371 if (!aRangeStr
.isEmpty())
372 pParentWindow
->SetCurrentCellStr( aRangeStr
);
376 case ScContentId::OLEOBJECT
:
377 case ScContentId::GRAPHIC
:
378 case ScContentId::DRAWING
:
379 pParentWindow
->SetCurrentObject( aText
);
382 case ScContentId::NOTE
:
384 ScAddress aPos
= GetNotePos( nChild
);
385 pParentWindow
->SetCurrentTable( aPos
.Tab() );
386 pParentWindow
->SetCurrentCell( aPos
.Col(), aPos
.Row() );
387 // Check whether the comment is currently visible and toggle its visibility
388 ScDocument
* pSrcDoc
= GetSourceDocument();
389 if (ScPostIt
* pNote
= pSrcDoc
? pSrcDoc
->GetNote(aPos
.Col(), aPos
.Row(), aPos
.Tab()) : nullptr)
391 bool bVisible
= pNote
->IsCaptionShown();
392 // Effectivelly set the visibility of the comment
393 GetManualOrCurrent()->GetDocFunc().ShowNote(aPos
, !bVisible
);
394 // Put the note in edit mode
395 ScTabViewShell
* pScTabViewShell
= ScNavigatorDlg::GetTabViewShell();
396 pScTabViewShell
->EditNote();
401 case ScContentId::AREALINK
:
403 const ScAreaLink
* pLink
= GetLink(nChild
);
404 ScDocument
* pSrcDoc
= GetSourceDocument();
405 if (pLink
&& pSrcDoc
)
407 const ScRange
& aRange
= pLink
->GetDestArea();
408 OUString
aRangeStr(aRange
.Format(*pSrcDoc
, ScRefFlags::RANGE_ABS_3D
, pSrcDoc
->GetAddressConvention()));
409 pParentWindow
->SetCurrentCellStr( aRangeStr
);
416 ScNavigatorDlg::ReleaseFocus(); // set focus into document
422 void ScContentTree::LaunchAsyncStoreNavigatorSettings()
424 if (!m_nAsyncMouseReleaseId
)
425 m_nAsyncMouseReleaseId
= Application::PostUserEvent(LINK(this, ScContentTree
, AsyncStoreNavigatorSettings
));
428 IMPL_LINK_NOARG(ScContentTree
, MouseReleaseHdl
, const MouseEvent
&, bool)
430 LaunchAsyncStoreNavigatorSettings();
434 IMPL_LINK_NOARG(ScContentTree
, AsyncStoreNavigatorSettings
, void*, void)
436 m_nAsyncMouseReleaseId
= nullptr;
437 StoreNavigatorSettings();
440 IMPL_LINK(ScContentTree
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
444 const vcl::KeyCode aCode
= rKEvt
.GetKeyCode();
445 if (aCode
.GetCode() == KEY_RETURN
)
447 switch (aCode
.GetModifier())
450 ToggleRoot(); // toggle root mode (as in Writer)
455 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
456 if (!m_xTreeView
->get_cursor(xEntry
.get()))
462 GetEntryIndexes(nType
, nChild
, xEntry
.get());
464 if (nType
!= ScContentId::ROOT
&& nChild
== SC_CONTENT_NOCHILD
)
466 if (m_xTreeView
->get_row_expanded(*xEntry
))
467 m_xTreeView
->collapse_row(*xEntry
);
469 m_xTreeView
->expand_row(*xEntry
);
472 ContentDoubleClickHdl(*m_xTreeView
); // select content as if double clicked
480 //Make KEY_SPACE has same function as DoubleClick, and realize
482 if ( bIsInNavigatorDlg
)
484 if(aCode
.GetCode() == KEY_SPACE
)
489 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
490 if (!m_xTreeView
->get_cursor(xEntry
.get()))
492 GetEntryIndexes(nType
, nChild
, xEntry
.get());
494 if (xEntry
&& (nType
!= ScContentId::ROOT
) && (nChild
!= SC_CONTENT_NOCHILD
))
496 OUString
aText(m_xTreeView
->get_text(*xEntry
));
497 if (!aManualDoc
.isEmpty())
498 pParentWindow
->SetCurrentDoc( aManualDoc
);
501 case ScContentId::OLEOBJECT
:
502 case ScContentId::GRAPHIC
:
503 case ScContentId::DRAWING
:
505 ScDrawView
* pScDrawView
= nullptr;
506 ScTabViewShell
* pScTabViewShell
= ScNavigatorDlg::GetTabViewShell();
508 pScDrawView
= pScTabViewShell
->GetViewData().GetScDrawView();
511 pScDrawView
->SelectCurrentViewObject(aText
);
512 bool bHasMakredObject
= false;
513 weld::TreeIter
* pParent
= m_aRootNodes
[nType
].get();
514 std::unique_ptr
<weld::TreeIter
> xBeginEntry(m_xTreeView
->make_iterator(pParent
));
515 bool bBeginEntry
= false;
517 bBeginEntry
= m_xTreeView
->iter_children(*xBeginEntry
);
520 OUString
aTempText(m_xTreeView
->get_text(*xBeginEntry
));
521 if( pScDrawView
->GetObjectIsMarked( pScDrawView
->GetObjectByName( aTempText
) ) )
523 bHasMakredObject
= true;
526 bBeginEntry
= m_xTreeView
->iter_next(*xBeginEntry
);
528 if (!bHasMakredObject
&& pScTabViewShell
)
529 pScTabViewShell
->SetDrawShell(false);
542 if (aCode
.GetCode() == KEY_F5
)
543 StoreNavigatorSettings();
545 LaunchAsyncStoreNavigatorSettings();
551 IMPL_LINK(ScContentTree
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
557 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
558 if (!m_xTreeView
->get_cursor(xEntry
.get()))
560 GetEntryIndexes(nType
, nChild
, xEntry
.get());
562 switch ( rCEvt
.GetCommand() )
564 case CommandEventId::ContextMenu
:
566 // drag-and-drop mode
567 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(m_xTreeView
.get(), u
"modules/scalc/ui/dropmenu.ui"_ustr
));
568 std::unique_ptr
<weld::Menu
> xPop(xBuilder
->weld_menu(u
"contextmenu"_ustr
));
569 std::unique_ptr
<weld::Menu
> xDropMenu(xBuilder
->weld_menu(u
"dragmodesubmenu"_ustr
));
571 switch (pParentWindow
->GetDropMode())
574 xDropMenu
->set_active(u
"hyperlink"_ustr
, true);
577 xDropMenu
->set_active(u
"link"_ustr
, true);
580 xDropMenu
->set_active(u
"copy"_ustr
, true);
584 // displayed document
585 std::unique_ptr
<weld::Menu
> xDocMenu(xBuilder
->weld_menu(u
"displaymenu"_ustr
));
590 ScDocShell
* pCurrentSh
= dynamic_cast<ScDocShell
*>( SfxObjectShell::Current() );
591 SfxObjectShell
* pSh
= SfxObjectShell::GetFirst();
594 if ( dynamic_cast<const ScDocShell
*>( pSh
) != nullptr )
596 OUString aName
= pSh
->GetTitle();
597 OUString aEntry
= aName
;
598 if ( pSh
== pCurrentSh
)
599 aEntry
+= pParentWindow
->aStrActive
;
601 aEntry
+= pParentWindow
->aStrNotActive
;
603 sId
= "document" + OUString::number(i
);
604 xDocMenu
->append_radio(sId
, aEntry
);
605 if (aName
== aManualDoc
)
608 pSh
= SfxObjectShell::GetNext( *pSh
);
612 sId
= "document" + OUString::number(i
);
613 xDocMenu
->append_radio(sId
, pParentWindow
->aStrActiveWin
);
614 if (aManualDoc
.isEmpty())
616 xDocMenu
->set_active(sActive
, true);
618 // Edit/Delete Comments are only visible for comments
619 if (nType
!= ScContentId::NOTE
)
621 xPop
->set_visible(u
"edit"_ustr
, false);
622 xPop
->set_visible(u
"delete"_ustr
, false);
625 OUString sIdent
= xPop
->popup_at_rect(m_xTreeView
.get(), tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1, 1)));
626 if (sIdent
== "hyperlink")
627 pParentWindow
->SetDropMode(0);
628 else if (sIdent
== "link")
629 pParentWindow
->SetDropMode(1);
630 else if (sIdent
== "copy")
631 pParentWindow
->SetDropMode(2);
632 else if (sIdent
.startsWith("document"))
634 OUString aName
= xDocMenu
->get_label(sIdent
);
637 else if (sIdent
== "edit")
639 ScAddress aPos
= GetNotePos( nChild
);
640 pParentWindow
->SetCurrentTable( aPos
.Tab() );
641 pParentWindow
->SetCurrentCell( aPos
.Col(), aPos
.Row() );
642 ScDocument
* pSrcDoc
= GetSourceDocument();
643 if (pSrcDoc
->GetNote(aPos
.Col(), aPos
.Row(), aPos
.Tab()))
645 // Make the note visible and put it in edit mode
646 GetManualOrCurrent()->GetDocFunc().ShowNote(aPos
, true);
647 ScTabViewShell
* pScTabViewShell
= ScNavigatorDlg::GetTabViewShell();
648 pScTabViewShell
->EditNote();
652 else if (sIdent
== "delete")
654 ScAddress aPos
= GetNotePos(nChild
);
655 pParentWindow
->SetCurrentTable(aPos
.Tab());
656 pParentWindow
->SetCurrentCell(aPos
.Col(), aPos
.Row());
657 ScTabViewShell
* pScTabViewShell
= ScNavigatorDlg::GetTabViewShell();
658 pScTabViewShell
->DeleteContents(InsertDeleteFlags::NOTE
);
668 IMPL_LINK(ScContentTree
, QueryTooltipHdl
, const weld::TreeIter
&, rEntry
, OUString
)
672 std::unique_ptr
<weld::TreeIter
> xParent(m_xTreeView
->make_iterator(&rEntry
));
673 if (!m_xTreeView
->iter_parent(*xParent
))
676 if (!xParent
) // Top-Level ?
678 aHelpText
= OUString::number(m_xTreeView
->iter_n_children(rEntry
)) +
679 " " + m_xTreeView
->get_text(rEntry
);
681 else if (m_aRootNodes
[ScContentId::NOTE
] && m_xTreeView
->iter_compare(*xParent
, *m_aRootNodes
[ScContentId::NOTE
]) == 0)
683 aHelpText
= m_xTreeView
->get_text(rEntry
); // notes as help text
685 else if (m_aRootNodes
[ScContentId::AREALINK
] && m_xTreeView
->iter_compare(*xParent
, *m_aRootNodes
[ScContentId::AREALINK
]) == 0)
687 auto nIndex
= GetChildIndex(&rEntry
);
688 if (nIndex
!= SC_CONTENT_NOCHILD
)
690 const ScAreaLink
* pLink
= GetLink(nIndex
);
693 aHelpText
= pLink
->GetFile(); // source file as help text
701 ScDocument
* ScContentTree::GetSourceDocument()
703 ScDocShell
* pSh
= GetManualOrCurrent();
705 return &pSh
->GetDocument();
709 void ScContentTree::Refresh( ScContentId nType
)
711 // if nothing has changed the cancel right away (against flicker)
712 if ( nType
== ScContentId::NOTE
)
713 if (!NoteStringsChanged())
715 if ( nType
== ScContentId::GRAPHIC
)
716 if (!DrawNamesChanged(ScContentId::GRAPHIC
))
718 if ( nType
== ScContentId::OLEOBJECT
)
719 if (!DrawNamesChanged(ScContentId::OLEOBJECT
))
721 if ( nType
== ScContentId::DRAWING
)
722 if (!DrawNamesChanged(ScContentId::DRAWING
))
729 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::TABLE
)
731 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::RANGENAME
)
733 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::DBAREA
)
735 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::GRAPHIC
)
737 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::OLEOBJECT
)
739 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::DRAWING
)
741 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::NOTE
)
743 if ( nType
== ScContentId::ROOT
|| nType
== ScContentId::AREALINK
)
748 ApplyNavigatorSettings();
751 void ScContentTree::GetTableNames()
753 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= ScContentId::TABLE
) // hidden ?
756 ScDocument
* pDoc
= GetSourceDocument();
761 SCTAB nCount
= pDoc
->GetTableCount();
762 for ( SCTAB i
=0; i
<nCount
; i
++ )
764 pDoc
->GetName( i
, aName
);
765 InsertContent( ScContentId::TABLE
, aName
);
771 OUString
createLocalRangeName(std::u16string_view rName
, std::u16string_view rTableName
)
773 return OUString::Concat(rName
) + " (" + rTableName
+ ")";
777 void ScContentTree::GetAreaNames()
779 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= ScContentId::RANGENAME
) // hidden ?
782 ScDocument
* pDoc
= GetSourceDocument();
787 std::set
<OUString
> aSet
;
788 ScRangeName
* pRangeNames
= pDoc
->GetRangeName();
789 for (const auto& rEntry
: *pRangeNames
)
791 if (rEntry
.second
->IsValidReference(aDummy
))
792 aSet
.insert(rEntry
.second
->GetName());
794 for (SCTAB i
= 0; i
< pDoc
->GetTableCount(); ++i
)
796 ScRangeName
* pLocalRangeName
= pDoc
->GetRangeName(i
);
797 if (pLocalRangeName
&& !pLocalRangeName
->empty())
800 pDoc
->GetName(i
, aTableName
);
801 for (const auto& rEntry
: *pLocalRangeName
)
803 if (rEntry
.second
->IsValidReference(aDummy
))
804 aSet
.insert(createLocalRangeName(rEntry
.second
->GetName(), aTableName
));
809 for (const auto& rItem
: aSet
)
811 InsertContent(ScContentId::RANGENAME
, rItem
);
815 void ScContentTree::GetDbNames()
817 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= ScContentId::DBAREA
) // hidden ?
820 ScDocument
* pDoc
= GetSourceDocument();
824 ScDBCollection
* pDbNames
= pDoc
->GetDBCollection();
825 const ScDBCollection::NamedDBs
& rDBs
= pDbNames
->getNamedDBs();
826 for (const auto& rxDB
: rDBs
)
828 const OUString
& aStrName
= rxDB
->GetName();
829 InsertContent(ScContentId::DBAREA
, aStrName
);
833 bool ScContentTree::IsPartOfType( ScContentId nContentType
, SdrObjKind nObjIdentifier
)
836 switch ( nContentType
)
838 case ScContentId::GRAPHIC
:
839 bRet
= ( nObjIdentifier
== SdrObjKind::Graphic
);
841 case ScContentId::OLEOBJECT
:
842 bRet
= ( nObjIdentifier
== SdrObjKind::OLE2
);
844 case ScContentId::DRAWING
:
845 bRet
= ( nObjIdentifier
!= SdrObjKind::Graphic
&& nObjIdentifier
!= SdrObjKind::OLE2
); // everything else
848 OSL_FAIL("unknown content type");
853 constexpr int MAX_TREE_NODES
= 1000;
855 void ScContentTree::GetDrawNames( ScContentId nType
)
857 if (!bIsInNavigatorDlg
)
860 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= nType
) // hidden ?
863 ScDocument
* pDoc
= GetSourceDocument();
867 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
871 ScDocShell
* pShell
= pDoc
->GetDocumentShell();
875 // iterate in flat mode for groups
876 SdrIterMode eIter
= ( nType
== ScContentId::DRAWING
) ? SdrIterMode::Flat
: SdrIterMode::DeepNoGroups
;
878 std::vector
<OUString
> aNames
;
879 SCTAB nTabCount
= pDoc
->GetTableCount();
880 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
882 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
883 OSL_ENSURE(pPage
,"Page ?");
886 SdrObjListIter
aIter(pPage
, eIter
);
887 SdrObject
* pObject
= aIter
.Next();
890 if (IsPartOfType(nType
, pObject
->GetObjIdentifier()))
892 OUString aName
= ScDrawLayer::GetVisibleName(pObject
);
893 if (!aName
.isEmpty())
894 aNames
.push_back(aName
);
895 if (aNames
.size() > MAX_TREE_NODES
)
897 SAL_WARN("sc", "too many tree nodes, ignoring the rest");
901 pObject
= aIter
.Next();
905 weld::TreeIter
* pParent
= m_aRootNodes
[nType
].get();
906 assert(pParent
&& "InsertContent without parent");
907 // insert all of these in one go under pParent
908 m_xTreeView
->bulk_insert_for_each(aNames
.size(), [this, &aNames
](weld::TreeIter
& rIter
, int nIndex
) {
909 m_xTreeView
->set_text(rIter
, aNames
[nIndex
], 0);
910 m_xTreeView
->set_sensitive(rIter
, true);
914 void ScContentTree::GetGraphicNames()
916 GetDrawNames( ScContentId::GRAPHIC
);
919 void ScContentTree::GetOleNames()
921 GetDrawNames( ScContentId::OLEOBJECT
);
924 void ScContentTree::GetDrawingNames()
926 GetDrawNames( ScContentId::DRAWING
);
929 void ScContentTree::GetLinkNames()
931 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= ScContentId::AREALINK
) // hidden ?
934 ScDocument
* pDoc
= GetSourceDocument();
938 sfx2::LinkManager
* pLinkManager
= pDoc
->GetLinkManager();
939 assert(pLinkManager
&& "no LinkManager on document?");
940 const ::sfx2::SvBaseLinks
& rLinks
= pLinkManager
->GetLinks();
941 sal_uInt16 nCount
= rLinks
.size();
942 for (sal_uInt16 i
=0; i
<nCount
; i
++)
944 ::sfx2::SvBaseLink
* pBase
= rLinks
[i
].get();
945 if (auto pScAreaLink
= dynamic_cast<const ScAreaLink
*>( pBase
))
946 InsertContent( ScContentId::AREALINK
, pScAreaLink
->GetSource() );
948 // insert in list the names of source areas
952 const ScAreaLink
* ScContentTree::GetLink( sal_uLong nIndex
)
954 ScDocument
* pDoc
= GetSourceDocument();
958 sal_uLong nFound
= 0;
959 sfx2::LinkManager
* pLinkManager
= pDoc
->GetLinkManager();
960 assert(pLinkManager
&& "no LinkManager on document?");
961 const ::sfx2::SvBaseLinks
& rLinks
= pLinkManager
->GetLinks();
962 sal_uInt16 nCount
= rLinks
.size();
963 for (sal_uInt16 i
=0; i
<nCount
; i
++)
965 ::sfx2::SvBaseLink
* pBase
= rLinks
[i
].get();
966 if (auto pAreaLink
= dynamic_cast<const ScAreaLink
*>( pBase
))
968 if (nFound
== nIndex
)
974 OSL_FAIL("link not found");
978 static OUString
lcl_NoteString( const ScPostIt
& rNote
)
980 return rNote
.GetText().replace('\n', ' ');
983 void ScContentTree::GetNoteStrings()
985 if ( nRootType
!= ScContentId::ROOT
&& nRootType
!= ScContentId::NOTE
) // hidden ?
988 ScDocument
* pDoc
= GetSourceDocument();
992 // loop over cell notes
993 std::vector
<sc::NoteEntry
> aEntries
;
994 pDoc
->GetAllNoteEntries(aEntries
);
995 weld::TreeIter
* pParent
= m_aRootNodes
[ScContentId::NOTE
].get();
996 for (const auto& rEntry
: aEntries
)
998 OUString aValue
= lcl_NoteString(*rEntry
.mpNote
);
999 m_xTreeView
->insert(pParent
, -1, &aValue
, nullptr, nullptr, nullptr, false, m_xScratchIter
.get());
1000 m_xTreeView
->set_sensitive(*m_xScratchIter
, true);
1004 ScAddress
ScContentTree::GetNotePos( sal_uLong nIndex
)
1006 ScDocument
* pDoc
= GetSourceDocument();
1010 return pDoc
->GetNotePosition(nIndex
);
1013 bool ScContentTree::NoteStringsChanged()
1015 ScDocument
* pDoc
= GetSourceDocument();
1019 weld::TreeIter
* pParent
= m_aRootNodes
[ScContentId::NOTE
].get();
1023 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator(pParent
));
1024 bool bEntry
= m_xTreeView
->iter_children(*xEntry
);
1026 std::vector
<sc::NoteEntry
> aEntries
;
1027 pDoc
->GetAllNoteEntries(aEntries
);
1028 for (const auto& rEntry
: aEntries
)
1030 const ScPostIt
* pNote
= rEntry
.mpNote
;
1034 if (lcl_NoteString(*pNote
) != m_xTreeView
->get_text(*xEntry
))
1037 bEntry
= m_xTreeView
->iter_next_sibling(*xEntry
);
1043 bool ScContentTree::DrawNamesChanged( ScContentId nType
)
1045 ScDocument
* pDoc
= GetSourceDocument();
1049 weld::TreeIter
* pParent
= m_aRootNodes
[nType
].get();
1053 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator(pParent
));
1054 bool bEntry
= m_xTreeView
->iter_children(*xEntry
);
1056 // iterate in flat mode for groups
1057 SdrIterMode eIter
= ( nType
== ScContentId::DRAWING
) ? SdrIterMode::Flat
: SdrIterMode::DeepNoGroups
;
1060 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
1061 ScDocShell
* pShell
= pDoc
->GetDocumentShell();
1062 if (pDrawLayer
&& pShell
)
1064 SCTAB nTabCount
= pDoc
->GetTableCount();
1065 for (SCTAB nTab
=0; nTab
<nTabCount
&& bEqual
; nTab
++)
1067 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
1068 OSL_ENSURE(pPage
,"Page ?");
1071 SdrObjListIter
aIter( pPage
, eIter
);
1072 SdrObject
* pObject
= aIter
.Next();
1073 while (pObject
&& bEqual
)
1075 if ( IsPartOfType( nType
, pObject
->GetObjIdentifier() ) )
1081 if (ScDrawLayer::GetVisibleName(pObject
) != m_xTreeView
->get_text(*xEntry
))
1084 bEntry
= m_xTreeView
->iter_next_sibling(*xEntry
);
1087 pObject
= aIter
.Next();
1094 bEqual
= false; // anything else
1099 static bool lcl_GetRange( const ScDocument
& rDoc
, ScContentId nType
, const OUString
& rName
, ScRange
& rRange
)
1101 bool bFound
= false;
1103 if ( nType
== ScContentId::RANGENAME
)
1105 ScRangeName
* pList
= rDoc
.GetRangeName();
1108 const ScRangeData
* p
= pList
->findByUpperName(ScGlobal::getCharClass().uppercase(rName
));
1109 if (p
&& p
->IsValidReference(rRange
))
1113 else if ( nType
== ScContentId::DBAREA
)
1115 ScDBCollection
* pList
= rDoc
.GetDBCollection();
1118 const ScDBData
* p
= pList
->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(rName
));
1124 p
->GetArea(nTab
, nCol1
, nRow1
, nCol2
, nRow2
);
1125 rRange
= ScRange(nCol1
, nRow1
, nTab
, nCol2
, nRow2
, nTab
);
1134 static bool lcl_DoDragObject( ScDocShell
* pSrcShell
, std::u16string_view rName
, ScContentId nType
, weld::TreeView
& rTreeView
)
1136 bool bDisallow
= true;
1138 ScDocument
& rSrcDoc
= pSrcShell
->GetDocument();
1139 ScDrawLayer
* pModel
= rSrcDoc
.GetDrawLayer();
1142 bool bOle
= ( nType
== ScContentId::OLEOBJECT
);
1143 bool bGraf
= ( nType
== ScContentId::GRAPHIC
);
1144 SdrObjKind nDrawId
= bOle
? SdrObjKind::OLE2
: ( bGraf
? SdrObjKind::Graphic
: SdrObjKind::Group
);
1146 SdrObject
* pObject
= pModel
->GetNamedObject( rName
, nDrawId
, nTab
);
1149 SdrView
aEditView(*pModel
);
1150 aEditView
.ShowSdrPage(aEditView
.GetModel().GetPage(nTab
));
1151 SdrPageView
* pPV
= aEditView
.GetSdrPageView();
1152 aEditView
.MarkObj(pObject
, pPV
);
1154 // tdf125520 this is a D&D-start potentially with an OLE object. If
1155 // so, we need to do similar as e.g. in ScDrawView::BeginDrag so that
1156 // the temporary SdrModel for transfer does have a GetPersist() so
1157 // that the EmbeddedObjectContainer gets copied. We need no CheckOle
1158 // here, test is simpler.
1159 ScDocShellRef aDragShellRef
;
1160 if(SdrObjKind::OLE2
== pObject
->GetObjIdentifier())
1162 aDragShellRef
= new ScDocShell
; // DocShell needs a Ref immediately
1163 aDragShellRef
->DoInitNew();
1166 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef
.get());
1167 std::unique_ptr
<SdrModel
> pDragModel(aEditView
.CreateMarkedObjModel());
1168 ScDrawLayer::SetGlobalDrawPersist(nullptr);
1170 TransferableObjectDescriptor aObjDesc
;
1171 pSrcShell
->FillTransferableObjectDescriptor( aObjDesc
);
1172 aObjDesc
.maDisplayName
= pSrcShell
->GetMedium()->GetURLObject().GetURLNoPass();
1173 // maSize is set in ScDrawTransferObj ctor
1175 rtl::Reference
<ScDrawTransferObj
> pTransferObj
= new ScDrawTransferObj( std::move(pDragModel
), pSrcShell
, std::move(aObjDesc
) );
1177 pTransferObj
->SetDragSourceObj( *pObject
, nTab
);
1178 pTransferObj
->SetDragSourceFlags(ScDragSrc::Navigator
);
1180 ScModule::get()->SetDragObject(nullptr, pTransferObj
.get());
1182 rtl::Reference
<TransferDataContainer
> xHelper(pTransferObj
);
1183 rTreeView
.enable_drag_source(xHelper
, DND_ACTION_COPY
| DND_ACTION_LINK
);
1192 static bool lcl_DoDragCells( ScDocShell
* pSrcShell
, const ScRange
& rRange
, ScDragSrc nFlags
, weld::TreeView
& rTreeView
)
1194 bool bDisallow
= true;
1196 ScDocument
& rSrcDoc
= pSrcShell
->GetDocument();
1197 ScMarkData
aMark(rSrcDoc
.GetSheetLimits());
1198 aMark
.SelectTable( rRange
.aStart
.Tab(), true );
1199 aMark
.SetMarkArea( rRange
);
1201 if ( !rSrcDoc
.HasSelectedBlockMatrixFragment( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
1202 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
1205 ScDocumentUniquePtr
pClipDoc(new ScDocument( SCDOCMODE_CLIP
));
1206 ScClipParam
aClipParam(rRange
, false);
1207 rSrcDoc
.CopyToClip(aClipParam
, pClipDoc
.get(), &aMark
, false, false);
1208 // pClipDoc->ExtendMerge( rRange, sal_True );
1210 TransferableObjectDescriptor aObjDesc
;
1211 pSrcShell
->FillTransferableObjectDescriptor( aObjDesc
);
1212 aObjDesc
.maDisplayName
= pSrcShell
->GetMedium()->GetURLObject().GetURLNoPass();
1213 // maSize is set in ScTransferObj ctor
1215 rtl::Reference
<ScTransferObj
> pTransferObj
= new ScTransferObj( std::move(pClipDoc
), std::move(aObjDesc
) );
1217 pTransferObj
->SetDragSource( pSrcShell
, aMark
);
1218 pTransferObj
->SetDragSourceFlags( nFlags
);
1220 ScModule::get()->SetDragObject(pTransferObj
.get(), nullptr); // for internal D&D
1222 rtl::Reference
<TransferDataContainer
> xHelper(pTransferObj
);
1223 rTreeView
.enable_drag_source(xHelper
, DND_ACTION_COPY
| DND_ACTION_LINK
);
1231 IMPL_LINK(ScContentTree
, DragBeginHdl
, bool&, rUnsetDragIcon
, bool)
1233 rUnsetDragIcon
= true;
1235 StoreNavigatorSettings();
1237 bool bDisallow
= true;
1239 ScModule
* pScMod
= ScModule::get();
1244 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
1245 if (!m_xTreeView
->get_cursor(xEntry
.get()))
1248 GetEntryIndexes(nType
, nChild
, xEntry
.get());
1251 (nChild
!= SC_CONTENT_NOCHILD
) &&
1252 (nType
!= ScContentId::ROOT
) &&
1253 (nType
!= ScContentId::NOTE
) &&
1254 (nType
!= ScContentId::AREALINK
) )
1256 OUString
aText(m_xTreeView
->get_text(*xEntry
));
1258 ScDocument
* pLocalDoc
= nullptr; // for URL drop
1260 ScDocShell
* pDocSh
= GetManualOrCurrent();
1263 if (pDocSh
->HasName())
1264 aDocName
= pDocSh
->GetMedium()->GetName();
1266 pLocalDoc
= &pDocSh
->GetDocument(); // drop only in this document
1269 bool bDoLinkTrans
= false; // use ScLinkTransferObj
1270 OUString aLinkURL
; // for ScLinkTransferObj
1273 sal_uInt16 nDropMode
= pParentWindow
->GetDropMode();
1274 switch ( nDropMode
)
1276 case SC_DROPMODE_URL
:
1278 OUString aUrl
= aDocName
+ "#" + aText
;
1280 pScMod
->SetDragJump( pLocalDoc
, aUrl
, aText
);
1282 if (!aDocName
.isEmpty())
1284 // provide URL to outside only if the document has a name
1285 // (without name, only internal D&D via SetDragJump)
1290 bDoLinkTrans
= true;
1293 case SC_DROPMODE_LINK
:
1295 if ( !aDocName
.isEmpty() ) // link only to named documents
1297 // for internal D&D, set flag to insert a link
1301 case ScContentId::TABLE
:
1302 pScMod
->SetDragLink( aDocName
, aText
, OUString() );
1303 bDoLinkTrans
= true;
1305 case ScContentId::RANGENAME
:
1306 case ScContentId::DBAREA
:
1307 pScMod
->SetDragLink( aDocName
, OUString(), aText
);
1308 bDoLinkTrans
= true;
1311 // other types cannot be linked
1317 case SC_DROPMODE_COPY
:
1319 ScDocShell
* pSrcShell
= GetManualOrCurrent();
1322 ScDocument
& rSrcDoc
= pSrcShell
->GetDocument();
1323 if ( nType
== ScContentId::RANGENAME
|| nType
== ScContentId::DBAREA
)
1326 if ( lcl_GetRange( rSrcDoc
, nType
, aText
, aRange
) )
1328 bDisallow
= lcl_DoDragCells( pSrcShell
, aRange
, ScDragSrc::Navigator
, *m_xTreeView
);
1331 else if ( nType
== ScContentId::TABLE
)
1334 if ( rSrcDoc
.GetTable( aText
, nTab
) )
1336 ScRange
aRange(0, 0, nTab
, rSrcDoc
.MaxCol(), rSrcDoc
.MaxRow(), nTab
);
1337 bDisallow
= lcl_DoDragCells( pSrcShell
, aRange
, (ScDragSrc::Navigator
| ScDragSrc::Table
), *m_xTreeView
);
1340 else if ( nType
== ScContentId::GRAPHIC
|| nType
== ScContentId::OLEOBJECT
||
1341 nType
== ScContentId::DRAWING
)
1343 bDisallow
= lcl_DoDragObject( pSrcShell
, aText
, nType
, *m_xTreeView
);
1345 // during ExecuteDrag the navigator can be deleted
1346 // -> don't access member anymore !!!
1355 if (!aLinkURL
.isEmpty())
1356 m_xTransferObj
->SetLinkURL(aLinkURL
, aLinkText
);
1358 rtl::Reference
<TransferDataContainer
> xHelper(m_xTransferObj
);
1359 m_xTreeView
->enable_drag_source(xHelper
, DND_ACTION_COPY
| DND_ACTION_LINK
);
1368 void ScContentTree::SetRootType( ScContentId nNew
)
1370 if ( nNew
!= nRootType
)
1375 ScNavipiCfg
& rCfg
= ScModule::get()->GetNavipiCfg();
1376 rCfg
.SetRootType( nRootType
);
1380 void ScContentTree::ToggleRoot() // after selection
1382 ScContentId nNew
= ScContentId::ROOT
;
1383 if ( nRootType
== ScContentId::ROOT
)
1385 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator());
1386 if (m_xTreeView
->get_cursor(xEntry
.get()))
1388 std::unique_ptr
<weld::TreeIter
> xParent(m_xTreeView
->make_iterator(xEntry
.get()));
1389 if (!m_xTreeView
->iter_parent(*xParent
))
1392 for (sal_uInt16 i
=1; i
<=int(ScContentId::LAST
); i
++)
1394 if (!m_aRootNodes
[static_cast<ScContentId
>(i
)])
1396 if ((m_xTreeView
->iter_compare(*xEntry
, *m_aRootNodes
[static_cast<ScContentId
>(i
)]) == 0) ||
1397 (xParent
&& m_xTreeView
->iter_compare(*xParent
, *m_aRootNodes
[static_cast<ScContentId
>(i
)]) == 0))
1399 nNew
= static_cast<ScContentId
>(i
);
1405 SetRootType( nNew
);
1408 void ScContentTree::ResetManualDoc()
1415 bool ScContentTree::ActiveDocChanged()
1417 bool bRefreshed
= false;
1419 if (aManualDoc
.isEmpty())
1421 Refresh(); // content only if automatic
1425 // if flag active Listbox must be updated
1429 ScDocShell
* pSh
= GetManualOrCurrent();
1431 aCurrent
= pSh
->GetTitle();
1434 // document is no longer available
1436 aManualDoc
.clear(); // again automatically
1439 pSh
= GetManualOrCurrent(); // should be active now
1441 aCurrent
= pSh
->GetTitle();
1444 pParentWindow
->GetDocNames( &aCurrent
); // select
1449 void ScContentTree::SetManualDoc(const OUString
& rName
)
1453 pParentWindow
->GetDocNames( &aManualDoc
); // select
1456 void ScContentTree::SelectDoc(const OUString
& rName
) // rName like shown in Menu/Listbox
1458 if ( rName
== pParentWindow
->aStrActiveWin
)
1464 // omit "active" or "inactive"
1466 OUString aRealName
= rName
;
1467 sal_Int32 nLen
= rName
.getLength();
1468 sal_Int32 nActiveStart
= nLen
- pParentWindow
->aStrActive
.getLength();
1469 if ( rName
.subView( nActiveStart
) == pParentWindow
->aStrActive
)
1470 aRealName
= rName
.copy( 0, nActiveStart
);
1471 sal_Int32 nNotActiveStart
= nLen
- pParentWindow
->aStrNotActive
.getLength();
1472 if ( rName
.subView( nNotActiveStart
) == pParentWindow
->aStrNotActive
)
1473 aRealName
= rName
.copy( 0, nNotActiveStart
);
1475 bool bLoaded
= false;
1477 // Is it a normally loaded document?
1479 SfxObjectShell
* pSh
= SfxObjectShell::GetFirst();
1480 while ( pSh
&& !bLoaded
)
1482 if ( dynamic_cast<const ScDocShell
*>( pSh
) != nullptr )
1483 if ( pSh
->GetTitle() == aRealName
)
1485 pSh
= SfxObjectShell::GetNext( *pSh
);
1490 SetManualDoc(aRealName
);
1494 OSL_FAIL("SelectDoc: not found");
1498 void ScContentTree::SelectEntryByName(const ScContentId nRoot
, std::u16string_view rName
)
1500 weld::TreeIter
* pParent
= m_aRootNodes
[nRoot
].get();
1502 if (!pParent
|| !m_xTreeView
->iter_has_child(*pParent
))
1505 std::unique_ptr
<weld::TreeIter
> xEntry(m_xTreeView
->make_iterator(pParent
));
1506 bool bEntry
= m_xTreeView
->iter_children(*xEntry
);
1510 if (m_xTreeView
->get_text(*xEntry
) == rName
)
1512 m_xTreeView
->select(*xEntry
);
1513 m_xTreeView
->set_cursor(*xEntry
);
1515 // Scroll to the selected item
1516 m_xTreeView
->scroll_to_row(*xEntry
);
1518 StoreNavigatorSettings();
1522 bEntry
= m_xTreeView
->iter_next(*xEntry
);
1526 void ScContentTree::ApplyNavigatorSettings()
1528 const ScNavigatorSettings
* pSettings
= ScNavigatorDlg::GetNavigatorSettings();
1532 ScContentId nRootSel
= pSettings
->GetRootSelected();
1533 auto nChildSel
= pSettings
->GetChildSelected();
1535 // tdf#133079 ensure Sheet root is selected if nothing
1537 if (nRootSel
== ScContentId::ROOT
)
1539 nRootSel
= ScContentId::TABLE
;
1540 nChildSel
= SC_CONTENT_NOCHILD
;
1543 for( int i
= 1; i
<= int(ScContentId::LAST
); ++i
)
1545 ScContentId nEntry
= static_cast<ScContentId
>(i
);
1546 if( m_aRootNodes
[ nEntry
] )
1549 if (!m_xTreeView
->iter_has_child(*m_aRootNodes
[nEntry
]))
1550 m_xTreeView
->set_sensitive(*m_aRootNodes
[nEntry
], false);
1552 m_xTreeView
->set_sensitive(*m_aRootNodes
[nEntry
], true);
1555 bool bExp
= pSettings
->IsExpanded( nEntry
);
1556 if (bExp
!= m_xTreeView
->get_row_expanded(*m_aRootNodes
[nEntry
]))
1559 m_xTreeView
->expand_row(*m_aRootNodes
[nEntry
]);
1561 m_xTreeView
->collapse_row(*m_aRootNodes
[nEntry
]);
1565 if( nRootSel
== nEntry
)
1567 std::unique_ptr
<weld::TreeIter
> xEntry
;
1568 if (bExp
&& (nChildSel
!= SC_CONTENT_NOCHILD
))
1570 xEntry
= m_xTreeView
->make_iterator(m_aRootNodes
[nEntry
].get());
1571 if (!m_xTreeView
->iter_children(*xEntry
) || !m_xTreeView
->iter_nth_sibling(*xEntry
, nChildSel
))
1574 m_xTreeView
->select(xEntry
? *xEntry
: *m_aRootNodes
[nEntry
]);
1575 m_xTreeView
->set_cursor(xEntry
? *xEntry
: *m_aRootNodes
[nEntry
]);
1581 void ScContentTree::StoreNavigatorSettings()
1583 if (m_nAsyncMouseReleaseId
)
1585 Application::RemoveUserEvent(m_nAsyncMouseReleaseId
);
1586 m_nAsyncMouseReleaseId
= nullptr;
1589 ScNavigatorSettings
* pSettings
= ScNavigatorDlg::GetNavigatorSettings();
1593 for( int i
= 1; i
<= int(ScContentId::LAST
); ++i
)
1595 ScContentId nEntry
= static_cast<ScContentId
>(i
);
1596 bool bExp
= m_aRootNodes
[nEntry
] && m_xTreeView
->get_row_expanded(*m_aRootNodes
[nEntry
]);
1597 pSettings
->SetExpanded( nEntry
, bExp
);
1600 std::unique_ptr
<weld::TreeIter
> xCurEntry(m_xTreeView
->make_iterator());
1601 if (!m_xTreeView
->get_cursor(xCurEntry
.get()))
1606 GetEntryIndexes(nRoot
, nChild
, xCurEntry
.get());
1608 pSettings
->SetRootSelected( nRoot
);
1609 pSettings
->SetChildSelected( nChild
);
1612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */