/src/libreoffice/sc/source/ui/docshell/tablink.cxx
Line | Count | Source |
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 <com/sun/star/task/InteractionHandler.hpp> |
23 | | |
24 | | #include <sfx2/sfxsids.hrc> |
25 | | #include <sfx2/app.hxx> |
26 | | #include <svl/itemset.hxx> |
27 | | #include <svl/stritem.hxx> |
28 | | #include <sfx2/docfile.hxx> |
29 | | #include <sfx2/docfilt.hxx> |
30 | | #include <sfx2/fcontnr.hxx> |
31 | | #include <sfx2/frame.hxx> |
32 | | #include <sfx2/linkmgr.hxx> |
33 | | #include <utility> |
34 | | #include <vcl/weld.hxx> |
35 | | #include <tools/urlobj.hxx> |
36 | | #include <unotools/transliterationwrapper.hxx> |
37 | | #include <comphelper/configuration.hxx> |
38 | | #include <comphelper/processfactory.hxx> |
39 | | |
40 | | #include <tablink.hxx> |
41 | | |
42 | | #include <scextopt.hxx> |
43 | | #include <document.hxx> |
44 | | #include <docsh.hxx> |
45 | | #include <globstr.hrc> |
46 | | #include <scresid.hxx> |
47 | | #include <undoblk.hxx> |
48 | | #include <undotab.hxx> |
49 | | #include <global.hxx> |
50 | | #include <hints.hxx> |
51 | | #include <dociter.hxx> |
52 | | #include <formula/opcode.hxx> |
53 | | #include <formulaiter.hxx> |
54 | | #include <tokenarray.hxx> |
55 | | |
56 | | ScTableLink::ScTableLink(ScDocShell& rShell, OUString aFile, |
57 | | OUString aFilter, OUString aOpt, |
58 | | sal_Int32 nRefreshDelaySeconds ): |
59 | 0 | ::sfx2::SvBaseLink(SfxLinkUpdateMode::ONCALL,SotClipboardFormatId::SIMPLE_FILE), |
60 | 0 | ScRefreshTimer( nRefreshDelaySeconds ), |
61 | 0 | m_rDocSh( rShell ), |
62 | 0 | aFileName(std::move(aFile)), |
63 | 0 | aFilterName(std::move(aFilter)), |
64 | 0 | aOptions(std::move(aOpt)), |
65 | 0 | bInCreate( false ), |
66 | 0 | bInEdit( false ), |
67 | 0 | bAddUndo( true ) |
68 | 0 | { |
69 | 0 | } |
70 | | |
71 | | ScTableLink::~ScTableLink() |
72 | 0 | { |
73 | | // cancel connection |
74 | |
|
75 | 0 | StopRefreshTimer(); |
76 | 0 | ScDocument& rDoc = m_rDocSh.GetDocument(); |
77 | 0 | SCTAB nCount = rDoc.GetTableCount(); |
78 | 0 | for (SCTAB nTab=0; nTab<nCount; nTab++) |
79 | 0 | if (rDoc.IsLinked(nTab) && aFileName == rDoc.GetLinkDoc(nTab)) |
80 | 0 | rDoc.SetLink( nTab, ScLinkMode::NONE, u""_ustr, u""_ustr, u""_ustr, u""_ustr, 0 ); |
81 | 0 | } |
82 | | |
83 | | void ScTableLink::Edit(weld::Window* pParent, const Link<SvBaseLink&,void>& rEndEditHdl) |
84 | 0 | { |
85 | 0 | m_aEndEditLink = rEndEditHdl; |
86 | |
|
87 | 0 | bInEdit = true; |
88 | 0 | SvBaseLink::Edit( pParent, LINK( this, ScTableLink, TableEndEditHdl ) ); |
89 | 0 | } |
90 | | |
91 | | ::sfx2::SvBaseLink::UpdateResult ScTableLink::DataChanged( |
92 | | const OUString&, const css::uno::Any& ) |
93 | 0 | { |
94 | 0 | sfx2::LinkManager* pLinkManager=m_rDocSh.GetDocument().GetLinkManager(); |
95 | 0 | if (pLinkManager!=nullptr) |
96 | 0 | { |
97 | 0 | OUString aFile, aFilter; |
98 | 0 | sfx2::LinkManager::GetDisplayNames(this, nullptr, &aFile, nullptr, &aFilter); |
99 | | |
100 | | // the file dialog returns the filter name with the application prefix |
101 | | // -> remove prefix |
102 | 0 | ScDocumentLoader::RemoveAppPrefix( aFilter ); |
103 | |
|
104 | 0 | if (!bInCreate) |
105 | 0 | Refresh( aFile, aFilter, nullptr, GetRefreshDelaySeconds() ); // don't load twice |
106 | 0 | } |
107 | 0 | return SUCCESS; |
108 | 0 | } |
109 | | |
110 | | void ScTableLink::Closed() |
111 | 0 | { |
112 | | // delete link: Undo |
113 | 0 | ScDocument& rDoc = m_rDocSh.GetDocument(); |
114 | 0 | bool bUndo (rDoc.IsUndoEnabled()); |
115 | |
|
116 | 0 | if (bAddUndo && bUndo) |
117 | 0 | { |
118 | 0 | m_rDocSh.GetUndoManager()->AddUndoAction( |
119 | 0 | std::make_unique<ScUndoRemoveLink>( m_rDocSh, aFileName ) ); |
120 | |
|
121 | 0 | bAddUndo = false; // only once |
122 | 0 | } |
123 | | |
124 | | // connection gets cancelled in the dtor |
125 | |
|
126 | 0 | SvBaseLink::Closed(); |
127 | 0 | } |
128 | | |
129 | | bool ScTableLink::IsUsed() const |
130 | 0 | { |
131 | 0 | return m_rDocSh.GetDocument().HasLink( aFileName, aFilterName, aOptions ); |
132 | 0 | } |
133 | | |
134 | | bool ScTableLink::Refresh(const OUString& rNewFile, const OUString& rNewFilter, |
135 | | const OUString* pNewOptions, sal_Int32 nNewRefreshDelaySeconds ) |
136 | 0 | { |
137 | | // load document |
138 | |
|
139 | 0 | if (rNewFile.isEmpty() || rNewFilter.isEmpty()) |
140 | 0 | return false; |
141 | | |
142 | 0 | OUString aNewUrl = ScGlobal::GetAbsDocName(rNewFile, &m_rDocSh); |
143 | 0 | bool bNewUrlName = aFileName != aNewUrl; |
144 | |
|
145 | 0 | std::shared_ptr<const SfxFilter> pFilter = m_rDocSh.GetFactory().GetFilterContainer()->GetFilter4FilterName(rNewFilter); |
146 | 0 | if (!pFilter) |
147 | 0 | return false; |
148 | | |
149 | 0 | ScDocument& rDoc = m_rDocSh.GetDocument(); |
150 | 0 | rDoc.SetInLinkUpdate( true ); |
151 | |
|
152 | 0 | bool bUndo(rDoc.IsUndoEnabled()); |
153 | | |
154 | | // if new filter has been selected, forget options |
155 | 0 | if (aFilterName != rNewFilter) |
156 | 0 | aOptions.clear(); |
157 | 0 | if ( pNewOptions ) // options hard-specified? |
158 | 0 | aOptions = *pNewOptions; |
159 | | |
160 | | // always create ItemSet, so that DocShell can set the options |
161 | 0 | auto pSet = std::make_shared<SfxAllItemSet>( SfxGetpApp()->GetPool() ); |
162 | 0 | if (!aOptions.isEmpty()) |
163 | 0 | pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) ); |
164 | |
|
165 | 0 | SfxMedium* pMed = new SfxMedium(aNewUrl, StreamMode::STD_READ, std::move(pFilter), std::move(pSet)); |
166 | |
|
167 | 0 | if ( bInEdit ) // only if using the edit dialog, |
168 | 0 | pMed->UseInteractionHandler(true); // enable the filter options dialog |
169 | | |
170 | | // aRef->DoClose() will be called explicitly, but it is still more safe to use SfxObjectShellLock here |
171 | 0 | rtl::Reference<ScDocShell> pSrcShell = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS); |
172 | 0 | pSrcShell->DoLoad(pMed); |
173 | | |
174 | | // options might have been set |
175 | 0 | OUString aNewOpt = ScDocumentLoader::GetOptions(*pMed); |
176 | 0 | if (aNewOpt.isEmpty()) |
177 | 0 | aNewOpt = aOptions; |
178 | | |
179 | | // Undo... |
180 | |
|
181 | 0 | ScDocumentUniquePtr pUndoDoc; |
182 | 0 | bool bFirst = true; |
183 | 0 | if (bAddUndo && bUndo) |
184 | 0 | pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO )); |
185 | | |
186 | | // copy tables |
187 | |
|
188 | 0 | ScDocShellModificator aModificator( m_rDocSh ); |
189 | |
|
190 | 0 | bool bNotFound = false; |
191 | 0 | ScDocument& rSrcDoc = pSrcShell->GetDocument(); |
192 | | |
193 | | // from text filters that don't set the table name, |
194 | | // use the one table regardless of link table name |
195 | 0 | bool bAutoTab = (rSrcDoc.GetTableCount() == 1) && |
196 | 0 | ScDocShell::HasAutomaticTableName( rNewFilter ); |
197 | |
|
198 | 0 | SCTAB nCount = rDoc.GetTableCount(); |
199 | 0 | for (SCTAB nTab=0; nTab<nCount; nTab++) |
200 | 0 | { |
201 | 0 | ScLinkMode nMode = rDoc.GetLinkMode(nTab); |
202 | 0 | if (nMode != ScLinkMode::NONE && aFileName == rDoc.GetLinkDoc(nTab)) |
203 | 0 | { |
204 | 0 | OUString aTabName = rDoc.GetLinkTab(nTab); |
205 | | |
206 | | // Undo |
207 | |
|
208 | 0 | if (bAddUndo && bUndo) |
209 | 0 | { |
210 | 0 | if (bFirst) |
211 | 0 | pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true ); |
212 | 0 | else |
213 | 0 | pUndoDoc->AddUndoTab( nTab, nTab, true, true ); |
214 | 0 | bFirst = false; |
215 | 0 | ScRange aRange(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab); |
216 | 0 | rDoc.CopyToDocument(aRange, InsertDeleteFlags::ALL, false, *pUndoDoc); |
217 | 0 | pUndoDoc->TransferDrawPage( rDoc, nTab, nTab ); |
218 | 0 | pUndoDoc->SetLink( nTab, nMode, aFileName, aFilterName, |
219 | 0 | aOptions, aTabName, GetRefreshDelaySeconds() ); |
220 | 0 | pUndoDoc->SetTabBgColor( nTab, rDoc.GetTabBgColor(nTab) ); |
221 | 0 | } |
222 | | |
223 | | // adjust table name of an ExtDocRef |
224 | |
|
225 | 0 | if ( bNewUrlName && nMode == ScLinkMode::VALUE ) |
226 | 0 | { |
227 | 0 | OUString aName; |
228 | 0 | rDoc.GetName( nTab, aName ); |
229 | 0 | if ( ScGlobal::GetTransliteration().isEqual( |
230 | 0 | ScGlobal::GetDocTabName( aFileName, aTabName ), aName ) ) |
231 | 0 | { |
232 | 0 | rDoc.RenameTab( nTab, |
233 | 0 | ScGlobal::GetDocTabName( aNewUrl, aTabName ), |
234 | 0 | true/*bExternalDocument*/ ); |
235 | 0 | } |
236 | 0 | } |
237 | | |
238 | | // copy |
239 | |
|
240 | 0 | SCTAB nSrcTab = 0; |
241 | 0 | bool bFound = false; |
242 | | /* #i71497# check if external document is loaded successfully, |
243 | | otherwise we may find the empty default sheet "Sheet1" in |
244 | | rSrcDoc, even if the document does not exist. */ |
245 | 0 | if( pMed->GetErrorIgnoreWarning() == ERRCODE_NONE ) |
246 | 0 | { |
247 | | // no sheet name -> use first sheet |
248 | 0 | if ( !aTabName.isEmpty() && !bAutoTab ) |
249 | 0 | bFound = rSrcDoc.GetTable( aTabName, nSrcTab ); |
250 | 0 | else |
251 | 0 | bFound = true; |
252 | 0 | } |
253 | |
|
254 | 0 | if (bFound) |
255 | 0 | rDoc.TransferTab( rSrcDoc, nSrcTab, nTab, false, // don't insert anew |
256 | 0 | (nMode == ScLinkMode::VALUE) ); // only values? |
257 | 0 | else |
258 | 0 | { |
259 | 0 | rDoc.DeleteAreaTab( 0,0,rDoc.MaxCol(),rDoc.MaxRow(), nTab, InsertDeleteFlags::ALL ); |
260 | |
|
261 | 0 | bool bShowError = true; |
262 | 0 | if ( nMode == ScLinkMode::VALUE ) |
263 | 0 | { |
264 | | // Value link (used with external references in formulas): |
265 | | // Look for formulas that reference the sheet, and put errors in the referenced cells. |
266 | |
|
267 | 0 | ScRangeList aErrorCells; // cells on the linked sheets that need error values |
268 | |
|
269 | 0 | ScCellIterator aIter(rDoc, ScRange(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB)); // all sheets |
270 | 0 | for (bool bHas = aIter.first(); bHas; bHas = aIter.next()) |
271 | 0 | { |
272 | 0 | if (aIter.getType() != CELLTYPE_FORMULA) |
273 | 0 | continue; |
274 | | |
275 | 0 | ScFormulaCell* pCell = aIter.getFormulaCell(); |
276 | 0 | ScDetectiveRefIter aRefIter(rDoc, pCell); |
277 | 0 | ScRange aRefRange; |
278 | 0 | while ( aRefIter.GetNextRef( aRefRange ) ) |
279 | 0 | { |
280 | 0 | if ( aRefRange.aStart.Tab() <= nTab && aRefRange.aEnd.Tab() >= nTab ) |
281 | 0 | { |
282 | | // use first cell of range references (don't fill potentially large ranges) |
283 | |
|
284 | 0 | aErrorCells.Join( ScRange( aRefRange.aStart ) ); |
285 | 0 | } |
286 | 0 | } |
287 | 0 | } |
288 | |
|
289 | 0 | size_t nRanges = aErrorCells.size(); |
290 | 0 | if ( nRanges ) // found any? |
291 | 0 | { |
292 | 0 | ScTokenArray aTokenArr(rDoc); |
293 | 0 | aTokenArr.AddOpCode( ocNotAvail ); |
294 | 0 | aTokenArr.AddOpCode( ocOpen ); |
295 | 0 | aTokenArr.AddOpCode( ocClose ); |
296 | 0 | aTokenArr.AddOpCode( ocStop ); |
297 | |
|
298 | 0 | for (size_t nPos=0; nPos < nRanges; nPos++) |
299 | 0 | { |
300 | 0 | const ScRange & rRange = aErrorCells[ nPos ]; |
301 | 0 | SCCOL nStartCol = rRange.aStart.Col(); |
302 | 0 | SCROW nStartRow = rRange.aStart.Row(); |
303 | 0 | SCCOL nEndCol = rRange.aEnd.Col(); |
304 | 0 | SCROW nEndRow = rRange.aEnd.Row(); |
305 | 0 | for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++) |
306 | 0 | for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) |
307 | 0 | { |
308 | 0 | ScAddress aDestPos( nCol, nRow, nTab ); |
309 | 0 | rDoc.SetFormula(aDestPos, aTokenArr); |
310 | 0 | } |
311 | 0 | } |
312 | |
|
313 | 0 | bShowError = false; |
314 | 0 | } |
315 | | // if no references were found, insert error message (don't leave the sheet empty) |
316 | 0 | } |
317 | |
|
318 | 0 | if ( bShowError ) |
319 | 0 | { |
320 | | // Normal link or no references: put error message on sheet. |
321 | |
|
322 | 0 | rDoc.SetString( 0,0,nTab, ScResId(STR_LINKERROR) ); |
323 | 0 | rDoc.SetString( 0,1,nTab, ScResId(STR_LINKERRORFILE) ); |
324 | 0 | rDoc.SetString( 1,1,nTab, aNewUrl ); |
325 | 0 | rDoc.SetString( 0,2,nTab, ScResId(STR_LINKERRORTAB) ); |
326 | 0 | rDoc.SetString( 1,2,nTab, aTabName ); |
327 | 0 | } |
328 | |
|
329 | 0 | bNotFound = true; |
330 | 0 | } |
331 | |
|
332 | 0 | if ( bNewUrlName || aFilterName != rNewFilter || |
333 | 0 | aOptions != aNewOpt || pNewOptions || |
334 | 0 | nNewRefreshDelaySeconds != GetRefreshDelaySeconds() ) |
335 | 0 | rDoc.SetLink( nTab, nMode, aNewUrl, rNewFilter, aNewOpt, |
336 | 0 | aTabName, nNewRefreshDelaySeconds ); |
337 | 0 | } |
338 | 0 | } |
339 | | |
340 | | // memorize new settings |
341 | |
|
342 | 0 | if ( bNewUrlName ) |
343 | 0 | aFileName = aNewUrl; |
344 | 0 | if (aFilterName != rNewFilter) |
345 | 0 | aFilterName = rNewFilter; |
346 | 0 | if (aOptions != aNewOpt) |
347 | 0 | aOptions = aNewOpt; |
348 | | |
349 | | // clean up |
350 | |
|
351 | 0 | pSrcShell->DoClose(); |
352 | | |
353 | | // Undo |
354 | |
|
355 | 0 | if (bAddUndo && bUndo) |
356 | 0 | m_rDocSh.GetUndoManager()->AddUndoAction( |
357 | 0 | std::make_unique<ScUndoRefreshLink>( m_rDocSh, std::move(pUndoDoc) ) ); |
358 | | |
359 | | // Paint (may be several tables) |
360 | |
|
361 | 0 | m_rDocSh.PostPaint( ScRange(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB), |
362 | 0 | PaintPartFlags::Grid | PaintPartFlags::Top | PaintPartFlags::Left | PaintPartFlags::Extras ); |
363 | 0 | aModificator.SetDocumentModified(); |
364 | |
|
365 | 0 | if (bNotFound) |
366 | 0 | { |
367 | | //! output error ? |
368 | 0 | } |
369 | |
|
370 | 0 | rDoc.SetInLinkUpdate( false ); |
371 | | |
372 | | // notify Uno objects (for XRefreshListener) |
373 | | //! also notify Uno objects if file name was changed! |
374 | 0 | ScLinkRefreshedHint aHint; |
375 | 0 | aHint.SetSheetLink( aFileName ); |
376 | 0 | rDoc.BroadcastUno( aHint ); |
377 | |
|
378 | 0 | return true; |
379 | 0 | } |
380 | | |
381 | | IMPL_LINK( ScTableLink, TableEndEditHdl, ::sfx2::SvBaseLink&, rLink, void ) |
382 | 0 | { |
383 | 0 | m_aEndEditLink.Call( rLink ); |
384 | 0 | bInEdit = false; |
385 | 0 | } |
386 | | |
387 | | // === ScDocumentLoader ================================================== |
388 | | |
389 | | OUString ScDocumentLoader::GetOptions( const SfxMedium& rMedium ) |
390 | 0 | { |
391 | 0 | if ( const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
392 | 0 | return pItem->GetValue(); |
393 | | |
394 | 0 | return OUString(); |
395 | 0 | } |
396 | | |
397 | | bool ScDocumentLoader::GetFilterName( const OUString& rFileName, |
398 | | OUString& rFilter, OUString& rOptions, |
399 | | bool bWithContent, bool bWithInteraction ) |
400 | 1.86k | { |
401 | 1.86k | SfxObjectShell* pDocSh = SfxObjectShell::GetFirst( checkSfxObjectShell<ScDocShell> ); |
402 | 1.86k | while ( pDocSh ) |
403 | 0 | { |
404 | 0 | if ( pDocSh->HasName() ) |
405 | 0 | { |
406 | 0 | SfxMedium* pMed = pDocSh->GetMedium(); |
407 | 0 | if ( pMed->GetName() == rFileName ) |
408 | 0 | { |
409 | 0 | rFilter = pMed->GetFilter()->GetFilterName(); |
410 | 0 | rOptions = GetOptions(*pMed); |
411 | 0 | return true; |
412 | 0 | } |
413 | 0 | } |
414 | 0 | pDocSh = SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell<ScDocShell> ); |
415 | 0 | } |
416 | | |
417 | 1.86k | INetURLObject aUrl( rFileName ); |
418 | 1.86k | INetProtocol eProt = aUrl.GetProtocol(); |
419 | 1.86k | if ( eProt == INetProtocol::NotValid ) // invalid URL? |
420 | 85 | return false; // abort without creating a medium |
421 | | |
422 | | // Filter detection |
423 | | |
424 | 1.78k | std::shared_ptr<const SfxFilter> pSfxFilter; |
425 | 1.78k | SfxMedium aMedium( rFileName, StreamMode::STD_READ ); |
426 | 1.78k | if (aMedium.GetErrorIgnoreWarning() == ERRCODE_NONE && !comphelper::IsFuzzing()) |
427 | 0 | { |
428 | 0 | if ( bWithInteraction ) |
429 | 0 | aMedium.UseInteractionHandler(true); // #i73992# no longer called from GuessFilter |
430 | |
|
431 | 0 | SfxFilterMatcher aMatcher(u"scalc"_ustr); |
432 | 0 | if( bWithContent ) |
433 | 0 | aMatcher.GuessFilter( aMedium, pSfxFilter ); |
434 | 0 | else |
435 | 0 | aMatcher.GuessFilterIgnoringContent( aMedium, pSfxFilter ); |
436 | 0 | } |
437 | | |
438 | 1.78k | bool bOK = false; |
439 | 1.78k | if ( aMedium.GetErrorIgnoreWarning() == ERRCODE_NONE ) |
440 | 1.78k | { |
441 | 1.78k | if ( pSfxFilter ) |
442 | 0 | rFilter = pSfxFilter->GetFilterName(); |
443 | 1.78k | else |
444 | 1.78k | rFilter = ScDocShell::GetOwnFilterName(); // otherwise Calc file |
445 | 1.78k | bOK = !rFilter.isEmpty(); |
446 | 1.78k | } |
447 | | |
448 | 1.78k | return bOK; |
449 | 1.86k | } |
450 | | |
451 | | void ScDocumentLoader::RemoveAppPrefix( OUString& rFilterName ) |
452 | 0 | { |
453 | 0 | OUString aAppPrefix( STRING_SCAPP + ": "); |
454 | 0 | if (rFilterName.startsWith( aAppPrefix)) |
455 | 0 | rFilterName = rFilterName.copy( aAppPrefix.getLength()); |
456 | 0 | } |
457 | | |
458 | | SfxMedium* ScDocumentLoader::CreateMedium( const OUString& rFileName, std::shared_ptr<const SfxFilter> const & pFilter, |
459 | | const OUString& rOptions, weld::Window* pInteractionParent ) |
460 | 0 | { |
461 | | // Always create SfxItemSet so ScDocShell can set options. |
462 | 0 | auto pSet = std::make_shared<SfxAllItemSet>( SfxGetpApp()->GetPool() ); |
463 | 0 | if ( !rOptions.isEmpty() ) |
464 | 0 | pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, rOptions ) ); |
465 | |
|
466 | 0 | if (pInteractionParent) |
467 | 0 | { |
468 | 0 | const css::uno::Reference<css::uno::XComponentContext>& xContext = comphelper::getProcessComponentContext(); |
469 | 0 | css::uno::Reference<css::task::XInteractionHandler> xIHdl(css::task::InteractionHandler::createWithParent(xContext, |
470 | 0 | pInteractionParent->GetXWindow()), css::uno::UNO_QUERY_THROW); |
471 | 0 | pSet->Put(SfxUnoAnyItem(SID_INTERACTIONHANDLER, css::uno::Any(xIHdl))); |
472 | 0 | } |
473 | |
|
474 | 0 | SfxMedium *pRet = new SfxMedium( rFileName, StreamMode::STD_READ, pFilter, std::move(pSet) ); |
475 | 0 | if (pInteractionParent) |
476 | 0 | pRet->UseInteractionHandler(true); // to enable the filter options dialog |
477 | 0 | return pRet; |
478 | 0 | } |
479 | | |
480 | | ScDocumentLoader::ScDocumentLoader(const OUString& rFileName, |
481 | | OUString& rFilterName, OUString& rOptions, |
482 | | sal_uInt32 nRekCnt, weld::Window* pInteractionParent, |
483 | | const css::uno::Reference<css::io::XInputStream>& xInputStream) |
484 | 0 | : pMedium(nullptr) |
485 | 0 | { |
486 | 0 | if ( rFilterName.isEmpty() ) |
487 | 0 | GetFilterName(rFileName, rFilterName, rOptions, true, pInteractionParent != nullptr); |
488 | |
|
489 | 0 | std::shared_ptr<const SfxFilter> pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( rFilterName ); |
490 | |
|
491 | 0 | pMedium = CreateMedium(rFileName, pFilter, rOptions, pInteractionParent); |
492 | 0 | if (xInputStream.is()) |
493 | 0 | pMedium->setStreamToLoadFrom(xInputStream, true); |
494 | 0 | if ( pMedium->GetErrorIgnoreWarning() != ERRCODE_NONE ) |
495 | 0 | return ; |
496 | | |
497 | 0 | pDocShell = new ScDocShell( SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS ); |
498 | |
|
499 | 0 | ScDocument& rDoc = pDocShell->GetDocument(); |
500 | 0 | ScExtDocOptions* pExtDocOpt = rDoc.GetExtDocOptions(); |
501 | 0 | if( !pExtDocOpt ) |
502 | 0 | { |
503 | 0 | rDoc.SetExtDocOptions( std::make_unique<ScExtDocOptions>() ); |
504 | 0 | pExtDocOpt = rDoc.GetExtDocOptions(); |
505 | 0 | } |
506 | 0 | pExtDocOpt->GetDocSettings().mnLinkCnt = nRekCnt; |
507 | |
|
508 | 0 | pDocShell->DoLoad( pMedium ); |
509 | |
|
510 | 0 | OUString aNew = GetOptions(*pMedium); // options are set per dialog on load |
511 | 0 | if (!aNew.isEmpty() && aNew != rOptions) |
512 | 0 | rOptions = aNew; |
513 | 0 | } |
514 | | |
515 | | ScDocumentLoader::~ScDocumentLoader() |
516 | 0 | { |
517 | 0 | if (pDocShell) |
518 | 0 | pDocShell->DoClose(); |
519 | 0 | else |
520 | 0 | delete pMedium; |
521 | 0 | } |
522 | | |
523 | | void ScDocumentLoader::ReleaseDocRef() |
524 | 0 | { |
525 | 0 | if (pDocShell) |
526 | 0 | { |
527 | | // release reference without calling DoClose - caller must |
528 | | // have another reference to the doc and call DoClose later |
529 | |
|
530 | 0 | pMedium = nullptr; |
531 | 0 | pDocShell.clear(); |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | | ScDocument* ScDocumentLoader::GetDocument() |
536 | 0 | { |
537 | 0 | return pDocShell ? &pDocShell->GetDocument() : nullptr; |
538 | 0 | } |
539 | | |
540 | | bool ScDocumentLoader::IsError() const |
541 | 0 | { |
542 | 0 | if ( pDocShell && pMedium ) |
543 | 0 | return pMedium->GetErrorIgnoreWarning() != ERRCODE_NONE; |
544 | 0 | else |
545 | 0 | return true; |
546 | 0 | } |
547 | | |
548 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |