sc/inc/dpfilteredcache.hxx              |    5 
 sc/source/core/data/dpfilteredcache.cxx |   12 +
 sc/source/core/data/dpgroup.cxx         |  300 +++++++++++++++++++-------------
 3 files changed, 201 insertions(+), 116 deletions(-)

New commits:
commit 6877ddc50d601f57d4cf77379ae613a33df19711
Author: Kohei Yoshida <kohei.yosh...@gmail.com>
Date:   Sat Jul 13 16:59:16 2013 -0400

    fdo#63998: Filtering by page fields to work again.
    
    Conflicts:
        sc/source/core/data/dpgroup.cxx
    
    Change-Id: I267ccb30cfa6347313fa1de96e18731f0e22d57d
    Reviewed-on: https://gerrit.libreoffice.org/4897
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Eike Rathke <er...@redhat.com>

diff --git a/sc/inc/dpfilteredcache.hxx b/sc/inc/dpfilteredcache.hxx
index 9caa2f8..c0002f2 100644
--- a/sc/inc/dpfilteredcache.hxx
+++ b/sc/inc/dpfilteredcache.hxx
@@ -56,6 +56,8 @@ public:
         /** returns true if the matching condition is met for a single cell
             value, or false otherwise. */
         virtual bool match( const  ScDPItemData& rCellData ) const = 0;
+
+        virtual std::vector<ScDPItemData> getMatchValues() const = 0;
     };
 
     /** ordinary single-item filter. */
@@ -66,7 +68,7 @@ public:
         virtual ~SingleFilter() {}
 
         virtual bool match(const ScDPItemData& rCellData) const;
-
+        virtual std::vector<ScDPItemData> getMatchValues() const;
         const ScDPItemData& getMatchValue() const;
 
     private:
@@ -82,6 +84,7 @@ public:
         GroupFilter();
         virtual ~GroupFilter() {}
         virtual bool match(const ScDPItemData& rCellData) const;
+        virtual std::vector<ScDPItemData> getMatchValues() const;
         void addMatchItem(const ScDPItemData& rItem);
         size_t getMatchItemCount() const;
 
diff --git a/sc/source/core/data/dpfilteredcache.cxx 
b/sc/source/core/data/dpfilteredcache.cxx
index ff82719..44e249f 100644
--- a/sc/source/core/data/dpfilteredcache.cxx
+++ b/sc/source/core/data/dpfilteredcache.cxx
@@ -63,6 +63,13 @@ bool ScDPFilteredCache::SingleFilter::match(const 
ScDPItemData& rCellData) const
     return maItem == rCellData;
 }
 
+std::vector<ScDPItemData> ScDPFilteredCache::SingleFilter::getMatchValues() 
const
+{
+    std::vector<ScDPItemData> aValues;
+    aValues.push_back(maItem);
+    return aValues;
+}
+
 const ScDPItemData& ScDPFilteredCache::SingleFilter::getMatchValue() const
 {
     return maItem;
@@ -84,6 +91,11 @@ bool ScDPFilteredCache::GroupFilter::match(const 
ScDPItemData& rCellData) const
     return false;
 }
 
