[Libreoffice-commits] core.git: include/vcl sc/inc sc/source vcl/source

Samuel Mehrbrodt (via logerrit) logerrit at kemper.freedesktop.org
Mon May 3 07:33:01 UTC 2021


 include/vcl/menu.hxx                 |    4 +++
 sc/inc/filterentries.hxx             |   10 ++++++++
 sc/inc/queryentry.hxx                |   14 +++++++++++
 sc/inc/strings.hrc                   |    2 +
 sc/source/core/data/column3.cxx      |   28 ++++++++++++++++++-----
 sc/source/core/data/table3.cxx       |   36 ++++++++++++++++++++++++++++++
 sc/source/core/tool/queryentry.cxx   |   24 ++++++++++++++++++++
 sc/source/ui/cctrl/checklistmenu.cxx |    4 +--
 sc/source/ui/inc/gridwin.hxx         |   13 ++++++++++-
 sc/source/ui/view/gridwin.cxx        |   41 +++++++++++++++++++++++++++++++++++
 vcl/source/window/menu.cxx           |   12 ++++++++++
 11 files changed, 178 insertions(+), 10 deletions(-)

New commits:
commit 5a4bd9bfbdb881368c202bc766f893a5c672621e
Author:     Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
AuthorDate: Wed Apr 21 09:53:54 2021 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
CommitDate: Mon May 3 09:32:17 2021 +0200

    tdf#76258 Filter by colors
    
    UI/Logic implementation
    
    Change-Id: If7b48219caa466d8a3341bdc4e104d696e8988c5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114385
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>

diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index f48a4e427d06..7bc136d680f7 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -24,6 +24,7 @@
 #include <string_view>
 
 #include <vcl/vclenum.hxx>
+#include <tools/color.hxx>
 #include <tools/link.hxx>
 #include <tools/long.hxx>
 #include <vcl/dllapi.h>
@@ -309,6 +310,9 @@ public:
     void SetItemImage( sal_uInt16 nItemId, const Image& rImage );
     Image GetItemImage( sal_uInt16 nItemId ) const;
 
+    // Instead of an image, draw a color
+    void SetItemColor( sal_uInt16 nItemId, const Color& rColor );
+
     void SetItemCommand( sal_uInt16 nItemId, const OUString& rCommand );
     OUString GetItemCommand( sal_uInt16 nItemId ) const;
 
diff --git a/sc/inc/filterentries.hxx b/sc/inc/filterentries.hxx
index 2a8dccd99cb3..6cbe4c43a929 100644
--- a/sc/inc/filterentries.hxx
+++ b/sc/inc/filterentries.hxx
@@ -13,12 +13,15 @@
 #include <sal/config.h>
 #include "typedstrdata.hxx"
 #include <vector>
+#include <tools/color.hxx>
 
 struct ScFilterEntries
 {
     std::vector<ScTypedStrData> maStrData;
     bool                        mbHasDates;
     bool                        mbHasEmpties;
+    std::set<Color>             maTextColors;
+    std::set<Color>             maBackgroundColors;
 
     ScFilterEntries() : mbHasDates(false), mbHasEmpties(false) {}
 
@@ -32,6 +35,13 @@ struct ScFilterEntries
     bool                                        empty() const   { return maStrData.empty(); }
     void                                        push_back( const ScTypedStrData& r ) { maStrData.push_back(r); }
     void                                        push_back( ScTypedStrData&& r )      { maStrData.push_back(r); }
+    std::set<Color>& getTextColors() { return maTextColors; };
+    void addTextColor(const Color& aTextColor) { maTextColors.emplace(aTextColor); }
+    std::set<Color>& getBackgroundColors() { return maBackgroundColors; };
+    void addBackgroundColor(const Color& aBackgroundColor)
+    {
+        maBackgroundColors.emplace(aBackgroundColor);
+    }
 };
 
 #endif
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 9b94f7cdcf6b..f7a7f6896934 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -22,6 +22,7 @@
 #include "global.hxx"
 #include <svl/sharedstring.hxx>
 #include <unotools/textsearch.hxx>
+#include <tools/color.hxx>
 
 #include <memory>
 #include <vector>
