[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-4+backports' - 2 commits - include/vcl include/xmloff schema/libreoffice sc/inc sc/qa sc/source vcl/source xmloff/source

Samuel Mehrbrodt (via logerrit) logerrit at kemper.freedesktop.org
Mon Jun 28 07:51:51 UTC 2021


 include/vcl/menu.hxx                                        |    4 +
 include/xmloff/xmltoken.hxx                                 |    1 
 sc/inc/filterentries.hxx                                    |   10 ++
 sc/inc/queryentry.hxx                                       |   14 +++-
 sc/inc/strings.hrc                                          |    2 
 sc/qa/unit/data/ods/autofilter-colors.ods                   |binary
 sc/qa/unit/subsequent_export-test.cxx                       |   17 ++++
 sc/source/core/data/column3.cxx                             |   28 ++++++--
 sc/source/core/data/table3.cxx                              |   36 ++++++++++
 sc/source/core/tool/queryentry.cxx                          |   24 +++++++
 sc/source/filter/xml/XMLExportDatabaseRanges.cxx            |   26 ++++++-
 sc/source/filter/xml/xmlfilti.cxx                           |    9 ++
 sc/source/ui/cctrl/checklistmenu.cxx                        |    4 -
 sc/source/ui/inc/gridwin.hxx                                |   13 +++
 sc/source/ui/view/gridwin.cxx                               |   41 ++++++++++++
 schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng |   14 +++-
 vcl/source/window/menu.cxx                                  |   12 +++
 xmloff/source/core/xmltoken.cxx                             |    1 
 xmloff/source/token/tokens.txt                              |    1 
 19 files changed, 242 insertions(+), 15 deletions(-)

New commits:
commit 1f201fd6ae64c97102a60dfdecda25e1dd32d49a
Author:     Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
AuthorDate: Wed Apr 28 16:25:42 2021 +0200
Commit:     Thorsten Behrens <thorsten.behrens at allotropia.de>
CommitDate: Mon Jun 28 09:51:30 2021 +0200

    tdf#76258 Add ODF import/export
    
    XML looks like:
    <table:filter-condition table:field-number="0" loext:data-type="background-color" table:value="#ffd7d7" table:operator="="/>
    <table:filter-condition table:field-number="1" loext:data-type="text-color" table:value="#3465a4" table:operator="="/>
    
    Change-Id: Idcddf0ce436da69567e5a7e9dfd7d796dc872586
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114812
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at allotropia.de>
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
    (cherry picked from commit e2bdd31c0231444f1ba1463bffb5656c230c3073)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115898
    Tested-by: Thorsten Behrens <thorsten.behrens at allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behrens at allotropia.de>

diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index a0e52903060a..5421a90da5cb 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1889,6 +1889,7 @@ namespace xmloff { namespace token {
         XML_TEXT_BACKGROUND_COLOR,
         XML_TEXT_BLINKING,
         XML_TEXT_BOX,
+        XML_TEXT_COLOR,
         XML_TEXT_COMBINE,
         XML_TEXT_COMBINE_END_CHAR,
         XML_TEXT_COMBINE_START_CHAR,
diff --git a/sc/qa/unit/data/ods/autofilter-colors.ods b/sc/qa/unit/data/ods/autofilter-colors.ods
new file mode 100644
index 000000000000..d5a88e9299fb
Binary files /dev/null and b/sc/qa/unit/data/ods/autofilter-colors.ods differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 61f6a46eba19..d2e1087acf55 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -201,6 +201,7 @@ public:
     void testTdf95640_ods_to_xlsx();
     void testTdf95640_ods_to_xlsx_with_standard_list();
     void testTdf95640_xlsx_to_xlsx();
+    void testAutofilterColorsODF();
 
     void testRefStringXLSX();
     void testRefStringConfigXLSX();
@@ -337,6 +338,7 @@ public:
     CPPUNIT_TEST(testTdf95640_ods_to_xlsx);
     CPPUNIT_TEST(testTdf95640_ods_to_xlsx_with_standard_list);
     CPPUNIT_TEST(testTdf95640_xlsx_to_xlsx);
+    CPPUNIT_TEST(testAutofilterColorsODF);
 
     CPPUNIT_TEST(testRefStringXLSX);
     CPPUNIT_TEST(testRefStringConfigXLSX);
@@ -4048,11 +4050,26 @@ void ScExportTest::testConditionalFormatContainsTextXLSX()
     CPPUNIT_ASSERT(xDocSh.is());
 
     xmlDocPtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/worksheets/sheet1.xml", FORMAT_XLSX);
+
     CPPUNIT_ASSERT(pDoc);
 
     assertXPathContent(pDoc, "//x:conditionalFormatting/x:cfRule/x:formula", "NOT(ISERROR(SEARCH(\"test\",A1)))");
 }
 
+void ScExportTest::testAutofilterColorsODF()
+{
+    ScDocShellRef xDocSh = loadDoc(u"autofilter-colors.", FORMAT_ODS);
+    CPPUNIT_ASSERT(xDocSh.is());
+
+    xmlDocPtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "content.xml", FORMAT_ODS);
+    CPPUNIT_ASSERT(pDoc);
+
+    assertXPath(pDoc, "//table:filter/table:filter-and/table:filter-condition[1]", "value", "#e8f2a1");
+    assertXPath(pDoc, "//table:filter/table:filter-and/table:filter-condition[1][@loext:data-type='background-color']");
+    assertXPath(pDoc, "//table:filter/table:filter-and/table:filter-condition[2]", "value", "#3465a4");
+    assertXPath(pDoc, "//table:filter/table:filter-and/table:filter-condition[2][@loext:data-type='text-color']");
+}
+
 void ScExportTest::testConditionalFormatPriorityCheckXLSX()
 {
     ScDocShellRef xDocSh = loadDoc("conditional_fmt_checkpriority.", FORMAT_XLSX);
diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
index 937ac271db26..687168abe5cf 100644
--- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
+++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx
@@ -435,16 +435,28 @@ private:
             return;
         }
 
-        mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart));
-        if (bCaseSens)
-            mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
-
         if (rItems.size() == 1)
         {
             // Single item condition.
             const ScQueryEntry::Item& rItem = rItems.front();
             if (rItem.meType == ScQueryEntry::ByString)
                 mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
+            else if (rItem.meType == ScQueryEntry::ByTextColor
+                     || rItem.meType == ScQueryEntry::ByBackgroundColor)
+            {
+                if (mrExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+                {
+                    if (rItem.meType == ScQueryEntry::ByTextColor)
+                        mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_TYPE, XML_TEXT_COLOR);
+                    else
+                        mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATA_TYPE,
+                                              XML_BACKGROUND_COLOR);
+                }
+
+                OUStringBuffer buffer;
+                sax::Converter::convertColor(buffer, rItem.maColor);
+                mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, buffer.makeStringAndClear());
+            }
             else
             {
                 mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER);
