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