+std::vector<ScDPItemData> ScDPFilteredCache::GroupFilter::getMatchValues() 
const
+{
+    return maItems;
+}
+
 void ScDPFilteredCache::GroupFilter::addMatchItem(const ScDPItemData& rItem)
 {
     maItems.push_back(rItem);
diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx
index 614b5b5..392173e 100644
--- a/sc/source/core/data/dpgroup.cxx
+++ b/sc/source/core/data/dpgroup.cxx
@@ -57,41 +57,58 @@ const sal_uInt16 SC_DP_LEAPYEAR = 1648;     // arbitrary 
leap year for date calc
 class ScDPGroupNumFilter : public ScDPFilteredCache::FilterBase
 {
 public:
-    ScDPGroupNumFilter(const ScDPItemData& rValue, const ScDPNumGroupInfo& 
rInfo);
+    ScDPGroupNumFilter(const std::vector<ScDPItemData>& rValues, const 
ScDPNumGroupInfo& rInfo);
     virtual ~ScDPGroupNumFilter() {}
     virtual bool match(const ScDPItemData &rCellData) const;
+    virtual std::vector<ScDPItemData> getMatchValues() const;
 private:
-    ScDPItemData maValue;
+    std::vector<ScDPItemData> maValues;
     ScDPNumGroupInfo maNumInfo;
 };
 
-ScDPGroupNumFilter::ScDPGroupNumFilter(const ScDPItemData& rValue, const 
ScDPNumGroupInfo& rInfo) :
-    maValue(rValue), maNumInfo(rInfo) {}
+ScDPGroupNumFilter::ScDPGroupNumFilter(const std::vector<ScDPItemData>& 
rValues, const ScDPNumGroupInfo& rInfo) :
+    maValues(rValues), maNumInfo(rInfo) {}
 
 bool ScDPGroupNumFilter::match(const ScDPItemData& rCellData) const
 {
     if (rCellData.GetType() != ScDPItemData::Value)
         return false;
 
-    double fVal = maValue.GetValue();
-    if (rtl::math::isInf(fVal))
+    std::vector<ScDPItemData>::const_iterator it = maValues.begin(), itEnd = 
maValues.end();
+    for (; it != itEnd; ++it)
     {
-        if (rtl::math::isSignBitSet(fVal))
+        double fVal = it->GetValue();
+        if (rtl::math::isInf(fVal))
         {
-            // Less than the min value.
-            return rCellData.GetValue() < maNumInfo.mfStart;
+            if (rtl::math::isSignBitSet(fVal))
+            {
+                // Less than the min value.
+                if (rCellData.GetValue() < maNumInfo.mfStart)
+                    return true;
+            }
+
+            // Greater than the max value.
+            if (maNumInfo.mfEnd < rCellData.GetValue())
+                return true;
+
+            continue;
         }
 
-        // Greater than the max value.
-        return maNumInfo.mfEnd < rCellData.GetValue();
+        double low = fVal;
+        double high = low + maNumInfo.mfStep;
+        if (maNumInfo.mbIntegerOnly)
+            high += 1.0;
+
+        if (low <= rCellData.GetValue() && rCellData.GetValue() < high)
+            return true;
     }
 
-    double low = fVal;
-    double high = low + maNumInfo.mfStep;
-    if (maNumInfo.mbIntegerOnly)
-        high += 1.0;
+    return false;
+}
 
-    return low <= rCellData.GetValue() && rCellData.GetValue() < high;
+std::vector<ScDPItemData> ScDPGroupNumFilter::getMatchValues() const
+{
+    return std::vector<ScDPItemData>();
 }
 
 class ScDPGroupDateFilter : public ScDPFilteredCache::FilterBase
@@ -99,14 +116,15 @@ class ScDPGroupDateFilter : public 
ScDPFilteredCache::FilterBase
 public:
     virtual ~ScDPGroupDateFilter() {}
     ScDPGroupDateFilter(
-        const ScDPItemData& rValue, const Date& rNullDate, const 
ScDPNumGroupInfo& rNumInfo);
+        const std::vector<ScDPItemData>& rValues, const Date& rNullDate, const 
ScDPNumGroupInfo& rNumInfo);
 
     virtual bool match(const ScDPItemData & rCellData) const;
+    virtual std::vector<ScDPItemData> getMatchValues() const;
 
 private:
     ScDPGroupDateFilter(); // disabled
 
-    ScDPItemData     maValue;
+    std::vector<ScDPItemData> maValues;
     Date             maNullDate;
     ScDPNumGroupInfo maNumInfo;
 };