@@ -31,7 +32,15 @@
  */
 struct SC_DLLPUBLIC ScQueryEntry
 {
-    enum QueryType { ByValue, ByString, ByDate, ByEmpty };
+    enum QueryType
+    {
+        ByValue,
+        ByString,
+        ByDate,
+        ByEmpty,
+        ByTextColor,
+        ByBackgroundColor,
+    };
 
     struct SAL_DLLPRIVATE Item
     {
@@ -40,6 +49,7 @@ struct SC_DLLPUBLIC ScQueryEntry
         svl::SharedString maString;
         bool              mbMatchEmpty;
         bool              mbFormattedValue;
+        Color maColor;
 
         Item() : meType(ByValue), mfVal(0.0), mbMatchEmpty(false), mbFormattedValue(false) {}
 
@@ -68,6 +78,8 @@ struct SC_DLLPUBLIC ScQueryEntry
     bool IsQueryByEmpty() const;
     void SetQueryByNonEmpty();
     bool IsQueryByNonEmpty() const;
+    void SetQueryByTextColor(Color color);
+    void SetQueryByBackgroundColor(Color color);
     const Item& GetQueryItem() const { return GetQueryItemImpl(); }
     Item& GetQueryItem() { return GetQueryItemImpl(); }
     void            Clear();
diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc
index b52355f03527..d2463ad39306 100644
--- a/sc/inc/strings.hrc
+++ b/sc/inc/strings.hrc
@@ -34,6 +34,8 @@
 #define SCSTR_TOP10FILTER                           NC_("SCSTR_TOP10FILTER", "Top 10")
 #define SCSTR_FILTER_EMPTY                          NC_("SCSTR_FILTER_EMPTY", "Empty")
 #define SCSTR_FILTER_NOTEMPTY                       NC_("SCSTR_FILTER_NOTEMPTY", "Not Empty")
+#define SCSTR_FILTER_TEXT_COLOR                     NC_("SCSTR_FILTER_TEXT_COLOR", "Text color")
+#define SCSTR_FILTER_BACKGROUND_COLOR               NC_("SCSTR_FILTER_BACKGROUND_COLOR", "Background color")
 #define SCSTR_NONAME                                NC_("SCSTR_NONAME", "unnamed")
 // "%1 is replaced to column letter, such as 'Column A'"
 #define SCSTR_COLUMN                                NC_("SCSTR_COLUMN", "Column %1")
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 7a90c00db4e6..712595aab369 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -44,6 +44,8 @@
 #include <sharedformula.hxx>
 #include <listenercontext.hxx>
 #include <filterentries.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
 
 #include <com/sun/star/i18n/LocaleDataItem2.hpp>
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
@@ -2416,16 +2418,26 @@ class FilterEntriesHandler
     ScColumn& mrColumn;
     ScFilterEntries& mrFilterEntries;
 
-    void processCell(SCROW nRow, ScRefCellValue& rCell)
+    void processCell(ScColumn& rColumn, SCROW nRow, ScRefCellValue& rCell)
     {
         SvNumberFormatter* pFormatter = mrColumn.GetDoc().GetFormatTable();
         OUString aStr;
         sal_uLong nFormat = mrColumn.GetNumberFormat(mrColumn.GetDoc().GetNonThreadedContext(), nRow);
         ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, mrColumn.GetDoc(), mrColumn.HasFiltering());
 
+        // Colors
+        ScAddress aPos(rColumn.GetCol(), nRow, rColumn.GetTab());
+        const SvxColorItem* pColor = rColumn.GetDoc().GetAttr(aPos, ATTR_FONT_COLOR);
+        Color textColor = pColor->GetValue();
+
+        const SvxBrushItem* pBrush = rColumn.GetDoc().GetAttr(aPos, ATTR_BACKGROUND);
+        Color backgroundColor = pBrush->GetColor();
+
         if (rCell.hasString())
         {
             mrFilterEntries.push_back(ScTypedStrData(aStr));
+            mrFilterEntries.addTextColor(textColor);
+            mrFilterEntries.addBackgroundColor(backgroundColor);
             return;
         }
 
@@ -2448,6 +2460,8 @@ class FilterEntriesHandler
                     if (!aErr.isEmpty())
                     {
                         mrFilterEntries.push_back(ScTypedStrData(aErr));
+                        mrFilterEntries.addTextColor(textColor);
+                        mrFilterEntries.addBackgroundColor(backgroundColor);
                         return;
                     }
                 }
@@ -2483,6 +2497,8 @@ class FilterEntriesHandler
         }
         // maybe extend ScTypedStrData enum is also an option here
         mrFilterEntries.push_back(ScTypedStrData(aStr, fVal, ScTypedStrData::Value,bDate));
+        mrFilterEntries.addTextColor(textColor);
+        mrFilterEntries.addBackgroundColor(backgroundColor);
     }
 
 public:
@@ -2492,25 +2508,25 @@ public:
     void operator() (size_t nRow, double fVal)
     {
         ScRefCellValue aCell(fVal);
-        processCell(nRow, aCell);
+        processCell(mrColumn, nRow, aCell);
     }
 
     void operator() (size_t nRow, const svl::SharedString& rStr)
     {
         ScRefCellValue aCell(&rStr);
-        processCell(nRow, aCell);
+        processCell(mrColumn, nRow, aCell);
     }
 
     void operator() (size_t nRow, const EditTextObject* p)
     {
         ScRefCellValue aCell(p);
-        processCell(nRow, aCell);
+        processCell(mrColumn, nRow, aCell);
     }
 
     void operator() (size_t nRow, const ScFormulaCell* p)
     {
         ScRefCellValue aCell(const_cast<ScFormulaCell*>(p));
-        processCell(nRow, aCell);
+        processCell(mrColumn, nRow, aCell);
     }
 
     void operator() (const int nElemType, size_t nRow, size_t /* nDataSize */)
