diff options
author | Dennis Francis <dennisfrancis.in@gmail.com> | 2016-05-31 23:46:52 +0530 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2016-06-10 13:29:16 +0000 |
commit | 760ca821442e3d8c0d36122bb8bc4a9c8078e97c (patch) | |
tree | 374e066083758ac2ca873f5d0dc6198722272806 | |
parent | 49b2548231a4eaf3f1304d15b0bb3f050ac99b49 (diff) |
tdf#97340 : Handle autofilter search for dates correctly
Reviewed-on: https://gerrit.libreoffice.org/26005
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit 848737eb576555f7c01d2159a9cf64d020dc2598)
Change-Id: I5c8413d560789a626ea87eb28a89059960177f1f
Reviewed-on: https://gerrit.libreoffice.org/26008
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Dennis Francis <dennisfrancis.in@gmail.com>
Tested-by: Dennis Francis <dennisfrancis.in@gmail.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | include/svtools/treelistentry.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/cctrl/checklistmenu.cxx | 135 | ||||
-rw-r--r-- | sc/source/ui/inc/checklistmenu.hxx | 44 |
3 files changed, 153 insertions, 27 deletions
diff --git a/include/svtools/treelistentry.hxx b/include/svtools/treelistentry.hxx index c5c523ce85b6..adbb469e64cd 100644 --- a/include/svtools/treelistentry.hxx +++ b/include/svtools/treelistentry.hxx @@ -114,6 +114,7 @@ public: void SetBackColor( const Color& aColor ) { maBackColor = aColor; } Color GetBackColor() const { return maBackColor; } + SvTreeListEntry* GetParent() const { return pParent; } }; #endif diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 8f7a3a9ec771..e5897ec628bc 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -845,10 +845,11 @@ ScCheckListMenuWindow::Config::Config() : { } -ScCheckListMenuWindow::Member::Member() +ScCheckListMember::ScCheckListMember() : mbVisible(true) , mbDate(false) , mbLeaf(false) + , meDatePartType(YEAR) , mpParent(nullptr) { } @@ -1136,7 +1137,7 @@ void ScCheckListMenuWindow::setAllMemberState(bool bSet) aLabel = maMembers[i].maName; if (aLabel.isEmpty()) aLabel = ScGlobal::GetRscString(STR_EMPTYDATA); - maChecks->ShowCheckEntry( aLabel, maMembers[i].mpParent, true, bSet); + maChecks->ShowCheckEntry( aLabel, maMembers[i], true, bSet); } if (!maConfig.mbAllowEmptySet) @@ -1223,29 +1224,61 @@ IMPL_LINK_NOARG_TYPED(ScCheckListMenuWindow, EdModifyHdl, Edit&, void) size_t n = maMembers.size(); size_t nSelCount = 0; OUString aLabelDisp; + bool bSomeDateDeletes = false; for (size_t i = 0; i < n; ++i) { - aLabelDisp = maMembers[i].maName; + bool bIsDate = maMembers[i].mbDate; + bool bPartialMatch = false; + aLabelDisp = maMembers[i].maName; if ( aLabelDisp.isEmpty() ) aLabelDisp = ScGlobal::GetRscString( STR_EMPTYDATA ); + if ( !bSearchTextEmpty ) + { + if ( !bIsDate ) + bPartialMatch = ( aLabelDisp.toAsciiLowerCase().indexOf( aSearchText ) != -1 ); + else if ( maMembers[i].meDatePartType == ScCheckListMember::DAY ) // Match with both numerical and text version of month + bPartialMatch = bPartialMatch || ( OUString( maMembers[i].maRealName + maMembers[i].maDateParts[1] ) + .toAsciiLowerCase().indexOf( aSearchText ) != -1 ); + else + continue; + } + else if ( bIsDate && maMembers[i].meDatePartType != ScCheckListMember::DAY ) + continue; + if ( bSearchTextEmpty ) { - maChecks->ShowCheckEntry( aLabelDisp, maMembers[i].mpParent, true, maMembers[i].mbVisible ); + SvTreeListEntry* pLeaf = maChecks->ShowCheckEntry( aLabelDisp, maMembers[i], true, maMembers[i].mbVisible ); + updateMemberParents( pLeaf, i ); if ( maMembers[i].mbVisible ) ++nSelCount; continue; } - if ( aLabelDisp.toAsciiLowerCase().indexOf( aSearchText ) != -1 ) + if ( bPartialMatch ) { - maChecks->ShowCheckEntry( aLabelDisp, maMembers[i].mpParent ); + SvTreeListEntry* pLeaf = maChecks->ShowCheckEntry( aLabelDisp, maMembers[i] ); + updateMemberParents( pLeaf, i ); ++nSelCount; } else - maChecks->ShowCheckEntry( aLabelDisp, maMembers[i].mpParent, false, false ); + { + maChecks->ShowCheckEntry( aLabelDisp, maMembers[i], false, false ); + if( bIsDate ) + bSomeDateDeletes = true; + } + } + + if ( bSomeDateDeletes ) + { + for (size_t i = 0; i < n; ++i) + { + if ( !maMembers[i].mbDate ) continue; + if ( maMembers[i].meDatePartType != ScCheckListMember::DAY ) continue; + updateMemberParents( nullptr, i ); + } } if ( nSelCount == n ) @@ -1336,6 +1369,42 @@ vcl::Window* ScCheckListMenuWindow::GetPreferredKeyInputWindow() return maTabStopCtrls[mnCurTabStop]; } +void ScCheckListMenuWindow::updateMemberParents( SvTreeListEntry* pLeaf, size_t nIdx ) +{ + + if ( !maMembers[nIdx].mbDate || maMembers[nIdx].meDatePartType != ScCheckListMember::DAY ) + return; + + OUString aYearName = maMembers[nIdx].maDateParts[0]; + OUString aMonthName = maMembers[nIdx].maDateParts[1]; + auto aItr = maYearMonthMap.find(aYearName + aMonthName); + + if ( pLeaf ) + { + SvTreeListEntry* pMonthEntry = pLeaf->GetParent(); + SvTreeListEntry* pYearEntry = ( pMonthEntry ) ? pMonthEntry->GetParent() : nullptr; + + maMembers[nIdx].mpParent = pMonthEntry; + if ( aItr != maYearMonthMap.end() ) + { + size_t nMonthIdx = aItr->second; + maMembers[nMonthIdx].mpParent = pYearEntry; + } + } + else + { + SvTreeListEntry* pYearEntry = maChecks->FindEntry( nullptr, aYearName ); + if ( aItr != maYearMonthMap.end() && !pYearEntry ) + { + size_t nMonthIdx = aItr->second; + maMembers[nMonthIdx].mpParent = nullptr; + maMembers[nIdx].mpParent = nullptr; + } + else if ( pYearEntry && !maChecks->FindEntry( pYearEntry, aMonthName ) ) + maMembers[nIdx].mpParent = nullptr; + } +} + Reference<XAccessible> ScCheckListMenuWindow::CreateAccessible() { if (!mxAccessible.is()) @@ -1392,19 +1461,23 @@ void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, b OUString aMonthName = aMonths[nMonth-1].FullName; OUString aDayName = OUString::number(nDay); + if ( aDayName.getLength() == 1 ) + aDayName = "0" + aDayName; + maChecks->SetUpdateMode(false); SvTreeListEntry* pYearEntry = maChecks->FindEntry(nullptr, aYearName); if (!pYearEntry) { pYearEntry = maChecks->InsertEntry(aYearName, nullptr, true); - Member aMemYear; + ScCheckListMember aMemYear; aMemYear.maName = aYearName; aMemYear.maRealName = rsName; aMemYear.mbDate = true; aMemYear.mbLeaf = false; aMemYear.mbVisible = bVisible; aMemYear.mpParent = nullptr; + aMemYear.meDatePartType = ScCheckListMember::YEAR; maMembers.push_back(aMemYear); } @@ -1412,27 +1485,33 @@ void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, b if (!pMonthEntry) { pMonthEntry = maChecks->InsertEntry(aMonthName, pYearEntry, true); - Member aMemMonth; + ScCheckListMember aMemMonth; aMemMonth.maName = aMonthName; aMemMonth.maRealName = rsName; aMemMonth.mbDate = true; aMemMonth.mbLeaf = false; aMemMonth.mbVisible = bVisible; aMemMonth.mpParent = pYearEntry; + aMemMonth.meDatePartType = ScCheckListMember::MONTH; maMembers.push_back(aMemMonth); + maYearMonthMap[aYearName + aMonthName] = maMembers.size() - 1; } SvTreeListEntry* pDayEntry = maChecks->FindEntry(pMonthEntry, aDayName); if (!pDayEntry) { maChecks->InsertEntry(aDayName, pMonthEntry); - Member aMemDay; + ScCheckListMember aMemDay; aMemDay.maName = aDayName; aMemDay.maRealName = rsName; + aMemDay.maDateParts.resize(2); + aMemDay.maDateParts[0] = aYearName; + aMemDay.maDateParts[1] = aMonthName; aMemDay.mbDate = true; aMemDay.mbLeaf = true; aMemDay.mbVisible = bVisible; aMemDay.mpParent = pMonthEntry; + aMemDay.meDatePartType = ScCheckListMember::DAY; maMembers.push_back(aMemDay); } @@ -1441,7 +1520,7 @@ void ScCheckListMenuWindow::addDateMember(const OUString& rsName, double nVal, b void ScCheckListMenuWindow::addMember(const OUString& rName, bool bVisible) { - Member aMember; + ScCheckListMember aMember; aMember.maName = rName; aMember.mbDate = false; aMember.mbLeaf = true; @@ -1543,13 +1622,31 @@ void ScCheckListBox::CheckEntry( SvTreeListEntry* pParent, bool bCheck ) } } -void ScCheckListBox::ShowCheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bShow, bool bCheck ) +SvTreeListEntry* ScCheckListBox::ShowCheckEntry( const OUString& sName, ScCheckListMember& rMember, bool bShow, bool bCheck ) { - SvTreeListEntry* pEntry = FindEntry( pParent, sName ); + SvTreeListEntry* pEntry = nullptr; + if ( !rMember.mbDate || ( rMember.mbDate && rMember.mpParent ) ) + pEntry = FindEntry( rMember.mpParent, sName ); + if ( bShow ) { if ( !pEntry ) { + if ( rMember.mbDate ) + { + SvTreeListEntry* pYearEntry = FindEntry( nullptr, rMember.maDateParts[0] ); + if ( !pYearEntry ) + pYearEntry = InsertEntry( rMember.maDateParts[0], nullptr, true ); + SvTreeListEntry* pMonthEntry = FindEntry( pYearEntry, rMember.maDateParts[1] ); + if ( !pMonthEntry ) + pMonthEntry = InsertEntry( rMember.maDateParts[1], pYearEntry, true ); + SvTreeListEntry* pDayEntry = FindEntry( pMonthEntry, rMember.maName ); + if ( !pDayEntry ) + pDayEntry = InsertEntry( rMember.maName, pMonthEntry ); + + return pDayEntry; // Return leaf node + } + pEntry = InsertEntry( sName); @@ -1560,7 +1657,17 @@ void ScCheckListBox::ShowCheckEntry( const OUString& sName, SvTreeListEntry* pPa CheckEntry( pEntry, bCheck ); } else if ( pEntry ) - RemoveParentKeepChildren( pEntry ); + { + GetModel()->Remove( pEntry ); + SvTreeListEntry* pParent = rMember.mpParent; + while ( pParent && !pParent->HasChildren() ) + { + SvTreeListEntry* pTmp = pParent; + pParent = pTmp->GetParent(); + GetModel()->Remove( pTmp ); + } + } + return nullptr; } SvTreeListEntry* ScCheckListBox::CountCheckedEntries( SvTreeListEntry* pParent, sal_uLong& nCount ) const diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx index c6717110e988..9f7587a1f416 100644 --- a/sc/source/ui/inc/checklistmenu.hxx +++ b/sc/source/ui/inc/checklistmenu.hxx @@ -19,6 +19,7 @@ #include <memory> #include <unordered_map> +#include <map> namespace com { namespace sun { namespace star { @@ -190,6 +191,8 @@ private: VclPtr<ScMenuFloatingWindow> mpParentMenu; }; +struct ScCheckListMember; + class ScCheckListBox : public SvTreeListBox { SvLBoxButtonData* mpCheckButton; @@ -204,13 +207,35 @@ class ScCheckListBox : public SvTreeListBox void Init(); void CheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bCheck = true ); void CheckEntry( SvTreeListEntry* pEntry, bool bCheck = true ); - void ShowCheckEntry( const OUString& sName, SvTreeListEntry* pParent, bool bShow = true, bool bCheck = true ); + SvTreeListEntry* ShowCheckEntry( const OUString& sName, ScCheckListMember& rMember, bool bShow = true, bool bCheck = true ); bool IsChecked( const OUString& sName, SvTreeListEntry* pParent ); SvTreeListEntry* FindEntry( SvTreeListEntry* pParent, const OUString& sNode ); sal_uInt16 GetCheckedEntryCount() const; void ExpandChildren( SvTreeListEntry* pParent ); virtual void KeyInput( const KeyEvent& rKEvt ) override; }; + +struct ScCheckListMember +{ + enum DatePartType + { + YEAR, + MONTH, + DAY, + }; + + OUString maName; // node name + OUString maRealName; + bool mbVisible; + bool mbDate; + bool mbLeaf; + DatePartType meDatePartType; + // To store Year and Month if the member if DAY type + std::vector<OUString> maDateParts; + ScCheckListMember(); + SvTreeListEntry* mpParent; +}; + /** * This class implements a popup window for field button, for quick access * of hide-item list, and possibly more stuff related to field options. @@ -280,17 +305,6 @@ protected: virtual void handlePopupEnd() override; private: - struct Member - { - OUString maName; // node name - OUString maRealName; - bool mbVisible; - bool mbDate; - bool mbLeaf; - - Member(); - SvTreeListEntry* mpParent; - }; class CancelButton : public ::CancelButton { @@ -327,6 +341,7 @@ private: void setAllMemberState(bool bSet); void selectCurrentMemberOnly(bool bSet); void cycleFocus(bool bReverse = false); + void updateMemberParents( SvTreeListEntry* pLeaf, size_t nIdx ); DECL_LINK_TYPED( ButtonHdl, Button*, void ); DECL_LINK_TYPED( TriStateHdl, Button*, void ); @@ -347,7 +362,10 @@ private: std::vector<VclPtr<vcl::Window> > maTabStopCtrls; size_t mnCurTabStop; - std::vector<Member> maMembers; + std::vector<ScCheckListMember> maMembers; + // For Dates + std::map<OUString, size_t> maYearMonthMap; + std::unique_ptr<ExtendedData> mpExtendedData; std::unique_ptr<Action> mpOKAction; std::unique_ptr<Action> mpPopupEndAction; |