@@ -114,8 +132,8 @@ private:
 // ----------------------------------------------------------------------------
 
 ScDPGroupDateFilter::ScDPGroupDateFilter(
-    const ScDPItemData& rItem, const Date& rNullDate, const ScDPNumGroupInfo& 
rNumInfo) :
-    maValue(rItem),
+    const std::vector<ScDPItemData>& rValues, const Date& rNullDate, const 
ScDPNumGroupInfo& rNumInfo) :
+    maValues(rValues),
     maNullDate(rNullDate),
     maNumInfo(rNumInfo)
 {
@@ -130,94 +148,122 @@ bool ScDPGroupDateFilter::match( const ScDPItemData & 
rCellData ) const
     if ( !rCellData.IsValue() )
         return false;
 
-    if (maValue.GetType() != ScDPItemData::GroupValue)
-        return false;
+    std::vector<ScDPItemData>::const_iterator it = maValues.begin(), itEnd = 
maValues.end();
+    for (; it != itEnd; ++it)
+    {
+        const ScDPItemData& rValue = *it;
+        if (rValue.GetType() != ScDPItemData::GroupValue)
+            continue;
 
-    sal_Int32 nGroupType = maValue.GetGroupValue().mnGroupType;
-    sal_Int32 nValue = maValue.GetGroupValue().mnValue;
+        sal_Int32 nGroupType = rValue.GetGroupValue().mnGroupType;
+        sal_Int32 nValue = rValue.GetGroupValue().mnValue;
 
-    // Start and end dates are inclusive.  (An end date without a time value
-    // is included, while an end date with a time value is not.)
+        // Start and end dates are inclusive.  (An end date without a time 
value
+        // is included, while an end date with a time value is not.)
 
-    if ( rCellData.GetValue() < maNumInfo.mfStart && 
!approxEqual(rCellData.GetValue(), maNumInfo.mfStart) )
-    {
-        return nValue == ScDPItemData::DateFirst;
-    }
+        if (rCellData.GetValue() < maNumInfo.mfStart && 
!approxEqual(rCellData.GetValue(), maNumInfo.mfStart))
+        {
+            if (nValue == ScDPItemData::DateFirst)
+                return true;
+            continue;
+        }
 
-    if ( rCellData.GetValue() > maNumInfo.mfEnd && 
!approxEqual(rCellData.GetValue(), maNumInfo.mfEnd) )
-    {
-        return nValue == ScDPItemData::DateLast;
-    }
+        if (rCellData.GetValue() > maNumInfo.mfEnd && 
!approxEqual(rCellData.GetValue(), maNumInfo.mfEnd))
+        {
+            if (nValue == ScDPItemData::DateLast)
+                return true;
+            continue;
+        }
 
+        if (nGroupType == DataPilotFieldGroupBy::HOURS || nGroupType == 
DataPilotFieldGroupBy::MINUTES ||
+            nGroupType == DataPilotFieldGroupBy::SECONDS)
+        {
+            // handle time
+            // (as in the cell functions, ScInterpreter::ScGetHour etc.: 
seconds are rounded)
 
-    if (nGroupType == DataPilotFieldGroupBy::HOURS || nGroupType == 
DataPilotFieldGroupBy::MINUTES ||
-        nGroupType == DataPilotFieldGroupBy::SECONDS)
-    {
-        // handle time
-        // (as in the cell functions, ScInterpreter::ScGetHour etc.: seconds 
are rounded)
+            double time = rCellData.GetValue() - 
approxFloor(rCellData.GetValue());
+            long seconds = static_cast<long>(approxFloor(time*D_TIMEFACTOR + 
0.5));
 
-        double time = rCellData.GetValue() - approxFloor(rCellData.GetValue());
-        long seconds = static_cast<long>(approxFloor(time*D_TIMEFACTOR + 0.5));
+            switch (nGroupType)
+            {
+                case DataPilotFieldGroupBy::HOURS:
+                {
+                    sal_Int32 hrs = seconds / 3600;
+                    if (hrs == nValue)
+                        return true;
+                }
+                break;
+                case DataPilotFieldGroupBy::MINUTES:
+                {
+                    sal_Int32 minutes = (seconds % 3600) / 60;
+                    if (minutes == nValue)
+                        return true;
+                }
+                break;
+                case DataPilotFieldGroupBy::SECONDS:
+                {
+                    sal_Int32 sec = seconds % 60;
+                    if (sec == nValue)
+                        return true;
+                }
+                break;
+                default:
+                    OSL_FAIL("invalid time part");
+            }
+
+            continue;
+        }
 
+        Date date = maNullDate + 
static_cast<long>(approxFloor(rCellData.GetValue()));
         switch (nGroupType)
         {
-            case DataPilotFieldGroupBy::HOURS:
+            case DataPilotFieldGroupBy::YEARS:
             {
-                sal_Int32 hrs = seconds / 3600;
-                return hrs == nValue;
+                sal_Int32 year = static_cast<sal_Int32>(date.GetYear());
+                if (year == nValue)
+                    return true;
             }
-            case DataPilotFieldGroupBy::MINUTES:
+            break;
+            case DataPilotFieldGroupBy::QUARTERS:
             {
-                sal_Int32 minutes = (seconds % 3600) / 60;
-                return minutes == nValue;
+                sal_Int32 qtr =  1 + (static_cast<sal_Int32>(date.GetMonth()) 
- 1) / 3;
+                if (qtr == nValue)
+                    return true;
             }
-            case DataPilotFieldGroupBy::SECONDS:
+            break;
+            case DataPilotFieldGroupBy::MONTHS:
             {
-                sal_Int32 sec = seconds % 60;
-                return sec == nValue;
+                sal_Int32 month = static_cast<sal_Int32>(date.GetMonth());
+                if (month == nValue)
+                    return true;
             }
-            default:
-                OSL_FAIL("invalid time part");
-        }
-        return false;
-    }
-
-    Date date = maNullDate + 
static_cast<long>(approxFloor(rCellData.GetValue()));
-    switch (nGroupType)
-    {
-        case DataPilotFieldGroupBy::YEARS:
-        {
-            sal_Int32 year = static_cast<sal_Int32>(date.GetYear());
-            return year == nValue;
-        }
-        case DataPilotFieldGroupBy::QUARTERS:
-        {
-            sal_Int32 qtr =  1 + (static_cast<sal_Int32>(date.GetMonth()) - 1) 
/ 3;
-            return qtr == nValue;
-        }
-        case DataPilotFieldGroupBy::MONTHS:
-        {
-            sal_Int32 month = static_cast<sal_Int32>(date.GetMonth());
-            return month == nValue;
-        }
-        case DataPilotFieldGroupBy::DAYS:
-        {
-            Date yearStart(1, 1, date.GetYear());
-            sal_Int32 days = (date - yearStart) + 1;       // Jan 01 has value 
1
-            if (days >= 60 && !date.IsLeapYear())
+            break;
+            case DataPilotFieldGroupBy::DAYS:
             {
-                // This is not a leap year.  Adjust the value accordingly.
-                ++days;
+                Date yearStart(1, 1, date.GetYear());
+                sal_Int32 days = (date - yearStart) + 1;       // Jan 01 has 
value 1
+                if (days >= 60 && !date.IsLeapYear())
+                {
+                    // This is not a leap year.  Adjust the value accordingly.
+                    ++days;
+                }
+                if (days == nValue)
+                    return true;
             }
-            return days == nValue;
+            break;
+            default:
+                OSL_FAIL("invalid date part");
         }
-        default:
-            OSL_FAIL("invalid date part");
     }
 
     return false;
 }
 
