Line data Source code
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 : #ifndef INCLUDED_SC_INC_EXTERNALREFMGR_HXX
21 : #define INCLUDED_SC_INC_EXTERNALREFMGR_HXX
22 :
23 : #include "global.hxx"
24 : #include "address.hxx"
25 : #include <sfx2/objsh.hxx>
26 : #include <sfx2/lnkbase.hxx>
27 : #include <sfx2/event.hxx>
28 : #include <tools/time.hxx>
29 : #include <vcl/timer.hxx>
30 : #include <svl/zforlist.hxx>
31 : #include <svl/lstner.hxx>
32 : #include "types.hxx"
33 : #include "rangelst.hxx"
34 : #include <formula/token.hxx>
35 : #include <osl/mutex.hxx>
36 :
37 : #include <boost/unordered_map.hpp>
38 : #include <boost/unordered_set.hpp>
39 : #include <boost/shared_ptr.hpp>
40 : #include <vector>
41 : #include <list>
42 : #include <set>
43 : #include <formula/ExternalReferenceHelper.hxx>
44 :
45 : class ScDocument;
46 : class ScTokenArray;
47 : namespace vcl { class Window; }
48 : class ScFormulaCell;
49 :
50 : class ScExternalRefCache;
51 :
52 : namespace svl {
53 :
54 : class SharedStringPool;
55 :
56 : }
57 :
58 : namespace sc {
59 :
60 : class ColumnSpanSet;
61 :
62 : }
63 :
64 : class ScExternalRefLink : public ::sfx2::SvBaseLink
65 : {
66 : public:
67 : ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const OUString& rFilter);
68 : virtual ~ScExternalRefLink();
69 :
70 : virtual void Closed() SAL_OVERRIDE;
71 : virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
72 : const OUString& rMimeType, const ::com::sun::star::uno::Any & rValue) SAL_OVERRIDE;
73 : virtual void Edit(vcl::Window* pParent, const Link& rEndEditHdl) SAL_OVERRIDE;
74 :
75 : void SetDoReferesh(bool b);
76 :
77 : private:
78 : ScExternalRefLink(); // disabled
79 : ScExternalRefLink(const ScExternalRefLink&); // disabled
80 :
81 : DECL_LINK( ExternalRefEndEditHdl, void* );
82 :
83 : sal_uInt16 mnFileId;
84 : OUString maFilterName;
85 : ScDocument* mpDoc;
86 : bool mbDoRefresh;
87 : };
88 :
89 : /**
90 : * Cache table for external reference data.
91 : */
92 : class ScExternalRefCache
93 : {
94 : public:
95 : typedef ::formula::FormulaTokenRef TokenRef;
96 : typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef;
97 :
98 114 : struct TableName
99 : {
100 : OUString maUpperName;
101 : OUString maRealName;
102 :
103 : explicit TableName(const OUString& rUppper, const OUString& rReal);
104 : };
105 :
106 : struct CellFormat
107 : {
108 : bool mbIsSet;
109 : short mnType;
110 : sal_uLong mnIndex;
111 :
112 : explicit CellFormat();
113 : };
114 :
115 : private:
116 : /** individual cell within cached external ref table. */
117 2404 : struct Cell
118 : {
119 : TokenRef mxToken;
120 : sal_uLong mnFmtIndex;
121 : };
122 : typedef ::boost::unordered_map<SCCOL, Cell> RowDataType;
123 : typedef ::boost::unordered_map<SCROW, RowDataType> RowsDataType;
124 :
125 : public:
126 : // SUNWS needs a forward declared friend, otherwise types and members
127 : // of the outer class are not accessible.
128 : class Table;
129 : friend class ScExternalRefCache::Table;
130 :
131 : /**
132 : * Represents a single cached table in an external document. It only
133 : * stores non-empty cells; empty cells should never be stored in the data
134 : * cache. Instead, cached ranges should be used to determine whether or
135 : * not a cell is empty or needs fetching from the source document. If a
136 : * cell's value is not stored but its address is within the cached ranges,
137 : * that cell is already queried in the source document and we know it's
138 : * empty.
139 : */
140 : class Table
141 : {
142 : public:
143 :
144 : enum ReferencedFlag
145 : {
146 : UNREFERENCED,
147 : REFERENCED_MARKED, // marked as referenced during store to file
148 : REFERENCED_PERMANENT // permanently marked, e.g. from within interpreter
149 : };
150 :
151 : Table();
152 : ~Table();
153 :
154 : void clear();
155 :
156 : /**
157 : * Add cell value to the cache.
158 : *
159 : * @param bSetCacheRange if true, mark this cell 'cached'. This is
160 : * false _only when_ adding a range of cell
161 : * values, for performance reasons.
162 : */
163 : SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uLong nFmtIndex = 0, bool bSetCacheRange = true);
164 : SC_DLLPUBLIC TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
165 : bool hasRow( SCROW nRow ) const;
166 : /** Set/clear referenced status flag only if current status is not
167 : REFERENCED_PERMANENT. */
168 : void setReferenced( bool bReferenced );
169 : /// Unconditionally set the reference status flag.
170 : void setReferencedFlag( ReferencedFlag eFlag );
171 0 : ReferencedFlag getReferencedFlag() const { return meReferenced;}
172 : bool isReferenced() const;
173 : /// Obtain a sorted vector of rows.
174 : void getAllRows(::std::vector<SCROW>& rRows, SCROW nLow = 0, SCROW nHigh = MAXROW) const;
175 : /// Returns the half-open range of used rows in this table. Returns [0,0) if table is empty.
176 : SC_DLLPUBLIC ::std::pair< SCROW, SCROW > getRowRange() const;
177 : /// Obtain a sorted vector of columns.
178 : void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols, SCCOL nLow = 0, SCCOL nHigh = MAXCOL) const;
179 : /// Returns the half-open range of used columns in the specified row. Returns [0,0) if row is empty.
180 : SC_DLLPUBLIC ::std::pair< SCCOL, SCCOL > getColRange( SCROW nRow ) const;
181 : void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
182 : bool isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const;
183 :
184 : void setCachedCell(SCCOL nCol, SCROW nRow);
185 : void setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
186 :
187 : /**
188 : * Call this to mark the entire table "cached". This will prevent all
189 : * future attempts to access the source document even when non-cached
190 : * cells are queried. In such case, non-cached cells are treated as
191 : * empty cells. Useful when loading a document with own external data
192 : * cache.
193 : */
194 : SC_DLLPUBLIC void setWholeTableCached();
195 : private:
196 : bool isInCachedRanges(SCCOL nCol, SCROW nRow) const;
197 : TokenRef getEmptyOrNullToken(SCCOL nCol, SCROW nRow) const;
198 :
199 : private:
200 : /** Data cache */
201 : RowsDataType maRows;
202 : /** Collection of individual cached ranges. The table ranges are
203 : * not used & always zero. */
204 : ScRangeList maCachedRanges;
205 : ReferencedFlag meReferenced;
206 : };
207 :
208 : typedef ::boost::shared_ptr<Table> TableTypeRef;
209 : typedef ::boost::unordered_map< OUString, size_t, OUStringHash>
210 : TableNameIndexMap;
211 :
212 : ScExternalRefCache();
213 : ~ScExternalRefCache();
214 :
215 : const OUString* getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const;
216 : const OUString* getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const;
217 :
218 : /**
219 : * Get a cached cell data at specified cell location.
220 : *
221 : * @param nFileId file ID of an external document
222 : * @param rTabName sheet name
223 : * @param nCol
224 : * @param nRow
225 : *
226 : * @return pointer to the token instance in the cache.
227 : */
228 : ScExternalRefCache::TokenRef getCellData(
229 : sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex);
230 :
231 : /**
232 : * Get a cached cell range data.
233 : *
234 : * @return a new token array instance. Note that <i>the caller must
235 : * manage the life cycle of the returned instance</i>, which is
236 : * guaranteed if the TokenArrayRef is properly used..
237 : */
238 : ScExternalRefCache::TokenArrayRef getCellRangeData(
239 : sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange);
240 :
241 : ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const OUString& rName);
242 : void setRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, TokenArrayRef pArray);
243 : bool isValidRangeName(sal_uInt16 nFileId, const OUString& rName) const;
244 :
245 : void setCellData(sal_uInt16 nFileId, const OUString& rTabName,
246 : SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uLong nFmtIndex);
247 :
248 88 : struct SingleRangeData
249 : {
250 : /** This name must be in upper-case. */
251 : OUString maTableName;
252 : ScMatrixRef mpRangeData;
253 : };
254 : void setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const ::std::vector<SingleRangeData>& rData,
255 : const TokenArrayRef& pArray);
256 :
257 : bool isDocInitialized(sal_uInt16 nFileId);
258 : void initializeDoc(sal_uInt16 nFileId, const ::std::vector<OUString>& rTabNames);
259 : OUString getTableName(sal_uInt16 nFileId, size_t nCacheId) const;
260 : void getAllTableNames(sal_uInt16 nFileId, ::std::vector<OUString>& rTabNames) const;
261 : SCsTAB getTabSpan( sal_uInt16 nFileId, const OUString& rStartTabName, const OUString& rEndTabName ) const;
262 : void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
263 :
264 : /**
265 : * Set all tables of a document as referenced, used only during
266 : * store-to-file.
267 : * @returns <TRUE/> if ALL tables of ALL documents are marked.
268 : */
269 : bool setCacheDocReferenced( sal_uInt16 nFileId );
270 :
271 : /**
272 : * Set a table as referenced, used only during store-to-file.
273 : * @returns <TRUE/> if ALL tables of ALL documents are marked.
274 : */
275 : bool setCacheTableReferenced( sal_uInt16 nFileId, const OUString& rTabName, size_t nSheets, bool bPermanent );
276 : void setAllCacheTableReferencedStati( bool bReferenced );
277 0 : bool areAllCacheTablesReferenced() const { return maReferenced.mbAllReferenced;}
278 :
279 : /**
280 : * Collect all cached non-empty cell positions, inferred directly from the
281 : * cached data, not the cached range metadata stored separately in the
282 : * Table.
283 : */
284 : void getAllCachedDataSpans( sal_uInt16 nFileId, sc::ColumnSpanSet& rSet ) const;
285 :
286 : private:
287 732 : struct ReferencedStatus
288 : {
289 0 : struct DocReferenced
290 : {
291 : ::std::vector<bool> maTables;
292 : bool mbAllTablesReferenced;
293 : // Initially, documents have no tables but all referenced.
294 0 : DocReferenced() : mbAllTablesReferenced(true) {}
295 : };
296 : typedef ::std::vector<DocReferenced> DocReferencedVec;
297 :
298 : DocReferencedVec maDocs;
299 : bool mbAllReferenced;
300 :
301 : ReferencedStatus();
302 : void reset( size_t nDocs );
303 : void checkAllDocs();
304 :
305 : } maReferenced;
306 : void addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex );
307 : void addCacheDocToReferenced( sal_uInt16 nFileId );
308 : public:
309 :
310 : ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const;
311 : ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const OUString& rTabName, bool bCreateNew, size_t* pnIndex);
312 :
313 : /**
314 : * Clear all caches including the cache tables.
315 : */
316 : void clearCache(sal_uInt16 nFileId);
317 :
318 : /**
319 : * Clear all caches but keep the tables. All cache tables will be empty
320 : * after the call, but the tables will not be removed.
321 : */
322 : void clearCacheTables(sal_uInt16 nFileId);
323 :
324 : private:
325 : struct RangeHash
326 : {
327 34 : size_t operator()(const ScRange& rRange) const
328 : {
329 34 : const ScAddress& s = rRange.aStart;
330 34 : const ScAddress& e = rRange.aEnd;
331 34 : return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row();
332 : }
333 : };
334 :
335 : typedef ::boost::unordered_map<OUString, TokenArrayRef, OUStringHash> RangeNameMap;
336 : typedef ::boost::unordered_map<ScRange, TokenArrayRef, RangeHash> RangeArrayMap;
337 : typedef ::boost::unordered_map<OUString, OUString, OUStringHash> NamePairMap;
338 :
339 : // SUNWS needs a forward declared friend, otherwise types and members
340 : // of the outer class are not accessible.
341 : struct DocItem;
342 : friend struct ScExternalRefCache::DocItem;
343 :
344 : /** Represents data cached for a single external document. */
345 90 : struct DocItem
346 : {
347 : /** The raw cache tables. */
348 : ::std::vector<TableTypeRef> maTables;
349 : /** Table name list in correct order, in both upper- and real-case. */
350 : ::std::vector<TableName> maTableNames;
351 : /** Table name to index map. The names must be stored upper-case. */
352 : TableNameIndexMap maTableNameIndex;
353 : /** Range name cache. */
354 : RangeNameMap maRangeNames;
355 : /** Token array cache for cell ranges. */
356 : RangeArrayMap maRangeArrays;
357 : /** Upper- to real-case mapping for range names. */
358 : NamePairMap maRealRangeNameMap;
359 :
360 : bool mbInitFromSource;
361 :
362 18 : DocItem() : mbInitFromSource(false) {}
363 : };
364 : typedef ::boost::unordered_map<sal_uInt16, DocItem> DocDataType;
365 : DocItem* getDocItem(sal_uInt16 nFileId) const;
366 :
367 : private:
368 : mutable osl::Mutex maMtxDocs;
369 : mutable DocDataType maDocs;
370 : };
371 :
372 : class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelper, SfxListener
373 : {
374 : public:
375 :
376 : typedef ::std::set<ScFormulaCell*> RefCellSet;
377 : typedef ::boost::unordered_map<sal_uInt16, RefCellSet> RefCellMap;
378 :
379 : enum LinkUpdateType { LINK_MODIFIED, LINK_BROKEN };
380 :
381 : /**
382 : * Base class for objects that need to listen to link updates. When a
383 : * link to a certain external file is updated, the notify() method gets
384 : * called.
385 : */
386 : class LinkListener
387 : {
388 : public:
389 : LinkListener();
390 : virtual ~LinkListener() = 0;
391 : virtual void notify(sal_uInt16 nFileId, LinkUpdateType eType) = 0;
392 :
393 : struct Hash
394 : {
395 0 : size_t operator() (const LinkListener* p) const
396 : {
397 0 : return reinterpret_cast<size_t>(p);
398 : }
399 : };
400 : };
401 :
402 : /**
403 : * Use this guard when performing something from the API that might query
404 : * values from external references. Interpreting formula strings is one
405 : * such example.
406 : */
407 : class SC_DLLPUBLIC ApiGuard
408 : {
409 : public:
410 : ApiGuard(ScDocument* pDoc);
411 : ~ApiGuard();
412 : private:
413 : ScExternalRefManager* mpMgr;
414 : bool mbOldInteractionEnabled;
415 : };
416 :
417 : private:
418 : /** Shell instance for a source document. */
419 0 : struct SrcShell
420 : {
421 : SfxObjectShellRef maShell;
422 : tools::Time maLastAccess;
423 :
424 0 : SrcShell() : maLastAccess( tools::Time::SYSTEM ) {}
425 : };
426 :
427 : typedef ::boost::unordered_map<sal_uInt16, SrcShell> DocShellMap;
428 : typedef ::boost::unordered_map<sal_uInt16, bool> LinkedDocMap;
429 :
430 : typedef ::boost::unordered_map<sal_uInt16, SvNumberFormatterMergeMap> NumFmtMap;
431 :
432 : typedef ::boost::unordered_set<LinkListener*, LinkListener::Hash> LinkListeners;
433 : typedef ::boost::unordered_map<sal_uInt16, LinkListeners> LinkListenerMap;
434 :
435 : public:
436 : /** Source document meta-data container. */
437 92 : struct SrcFileData
438 : {
439 : OUString maFileName; /// original file name as loaded from the file.
440 : OUString maRealFileName; /// file name created from the relative name.
441 : OUString maRelativeName;
442 : OUString maFilterName;
443 : OUString maFilterOptions;
444 : bool bUnsaved;
445 :
446 : void maybeCreateRealFileName(const OUString& rOwnDocName);
447 : };
448 :
449 : public:
450 : explicit ScExternalRefManager(ScDocument* pDoc);
451 : virtual ~ScExternalRefManager();
452 :
453 : virtual OUString getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const SAL_OVERRIDE;
454 :
455 : /**
456 : * Get a cache table instance for specified table and table index. Unlike
457 : * the other method that takes a table name, this method does not create a
458 : * new table when a table is not available for specified index.
459 : *
460 : * @param nFileId file ID
461 : * @param nTabIndex cache table index
462 : *
463 : * @return shared_ptr to the cache table instance
464 : */
465 : ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const;
466 :
467 : /**
468 : * Get a cache table instance for specified file and table name. If the
469 : * table instance is not already present, it'll instantiate a new one and
470 : * append it to the end of the table array. <I>It's important to be
471 : * aware of this fact especially for multi-table ranges for which
472 : * table orders are critical.</I>
473 : *
474 : * Excel filter calls this method to populate the cache table from the
475 : * XCT/CRN records.
476 : *
477 : * @param nFileId file ID
478 : * @param rTabName table name
479 : * @param bCreateNew if true, create a new table instance if it's not
480 : * already present. If false, it returns NULL if the
481 : * specified table's cache doesn't exist.
482 : * @param pnIndex if non-NULL pointer is passed, it stores the internal
483 : * index of a cache table instance.
484 : *
485 : * @return shared_ptr to the cache table instance
486 : */
487 : ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const OUString& rTabName, bool bCreateNew, size_t* pnIndex = 0);
488 :
489 : /** Returns a vector containing all (real) table names and cache tables of
490 : the specified file.
491 :
492 : The index in the returned vector corresponds to the table index used to
493 : access the cache table, e.g. in getCacheTable().
494 : */
495 : void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<OUString>& rTabNames) const;
496 :
497 : /**
498 : * Get the span (distance+sign(distance)) of two sheets of a specified
499 : * file.
500 : *
501 : * @param nFileId file ID
502 : * @param rStartTabName name of first sheet (sheet1)
503 : * @param rEndTabName name of second sheet (sheet2)
504 : *
505 : * @return span
506 : * 1 if sheet2 == sheet1
507 : * > 1 if sheet2 > sheet1
508 : * < -1 if sheet2 < sheet1
509 : * -1 if nFileId or rStartTabName not found
510 : * 0 if rEndTabName not found
511 : */
512 : SCsTAB getCachedTabSpan(
513 : sal_uInt16 nFileId, const OUString& rStartTabName, const OUString& rEndTabName) const;
514 :
515 : /**
516 : * Get all unique number format indices that are used in the cache tables.
517 : * The retrieved indices are sorted in ascending order.
518 : *
519 : * @param rNumFmts (reference) all unique number format indices.
520 : */
521 : void getAllCachedNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
522 :
523 : sal_uInt16 getExternalFileCount() const;
524 :
525 : /**
526 : * Mark all tables as referenced that are used by any LinkListener, used
527 : * only during store-to-file.
528 : * @returns <TRUE/> if ALL tables of ALL external documents are marked.
529 : */
530 : bool markUsedByLinkListeners();
531 :
532 : bool markUsedExternalRefCells();
533 :
534 : /**
535 : * Set a table as referenced, used only during store-to-file.
536 : * @returns <TRUE/> if ALL tables of ALL external documents are marked.
537 : */
538 : bool setCacheTableReferenced( sal_uInt16 nFileId, const OUString& rTabName, size_t nSheets );
539 : void setAllCacheTableReferencedStati( bool bReferenced );
540 :
541 : /**
542 : * @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called,
543 : * <FALSE/> if setAllCacheTableReferencedStati(true) was called.
544 : */
545 140 : bool isInReferenceMarking() const { return mbInReferenceMarking; }
546 :
547 : void storeRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, const ScTokenArray& rArray);
548 :
549 : ScExternalRefCache::TokenRef getSingleRefToken(
550 : sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell,
551 : const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt = NULL);
552 :
553 : /**
554 : * Get an array of tokens that consist of the specified external cell
555 : * range.
556 : *
557 : * @param nFileId file ID for an external document
558 : * @param rTabName referenced sheet name
559 : * @param rRange referenced cell range
560 : * @param pCurPos current cursor position to keep track of cells that
561 : * reference an external data.
562 : *
563 : * @return shared_ptr to a token array instance. <i>The caller must not
564 : * delete the instance returned by this method.</i>
565 : */
566 : ScExternalRefCache::TokenArrayRef getDoubleRefTokens(
567 : sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange, const ScAddress* pCurPos);
568 :
569 : /**
570 : * Get an array of tokens corresponding with a specified name in a
571 : * specified file.
572 : *
573 : * @param pCurPos currnet cell address where this name token is used.
574 : * This is purely to keep track of all cells containing
575 : * external names for refreshing purposes. If this is
576 : * NULL, then the cell will not be added to the list.
577 : *
578 : * @return shared_ptr to array of tokens composing the name
579 : */
580 : ScExternalRefCache::TokenArrayRef getRangeNameTokens(
581 : sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos = NULL);
582 :
583 : bool isValidRangeName(sal_uInt16 nFileId, const OUString& rName);
584 :
585 : OUString getOwnDocumentName() const;
586 : bool isOwnDocument(const OUString& rFile) const;
587 :
588 : /**
589 : * Takes a flat file name, and convert it to an absolute URL path. An
590 : * absolute URL path begines with 'file:///.
591 : *
592 : * @param rFile file name to convert
593 : */
594 : void convertToAbsName(OUString& rFile) const;
595 : sal_uInt16 getExternalFileId(const OUString& rFile);
596 :
597 : /**
598 : * It returns a pointer to the name of the URI associated with a given
599 : * external file ID. In case the original document has moved, it returns
600 : * an URI adjusted for the relocation.
601 : *
602 : * @param nFileId file ID for an external document
603 : * @param bForceOriginal If true, it always returns the original document
604 : * URI even if the referring document has relocated.
605 : * If false, it returns an URI adjusted for
606 : * relocated document.
607 : *
608 : * @return const OUString* external document URI.
609 : */
610 : const OUString* getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal = false);
611 :
612 : /**
613 : * Get all cached external file names as an array. Array indices of the
614 : * returned name array correspond with external file ID's.
615 : */
616 : std::vector<OUString> getAllCachedExternalFileNames() const;
617 :
618 : bool hasExternalFile(sal_uInt16 nFileId) const;
619 : bool hasExternalFile(const OUString& rFile) const;
620 : const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
621 :
622 : const OUString* getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const;
623 : const OUString* getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const;
624 : void clearCache(sal_uInt16 nFileId);
625 : bool refreshSrcDocument(sal_uInt16 nFileId);
626 : void breakLink(sal_uInt16 nFileId);
627 : void switchSrcFile(sal_uInt16 nFileId, const OUString& rNewFile, const OUString& rNewFilter);
628 :
629 : /**
630 : * Set a relative file path for the specified file ID. Note that the
631 : * caller must ensure that the passed URL is a valid relative URL.
632 : *
633 : * @param nFileId file ID for an external document
634 : * @param rRelUrl relative URL
635 : */
636 : void setRelativeFileName(sal_uInt16 nFileId, const OUString& rRelUrl);
637 :
638 : /**
639 : * Set the filter name and options if any for a given source document.
640 : * These values get reset when the source document ever gets reloaded.
641 : *
642 : * @param nFileId
643 : * @param rFilterName
644 : * @param rOptions
645 : */
646 : void setFilterData(sal_uInt16 nFileId, const OUString& rFilterName, const OUString& rOptions);
647 :
648 : void clear();
649 :
650 : bool hasExternalData() const;
651 :
652 : /**
653 : * Re-generates relative names for all stored source files. This is
654 : * necessary when exporting to an ods document, to ensure that all source
655 : * files have their respective relative names for xlink:href export.
656 : *
657 : * @param rBaseFileUrl Absolute URL of the content.xml fragment of the
658 : * document being exported.
659 : */
660 : void resetSrcFileData(const OUString& rBaseFileUrl);
661 :
662 : /**
663 : * Replace the original URL wirh the real URL that was generated from the relative URL.
664 : */
665 : void updateAbsAfterLoad();
666 :
667 : /**
668 : * Stop tracking a specific formula cell.
669 : *
670 : * @param pCell pointer to cell that formerly contained external
671 : * reference.
672 : */
673 : void removeRefCell(ScFormulaCell* pCell);
674 :
675 : /**
676 : * Register a new link listener to a specified external document. Note
677 : * that the caller is responsible for managing the life cycle of the
678 : * listener object.
679 : */
680 : void addLinkListener(sal_uInt16 nFileId, LinkListener* pListener);
681 :
682 : /**
683 : * Remove an existing link listener. Note that removing a listener
684 : * pointer here does not delete the listener object instance.
685 : */
686 : void removeLinkListener(sal_uInt16 nFileId, LinkListener* pListener);
687 :
688 : void removeLinkListener(LinkListener* pListener);
689 :
690 : /**
691 : * Notify all listeners that are listening to a specified external
692 : * document.
693 : *
694 : * @param nFileId file ID for an external document.
695 : */
696 : void notifyAllLinkListeners(sal_uInt16 nFileId, LinkUpdateType eType);
697 :
698 : /**
699 : * Check if the file specified by the path is a legitimate file that
700 : * exists & can be loaded.
701 : */
702 : bool isFileLoadable(const OUString& rFile) const;
703 :
704 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
705 :
706 : /**
707 : * If we still contain unsaved files we should warn the user before saving
708 : *
709 : * @return true if the document still contains references to an unsaved file
710 : */
711 4 : bool containsUnsavedReferences() const { return !maUnsavedDocShells.empty(); }
712 :
713 : void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell);
714 :
715 : void enableDocTimer( bool bEnable );
716 :
717 : private:
718 : ScExternalRefManager();
719 : ScExternalRefManager(const ScExternalRefManager&);
720 :
721 : void refreshAllRefCells(sal_uInt16 nFileId);
722 :
723 : void fillCellFormat(sal_uLong nFmtIndex, ScExternalRefCache::CellFormat* pFmt) const;
724 :
725 : ScExternalRefCache::TokenRef getSingleRefTokenFromSrcDoc(
726 : sal_uInt16 nFileId, ScDocument* pSrcDoc, const ScAddress& rPos,
727 : ScExternalRefCache::CellFormat* pFmt);
728 :
729 : /**
730 : * Retrieve a range token array from a source document instance.
731 : *
732 : * @param pSrcDoc pointer to the source document instance.
733 : * @param rTabName name of the first table.
734 : * @param rRange range specified. Upon successful retrieval, this range
735 : * gets modified to contain the correct table IDs, and in
736 : * case the range is larger than the data area of the source
737 : * document, it gets reduced to the data area.
738 : * @param rCacheData an array of structs, with each struct containing the
739 : * table name and the data in the specified range.
740 : *
741 : * @return range token array
742 : */
743 : ScExternalRefCache::TokenArrayRef getDoubleRefTokensFromSrcDoc(
744 : ScDocument* pSrcDoc, const OUString& rTabName, ScRange& rRange,
745 : ::std::vector<ScExternalRefCache::SingleRangeData>& rCacheData);
746 :
747 : /**
748 : * Retrieve range name token array from a source document instance.
749 : *
750 : * @param nFileId file ID of the source document.
751 : * @param pSrcDoc pointer to the source document instance
752 : * @param rName range name to retrieve. Note that the range name lookup
753 : * is case <i>in</i>-sensitive, and upon successful retrieval
754 : * of the range name array, this name gets updated to the
755 : * actual range name with the correct casing.
756 : *
757 : * @return range name token array
758 : */
759 : ScExternalRefCache::TokenArrayRef getRangeNameTokensFromSrcDoc(
760 : sal_uInt16 nFileId, ScDocument* pSrcDoc, OUString& rName);
761 :
762 : ScDocument* getInMemorySrcDocument(sal_uInt16 nFileId);
763 : ScDocument* getSrcDocument(sal_uInt16 nFileId);
764 : SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, OUString& rFilter);
765 :
766 : /**
767 : * Caller must ensure that the passed shell is not already stored.
768 : */
769 : ScDocument& cacheNewDocShell( sal_uInt16 nFileId, SrcShell& rSrcShell );
770 :
771 : void maybeLinkExternalFile(sal_uInt16 nFileId);
772 :
773 : /**
774 : * Try to create a "real" file name from the relative path. The original
775 : * file name may not point to the real document when the referencing and
776 : * referenced documents have been moved.
777 : *
778 : * For the real file name to be created, the relative name should not be
779 : * empty before calling this method, or the real file name will not be
780 : * created.
781 : *
782 : * @param nFileId file ID for an external document
783 : */
784 : void maybeCreateRealFileName(sal_uInt16 nFileId);
785 :
786 : /**
787 : * Purge those source document instances that have not been accessed for
788 : * the specified duration.
789 : *
790 : * @param nTimeOut time out value in 100th of a second
791 : */
792 : void purgeStaleSrcDocument(sal_Int32 nTimeOut);
793 :
794 : sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc);
795 :
796 : /**
797 : * If in maUnsavedDocShells move it to maDocShells and create a correct
798 : * external reference entry
799 : *
800 : * @param Pointer to the newly saved DocumentShell
801 : */
802 : void transformUnsavedRefToSavedRef( SfxObjectShell* pShell );
803 :
804 : private:
805 : ScDocument* mpDoc;
806 :
807 : /** cache of referenced ranges and names from source documents. */
808 : ScExternalRefCache maRefCache;
809 :
810 : /**
811 : * Source document cache. This stores the original source document shell
812 : * instances. They get purged after a certain period of time.
813 : */
814 : DocShellMap maDocShells;
815 :
816 : /**
817 : * DocShells to unsaved but referenced documents. If not empty ask before saving!
818 : * Move to maDocShells if document referenced here is saved
819 : */
820 : DocShellMap maUnsavedDocShells;
821 :
822 : /** list of source documents that are managed by the link manager. */
823 : LinkedDocMap maLinkedDocs;
824 :
825 : /**
826 : * List of referencing cells that may contain external names. There is
827 : * one list per source document.
828 : */
829 : RefCellMap maRefCells;
830 :
831 : LinkListenerMap maLinkListeners;
832 :
833 : NumFmtMap maNumFormatMap;
834 :
835 : /**
836 : * List of external source document meta-data, used to keep track of
837 : * external document identifiers.
838 : */
839 : std::vector<SrcFileData> maSrcFiles;
840 :
841 : /** Status whether in reference marking state. See isInReferenceMarking(). */
842 : bool mbInReferenceMarking:1;
843 :
844 : /**
845 : * Controls whether or not to allow user interaction. We don't want any
846 : * user interaction when calling from the API.
847 : */
848 : bool mbUserInteractionEnabled:1;
849 :
850 : bool mbDocTimerEnabled:1;
851 :
852 : AutoTimer maSrcDocTimer;
853 : DECL_LINK(TimeOutHdl, AutoTimer*);
854 : };
855 :
856 : #endif
857 :
858 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|