@@ -454,6 +466,9 @@ private:
             }
 
             mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, getOperatorXML(rEntry, eSearchType));
+            mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart));
+            if (bCaseSens)
+                mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
             SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true);
         }
         else
@@ -465,6 +480,9 @@ private:
             const ScQueryEntry::Item& rItem = rItems.front();
             mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, rItem.maString.getString());
             mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, OUString("="));
+            mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(rEntry.nField - nFieldStart));
+            if (bCaseSens)
+                mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE);
             SvXMLElementExport aElemC(mrExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true);
 
             std::for_each(rItems.begin(), rItems.end(), WriteSetItem(mrExport));
diff --git a/sc/source/filter/xml/xmlfilti.cxx b/sc/source/filter/xml/xmlfilti.cxx
index 47fea817123c..000dbdfaf302 100644
--- a/sc/source/filter/xml/xmlfilti.cxx
+++ b/sc/source/filter/xml/xmlfilti.cxx
@@ -26,6 +26,7 @@
 #include <document.hxx>
 
 #include <o3tl/safeint.hxx>
+#include <sax/tools/converter.hxx>
 #include <svl/sharedstringpool.hxx>
 #include <xmloff/xmltoken.hxx>
 #include <xmloff/xmlnmspe.hxx>
@@ -312,6 +313,7 @@ ScXMLConditionContext::ScXMLConditionContext(
                 }
                 break;
                 case XML_ELEMENT( TABLE, XML_DATA_TYPE ):
+                case XML_ELEMENT( LO_EXT, XML_DATA_TYPE ):
                 {
                     sDataType = aIter.toString();
                 }