@@ -2525,7 +2541,7 @@ public:
             return;
         }
         ScRefCellValue aCell = mrColumn.GetCellValue(nRow);
-        processCell(nRow, aCell);
+        processCell(mrColumn, nRow, aCell);
     }
 };
 
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 93cd3f9dd5b2..dcc76104280b 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -19,6 +19,8 @@
 
 #include <comphelper/processfactory.hxx>
 #include <comphelper/random.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/colritem.hxx>
 #include <unotools/textsearch.hxx>
 #include <svl/zforlist.hxx>
 #include <svl/zformat.hxx>
@@ -2695,6 +2697,26 @@ public:
         return std::pair<bool,bool>(bOk, bTestEqual);
     }
 
+    std::pair<bool, bool> compareByTextColor(SCCOL nCol, SCROW nRow, SCTAB nTab,
+                                             const ScQueryEntry::Item& rItem)
+    {
+        ScAddress aPos(nCol, nRow, nTab);
+        const SvxColorItem* pColor = mrDoc.GetAttr(aPos, ATTR_FONT_COLOR);
+        Color color = pColor->GetValue();
+        bool bMatch = rItem.maColor == color;
+        return std::pair<bool, bool>(bMatch, false);
+    }
+
+    std::pair<bool, bool> compareByBackgroundColor(SCCOL nCol, SCROW nRow, SCTAB nTab,
+                                                   const ScQueryEntry::Item& rItem)
+    {
+        ScAddress aPos(nCol, nRow, nTab);
+        const SvxBrushItem* pBrush = mrDoc.GetAttr(aPos, ATTR_BACKGROUND);
+        Color color = pBrush->GetColor();
+        bool bMatch = rItem.maColor == color;
+        return std::pair<bool, bool>(bMatch, false);
+    }
+
     // To be called only if both isQueryByValue() and isQueryByString()
     // returned false and range lookup is wanted! In range lookup comparison
     // numbers are less than strings. Nothing else is compared.
@@ -2809,6 +2831,20 @@ bool ScTable::ValidQuery(
                     aRes.first |= aThisRes.first;
                     aRes.second |= aThisRes.second;
                 }
+                if (rItem.meType == ScQueryEntry::ByTextColor)
+                {
+                    std::pair<bool, bool> aThisRes
+                        = aEval.compareByTextColor(nCol, nRow, nTab, rItem);
+                    aRes.first |= aThisRes.first;
+                    aRes.second |= aThisRes.second;
+                }
+                if (rItem.meType == ScQueryEntry::ByBackgroundColor)
+                {
+                    std::pair<bool,bool> aThisRes =
+                        aEval.compareByBackgroundColor(nCol, nRow, nTab, rItem);
+                    aRes.first |= aThisRes.first;
+                    aRes.second |= aThisRes.second;
+                }
                 else if (rParam.mbRangeLookup)
                 {
                     std::pair<bool,bool> aThisRes =
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index a295759e0c3c..836b2caf7dd8 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -29,6 +29,8 @@
 
 #define SC_EMPTYFIELDS      (double(0x0042))
 #define SC_NONEMPTYFIELDS   (double(0x0043))
+#define SC_TEXTCOLOR        (double(0x0044))
+#define SC_BACKGROUNDCOLOR  (double(0x0045))
 
 bool ScQueryEntry::Item::operator== (const Item& r) const
 {
@@ -115,6 +117,28 @@ bool ScQueryEntry::IsQueryByNonEmpty() const
         rItem.mfVal == SC_NONEMPTYFIELDS;
 }
 
+void ScQueryEntry::SetQueryByTextColor(Color color)
+{
+    eOp = SC_EQUAL;
+    maQueryItems.resize(1);
+    Item& rItem = maQueryItems[0];
+    rItem.meType = ByTextColor;
+    rItem.maString = svl::SharedString();
+    rItem.mfVal = SC_TEXTCOLOR;
+    rItem.maColor = color;
+}
+
+void ScQueryEntry::SetQueryByBackgroundColor(Color color)
+{
+    eOp = SC_EQUAL;
+    maQueryItems.resize(1);
+    Item& rItem = maQueryItems[0];
+    rItem.meType = ByBackgroundColor;
+    rItem.maString = svl::SharedString();
+    rItem.mfVal = SC_BACKGROUNDCOLOR;
+    rItem.maColor = color;
+}
+
 ScQueryEntry::Item& ScQueryEntry::GetQueryItemImpl() const
 {
     if (maQueryItems.size() != 1)
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index 4200457956fe..f825335f5af6 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -197,9 +197,9 @@ void ScCheckListMenuControl::executeMenuItem(size_t nPos)
         // no action is defined.
         return;
 
-    terminateAllPopupMenus();
-
     maMenuItems[nPos].mxAction->execute();
+
+    terminateAllPopupMenus();
 }
 
 void ScCheckListMenuControl::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer)
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 950d574a1ec7..023715a33c8a 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -322,7 +322,18 @@ protected:
     virtual void    StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
 
 public:
