xref: /core/cui/source/dialogs/linkdlg.cxx (revision ecf6f6f2)
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 <linkdlg.hxx>
21 #include <o3tl/safeint.hxx>
22 #include <vcl/svapp.hxx>
23 
24 #include <comphelper/diagnose_ex.hxx>
25 #include <tools/debug.hxx>
26 #include <tools/urlobj.hxx>
27 #include <vcl/idle.hxx>
28 #include <vcl/timer.hxx>
29 #include <vcl/weld.hxx>
30 #include <vcl/weldutils.hxx>
31 
32 #include <strings.hrc>
33 #include <sfx2/filedlghelper.hxx>
34 #include <sfx2/linkmgr.hxx>
35 #include <sfx2/linksrc.hxx>
36 #include <sfx2/lnkbase.hxx>
37 #include <sfx2/objsh.hxx>
38 
39 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
40 #include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
41 #include <comphelper/processfactory.hxx>
42 
43 #include <dialmgr.hxx>
44 
45 
46 using namespace sfx2;
47 using namespace ::com::sun::star;
48 
49 namespace {
50 
51 class SvBaseLinkMemberList {
52 private:
53     std::vector<SvBaseLink*> mLinks;
54 
55 public:
~SvBaseLinkMemberList()56     ~SvBaseLinkMemberList()
57     {
58         for (auto const& link : mLinks)
59         {
60             if( link )
61                 link->ReleaseRef();
62         }
63     }
64 
size() const65     size_t size() const { return mLinks.size(); }
66 
operator [](size_t i) const67     SvBaseLink *operator[](size_t i) const { return mLinks[i]; }
68 
push_back(SvBaseLink * p)69     void push_back(SvBaseLink* p)
70     {
71         mLinks.push_back(p);
72         p->AddFirstRef();
73     }
74 };
75 
76 }
77 
SvBaseLinksDlg(weld::Window * pParent,LinkManager * pMgr,bool bHtmlMode)78 SvBaseLinksDlg::SvBaseLinksDlg(weld::Window * pParent, LinkManager* pMgr, bool bHtmlMode)
79     : GenericDialogController(pParent, u"cui/ui/baselinksdialog.ui"_ustr, u"BaseLinksDialog"_ustr)
80     , aStrAutolink( CuiResId( STR_AUTOLINK ) )
81     , aStrManuallink( CuiResId( STR_MANUALLINK ) )
82     , aStrBrokenlink( CuiResId( STR_BROKENLINK ) )
83     , aStrCloselinkmsg( CuiResId( STR_CLOSELINKMSG ) )
84     , aStrCloselinkmsgMulti( CuiResId( STR_CLOSELINKMSG_MULTI ) )
85     , aStrWaitinglink( CuiResId( STR_WAITINGLINK ) )
86     , pLinkMgr( nullptr )
87     , aUpdateIdle("cui SvBaseLinksDlg UpdateIdle")
88     , m_xTbLinks(m_xBuilder->weld_tree_view(u"TB_LINKS"_ustr))
89     , m_xFtFullFileName(m_xBuilder->weld_link_button(u"FULL_FILE_NAME"_ustr))
90     , m_xFtFullSourceName(m_xBuilder->weld_label(u"FULL_SOURCE_NAME"_ustr))
91     , m_xFtFullTypeName(m_xBuilder->weld_label(u"FULL_TYPE_NAME"_ustr))
92     , m_xRbAutomatic(m_xBuilder->weld_radio_button(u"AUTOMATIC"_ustr))
93     , m_xRbManual(m_xBuilder->weld_radio_button(u"MANUAL"_ustr))
94     , m_xPbUpdateNow(m_xBuilder->weld_button(u"UPDATE_NOW"_ustr))
95     , m_xPbChangeSource(m_xBuilder->weld_button(u"CHANGE_SOURCE"_ustr))
96     , m_xPbBreakLink(m_xBuilder->weld_button(u"BREAK_LINK"_ustr))
97     , m_xVirDev(VclPtr<VirtualDevice>::Create())
98 {
99     // expand the point size of the desired font to the equivalent pixel size
100     weld::SetPointFont(*m_xVirDev, m_xTbLinks->get_font());
101     m_xTbLinks->set_size_request(m_xTbLinks->get_approximate_digit_width() * 90,
102                                  m_xTbLinks->get_height_rows(12));
103 
104     m_xTbLinks->set_selection_mode(SelectionMode::Multiple);
105 
106     std::vector<int> aWidths
107     {
108         o3tl::narrowing<int>(m_xTbLinks->get_approximate_digit_width() * 30),
109         o3tl::narrowing<int>(m_xTbLinks->get_approximate_digit_width() * 20),
110         o3tl::narrowing<int>(m_xTbLinks->get_approximate_digit_width() * 20)
111     };
112     m_xTbLinks->set_column_fixed_widths(aWidths);
113 
114     // UpdateTimer for DDE-/Grf-links, which are waited for
115     aUpdateIdle.SetInvokeHandler( LINK( this, SvBaseLinksDlg, UpdateWaitingHdl ) );
116     aUpdateIdle.SetPriority( TaskPriority::LOWEST );
117 
118     m_xTbLinks->connect_changed( LINK( this, SvBaseLinksDlg, LinksSelectHdl ) );
119     m_xTbLinks->connect_row_activated( LINK( this, SvBaseLinksDlg, LinksDoubleClickHdl ) );
120     m_xRbAutomatic->connect_toggled( LINK( this, SvBaseLinksDlg, ToggleHdl ) );
121     m_xRbManual->connect_toggled( LINK( this, SvBaseLinksDlg, ToggleHdl ) );
122     m_xPbUpdateNow->connect_clicked( LINK( this, SvBaseLinksDlg, UpdateNowClickHdl ) );
123     m_xPbChangeSource->connect_clicked( LINK( this, SvBaseLinksDlg, ChangeSourceClickHdl ) );
124     if(!bHtmlMode)
125         m_xPbBreakLink->connect_clicked( LINK( this, SvBaseLinksDlg, BreakLinkClickHdl ) );
126     else
127         m_xPbBreakLink->hide();
128 
129     SetManager( pMgr );
130 }
131 
~SvBaseLinksDlg()132 SvBaseLinksDlg::~SvBaseLinksDlg()
133 {
134 }
135 
136 /*************************************************************************
137 |*    SvBaseLinksDlg::Handler()
138 *************************************************************************/
IMPL_LINK(SvBaseLinksDlg,LinksSelectHdl,weld::TreeView &,rTreeView,void)139 IMPL_LINK(SvBaseLinksDlg, LinksSelectHdl, weld::TreeView&, rTreeView, void)
140 {
141     LinksSelectHdl(&rTreeView);
142 }
143 
LinksSelectHdl(weld::TreeView * pSvTabListBox)144 void SvBaseLinksDlg::LinksSelectHdl(weld::TreeView* pSvTabListBox)
145 {
146     const int nSelectionCount = pSvTabListBox ?
147         pSvTabListBox->count_selected_rows() : 0;
148     if (nSelectionCount > 1)
149     {
150         // possibly deselect old entries in case of multi-selection
151         int nSelEntry = pSvTabListBox->get_selected_index();
152         SvBaseLink* pLink = weld::fromId<SvBaseLink*>(pSvTabListBox->get_id(nSelEntry));
153         SvBaseLinkObjectType nObjectType = pLink->GetObjType();
154         if(!isClientFileType(nObjectType))
155         {
156             pSvTabListBox->unselect_all();
157             pSvTabListBox->select(nSelEntry);
158         }
159         else
160         {
161             std::vector<int> aRows = pSvTabListBox->get_selected_rows();
162             for (auto nEntry : aRows)
163             {
164                 pLink = weld::fromId<SvBaseLink*>(pSvTabListBox->get_id(nEntry));
165                 DBG_ASSERT(pLink, "Where is the Link?");
166                 if (!pLink)
167                     continue;
168                 if( !isClientFileType(pLink->GetObjType()) )
169                     pSvTabListBox->unselect(nEntry);
170             }
171         }
172 
173         m_xPbUpdateNow->set_sensitive(true);
174         m_xRbAutomatic->set_sensitive(false);
175         m_xRbManual->set_active(true);
176         m_xRbManual->set_sensitive(false);
177     }
178     else
179     {
180         int nPos;
181         SvBaseLink* pLink = GetSelEntry( &nPos );
182         if( !pLink )
183             return;
184 
185         m_xPbUpdateNow->set_sensitive(true);
186 
187         OUString sType, sLink;
188         OUString *pLinkNm = &sLink, *pFilter = nullptr;
189 
190         if( isClientFileType(pLink->GetObjType()) )
191         {
192             m_xRbAutomatic->set_sensitive(false);
193             m_xRbManual->set_active(true);
194             m_xRbManual->set_sensitive(false);
195             if( SvBaseLinkObjectType::ClientGraphic == pLink->GetObjType() )
196             {
197                 pLinkNm = nullptr;
198                 pFilter = &sLink;
199             }
200         }
201         else
202         {
203             m_xRbAutomatic->set_sensitive(true);
204             m_xRbManual->set_sensitive(true);
205 
206             if( SfxLinkUpdateMode::ALWAYS == pLink->GetUpdateMode() )
207                 m_xRbAutomatic->set_active(true);
208             else
209                 m_xRbManual->set_active(true);
210         }
211 
212         OUString aFileName;
213         sfx2::LinkManager::GetDisplayNames( pLink, &sType, &aFileName, pLinkNm, pFilter );
214         aFileName = INetURLObject::decode(aFileName, INetURLObject::DecodeMechanism::Unambiguous);
215         m_xFtFullFileName->set_label( aFileName );
216         m_xFtFullFileName->set_uri( aFileName );
217         m_xFtFullSourceName->set_label( sLink );
218         m_xFtFullTypeName->set_label( sType );
219     }
220 }
221 
IMPL_LINK_NOARG(SvBaseLinksDlg,LinksDoubleClickHdl,weld::TreeView &,bool)222 IMPL_LINK_NOARG( SvBaseLinksDlg, LinksDoubleClickHdl, weld::TreeView&, bool )
223 {
224     ChangeSourceClickHdl(*m_xPbChangeSource);
225     return true;
226 }
227 
IMPL_LINK(SvBaseLinksDlg,ToggleHdl,weld::Toggleable &,rButton,void)228 IMPL_LINK(SvBaseLinksDlg, ToggleHdl, weld::Toggleable&, rButton, void)
229 {
230     if (!rButton.get_active())
231         return;
232 
233     int nPos;
234     SvBaseLink* pLink = GetSelEntry( &nPos );
235 
236     if (m_xRbAutomatic->get_active())
237     {
238         if( pLink && !isClientFileType( pLink->GetObjType() ) &&
239             SfxLinkUpdateMode::ALWAYS != pLink->GetUpdateMode() )
240             SetType( *pLink, nPos, SfxLinkUpdateMode::ALWAYS );
241     }
242     else
243     {
244         if( pLink && !isClientFileType( pLink->GetObjType() ) &&
245             SfxLinkUpdateMode::ONCALL != pLink->GetUpdateMode())
246             SetType( *pLink, nPos, SfxLinkUpdateMode::ONCALL );
247     }
248 }
249 
IMPL_LINK_NOARG(SvBaseLinksDlg,UpdateNowClickHdl,weld::Button &,void)250 IMPL_LINK_NOARG(SvBaseLinksDlg, UpdateNowClickHdl, weld::Button&, void)
251 {
252     std::vector< SvBaseLink* > aLnkArr;
253     std::vector< sal_Int16 > aPosArr;
254 
255     std::vector<int> aRows = m_xTbLinks->get_selected_rows();
256     for (int nFndPos : aRows)
257     {
258         aLnkArr.push_back( weld::fromId<SvBaseLink*>( m_xTbLinks->get_id(nFndPos) ) );
259         aPosArr.push_back( nFndPos );
260     }
261 
262     if( aLnkArr.empty() )
263         return;
264 
265     for( size_t n = 0; n < aLnkArr.size(); ++n )
266     {
267         tools::SvRef<SvBaseLink> xLink = aLnkArr[ n ];
268 
269         // first look for the entry in the array
270         for(const auto & i : pLinkMgr->GetLinks())
271             if( xLink == i )
272             {
273                 SetType( *xLink, aPosArr[ n ], xLink->GetUpdateMode() );
274                 break;
275             }
276     }
277 
278     // if somebody is of the opinion to swap his links (SD)
279     LinkManager* pNewMgr = pLinkMgr;
280     pLinkMgr = nullptr;
281     SetManager( pNewMgr );
282 
283 
284     OUString sId = weld::toId(aLnkArr[0]);
285     int nE = m_xTbLinks->find_id(sId);
286     if (nE == -1)
287         nE = m_xTbLinks->get_selected_index();
288     int nSelEntry = m_xTbLinks->get_selected_index();
289     if (nE != nSelEntry)
290         m_xTbLinks->unselect(nSelEntry);
291     m_xTbLinks->select(nE);
292     m_xTbLinks->scroll_to_row(nE);
293 
294     pNewMgr->CloseCachedComps();
295 }
296 
IMPL_LINK_NOARG(SvBaseLinksDlg,ChangeSourceClickHdl,weld::Button &,void)297 IMPL_LINK_NOARG(SvBaseLinksDlg, ChangeSourceClickHdl, weld::Button&, void)
298 {
299     std::vector<int> aRows = m_xTbLinks->get_selected_rows();
300     if (aRows.size() > 1)
301     {
302         try
303         {
304             uno::Reference<ui::dialogs::XFolderPicker2> xFolderPicker = sfx2::createFolderPicker(
305                     comphelper::getProcessComponentContext(), m_xDialog.get());
306 
307             OUString sType, sFile, sLinkName;
308             OUString sFilter;
309             SvBaseLink* pLink = weld::fromId<SvBaseLink*>(m_xTbLinks->get_id(aRows[0]));
310             sfx2::LinkManager::GetDisplayNames( pLink, &sType, &sFile );
311             INetURLObject aUrl(sFile);
312             if(aUrl.GetProtocol() == INetProtocol::File)
313             {
314                 OUString sOldPath(aUrl.PathToFileName());
315                 sal_Int32 nLen = aUrl.GetLastName().getLength();
316                 sOldPath = sOldPath.copy(0, sOldPath.getLength() - nLen);
317                 xFolderPicker->setDisplayDirectory(sOldPath);
318             }
319             if (xFolderPicker->execute() == ui::dialogs::ExecutableDialogResults::OK)
320             {
321                 OUString aPath = xFolderPicker->getDirectory();
322 
323                 for (auto nRow : aRows)
324                 {
325                     pLink = weld::fromId<SvBaseLink*>(m_xTbLinks->get_id(nRow));
326                     DBG_ASSERT(pLink,"Where is the link?");
327                     if (!pLink)
328                         continue;
329                     sfx2::LinkManager::GetDisplayNames( pLink, &sType, &sFile, &sLinkName, &sFilter );
330                     INetURLObject aUrl_(sFile);
331                     INetURLObject aUrl2(aPath, INetProtocol::File);
332                     aUrl2.insertName( aUrl_.getName() );
333                     OUString sNewLinkName;
334                     MakeLnkName( sNewLinkName, nullptr ,
335                             aUrl2.GetMainURL(INetURLObject::DecodeMechanism::ToIUri), sLinkName, &sFilter);
336                     pLink->SetLinkSourceName( sNewLinkName );
337                     pLink->Update();
338                 }
339                 if( pLinkMgr->GetPersist() )
340                     pLinkMgr->GetPersist()->SetModified();
341                 LinkManager* pNewMgr = pLinkMgr;
342                 pLinkMgr = nullptr;
343                 SetManager( pNewMgr );
344             }
345         }
346         catch (const uno::Exception &)
347         {
348             TOOLS_WARN_EXCEPTION("cui.dialogs", "SvBaseLinksDlg");
349         }
350     }
351     else
352     {
353         int nPos;
354         SvBaseLink* pLink = GetSelEntry( &nPos );
355         if ( pLink && !pLink->GetLinkSourceName().isEmpty() )
356             pLink->Edit(m_xDialog.get(), LINK(this, SvBaseLinksDlg, EndEditHdl));
357     }
358 }
359 
IMPL_LINK_NOARG(SvBaseLinksDlg,BreakLinkClickHdl,weld::Button &,void)360 IMPL_LINK_NOARG( SvBaseLinksDlg, BreakLinkClickHdl, weld::Button&, void )
361 {
362     bool bModified = false;
363     if (m_xTbLinks->count_selected_rows() <= 1)
364     {
365         int nPos;
366         tools::SvRef<SvBaseLink> xLink = GetSelEntry( &nPos );
367         if( !xLink.is() )
368             return;
369 
370         std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
371                                                        VclMessageType::Question, VclButtonsType::YesNo,
372                                                        aStrCloselinkmsg));
373         xQueryBox->set_default_response(RET_YES);
374 
375         if (RET_YES == xQueryBox->run())
376         {
377             m_xTbLinks->remove(nPos);
378 
379             // close object, if it's still existing
380             bool bNewLnkMgr = SvBaseLinkObjectType::ClientFile == xLink->GetObjType();
381 
382             // tell the link that it will be resolved!
383             xLink->Closed();
384 
385             // if somebody has forgotten to deregister himself
386             if( xLink.is() )
387                 pLinkMgr->Remove( xLink.get() );
388 
389             if( bNewLnkMgr )
390             {
391                 LinkManager* pNewMgr = pLinkMgr;
392                 pLinkMgr = nullptr;
393                 SetManager( pNewMgr );
394                 m_xTbLinks->set_cursor(nPos ? --nPos : 0);
395             }
396             bModified = true;
397         }
398     }
399     else
400     {
401         std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(m_xDialog.get(),
402                                                        VclMessageType::Question, VclButtonsType::YesNo,
403                                                        aStrCloselinkmsgMulti));
404         xQueryBox->set_default_response(RET_YES);
405 
406         if (RET_YES == xQueryBox->run())
407         {
408             std::vector<int> aRows = m_xTbLinks->get_selected_rows();
409             SvBaseLinkMemberList aLinkList;
410             for (auto nRow : aRows)
411             {
412                 SvBaseLink* pLink = weld::fromId<SvBaseLink*>(m_xTbLinks->get_id(nRow));
413                 if (pLink)
414                     aLinkList.push_back(pLink);
415             }
416             std::sort(aRows.begin(), aRows.end());
417             for (auto it = aRows.rbegin(); it != aRows.rend(); ++it)
418                 m_xTbLinks->remove(*it);
419             for (size_t i = 0; i < aLinkList.size(); ++i)
420             {
421                 tools::SvRef<SvBaseLink> xLink = aLinkList[i];
422                 // tell the link that it will be resolved!
423                 xLink->Closed();
424 
425                 // if somebody has forgotten to deregister himself
426                 pLinkMgr->Remove( xLink.get() );
427                 bModified = true;
428             }
429             // then remove all selected entries
430         }
431     }
432     if(!bModified)
433         return;
434 
435     if (!m_xTbLinks->n_children())
436     {
437         m_xRbAutomatic->set_sensitive(false);
438         m_xRbManual->set_sensitive(false);
439         m_xPbUpdateNow->set_sensitive(false);
440         m_xPbChangeSource->set_sensitive(false);
441         m_xPbBreakLink->set_sensitive(false);
442 
443         m_xFtFullSourceName->set_label( u""_ustr );
444         m_xFtFullTypeName->set_label( u""_ustr );
445     }
446     if( pLinkMgr && pLinkMgr->GetPersist() )
447         pLinkMgr->GetPersist()->SetModified();
448 }
449 
IMPL_LINK_NOARG(SvBaseLinksDlg,UpdateWaitingHdl,Timer *,void)450 IMPL_LINK_NOARG( SvBaseLinksDlg, UpdateWaitingHdl, Timer*, void )
451 {
452     m_xTbLinks->freeze();
453     for (int nPos = m_xTbLinks->n_children(); nPos; --nPos)
454     {
455         tools::SvRef<SvBaseLink> xLink( weld::fromId<SvBaseLink*>(m_xTbLinks->get_id(nPos)) );
456         if( xLink.is() )
457         {
458             OUString sCur( ImplGetStateStr( *xLink ) ),
459                     sOld( m_xTbLinks->get_text(nPos, 3) );
460             if( sCur != sOld )
461                 m_xTbLinks->set_text(nPos, sCur, 3);
462         }
463     }
464     m_xTbLinks->thaw();
465 }
466 
IMPL_LINK(SvBaseLinksDlg,EndEditHdl,sfx2::SvBaseLink &,_rLink,void)467 IMPL_LINK( SvBaseLinksDlg, EndEditHdl, sfx2::SvBaseLink&, _rLink, void )
468 {
469     int nPos;
470     GetSelEntry( &nPos );
471 
472     if( !_rLink.WasLastEditOK() )
473         return;
474 
475     // StarImpress/Draw swap the LinkObjects themselves!
476     // So search for the link in the manager; if it does not exist
477     // anymore, fill the list completely new. Otherwise only the
478     // edited link needs to be refreshed.
479     bool bLinkFnd = false;
480     for( size_t n = pLinkMgr->GetLinks().size(); n;  )
481         if( &_rLink == &(*pLinkMgr->GetLinks()[ --n ]) )
482         {
483             bLinkFnd = true;
484             break;
485         }
486 
487     if( bLinkFnd )
488     {
489         m_xTbLinks->remove(nPos);
490         int nToUnselect = m_xTbLinks->get_selected_index();
491         InsertEntry(_rLink, nPos, true);
492         if (nToUnselect != -1)
493             m_xTbLinks->unselect(nToUnselect);
494     }
495     else
496     {
497         LinkManager* pNewMgr = pLinkMgr;
498         pLinkMgr = nullptr;
499         SetManager( pNewMgr );
500     }
501     if (pLinkMgr && pLinkMgr->GetPersist())
502         pLinkMgr->GetPersist()->SetModified();
503 }
504 
ImplGetStateStr(const SvBaseLink & rLnk)505 OUString SvBaseLinksDlg::ImplGetStateStr( const SvBaseLink& rLnk )
506 {
507     OUString sRet;
508     if( !rLnk.GetObj() )
509         sRet = aStrBrokenlink;
510     else if( rLnk.GetObj()->IsPending() )
511     {
512         sRet = aStrWaitinglink;
513         aUpdateIdle.Start();
514     }
515     else if( SfxLinkUpdateMode::ALWAYS == rLnk.GetUpdateMode() )
516         sRet = aStrAutolink;
517     else
518         sRet = aStrManuallink;
519 
520     return sRet;
521 }
522 
SetManager(LinkManager * pNewMgr)523 void SvBaseLinksDlg::SetManager( LinkManager* pNewMgr )
524 {
525     if( pLinkMgr == pNewMgr )
526         return;
527 
528     if (pNewMgr)
529     {
530         // update has to be stopped before clear
531         m_xTbLinks->freeze();
532     }
533 
534     m_xTbLinks->clear();
535     pLinkMgr = pNewMgr;
536 
537     if( !pLinkMgr )
538         return;
539 
540     SvBaseLinks& rLnks = const_cast<SvBaseLinks&>(pLinkMgr->GetLinks());
541     for( size_t n = 0; n < rLnks.size(); ++n )
542     {
543         tools::SvRef<SvBaseLink>& rLinkRef = rLnks[ n ];
544         if( !rLinkRef.is() )
545         {
546             rLnks.erase( rLnks.begin() + n );
547             --n;
548             continue;
549         }
550         if( rLinkRef->IsVisible() )
551             InsertEntry( *rLinkRef );
552     }
553 
554     m_xTbLinks->thaw();
555 
556     if( !rLnks.empty() )
557     {
558         m_xTbLinks->set_cursor(0);
559         m_xTbLinks->select(0);
560         LinksSelectHdl( nullptr );
561     }
562 }
563 
InsertEntry(const SvBaseLink & rLink,int nPos,bool bSelect)564 void SvBaseLinksDlg::InsertEntry(const SvBaseLink& rLink, int nPos, bool bSelect)
565 {
566     OUString sFileNm, sLinkNm, sTypeNm, sFilter;
567 
568     sfx2::LinkManager::GetDisplayNames( &rLink, &sTypeNm, &sFileNm, &sLinkNm, &sFilter );
569 
570     auto nWidthPixel = m_xTbLinks->get_column_width(0);
571     OUString aTxt = m_xVirDev->GetEllipsisString(sFileNm, nWidthPixel, DrawTextFlags::PathEllipsis);
572     INetURLObject aPath( sFileNm, INetProtocol::File );
573     OUString aFileName = aPath.getName(
574         INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous);
575 
576     if( aFileName.getLength() > aTxt.getLength() )
577         aTxt = aFileName;
578     else if (!aFileName.isEmpty() && aTxt.indexOf(aFileName, aTxt.getLength() - aFileName.getLength()) == -1)
579         // filename not in string
580         aTxt = aFileName;
581 
582     if (nPos == -1)
583         nPos = m_xTbLinks->n_children();
584     m_xTbLinks->insert(nPos);
585     m_xTbLinks->set_text(nPos, aTxt, 0);
586     m_xTbLinks->set_id(nPos, weld::toId(&rLink));
587     if( SvBaseLinkObjectType::ClientGraphic == rLink.GetObjType() )
588         m_xTbLinks->set_text(nPos, sFilter, 1);
589     else
590         m_xTbLinks->set_text(nPos, sLinkNm, 1);
591     m_xTbLinks->set_text(nPos, sTypeNm, 2);
592     m_xTbLinks->set_text(nPos, ImplGetStateStr(rLink), 3);
593     if (bSelect)
594         m_xTbLinks->select(nPos);
595 }
596 
GetSelEntry(int * pPos)597 SvBaseLink* SvBaseLinksDlg::GetSelEntry(int* pPos)
598 {
599     int nPos = m_xTbLinks->get_selected_index();
600     if (nPos != -1)
601     {
602         if (pPos)
603             *pPos = nPos;
604         return weld::fromId<SvBaseLink*>(m_xTbLinks->get_id(nPos));
605     }
606     return nullptr;
607 }
608 
SetType(SvBaseLink & rLink,int nSelPos,SfxLinkUpdateMode nType)609 void SvBaseLinksDlg::SetType(SvBaseLink& rLink,
610                              int nSelPos,
611                              SfxLinkUpdateMode nType)
612 {
613     rLink.SetUpdateMode( nType );
614     rLink.Update();
615     m_xTbLinks->set_text(nSelPos, ImplGetStateStr(rLink), 3);
616     if (pLinkMgr->GetPersist())
617         pLinkMgr->GetPersist()->SetModified();
618 }
619 
SetActLink(SvBaseLink const * pLink)620 void SvBaseLinksDlg::SetActLink( SvBaseLink const * pLink )
621 {
622     if( !pLinkMgr )
623         return;
624 
625     const SvBaseLinks& rLnks = pLinkMgr->GetLinks();
626     int nSelect = 0;
627     for(const auto & rLinkRef : rLnks)
628     {
629         // #109573# only visible links have been inserted into the TreeListBox,
630         // invisible ones have to be skipped here
631         if( rLinkRef->IsVisible() )
632         {
633             if( pLink == rLinkRef.get() )
634             {
635                 m_xTbLinks->select(nSelect);
636                 LinksSelectHdl( nullptr );
637                 return ;
638             }
639             ++nSelect;
640         }
641     }
642 }
643 
644 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
645