Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / dbdata.cxx
blob5eb88b320fea90d22051f2f33a812bf51bfe5785
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <unotools/transliterationwrapper.hxx>
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"
33 #include <memory>
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;
42 bool ScDBData::less::operator() (const ScDBData& left, const ScDBData& right) const
44 return ScGlobal::GetpTransliteration()->compareString(left.GetUpperName(), right.GetUpperName()) < 0;
47 ScDBData::ScDBData( const OUString& rName,
48 SCTAB nTab,
49 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
50 bool bByR, bool bHasH) :
51 mpSortParam(new ScSortParam),
52 mpQueryParam(new ScQueryParam),
53 mpSubTotal(new ScSubTotalParam),
54 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 bModified (false)
73 aUpper = ScGlobal::pCharClass->uppercase(aUpper);
76 ScDBData::ScDBData( const ScDBData& rData ) :
77 ScRefreshTimer ( rData ),
78 mpSortParam(new ScSortParam(*rData.mpSortParam)),
79 mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
80 mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
81 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 bModified (rData.bModified)
103 ScDBData::ScDBData( const OUString& rName, const ScDBData& rData ) :
104 ScRefreshTimer ( rData ),
105 mpSortParam(new ScSortParam(*rData.mpSortParam)),
106 mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
107 mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
108 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 bModified (rData.bModified)
128 aUpper = ScGlobal::pCharClass->uppercase(aUpper);
131 ScDBData& ScDBData::operator= (const ScDBData& rData)
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 ScRefreshTimer::operator=( rData );
136 mpSortParam.reset(new ScSortParam(*rData.mpSortParam));
137 mpQueryParam.reset(new ScQueryParam(*rData.mpQueryParam));
138 mpSubTotal.reset(new ScSubTotalParam(*rData.mpSubTotal));
139 mpImportParam.reset(new ScImportParam(*rData.mpImportParam));
140 nTable = rData.nTable;
141 nStartCol = rData.nStartCol;
142 nStartRow = rData.nStartRow;
143 nEndCol = rData.nEndCol;
144 nEndRow = rData.nEndRow;
145 bByRow = rData.bByRow;
146 bHasHeader = rData.bHasHeader;
147 bDoSize = rData.bDoSize;
148 bKeepFmt = rData.bKeepFmt;
149 bStripData = rData.bStripData;
150 bIsAdvanced = rData.bIsAdvanced;
151 aAdvSource = rData.aAdvSource;
152 bDBSelection = rData.bDBSelection;
153 nIndex = rData.nIndex;
154 bAutoFilter = rData.bAutoFilter;
156 return *this;
159 bool ScDBData::operator== (const ScDBData& rData) const
161 // Daten, die nicht in den Params sind
163 if ( nTable != rData.nTable ||
164 bDoSize != rData.bDoSize ||
165 bKeepFmt != rData.bKeepFmt ||
166 bIsAdvanced!= rData.bIsAdvanced||
167 bStripData != rData.bStripData ||
168 // SAB: I think this should be here, but I don't want to break something
169 // bAutoFilter!= rData.bAutoFilter||
170 ScRefreshTimer::operator!=( rData )
172 return false;
174 if ( bIsAdvanced && aAdvSource != rData.aAdvSource )
175 return false;
177 ScSortParam aSort1, aSort2;
178 GetSortParam(aSort1);
179 rData.GetSortParam(aSort2);
180 if (!(aSort1 == aSort2))
181 return false;
183 ScQueryParam aQuery1, aQuery2;
184 GetQueryParam(aQuery1);
185 rData.GetQueryParam(aQuery2);
186 if (!(aQuery1 == aQuery2))
187 return false;
189 ScSubTotalParam aSubTotal1, aSubTotal2;
190 GetSubTotalParam(aSubTotal1);
191 rData.GetSubTotalParam(aSubTotal2);
192 if (!(aSubTotal1 == aSubTotal2))
193 return false;
195 ScImportParam aImport1, aImport2;
196 GetImportParam(aImport1);
197 rData.GetImportParam(aImport2);
198 if (!(aImport1 == aImport2))
199 return false;
201 return true;
204 ScDBData::~ScDBData()
206 StopRefreshTimer();
209 OUString ScDBData::GetSourceString() const
211 OUStringBuffer aBuf;
212 if (mpImportParam->bImport)
214 aBuf.append(mpImportParam->aDBName);
215 aBuf.append('/');
216 aBuf.append(mpImportParam->aStatement);
218 return aBuf.makeStringAndClear();
221 OUString ScDBData::GetOperations() const
223 OUStringBuffer aBuf;
224 if (mpQueryParam->GetEntryCount())
226 const ScQueryEntry& rEntry = mpQueryParam->GetEntry(0);
227 if (rEntry.bDoQuery)
228 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_FILTER));
231 if (mpSortParam->maKeyState[0].bDoSort)
233 if (!aBuf.isEmpty())
234 aBuf.append(", ");
235 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SORT));
238 if (mpSubTotal->bGroupActive[0] && !mpSubTotal->bRemoveOnly)
240 if (!aBuf.isEmpty())
241 aBuf.append(", ");
242 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SUBTOTAL));
245 if (aBuf.isEmpty())
246 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_NONE));
248 return aBuf.makeStringAndClear();
251 void ScDBData::GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const
253 rTab = nTable;
254 rCol1 = nStartCol;
255 rRow1 = nStartRow;
256 rCol2 = nEndCol;
257 rRow2 = nEndRow;
260 void ScDBData::GetArea(ScRange& rRange) const
262 SCROW nNewEndRow = nEndRow;
263 rRange = ScRange( nStartCol, nStartRow, nTable, nEndCol, nNewEndRow, nTable );
266 void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
268 nTable = nTab;
269 nStartCol = nCol1;
270 nStartRow = nRow1;
271 nEndCol = nCol2;
272 nEndRow = nRow2;
275 void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
277 sal_uInt16 i;
278 long nDifX = ((long) nCol1) - ((long) nStartCol);
279 long nDifY = ((long) nRow1) - ((long) nStartRow);
281 long nSortDif = bByRow ? nDifX : nDifY;
282 long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2);
284 for (i=0; i<mpSortParam->GetSortKeyCount(); i++)
286 mpSortParam->maKeyState[i].nField += nSortDif;
287 if (mpSortParam->maKeyState[i].nField > nSortEnd)
289 mpSortParam->maKeyState[i].nField = 0;
290 mpSortParam->maKeyState[i].bDoSort = false;
294 SCSIZE nCount = mpQueryParam->GetEntryCount();
295 for (i = 0; i < nCount; ++i)
297 ScQueryEntry& rEntry = mpQueryParam->GetEntry(i);
298 rEntry.nField += nDifX;
299 if (rEntry.nField > nCol2)
301 rEntry.nField = 0;
302 rEntry.bDoQuery = false;
305 for (i=0; i<MAXSUBTOTAL; i++)
307 mpSubTotal->nField[i] = sal::static_int_cast<SCCOL>( mpSubTotal->nField[i] + nDifX );
308 if (mpSubTotal->nField[i] > nCol2)
310 mpSubTotal->nField[i] = 0;
311 mpSubTotal->bGroupActive[i] = false;
315 SetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
318 void ScDBData::GetSortParam( ScSortParam& rSortParam ) const
320 rSortParam = *mpSortParam;
321 rSortParam.nCol1 = nStartCol;
322 rSortParam.nRow1 = nStartRow;
323 rSortParam.nCol2 = nEndCol;
324 rSortParam.nRow2 = nEndRow;
325 rSortParam.bByRow = bByRow;
326 rSortParam.bHasHeader = bHasHeader;
329 void ScDBData::SetSortParam( const ScSortParam& rSortParam )
331 mpSortParam.reset(new ScSortParam(rSortParam));
332 bByRow = rSortParam.bByRow;
335 void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
337 rQueryParam = *mpQueryParam;
338 rQueryParam.nCol1 = nStartCol;
339 rQueryParam.nRow1 = nStartRow;
340 rQueryParam.nCol2 = nEndCol;
341 rQueryParam.nRow2 = nEndRow;
342 rQueryParam.nTab = nTable;
343 rQueryParam.bByRow = bByRow;
344 rQueryParam.bHasHeader = bHasHeader;
347 void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
349 mpQueryParam.reset(new ScQueryParam(rQueryParam));
351 // set bIsAdvanced to false for everything that is not from the
352 // advanced filter dialog
353 bIsAdvanced = false;
356 void ScDBData::SetAdvancedQuerySource(const ScRange* pSource)
358 if (pSource)
360 aAdvSource = *pSource;
361 bIsAdvanced = true;
363 else
364 bIsAdvanced = false;
367 bool ScDBData::GetAdvancedQuerySource(ScRange& rSource) const
369 rSource = aAdvSource;
370 return bIsAdvanced;
373 void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
375 rSubTotalParam = *mpSubTotal;
377 // Share the data range with the parent db data. The range in the subtotal
378 // param struct is not used.
379 rSubTotalParam.nCol1 = nStartCol;
380 rSubTotalParam.nRow1 = nStartRow;
381 rSubTotalParam.nCol2 = nEndCol;
382 rSubTotalParam.nRow2 = nEndRow;
385 void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
387 mpSubTotal.reset(new ScSubTotalParam(rSubTotalParam));
390 void ScDBData::GetImportParam(ScImportParam& rImportParam) const
392 rImportParam = *mpImportParam;
393 // set the range.
394 rImportParam.nCol1 = nStartCol;
395 rImportParam.nRow1 = nStartRow;
396 rImportParam.nCol2 = nEndCol;
397 rImportParam.nRow2 = nEndRow;
400 void ScDBData::SetImportParam(const ScImportParam& rImportParam)
402 // the range is ignored.
403 mpImportParam.reset(new ScImportParam(rImportParam));
406 bool ScDBData::IsDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
408 if (nTab == nTable)
410 if ( bStartOnly )
411 return ( nCol == nStartCol && nRow == nStartRow );
412 else
413 return ( nCol >= nStartCol && nCol <= nEndCol &&
414 nRow >= nStartRow && nRow <= nEndRow );
417 return false;
420 bool ScDBData::IsDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
422 return (bool)((nTab == nTable)
423 && (nCol1 == nStartCol) && (nRow1 == nStartRow)
424 && (nCol2 == nEndCol) && (nRow2 == nEndRow));
427 bool ScDBData::HasImportParam() const
429 return mpImportParam && mpImportParam->bImport;
432 bool ScDBData::HasQueryParam() const
434 if (!mpQueryParam)
435 return false;
437 if (!mpQueryParam->GetEntryCount())
438 return false;
440 return mpQueryParam->GetEntry(0).bDoQuery;
443 bool ScDBData::HasSortParam() const
445 return mpSortParam &&
446 !mpSortParam->maKeyState.empty() &&
447 mpSortParam->maKeyState[0].bDoSort;
450 bool ScDBData::HasSubTotalParam() const
452 return mpSubTotal && mpSubTotal->bGroupActive[0];
455 void ScDBData::UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos)
457 ScRange aRange;
458 GetArea( aRange );
459 SCTAB nTab = aRange.aStart.Tab(); // hat nur eine Tabelle
461 // anpassen wie die aktuelle Tabelle bei ScTablesHint (tabvwsh5.cxx)
463 if ( nTab == nOldPos ) // verschobene Tabelle
464 nTab = nNewPos;
465 else if ( nOldPos < nNewPos ) // nach hinten verschoben
467 if ( nTab > nOldPos && nTab <= nNewPos ) // nachrueckender Bereich
468 --nTab;
470 else // nach vorne verschoben
472 if ( nTab >= nNewPos && nTab < nOldPos ) // nachrueckender Bereich
473 ++nTab;
476 bool bChanged = ( nTab != aRange.aStart.Tab() );
477 if (bChanged)
478 SetArea( nTab, aRange.aStart.Col(), aRange.aStart.Row(),
479 aRange.aEnd.Col(),aRange.aEnd .Row() );
481 // MoveTo ist nicht noetig, wenn nur die Tabelle geaendert ist
483 SetModified(bChanged);
487 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)
492 SCCOL theCol1;
493 SCROW theRow1;
494 SCTAB theTab1;
495 SCCOL theCol2;
496 SCROW theRow2;
497 SCTAB theTab2;
498 GetArea( theTab1, theCol1, theRow1, theCol2, theRow2 );
499 theTab2 = theTab1;
501 bool bDoUpdate = ScRefUpdate::Update( pDoc, eUpdateRefMode,
502 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
503 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) != UR_NOTHING;
504 if (bDoUpdate)
505 MoveTo( theTab1, theCol1, theRow1, theCol2, theRow2 );
507 ScRange aRangeAdvSource;
508 if ( GetAdvancedQuerySource(aRangeAdvSource) )
510 aRangeAdvSource.GetVars( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
511 if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
512 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
513 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
515 aRangeAdvSource.aStart.Set( theCol1,theRow1,theTab1 );
516 aRangeAdvSource.aEnd.Set( theCol2,theRow2,theTab2 );
517 SetAdvancedQuerySource( &aRangeAdvSource );
519 bDoUpdate = true; // DBData is modified
523 SetModified(bDoUpdate);
525 //! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!!
528 void ScDBData::ExtendDataArea(ScDocument* pDoc)
530 // Extend the DB area to include data rows immediately below.
531 // or shrink it if all cells are empty
532 pDoc->GetDataArea(nTable, nStartCol, nStartRow, nEndCol, nEndRow, false, true);
535 namespace {
537 class FindByTable : public unary_function<ScDBData, bool>
539 SCTAB mnTab;
540 public:
541 FindByTable(SCTAB nTab) : mnTab(nTab) {}
543 bool operator() (const ScDBData& r) const
545 ScRange aRange;
546 r.GetArea(aRange);
547 return aRange.aStart.Tab() == mnTab;
551 class UpdateRefFunc : public unary_function<ScDBData, void>
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;
565 public:
566 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 mnDx(nDx), mnDy(nDy), mnDz(nDz) {}
575 void operator() (ScDBData& r)
577 r.UpdateReference(mpDoc, meMode, mnCol1, mnRow1, mnTab1, mnCol2, mnRow2, mnTab2, mnDx, mnDy, mnDz);
581 class UpdateMoveTabFunc : public unary_function<ScDBData, void>
583 SCTAB mnOldTab;
584 SCTAB mnNewTab;
585 public:
586 UpdateMoveTabFunc(SCTAB nOld, SCTAB nNew) : mnOldTab(nOld), mnNewTab(nNew) {}
587 void operator() (ScDBData& r)
589 r.UpdateMoveTab(mnOldTab, mnNewTab);
593 class FindByCursor : public unary_function<ScDBData, bool>
595 SCCOL mnCol;
596 SCROW mnRow;
597 SCTAB mnTab;
598 bool mbStartOnly;
599 public:
600 FindByCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) :
601 mnCol(nCol), mnRow(nRow), mnTab(nTab), mbStartOnly(bStartOnly) {}
603 bool operator() (const ScDBData& r)
605 return r.IsDBAtCursor(mnCol, mnRow, mnTab, mbStartOnly);
609 class FindByRange : public unary_function<ScDBData, bool>
611 const ScRange& mrRange;
612 public:
613 FindByRange(const ScRange& rRange) : mrRange(rRange) {}
615 bool operator() (const ScDBData& r)
617 return r.IsDBAtArea(
618 mrRange.aStart.Tab(), mrRange.aStart.Col(), mrRange.aStart.Row(), mrRange.aEnd.Col(), mrRange.aEnd.Row());
622 class FindByIndex : public unary_function<ScDBData, bool>
624 sal_uInt16 mnIndex;
625 public:
626 FindByIndex(sal_uInt16 nIndex) : mnIndex(nIndex) {}
627 bool operator() (const ScDBData& r) const
629 return r.GetIndex() == mnIndex;
633 class FindByUpperName : public unary_function<ScDBData, bool>
635 const OUString& mrName;
636 public:
637 FindByUpperName(const OUString& rName) : mrName(rName) {}
638 bool operator() (const ScDBData& r) const
640 return r.GetUpperName() == mrName;
646 ScDBCollection::NamedDBs::NamedDBs(ScDBCollection& rParent, ScDocument& rDoc) :
647 mrParent(rParent), mrDoc(rDoc) {}
649 ScDBCollection::NamedDBs::NamedDBs(const NamedDBs& r) :
650 maDBs(r.maDBs), mrParent(r.mrParent), mrDoc(r.mrDoc) {}
652 ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::begin()
654 return maDBs.begin();
657 ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::end()
659 return maDBs.end();
662 ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::begin() const
664 return maDBs.begin();
667 ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::end() const
669 return maDBs.end();
672 ScDBData* ScDBCollection::NamedDBs::findByIndex(sal_uInt16 nIndex)
674 DBsType::iterator itr = find_if(
675 maDBs.begin(), maDBs.end(), FindByIndex(nIndex));
676 return itr == maDBs.end() ? NULL : &(*itr);
679 ScDBData* ScDBCollection::NamedDBs::findByUpperName(const OUString& rName)
681 DBsType::iterator itr = find_if(
682 maDBs.begin(), maDBs.end(), FindByUpperName(rName));
683 return itr == maDBs.end() ? NULL : &(*itr);
686 bool ScDBCollection::NamedDBs::insert(ScDBData* p)
688 SAL_WNODEPRECATED_DECLARATIONS_PUSH
689 auto_ptr<ScDBData> pData(p);
690 SAL_WNODEPRECATED_DECLARATIONS_POP
691 if (!pData->GetIndex())
692 pData->SetIndex(mrParent.nEntryIndex++);
694 pair<DBsType::iterator, bool> r = maDBs.insert(pData);
696 if (r.second && p->HasImportParam() && !p->HasImportSelection())
698 p->SetRefreshHandler(mrParent.GetRefreshHandler());
699 p->SetRefreshControl(mrDoc.GetRefreshTimerControlAddress());
701 return r.second;
704 void ScDBCollection::NamedDBs::erase(iterator itr)
706 maDBs.erase(itr);
709 void ScDBCollection::NamedDBs::erase(const ScDBData& r)
711 maDBs.erase(r);
714 bool ScDBCollection::NamedDBs::empty() const
716 return maDBs.empty();
719 size_t ScDBCollection::NamedDBs::size() const
721 return maDBs.size();
724 bool ScDBCollection::NamedDBs::operator== (const NamedDBs& r) const
726 return maDBs == r.maDBs;
729 ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::begin()
731 return maDBs.begin();
734 ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::end()
736 return maDBs.end();
739 ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::begin() const
741 return maDBs.begin();
744 ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::end() const
746 return maDBs.end();
749 const ScDBData* ScDBCollection::AnonDBs::findAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
751 DBsType::const_iterator itr = find_if(
752 maDBs.begin(), maDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
753 return itr == maDBs.end() ? NULL : &(*itr);
756 const ScDBData* ScDBCollection::AnonDBs::findByRange(const ScRange& rRange) const
758 DBsType::const_iterator itr = find_if(
759 maDBs.begin(), maDBs.end(), FindByRange(rRange));
760 return itr == maDBs.end() ? NULL : &(*itr);
763 ScDBData* ScDBCollection::AnonDBs::getByRange(const ScRange& rRange)
765 const ScDBData* pData = findByRange(rRange);
766 if (!pData)
768 // Insert a new db data. They all have identical names.
769 OUString aName(STR_DB_GLOBAL_NONAME);
770 SAL_WNODEPRECATED_DECLARATIONS_PUSH
771 ::std::auto_ptr<ScDBData> pNew(new ScDBData(
772 aName, rRange.aStart.Tab(), rRange.aStart.Col(), rRange.aStart.Row(),
773 rRange.aEnd.Col(), rRange.aEnd.Row(), true, false));
774 SAL_WNODEPRECATED_DECLARATIONS_POP
775 pData = pNew.get();
776 maDBs.push_back(pNew);
778 return const_cast<ScDBData*>(pData);
781 void ScDBCollection::AnonDBs::insert(ScDBData* p)
783 SAL_WNODEPRECATED_DECLARATIONS_PUSH
784 ::std::auto_ptr<ScDBData> pNew(p);
785 SAL_WNODEPRECATED_DECLARATIONS_POP
786 maDBs.push_back(pNew);
789 bool ScDBCollection::AnonDBs::empty() const
791 return maDBs.empty();
794 bool ScDBCollection::AnonDBs::operator== (const AnonDBs& r) const
796 return maDBs == r.maDBs;
799 ScDBCollection::ScDBCollection(ScDocument* pDocument) :
800 pDoc(pDocument), nEntryIndex(SC_START_INDEX_DB_COLL), maNamedDBs(*this, *pDocument) {}
802 ScDBCollection::ScDBCollection(const ScDBCollection& r) :
803 pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maNamedDBs(r.maNamedDBs), maAnonDBs(r.maAnonDBs) {}
805 ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs()
807 return maNamedDBs;
810 const ScDBCollection::NamedDBs& ScDBCollection::getNamedDBs() const
812 return maNamedDBs;
815 ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs()
817 return maAnonDBs;
820 const ScDBCollection::AnonDBs& ScDBCollection::getAnonDBs() const
822 return maAnonDBs;
825 const ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly) const
827 // First, search the global named db ranges.
828 NamedDBs::DBsType::const_iterator itr = find_if(
829 maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
830 if (itr != maNamedDBs.end())
831 return &(*itr);
833 // Check for the sheet-local anonymous db range.
834 const ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
835 if (pNoNameData)
836 if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
837 return pNoNameData;
839 // Check the global anonymous db ranges.
840 const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
841 if (pData)
842 return pData;
844 return NULL;
847 ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly)
849 // First, search the global named db ranges.
850 NamedDBs::DBsType::iterator itr = find_if(
851 maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
852 if (itr != maNamedDBs.end())
853 return &(*itr);
855 // Check for the sheet-local anonymous db range.
856 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
857 if (pNoNameData)
858 if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
859 return pNoNameData;
861 // Check the global anonymous db ranges.
862 const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
863 if (pData)
864 return const_cast<ScDBData*>(pData);
866 return NULL;
869 const ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
871 // First, search the global named db ranges.
872 ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
873 NamedDBs::DBsType::const_iterator itr = find_if(
874 maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
875 if (itr != maNamedDBs.end())
876 return &(*itr);
878 // Check for the sheet-local anonymous db range.
879 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
880 if (pNoNameData)
881 if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
882 return pNoNameData;
884 // Lastly, check the global anonymous db ranges.
885 return maAnonDBs.findByRange(aRange);
888 ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
890 // First, search the global named db ranges.
891 ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
892 NamedDBs::DBsType::iterator itr = find_if(
893 maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
894 if (itr != maNamedDBs.end())
895 return &(*itr);
897 // Check for the sheet-local anonymous db range.
898 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
899 if (pNoNameData)
900 if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
901 return pNoNameData;
903 // Lastly, check the global anonymous db ranges.
904 const ScDBData* pData = getAnonDBs().findByRange(aRange);
905 if (pData)
906 return const_cast<ScDBData*>(pData);
908 return NULL;
911 void ScDBCollection::DeleteOnTab( SCTAB nTab )
913 FindByTable func(nTab);
914 // First, collect the positions of all items that need to be deleted.
915 ::std::vector<NamedDBs::DBsType::iterator> v;
917 NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
918 for (; itr != itrEnd; ++itr)
920 if (func(*itr))
921 v.push_back(itr);
925 // Delete them all.
926 ::std::vector<NamedDBs::DBsType::iterator>::iterator itr = v.begin(), itrEnd = v.end();
927 for (; itr != itrEnd; ++itr)
928 maNamedDBs.erase(*itr);
930 remove_if(maAnonDBs.begin(), maAnonDBs.end(), func);
933 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 )
938 ScDBData* pData = pDoc->GetAnonymousDBData(nTab1);
939 if (pData)
941 if (nTab1 == nTab2 && nDz == 0)
943 pData->UpdateReference(
944 pDoc, eUpdateRefMode,
945 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
947 else
949 //this will perhabs break undo
953 UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
954 for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
955 for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
958 void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
960 UpdateMoveTabFunc func(nOldPos, nNewPos);
961 for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
962 for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
965 ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab )
967 ScDBData* pNearData = NULL;
968 NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
969 for (; itr != itrEnd; ++itr)
971 SCTAB nAreaTab;
972 SCCOL nStartCol, nEndCol;
973 SCROW nStartRow, nEndRow;
974 itr->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
975 if ( nTab == nAreaTab && nCol+1 >= nStartCol && nCol <= nEndCol+1 &&
976 nRow+1 >= nStartRow && nRow <= nEndRow+1 )
978 if ( nCol < nStartCol || nCol > nEndCol || nRow < nStartRow || nRow > nEndRow )
980 if (!pNearData)
981 pNearData = &(*itr); // ersten angrenzenden Bereich merken
983 else
984 return &(*itr); // nicht "unbenannt" und Cursor steht wirklich drin
987 if (pNearData)
988 return pNearData; // angrenzender, wenn nichts direkt getroffen
989 return pDoc->GetAnonymousDBData(nTab); // "unbenannt" nur zurueck, wenn sonst nichts gefunden
992 bool ScDBCollection::empty() const
994 return maNamedDBs.empty() && maAnonDBs.empty();
997 bool ScDBCollection::operator== (const ScDBCollection& r) const
999 return maNamedDBs == r.maNamedDBs && maAnonDBs == r.maAnonDBs &&
1000 nEntryIndex == r.nEntryIndex && pDoc == r.pDoc && aRefreshHandler == r.aRefreshHandler;
1003 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */