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 <svl/stritem.hxx>
21 #include <sfx2/fcontnr.hxx>
22 #include <sfx2/linkmgr.hxx>
23 #include <sfx2/dispatch.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <svl/urihelper.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/docfilt.hxx>
28 #include <vcl/help.hxx>
29 #include <sot/filelist.hxx>
30 #include <svl/eitem.hxx>
31 #include <svl/urlbmk.hxx>
32 #include <svx/svxids.hrc>
33 #include <vcl/graphicfilter.hxx>
34 #include <vcl/settings.hxx>
35
36 #include <vcl/treelistentry.hxx>
37 #include <sfx2/docinsert.hxx>
38 #include <sfx2/filedlghelper.hxx>
39
40 #include <sfx2/app.hxx>
41 #include <swmodule.hxx>
42 #include <wrtsh.hxx>
43 #include <view.hxx>
44 #include <docsh.hxx>
45 #include <content.hxx>
46 #include <edglbldc.hxx>
47 #include <section.hxx>
48 #include <tox.hxx>
49 #include <cnttab.hxx>
50 #include <navipi.hxx>
51 #include <navicont.hxx>
52 #include <edtwin.hxx>
53 #include <uitool.hxx>
54 #include <toxmgr.hxx>
55
56 #include <cmdid.h>
57 #include <helpids.h>
58 #include <strings.hrc>
59 #include <globals.hrc>
60 #include <bitmaps.hlst>
61 #include <swabstdlg.hxx>
62 #include <memory>
63
64 using namespace ::com::sun::star::uno;
65
66 // Context menu for GlobalTree
67 #define CTX_INSERT_ANY_INDEX 10
68 #define CTX_INSERT_FILE 11
69 #define CTX_INSERT_NEW_FILE 12
70 #define CTX_INSERT_TEXT 13
71
72 #define CTX_UPDATE_SEL 20
73 #define CTX_UPDATE_INDEX 21
74 #define CTX_UPDATE_LINK 22
75 #define CTX_UPDATE_ALL 23
76
77 #define CTX_UPDATE 1
78 #define CTX_INSERT 2
79 #define CTX_EDIT 3
80 #define CTX_DELETE 4
81 #define CTX_EDIT_LINK 5
82
83 #define GLOBAL_UPDATE_TIMEOUT 2000
84
85 // TabPos: push to left
86 #define GLBL_TABPOS_SUB 5
87
88 const SfxObjectShell* SwGlobalTree::pShowShell = nullptr;
89 static const char* aHelpForMenu[] =
90 {
91 nullptr,
92 HID_GLBLTREE_UPDATE, //CTX_UPDATE
93 HID_GLBLTREE_INSERT, //CTX_INSERT
94 HID_GLBLTREE_EDIT, //CTX_EDIT
95 HID_GLBLTREE_DEL, //CTX_DELETE
96 HID_GLBLTREE_EDIT_LINK, //CTX_EDIT_LINK
97 nullptr,
98 nullptr,
99 nullptr,
100 nullptr,
101 HID_GLBLTREE_INS_IDX, //CTX_INSERT_ANY_INDEX
102 HID_GLBLTREE_INS_FILE, //CTX_INSERT_FILE
103 HID_GLBLTREE_INS_NEW_FILE, //CTX_INSERT_NEW_FILE
104 HID_GLBLTREE_INS_TEXT, //CTX_INSERT_TEXT
105 nullptr,
106 nullptr,
107 nullptr,
108 nullptr,
109 nullptr,
110 nullptr,
111 HID_GLBLTREE_UPD_SEL, //CTX_UPDATE_SEL
112 HID_GLBLTREE_UPD_IDX, //CTX_UPDATE_INDEX
113 HID_GLBLTREE_UPD_LINK, //CTX_UPDATE_LINK
114 HID_GLBLTREEUPD_ALL //CTX_UPDATE_ALL
115 };
116
117 class SwGlobalFrameListener_Impl : public SfxListener
118 {
119 bool bValid;
120 public:
SwGlobalFrameListener_Impl(SfxViewFrame & rFrame)121 explicit SwGlobalFrameListener_Impl(SfxViewFrame& rFrame)
122 : bValid(true)
123 {
124 StartListening(rFrame);
125 }
126
127 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
128
IsValid() const129 bool IsValid() const {return bValid;}
130 };
131
Notify(SfxBroadcaster &,const SfxHint & rHint)132 void SwGlobalFrameListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
133 {
134 if( rHint.GetId() == SfxHintId::Dying)
135 bValid = false;
136 }
137
138 enum GLOBAL_CONTEXT_IDX
139 {
140 IDX_STR_UPDATE = 0,
141 IDX_STR_EDIT_CONTENT = 1,
142 IDX_STR_EDIT_INSERT = 2,
143 IDX_STR_INDEX = 3,
144 IDX_STR_FILE = 4,
145 IDX_STR_NEW_FILE = 5,
146 IDX_STR_INSERT_TEXT = 6,
147 IDX_STR_DELETE = 7,
148 IDX_STR_UPDATE_SEL = 8,
149 IDX_STR_UPDATE_INDEX = 9,
150 IDX_STR_UPDATE_LINK = 10,
151 IDX_STR_UPDATE_ALL = 11,
152 IDX_STR_BROKEN_LINK = 12,
153 IDX_STR_EDIT_LINK = 13
154 };
155
156 static const char* GLOBAL_CONTEXT_ARY[] =
157 {
158 STR_UPDATE,
159 STR_EDIT_CONTENT,
160 STR_EDIT_INSERT,
161 STR_INDEX,
162 STR_FILE,
163 STR_NEW_FILE,
164 STR_INSERT_TEXT,
165 STR_DELETE,
166 STR_UPDATE_SEL,
167 STR_UPDATE_INDEX,
168 STR_UPDATE_LINK,
169 STR_UPDATE_ALL,
170 STR_BROKEN_LINK,
171 STR_EDIT_LINK
172 };
173
SwGlobalTree(vcl::Window * pParent,SwNavigationPI * pDialog)174 SwGlobalTree::SwGlobalTree(vcl::Window* pParent, SwNavigationPI* pDialog)
175 : SvTreeListBox(pParent)
176 , m_xDialog(pDialog)
177 , m_pActiveShell(nullptr)
178 , m_pEmphasisEntry(nullptr)
179 , m_pDDSource(nullptr)
180 , m_bIsInternalDrag(false)
181 , m_bLastEntryEmphasis(false)
182 {
183 SetDragDropMode(DragDropMode::APP_COPY |
184 DragDropMode::CTRL_MOVE |
185 DragDropMode::ENABLE_TOP );
186
187 m_aUpdateTimer.SetTimeout(GLOBAL_UPDATE_TIMEOUT);
188 m_aUpdateTimer.SetInvokeHandler(LINK(this, SwGlobalTree, Timeout));
189 m_aUpdateTimer.Start();
190 for (sal_uInt16 i = 0; i < GLOBAL_CONTEXT_COUNT; i++)
191 {
192 m_aContextStrings[i] = SwResId(GLOBAL_CONTEXT_ARY[i]);
193 }
194 SetHelpId(HID_NAVIGATOR_GLOB_TREELIST);
195 SelectHdl();
196 SetDoubleClickHdl(LINK(this, SwGlobalTree, DoubleClickHdl));
197 EnableContextMenuHandling();
198 }
199
~SwGlobalTree()200 SwGlobalTree::~SwGlobalTree()
201 {
202 disposeOnce();
203 }
204
dispose()205 void SwGlobalTree::dispose()
206 {
207 m_pSwGlblDocContents.reset();
208 m_pDocInserter.reset();
209 m_aUpdateTimer.Stop();
210 m_xDialog.clear();
211 SvTreeListBox::dispose();
212 }
213
GetOptimalSize() const214 Size SwGlobalTree::GetOptimalSize() const
215 {
216 return LogicToPixel(Size(110, 112), MapMode(MapUnit::MapAppFont));
217 }
218
ExecuteDrop(const ExecuteDropEvent & rEvt)219 sal_Int8 SwGlobalTree::ExecuteDrop( const ExecuteDropEvent& rEvt )
220 {
221 sal_Int8 nRet = DND_ACTION_NONE;
222 SvTreeListEntry* pLast = LastVisible();
223 if(m_pEmphasisEntry)
224 {
225 ImplShowTargetEmphasis( Prev(m_pEmphasisEntry), false );
226 m_pEmphasisEntry = nullptr;
227 }
228 else if(m_bLastEntryEmphasis && pLast)
229 {
230 ImplShowTargetEmphasis( pLast, false);
231 }
232
233 SvTreeListEntry* pDropEntry = m_bLastEntryEmphasis ? nullptr : GetEntry(rEvt.maPosPixel);
234 if( m_bIsInternalDrag )
235 {
236 SvTreeListEntry* pDummy = nullptr;
237 sal_uLong nInsertionPos = TREELIST_APPEND;
238 NotifyMoving( pDropEntry, m_pDDSource, pDummy, nInsertionPos );
239 }
240 else
241 {
242 TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
243
244 OUString sFileName;
245 const SwGlblDocContent* pCnt = pDropEntry ?
246 static_cast<const SwGlblDocContent*>(pDropEntry->GetUserData()) :
247 nullptr;
248 if( aData.HasFormat( SotClipboardFormatId::FILE_LIST ))
249 {
250 nRet = rEvt.mnAction;
251 std::unique_ptr<SwGlblDocContents> pTempContents(new SwGlblDocContents);
252 int nAbsContPos = pDropEntry ?
253 static_cast<int>(GetModel()->GetAbsPos(pDropEntry)):
254 - 1;
255 sal_uLong nEntryCount = GetEntryCount();
256
257 // Get data
258 FileList aFileList;
259 aData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList );
260 for ( size_t n = aFileList.Count(); n--; )
261 {
262 sFileName = aFileList.GetFile(n);
263 InsertRegion(pCnt, &sFileName);
264 // The list of contents must be newly fetched after inserting,
265 // to not work on an old content.
266 if(n)
267 {
268 m_pActiveShell->GetGlobalDocContent(*pTempContents);
269 // If the file was successfully inserted,
270 // then the next content must also be fetched.
271 if(nEntryCount < pTempContents->size())
272 {
273 nEntryCount++;
274 nAbsContPos++;
275 pCnt = (*pTempContents)[ nAbsContPos ].get();
276 }
277 }
278 }
279 }
280 else if( !(sFileName =
281 SwNavigationPI::CreateDropFileName( aData )).isEmpty())
282 {
283 INetURLObject aTemp(sFileName);
284 GraphicDescriptor aDesc(aTemp);
285 if( !aDesc.Detect() ) // accept no graphics
286 {
287 nRet = rEvt.mnAction;
288 InsertRegion(pCnt, &sFileName);
289 }
290 }
291 }
292 m_bLastEntryEmphasis = false;
293 return nRet;
294
295 }
296
AcceptDrop(const AcceptDropEvent & rEvt)297 sal_Int8 SwGlobalTree::AcceptDrop( const AcceptDropEvent& rEvt )
298 {
299 sal_Int8 nRet = rEvt.mnAction;
300
301 //initiate scrolling
302 GetDropTarget( rEvt.maPosPixel );
303 SvTreeListEntry* pLast = LastVisible();
304 if( rEvt.mbLeaving )
305 {
306 if( m_pEmphasisEntry )
307 {
308 ImplShowTargetEmphasis( Prev(m_pEmphasisEntry), false );
309 m_pEmphasisEntry = nullptr;
310 }
311 else if(m_bLastEntryEmphasis && pLast)
312 {
313 ImplShowTargetEmphasis( pLast, false);
314 }
315 m_bLastEntryEmphasis = false;
316 }
317 else
318 {
319 SvTreeListEntry* pDropEntry = GetEntry( rEvt.maPosPixel );
320 if(m_bIsInternalDrag)
321 {
322 if( m_pDDSource != pDropEntry )
323 nRet = rEvt.mnAction;
324 }
325 else if( IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
326 IsDropFormatSupported( SotClipboardFormatId::STRING ) ||
327 IsDropFormatSupported( SotClipboardFormatId::FILE_LIST ) ||
328 IsDropFormatSupported( SotClipboardFormatId::SOLK ) ||
329 IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
330 IsDropFormatSupported( SotClipboardFormatId::FILECONTENT ) ||
331 IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
332 IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) ||
333 IsDropFormatSupported( SotClipboardFormatId::FILENAME ))
334 nRet = DND_ACTION_LINK;
335
336 if(m_pEmphasisEntry && m_pEmphasisEntry != pDropEntry)
337 ImplShowTargetEmphasis( Prev(m_pEmphasisEntry), false );
338 else if(pLast && m_bLastEntryEmphasis && pDropEntry)
339 {
340 ImplShowTargetEmphasis( pLast, false);
341 m_bLastEntryEmphasis = false;
342 }
343
344 if(pDropEntry)
345 ImplShowTargetEmphasis( Prev(pDropEntry), DND_ACTION_NONE != nRet );
346 else if(pLast)
347 {
348 ImplShowTargetEmphasis( pLast, DND_ACTION_NONE != nRet );
349 m_bLastEntryEmphasis = true;
350 }
351 m_pEmphasisEntry = pDropEntry;
352 }
353 return nRet;
354 }
355
CreateContextMenu()356 VclPtr<PopupMenu> SwGlobalTree::CreateContextMenu()
357 {
358 VclPtr<PopupMenu> pPop;
359 if(m_pActiveShell &&
360 !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
361 {
362 const MenuEnableFlags nEnableFlags = GetEnableFlags();
363 pPop = VclPtr<PopupMenu>::Create();
364 VclPtrInstance<PopupMenu> pSubPop1;
365 VclPtrInstance<PopupMenu> pSubPop2;
366
367 for (sal_uInt16 i = CTX_UPDATE_SEL; i <= CTX_UPDATE_ALL; i++)
368 {
369 pSubPop2->InsertItem( i, m_aContextStrings[IDX_STR_UPDATE_SEL + i - CTX_UPDATE_SEL] );
370 pSubPop2->SetHelpId(i, aHelpForMenu[i]);
371 }
372 pSubPop2->EnableItem(CTX_UPDATE_SEL, bool(nEnableFlags & MenuEnableFlags::UpdateSel));
373
374 pSubPop1->InsertItem(CTX_INSERT_ANY_INDEX, m_aContextStrings[IDX_STR_INDEX]);
375 pSubPop1->SetHelpId(CTX_INSERT_ANY_INDEX, aHelpForMenu[CTX_INSERT_ANY_INDEX]);
376 pSubPop1->InsertItem(CTX_INSERT_FILE, m_aContextStrings[IDX_STR_FILE]);
377 pSubPop1->SetHelpId(CTX_INSERT_FILE, aHelpForMenu[CTX_INSERT_FILE]);
378 pSubPop1->InsertItem(CTX_INSERT_NEW_FILE, m_aContextStrings[IDX_STR_NEW_FILE]);
379 pSubPop1->SetHelpId(CTX_INSERT_NEW_FILE, aHelpForMenu[CTX_INSERT_NEW_FILE]);
380 pSubPop1->InsertItem(CTX_INSERT_TEXT, m_aContextStrings[IDX_STR_INSERT_TEXT]);
381 pSubPop1->SetHelpId(CTX_INSERT_TEXT, aHelpForMenu[CTX_INSERT_TEXT]);
382
383 pPop->InsertItem(CTX_UPDATE, m_aContextStrings[IDX_STR_UPDATE]);
384 pPop->SetHelpId(CTX_UPDATE, aHelpForMenu[CTX_UPDATE]);
385 pPop->InsertItem(CTX_EDIT, m_aContextStrings[IDX_STR_EDIT_CONTENT]);
386 pPop->SetHelpId(CTX_EDIT, aHelpForMenu[CTX_EDIT]);
387 if(nEnableFlags&MenuEnableFlags::EditLink)
388 {
389 pPop->InsertItem(CTX_EDIT_LINK, m_aContextStrings[IDX_STR_EDIT_LINK]);
390 pPop->SetHelpId(CTX_EDIT_LINK, aHelpForMenu[CTX_EDIT_LINK]);
391 }
392 pPop->InsertItem(CTX_INSERT, m_aContextStrings[IDX_STR_EDIT_INSERT]);
393 pPop->SetHelpId(CTX_INSERT, aHelpForMenu[CTX_INSERT]);
394 pPop->InsertSeparator() ;
395 pPop->InsertItem(CTX_DELETE, m_aContextStrings[IDX_STR_DELETE]);
396 pPop->SetHelpId(CTX_DELETE, aHelpForMenu[CTX_DELETE]);
397
398 //disabling if applicable
399 pSubPop1->EnableItem(CTX_INSERT_ANY_INDEX, bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
400 pSubPop1->EnableItem(CTX_INSERT_TEXT, bool(nEnableFlags & MenuEnableFlags::InsertText));
401 pSubPop1->EnableItem(CTX_INSERT_FILE, bool(nEnableFlags & MenuEnableFlags::InsertFile));
402 pSubPop1->EnableItem(CTX_INSERT_NEW_FILE, bool(nEnableFlags & MenuEnableFlags::InsertFile));
403
404 pPop->EnableItem(CTX_UPDATE, bool(nEnableFlags & MenuEnableFlags::Update));
405 pPop->EnableItem(CTX_INSERT, bool(nEnableFlags & MenuEnableFlags::InsertIdx));
406 pPop->EnableItem(CTX_EDIT, bool(nEnableFlags & MenuEnableFlags::Edit));
407 pPop->EnableItem(CTX_DELETE, bool(nEnableFlags & MenuEnableFlags::Delete));
408
409 pPop->SetPopupMenu( CTX_INSERT, pSubPop1 );
410 pPop->SetPopupMenu( CTX_UPDATE, pSubPop2 );
411 }
412 return pPop;
413 }
414
TbxMenuHdl(sal_uInt16 nTbxId,ToolBox * pBox)415 void SwGlobalTree::TbxMenuHdl(sal_uInt16 nTbxId, ToolBox* pBox)
416 {
417 const MenuEnableFlags nEnableFlags = GetEnableFlags();
418 const OUString sCommand(pBox->GetItemCommand(nTbxId));
419 if (sCommand == "insert")
420 {
421 ScopedVclPtrInstance<PopupMenu> pMenu;
422 for (sal_uInt16 i = CTX_INSERT_ANY_INDEX; i <= CTX_INSERT_TEXT; ++i)
423 {
424 pMenu->InsertItem( i, m_aContextStrings[IDX_STR_INDEX + i - CTX_INSERT_ANY_INDEX] );
425 pMenu->SetHelpId(i, aHelpForMenu[i] );
426 }
427 pMenu->EnableItem(CTX_INSERT_ANY_INDEX, bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
428 pMenu->EnableItem(CTX_INSERT_TEXT, bool(nEnableFlags & MenuEnableFlags::InsertText));
429 pMenu->EnableItem(CTX_INSERT_FILE, bool(nEnableFlags & MenuEnableFlags::InsertFile));
430 pMenu->EnableItem(CTX_INSERT_NEW_FILE, bool(nEnableFlags & MenuEnableFlags::InsertFile));
431 pMenu->SetSelectHdl(LINK(this, SwGlobalTree, PopupHdl));
432 pMenu->Execute(pBox, pBox->GetItemRect(nTbxId));
433 pMenu.disposeAndClear();
434 pBox->EndSelection();
435 pBox->Invalidate();
436 }
437 else if (sCommand == "update")
438 {
439 ScopedVclPtrInstance<PopupMenu> pMenu;
440 for (sal_uInt16 i = CTX_UPDATE_SEL; i <= CTX_UPDATE_ALL; i++)
441 {
442 pMenu->InsertItem( i, m_aContextStrings[IDX_STR_UPDATE_SEL + i - CTX_UPDATE_SEL] );
443 pMenu->SetHelpId(i, aHelpForMenu[i] );
444 }
445 pMenu->EnableItem(CTX_UPDATE_SEL, bool(nEnableFlags & MenuEnableFlags::UpdateSel));
446 pMenu->SetSelectHdl(LINK(this, SwGlobalTree, PopupHdl));
447 pMenu->Execute(pBox, pBox->GetItemRect(nTbxId));
448 pMenu.disposeAndClear();
449 pBox->EndSelection();
450 pBox->Invalidate();
451 }
452 }
453
GetEnableFlags() const454 MenuEnableFlags SwGlobalTree::GetEnableFlags() const
455 {
456 SvTreeListEntry* pEntry = FirstSelected();
457 sal_uLong nSelCount = GetSelectionCount();
458 sal_uLong nEntryCount = GetEntryCount();
459 SvTreeListEntry* pPrevEntry = pEntry ? Prev(pEntry) : nullptr;
460
461 MenuEnableFlags nRet = MenuEnableFlags::NONE;
462 if(nSelCount == 1 || !nEntryCount)
463 nRet |= MenuEnableFlags::InsertIdx|MenuEnableFlags::InsertFile;
464 if(nSelCount == 1)
465 {
466 nRet |= MenuEnableFlags::Edit;
467 if (pEntry && static_cast<SwGlblDocContent*>(pEntry->GetUserData())->GetType() != GLBLDOC_UNKNOWN &&
468 (!pPrevEntry || static_cast<SwGlblDocContent*>(pPrevEntry->GetUserData())->GetType() != GLBLDOC_UNKNOWN))
469 nRet |= MenuEnableFlags::InsertText;
470 if (pEntry && GLBLDOC_SECTION == static_cast<SwGlblDocContent*>(pEntry->GetUserData())->GetType())
471 nRet |= MenuEnableFlags::EditLink;
472 }
473 else if(!nEntryCount)
474 {
475 nRet |= MenuEnableFlags::InsertText;
476 }
477 if(nEntryCount)
478 nRet |= MenuEnableFlags::Update|MenuEnableFlags::Delete;
479 if(nSelCount)
480 nRet |= MenuEnableFlags::UpdateSel;
481 return nRet;
482 }
483
RequestHelp(const HelpEvent & rHEvt)484 void SwGlobalTree::RequestHelp( const HelpEvent& rHEvt )
485 {
486 bool bParent = true;
487 Update(true);
488 Display(true);
489 if( rHEvt.GetMode() & HelpEventMode::QUICK )
490 {
491 Point aPos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
492 SvTreeListEntry* pEntry = GetEntry( aPos );
493 const SwGlblDocContent* pCont = pEntry ?
494 static_cast<const SwGlblDocContent*>(pEntry->GetUserData()) : nullptr;
495 if( pCont && GLBLDOC_SECTION == pCont->GetType())
496 {
497 bParent = false;
498 SvLBoxTab* pTab;
499 SvLBoxItem* pItem = GetItem( pEntry, aPos.X(), &pTab );
500 if (pItem && SvLBoxItemType::String == pItem->GetType())
501 {
502 const SwSection* pSect = pCont->GetSection();
503 OUString sEntry = pSect->GetLinkFileName().getToken(0, sfx2::cTokenSeparator);
504 if(!pSect->IsConnectFlag())
505 sEntry = m_aContextStrings[IDX_STR_BROKEN_LINK] + sEntry;
506 Point aEntryPos = GetEntryPosition( pEntry );
507
508 aEntryPos.setX( GetTabPos( pEntry, pTab ) );
509 Size aSize(pItem->GetWidth(this, pEntry), pItem->GetHeight(this, pEntry));
510
511 if((aEntryPos.X() + aSize.Width()) > GetSizePixel().Width())
512 aSize.setWidth( GetSizePixel().Width() - aEntryPos.X() );
513
514 aEntryPos = OutputToScreenPixel(aEntryPos);
515 tools::Rectangle aItemRect( aEntryPos, aSize );
516 if(Help::IsBalloonHelpEnabled())
517 {
518 aEntryPos.AdjustX(aSize.Width() );
519 Help::ShowBalloon( this, aEntryPos, aItemRect, sEntry );
520 }
521 else
522 Help::ShowQuickHelp( this, aItemRect, sEntry,
523 QuickHelpFlags::Left|QuickHelpFlags::VCenter );
524 }
525 }
526 }
527
528 if(bParent)
529 SvTreeListBox::RequestHelp(rHEvt);
530 }
531
SelectHdl()532 void SwGlobalTree::SelectHdl()
533 {
534
535 sal_uLong nSelCount = GetSelectionCount();
536 SvTreeListEntry* pSel = FirstSelected();
537 sal_uLong nAbsPos = pSel ? GetModel()->GetAbsPos(pSel) : 0;
538 SwNavigationPI* pNavi = GetParentWindow();
539 bool bReadonly = !m_pActiveShell ||
540 m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
541 pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("edit"), nSelCount == 1 && !bReadonly);
542 pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("insert"), nSelCount <= 1 && !bReadonly);
543 pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("update"), GetEntryCount() > 0 && !bReadonly);
544 pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("up"),
545 nSelCount == 1 && nAbsPos && !bReadonly);
546 pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("down"),
547 nSelCount == 1 && nAbsPos < GetEntryCount() - 1 && !bReadonly);
548
549 }
550
DeselectHdl()551 void SwGlobalTree::DeselectHdl()
552 {
553 SelectHdl();
554 }
555
NotifyStartDrag(TransferDataContainer &,SvTreeListEntry * pEntry)556 DragDropMode SwGlobalTree::NotifyStartDrag( TransferDataContainer& ,
557 SvTreeListEntry* pEntry )
558 {
559 m_bIsInternalDrag = true;
560 m_pDDSource = pEntry;
561 return DragDropMode::CTRL_MOVE;
562 }
563
GetTabPos(SvTreeListEntry *,SvLBoxTab * pTab)564 sal_IntPtr SwGlobalTree::GetTabPos( SvTreeListEntry*, SvLBoxTab* pTab)
565 {
566 return pTab->GetPos() - GLBL_TABPOS_SUB;
567 }
568
NotifyMoving(SvTreeListEntry * pTarget,SvTreeListEntry * pSource,SvTreeListEntry * &,sal_uLong &)569 TriState SwGlobalTree::NotifyMoving( SvTreeListEntry* pTarget,
570 SvTreeListEntry* pSource,
571 SvTreeListEntry*&,
572 sal_uLong&
573 )
574 {
575 SvTreeList* _pModel = GetModel();
576 sal_uLong nSource = _pModel->GetAbsPos(pSource);
577 sal_uLong nDest = pTarget ? _pModel->GetAbsPos(pTarget) : m_pSwGlblDocContents->size();
578
579 if( m_pActiveShell->MoveGlobalDocContent(
580 *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
581 Update( false ))
582 Display();
583
584 return TRISTATE_FALSE;
585 }
586
NotifyCopying(SvTreeListEntry *,SvTreeListEntry *,SvTreeListEntry * &,sal_uLong &)587 TriState SwGlobalTree::NotifyCopying( SvTreeListEntry* /*pTarget*/,
588 SvTreeListEntry* /*pEntry*/,
589 SvTreeListEntry*& /*rpNewParent*/,
590 sal_uLong& /*rNewChildPos*/
591 )
592 {
593 return TRISTATE_FALSE;
594 }
595
NotifyAcceptDrop(SvTreeListEntry * pEntry)596 bool SwGlobalTree::NotifyAcceptDrop( SvTreeListEntry* pEntry)
597 {
598 return pEntry != nullptr;
599 }
600
StartDrag(sal_Int8 nAction,const Point & rPt)601 void SwGlobalTree::StartDrag( sal_Int8 nAction, const Point& rPt )
602 {
603 if( 1 == GetSelectionCount() )
604 SvTreeListBox::StartDrag( nAction, rPt );
605 }
606
DragFinished(sal_Int8 nAction)607 void SwGlobalTree::DragFinished( sal_Int8 nAction )
608 {
609 SvTreeListBox::DragFinished( nAction );
610 m_bIsInternalDrag = false;
611 }
612
613 // If a Ctrl+DoubleClick is executed in an empty area,
614 // then the base function of the control should be called.
615
MouseButtonDown(const MouseEvent & rMEvt)616 void SwGlobalTree::MouseButtonDown( const MouseEvent& rMEvt )
617 {
618 Point aPos( rMEvt.GetPosPixel());
619 SvTreeListEntry* pEntry = GetEntry( aPos, true );
620 if( !pEntry && rMEvt.IsLeft() && rMEvt.IsMod1() && (rMEvt.GetClicks() % 2) == 0)
621 Control::MouseButtonDown( rMEvt );
622 else
623 SvTreeListBox::MouseButtonDown( rMEvt );
624 }
625
GetFocus()626 void SwGlobalTree::GetFocus()
627 {
628 if(Update( false ))
629 Display();
630 SvTreeListBox::GetFocus();
631 }
632
KeyInput(const KeyEvent & rKEvt)633 void SwGlobalTree::KeyInput(const KeyEvent& rKEvt)
634 {
635 const vcl::KeyCode aCode = rKEvt.GetKeyCode();
636 if(aCode.GetCode() == KEY_RETURN)
637 {
638 switch(aCode.GetModifier())
639 {
640 case KEY_MOD2:
641 // Switch boxes
642 GetParentWindow()->ToggleTree();
643 break;
644 }
645 }
646 else
647 SvTreeListBox::KeyInput(rKEvt);
648 }
649
Clear()650 void SwGlobalTree::Clear()
651 {
652 m_pEmphasisEntry = nullptr;
653 SvTreeListBox::Clear();
654 }
655
Display(bool bOnlyUpdateUserData)656 void SwGlobalTree::Display(bool bOnlyUpdateUserData)
657 {
658 size_t nCount = m_pSwGlblDocContents->size();
659 if(bOnlyUpdateUserData && GetEntryCount() == m_pSwGlblDocContents->size())
660 {
661 SvTreeListEntry* pEntry = First();
662 for (size_t i = 0; i < nCount && pEntry; i++)
663 {
664 SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
665 pEntry->SetUserData(pCont);
666 pEntry = Next(pEntry);
667 assert(pEntry || i == nCount - 1);
668 }
669 }
670 else
671 {
672 SetUpdateMode( false );
673 SvTreeListEntry* pOldSelEntry = FirstSelected();
674 OUString sEntryName; // Name of the entry
675 sal_uLong nSelPos = TREELIST_ENTRY_NOTFOUND;
676 if(pOldSelEntry)
677 {
678 sEntryName = GetEntryText(pOldSelEntry);
679 nSelPos = GetModel()->GetAbsPos(pOldSelEntry);
680 }
681 Clear();
682 if(!m_pSwGlblDocContents)
683 Update( false );
684
685 SvTreeListEntry* pSelEntry = nullptr;
686 for( size_t i = 0; i < nCount; i++)
687 {
688 SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get();
689 OUString sEntry;
690 Image aImage;
691 switch( pCont->GetType() )
692 {
693 case GLBLDOC_UNKNOWN:
694 {
695 sEntry = m_aContextStrings[IDX_STR_INSERT_TEXT];
696 }
697 break;
698 case GLBLDOC_TOXBASE:
699 {
700 const SwTOXBase* pBase = pCont->GetTOX();
701 sEntry = pBase->GetTitle();
702 aImage = Image(StockImage::Yes, RID_BMP_NAVI_INDEX);
703 }
704 break;
705 case GLBLDOC_SECTION:
706 {
707 const SwSection* pSect = pCont->GetSection();
708 sEntry = pSect->GetSectionName();
709 aImage = Image(StockImage::Yes, RID_BMP_DROP_REGION);
710 }
711 break;
712 }
713 SvTreeListEntry* pEntry = InsertEntry(sEntry, aImage, aImage,
714 nullptr, false, TREELIST_APPEND, pCont);
715 if(sEntry == sEntryName)
716 {
717 pSelEntry = pEntry;
718 }
719 }
720 if(pSelEntry)
721 {
722 Select(pSelEntry);
723 }
724 else if(nSelPos != TREELIST_ENTRY_NOTFOUND && nSelPos < nCount)
725 {
726 Select(GetEntry(nSelPos));
727 }
728 else if(nCount)
729 Select(First());
730 else
731 SelectHdl();
732 SetUpdateMode( true );
733 }
734 }
735
InsertRegion(const SwGlblDocContent * pCont,const OUString * pFileName)736 void SwGlobalTree::InsertRegion( const SwGlblDocContent* pCont, const OUString* pFileName )
737 {
738 Sequence< OUString > aFileNames;
739 if ( !pFileName )
740 {
741 m_pDocInserter.reset(new ::sfx2::DocumentInserter(GetFrameWeld(), "swriter", sfx2::DocumentInserter::Mode::InsertMulti));
742 m_pDocInserter->StartExecuteModal( LINK( this, SwGlobalTree, DialogClosedHdl ) );
743 }
744 else if ( !pFileName->isEmpty() )
745 {
746 aFileNames.realloc(1);
747 INetURLObject aFileName;
748 aFileName.SetSmartURL( *pFileName );
749 aFileNames.getArray()[0] = aFileName.GetMainURL( INetURLObject::DecodeMechanism::NONE );
750 InsertRegion( pCont, aFileNames );
751 }
752 }
753
EditContent(const SwGlblDocContent * pCont)754 void SwGlobalTree::EditContent(const SwGlblDocContent* pCont )
755 {
756 sal_uInt16 nSlot = 0;
757 switch( pCont->GetType() )
758 {
759 case GLBLDOC_UNKNOWN:
760 m_pActiveShell->GetView().GetEditWin().GrabFocus();
761 break;
762 case GLBLDOC_TOXBASE:
763 {
764 const SwTOXBase* pBase = pCont->GetTOX();
765 if(pBase)
766 nSlot = FN_INSERT_MULTI_TOX;
767 }
768 break;
769 case GLBLDOC_SECTION:
770 {
771 OpenDoc(pCont);
772
773 nSlot = 0;
774 pCont = nullptr;
775 }
776 break;
777 }
778 if(pCont)
779 GotoContent(pCont);
780 if(nSlot)
781 {
782 m_pActiveShell->GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot);
783 if(Update( false ))
784 Display();
785 }
786 }
787
IMPL_LINK(SwGlobalTree,PopupHdl,Menu *,pMenu,bool)788 IMPL_LINK( SwGlobalTree, PopupHdl, Menu* , pMenu, bool)
789 {
790 ExecuteContextMenuAction( pMenu->GetCurItemId());
791 return true;
792 }
793
ExecuteContextMenuAction(sal_uInt16 nSelectedPopupEntry)794 void SwGlobalTree::ExecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry )
795 {
796 bool bUpdateHard = false;
797
798 SvTreeListEntry* pEntry = FirstSelected();
799 SwGlblDocContent* pCont = pEntry ? static_cast<SwGlblDocContent*>(pEntry->GetUserData()) : nullptr;
800 // If a RequestHelp is called during the dialogue,
801 // then the content gets lost. Because of that a copy
802 // is created in which only the DocPos is set correctly.
803 std::unique_ptr<SwGlblDocContent> pContCopy;
804 if(pCont)
805 pContCopy.reset(new SwGlblDocContent(pCont->GetDocPos()));
806 SfxDispatcher& rDispatch = *m_pActiveShell->GetView().GetViewFrame()->GetDispatcher();
807 sal_uInt16 nSlot = 0;
808 switch( nSelectedPopupEntry )
809 {
810 case CTX_UPDATE_SEL:
811 {
812 // Two passes: first update the areas, then the directories.
813 SvTreeListEntry* pSelEntry = FirstSelected();
814 while( pSelEntry )
815 {
816 SwGlblDocContent* pContent = static_cast<SwGlblDocContent*>(pSelEntry->GetUserData());
817 if(GLBLDOC_SECTION == pContent->GetType() &&
818 pContent->GetSection()->IsConnected())
819 {
820 const_cast<SwSection*>(pContent->GetSection())->UpdateNow();
821 }
822
823 pSelEntry = NextSelected(pSelEntry);
824 }
825 pSelEntry = FirstSelected();
826 while( pSelEntry )
827 {
828 SwGlblDocContent* pContent = static_cast<SwGlblDocContent*>(pSelEntry->GetUserData());
829 if(GLBLDOC_TOXBASE == pContent->GetType())
830 m_pActiveShell->UpdateTableOf(*pContent->GetTOX());
831 pSelEntry = NextSelected(pSelEntry);
832 }
833 bUpdateHard = true;
834 }
835 break;
836 case CTX_UPDATE_INDEX:
837 {
838 nSlot = FN_UPDATE_TOX;
839 bUpdateHard = true;
840 }
841 break;
842 case CTX_UPDATE_LINK:
843 case CTX_UPDATE_ALL:
844 {
845 m_pActiveShell->GetLinkManager().UpdateAllLinks(true, false, nullptr);
846 if(CTX_UPDATE_ALL == nSelectedPopupEntry)
847 nSlot = FN_UPDATE_TOX;
848 pCont = nullptr;
849 bUpdateHard = true;
850 }
851 break;
852 case CTX_EDIT:
853 {
854 OSL_ENSURE(pCont, "edit without entry ? " );
855 if (pCont)
856 {
857 EditContent(pCont);
858 }
859 }
860 break;
861 case CTX_EDIT_LINK:
862 {
863 OSL_ENSURE(pCont, "edit without entry ? " );
864 if (pCont)
865 {
866 SfxStringItem aName(FN_EDIT_REGION,
867 pCont->GetSection()->GetSectionName());
868 rDispatch.ExecuteList(FN_EDIT_REGION, SfxCallMode::ASYNCHRON,
869 { &aName });
870 }
871 }
872 break;
873 case CTX_DELETE:
874 {
875 // If several entries selected, then after each delete the array
876 // must be refilled. So you do not have to remember anything,
877 // deleting begins at the end.
878 SvTreeListEntry* pSelEntry = LastSelected();
879 std::unique_ptr<SwGlblDocContents> pTempContents;
880 m_pActiveShell->StartAction();
881 while(pSelEntry)
882 {
883 m_pActiveShell->DeleteGlobalDocContent(
884 pTempContents ? *pTempContents : *m_pSwGlblDocContents,
885 GetModel()->GetAbsPos(pSelEntry));
886 pSelEntry = PrevSelected(pSelEntry);
887 if(pSelEntry)
888 {
889 pTempContents.reset(new SwGlblDocContents);
890 m_pActiveShell->GetGlobalDocContent(*pTempContents);
891 }
892 }
893 pTempContents.reset();
894 m_pActiveShell->EndAction();
895 pCont = nullptr;
896 }
897 break;
898 case CTX_INSERT_ANY_INDEX:
899 {
900 if(pContCopy)
901 {
902 SfxItemSet aSet(
903 m_pActiveShell->GetView().GetPool(),
904 svl::Items<
905 RES_FRM_SIZE, RES_FRM_SIZE,
906 RES_LR_SPACE, RES_LR_SPACE,
907 RES_BACKGROUND, RES_BACKGROUND,
908 RES_COL, RES_COL,
909 SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
910 FN_PARAM_TOX_TYPE, FN_PARAM_TOX_TYPE>{});
911
912 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
913 ScopedVclPtr<AbstractMultiTOXTabDialog> pDlg(pFact->CreateMultiTOXTabDialog(
914 GetFrameWeld(), aSet,
915 *m_pActiveShell,
916 nullptr,
917 true));
918 if(RET_OK == pDlg->Execute())
919 {
920 SwTOXDescription& rDesc = pDlg->GetTOXDescription(
921 pDlg->GetCurrentTOXType());
922 SwTOXMgr aMgr(m_pActiveShell);
923 SwTOXBase* pToInsert = nullptr;
924 if(aMgr.UpdateOrInsertTOX(rDesc, &pToInsert, pDlg->GetOutputItemSet()))
925 m_pActiveShell->InsertGlobalDocContent( *pContCopy, *pToInsert );
926 }
927 pCont = nullptr;
928 }
929 }
930 break;
931 case CTX_INSERT_FILE:
932 {
933 m_pDocContent = std::move(pContCopy);
934 InsertRegion( m_pDocContent.get() );
935 pCont = nullptr;
936 }
937 break;
938 case CTX_INSERT_NEW_FILE:
939 {
940 SfxViewFrame* pGlobFrame = m_pActiveShell->GetView().GetViewFrame();
941 SwGlobalFrameListener_Impl aFrameListener(*pGlobFrame);
942
943 sal_uLong nEntryPos = pEntry ? GetModel()->GetAbsPos(pEntry) : sal_uLong(-1);
944 // Creating a new doc
945 SfxStringItem aFactory(SID_NEWDOCDIRECT,
946 SwDocShell::Factory().GetFilterContainer()->GetName());
947
948 const SfxFrameItem* pItem = static_cast<const SfxFrameItem*>(
949 rDispatch.ExecuteList(SID_NEWDOCDIRECT,
950 SfxCallMode::SYNCHRON, { &aFactory }));
951
952 // save at
953 SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr;
954 SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr;
955 if (pViewFrame)
956 {
957 const SfxBoolItem* pBool = static_cast<const SfxBoolItem*>(
958 pViewFrame->GetDispatcher()->Execute(
959 SID_SAVEASDOC, SfxCallMode::SYNCHRON ));
960 SfxObjectShell& rObj = *pViewFrame->GetObjectShell();
961 const SfxMedium* pMedium = rObj.GetMedium();
962 OUString sNewFile(pMedium->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri));
963 // Insert the area with the Doc-Name
964 // Bring the own Doc in the foreground
965 if(aFrameListener.IsValid() && !sNewFile.isEmpty())
966 {
967 pGlobFrame->ToTop();
968 // Due to the update the entries are invalid
969 if(nEntryPos != sal_uLong(-1))
970 {
971 Update( false );
972 Display();
973 Select(GetModel()->GetEntryAtAbsPos(nEntryPos));
974 pEntry = FirstSelected();
975 pCont = pEntry ? static_cast<SwGlblDocContent*>(pEntry->GetUserData()) : nullptr;
976 }
977 else
978 {
979 pEntry = nullptr;
980 pCont = nullptr;
981 }
982 if(pBool->GetValue())
983 {
984 InsertRegion(pCont, &sNewFile);
985 pViewFrame->ToTop();
986 }
987 else
988 pViewFrame->GetDispatcher()->Execute(SID_CLOSEWIN,
989 SfxCallMode::SYNCHRON);
990 }
991 else
992 {
993 pViewFrame->ToTop();
994 return;
995 }
996 }
997 }
998 break;
999 case CTX_INSERT_TEXT:
1000 {
1001 if(pCont)
1002 m_pActiveShell->InsertGlobalDocContent(*pCont);
1003 else
1004 {
1005 m_pActiveShell->SplitNode(); // Empty document
1006 m_pActiveShell->Up( false );
1007 }
1008 m_pActiveShell->GetView().GetEditWin().GrabFocus();
1009 }
1010 break;
1011 case CTX_UPDATE:
1012 pCont = nullptr;
1013 break;
1014 default:;
1015 // here nothing happens
1016 }
1017 if(pCont)
1018 GotoContent(pCont);
1019 if(nSlot)
1020 rDispatch.Execute(nSlot);
1021 if (Update(bUpdateHard))
1022 Display();
1023 }
1024
IMPL_LINK_NOARG(SwGlobalTree,Timeout,Timer *,void)1025 IMPL_LINK_NOARG(SwGlobalTree, Timeout, Timer *, void)
1026 {
1027 if(!IsDisposed() && !HasFocus() && Update( false ))
1028 Display();
1029 }
1030
GotoContent(const SwGlblDocContent * pCont)1031 void SwGlobalTree::GotoContent(const SwGlblDocContent* pCont)
1032 {
1033 m_pActiveShell->EnterStdMode();
1034
1035 switch( pCont->GetType() )
1036 {
1037 case GLBLDOC_UNKNOWN:
1038 m_pActiveShell->GotoGlobalDocContent(*pCont);
1039 break;
1040 case GLBLDOC_TOXBASE:
1041 {
1042 const OUString sName = pCont->GetTOX()->GetTOXName();
1043 if (!m_pActiveShell->GotoNextTOXBase(&sName))
1044 m_pActiveShell->GotoPrevTOXBase(&sName);
1045 }
1046 break;
1047 case GLBLDOC_SECTION:
1048 break;
1049 }
1050
1051 }
1052
ShowTree()1053 void SwGlobalTree::ShowTree()
1054 {
1055 m_aUpdateTimer.Start();
1056 SvTreeListBox::Show();
1057 }
1058
HideTree()1059 void SwGlobalTree::HideTree()
1060 {
1061 m_aUpdateTimer.Stop();
1062 SvTreeListBox::Hide();
1063 }
1064
ExecCommand(const OUString & rCmd)1065 void SwGlobalTree::ExecCommand(const OUString &rCmd)
1066 {
1067 SvTreeListEntry* pEntry = FirstSelected();
1068 OSL_ENSURE(pEntry, "It explodes in the next moment");
1069 if (rCmd == "edit")
1070 {
1071 const SwGlblDocContent* pCont = static_cast<const SwGlblDocContent*>(
1072 pEntry->GetUserData());
1073 EditContent(pCont);
1074 }
1075 else
1076 {
1077 if(GetSelectionCount() == 1)
1078 {
1079 bool bMove = false;
1080 sal_uLong nSource = GetModel()->GetAbsPos(pEntry);
1081 sal_uLong nDest = nSource;
1082 if (rCmd == "down")
1083 {
1084 sal_uLong nEntryCount = GetEntryCount();
1085 bMove = nEntryCount > nSource + 1;
1086 nDest+= 2;
1087 }
1088 else if (rCmd == "up")
1089 {
1090 bMove = 0 != nSource;
1091 nDest--;
1092 }
1093 if( bMove && m_pActiveShell->MoveGlobalDocContent(
1094 *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
1095 Update( false ))
1096 Display();
1097 }
1098 }
1099 }
1100
Update(bool bHard)1101 bool SwGlobalTree::Update(bool bHard)
1102 {
1103 SwView* pActView = GetParentWindow()->GetCreateView();
1104 bool bRet = false;
1105 if (pActView && pActView->GetWrtShellPtr())
1106 {
1107 const SwWrtShell* pOldShell = m_pActiveShell;
1108 m_pActiveShell = pActView->GetWrtShellPtr();
1109 if(m_pActiveShell != pOldShell)
1110 {
1111 m_pSwGlblDocContents.reset();
1112 }
1113 if(!m_pSwGlblDocContents)
1114 {
1115 m_pSwGlblDocContents.reset(new SwGlblDocContents);
1116 bRet = true;
1117 m_pActiveShell->GetGlobalDocContent(*m_pSwGlblDocContents);
1118 }
1119 else
1120 {
1121 bool bCopy = false;
1122 std::unique_ptr<SwGlblDocContents> pTempContents(new SwGlblDocContents);
1123 m_pActiveShell->GetGlobalDocContent(*pTempContents);
1124 if(pTempContents->size() != m_pSwGlblDocContents->size() ||
1125 pTempContents->size() != GetEntryCount())
1126 {
1127 bRet = true;
1128 bCopy = true;
1129 }
1130 else
1131 {
1132 for(size_t i = 0; i < pTempContents->size() && !bCopy; i++)
1133 {
1134 SwGlblDocContent* pLeft = (*pTempContents)[i].get();
1135 SwGlblDocContent* pRight = (*m_pSwGlblDocContents)[i].get();
1136 GlobalDocContentType eType = pLeft->GetType();
1137 SvTreeListEntry* pEntry = GetEntry(i);
1138 OUString sTemp = GetEntryText(pEntry);
1139 if (
1140 eType != pRight->GetType() ||
1141 (
1142 eType == GLBLDOC_SECTION &&
1143 pLeft->GetSection()->GetSectionName() != sTemp
1144 ) ||
1145 (
1146 eType == GLBLDOC_TOXBASE &&
1147 pLeft->GetTOX()->GetTitle() != sTemp
1148 )
1149 )
1150 {
1151 bCopy = bRet = true;
1152 }
1153 }
1154 }
1155 if(bCopy || bHard)
1156 {
1157 *m_pSwGlblDocContents = std::move( *pTempContents );
1158 }
1159 }
1160 }
1161 else
1162 {
1163 Clear();
1164 if(m_pSwGlblDocContents)
1165 m_pSwGlblDocContents->clear();
1166 }
1167 // FIXME: Implement a test for changes!
1168 return bRet;
1169 }
1170
OpenDoc(const SwGlblDocContent * pCont)1171 void SwGlobalTree::OpenDoc(const SwGlblDocContent* pCont)
1172 {
1173 const OUString sFileName(pCont->GetSection()->GetLinkFileName().getToken(0,
1174 sfx2::cTokenSeparator));
1175 bool bFound = false;
1176 const SfxObjectShell* pCurr = SfxObjectShell::GetFirst();
1177 while( !bFound && pCurr )
1178 {
1179 if(pCurr->GetMedium() &&
1180 pCurr->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri) == sFileName)
1181 {
1182 bFound = true;
1183 SwGlobalTree::SetShowShell(pCurr);
1184 Application::PostUserEvent( LINK( this, SwGlobalTree, ShowFrameHdl ), nullptr, true );
1185 pCurr = nullptr;
1186 }
1187 else
1188 pCurr = SfxObjectShell::GetNext(*pCurr);
1189 }
1190 if(!bFound)
1191 {
1192 SfxStringItem aURL(SID_FILE_NAME, sFileName);
1193 SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
1194 SfxStringItem aTargetFrameName( SID_TARGETNAME, "_blank" );
1195 SfxStringItem aReferer(SID_REFERER, m_pActiveShell->GetView().GetDocShell()->GetTitle());
1196 m_pActiveShell->GetView().GetViewFrame()->GetDispatcher()->
1197 ExecuteList(SID_OPENDOC, SfxCallMode::ASYNCHRON,
1198 { &aURL, &aReadOnly, &aReferer, &aTargetFrameName });
1199 }
1200 }
1201
IMPL_LINK_NOARG(SwGlobalTree,DoubleClickHdl,SvTreeListBox *,bool)1202 IMPL_LINK_NOARG( SwGlobalTree, DoubleClickHdl, SvTreeListBox*, bool)
1203 {
1204 SvTreeListEntry* pEntry = GetCurEntry();
1205 SwGlblDocContent* pCont = static_cast<SwGlblDocContent*>(pEntry->GetUserData());
1206 if(pCont->GetType() == GLBLDOC_SECTION)
1207 OpenDoc(pCont);
1208 else
1209 {
1210 GotoContent(pCont);
1211 m_pActiveShell->GetView().GetEditWin().GrabFocus();
1212 }
1213 return false;
1214 }
1215
GetParentWindow()1216 SwNavigationPI* SwGlobalTree::GetParentWindow()
1217 {
1218 return m_xDialog;
1219 }
1220
IMPL_STATIC_LINK_NOARG(SwGlobalTree,ShowFrameHdl,void *,void)1221 IMPL_STATIC_LINK_NOARG(SwGlobalTree, ShowFrameHdl, void*, void)
1222 {
1223 SfxViewFrame* pFirst = pShowShell ? SfxViewFrame::GetFirst(pShowShell) : nullptr;
1224 if (pFirst)
1225 pFirst->ToTop();
1226 SwGlobalTree::SetShowShell(nullptr);
1227 }
1228
InitEntry(SvTreeListEntry * pEntry,const OUString & rStr,const Image & rImg1,const Image & rImg2)1229 void SwGlobalTree::InitEntry(SvTreeListEntry* pEntry,
1230 const OUString& rStr ,const Image& rImg1,const Image& rImg2)
1231 {
1232 const size_t nColToHilite = 1; //0==Bitmap;1=="Column1";2=="Column2"
1233 SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2 );
1234 SvLBoxString& rCol = static_cast<SvLBoxString&>(pEntry->GetItem( nColToHilite ));
1235 pEntry->ReplaceItem(std::make_unique<SwLBoxString>(rCol.GetText()), nColToHilite);
1236 }
1237
Paint(const Point & rPos,SvTreeListBox & rDev,vcl::RenderContext & rRenderContext,const SvViewDataEntry * pView,const SvTreeListEntry & rEntry)1238 void SwLBoxString::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
1239 const SvViewDataEntry* pView, const SvTreeListEntry& rEntry)
1240 {
1241 SwGlblDocContent* pCont = static_cast<SwGlblDocContent*>(rEntry.GetUserData());
1242 if (pCont->GetType() == GLBLDOC_SECTION &&
1243 !pCont->GetSection()->IsConnectFlag())
1244 {
1245 rRenderContext.Push(PushFlags::FONT);
1246 vcl::Font aOldFont(rRenderContext.GetFont());
1247 vcl::Font aFont(rRenderContext.GetFont());
1248 aFont.SetColor(COL_LIGHTRED);
1249 rRenderContext.SetFont(aFont);
1250 rRenderContext.DrawText(rPos, GetText());
1251 rRenderContext.Pop();
1252 }
1253 else
1254 SvLBoxString::Paint(rPos, rDev, rRenderContext, pView, rEntry);
1255 }
1256
DataChanged(const DataChangedEvent & rDCEvt)1257 void SwGlobalTree::DataChanged( const DataChangedEvent& rDCEvt )
1258 {
1259 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1260 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1261 {
1262 Update(true);
1263 }
1264 SvTreeListBox::DataChanged( rDCEvt );
1265 }
1266
InsertRegion(const SwGlblDocContent * _pContent,const Sequence<OUString> & _rFiles)1267 void SwGlobalTree::InsertRegion( const SwGlblDocContent* _pContent, const Sequence< OUString >& _rFiles )
1268 {
1269 sal_Int32 nFiles = _rFiles.getLength();
1270 if ( !nFiles )
1271 return;
1272
1273 bool bMove = false;
1274 if ( !_pContent )
1275 {
1276 SvTreeListEntry* pLast = LastVisible();
1277 _pContent = static_cast<SwGlblDocContent*>(pLast->GetUserData());
1278 bMove = true;
1279 }
1280 sal_uLong nEntryCount = GetEntryCount();
1281 const OUString* pFileNames = _rFiles.getConstArray();
1282 SwWrtShell& rSh = GetParentWindow()->GetCreateView()->GetWrtShell();
1283 rSh.StartAction();
1284 // after insertion of the first new content the 'pCont' parameter becomes invalid
1285 // find the index of the 'anchor' content to always use a current anchor content
1286 size_t nAnchorContent = m_pSwGlblDocContents->size() - 1;
1287 if ( !bMove )
1288 {
1289 for (size_t nContent = 0; nContent < m_pSwGlblDocContents->size();
1290 ++nContent)
1291 {
1292 if( *_pContent == *(*m_pSwGlblDocContents)[ nContent ] )
1293 {
1294 nAnchorContent = nContent;
1295 break;
1296 }
1297 }
1298 }
1299 SwGlblDocContents aTempContents;
1300 for ( sal_Int32 nFile = 0; nFile < nFiles; ++nFile )
1301 {
1302 //update the global document content after each inserted document
1303 rSh.GetGlobalDocContent(aTempContents);
1304 SwGlblDocContent* pAnchorContent = nullptr;
1305 OSL_ENSURE(aTempContents.size() > (nAnchorContent + nFile), "invalid anchor content -> last insertion failed");
1306 if ( aTempContents.size() > (nAnchorContent + nFile) )
1307 pAnchorContent = aTempContents[nAnchorContent + nFile].get();
1308 else
1309 pAnchorContent = aTempContents.back().get();
1310 OUString sFileName(pFileNames[nFile]);
1311 INetURLObject aFileUrl;
1312 aFileUrl.SetSmartURL( sFileName );
1313 OUString sSectionName(aFileUrl.GetLastName(
1314 INetURLObject::DecodeMechanism::Unambiguous).getToken(0, sfx2::cTokenSeparator));
1315 sal_uInt16 nSectCount = rSh.GetSectionFormatCount();
1316 OUString sTempSectionName(sSectionName);
1317 sal_uInt16 nAddNumber = 0;
1318 sal_uInt16 nCount = 0;
1319 // if applicable: add index if the range name is already in use.
1320 while ( nCount < nSectCount )
1321 {
1322 const SwSectionFormat& rFormat = rSh.GetSectionFormat(nCount);
1323 if ((rFormat.GetSection()->GetSectionName() == sTempSectionName)
1324 && rFormat.IsInNodesArr())
1325 {
1326 nCount = 0;
1327 nAddNumber++;
1328 sTempSectionName = sSectionName + ":" + OUString::number( nAddNumber );
1329 }
1330 else
1331 nCount++;
1332 }
1333
1334 if ( nAddNumber )
1335 sSectionName = sTempSectionName;
1336
1337 SwSectionData aSectionData(CONTENT_SECTION, sSectionName);
1338 aSectionData.SetProtectFlag(true);
1339 aSectionData.SetHidden(false);
1340
1341 aSectionData.SetLinkFileName(sFileName);
1342 aSectionData.SetType(FILE_LINK_SECTION);
1343 aSectionData.SetLinkFilePassword( OUString() );
1344
1345 rSh.InsertGlobalDocContent( *pAnchorContent, aSectionData );
1346 }
1347 if ( bMove )
1348 {
1349 Update( false );
1350 rSh.MoveGlobalDocContent(
1351 *m_pSwGlblDocContents, nEntryCount, nEntryCount + nFiles, nEntryCount - nFiles );
1352 }
1353 rSh.EndAction();
1354 Update( false );
1355 Display();
1356
1357 }
1358
IMPL_LINK(SwGlobalTree,DialogClosedHdl,sfx2::FileDialogHelper *,_pFileDlg,void)1359 IMPL_LINK( SwGlobalTree, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
1360 {
1361 if ( ERRCODE_NONE != _pFileDlg->GetError() )
1362 return;
1363
1364 SfxMediumList aMedList(m_pDocInserter->CreateMediumList());
1365 if ( !aMedList.empty() )
1366 {
1367 Sequence< OUString >aFileNames( aMedList.size() );
1368 OUString* pFileNames = aFileNames.getArray();
1369 sal_Int32 nPos = 0;
1370 for (const std::unique_ptr<SfxMedium>& pMed : aMedList)
1371 {
1372 OUString sFileName = pMed->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE )
1373 + OUStringChar(sfx2::cTokenSeparator)
1374 + pMed->GetFilter()->GetFilterName()
1375 + OUStringChar(sfx2::cTokenSeparator);
1376 pFileNames[nPos++] = sFileName;
1377 }
1378 InsertRegion( m_pDocContent.get(), aFileNames );
1379 m_pDocContent.reset();
1380 }
1381 }
1382
1383 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1384