diff options
author | Kohei Yoshida <kyoshida@novell.com> | 2011-03-31 23:52:33 -0400 |
---|---|---|
committer | Kohei Yoshida <kyoshida@novell.com> | 2011-04-01 00:11:03 -0400 |
commit | 1b059829bc6698c15c6bb5459a61348ac56ffda5 (patch) | |
tree | 56da868d442162213304709c653369037233d48f | |
parent | 8dcd3e554cf1eb1f92419ae6b55213accec656a4 (diff) |
Added container to store global anonymous db ranges.
This is needed to support multiple subtotal ranges.
-rw-r--r-- | sc/inc/dbcolect.hxx | 25 | ||||
-rw-r--r-- | sc/source/core/tool/dbcolect.cxx | 185 | ||||
-rw-r--r-- | sc/source/filter/xml/XMLExportDatabaseRanges.cxx | 10 | ||||
-rw-r--r-- | sc/source/filter/xml/xmldrani.cxx | 23 |
4 files changed, 219 insertions, 24 deletions
diff --git a/sc/inc/dbcolect.hxx b/sc/inc/dbcolect.hxx index 251325715d06..d8c36b1afa0f 100644 --- a/sc/inc/dbcolect.hxx +++ b/sc/inc/dbcolect.hxx @@ -38,6 +38,8 @@ #include "scdllapi.h" #include "subtotalparam.hxx" +#include <boost/ptr_container/ptr_vector.hpp> + class ScDocument; class ScDBData : public ScDataObject, public ScRefreshTimer @@ -178,22 +180,25 @@ public: void SetModified(sal_Bool bMod) { bModified = bMod; } void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ); - void UpdateReference(UpdateRefMode eUpdateRefMode, + void UpdateReference(ScDocument* pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, - SCsCOL nDx, SCsROW nDy, SCsTAB nDz, - ScDocument* pDoc ); + SCsCOL nDx, SCsROW nDy, SCsTAB nDz); }; //------------------------------------------------------------------------ class SC_DLLPUBLIC ScDBCollection : public ScSortedCollection { + typedef ::boost::ptr_vector<ScDBData> DBRangesType; +public: + typedef DBRangesType AnonDBsType; private: Link aRefreshHandler; ScDocument* pDoc; sal_uInt16 nEntryIndex; // counter for unique indices + AnonDBsType maAnonDBs; public: ScDBCollection(sal_uInt16 nLim = 4, sal_uInt16 nDel = 4, sal_Bool bDup = false, ScDocument* pDocument = NULL) : @@ -201,11 +206,8 @@ public: pDoc ( pDocument ), nEntryIndex ( SC_START_INDEX_DB_COLL ) // see above for the names {} - ScDBCollection(const ScDBCollection& rScDBCollection) : - ScSortedCollection ( rScDBCollection ), - pDoc ( rScDBCollection.pDoc ), - nEntryIndex ( rScDBCollection.nEntryIndex) - {} + + ScDBCollection(const ScDBCollection& r); virtual ScDataObject* Clone() const { return new ScDBCollection(*this); } ScDBData* operator[]( const sal_uInt16 nIndex) const {return (ScDBData*)At(nIndex);} @@ -232,6 +234,13 @@ public: void SetRefreshHandler( const Link& rLink ) { aRefreshHandler = rLink; } const Link& GetRefreshHandler() const { return aRefreshHandler; } + + const ScDBData* findAnonAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const; + const ScDBData* findAnonByRange(const ScRange& rRange) const; + ScDBData* getAnonByRange(const ScRange& rRange); + void insertAnonRange(ScDBData* pData); + + const AnonDBsType& getAnonRanges() const; }; #endif diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx index 8159cb2b6fec..bd5598d785ff 100644 --- a/sc/source/core/tool/dbcolect.cxx +++ b/sc/source/core/tool/dbcolect.cxx @@ -43,6 +43,13 @@ #include "globstr.hrc" #include "subtotalparam.hxx" +#include <memory> + +using ::std::unary_function; +using ::std::for_each; +using ::std::find_if; +using ::std::remove_if; + //--------------------------------------------------------------------------------------- ScDBData::ScDBData( const String& rName, @@ -612,11 +619,10 @@ void ScDBData::UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos) } -void ScDBData::UpdateReference(UpdateRefMode eUpdateRefMode, +void ScDBData::UpdateReference(ScDocument* pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, - SCsCOL nDx, SCsROW nDy, SCsTAB nDz, - ScDocument* pDoc ) + SCsCOL nDx, SCsROW nDy, SCsTAB nDz) { SCCOL theCol1; SCROW theRow1; @@ -653,8 +659,99 @@ void ScDBData::UpdateReference(UpdateRefMode eUpdateRefMode, //! Testen, ob mitten aus dem Bereich geloescht/eingefuegt wurde !!! } -//--------------------------------------------------------------------------------------- -// Compare zum Sortieren + +namespace { + +class FindByTable : public ::std::unary_function<ScDBData, bool> +{ + SCTAB mnTab; +public: + FindByTable(SCTAB nTab) : mnTab(nTab) {} + + bool operator() (const ScDBData& r) const + { + ScRange aRange; + r.GetArea(aRange); + return aRange.aStart.Tab() == mnTab; + } +}; + +class UpdateRefFunc : public unary_function<ScDBData, void> +{ + ScDocument* mpDoc; + UpdateRefMode meMode; + SCCOL mnCol1; + SCROW mnRow1; + SCTAB mnTab1; + SCCOL mnCol2; + SCROW mnRow2; + SCTAB mnTab2; + SCsCOL mnDx; + SCsROW mnDy; + SCsTAB mnDz; + +public: + UpdateRefFunc(ScDocument* pDoc, UpdateRefMode eMode, + SCCOL nCol1, SCROW nRow1, SCTAB nTab1, + SCCOL nCol2, SCROW nRow2, SCTAB nTab2, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz) : + mpDoc(pDoc), meMode(eMode), + mnCol1(nCol1), mnRow1(nRow1), mnTab1(nTab1), + mnCol2(nCol2), mnRow2(nRow2), mnTab2(nTab2), + mnDx(nDx), mnDy(nDy), mnDz(nDz) {} + + void operator() (ScDBData& r) + { + r.UpdateReference(mpDoc, meMode, mnCol1, mnRow1, mnTab1, mnCol2, mnRow2, mnTab2, mnDx, mnDy, mnDz); + } +}; + +class UpdateMoveTabFunc : public unary_function<ScDBData, void> +{ + SCTAB mnOldTab; + SCTAB mnNewTab; +public: + UpdateMoveTabFunc(SCTAB nOld, SCTAB nNew) : mnOldTab(nOld), mnNewTab(nNew) {} + void operator() (ScDBData& r) + { + r.UpdateMoveTab(mnOldTab, mnNewTab); + } +}; + +class FindByCursor : public unary_function<ScDBData, bool> +{ + SCCOL mnCol; + SCROW mnRow; + SCTAB mnTab; + bool mbStartOnly; +public: + FindByCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) : + mnCol(nCol), mnRow(nRow), mnTab(nTab), mbStartOnly(bStartOnly) {} + + bool operator() (const ScDBData& r) + { + return r.IsDBAtCursor(mnCol, mnRow, mnTab, mbStartOnly); + } +}; + +class FindByRange : public unary_function<ScDBData, bool> +{ + const ScRange& mrRange; +public: + FindByRange(const ScRange& rRange) : mrRange(rRange) {} + + bool operator() (const ScDBData& r) + { + return r.IsDBAtArea( + mrRange.aStart.Tab(), mrRange.aStart.Col(), mrRange.aStart.Row(), mrRange.aEnd.Col(), mrRange.aEnd.Row()); + } +}; + +} + +ScDBCollection::ScDBCollection(const ScDBCollection& r) : + ScSortedCollection(r), pDoc(r.pDoc), nEntryIndex(r.nEntryIndex), maAnonDBs(r.maAnonDBs) +{} short ScDBCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const { @@ -687,6 +784,12 @@ ScDBData* ScDBCollection::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_ if (pNoNameData) if (pNoNameData->IsDBAtCursor(nCol,nRow,nTab,bStartOnly)) return pNoNameData; + + // Check the anonymous db ranges. + const ScDBData* pData = findAnonAtCursor(nCol, nRow, nTab, bStartOnly); + if (pData) + return const_cast<ScDBData*>(pData); + return NULL; } @@ -705,6 +808,13 @@ ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCO if (pNoNameData) if (pNoNameData->IsDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2)) return pNoNameData; + + // Check the anonymous db ranges. + ScRange aRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab); + const ScDBData* pData = findAnonByRange(aRange); + if (pData) + return const_cast<ScDBData*>(pData); + return NULL; } @@ -732,6 +842,8 @@ void ScDBCollection::DeleteOnTab( SCTAB nTab ) else ++nPos; } + + remove_if(maAnonDBs.begin(), maAnonDBs.end(), FindByTable(nTab)); } void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode, @@ -741,26 +853,27 @@ void ScDBCollection::UpdateReference(UpdateRefMode eUpdateRefMode, { for (sal_uInt16 i=0; i<nCount; i++) { - ((ScDBData*)pItems[i])->UpdateReference(eUpdateRefMode, - nCol1, nRow1, nTab1, - nCol2, nRow2, nTab2, - nDx, nDy, nDz, pDoc); + ((ScDBData*)pItems[i])->UpdateReference( + pDoc, eUpdateRefMode, + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz); } ScDBData* pData = pDoc->GetAnonymousDBData(nTab1); if (pData) { - if (nTab1==nTab2&&nDz==0) + if (nTab1 == nTab2 && nDz == 0) { - pData->UpdateReference(eUpdateRefMode, - nCol1, nRow1, nTab1, - nCol2, nRow2, nTab2, - nDx, nDy, nDz, pDoc); + pData->UpdateReference( + pDoc, eUpdateRefMode, + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz); } else { //this will perhabs break undo } } + + UpdateRefFunc func(pDoc, eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz); + for_each(maAnonDBs.begin(), maAnonDBs.end(), func); } @@ -773,6 +886,9 @@ void ScDBCollection::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ) ScDBData* pData = (ScDBData*)pItems[i]; pData->UpdateMoveTab(nOldPos, nNewPos); } + + UpdateMoveTabFunc func(nOldPos, nNewPos); + for_each(maAnonDBs.begin(), maAnonDBs.end(), func); } @@ -829,5 +945,46 @@ ScDBData* ScDBCollection::GetDBNearCursor(SCCOL nCol, SCROW nRow, SCTAB nTab ) return pDoc->GetAnonymousDBData(nTab); // "unbenannt" nur zurueck, wenn sonst nichts gefunden } +const ScDBData* ScDBCollection::findAnonAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const +{ + AnonDBsType::const_iterator itr = find_if( + maAnonDBs.begin(), maAnonDBs.end(), FindByCursor(nCol, nRow, nTab, bStartOnly)); + return itr == maAnonDBs.end() ? NULL : &(*itr); +} + +const ScDBData* ScDBCollection::findAnonByRange(const ScRange& rRange) const +{ + AnonDBsType::const_iterator itr = find_if( + maAnonDBs.begin(), maAnonDBs.end(), FindByRange(rRange)); + return itr == maAnonDBs.end() ? NULL : &(*itr); +} + +ScDBData* ScDBCollection::getAnonByRange(const ScRange& rRange) +{ + const ScDBData* pData = findAnonByRange(rRange); + if (!pData) + { + // Insert a new db data. They all have identical names. + rtl::OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME)); + ::std::auto_ptr<ScDBData> pNew(new ScDBData( + aName, rRange.aStart.Tab(), rRange.aStart.Col(), rRange.aStart.Row(), + rRange.aEnd.Col(), rRange.aEnd.Row(), true, false)); + pData = pNew.get(); + maAnonDBs.push_back(pNew); + } + return const_cast<ScDBData*>(pData); +} + +void ScDBCollection::insertAnonRange(ScDBData* pData) +{ + rtl::OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME)); + ::std::auto_ptr<ScDBData> pNew(pData); + maAnonDBs.push_back(pNew); +} + +const ScDBCollection::AnonDBsType& ScDBCollection::getAnonRanges() const +{ + return maAnonDBs; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx index cb711d39898a..44e28332dd57 100644 --- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx @@ -1109,8 +1109,9 @@ void ScXMLExportDatabaseRanges::WriteDatabaseRanges(const com::sun::star::uno::R // See if we have global ranges. ScDBCollection* pDBCollection = pDoc->GetDBCollection(); - if (pDBCollection && pDBCollection->GetCount() > 0) - bHasRanges = true; + if (pDBCollection) + if (pDBCollection->GetCount() > 0 || !pDBCollection->getAnonRanges().empty()) + bHasRanges = true; if (!bHasRanges) // No ranges to export. Bail out. @@ -1209,8 +1210,13 @@ void ScXMLExportDatabaseRanges::WriteDatabaseRanges(const com::sun::star::uno::R } WriteDatabaseRange func(rExport, pDoc); + // Write sheet-local ranges. ::std::for_each(aSheetDBs.begin(), aSheetDBs.end(), func); + + // Add global anonymous DB ranges. + const ScDBCollection::AnonDBsType& rAnonDBs = pDBCollection->getAnonRanges(); + ::std::for_each(rAnonDBs.begin(), rAnonDBs.end(), func); } } diff --git a/sc/source/filter/xml/xmldrani.cxx b/sc/source/filter/xml/xmldrani.cxx index 301c3e369d1a..789dbee09a42 100644 --- a/sc/source/filter/xml/xmldrani.cxx +++ b/sc/source/filter/xml/xmldrani.cxx @@ -224,6 +224,8 @@ ScXMLDatabaseRangeContext::ScXMLDatabaseRangeContext( ScXMLImport& rImport, if (sDatabaseRangeName.matchAsciiL(STR_DB_LOCAL_NONAME, strlen(STR_DB_LOCAL_NONAME))) meRangeType = SheetAnonymous; + else if (sDatabaseRangeName.matchAsciiL(STR_DB_GLOBAL_NONAME, strlen(STR_DB_GLOBAL_NONAME))) + meRangeType = GlobalAnonymous; } ScXMLDatabaseRangeContext::~ScXMLDatabaseRangeContext() @@ -482,6 +484,27 @@ void ScXMLDatabaseRangeContext::EndElement() } return; } + else if (meRangeType == GlobalAnonymous) + { + OUString aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_GLOBAL_NONAME)); + ::std::auto_ptr<ScDBData> pData(ConvertToDBData(aName)); + + if (pData.get()) + { + if (pData->HasAutoFilter()) + { + // Set autofilter flags so that the buttons get displayed. + ScRange aRange; + pData->GetArea(aRange); + pDoc->ApplyFlagsTab( + aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), SC_MF_AUTO); + } + + pDoc->GetDBCollection()->insertAnonRange(pData.release()); + } + return; + } if (GetScImport().GetModel().is()) { |