bump product version to 6.4.0.3
[LibreOffice.git] / cui / source / dialogs / linkdlg.cxx
blobf8388ece411c501a8e9cd1425d80badfe10499c5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <linkdlg.hxx>
21 #include <vcl/svapp.hxx>
23 #include <tools/diagnose_ex.h>
24 #include <tools/debug.hxx>
25 #include <tools/urlobj.hxx>
26 #include <vcl/idle.hxx>
27 #include <vcl/timer.hxx>
28 #include <vcl/weld.hxx>
29 #include <vcl/window.hxx>
31 #include <strings.hrc>
32 #include <sfx2/linkmgr.hxx>
33 #include <sfx2/linksrc.hxx>
34 #include <sfx2/lnkbase.hxx>
35 #include <sfx2/objsh.hxx>
37 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
38 #include <com/sun/star/ui/dialogs/FolderPicker.hpp>
39 #include <comphelper/processfactory.hxx>
41 #include <dialmgr.hxx>
44 #define FILEOBJECT ( OBJECT_CLIENT_FILE & ~OBJECT_CLIENT_SO )
46 using namespace sfx2;
47 using namespace ::com::sun::star;
49 class SvBaseLinkMemberList {
50 private:
51 std::vector<SvBaseLink*> mLinks;
53 public:
54 ~SvBaseLinkMemberList()
56 for (auto const& link : mLinks)
58 if( link )
59 link->ReleaseRef();
63 size_t size() const { return mLinks.size(); }
65 SvBaseLink *operator[](size_t i) const { return mLinks[i]; }
67 void push_back(SvBaseLink* p)
69 mLinks.push_back(p);
70 p->AddFirstRef();
74 SvBaseLinksDlg::SvBaseLinksDlg(weld::Window * pParent, LinkManager* pMgr, bool bHtmlMode)
75 : GenericDialogController(pParent, "cui/ui/baselinksdialog.ui", "BaseLinksDialog")
76 , aStrAutolink( CuiResId( STR_AUTOLINK ) )
77 , aStrManuallink( CuiResId( STR_MANUALLINK ) )
78 , aStrBrokenlink( CuiResId( STR_BROKENLINK ) )
79 , aStrCloselinkmsg( CuiResId( STR_CLOSELINKMSG ) )
80 , aStrCloselinkmsgMulti( CuiResId( STR_CLOSELINKMSG_MULTI ) )
81 , aStrWaitinglink( CuiResId( STR_WAITINGLINK ) )
82 , pLinkMgr( nullptr )
83 , aUpdateIdle("cui SvBaseLinksDlg UpdateIdle")
84 , m_xTbLinks(m_xBuilder->weld_tree_view("TB_LINKS"))
85 , m_xFtFullFileName(m_xBuilder->weld_link_button("FULL_FILE_NAME"))
86 , m_xFtFullSourceName(m_xBuilder->weld_label("FULL_SOURCE_NAME"))
87 , m_xFtFullTypeName(m_xBuilder->weld_label("FULL_TYPE_NAME"))
88 , m_xRbAutomatic(m_xBuilder->weld_radio_button("AUTOMATIC"))
89 , m_xRbManual(m_xBuilder->weld_radio_button("MANUAL"))
90 , m_xPbUpdateNow(m_xBuilder->weld_button("UPDATE_NOW"))
91 , m_xPbChangeSource(m_xBuilder->weld_button("CHANGE_SOURCE"))
92 , m_xPbBreakLink(m_xBuilder->weld_button("BREAK_LINK"))
93 , m_xVirDev(VclPtr<VirtualDevice>::Create())
95 // expand the point size of the desired font to the equivalent pixel size
96 if (vcl::Window* pDefaultDevice = dynamic_cast<vcl::Window*>(Application::GetDefaultDevice()))
97 pDefaultDevice->SetPointFont(*m_xVirDev, m_xTbLinks->get_font());
98 m_xTbLinks->set_size_request(m_xTbLinks->get_approximate_digit_width() * 90,
99 m_xTbLinks->get_height_rows(12));
101 m_xTbLinks->set_selection_mode(SelectionMode::Multiple);
103 std::vector<int> aWidths;
104 aWidths.push_back(m_xTbLinks->get_approximate_digit_width() * 30);
105 aWidths.push_back(m_xTbLinks->get_approximate_digit_width() * 20);
106 aWidths.push_back(m_xTbLinks->get_approximate_digit_width() * 20);
107 m_xTbLinks->set_column_fixed_widths(aWidths);
109 // UpdateTimer for DDE-/Grf-links, which are waited for
110 aUpdateIdle.SetInvokeHandler( LINK( this, SvBaseLinksDlg, UpdateWaitingHdl ) );
111 aUpdateIdle.SetPriority( TaskPriority::LOWEST );
113 m_xTbLinks->connect_changed( LINK( this, SvBaseLinksDlg, LinksSelectHdl ) );
114 m_xTbLinks->connect_row_activated( LINK( this, SvBaseLinksDlg, LinksDoubleClickHdl ) );
115 m_xRbAutomatic->connect_clicked( LINK( this, SvBaseLinksDlg, AutomaticClickHdl ) );
116 m_xRbManual->connect_clicked( LINK( this, SvBaseLinksDlg, ManualClickHdl ) );
117 m_xPbUpdateNow->connect_clicked( LINK( this, SvBaseLinksDlg, UpdateNowClickHdl ) );
118 m_xPbChangeSource->connect_clicked( LINK( this, SvBaseLinksDlg, ChangeSourceClickHdl ) );
119 if(!bHtmlMode)
120 m_xPbBreakLink->connect_clicked( LINK( this, SvBaseLinksDlg, BreakLinkClickHdl ) );
121 else
122 m_xPbBreakLink->hide();
124 SetManager( pMgr );
127 SvBaseLinksDlg::~SvBaseLinksDlg()
131 /*************************************************************************
132 |* SvBaseLinksDlg::Handler()
133 *************************************************************************/
134 IMPL_LINK(SvBaseLinksDlg, LinksSelectHdl, weld::TreeView&, rTreeView, void)
136 LinksSelectHdl(&rTreeView);
139 void SvBaseLinksDlg::LinksSelectHdl(weld::TreeView* pSvTabListBox)
141 const int nSelectionCount = pSvTabListBox ?
142 pSvTabListBox->count_selected_rows() : 0;
143 if (nSelectionCount > 1)
145 // possibly deselect old entries in case of multi-selection
146 int nSelEntry = pSvTabListBox->get_selected_index();
147 SvBaseLink* pLink = reinterpret_cast<SvBaseLink*>(pSvTabListBox->get_id(nSelEntry).toInt64());
148 sal_uInt16 nObjectType = pLink->GetObjType();
149 if((OBJECT_CLIENT_FILE & nObjectType) != OBJECT_CLIENT_FILE)
151 pSvTabListBox->unselect_all();
152 pSvTabListBox->select(nSelEntry);
154 else
156 std::vector<int> aRows = pSvTabListBox->get_selected_rows();
157 for (auto nEntry : aRows)
159 pLink = reinterpret_cast<SvBaseLink*>(pSvTabListBox->get_id(nEntry).toInt64());
160 DBG_ASSERT(pLink, "Where is the Link?");
161 if (!pLink)
162 continue;
163 if( (OBJECT_CLIENT_FILE & pLink->GetObjType()) != OBJECT_CLIENT_FILE )
164 pSvTabListBox->unselect(nEntry);
168 m_xPbUpdateNow->set_sensitive(true);
169 m_xRbAutomatic->set_sensitive(false);
170 m_xRbManual->set_active(true);
171 m_xRbManual->set_sensitive(false);
173 else
175 int nPos;
176 SvBaseLink* pLink = GetSelEntry( &nPos );
177 if( !pLink )
178 return;
180 m_xPbUpdateNow->set_sensitive(true);
182 OUString sType, sLink;
183 OUString *pLinkNm = &sLink, *pFilter = nullptr;
185 if( FILEOBJECT & pLink->GetObjType() )
187 m_xRbAutomatic->set_sensitive(false);
188 m_xRbManual->set_active(true);
189 m_xRbManual->set_sensitive(false);
190 if( OBJECT_CLIENT_GRF == pLink->GetObjType() )
192 pLinkNm = nullptr;
193 pFilter = &sLink;
196 else
198 m_xRbAutomatic->set_sensitive(true);
199 m_xRbManual->set_sensitive(true);
201 if( SfxLinkUpdateMode::ALWAYS == pLink->GetUpdateMode() )
202 m_xRbAutomatic->set_active(true);
203 else
204 m_xRbManual->set_active(true);
207 OUString aFileName;
208 sfx2::LinkManager::GetDisplayNames( pLink, &sType, &aFileName, pLinkNm, pFilter );
209 aFileName = INetURLObject::decode(aFileName, INetURLObject::DecodeMechanism::Unambiguous);
210 m_xFtFullFileName->set_label( aFileName );
211 m_xFtFullFileName->set_uri( aFileName );
212 m_xFtFullSourceName->set_label( sLink );
213 m_xFtFullTypeName->set_label( sType );
217 IMPL_LINK_NOARG( SvBaseLinksDlg, LinksDoubleClickHdl, weld::TreeView&, bool )
219 ChangeSourceClickHdl(*m_xPbChangeSource);
220 return true;
223 IMPL_LINK_NOARG( SvBaseLinksDlg, AutomaticClickHdl, weld::Button&, void )
225 int nPos;
226 SvBaseLink* pLink = GetSelEntry( &nPos );
227 if( pLink && !( FILEOBJECT & pLink->GetObjType() ) &&
228 SfxLinkUpdateMode::ALWAYS != pLink->GetUpdateMode() )
229 SetType( *pLink, nPos, SfxLinkUpdateMode::ALWAYS );
232 IMPL_LINK_NOARG( SvBaseLinksDlg, ManualClickHdl, weld::Button&, void )
234 int nPos;
235 SvBaseLink* pLink = GetSelEntry( &nPos );
236 if( pLink && !( FILEOBJECT & pLink->GetObjType() ) &&
237 SfxLinkUpdateMode::ONCALL != pLink->GetUpdateMode())
238 SetType( *pLink, nPos, SfxLinkUpdateMode::ONCALL );
241 IMPL_LINK_NOARG(SvBaseLinksDlg, UpdateNowClickHdl, weld::Button&, void)
243 std::vector< SvBaseLink* > aLnkArr;
244 std::vector< sal_Int16 > aPosArr;
246 std::vector<int> aRows = m_xTbLinks->get_selected_rows();
247 for (int nFndPos : aRows)
249 aLnkArr.push_back( reinterpret_cast<SvBaseLink*>( m_xTbLinks->get_id(nFndPos).toInt64() ) );
250 aPosArr.push_back( nFndPos );
253 if( !aLnkArr.empty() )
255 for( size_t n = 0; n < aLnkArr.size(); ++n )
257 tools::SvRef<SvBaseLink> xLink = aLnkArr[ n ];
259 // first look for the entry in the array
260 for(const auto & i : pLinkMgr->GetLinks())
261 if( xLink == i )
263 SetType( *xLink, aPosArr[ n ], xLink->GetUpdateMode() );
264 break;
268 // if somebody is of the opinion to swap his links (SD)
269 LinkManager* pNewMgr = pLinkMgr;
270 pLinkMgr = nullptr;
271 SetManager( pNewMgr );
274 OUString sId = OUString::number(reinterpret_cast<sal_Int64>(aLnkArr[0]));
275 int nE = m_xTbLinks->find_id(sId);
276 if (nE == -1)
277 nE = m_xTbLinks->get_selected_index();
278 int nSelEntry = m_xTbLinks->get_selected_index();
279 if (nE != nSelEntry)
280 m_xTbLinks->unselect(nSelEntry);
281 m_xTbLinks->select(nE);
282 m_xTbLinks->scroll_to_row(nE);
284 pNewMgr->CloseCachedComps();
288 IMPL_LINK_NOARG(SvBaseLinksDlg, ChangeSourceClickHdl, weld::Button&, void)
290 std::vector<int> aRows = m_xTbLinks->get_selected_rows();
291 if (aRows.size() > 1)
295 uno::Reference<ui::dialogs::XFolderPicker2> xFolderPicker = ui::dialogs::FolderPicker::create(comphelper::getProcessComponentContext());
297 OUString sType, sFile, sLinkName;
298 OUString sFilter;
299 SvBaseLink* pLink = reinterpret_cast<SvBaseLink*>(m_xTbLinks->get_id(aRows[0]).toInt64());
300 sfx2::LinkManager::GetDisplayNames( pLink, &sType, &sFile );
301 INetURLObject aUrl(sFile);
302 if(aUrl.GetProtocol() == INetProtocol::File)
304 OUString sOldPath(aUrl.PathToFileName());
305 sal_Int32 nLen = aUrl.GetLastName().getLength();
306 sOldPath = sOldPath.copy(0, sOldPath.getLength() - nLen);
307 xFolderPicker->setDisplayDirectory(sOldPath);
309 if (xFolderPicker->execute() == ui::dialogs::ExecutableDialogResults::OK)
311 OUString aPath = xFolderPicker->getDirectory();
313 for (auto nRow : aRows)
315 pLink = reinterpret_cast<SvBaseLink*>(m_xTbLinks->get_id(nRow).toInt64());
316 DBG_ASSERT(pLink,"Where is the link?");
317 if (!pLink)
318 continue;
319 sfx2::LinkManager::GetDisplayNames( pLink, &sType, &sFile, &sLinkName, &sFilter );
320 INetURLObject aUrl_(sFile);
321 INetURLObject aUrl2(aPath, INetProtocol::File);
322 aUrl2.insertName( aUrl_.getName() );
323 OUString sNewLinkName;
324 MakeLnkName( sNewLinkName, nullptr ,
325 aUrl2.GetMainURL(INetURLObject::DecodeMechanism::ToIUri), sLinkName, &sFilter);
326 pLink->SetLinkSourceName( sNewLinkName );
327 pLink->Update();
329 if( pLinkMgr->GetPersist() )
330 pLinkMgr->GetPersist()->SetModified();
331 LinkManager* pNewMgr = pLinkMgr;
332 pLinkMgr = nullptr;
333 SetManager( pNewMgr );
336 catch (const uno::Exception &)
338 TOOLS_WARN_EXCEPTION("cui.dialogs", "SvBaseLinksDlg");
341 else
343 int nPos;
344 SvBaseLink* pLink = GetSelEntry( &nPos );
345 if ( pLink && !pLink->GetLinkSourceName().isEmpty() )
346 pLink->Edit(m_xDialog.get(), LINK(this, SvBaseLinksDlg, EndEditHdl));
350 IMPL_LINK_NOARG( SvBaseLinksDlg, BreakLinkClickHdl, weld::Button&, void )
352 bool bModified = false;
353 if (m_xTbLinks->count_selected_rows() <= 1)
355 int nPos;
356 tools::SvRef<SvBaseLink> xLink = GetSelEntry( &nPos );
357 if( !xLink.is() )
358 return;
360 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
361 VclMessageType::Question, VclButtonsType::YesNo,
362 aStrCloselinkmsg));
363 xQueryBox->set_default_response(RET_YES);
365 if (RET_YES == xQueryBox->run())
367 m_xTbLinks->remove(nPos);
369 // close object, if it's still existing
370 bool bNewLnkMgr = OBJECT_CLIENT_FILE == xLink->GetObjType();
372 // tell the link that it will be resolved!
373 xLink->Closed();
375 // if somebody has forgotten to deregister himself
376 if( xLink.is() )
377 pLinkMgr->Remove( xLink.get() );
379 if( bNewLnkMgr )
381 LinkManager* pNewMgr = pLinkMgr;
382 pLinkMgr = nullptr;
383 SetManager( pNewMgr );
384 m_xTbLinks->set_cursor(nPos ? --nPos : 0);
386 bModified = true;
389 else
391 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
392 VclMessageType::Question, VclButtonsType::YesNo,
393 aStrCloselinkmsgMulti));
394 xQueryBox->set_default_response(RET_YES);
396 if (RET_YES == xQueryBox->run())
398 std::vector<int> aRows = m_xTbLinks->get_selected_rows();
399 SvBaseLinkMemberList aLinkList;
400 for (auto nRow : aRows)
402 SvBaseLink* pLink = reinterpret_cast<SvBaseLink*>(m_xTbLinks->get_id(nRow).toInt64());
403 if (pLink)
404 aLinkList.push_back(pLink);
406 std::sort(aRows.begin(), aRows.end());
407 for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
408 m_xTbLinks->remove(*it);
409 for (size_t i = 0; i < aLinkList.size(); ++i)
411 tools::SvRef<SvBaseLink> xLink = aLinkList[i];
412 // tell the link that it will be resolved!
413 xLink->Closed();
415 // if somebody has forgotten to deregister himself
416 pLinkMgr->Remove( xLink.get() );
417 bModified = true;
419 // then remove all selected entries
422 if(bModified)
424 if (!m_xTbLinks->n_children())
426 m_xRbAutomatic->set_sensitive(false);
427 m_xRbManual->set_sensitive(false);
428 m_xPbUpdateNow->set_sensitive(false);
429 m_xPbChangeSource->set_sensitive(false);
430 m_xPbBreakLink->set_sensitive(false);
432 m_xFtFullSourceName->set_label( "" );
433 m_xFtFullTypeName->set_label( "" );
435 if( pLinkMgr && pLinkMgr->GetPersist() )
436 pLinkMgr->GetPersist()->SetModified();
440 IMPL_LINK_NOARG( SvBaseLinksDlg, UpdateWaitingHdl, Timer*, void )
442 m_xTbLinks->freeze();
443 for (int nPos = m_xTbLinks->n_children(); nPos; --nPos)
445 tools::SvRef<SvBaseLink> xLink( reinterpret_cast<SvBaseLink*>(m_xTbLinks->get_id(nPos).toInt64()) );
446 if( xLink.is() )
448 OUString sCur( ImplGetStateStr( *xLink ) ),
449 sOld( m_xTbLinks->get_text(nPos, 3) );
450 if( sCur != sOld )
451 m_xTbLinks->set_text(nPos, sCur, 3);
454 m_xTbLinks->thaw();
457 IMPL_LINK( SvBaseLinksDlg, EndEditHdl, sfx2::SvBaseLink&, _rLink, void )
459 int nPos;
460 GetSelEntry( &nPos );
462 if( _rLink.WasLastEditOK() )
464 // StarImpress/Draw swap the LinkObjects themselves!
465 // So search for the link in the manager; if it does not exist
466 // anymore, fill the list completely new. Otherwise only the
467 // edited link needs to be refreshed.
468 bool bLinkFnd = false;
469 for( size_t n = pLinkMgr->GetLinks().size(); n; )
470 if( &_rLink == &(*pLinkMgr->GetLinks()[ --n ]) )
472 bLinkFnd = true;
473 break;
476 if( bLinkFnd )
478 m_xTbLinks->remove(nPos);
479 int nToUnselect = m_xTbLinks->get_selected_index();
480 InsertEntry(_rLink, nPos, true);
481 if (nToUnselect != -1)
482 m_xTbLinks->unselect(nToUnselect);
484 else
486 LinkManager* pNewMgr = pLinkMgr;
487 pLinkMgr = nullptr;
488 SetManager( pNewMgr );
490 if (pLinkMgr && pLinkMgr->GetPersist())
491 pLinkMgr->GetPersist()->SetModified();
495 OUString SvBaseLinksDlg::ImplGetStateStr( const SvBaseLink& rLnk )
497 OUString sRet;
498 if( !rLnk.GetObj() )
499 sRet = aStrBrokenlink;
500 else if( rLnk.GetObj()->IsPending() )
502 sRet = aStrWaitinglink;
503 aUpdateIdle.Start();
505 else if( SfxLinkUpdateMode::ALWAYS == rLnk.GetUpdateMode() )
506 sRet = aStrAutolink;
507 else
508 sRet = aStrManuallink;
510 return sRet;
513 void SvBaseLinksDlg::SetManager( LinkManager* pNewMgr )
515 if( pLinkMgr == pNewMgr )
516 return;
518 if (pNewMgr)
520 // update has to be stopped before clear
521 m_xTbLinks->freeze();
524 m_xTbLinks->clear();
525 pLinkMgr = pNewMgr;
527 if( pLinkMgr )
529 SvBaseLinks& rLnks = const_cast<SvBaseLinks&>(pLinkMgr->GetLinks());
530 for( size_t n = 0; n < rLnks.size(); ++n )
532 tools::SvRef<SvBaseLink>& rLinkRef = rLnks[ n ];
533 if( !rLinkRef.is() )
535 rLnks.erase( rLnks.begin() + n );
536 --n;
537 continue;
539 if( rLinkRef->IsVisible() )
540 InsertEntry( *rLinkRef );
543 m_xTbLinks->thaw();
545 if( !rLnks.empty() )
547 m_xTbLinks->set_cursor(0);
548 m_xTbLinks->select(0);
549 LinksSelectHdl( nullptr );
554 void SvBaseLinksDlg::InsertEntry(const SvBaseLink& rLink, int nPos, bool bSelect)
556 OUString sFileNm, sLinkNm, sTypeNm, sFilter;
558 sfx2::LinkManager::GetDisplayNames( &rLink, &sTypeNm, &sFileNm, &sLinkNm, &sFilter );
560 auto nWidthPixel = m_xTbLinks->get_column_width(0);
561 OUString aTxt = m_xVirDev->GetEllipsisString(sFileNm, nWidthPixel, DrawTextFlags::PathEllipsis);
562 INetURLObject aPath( sFileNm, INetProtocol::File );
563 OUString aFileName = aPath.getName(
564 INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous);
566 if( aFileName.getLength() > aTxt.getLength() )
567 aTxt = aFileName;
568 else if (!aFileName.isEmpty() && aTxt.indexOf(aFileName, aTxt.getLength() - aFileName.getLength()) == -1)
569 // filename not in string
570 aTxt = aFileName;
572 if (nPos == -1)
573 nPos = m_xTbLinks->n_children();
574 m_xTbLinks->insert(nPos);
575 m_xTbLinks->set_text(nPos, aTxt, 0);
576 m_xTbLinks->set_id(nPos, OUString::number(reinterpret_cast<sal_Int64>(&rLink)));
577 if( OBJECT_CLIENT_GRF == rLink.GetObjType() )
578 m_xTbLinks->set_text(nPos, sFilter, 1);
579 else
580 m_xTbLinks->set_text(nPos, sLinkNm, 1);
581 m_xTbLinks->set_text(nPos, sTypeNm, 2);
582 m_xTbLinks->set_text(nPos, ImplGetStateStr(rLink), 3);
583 if (bSelect)
584 m_xTbLinks->select(nPos);
587 SvBaseLink* SvBaseLinksDlg::GetSelEntry(int* pPos)
589 int nPos = m_xTbLinks->get_selected_index();
590 if (nPos != -1)
592 if (pPos)
593 *pPos = nPos;
594 return reinterpret_cast<SvBaseLink*>(m_xTbLinks->get_id(nPos).toInt64());
596 return nullptr;
599 void SvBaseLinksDlg::SetType(SvBaseLink& rLink,
600 int nSelPos,
601 SfxLinkUpdateMode nType)
603 rLink.SetUpdateMode( nType );
604 rLink.Update();
605 m_xTbLinks->set_text(nSelPos, ImplGetStateStr(rLink), 3);
606 if (pLinkMgr->GetPersist())
607 pLinkMgr->GetPersist()->SetModified();
610 void SvBaseLinksDlg::SetActLink( SvBaseLink const * pLink )
612 if( pLinkMgr )
614 const SvBaseLinks& rLnks = pLinkMgr->GetLinks();
615 int nSelect = 0;
616 for(const auto & rLinkRef : rLnks)
618 // #109573# only visible links have been inserted into the TreeListBox,
619 // invisible ones have to be skipped here
620 if( rLinkRef->IsVisible() )
622 if( pLink == rLinkRef.get() )
624 m_xTbLinks->select(nSelect);
625 LinksSelectHdl( nullptr );
626 return ;
628 ++nSelect;
634 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */