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