@@ -437,6 +439,13 @@ void SAL_CALL ScXMLConditionContext::endFastElement( sal_Int32 /*nElement*/ )
             rItem.mfVal = sConditionValue.toDouble();
             rItem.meType = ScQueryEntry::ByValue;
         }
+        else if (IsXMLToken(sDataType, XML_TEXT_COLOR)
+                 || IsXMLToken(sDataType, XML_BACKGROUND_COLOR))
+        {
+            rItem.meType = IsXMLToken(sDataType, XML_TEXT_COLOR) ? ScQueryEntry::ByTextColor
+                                                                 : ScQueryEntry::ByBackgroundColor;
+            sax::Converter::convertColor(rItem.maColor, sConditionValue);
+        }
         else
         {
             svl::SharedStringPool& rPool = GetScImport().GetDocument()->GetSharedStringPool();
diff --git a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
index 69d43e510d44..47cacf855855 100644
--- a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
+++ b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
@@ -29,7 +29,7 @@
 	basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 	LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
 	INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR
-	FITNESS FOR A PARTICULAR PURPOSE. 
+	FITNESS FOR A PARTICULAR PURPOSE.
 -->
 <rng:grammar xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:db="urn:oasis:names:tc:opendocument:xmlns:database:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:rng="http://relaxng.org/ns/structure/1.0" xmlns:script="urn:oa
 sis:names:tc:opendocument:xmlns:script:1.0" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
 
@@ -2412,4 +2412,16 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
     </rng:optional>
   </rng:define>
 
+  <!-- TODO no proposal -->
+  <rng:define name="table-filter-condition-attlist" combine="interleave">
+    <rng:optional>
+      <rng:attribute name="loext:data-type">
+        <rng:choice>
+          <rng:value>background-color</rng:value>
+          <rng:value>text-color</rng:value>
+        </rng:choice>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
 </rng:grammar>
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 13f1415b8cc4..8c2276ab1251 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1891,6 +1891,7 @@ namespace xmloff { namespace token {
         TOKEN( "text-background-color",           XML_TEXT_BACKGROUND_COLOR ),
         TOKEN( "text-blinking",                   XML_TEXT_BLINKING ),
         TOKEN( "text-box",                        XML_TEXT_BOX ),
+        TOKEN( "text-color",                      XML_TEXT_COLOR ),
         TOKEN( "text-combine",                    XML_TEXT_COMBINE ),
         TOKEN( "text-combine-end-char",           XML_TEXT_COMBINE_END_CHAR ),
         TOKEN( "text-combine-start-char",         XML_TEXT_COMBINE_START_CHAR ),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index b2b95e956bd1..d2dd36122280 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -1806,6 +1806,7 @@ text-autospace
 text-background-color
 text-blinking
 text-box
+text-color
 text-combine
 text-combine-end-char
 text-combine-start-char
commit 8b5fe4be2a5293af34c27fe21c68be198a82b154
Author:     Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
AuthorDate: Wed Apr 21 09:53:54 2021 +0200
Commit:     Thorsten Behrens <thorsten.behrens at allotropia.de>
CommitDate: Mon Jun 28 09:51:16 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>
    (cherry picked from commit 5a4bd9bfbdb881368c202bc766f893a5c672621e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115869
    Tested-by: Thorsten Behrens <thorsten.behrens at allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behrens at allotropia.de>

diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 76a39c813eef..b787b43b31b7 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -22,6 +22,7 @@
 
 #include <memory>
 #include <vcl/vclenum.hxx>
+#include <tools/color.hxx>
 #include <tools/link.hxx>
 #include <vcl/dllapi.h>
 #include <vcl/keycod.hxx>
@@ -306,6 +307,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 df858f08f339..848e55c3016d 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -23,6 +23,7 @@
 #include "global.hxx"
 #include <svl/sharedstring.hxx>
 #include <unotools/textsearch.hxx>
+#include <tools/color.hxx>
 
 #include <memory>
 #include <vector>
@@ -32,7 +33,15 @@
  */
 struct SC_DLLPUBLIC ScQueryEntry
 {
-    enum QueryType { ByValue, ByString, ByDate, ByEmpty };
+    enum QueryType
+    {
+        ByValue,
+        ByString,
+        ByDate,
+        ByEmpty,
+        ByTextColor,
+        ByBackgroundColor,
+    };
 
     struct Item
     {
@@ -40,6 +49,7 @@ struct SC_DLLPUBLIC ScQueryEntry
         double        mfVal;
         svl::SharedString maString;
         bool              mbMatchEmpty;
+        Color maColor;
 
         Item() : meType(ByValue), mfVal(0.0), mbMatchEmpty(false) {}
 
@@ -70,6 +80,8 @@ struct SC_DLLPUBLIC ScQueryEntry
     bool IsQueryByNonEmpty() const;
     const Item& GetQueryItem() const;
     Item& GetQueryItem();
+    void SetQueryByTextColor(Color color);
+    void SetQueryByBackgroundColor(Color color);
     void            Clear();
     ScQueryEntry&   operator=( const ScQueryEntry& r );
     bool            operator==( const ScQueryEntry& r ) const;
diff --git a/sc/inc/strings.hrc b/sc/inc/strings.hrc
index 9a44676ffbd3..95833ec5b2f2 100644
--- a/sc/inc/strings.hrc
+++ b/sc/inc/strings.hrc
@@ -35,6 +35,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 90a0dcec43aa..196369e54da8 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>
@@ -2402,16 +2404,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());
 
+        // 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;
         }
 
@@ -2434,6 +2446,8 @@ class FilterEntriesHandler
                     if (!aErr.isEmpty())
                     {
                         mrFilterEntries.push_back(ScTypedStrData(aErr));
+                        mrFilterEntries.addTextColor(textColor);
+                        mrFilterEntries.addBackgroundColor(backgroundColor);
                         return;
                     }
                 }
@@ -2461,6 +2475,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:
@@ -2470,25 +2486,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 */)
@@ -2503,7 +2519,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 c27c73fb88e1..60357a32d634 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>
@@ -2687,6 +2689,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.
@@ -2801,6 +2823,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 ecc912b34c4a..581939748f86 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;
+}
+
 const ScQueryEntry::Item& ScQueryEntry::GetQueryItem() const
 {
     if (maQueryItems.size() > 1)
diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx
index b9b5acca11c8..462051061e55 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -452,9 +452,9 @@ void ScMenuFloatingWindow::executeMenuItem(size_t nPos)
         // no action is defined.
         return;
 
-    terminateAllPopupMenus();
-
     maMenuItems[nPos].mpAction->execute();
+
+    terminateAllPopupMenus();
 }
 
 void ScMenuFloatingWindow::setSelectedMenuItem(size_t nPos, bool bSubMenuTimer, bool bEnsureSubMenu)
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index bd4ca07159c5..5ebb26241d10 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -302,7 +302,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* pData, ScSplitPos eWhichPos );
     virtual ~ScGridWindow() override;
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 6d2c4ea19106..bb2a40368bfe 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -705,6 +705,11 @@ void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
     mpAutoFilterPopup->addMenuItem(
         ScResId(SCSTR_FILTER_NOTEMPTY), new AutoFilterAction(this, AutoFilterMode::NonEmpty));
     mpAutoFilterPopup->addSeparator();
