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