-    enum class AutoFilterMode { Normal, Top10, Custom, Empty, NonEmpty, SortAscending, SortDescending };
+    enum class AutoFilterMode
+    {
+        Normal,
+        Top10,
+        Custom,
+        Empty,
+        NonEmpty,
+        TextColor,
+        BackgroundColor,
+        SortAscending,
+        SortDescending,
+    };
 
     ScGridWindow( vcl::Window* pParent, ScViewData& rData, ScSplitPos eWhichPos );
     virtual ~ScGridWindow() override;
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 59c0868e7c31..3a60311691b5 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -704,6 +704,11 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
     rControl.addMenuItem(
         ScResId(SCSTR_FILTER_NOTEMPTY), new AutoFilterAction(this, AutoFilterMode::NonEmpty));
     rControl.addSeparator();
+    rControl.addMenuItem(
+        ScResId(SCSTR_FILTER_TEXT_COLOR), new AutoFilterAction(this, AutoFilterMode::TextColor));
+    rControl.addMenuItem(
+        ScResId(SCSTR_FILTER_BACKGROUND_COLOR), new AutoFilterAction(this, AutoFilterMode::BackgroundColor));
+    rControl.addSeparator();
     rControl.addMenuItem(
         ScResId(SCSTR_STDFILTER), new AutoFilterAction(this, AutoFilterMode::Custom));
 
@@ -868,6 +873,42 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
             break;
             case AutoFilterMode::NonEmpty:
                 pEntry->SetQueryByNonEmpty();
+            break;
+            case AutoFilterMode::TextColor:
+            case AutoFilterMode::BackgroundColor:
+            {
+                ScFilterEntries aFilterEntries;
+                rDoc.GetFilterEntries(rPos.Col(), rPos.Row(), rPos.Tab(), aFilterEntries);
+
+                VclPtr<PopupMenu> pColorMenu = VclPtr<PopupMenu>::Create();
+                std::set<Color> aColors = eMode == AutoFilterMode::TextColor
+                                              ? aFilterEntries.getTextColors()
+                                              : aFilterEntries.getBackgroundColors();
+                sal_Int32 i = 1;
+                for (auto& rColor : aColors)
+                {
+                    pColorMenu->InsertItem(i, OUString(), MenuItemBits::CHECKABLE);
+                    pColorMenu->SetItemColor(i, rColor);
+                    i++;
+                }
+
+                sal_uInt16 nSelected = pColorMenu->Execute(this, mpAutoFilterPopup->GetPosPixel());
+                pColorMenu.disposeAndClear();
+
+                if (nSelected == 0)
+                    break;
+
+                // Get selected color from set
+                std::set<Color>::iterator it = aColors.begin();
+                std::advance(it, nSelected - 1);
+                Color selectedColor = *it;
+
+                if (eMode == AutoFilterMode::TextColor)
+                    pEntry->SetQueryByTextColor(selectedColor);
+                else
+                    pEntry->SetQueryByBackgroundColor(selectedColor);
+            }
+
             break;
             default:
                 // We don't know how to handle this!
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 233f531cfcaf..a1d39df63bf0 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -21,6 +21,7 @@
 #include <sal/log.hxx>
 
 #include <comphelper/lok.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/mnemonic.hxx>
 #include <vcl/image.hxx>
@@ -1022,6 +1023,17 @@ OUString Menu::GetItemText( sal_uInt16 nItemId ) const
     return OUString();
 }
 
+void Menu::SetItemColor(sal_uInt16 nItemId, const Color& rColor)
+{
+    Bitmap aBmp(Size(50, 50), vcl::PixelFormat::N24_BPP);
+    BitmapWriteAccess aBmpAccess(aBmp);
+    aBmpAccess.SetFillColor(rColor);
+    aBmpAccess.FillRect(tools::Rectangle(0, 0, 49, 49));
+    BitmapEx aBmpEx(aBmp);
+    Image aImage(aBmpEx);
+    SetItemImage(nItemId, aImage);
+}
+
 void Menu::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
 {
     size_t          nPos;


More information about the Libreoffice-commits mailing list