+std::vector<ScDPItemData> ScDPGroupDateFilter::getMatchValues() const
+{
+    return std::vector<ScDPItemData>();
+}
+
 namespace {
 
 bool isDateInGroup(const ScDPItemData& rGroupItem, const ScDPItemData& 
rChildItem)
@@ -619,14 +665,34 @@ void ScDPGroupTableData::CreateCacheTable()
     pSourceData->CreateCacheTable();
 }
 
+namespace {
+
+class FindCaseInsensitive : std::unary_function<ScDPItemData, bool>
+{
+    ScDPItemData maValue;
+public:
+    FindCaseInsensitive(const ScDPItemData& rVal) : maValue(rVal) {}
+
+    bool operator() (const ScDPItemData& rItem) const
+    {
+        return maValue.IsCaseInsEqual(rItem);
+    }
+};
+
+}
+
 void 
ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterion>& 
rCriteria)
 {
+    // Build dimension ID to object map for group dimensions.
     typedef boost::unordered_map<long, const ScDPGroupDimension*> 
GroupFieldMapType;
     GroupFieldMapType aGroupFieldIds;
     {
         ScDPGroupDimensionVec::const_iterator itr = aGroups.begin(), itrEnd = 
aGroups.end();
         for (; itr != itrEnd; ++itr)
-            aGroupFieldIds.insert( boost::unordered_map<long, const 
ScDPGroupDimension*>::value_type(itr->GetGroupDim(), &(*itr)) );
+        {
+            aGroupFieldIds.insert(
+                GroupFieldMapType::value_type(itr->GetGroupDim(), &(*itr)));
+        }
     }
 
     vector<ScDPFilteredCache::Criterion> aNewCriteria;
@@ -639,10 +705,7 @@ void 
ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
     GroupFieldMapType::const_iterator itrGrpEnd = aGroupFieldIds.end();
     for (vector<ScDPFilteredCache::Criterion>::const_iterator itr = 
rCriteria.begin(); itr != itrEnd; ++itr)
     {
-        ScDPFilteredCache::SingleFilter* pFilter = 
dynamic_cast<ScDPFilteredCache::SingleFilter*>(itr->mpFilter.get());
-        if (!pFilter)
-            // We expect this to be a single filter.
-            continue;
+        std::vector<ScDPItemData> aMatchValues = 
itr->mpFilter->getMatchValues();
 
         GroupFieldMapType::const_iterator itrGrp = 
aGroupFieldIds.find(itr->mnFieldIndex);
         if (itrGrp == itrGrpEnd)
@@ -650,26 +713,27 @@ void 
ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
             if (IsNumGroupDimension(itr->mnFieldIndex))
             {
                 // internal number group field
+                const ScDPNumGroupInfo* pNumInfo = 
pCache->GetNumGroupInfo(itr->mnFieldIndex);
+                if (!pNumInfo)
+                    // Number group dimension without num info?  Something is 
wrong...
+                    continue;
+
                 ScDPFilteredCache::Criterion aCri;
                 aCri.mnFieldIndex = itr->mnFieldIndex;
                 const ScDPNumGroupDimension& rNumGrpDim = 
pNumGroups[itr->mnFieldIndex];
-                const ScDPNumGroupInfo* pNumInfo = 
pCache->GetNumGroupInfo(itr->mnFieldIndex);
 
-                if (pNumInfo)
+                if (rNumGrpDim.IsDateDimension())
+                {
+                    // grouped by dates.
+                    aCri.mpFilter.reset(
+                        new ScDPGroupDateFilter(
+                            aMatchValues, 
*pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
+                }
+                else
                 {
-                    if (rNumGrpDim.IsDateDimension())
-                    {
-                        // grouped by dates.
-                        aCri.mpFilter.reset(
-                            new ScDPGroupDateFilter(
-                                pFilter->getMatchValue(), 
*pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
-                    }
-                    else
-                    {
-                        // This dimension is grouped by numeric ranges.
-                        aCri.mpFilter.reset(
-                            new ScDPGroupNumFilter(pFilter->getMatchValue(), 
*pNumInfo));
-                    }
+                    // This dimension is grouped by numeric ranges.
+                    aCri.mpFilter.reset(
+                        new ScDPGroupNumFilter(aMatchValues, *pNumInfo));
                 }
 
                 aNewCriteria.push_back(aCri);
@@ -696,7 +760,7 @@ void 
ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
                 aCri.mnFieldIndex = nSrcDim;  // use the source dimension, not 
the group dimension.
                 aCri.mpFilter.reset(
                     new ScDPGroupDateFilter(
-                        pFilter->getMatchValue(), 
*pDoc->GetFormatTable()->GetNullDate(), *pNumInfo));
+                        aMatchValues, *pDoc->GetFormatTable()->GetNullDate(), 
*pNumInfo));
 
                 aNewCriteria.push_back(aCri);
             }
@@ -704,25 +768,31 @@ void 
ScDPGroupTableData::ModifyFilterCriteria(vector<ScDPFilteredCache::Criterio
             {
                 // normal group
 
-                // Note that each group dimension may have multiple group 
names!
+                ScDPFilteredCache::Criterion aCri;
+                aCri.mnFieldIndex = nSrcDim;
+                aCri.mpFilter.reset(new ScDPFilteredCache::GroupFilter());
+                ScDPFilteredCache::GroupFilter* pGrpFilter =
+                    
static_cast<ScDPFilteredCache::GroupFilter*>(aCri.mpFilter.get());
+
                 size_t nGroupItemCount = pGrpDim->GetItemCount();
                 for (size_t i = 0; i < nGroupItemCount; ++i)
                 {
                     const ScDPGroupItem* pGrpItem = 
pGrpDim->GetGroupByIndex(i);
-                    ScDPItemData aName = pFilter->getMatchValue();
-
-                    if (!pGrpItem || 
!pGrpItem->GetName().IsCaseInsEqual(aName))
+                    if (!pGrpItem)
                         continue;
 
-                    ScDPFilteredCache::Criterion aCri;
-                    aCri.mnFieldIndex = nSrcDim;
-                    aCri.mpFilter.reset(new ScDPFilteredCache::GroupFilter());
-                    ScDPFilteredCache::GroupFilter* pGrpFilter =
-                        
static_cast<ScDPFilteredCache::GroupFilter*>(aCri.mpFilter.get());
+                    // Make sure this group name equals one of the match 
values.
+                    std::vector<ScDPItemData>::iterator it =
+                        std::find_if(
+                            aMatchValues.begin(), aMatchValues.end(), 
FindCaseInsensitive(pGrpItem->GetName()));
+
+                    if (it == aMatchValues.end())
+                        continue;
 
                     pGrpItem->FillGroupFilter(*pGrpFilter);
-                    aNewCriteria.push_back(aCri);
                 }
+
+                aNewCriteria.push_back(aCri);
             }
         }
     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to