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 :
21 : #include <unotools/transliterationwrapper.hxx>
22 :
23 : #include "dbdata.hxx"
24 : #include "globalnames.hxx"
25 : #include "refupdat.hxx"
26 : #include "rechead.hxx"
27 : #include "document.hxx"
28 : #include "queryparam.hxx"
29 : #include "queryentry.hxx"
30 : #include "globstr.hrc"
31 : #include "subtotalparam.hxx"
32 : #include "sortparam.hxx"
33 :
34 : #include <memory>
35 :
36 : using ::std::auto_ptr;
37 : using ::std::unary_function;
38 : using ::std::for_each;
39 : using ::std::find_if;
40 : using ::std::remove_if;
41 : using ::std::pair;
42 :
43 : //---------------------------------------------------------------------------------------
44 :
45 3 : bool ScDBData::less::operator() (const ScDBData& left, const ScDBData& right) const
46 : {
47 3 : return ScGlobal::GetpTransliteration()->compareString(left.GetUpperName(), right.GetUpperName()) < 0;
48 : }
49 :
50 13 : ScDBData::ScDBData( const ::rtl::OUString& rName,
51 : SCTAB nTab,
52 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
53 : bool bByR, bool bHasH) :
54 13 : mpSortParam(new ScSortParam),
55 13 : mpQueryParam(new ScQueryParam),
56 13 : mpSubTotal(new ScSubTotalParam),
57 13 : mpImportParam(new ScImportParam),
58 : aName (rName),
59 : aUpper (rName),
60 : nTable (nTab),
61 : nStartCol (nCol1),
62 : nStartRow (nRow1),
63 : nEndCol (nCol2),
64 : nEndRow (nRow2),
65 : bByRow (bByR),
66 : bHasHeader (bHasH),
67 : bDoSize (false),
68 : bKeepFmt (false),
69 : bStripData (false),
70 : bIsAdvanced (false),
71 : bDBSelection(false),
72 : nIndex (0),
73 : bAutoFilter (false),
74 65 : bModified (false)
75 : {
76 13 : aUpper = ScGlobal::pCharClass->uppercase(aUpper);
77 13 : }
78 :
79 8 : ScDBData::ScDBData( const ScDBData& rData ) :
80 : ScRefreshTimer ( rData ),
81 16 : mpSortParam(new ScSortParam(*rData.mpSortParam)),
82 16 : mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
83 16 : mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
84 16 : mpImportParam(new ScImportParam(*rData.mpImportParam)),
85 : aName (rData.aName),
86 : aUpper (rData.aUpper),
87 : nTable (rData.nTable),
88 : nStartCol (rData.nStartCol),
89 : nStartRow (rData.nStartRow),
90 : nEndCol (rData.nEndCol),
91 : nEndRow (rData.nEndRow),
92 : bByRow (rData.bByRow),
93 : bHasHeader (rData.bHasHeader),
94 : bDoSize (rData.bDoSize),
95 : bKeepFmt (rData.bKeepFmt),
96 : bStripData (rData.bStripData),
97 : bIsAdvanced (rData.bIsAdvanced),
98 : aAdvSource (rData.aAdvSource),
99 : bDBSelection (rData.bDBSelection),
100 : nIndex (rData.nIndex),
101 : bAutoFilter (rData.bAutoFilter),
102 72 : bModified (rData.bModified)
103 : {
104 8 : }
105 :
106 0 : ScDBData::ScDBData( const ::rtl::OUString& rName, const ScDBData& rData ) :
107 : ScRefreshTimer ( rData ),
108 0 : mpSortParam(new ScSortParam(*rData.mpSortParam)),
109 0 : mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
110 0 : mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
111 0 : mpImportParam(new ScImportParam(*rData.mpImportParam)),
112 : aName (rName),
113 : aUpper (rName),
114 : nTable (rData.nTable),
115 : nStartCol (rData.nStartCol),
116 : nStartRow (rData.nStartRow),
117 : nEndCol (rData.nEndCol),
118 : nEndRow (rData.nEndRow),
119 : bByRow (rData.bByRow),
120 : bHasHeader (rData.bHasHeader),
121 : bDoSize (rData.bDoSize),
122 : bKeepFmt (rData.bKeepFmt),
123 : bStripData (rData.bStripData),
124 : bIsAdvanced (rData.bIsAdvanced),
125 : aAdvSource (rData.aAdvSource),
126 : bDBSelection (rData.bDBSelection),
127 : nIndex (rData.nIndex),
128 : bAutoFilter (rData.bAutoFilter),
129 0 : bModified (rData.bModified)
130 : {
131 0 : aUpper = ScGlobal::pCharClass->uppercase(aUpper);
132 0 : }
133 :
134 8 : ScDBData& ScDBData::operator= (const ScDBData& rData)
135 : {
136 : // Don't modify the name. The name is not mutable as it is used as a key
137 : // in the container to keep the db ranges sorted by the name.
138 8 : ScRefreshTimer::operator=( rData );
139 8 : mpSortParam.reset(new ScSortParam(*rData.mpSortParam));
140 8 : mpQueryParam.reset(new ScQueryParam(*rData.mpQueryParam));
141 8 : mpSubTotal.reset(new ScSubTotalParam(*rData.mpSubTotal));
142 8 : mpImportParam.reset(new ScImportParam(*rData.mpImportParam));
143 8 : nTable = rData.nTable;
144 8 : nStartCol = rData.nStartCol;
145 8 : nStartRow = rData.nStartRow;
146 8 : nEndCol = rData.nEndCol;
147 8 : nEndRow = rData.nEndRow;
148 8 : bByRow = rData.bByRow;
149 8 : bHasHeader = rData.bHasHeader;
150 8 : bDoSize = rData.bDoSize;
151 8 : bKeepFmt = rData.bKeepFmt;
152 8 : bStripData = rData.bStripData;
153 8 : bIsAdvanced = rData.bIsAdvanced;
154 8 : aAdvSource = rData.aAdvSource;
155 8 : bDBSelection = rData.bDBSelection;
156 8 : nIndex = rData.nIndex;
157 8 : bAutoFilter = rData.bAutoFilter;
158 :
159 8 : return *this;
160 : }
161 :
162 0 : bool ScDBData::operator== (const ScDBData& rData) const
163 : {
164 : // Daten, die nicht in den Params sind
165 :
166 0 : if ( nTable != rData.nTable ||
167 : bDoSize != rData.bDoSize ||
168 : bKeepFmt != rData.bKeepFmt ||
169 : bIsAdvanced!= rData.bIsAdvanced||
170 : bStripData != rData.bStripData ||
171 : // SAB: I think this should be here, but I don't want to break something
172 : // bAutoFilter!= rData.bAutoFilter||
173 0 : ScRefreshTimer::operator!=( rData )
174 : )
175 0 : return false;
176 :
177 0 : if ( bIsAdvanced && aAdvSource != rData.aAdvSource )
178 0 : return false;
179 :
180 0 : ScSortParam aSort1, aSort2;
181 0 : GetSortParam(aSort1);
182 0 : rData.GetSortParam(aSort2);
183 0 : if (!(aSort1 == aSort2))
184 0 : return false;
185 :
186 0 : ScQueryParam aQuery1, aQuery2;
187 0 : GetQueryParam(aQuery1);
188 0 : rData.GetQueryParam(aQuery2);
189 0 : if (!(aQuery1 == aQuery2))
190 0 : return false;
191 :
192 0 : ScSubTotalParam aSubTotal1, aSubTotal2;
193 0 : GetSubTotalParam(aSubTotal1);
194 0 : rData.GetSubTotalParam(aSubTotal2);
195 0 : if (!(aSubTotal1 == aSubTotal2))
196 0 : return false;
197 :
198 0 : ScImportParam aImport1, aImport2;
199 0 : GetImportParam(aImport1);
200 0 : rData.GetImportParam(aImport2);
201 0 : if (!(aImport1 == aImport2))
202 0 : return false;
203 :
204 0 : return true;
205 : }
206 :
207 52 : ScDBData::~ScDBData()
208 : {
209 20 : StopRefreshTimer();
210 32 : }
211 :
212 :
213 0 : ::rtl::OUString ScDBData::GetSourceString() const
214 : {
215 0 : ::rtl::OUStringBuffer aBuf;
216 0 : if (mpImportParam->bImport)
217 : {
218 0 : aBuf.append(mpImportParam->aDBName);
219 0 : aBuf.append(sal_Unicode('/'));
220 0 : aBuf.append(mpImportParam->aStatement);
221 : }
222 0 : return aBuf.makeStringAndClear();
223 : }
224 :
225 0 : ::rtl::OUString ScDBData::GetOperations() const
226 : {
227 0 : ::rtl::OUStringBuffer aBuf;
228 0 : if (mpQueryParam->GetEntryCount())
229 : {
230 0 : const ScQueryEntry& rEntry = mpQueryParam->GetEntry(0);
231 0 : if (rEntry.bDoQuery)
232 0 : aBuf.append(ScGlobal::GetRscString(STR_OPERATION_FILTER));
233 : }
234 :
235 0 : if (mpSortParam->maKeyState[0].bDoSort)
236 : {
237 0 : if (aBuf.getLength())
238 0 : aBuf.appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
239 0 : aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SORT));
240 : }
241 :
242 0 : if (mpSubTotal->bGroupActive[0] && !mpSubTotal->bRemoveOnly)
243 : {
244 0 : if (aBuf.getLength())
245 0 : aBuf.appendAscii(RTL_CONSTASCII_STRINGPARAM(", "));
246 0 : aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SUBTOTAL));
247 : }
248 :
249 0 : if (!aBuf.getLength())
250 0 : aBuf.append(ScGlobal::GetRscString(STR_OPERATION_NONE));
251 :
252 0 : return aBuf.makeStringAndClear();
253 : }
254 :
255 2 : void ScDBData::GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const
256 : {
257 2 : rTab = nTable;
258 2 : rCol1 = nStartCol;
259 2 : rRow1 = nStartRow;
260 2 : rCol2 = nEndCol;
261 2 : rRow2 = nEndRow;
262 2 : }
263 :
264 43 : void ScDBData::GetArea(ScRange& rRange) const
265 : {
266 43 : SCROW nNewEndRow = nEndRow;
267 43 : rRange = ScRange( nStartCol, nStartRow, nTable, nEndCol, nNewEndRow, nTable );
268 43 : }
269 :
270 0 : void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
271 : {
272 0 : nTable = nTab;
273 0 : nStartCol = nCol1;
274 0 : nStartRow = nRow1;
275 0 : nEndCol = nCol2;
276 0 : nEndRow = nRow2;
277 0 : }
278 :
279 0 : void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
280 : {
281 : sal_uInt16 i;
282 0 : long nDifX = ((long) nCol1) - ((long) nStartCol);
283 0 : long nDifY = ((long) nRow1) - ((long) nStartRow);
284 :
285 0 : long nSortDif = bByRow ? nDifX : nDifY;
286 0 : long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2);
287 :
288 0 : for (i=0; i<mpSortParam->GetSortKeyCount(); i++)
289 : {
290 0 : mpSortParam->maKeyState[i].nField += nSortDif;
291 0 : if (mpSortParam->maKeyState[i].nField > nSortEnd)
292 : {
293 0 : mpSortParam->maKeyState[i].nField = 0;
294 0 : mpSortParam->maKeyState[i].bDoSort = false;
295 : }
296 : }
297 :
298 0 : SCSIZE nCount = mpQueryParam->GetEntryCount();
299 0 : for (i = 0; i < nCount; ++i)
300 : {
301 0 : ScQueryEntry& rEntry = mpQueryParam->GetEntry(i);
302 0 : rEntry.nField += nDifX;
303 0 : if (rEntry.nField > nCol2)
304 : {
305 0 : rEntry.nField = 0;
306 0 : rEntry.bDoQuery = false;
307 : }
308 : }
309 0 : for (i=0; i<MAXSUBTOTAL; i++)
310 : {
311 0 : mpSubTotal->nField[i] = sal::static_int_cast<SCCOL>( mpSubTotal->nField[i] + nDifX );
312 0 : if (mpSubTotal->nField[i] > nCol2)
313 : {
314 0 : mpSubTotal->nField[i] = 0;
315 0 : mpSubTotal->bGroupActive[i] = false;
316 : }
317 : }
318 :
319 0 : SetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
320 0 : }
321 :
322 0 : void ScDBData::GetSortParam( ScSortParam& rSortParam ) const
323 : {
324 0 : rSortParam = *mpSortParam;
325 0 : rSortParam.nCol1 = nStartCol;
326 0 : rSortParam.nRow1 = nStartRow;
327 0 : rSortParam.nCol2 = nEndCol;
328 0 : rSortParam.nRow2 = nEndRow;
329 0 : rSortParam.bByRow = bByRow;
330 0 : rSortParam.bHasHeader = bHasHeader;
331 0 : }
332 :
333 0 : void ScDBData::SetSortParam( const ScSortParam& rSortParam )
334 : {
335 0 : mpSortParam.reset(new ScSortParam(rSortParam));
336 0 : bByRow = rSortParam.bByRow;
337 0 : }
338 :
339 9 : void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
340 : {
341 9 : rQueryParam = *mpQueryParam;
342 9 : rQueryParam.nCol1 = nStartCol;
343 9 : rQueryParam.nRow1 = nStartRow;
344 9 : rQueryParam.nCol2 = nEndCol;
345 9 : rQueryParam.nRow2 = nEndRow;
346 9 : rQueryParam.nTab = nTable;
347 9 : rQueryParam.bByRow = bByRow;
348 9 : rQueryParam.bHasHeader = bHasHeader;
349 9 : }
350 :
351 19 : void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
352 : {
353 19 : mpQueryParam.reset(new ScQueryParam(rQueryParam));
354 :
355 : // set bIsAdvanced to false for everything that is not from the
356 : // advanced filter dialog
357 19 : bIsAdvanced = false;
358 19 : }
359 :
360 7 : void ScDBData::SetAdvancedQuerySource(const ScRange* pSource)
361 : {
362 7 : if (pSource)
363 : {
364 0 : aAdvSource = *pSource;
365 0 : bIsAdvanced = true;
366 : }
367 : else
368 7 : bIsAdvanced = false;
369 7 : }
370 :
371 7 : bool ScDBData::GetAdvancedQuerySource(ScRange& rSource) const
372 : {
373 7 : rSource = aAdvSource;
374 7 : return bIsAdvanced;
375 : }
376 :
377 0 : void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
378 : {
379 0 : rSubTotalParam = *mpSubTotal;
380 :
381 : // Share the data range with the parent db data. The range in the subtotal
382 : // param struct is not used.
383 0 : rSubTotalParam.nCol1 = nStartCol;
384 0 : rSubTotalParam.nRow1 = nStartRow;
385 0 : rSubTotalParam.nCol2 = nEndCol;
386 0 : rSubTotalParam.nRow2 = nEndRow;
387 0 : }
388 :
389 0 : void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
390 : {
391 0 : mpSubTotal.reset(new ScSubTotalParam(rSubTotalParam));
392 0 : }
393 :
394 0 : void ScDBData::GetImportParam(ScImportParam& rImportParam) const
395 : {
396 0 : rImportParam = *mpImportParam;
397 : // set the range.
398 0 : rImportParam.nCol1 = nStartCol;
399 0 : rImportParam.nRow1 = nStartRow;
400 0 : rImportParam.nCol2 = nEndCol;
401 0 : rImportParam.nRow2 = nEndRow;
402 0 : }
403 :
404 4 : void ScDBData::SetImportParam(const ScImportParam& rImportParam)
405 : {
406 : // the range is ignored.
407 4 : mpImportParam.reset(new ScImportParam(rImportParam));
408 4 : }
409 :
410 0 : bool ScDBData::IsDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
411 : {
412 0 : if (nTab == nTable)
413 : {
414 0 : if ( bStartOnly )
415 0 : return ( nCol == nStartCol && nRow == nStartRow );
416 : else
417 : return ( nCol >= nStartCol && nCol <= nEndCol &&
418 0 : nRow >= nStartRow && nRow <= nEndRow );
419 : }
420 :
421 0 : return false;
422 : }
423 :
424 0 : bool ScDBData::IsDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
425 : {
426 : return (bool)((nTab == nTable)
427 : && (nCol1 == nStartCol) && (nRow1 == nStartRow)
428 0 : && (nCol2 == nEndCol) && (nRow2 == nEndRow));
429 : }
430 :
431 7 : bool ScDBData::HasImportParam() const
432 : {
433 7 : return mpImportParam && mpImportParam->bImport;
434 : }
435 :
436 0 : bool ScDBData::HasQueryParam() const
437 : {
438 0 : if (!mpQueryParam)
439 0 : return false;
440 :
441 0 : if (!mpQueryParam->GetEntryCount())
442 0 : return false;
443 :
444 0 : return mpQueryParam->GetEntry(0).bDoQuery;
445 : }
446 :
447 0 : bool ScDBData::HasSortParam() const
448 : {
449 : return mpSortParam &&
450 0 : !mpSortParam->maKeyState.empty() &&
451 0 : mpSortParam->maKeyState[0].bDoSort;
452 : }
453 :
454 0 : bool ScDBData::HasSubTotalParam() const
455 : {
456 0 : return mpSubTotal && mpSubTotal->bGroupActive[0];
457 : }
458 :
459 0 : void ScDBData::UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos)
460 : {
461 0 : ScRange aRange;
462 0 : GetArea( aRange );
463 0 : SCTAB nTab = aRange.aStart.Tab(); // hat nur eine Tabelle
464 :
465 : // anpassen wie die aktuelle Tabelle bei ScTablesHint (tabvwsh5.cxx)
466 :
467 0 : if ( nTab == nOldPos ) // verschobene Tabelle
468 0 : nTab = nNewPos;
469 0 : else if ( nOldPos < nNewPos ) // nach hinten verschoben
470 : {
471 0 : if ( nTab > nOldPos && nTab <= nNewPos ) // nachrueckender Bereich
472 0 : --nTab;
473 : }
474 : else // nach vorne verschoben
475 : {
476 0 : if ( nTab >= nNewPos && nTab < nOldPos ) // nachrueckender Bereich
477 0 : ++nTab;
478 : }
479 :
480 0 : bool bChanged = ( nTab != aRange.aStart.Tab() );
481 0 : if (bChanged)
482 0 : SetArea( nTab, aRange.aStart.Col(), aRange.aStart.Row(),
483 0 : aRange.aEnd.Col(),aRange.aEnd .Row() );
484 :
485 : // MoveTo ist nicht noetig, wenn nur die Tabelle geaendert ist
486 :
487 0 : SetModified(bChanged);
488 :
489 0 : }
490 :
491 0 : void ScDBData::UpdateReference(ScDocument* pDoc, UpdateRefMode eUpdateRefMode,
492 : SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
493 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
494 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz)
495 : {
496 : SCCOL theCol1;
497 : SCROW theRow1;
498 : SCTAB theTab1;
499 : SCCOL theCol2;
500 : SCROW theRow2;
501 : SCTAB theTab2;
502 0 : GetArea( theTab1, theCol1, theRow1, theCol2, theRow2 );
503 0 : theTab2 = theTab1;
504 :
505 : bool bDoUpdate = ScRefUpdate::Update( pDoc, eUpdateRefMode,
506 : nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
507 0 : theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) != UR_NOTHING;
508 0 : if (bDoUpdate)
509 0 : MoveTo( theTab1, theCol1, theRow1, theCol2, theRow2 );
510 :
511 0 : ScRange aRangeAdvSource;
512 0 : if ( GetAdvancedQuerySource(aRangeAdvSource) )
513 : {
514 0 : aRangeAdvSource.GetVars( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
515 0 : if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
516 : nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
517 0 : theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
518 : {
519 0 : aRangeAdvSource.aStart.Set( theCol1,theRow1,theTab1 );
520 0 : aRangeAdvSource.aEnd.Set( theCol2,theRow2,theTab2 );
521 0 : SetAdvancedQuerySource( &aRangeAdvSource );
522 :
523 0 : bDoUpdate = true; // DBData is modified
524 : }
525 : }
526 :
527 0 : SetModified(bDoUpdate);
528 :
529 : //! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!!
530 0 : }
531 :
532 0 : void ScDBData::ExtendDataArea(ScDocument* pDoc)
533 : {
534 : // Extend the DB area to include data rows immediately below.
535 : // or shrink it if all cells are empty
536 0 : pDoc->GetDataArea(nTable, nStartCol, nStartRow, nEndCol, nEndRow, false, true);
537 0 : }
538 :
539 : namespace {
540 :
541 : class FindByTable : public unary_function<ScDBData, bool>
542 : {
543 : SCTAB mnTab;
544 : public:
545 34 : FindByTable(SCTAB nTab) : mnTab(nTab) {}
546 :
547 0 : bool operator() (const ScDBData& r) const
548 : {
549 0 : ScRange aRange;
550 0 : r.GetArea(aRange);
551 0 : return aRange.aStart.Tab() == mnTab;
552 : }
553 : };
554 :
555 : class UpdateRefFunc : public unary_function<ScDBData, void>
556 : {
557 : ScDocument* mpDoc;
558 : UpdateRefMode meMode;
559 : SCCOL mnCol1;
560 : SCROW mnRow1;
561 : SCTAB mnTab1;
562 : SCCOL mnCol2;
563 : SCROW mnRow2;
564 : SCTAB mnTab2;
565 : SCsCOL mnDx;
566 : SCsROW mnDy;
567 : SCsTAB mnDz;
568 :
569 : public:
570 61 : UpdateRefFunc(ScDocument* pDoc, UpdateRefMode eMode,
571 : SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
572 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
573 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz) :
574 : mpDoc(pDoc), meMode(eMode),
575 : mnCol1(nCol1), mnRow1(nRow1), mnTab1(nTab1),
576 : mnCol2(nCol2), mnRow2(nRow2), mnTab2(nTab2),
577 61 : mnDx(nDx), mnDy(nDy), mnDz(nDz) {}
578 :
579 0 : void operator() (ScDBData& r)
580 : {
581 0 : r.UpdateReference(mpDoc, meMode, mnCol1, mnRow1, mnTab1, mnCol2, mnRow2, mnTab2, mnDx, mnDy, mnDz);
582 0 : }
583 : };
584 :
585 : class UpdateMoveTabFunc : public unary_function<ScDBData, void>
586 : {
587 : SCTAB mnOldTab;
588 : SCTAB mnNewTab;
589 : public:
590 5 : UpdateMoveTabFunc(SCTAB nOld, SCTAB nNew) : mnOldTab(nOld), mnNewTab(nNew) {}
591 0 : void operator() (ScDBData& r)
592 : {
593 0 : r.UpdateMoveTab(mnOldTab, mnNewTab);
594 0 : }
595 : };
596 :
597 : class FindByCursor : public unary_function<ScDBData, bool>
598 : {
599 : SCCOL mnCol;
600 : SCROW mnRow;
601 : SCTAB mnTab;
602 : bool mbStartOnly;
603 : public:
604 0 : FindByCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) :
605 0 : mnCol(nCol), mnRow(nRow), mnTab(nTab), mbStartOnly(bStartOnly) {}
606 :
607 0 : bool operator() (const ScDBData& r)
608 : {
609 0 : return r.IsDBAtCursor(mnCol, mnRow, mnTab, mbStartOnly);
610 : }
611 : };
612 :
613 : class FindByRange : public unary_function<ScDBData, bool>
614 : {
615 : const ScRange& mrRange;
616 : public:
617 0 : FindByRange(const ScRange& rRange) : mrRange(rRange) {}
618 :
619 0 : bool operator() (const ScDBData& r)
620 : {
621 : return r.IsDBAtArea(
622 0 : mrRange.aStart.Tab(), mrRange.aStart.Col(), mrRange.aStart.Row(), mrRange.aEnd.Col(), mrRange.aEnd.Row());
623 : }
624 : };
625 :
626 : class FindByIndex : public unary_function<ScDBData, bool>
627 : {
628 : sal_uInt16 mnIndex;
629 : public:
630 2 : FindByIndex(sal_uInt16 nIndex) : mnIndex(nIndex) {}
631 2 : bool operator() (const ScDBData& r) const
632 : {
633 2 : return r.GetIndex() == mnIndex;
634 : }
635 : };
636 :
637 : class FindByUpperName : public unary_function<ScDBData, bool>
638 : {
639 : const ::rtl::OUString& mrName;
640 : public:
641 11 : FindByUpperName(const ::rtl::OUString& rName) : mrName(rName) {}
642 5 : bool operator() (const ScDBData& r) const
643 : {
644 5 : return r.GetUpperName() == mrName;
645 : }
646 : };
647 :
648 : }
649 :
650 197 : ScDBCollection::NamedDBs::NamedDBs(ScDBCollection& rParent, ScDocument& rDoc) :
651 197 : mrParent(rParent), mrDoc(rDoc) {}
652 :
653 4 : ScDBCollection::NamedDBs::NamedDBs(const NamedDBs& r) :
654 4 : maDBs(r.maDBs), mrParent(r.mrParent), mrDoc(r.mrDoc) {}
655 :
656 111 : ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::begin()
657 : {
658 111 : return maDBs.begin();
659 : }
660 :
661 111 : ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::end()
662 : {
663 111 : return maDBs.end();
664 : }
665 :
666 2 : ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::begin() const
667 : {
668 2 : return maDBs.begin();
669 : }
670 :
671 2 : ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::end() const
672 : {
673 2 : return maDBs.end();
674 : }
675 :
676 2 : ScDBData* ScDBCollection::NamedDBs::findByIndex(sal_uInt16 nIndex)
677 : {
678 : DBsType::iterator itr = find_if(
679 2 : maDBs.begin(), maDBs.end(), FindByIndex(nIndex));
680 2 : return itr == maDBs.end() ? NULL : &(*itr);
681 : }
682 :
683 11 : ScDBData* ScDBCollection::NamedDBs::findByUpperName(const ::rtl::OUString& rName)
684 : {
685 : DBsType::iterator itr = find_if(
686 11 : maDBs.begin(), maDBs.end(), FindByUpperName(rName));
687 11 : return itr == maDBs.end() ? NULL : &(*itr);
688 : }
689 :
690 3 : bool ScDBCollection::NamedDBs::insert(ScDBData* p)
691 : {
692 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
693 3 : auto_ptr<ScDBData> pData(p);
694 : SAL_WNODEPRECATED_DECLARATIONS_POP
695 3 : if (!pData->GetIndex())
696 3 : pData->SetIndex(mrParent.nEntryIndex++);
697 :
698 3 : pair<DBsType::iterator, bool> r = maDBs.insert(pData);
699 :
700 3 : if (r.second && p->HasImportParam() && !p->HasImportSelection())
701 : {
702 0 : p->SetRefreshHandler(mrParent.GetRefreshHandler());
703 0 : p->SetRefreshControl(mrDoc.GetRefreshTimerControlAddress());
704 : }
705 3 : return r.second;
706 : }
707 :
708 0 : void ScDBCollection::NamedDBs::erase(iterator itr)
709 : {
710 0 : maDBs.erase(itr);
711 0 : }
712 :
713 0 : void ScDBCollection::NamedDBs::erase(const ScDBData& r)
714 : {
715 0 : maDBs.erase(r);
716 0 : }
717 :
718 2 : bool ScDBCollection::NamedDBs::empty() const
719 : {
720 2 : return maDBs.empty();
721 : }
722 :
723 2 : size_t ScDBCollection::NamedDBs::size() const
724 : {
725 2 : return maDBs.size();
726 : }
727 :
728 3 : bool ScDBCollection::NamedDBs::operator== (const NamedDBs& r) const
729 : {
730 3 : return maDBs == r.maDBs;
731 : }
732 :
733 100 : ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::begin()
734 : {
735 100 : return maDBs.begin();
736 : }
737 :
738 100 : ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::end()
739 : {
740 100 : return maDBs.end();
741 : }
742 :
743 0 : ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::begin() const
744 : {
745 0 : return maDBs.begin();
746 : }
747 :
748 0 : ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::end() const
749 : {
750 0 : return maDBs.end();
751 : }
752 :
753 0 : const ScDBData* ScDBCollection::AnonDBs::findAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
754 : {
755 : DBsType::const_iterator itr = find_if(
756 0 : maDBs.begin(), maDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
757 0 : return itr == maDBs.end() ? NULL : &(*itr);
758 : }
759 :
760 0 : const ScDBData* ScDBCollection::AnonDBs::findByRange(const ScRange& rRange) const
761 : {
762 : DBsType::const_iterator itr = find_if(
763 0 : maDBs.begin(), maDBs.end(), FindByRange(rRange));
764 0 : return itr == maDBs.end() ? NULL : &(*itr);
765 : }
766 :
767 0 : ScDBData* ScDBCollection::AnonDBs::getByRange(const ScRange& rRange)
768 : {
769 0 : const ScDBData* pData = findByRange(rRange);
770 0 : if (!pData)
771 : {
772 : // Insert a new db data. They all have identical names.
773 0 : rtl::OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME));
774 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
775 : ::std::auto_ptr<ScDBData> pNew(new ScDBData(
776 0 : aName, rRange.aStart.Tab(), rRange.aStart.Col(), rRange.aStart.Row(),
777 0 : rRange.aEnd.Col(), rRange.aEnd.Row(), true, false));
778 : SAL_WNODEPRECATED_DECLARATIONS_POP
779 0 : pData = pNew.get();
780 0 : maDBs.push_back(pNew);
781 : }
782 0 : return const_cast<ScDBData*>(pData);
783 : }
784 :
785 0 : void ScDBCollection::AnonDBs::insert(ScDBData* p)
786 : {
787 0 : rtl::OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME));
788 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
789 0 : ::std::auto_ptr<ScDBData> pNew(p);
790 : SAL_WNODEPRECATED_DECLARATIONS_POP
791 0 : maDBs.push_back(pNew);
792 0 : }
793 :
794 2 : bool ScDBCollection::AnonDBs::empty() const
795 : {
796 2 : return maDBs.empty();
797 : }
798 :
799 3 : bool ScDBCollection::AnonDBs::operator== (const AnonDBs& r) const
800 : {
801 3 : return maDBs == r.maDBs;
802 : }
803 :
804 197 : ScDBCollection::ScDBCollection(ScDocument* pDocument) :
805 197 : pDoc(pDocument), nEntryIndex(SC_START_INDEX_DB_COLL), maNamedDBs(*this, *pDocument) {}
806 :
807 4 : ScDBCollection::ScDBCollection(const ScDBCollection& r) :
808 4 : pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maNamedDBs(r.maNamedDBs), maAnonDBs(r.maAnonDBs) {}
809 :
810 31 : ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs()
811 : {
812 31 : return maNamedDBs;
813 : }
814 :
815 0 : const ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs() const
816 : {
817 0 : return maNamedDBs;
818 : }
819 :
820 2 : ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs()
821 : {
822 2 : return maAnonDBs;
823 : }
824 :
825 0 : const ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs() const
826 : {
827 0 : return maAnonDBs;
828 : }
829 :
830 0 : const ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly) const
831 : {
832 : // First, search the global named db ranges.
833 : NamedDBs::DBsType::const_iterator itr = find_if(
834 0 : maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
835 0 : if (itr != maNamedDBs.end())
836 0 : return &(*itr);
837 :
838 : // Check for the sheet-local anonymous db range.
839 0 : const ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
840 0 : if (pNoNameData)
841 0 : if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
842 0 : return pNoNameData;
843 :
844 : // Check the global anonymous db ranges.
845 0 : const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
846 0 : if (pData)
847 0 : return pData;
848 :
849 0 : return NULL;
850 : }
851 :
852 0 : ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly)
853 : {
854 : // First, search the global named db ranges.
855 : NamedDBs::DBsType::iterator itr = find_if(
856 0 : maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
857 0 : if (itr != maNamedDBs.end())
858 0 : return &(*itr);
859 :
860 : // Check for the sheet-local anonymous db range.
861 0 : ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
862 0 : if (pNoNameData)
863 0 : if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
864 0 : return pNoNameData;
865 :
866 : // Check the global anonymous db ranges.
867 0 : const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
868 0 : if (pData)
869 0 : return const_cast<ScDBData*>(pData);
870 :
871 0 : return NULL;
872 : }
873 :
874 0 : const ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
875 : {
876 : // First, search the global named db ranges.
877 0 : ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
878 : NamedDBs::DBsType::const_iterator itr = find_if(
879 0 : maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
880 0 : if (itr != maNamedDBs.end())
881 0 : return &(*itr);
882 :
883 : // Check for the sheet-local anonymous db range.
884 0 : ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
885 0 : if (pNoNameData)
886 0 : if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
887 0 : return pNoNameData;
888 :
889 : // Lastly, check the global anonymous db ranges.
890 0 : return maAnonDBs.findByRange(aRange);
891 : }
892 :
893 0 : ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
894 : {
895 : // First, search the global named db ranges.
896 0 : ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
897 : NamedDBs::DBsType::iterator itr = find_if(
898 0 : maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
899 0 : if (itr != maNamedDBs.end())
900 0 : return &(*itr);
901 :
902 : // Check for the sheet-local anonymous db range.
903 0 : ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
904 0 : if (pNoNameData)
905 0 : if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
906 0 : return pNoNameData;
907 :
908 : // Lastly, check the global anonymous db ranges.
909 0 : const ScDBData* pData = getAnonDBs().findByRange(aRange);
910 0 : if (pData)
911 0 : return const_cast<ScDBData*>(pData);
912 :
913 0 : return NULL;
914 : }
915 :
916 34 : void ScDBCollection::DeleteOnTab( SCTAB nTab )
917 : {
918 34 : FindByTable func(nTab);
919 : // First, collect the positions of all items that need to be deleted.
920 34 : ::std::vector<NamedDBs::DBsType::iterator> v;
921 : {
922 34 : NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
923 34 : for (; itr != itrEnd; ++itr)
924 : {
925 0 : if (func(*itr))
926 0 : v.push_back(itr);
927 : }
928 : }
929 :
930 : // Delete them all.
931 34 : ::std::vector<NamedDBs::DBsType::iterator>::iterator itr = v.begin(), itrEnd = v.end();
932 34 : for (; itr != itrEnd; ++itr)
933 0 : maNamedDBs.erase(*itr);
934 :
935 34 : remove_if(maAnonDBs.begin(), maAnonDBs.end(), func);
936 34 : }
937 :
938 61 : void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode,
939 : SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
940 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
941 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
942 : {
943 61 : ScDBData* pData = pDoc->GetAnonymousDBData(nTab1);
944 61 : if (pData)
945 : {
946 0 : if (nTab1 == nTab2 && nDz == 0)
947 : {
948 : pData->UpdateReference(
949 : pDoc, eUpdateRefMode,
950 0 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
951 : }
952 : else
953 : {
954 : //this will perhabs break undo
955 : }
956 : }
957 :
958 61 : UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
959 61 : for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
960 61 : for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
961 61 : }
962 :
963 :
964 5 : void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
965 : {
966 5 : UpdateMoveTabFunc func(nOldPos, nNewPos);
967 5 : for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
968 5 : for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
969 5 : }
970 :
971 0 : ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab )
972 : {
973 0 : ScDBData* pNearData = NULL;
974 0 : NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
975 0 : for (; itr != itrEnd; ++itr)
976 : {
977 : SCTAB nAreaTab;
978 : SCCOL nStartCol, nEndCol;
979 : SCROW nStartRow, nEndRow;
980 0 : itr->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
981 0 : if ( nTab == nAreaTab && nCol+1 >= nStartCol && nCol <= nEndCol+1 &&
982 : nRow+1 >= nStartRow && nRow <= nEndRow+1 )
983 : {
984 0 : if ( nCol < nStartCol || nCol > nEndCol || nRow < nStartRow || nRow > nEndRow )
985 : {
986 0 : if (!pNearData)
987 0 : pNearData = &(*itr); // ersten angrenzenden Bereich merken
988 : }
989 : else
990 0 : return &(*itr); // nicht "unbenannt" und Cursor steht wirklich drin
991 : }
992 : }
993 0 : if (pNearData)
994 0 : return pNearData; // angrenzender, wenn nichts direkt getroffen
995 0 : return pDoc->GetAnonymousDBData(nTab); // "unbenannt" nur zurueck, wenn sonst nichts gefunden
996 : }
997 :
998 0 : bool ScDBCollection::empty() const
999 : {
1000 0 : return maNamedDBs.empty() && maAnonDBs.empty();
1001 : }
1002 :
1003 3 : bool ScDBCollection::operator== (const ScDBCollection& r) const
1004 : {
1005 6 : return maNamedDBs == r.maNamedDBs && maAnonDBs == r.maAnonDBs &&
1006 6 : nEntryIndex == r.nEntryIndex && pDoc == r.pDoc && aRefreshHandler == r.aRefreshHandler;
1007 : }
1008 :
1009 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|