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 0 : bool ScDBData::less::operator() (const ScDBData& left, const ScDBData& right) const
43 : {
44 0 : return ScGlobal::GetpTransliteration()->compareString(left.GetUpperName(), right.GetUpperName()) < 0;
45 : }
46 :
47 0 : ScDBData::ScDBData( const OUString& rName,
48 : SCTAB nTab,
49 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
50 : bool bByR, bool bHasH) :
51 0 : mpSortParam(new ScSortParam),
52 0 : mpQueryParam(new ScQueryParam),
53 0 : mpSubTotal(new ScSubTotalParam),
54 0 : 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 0 : bModified (false)
72 : {
73 0 : aUpper = ScGlobal::pCharClass->uppercase(aUpper);
74 0 : }
75 :
76 0 : ScDBData::ScDBData( const ScDBData& rData ) :
77 : ScRefreshTimer ( rData ),
78 0 : mpSortParam(new ScSortParam(*rData.mpSortParam)),
79 0 : mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
80 0 : mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
81 0 : 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 0 : bModified (rData.bModified)
100 : {
101 0 : }
102 :
103 0 : ScDBData::ScDBData( const OUString& rName, const ScDBData& rData ) :
104 : ScRefreshTimer ( rData ),
105 0 : mpSortParam(new ScSortParam(*rData.mpSortParam)),
106 0 : mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
107 0 : mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
108 0 : 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 0 : bModified (rData.bModified)
127 : {
128 0 : aUpper = ScGlobal::pCharClass->uppercase(aUpper);
129 0 : }
130 :
131 0 : 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 0 : ScRefreshTimer::operator=( rData );
136 0 : mpSortParam.reset(new ScSortParam(*rData.mpSortParam));
137 0 : mpQueryParam.reset(new ScQueryParam(*rData.mpQueryParam));
138 0 : mpSubTotal.reset(new ScSubTotalParam(*rData.mpSubTotal));
139 0 : mpImportParam.reset(new ScImportParam(*rData.mpImportParam));
140 0 : nTable = rData.nTable;
141 0 : nStartCol = rData.nStartCol;
142 0 : nStartRow = rData.nStartRow;
143 0 : nEndCol = rData.nEndCol;
144 0 : nEndRow = rData.nEndRow;
145 0 : bByRow = rData.bByRow;
146 0 : bHasHeader = rData.bHasHeader;
147 0 : bDoSize = rData.bDoSize;
148 0 : bKeepFmt = rData.bKeepFmt;
149 0 : bStripData = rData.bStripData;
150 0 : bIsAdvanced = rData.bIsAdvanced;
151 0 : aAdvSource = rData.aAdvSource;
152 0 : bDBSelection = rData.bDBSelection;
153 0 : nIndex = rData.nIndex;
154 0 : bAutoFilter = rData.bAutoFilter;
155 :
156 0 : 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 0 : ScDBData::~ScDBData()
205 : {
206 0 : StopRefreshTimer();
207 0 : }
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 0 : void ScDBData::GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const
252 : {
253 0 : rTab = nTable;
254 0 : rCol1 = nStartCol;
255 0 : rRow1 = nStartRow;
256 0 : rCol2 = nEndCol;
257 0 : rRow2 = nEndRow;
258 0 : }
259 :
260 0 : void ScDBData::GetArea(ScRange& rRange) const
261 : {
262 0 : SCROW nNewEndRow = nEndRow;
263 0 : rRange = ScRange( nStartCol, nStartRow, nTable, nEndCol, nNewEndRow, nTable );
264 0 : }
265 :
266 0 : void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
267 : {
268 0 : nTable = nTab;
269 0 : nStartCol = nCol1;
270 0 : nStartRow = nRow1;
271 0 : nEndCol = nCol2;
272 0 : nEndRow = nRow2;
273 0 : }
274 :
275 0 : void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
276 : {
277 : sal_uInt16 i;
278 0 : long nDifX = ((long) nCol1) - ((long) nStartCol);
279 0 : long nDifY = ((long) nRow1) - ((long) nStartRow);
280 :
281 0 : long nSortDif = bByRow ? nDifX : nDifY;
282 0 : long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2);
283 :
284 0 : for (i=0; i<mpSortParam->GetSortKeyCount(); i++)
285 : {
286 0 : mpSortParam->maKeyState[i].nField += nSortDif;
287 0 : 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 0 : SCSIZE nCount = mpQueryParam->GetEntryCount();
295 0 : for (i = 0; i < nCount; ++i)
296 : {
297 0 : ScQueryEntry& rEntry = mpQueryParam->GetEntry(i);
298 0 : rEntry.nField += nDifX;
299 0 : if (rEntry.nField > nCol2)
300 : {
301 0 : rEntry.nField = 0;
302 0 : rEntry.bDoQuery = false;
303 : }
304 : }
305 0 : for (i=0; i<MAXSUBTOTAL; i++)
306 : {
307 0 : mpSubTotal->nField[i] = sal::static_int_cast<SCCOL>( mpSubTotal->nField[i] + nDifX );
308 0 : if (mpSubTotal->nField[i] > nCol2)
309 : {
310 0 : mpSubTotal->nField[i] = 0;
311 0 : mpSubTotal->bGroupActive[i] = false;
312 : }
313 : }
314 :
315 0 : SetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
316 0 : }
317 :
318 0 : void ScDBData::GetSortParam( ScSortParam& rSortParam ) const
319 : {
320 0 : rSortParam = *mpSortParam;
321 0 : rSortParam.nCol1 = nStartCol;
322 0 : rSortParam.nRow1 = nStartRow;
323 0 : rSortParam.nCol2 = nEndCol;
324 0 : rSortParam.nRow2 = nEndRow;
325 0 : rSortParam.bByRow = bByRow;
326 0 : rSortParam.bHasHeader = bHasHeader;
327 0 : }
328 :
329 0 : void ScDBData::SetSortParam( const ScSortParam& rSortParam )
330 : {
331 0 : mpSortParam.reset(new ScSortParam(rSortParam));
332 0 : bByRow = rSortParam.bByRow;
333 0 : }
334 :
335 0 : void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
336 : {
337 0 : rQueryParam = *mpQueryParam;
338 0 : rQueryParam.nCol1 = nStartCol;
339 0 : rQueryParam.nRow1 = nStartRow;
340 0 : rQueryParam.nCol2 = nEndCol;
341 0 : rQueryParam.nRow2 = nEndRow;
342 0 : rQueryParam.nTab = nTable;
343 0 : rQueryParam.bByRow = bByRow;
344 0 : rQueryParam.bHasHeader = bHasHeader;
345 0 : }
346 :
347 0 : void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
348 : {
349 0 : mpQueryParam.reset(new ScQueryParam(rQueryParam));
350 :
351 : // set bIsAdvanced to false for everything that is not from the
352 : // advanced filter dialog
353 0 : bIsAdvanced = false;
354 0 : }
355 :
356 0 : void ScDBData::SetAdvancedQuerySource(const ScRange* pSource)
357 : {
358 0 : if (pSource)
359 : {
360 0 : aAdvSource = *pSource;
361 0 : bIsAdvanced = true;
362 : }
363 : else
364 0 : bIsAdvanced = false;
365 0 : }
366 :
367 0 : bool ScDBData::GetAdvancedQuerySource(ScRange& rSource) const
368 : {
369 0 : rSource = aAdvSource;
370 0 : return bIsAdvanced;
371 : }
372 :
373 0 : void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
374 : {
375 0 : 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 0 : rSubTotalParam.nCol1 = nStartCol;
380 0 : rSubTotalParam.nRow1 = nStartRow;
381 0 : rSubTotalParam.nCol2 = nEndCol;
382 0 : rSubTotalParam.nRow2 = nEndRow;
383 0 : }
384 :
385 0 : void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
386 : {
387 0 : mpSubTotal.reset(new ScSubTotalParam(rSubTotalParam));
388 0 : }
389 :
390 0 : void ScDBData::GetImportParam(ScImportParam& rImportParam) const
391 : {
392 0 : rImportParam = *mpImportParam;
393 : // set the range.
394 0 : rImportParam.nCol1 = nStartCol;
395 0 : rImportParam.nRow1 = nStartRow;
396 0 : rImportParam.nCol2 = nEndCol;
397 0 : rImportParam.nRow2 = nEndRow;
398 0 : }
399 :
400 0 : void ScDBData::SetImportParam(const ScImportParam& rImportParam)
401 : {
402 : // the range is ignored.
403 0 : mpImportParam.reset(new ScImportParam(rImportParam));
404 0 : }
405 :
406 0 : bool ScDBData::IsDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
407 : {
408 0 : if (nTab == nTable)
409 : {
410 0 : if ( bStartOnly )
411 0 : return ( nCol == nStartCol && nRow == nStartRow );
412 : else
413 0 : return ( nCol >= nStartCol && nCol <= nEndCol &&
414 0 : nRow >= nStartRow && nRow <= nEndRow );
415 : }
416 :
417 0 : return false;
418 : }
419 :
420 0 : bool ScDBData::IsDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
421 : {
422 0 : return (bool)((nTab == nTable)
423 0 : && (nCol1 == nStartCol) && (nRow1 == nStartRow)
424 0 : && (nCol2 == nEndCol) && (nRow2 == nEndRow));
425 : }
426 :
427 0 : bool ScDBData::HasImportParam() const
428 : {
429 0 : 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 0 : 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 0 : GetArea( theTab1, theCol1, theRow1, theCol2, theRow2 );
499 0 : theTab2 = theTab1;
500 :
501 : bool bDoUpdate = ScRefUpdate::Update( pDoc, eUpdateRefMode,
502 : nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
503 0 : theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) != UR_NOTHING;
504 0 : if (bDoUpdate)
505 0 : MoveTo( theTab1, theCol1, theRow1, theCol2, theRow2 );
506 :
507 0 : ScRange aRangeAdvSource;
508 0 : 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 0 : SetModified(bDoUpdate);
524 :
525 : //! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!!
526 0 : }
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 0 : FindByTable(SCTAB nTab) : mnTab(nTab) {}
542 :
543 0 : bool operator() (const ScDBData& r) const
544 : {
545 0 : ScRange aRange;
546 0 : r.GetArea(aRange);
547 0 : 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 0 : 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 0 : mnDx(nDx), mnDy(nDy), mnDz(nDz) {}
574 :
575 0 : void operator() (ScDBData& r)
576 : {
577 0 : r.UpdateReference(mpDoc, meMode, mnCol1, mnRow1, mnTab1, mnCol2, mnRow2, mnTab2, mnDx, mnDy, mnDz);
578 0 : }
579 : };
580 :
581 : class UpdateMoveTabFunc : public unary_function<ScDBData, void>
582 : {
583 : SCTAB mnOldTab;
584 : SCTAB mnNewTab;
585 : public:
586 0 : 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 0 : FindByCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) :
601 0 : mnCol(nCol), mnRow(nRow), mnTab(nTab), mbStartOnly(bStartOnly) {}
602 :
603 0 : bool operator() (const ScDBData& r)
604 : {
605 0 : 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 0 : FindByRange(const ScRange& rRange) : mrRange(rRange) {}
614 :
615 0 : bool operator() (const ScDBData& r)
616 : {
617 : return r.IsDBAtArea(
618 0 : 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 0 : FindByIndex(sal_uInt16 nIndex) : mnIndex(nIndex) {}
627 0 : bool operator() (const ScDBData& r) const
628 : {
629 0 : return r.GetIndex() == mnIndex;
630 : }
631 : };
632 :
633 : class FindByUpperName : public unary_function<ScDBData, bool>
634 : {
635 : const OUString& mrName;
636 : public:
637 0 : FindByUpperName(const OUString& rName) : mrName(rName) {}
638 0 : bool operator() (const ScDBData& r) const
639 : {
640 0 : return r.GetUpperName() == mrName;
641 : }
642 : };
643 :
644 : }
645 :
646 0 : ScDBCollection::NamedDBs::NamedDBs(ScDBCollection& rParent, ScDocument& rDoc) :
647 0 : mrParent(rParent), mrDoc(rDoc) {}
648 :
649 0 : ScDBCollection::NamedDBs::NamedDBs(const NamedDBs& r) :
650 0 : maDBs(r.maDBs), mrParent(r.mrParent), mrDoc(r.mrDoc) {}
651 :
652 0 : ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::begin()
653 : {
654 0 : return maDBs.begin();
655 : }
656 :
657 0 : ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::end()
658 : {
659 0 : return maDBs.end();
660 : }
661 :
662 0 : ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::begin() const
663 : {
664 0 : return maDBs.begin();
665 : }
666 :
667 0 : ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::end() const
668 : {
669 0 : return maDBs.end();
670 : }
671 :
672 0 : ScDBData* ScDBCollection::NamedDBs::findByIndex(sal_uInt16 nIndex)
673 : {
674 : DBsType::iterator itr = find_if(
675 0 : maDBs.begin(), maDBs.end(), FindByIndex(nIndex));
676 0 : return itr == maDBs.end() ? NULL : &(*itr);
677 : }
678 :
679 0 : ScDBData* ScDBCollection::NamedDBs::findByUpperName(const OUString& rName)
680 : {
681 : DBsType::iterator itr = find_if(
682 0 : maDBs.begin(), maDBs.end(), FindByUpperName(rName));
683 0 : return itr == maDBs.end() ? NULL : &(*itr);
684 : }
685 :
686 0 : bool ScDBCollection::NamedDBs::insert(ScDBData* p)
687 : {
688 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
689 0 : auto_ptr<ScDBData> pData(p);
690 : SAL_WNODEPRECATED_DECLARATIONS_POP
691 0 : if (!pData->GetIndex())
692 0 : pData->SetIndex(mrParent.nEntryIndex++);
693 :
694 0 : pair<DBsType::iterator, bool> r = maDBs.insert(pData);
695 :
696 0 : if (r.second && p->HasImportParam() && !p->HasImportSelection())
697 : {
698 0 : p->SetRefreshHandler(mrParent.GetRefreshHandler());
699 0 : p->SetRefreshControl(mrDoc.GetRefreshTimerControlAddress());
700 : }
701 0 : return r.second;
702 : }
703 :
704 0 : void ScDBCollection::NamedDBs::erase(iterator itr)
705 : {
706 0 : maDBs.erase(itr);
707 0 : }
708 :
709 0 : void ScDBCollection::NamedDBs::erase(const ScDBData& r)
710 : {
711 0 : maDBs.erase(r);
712 0 : }
713 :
714 0 : bool ScDBCollection::NamedDBs::empty() const
715 : {
716 0 : return maDBs.empty();
717 : }
718 :
719 0 : size_t ScDBCollection::NamedDBs::size() const
720 : {
721 0 : return maDBs.size();
722 : }
723 :
724 0 : bool ScDBCollection::NamedDBs::operator== (const NamedDBs& r) const
725 : {
726 0 : return maDBs == r.maDBs;
727 : }
728 :
729 0 : ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::begin()
730 : {
731 0 : return maDBs.begin();
732 : }
733 :
734 0 : ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::end()
735 : {
736 0 : 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 0 : const ScDBData* ScDBCollection::AnonDBs::findAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
750 : {
751 : DBsType::const_iterator itr = find_if(
752 0 : maDBs.begin(), maDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
753 0 : return itr == maDBs.end() ? NULL : &(*itr);
754 : }
755 :
756 0 : const ScDBData* ScDBCollection::AnonDBs::findByRange(const ScRange& rRange) const
757 : {
758 : DBsType::const_iterator itr = find_if(
759 0 : maDBs.begin(), maDBs.end(), FindByRange(rRange));
760 0 : 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 0 : bool ScDBCollection::AnonDBs::empty() const
790 : {
791 0 : return maDBs.empty();
792 : }
793 :
794 0 : bool ScDBCollection::AnonDBs::operator== (const AnonDBs& r) const
795 : {
796 0 : return maDBs == r.maDBs;
797 : }
798 :
799 0 : ScDBCollection::ScDBCollection(ScDocument* pDocument) :
800 0 : pDoc(pDocument), nEntryIndex(SC_START_INDEX_DB_COLL), maNamedDBs(*this, *pDocument) {}
801 :
802 0 : ScDBCollection::ScDBCollection(const ScDBCollection& r) :
803 0 : pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maNamedDBs(r.maNamedDBs), maAnonDBs(r.maAnonDBs) {}
804 :
805 0 : ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs()
806 : {
807 0 : return maNamedDBs;
808 : }
809 :
810 0 : const ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs() const
811 : {
812 0 : return maNamedDBs;
813 : }
814 :
815 0 : ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs()
816 : {
817 0 : 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 0 : 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 0 : maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
852 0 : if (itr != maNamedDBs.end())
853 0 : return &(*itr);
854 :
855 : // Check for the sheet-local anonymous db range.
856 0 : ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
857 0 : if (pNoNameData)
858 0 : if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
859 0 : return pNoNameData;
860 :
861 : // Check the global anonymous db ranges.
862 0 : const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
863 0 : if (pData)
864 0 : return const_cast<ScDBData*>(pData);
865 :
866 0 : 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 0 : ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
889 : {
890 : // First, search the global named db ranges.
891 0 : ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
892 : NamedDBs::DBsType::iterator itr = find_if(
893 0 : maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
894 0 : if (itr != maNamedDBs.end())
895 0 : return &(*itr);
896 :
897 : // Check for the sheet-local anonymous db range.
898 0 : ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
899 0 : if (pNoNameData)
900 0 : if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
901 0 : return pNoNameData;
902 :
903 : // Lastly, check the global anonymous db ranges.
904 0 : const ScDBData* pData = getAnonDBs().findByRange(aRange);
905 0 : if (pData)
906 0 : return const_cast<ScDBData*>(pData);
907 :
908 0 : return NULL;
909 : }
910 :
911 0 : void ScDBCollection::DeleteOnTab( SCTAB nTab )
912 : {
913 0 : FindByTable func(nTab);
914 : // First, collect the positions of all items that need to be deleted.
915 0 : ::std::vector<NamedDBs::DBsType::iterator> v;
916 : {
917 0 : NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
918 0 : for (; itr != itrEnd; ++itr)
919 : {
920 0 : if (func(*itr))
921 0 : v.push_back(itr);
922 : }
923 : }
924 :
925 : // Delete them all.
926 0 : ::std::vector<NamedDBs::DBsType::iterator>::iterator itr = v.begin(), itrEnd = v.end();
927 0 : for (; itr != itrEnd; ++itr)
928 0 : maNamedDBs.erase(*itr);
929 :
930 0 : remove_if(maAnonDBs.begin(), maAnonDBs.end(), func);
931 0 : }
932 :
933 0 : 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 0 : ScDBData* pData = pDoc->GetAnonymousDBData(nTab1);
939 0 : if (pData)
940 : {
941 0 : if (nTab1 == nTab2 && nDz == 0)
942 : {
943 : pData->UpdateReference(
944 : pDoc, eUpdateRefMode,
945 0 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
946 : }
947 : else
948 : {
949 : //this will perhabs break undo
950 : }
951 : }
952 :
953 0 : UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
954 0 : for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
955 0 : for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
956 0 : }
957 :
958 0 : void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
959 : {
960 0 : UpdateMoveTabFunc func(nOldPos, nNewPos);
961 0 : for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
962 0 : for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
963 0 : }
964 :
965 0 : ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab )
966 : {
967 0 : ScDBData* pNearData = NULL;
968 0 : NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
969 0 : 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 0 : if (pNearData)
988 0 : return pNearData; // angrenzender, wenn nichts direkt getroffen
989 0 : return pDoc->GetAnonymousDBData(nTab); // "unbenannt" nur zurueck, wenn sonst nichts gefunden
990 : }
991 :
992 0 : bool ScDBCollection::empty() const
993 : {
994 0 : return maNamedDBs.empty() && maAnonDBs.empty();
995 : }
996 :
997 0 : bool ScDBCollection::operator== (const ScDBCollection& r) const
998 : {
999 0 : return maNamedDBs == r.maNamedDBs && maAnonDBs == r.maAnonDBs &&
1000 0 : nEntryIndex == r.nEntryIndex && pDoc == r.pDoc && aRefreshHandler == r.aRefreshHandler;
1001 : }
1002 :
1003 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|