+    mpAutoFilterPopup->addMenuItem(
+        ScResId(SCSTR_FILTER_TEXT_COLOR), new AutoFilterAction(this, AutoFilterMode::TextColor));
+    mpAutoFilterPopup->addMenuItem(
+        ScResId(SCSTR_FILTER_BACKGROUND_COLOR), new AutoFilterAction(this, AutoFilterMode::BackgroundColor));
+    mpAutoFilterPopup->addSeparator();
     mpAutoFilterPopup->addMenuItem(
         ScResId(SCSTR_STDFILTER), new AutoFilterAction(this, AutoFilterMode::Custom));
 
@@ -863,6 +868,42 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
             break;
             case AutoFilterMode::NonEmpty:
                 pEntry->SetQueryByNonEmpty();
+            break;
+            case AutoFilterMode::TextColor:
+            case AutoFilterMode::BackgroundColor:
+            {
+                ScFilterEntries aFilterEntries;
+                pDoc->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 1d25c089e976..918910444a70 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 <bitmapwriteaccess.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/mnemonic.hxx>
 #include <vcl/image.hxx>
@@ -1010,6 +1011,17 @@ OUString Menu::GetItemText( sal_uInt16 nItemId ) const
     return OUString();
 }
 
+void Menu::SetItemColor(sal_uInt16 nItemId, const Color& rColor)
+{
+    Bitmap aBmp(Size(50, 50), 24);
+    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