fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / dbdata.cxx
blobe91f2b1bf061c14371c80728cc6494f36637e4ad
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 <sal/config.h>
22 #include <o3tl/ptr_container.hxx>
23 #include <unotools/transliterationwrapper.hxx>
25 #include "dbdata.hxx"
26 #include "globalnames.hxx"
27 #include "refupdat.hxx"
28 #include "rechead.hxx"
29 #include "document.hxx"
30 #include "queryparam.hxx"
31 #include "queryentry.hxx"
32 #include "globstr.hrc"
33 #include "subtotalparam.hxx"
34 #include "sortparam.hxx"
36 #include <memory>
37 #include <utility>
39 using ::std::unique_ptr;
40 using ::std::unary_function;
41 using ::std::for_each;
42 using ::std::find_if;
43 using ::std::remove_if;
44 using ::std::pair;
46 bool ScDBData::less::operator() (const ScDBData& left, const ScDBData& right) const
48 return ScGlobal::GetpTransliteration()->compareString(left.GetUpperName(), right.GetUpperName()) < 0;
51 ScDBData::ScDBData( const OUString& rName,
52 SCTAB nTab,
53 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
54 bool bByR, bool bHasH, bool bTotals) :
55 mpSortParam(new ScSortParam),
56 mpQueryParam(new ScQueryParam),
57 mpSubTotal(new ScSubTotalParam),
58 mpImportParam(new ScImportParam),
59 aName (rName),
60 aUpper (rName),
61 nTable (nTab),
62 nStartCol (nCol1),
63 nStartRow (nRow1),
64 nEndCol (nCol2),
65 nEndRow (nRow2),
66 bByRow (bByR),
67 bHasHeader (bHasH),
68 bHasTotals (bTotals),
69 bDoSize (false),
70 bKeepFmt (false),
71 bStripData (false),
72 bIsAdvanced (false),
73 bDBSelection(false),
74 nIndex (0),
75 bAutoFilter (false),
76 bModified (false)
78 aUpper = ScGlobal::pCharClass->uppercase(aUpper);
81 ScDBData::ScDBData( const ScDBData& rData ) :
82 ScRefreshTimer ( rData ),
83 mpSortParam(new ScSortParam(*rData.mpSortParam)),
84 mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
85 mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
86 mpImportParam(new ScImportParam(*rData.mpImportParam)),
87 aName (rData.aName),
88 aUpper (rData.aUpper),
89 nTable (rData.nTable),
90 nStartCol (rData.nStartCol),
91 nStartRow (rData.nStartRow),
92 nEndCol (rData.nEndCol),
93 nEndRow (rData.nEndRow),
94 bByRow (rData.bByRow),
95 bHasHeader (rData.bHasHeader),
96 bHasTotals (rData.bHasTotals),
97 bDoSize (rData.bDoSize),
98 bKeepFmt (rData.bKeepFmt),
99 bStripData (rData.bStripData),
100 bIsAdvanced (rData.bIsAdvanced),
101 aAdvSource (rData.aAdvSource),
102 bDBSelection (rData.bDBSelection),
103 nIndex (rData.nIndex),
104 bAutoFilter (rData.bAutoFilter),
105 bModified (rData.bModified),
106 maTableColumnNames (rData.maTableColumnNames)
110 ScDBData::ScDBData( const OUString& rName, const ScDBData& rData ) :
111 ScRefreshTimer ( rData ),
112 mpSortParam(new ScSortParam(*rData.mpSortParam)),
113 mpQueryParam(new ScQueryParam(*rData.mpQueryParam)),
114 mpSubTotal(new ScSubTotalParam(*rData.mpSubTotal)),
115 mpImportParam(new ScImportParam(*rData.mpImportParam)),
116 aName (rName),
117 aUpper (rName),
118 nTable (rData.nTable),
119 nStartCol (rData.nStartCol),
120 nStartRow (rData.nStartRow),
121 nEndCol (rData.nEndCol),
122 nEndRow (rData.nEndRow),
123 bByRow (rData.bByRow),
124 bHasHeader (rData.bHasHeader),
125 bHasTotals (rData.bHasTotals),
126 bDoSize (rData.bDoSize),
127 bKeepFmt (rData.bKeepFmt),
128 bStripData (rData.bStripData),
129 bIsAdvanced (rData.bIsAdvanced),
130 aAdvSource (rData.aAdvSource),
131 bDBSelection (rData.bDBSelection),
132 nIndex (rData.nIndex),
133 bAutoFilter (rData.bAutoFilter),
134 bModified (rData.bModified),
135 maTableColumnNames (rData.maTableColumnNames)
137 aUpper = ScGlobal::pCharClass->uppercase(aUpper);
140 ScDBData& ScDBData::operator= (const ScDBData& rData)
142 // Don't modify the name. The name is not mutable as it is used as a key
143 // in the container to keep the db ranges sorted by the name.
144 ScRefreshTimer::operator=( rData );
145 mpSortParam.reset(new ScSortParam(*rData.mpSortParam));
146 mpQueryParam.reset(new ScQueryParam(*rData.mpQueryParam));
147 mpSubTotal.reset(new ScSubTotalParam(*rData.mpSubTotal));
148 mpImportParam.reset(new ScImportParam(*rData.mpImportParam));
149 nTable = rData.nTable;
150 nStartCol = rData.nStartCol;
151 nStartRow = rData.nStartRow;
152 nEndCol = rData.nEndCol;
153 nEndRow = rData.nEndRow;
154 bByRow = rData.bByRow;
155 bHasHeader = rData.bHasHeader;
156 bHasTotals = rData.bHasTotals;
157 bDoSize = rData.bDoSize;
158 bKeepFmt = rData.bKeepFmt;
159 bStripData = rData.bStripData;
160 bIsAdvanced = rData.bIsAdvanced;
161 aAdvSource = rData.aAdvSource;
162 bDBSelection = rData.bDBSelection;
163 nIndex = rData.nIndex;
164 bAutoFilter = rData.bAutoFilter;
165 maTableColumnNames = rData.maTableColumnNames;
167 return *this;
170 bool ScDBData::operator== (const ScDBData& rData) const
172 // Daten, die nicht in den Params sind
174 if ( nTable != rData.nTable ||
175 bDoSize != rData.bDoSize ||
176 bKeepFmt != rData.bKeepFmt ||
177 bIsAdvanced!= rData.bIsAdvanced||
178 bStripData != rData.bStripData ||
179 // SAB: I think this should be here, but I don't want to break something
180 // bAutoFilter!= rData.bAutoFilter||
181 ScRefreshTimer::operator!=( rData )
183 return false;
185 if ( bIsAdvanced && aAdvSource != rData.aAdvSource )
186 return false;
188 ScSortParam aSort1, aSort2;
189 GetSortParam(aSort1);
190 rData.GetSortParam(aSort2);
191 if (!(aSort1 == aSort2))
192 return false;
194 ScQueryParam aQuery1, aQuery2;
195 GetQueryParam(aQuery1);
196 rData.GetQueryParam(aQuery2);
197 if (!(aQuery1 == aQuery2))
198 return false;
200 ScSubTotalParam aSubTotal1, aSubTotal2;
201 GetSubTotalParam(aSubTotal1);
202 rData.GetSubTotalParam(aSubTotal2);
203 if (!(aSubTotal1 == aSubTotal2))
204 return false;
206 ScImportParam aImport1, aImport2;
207 GetImportParam(aImport1);
208 rData.GetImportParam(aImport2);
209 if (!(aImport1 == aImport2))
210 return false;
212 return true;
215 ScDBData::~ScDBData()
217 StopRefreshTimer();
220 OUString ScDBData::GetSourceString() const
222 OUStringBuffer aBuf;
223 if (mpImportParam->bImport)
225 aBuf.append(mpImportParam->aDBName);
226 aBuf.append('/');
227 aBuf.append(mpImportParam->aStatement);
229 return aBuf.makeStringAndClear();
232 OUString ScDBData::GetOperations() const
234 OUStringBuffer aBuf;
235 if (mpQueryParam->GetEntryCount())
237 const ScQueryEntry& rEntry = mpQueryParam->GetEntry(0);
238 if (rEntry.bDoQuery)
239 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_FILTER));
242 if (mpSortParam->maKeyState[0].bDoSort)
244 if (!aBuf.isEmpty())
245 aBuf.append(", ");
246 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SORT));
249 if (mpSubTotal->bGroupActive[0] && !mpSubTotal->bRemoveOnly)
251 if (!aBuf.isEmpty())
252 aBuf.append(", ");
253 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_SUBTOTAL));
256 if (aBuf.isEmpty())
257 aBuf.append(ScGlobal::GetRscString(STR_OPERATION_NONE));
259 return aBuf.makeStringAndClear();
262 void ScDBData::GetArea(SCTAB& rTab, SCCOL& rCol1, SCROW& rRow1, SCCOL& rCol2, SCROW& rRow2) const
264 rTab = nTable;
265 rCol1 = nStartCol;
266 rRow1 = nStartRow;
267 rCol2 = nEndCol;
268 rRow2 = nEndRow;
271 void ScDBData::GetArea(ScRange& rRange) const
273 SCROW nNewEndRow = nEndRow;
274 rRange = ScRange( nStartCol, nStartRow, nTable, nEndCol, nNewEndRow, nTable );
277 void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
279 ::std::vector<OUString>().swap( maTableColumnNames); // invalidate column names/offsets
281 nTable = nTab;
282 nStartCol = nCol1;
283 nStartRow = nRow1;
284 nEndCol = nCol2;
285 nEndRow = nRow2;
288 void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
290 sal_uInt16 i;
291 long nDifX = ((long) nCol1) - ((long) nStartCol);
292 long nDifY = ((long) nRow1) - ((long) nStartRow);
294 long nSortDif = bByRow ? nDifX : nDifY;
295 long nSortEnd = bByRow ? static_cast<long>(nCol2) : static_cast<long>(nRow2);
297 for (i=0; i<mpSortParam->GetSortKeyCount(); i++)
299 mpSortParam->maKeyState[i].nField += nSortDif;
300 if (mpSortParam->maKeyState[i].nField > nSortEnd)
302 mpSortParam->maKeyState[i].nField = 0;
303 mpSortParam->maKeyState[i].bDoSort = false;
307 SCSIZE nCount = mpQueryParam->GetEntryCount();
308 for (i = 0; i < nCount; ++i)
310 ScQueryEntry& rEntry = mpQueryParam->GetEntry(i);
311 rEntry.nField += nDifX;
312 if (rEntry.nField > nCol2)
314 rEntry.nField = 0;
315 rEntry.bDoQuery = false;
318 for (i=0; i<MAXSUBTOTAL; i++)
320 mpSubTotal->nField[i] = sal::static_int_cast<SCCOL>( mpSubTotal->nField[i] + nDifX );
321 if (mpSubTotal->nField[i] > nCol2)
323 mpSubTotal->nField[i] = 0;
324 mpSubTotal->bGroupActive[i] = false;
328 SetArea( nTab, nCol1, nRow1, nCol2, nRow2 );
331 void ScDBData::GetSortParam( ScSortParam& rSortParam ) const
333 rSortParam = *mpSortParam;
334 rSortParam.nCol1 = nStartCol;
335 rSortParam.nRow1 = nStartRow;
336 rSortParam.nCol2 = nEndCol;
337 rSortParam.nRow2 = nEndRow;
338 rSortParam.bByRow = bByRow;
339 rSortParam.bHasHeader = bHasHeader;
340 /* TODO: add Totals to ScSortParam? */
343 void ScDBData::SetSortParam( const ScSortParam& rSortParam )
345 mpSortParam.reset(new ScSortParam(rSortParam));
346 bByRow = rSortParam.bByRow;
349 void ScDBData::UpdateFromSortParam( const ScSortParam& rSortParam )
351 bHasHeader = rSortParam.bHasHeader;
354 void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
356 rQueryParam = *mpQueryParam;
357 rQueryParam.nCol1 = nStartCol;
358 rQueryParam.nRow1 = nStartRow;
359 rQueryParam.nCol2 = nEndCol;
360 rQueryParam.nRow2 = nEndRow;
361 rQueryParam.nTab = nTable;
362 rQueryParam.bByRow = bByRow;
363 rQueryParam.bHasHeader = bHasHeader;
364 /* TODO: add Totals to ScQueryParam? */
367 void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
369 mpQueryParam.reset(new ScQueryParam(rQueryParam));
371 // set bIsAdvanced to false for everything that is not from the
372 // advanced filter dialog
373 bIsAdvanced = false;
376 void ScDBData::SetAdvancedQuerySource(const ScRange* pSource)
378 if (pSource)
380 aAdvSource = *pSource;
381 bIsAdvanced = true;
383 else
384 bIsAdvanced = false;
387 bool ScDBData::GetAdvancedQuerySource(ScRange& rSource) const
389 rSource = aAdvSource;
390 return bIsAdvanced;
393 void ScDBData::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const
395 rSubTotalParam = *mpSubTotal;
397 // Share the data range with the parent db data. The range in the subtotal
398 // param struct is not used.
399 rSubTotalParam.nCol1 = nStartCol;
400 rSubTotalParam.nRow1 = nStartRow;
401 rSubTotalParam.nCol2 = nEndCol;
402 rSubTotalParam.nRow2 = nEndRow;
405 void ScDBData::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam)
407 mpSubTotal.reset(new ScSubTotalParam(rSubTotalParam));
410 void ScDBData::GetImportParam(ScImportParam& rImportParam) const
412 rImportParam = *mpImportParam;
413 // set the range.
414 rImportParam.nCol1 = nStartCol;
415 rImportParam.nRow1 = nStartRow;
416 rImportParam.nCol2 = nEndCol;
417 rImportParam.nRow2 = nEndRow;
420 void ScDBData::SetImportParam(const ScImportParam& rImportParam)
422 // the range is ignored.
423 mpImportParam.reset(new ScImportParam(rImportParam));
426 bool ScDBData::IsDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
428 if (nTab == nTable)
430 if ( bStartOnly )
431 return ( nCol == nStartCol && nRow == nStartRow );
432 else
433 return ( nCol >= nStartCol && nCol <= nEndCol &&
434 nRow >= nStartRow && nRow <= nEndRow );
437 return false;
440 bool ScDBData::IsDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
442 return (bool)((nTab == nTable)
443 && (nCol1 == nStartCol) && (nRow1 == nStartRow)
444 && (nCol2 == nEndCol) && (nRow2 == nEndRow));
447 bool ScDBData::HasImportParam() const
449 return mpImportParam && mpImportParam->bImport;
452 bool ScDBData::HasQueryParam() const
454 if (!mpQueryParam)
455 return false;
457 if (!mpQueryParam->GetEntryCount())
458 return false;
460 return mpQueryParam->GetEntry(0).bDoQuery;
463 bool ScDBData::HasSortParam() const
465 return mpSortParam &&
466 !mpSortParam->maKeyState.empty() &&
467 mpSortParam->maKeyState[0].bDoSort;
470 bool ScDBData::HasSubTotalParam() const
472 return mpSubTotal && mpSubTotal->bGroupActive[0];
475 void ScDBData::UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos)
477 ScRange aRange;
478 GetArea( aRange );
479 SCTAB nTab = aRange.aStart.Tab(); // hat nur eine Tabelle
481 // anpassen wie die aktuelle Tabelle bei ScTablesHint (tabvwsh5.cxx)
483 if ( nTab == nOldPos ) // verschobene Tabelle
484 nTab = nNewPos;
485 else if ( nOldPos < nNewPos ) // nach hinten verschoben
487 if ( nTab > nOldPos && nTab <= nNewPos ) // nachrueckender Bereich
488 --nTab;
490 else // nach vorne verschoben
492 if ( nTab >= nNewPos && nTab < nOldPos ) // nachrueckender Bereich
493 ++nTab;
496 bool bChanged = ( nTab != aRange.aStart.Tab() );
497 if (bChanged)
499 // Save and restore column names, as SetArea() invalidates them.
500 ::std::vector<OUString> aNames( maTableColumnNames);
501 SetArea( nTab, aRange.aStart.Col(), aRange.aStart.Row(),
502 aRange.aEnd.Col(),aRange.aEnd .Row() );
503 maTableColumnNames = aNames;
506 // MoveTo ist nicht noetig, wenn nur die Tabelle geaendert ist
508 SetModified(bChanged);
512 void ScDBData::UpdateReference(ScDocument* pDoc, UpdateRefMode eUpdateRefMode,
513 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
514 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
515 SCsCOL nDx, SCsROW nDy, SCsTAB nDz)
517 SCCOL theCol1;
518 SCROW theRow1;
519 SCTAB theTab1;
520 SCCOL theCol2;
521 SCROW theRow2;
522 SCTAB theTab2;
523 GetArea( theTab1, theCol1, theRow1, theCol2, theRow2 );
524 theTab2 = theTab1;
525 SCCOL nOldCol1 = theCol1, nOldCol2 = theCol2;
527 bool bDoUpdate = ScRefUpdate::Update( pDoc, eUpdateRefMode,
528 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
529 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) != UR_NOTHING;
530 if (bDoUpdate)
532 // MoveTo() invalidates column names via SetArea(); adjust, remember
533 // and set new column offsets for names.
534 AdjustTableColumnNames( eUpdateRefMode, nDx, nCol1, nOldCol1, nOldCol2, theCol1, theCol2);
535 ::std::vector<OUString> aNames( maTableColumnNames);
536 MoveTo( theTab1, theCol1, theRow1, theCol2, theRow2 );
537 maTableColumnNames = aNames;
540 ScRange aRangeAdvSource;
541 if ( GetAdvancedQuerySource(aRangeAdvSource) )
543 aRangeAdvSource.GetVars( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
544 if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
545 nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, nDx,nDy,nDz,
546 theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
548 aRangeAdvSource.aStart.Set( theCol1,theRow1,theTab1 );
549 aRangeAdvSource.aEnd.Set( theCol2,theRow2,theTab2 );
550 SetAdvancedQuerySource( &aRangeAdvSource );
552 bDoUpdate = true; // DBData is modified
556 SetModified(bDoUpdate);
558 //TODO: check if something was deleted/inserted with-in the range !!!
561 void ScDBData::ExtendDataArea(ScDocument* pDoc)
563 // Extend the DB area to include data rows immediately below.
564 // or shrink it if all cells are empty
565 SCCOL nOldCol1 = nStartCol, nOldCol2 = nEndCol;
566 pDoc->GetDataArea(nTable, nStartCol, nStartRow, nEndCol, nEndRow, false, true);
567 if (nStartCol != nOldCol1 || nEndCol != nOldCol2)
568 ::std::vector<OUString>().swap( maTableColumnNames); // invalidate column names/offsets
571 void ScDBData::AdjustTableColumnNames( UpdateRefMode eUpdateRefMode, SCCOL nDx, SCCOL nCol1,
572 SCCOL nOldCol1, SCCOL nOldCol2, SCCOL nNewCol1, SCCOL nNewCol2 )
574 if (maTableColumnNames.empty())
575 return;
577 SCCOL nDiff1 = nNewCol1 - nOldCol1;
578 SCCOL nDiff2 = nNewCol2 - nOldCol2;
579 if (nDiff1 == nDiff2)
580 return; // not moved or entirely moved, nothing to do
582 ::std::vector<OUString> aNewNames;
583 if (eUpdateRefMode == URM_INSDEL)
585 // nCol1 is the first column of the block that gets shifted, determine
586 // the head and tail elements that are to be copied for deletion or
587 // insertion.
588 size_t nHead = static_cast<size_t>(::std::max( nCol1 + (nDx < 0 ? nDx : 0) - nOldCol1, 0));
589 size_t nTail = static_cast<size_t>(::std::max( nOldCol2 - nCol1 + 1, 0));
590 size_t n = nHead + nTail;
591 if (0 < n && n <= maTableColumnNames.size())
593 if (nDx > 0)
594 n += nDx;
595 aNewNames.resize(n);
596 // Copy head.
597 for (size_t i = 0; i < nHead; ++i)
599 aNewNames[i] = maTableColumnNames[i];
601 // Copy tail, inserted middle range, if any, stays empty.
602 for (size_t i = n - nTail, j = maTableColumnNames.size() - nTail; i < n; ++i, ++j)
604 aNewNames[i] = maTableColumnNames[j];
607 } // else empty aNewNames invalidates names/offsets
608 aNewNames.swap( maTableColumnNames);
611 namespace {
612 class TableColumnNameSearch : public unary_function<ScDBData, bool>
614 public:
615 explicit TableColumnNameSearch( const OUString& rSearchName ) :
616 maSearchName( rSearchName )
620 bool operator()( const OUString& rName ) const
622 return ScGlobal::GetpTransliteration()->isEqual( maSearchName, rName);
625 private:
626 OUString maSearchName;
630 sal_Int32 ScDBData::GetColumnNameOffset( const OUString& rName ) const
632 if (maTableColumnNames.empty())
633 return -1;
635 ::std::vector<OUString>::const_iterator it(
636 ::std::find_if( maTableColumnNames.begin(), maTableColumnNames.end(), TableColumnNameSearch( rName)));
637 if (it != maTableColumnNames.end())
638 return it - maTableColumnNames.begin();
640 return -1;
643 namespace {
645 class FindByTable : public unary_function<ScDBData, bool>
647 SCTAB mnTab;
648 public:
649 FindByTable(SCTAB nTab) : mnTab(nTab) {}
651 bool operator() (const ScDBData& r) const
653 ScRange aRange;
654 r.GetArea(aRange);
655 return aRange.aStart.Tab() == mnTab;
659 class UpdateRefFunc : public unary_function<ScDBData, void>
661 ScDocument* mpDoc;
662 UpdateRefMode meMode;
663 SCCOL mnCol1;
664 SCROW mnRow1;
665 SCTAB mnTab1;
666 SCCOL mnCol2;
667 SCROW mnRow2;
668 SCTAB mnTab2;
669 SCsCOL mnDx;
670 SCsROW mnDy;
671 SCsTAB mnDz;
673 public:
674 UpdateRefFunc(ScDocument* pDoc, UpdateRefMode eMode,
675 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
676 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
677 SCsCOL nDx, SCsROW nDy, SCsTAB nDz) :
678 mpDoc(pDoc), meMode(eMode),
679 mnCol1(nCol1), mnRow1(nRow1), mnTab1(nTab1),
680 mnCol2(nCol2), mnRow2(nRow2), mnTab2(nTab2),
681 mnDx(nDx), mnDy(nDy), mnDz(nDz) {}
683 void operator() (ScDBData& r)
685 r.UpdateReference(mpDoc, meMode, mnCol1, mnRow1, mnTab1, mnCol2, mnRow2, mnTab2, mnDx, mnDy, mnDz);
689 class UpdateMoveTabFunc : public unary_function<ScDBData, void>
691 SCTAB mnOldTab;
692 SCTAB mnNewTab;
693 public:
694 UpdateMoveTabFunc(SCTAB nOld, SCTAB nNew) : mnOldTab(nOld), mnNewTab(nNew) {}
695 void operator() (ScDBData& r)
697 r.UpdateMoveTab(mnOldTab, mnNewTab);
701 class FindByCursor : public unary_function<ScDBData, bool>
703 SCCOL mnCol;
704 SCROW mnRow;
705 SCTAB mnTab;
706 bool mbStartOnly;
707 public:
708 FindByCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) :
709 mnCol(nCol), mnRow(nRow), mnTab(nTab), mbStartOnly(bStartOnly) {}
711 bool operator() (const ScDBData& r)
713 return r.IsDBAtCursor(mnCol, mnRow, mnTab, mbStartOnly);
717 class FindByRange : public unary_function<ScDBData, bool>
719 const ScRange& mrRange;
720 public:
721 FindByRange(const ScRange& rRange) : mrRange(rRange) {}
723 bool operator() (const ScDBData& r)
725 return r.IsDBAtArea(
726 mrRange.aStart.Tab(), mrRange.aStart.Col(), mrRange.aStart.Row(), mrRange.aEnd.Col(), mrRange.aEnd.Row());
730 class FindByIndex : public unary_function<ScDBData, bool>
732 sal_uInt16 mnIndex;
733 public:
734 FindByIndex(sal_uInt16 nIndex) : mnIndex(nIndex) {}
735 bool operator() (const ScDBData& r) const
737 return r.GetIndex() == mnIndex;
741 class FindByUpperName : public unary_function<ScDBData, bool>
743 const OUString& mrName;
744 public:
745 FindByUpperName(const OUString& rName) : mrName(rName) {}
746 bool operator() (const ScDBData& r) const
748 return r.GetUpperName() == mrName;
752 class FindByPointer : public unary_function<ScDBData, bool>
754 const ScDBData* mpDBData;
755 public:
756 FindByPointer(const ScDBData* pDBData) : mpDBData(pDBData) {}
757 bool operator() (const ScDBData& r) const
759 return &r == mpDBData;
765 ScDBCollection::NamedDBs::NamedDBs(ScDBCollection& rParent, ScDocument& rDoc) :
766 mrParent(rParent), mrDoc(rDoc) {}
768 ScDBCollection::NamedDBs::NamedDBs(const NamedDBs& r) :
769 maDBs(r.maDBs), mrParent(r.mrParent), mrDoc(r.mrDoc) {}
771 ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::begin()
773 return maDBs.begin();
776 ScDBCollection::NamedDBs::iterator ScDBCollection::NamedDBs::end()
778 return maDBs.end();
781 ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::begin() const
783 return maDBs.begin();
786 ScDBCollection::NamedDBs::const_iterator ScDBCollection::NamedDBs::end() const
788 return maDBs.end();
791 ScDBData* ScDBCollection::NamedDBs::findByIndex(sal_uInt16 nIndex)
793 DBsType::iterator itr = find_if(
794 maDBs.begin(), maDBs.end(), FindByIndex(nIndex));
795 return itr == maDBs.end() ? NULL : &(*itr);
798 ScDBData* ScDBCollection::NamedDBs::findByUpperName(const OUString& rName)
800 DBsType::iterator itr = find_if(
801 maDBs.begin(), maDBs.end(), FindByUpperName(rName));
802 return itr == maDBs.end() ? NULL : &(*itr);
805 bool ScDBCollection::NamedDBs::insert(ScDBData* p)
807 unique_ptr<ScDBData> pData(p);
808 if (!pData->GetIndex())
809 pData->SetIndex(mrParent.nEntryIndex++);
811 pair<DBsType::iterator, bool> r = o3tl::ptr_container::insert(maDBs, std::move(pData));
813 if (r.second && p->HasImportParam() && !p->HasImportSelection())
815 p->SetRefreshHandler(mrParent.GetRefreshHandler());
816 p->SetRefreshControl(&mrDoc.GetRefreshTimerControlAddress());
818 return r.second;
821 void ScDBCollection::NamedDBs::erase(iterator itr)
823 maDBs.erase(itr);
826 void ScDBCollection::NamedDBs::erase(const ScDBData& r)
828 maDBs.erase(r);
831 bool ScDBCollection::NamedDBs::empty() const
833 return maDBs.empty();
836 size_t ScDBCollection::NamedDBs::size() const
838 return maDBs.size();
841 bool ScDBCollection::NamedDBs::operator== (const NamedDBs& r) const
843 return maDBs == r.maDBs;
846 ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::begin()
848 return maDBs.begin();
851 ScDBCollection::AnonDBs::iterator ScDBCollection::AnonDBs::end()
853 return maDBs.end();
856 ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::begin() const
858 return maDBs.begin();
861 ScDBCollection::AnonDBs::const_iterator ScDBCollection::AnonDBs::end() const
863 return maDBs.end();
866 const ScDBData* ScDBCollection::AnonDBs::findAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
868 DBsType::const_iterator itr = find_if(
869 maDBs.begin(), maDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
870 return itr == maDBs.end() ? NULL : &(*itr);
873 const ScDBData* ScDBCollection::AnonDBs::findByRange(const ScRange& rRange) const
875 DBsType::const_iterator itr = find_if(
876 maDBs.begin(), maDBs.end(), FindByRange(rRange));
877 return itr == maDBs.end() ? NULL : &(*itr);
880 void ScDBCollection::AnonDBs::deleteOnTab(SCTAB nTab)
882 FindByTable func(nTab);
883 maDBs.erase_if(func);
886 ScDBData* ScDBCollection::AnonDBs::getByRange(const ScRange& rRange)
888 const ScDBData* pData = findByRange(rRange);
889 if (!pData)
891 // Insert a new db data. They all have identical names.
892 OUString aName(STR_DB_GLOBAL_NONAME);
893 ::std::unique_ptr<ScDBData> pNew(new ScDBData(
894 aName, rRange.aStart.Tab(), rRange.aStart.Col(), rRange.aStart.Row(),
895 rRange.aEnd.Col(), rRange.aEnd.Row(), true, false, false));
896 pData = pNew.get();
897 o3tl::ptr_container::push_back(maDBs, std::move(pNew));
899 return const_cast<ScDBData*>(pData);
902 void ScDBCollection::AnonDBs::insert(ScDBData* p)
904 ::std::unique_ptr<ScDBData> pNew(p);
905 o3tl::ptr_container::push_back(maDBs, std::move(pNew));
908 bool ScDBCollection::AnonDBs::empty() const
910 return maDBs.empty();
913 bool ScDBCollection::AnonDBs::has( const ScDBData* p ) const
915 return find_if( maDBs.begin(), maDBs.end(), FindByPointer(p)) != maDBs.end();
918 bool ScDBCollection::AnonDBs::operator== (const AnonDBs& r) const
920 return maDBs == r.maDBs;
923 ScDBCollection::ScDBCollection(ScDocument* pDocument) :
924 pDoc(pDocument), nEntryIndex(1), maNamedDBs(*this, *pDocument) {}
926 ScDBCollection::ScDBCollection(const ScDBCollection& r) :
927 pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maNamedDBs(r.maNamedDBs), maAnonDBs(r.maAnonDBs) {}
929 const ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
931 // First, search the global named db ranges.
932 NamedDBs::DBsType::const_iterator itr = find_if(
933 maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
934 if (itr != maNamedDBs.end())
935 return &(*itr);
937 // Check for the sheet-local anonymous db range.
938 const ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
939 if (pNoNameData)
940 if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
941 return pNoNameData;
943 // Check the global anonymous db ranges.
944 const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
945 if (pData)
946 return pData;
948 return NULL;
951 ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly)
953 // First, search the global named db ranges.
954 NamedDBs::DBsType::iterator itr = find_if(
955 maNamedDBs.begin(), maNamedDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly));
956 if (itr != maNamedDBs.end())
957 return &(*itr);
959 // Check for the sheet-local anonymous db range.
960 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
961 if (pNoNameData)
962 if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly))
963 return pNoNameData;
965 // Check the global anonymous db ranges.
966 const ScDBData* pData = getAnonDBs().findAtCursor(nCol, nRow, nTab, bStartOnly);
967 if (pData)
968 return const_cast<ScDBData*>(pData);
970 return NULL;
973 const ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
975 // First, search the global named db ranges.
976 ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
977 NamedDBs::DBsType::const_iterator itr = find_if(
978 maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
979 if (itr != maNamedDBs.end())
980 return &(*itr);
982 // Check for the sheet-local anonymous db range.
983 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
984 if (pNoNameData)
985 if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
986 return pNoNameData;
988 // Lastly, check the global anonymous db ranges.
989 return maAnonDBs.findByRange(aRange);
992 ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
994 // First, search the global named db ranges.
995 ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
996 NamedDBs::DBsType::iterator itr = find_if(
997 maNamedDBs.begin(), maNamedDBs.end(), FindByRange(aRange));
998 if (itr != maNamedDBs.end())
999 return &(*itr);
1001 // Check for the sheet-local anonymous db range.
1002 ScDBData* pNoNameData = pDoc->GetAnonymousDBData(nTab);
1003 if (pNoNameData)
1004 if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2))
1005 return pNoNameData;
1007 // Lastly, check the global anonymous db ranges.
1008 const ScDBData* pData = getAnonDBs().findByRange(aRange);
1009 if (pData)
1010 return const_cast<ScDBData*>(pData);
1012 return NULL;
1015 void ScDBCollection::DeleteOnTab( SCTAB nTab )
1017 FindByTable func(nTab);
1018 // First, collect the positions of all items that need to be deleted.
1019 ::std::vector<NamedDBs::DBsType::iterator> v;
1021 NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
1022 for (; itr != itrEnd; ++itr)
1024 if (func(*itr))
1025 v.push_back(itr);
1029 // Delete them all.
1030 ::std::vector<NamedDBs::DBsType::iterator>::iterator itr = v.begin(), itrEnd = v.end();
1031 for (; itr != itrEnd; ++itr)
1032 maNamedDBs.erase(*itr);
1034 maAnonDBs.deleteOnTab(nTab);
1037 void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode,
1038 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1039 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1040 SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1042 ScDBData* pData = pDoc->GetAnonymousDBData(nTab1);
1043 if (pData)
1045 if (nTab1 == nTab2 && nDz == 0)
1047 pData->UpdateReference(
1048 pDoc, eUpdateRefMode,
1049 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
1051 else
1053 //this will perhabs break undo
1057 UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz);
1058 for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
1059 for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
1062 void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
1064 UpdateMoveTabFunc func(nOldPos, nNewPos);
1065 for_each(maNamedDBs.begin(), maNamedDBs.end(), func);
1066 for_each(maAnonDBs.begin(), maAnonDBs.end(), func);
1069 ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab )
1071 ScDBData* pNearData = NULL;
1072 NamedDBs::DBsType::iterator itr = maNamedDBs.begin(), itrEnd = maNamedDBs.end();
1073 for (; itr != itrEnd; ++itr)
1075 SCTAB nAreaTab;
1076 SCCOL nStartCol, nEndCol;
1077 SCROW nStartRow, nEndRow;
1078 itr->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1079 if ( nTab == nAreaTab && nCol+1 >= nStartCol && nCol <= nEndCol+1 &&
1080 nRow+1 >= nStartRow && nRow <= nEndRow+1 )
1082 if ( nCol < nStartCol || nCol > nEndCol || nRow < nStartRow || nRow > nEndRow )
1084 if (!pNearData)
1085 pNearData = &(*itr); // ersten angrenzenden Bereich merken
1087 else
1088 return &(*itr); // nicht "unbenannt" und Cursor steht wirklich drin
1091 if (pNearData)
1092 return pNearData; // angrenzender, wenn nichts direkt getroffen
1093 return pDoc->GetAnonymousDBData(nTab); // "unbenannt" nur zurueck, wenn sonst nichts gefunden
1096 bool ScDBCollection::empty() const
1098 return maNamedDBs.empty() && maAnonDBs.empty();
1101 bool ScDBCollection::operator== (const ScDBCollection& r) const
1103 return maNamedDBs == r.maNamedDBs && maAnonDBs == r.maAnonDBs &&
1104 nEntryIndex == r.nEntryIndex && pDoc == r.pDoc && aRefreshHandler == r.aRefreshHandler;
1107 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */