summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kyoshida@novell.com>2011-03-31 23:52:33 -0400
committerKohei Yoshida <kyoshida@novell.com>2011-04-01 00:11:03 -0400
commit1b059829bc6698c15c6bb5459a61348ac56ffda5 (patch)
tree56da868d442162213304709c653369037233d48f
parent8dcd3e554cf1eb1f92419ae6b55213accec656a4 (diff)
Added container to store global anonymous db ranges.
This is needed to support multiple subtotal ranges.
-rw-r--r--sc/inc/dbcolect.hxx25
-rw-r--r--sc/source/core/tool/dbcolect.cxx185
-rw-r--r--sc/source/filter/xml/XMLExportDatabaseRanges.cxx10
-rw-r--r--sc/source/filter/xml/xmldrani.cxx23
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())
{