include/svx/ColorSets.hxx         |    8 -
 svx/Package_document_themes.mk    |    8 +
 svx/source/styles/ColorSets.cxx   |  231 +++++++++++++++++++-------------------
 svx/uiconfig/themes/Beach.theme   |   18 ++
 svx/uiconfig/themes/Breeze.theme  |   18 ++
 svx/uiconfig/themes/Forest.theme  |   18 ++
 svx/uiconfig/themes/Ocean.theme   |   18 ++
 svx/uiconfig/themes/Rainbow.theme |   18 ++
 svx/uiconfig/themes/Sunset.theme  |   18 ++
 sw/qa/core/theme/ThemeTest.cxx    |    3 
 10 files changed, 237 insertions(+), 121 deletions(-)

New commits:
commit f877f7e88663657587561e65f7f46a9f5f4421fb
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Mon Jan 20 21:36:32 2025 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Wed Jan 22 15:33:36 2025 +0100

    docthemes: Load document themes def. files into ColorSets
    
    This is then used in Theme dialog to show which themes are
    available. Also add the existing hardcoded themes as theme def.
    files.
    
    Change-Id: I230bc84ae70f22b558aa31053339d602d04885bb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180541
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <[email protected]>

diff --git a/include/svx/ColorSets.hxx b/include/svx/ColorSets.hxx
index 6d7ba41398b4..4cf3313e0855 100644
--- a/include/svx/ColorSets.hxx
+++ b/include/svx/ColorSets.hxx
@@ -5,11 +5,9 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
  */
 
-#ifndef INCLUDED_SVX_COLORSETS_HXX
-#define INCLUDED_SVX_COLORSETS_HXX
+#pragma once
 
 #include <svx/svxdllapi.h>
 #include <docmodel/theme/ColorSet.hxx>
@@ -39,11 +37,9 @@ public:
 
     model::ColorSet const* getColorSet(std::u16string_view rName) const;
 
-    void insert(model::ColorSet const& rColorSet, IdenticalNameAction eAction 
= IdenticalNameAction::Overwrite);
+    void insert(model::ColorSet const& rColorSet, IdenticalNameAction eAction);
 };
 
 } // end of namespace svx
 
-#endif // INCLUDED_SVX_COLORSETS_HXX
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/Package_document_themes.mk b/svx/Package_document_themes.mk
index 254292d9c45d..0664f1f9f0ae 100644
--- a/svx/Package_document_themes.mk
+++ b/svx/Package_document_themes.mk
@@ -10,7 +10,13 @@
 $(eval $(call 
gb_Package_Package,svx_document_themes,$(SRCDIR)/svx/uiconfig/themes))
 
 $(eval $(call 
gb_Package_add_files_with_dir,svx_document_themes,$(LIBO_SHARE_FOLDER)/themes,\
-    libreoffice.theme \
+    Beach.theme \
+    Breeze.theme \
+    Forest.theme \
+    Libreoffice.theme \
+    Ocean.theme \
+    Rainbow.theme \
+    Sunset.theme \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/svx/source/styles/ColorSets.cxx b/svx/source/styles/ColorSets.cxx
index 92b4973cbcca..57c4b44227a2 100644
--- a/svx/source/styles/ColorSets.cxx
+++ b/svx/source/styles/ColorSets.cxx
@@ -12,12 +12,127 @@
 
 #include <optional>
 #include <unordered_set>
+#include <vector>
+
 #include <docmodel/theme/ColorSet.hxx>
+#include <o3tl/numeric.hxx>
+#include <tools/stream.hxx>
+#include <tools/XmlWalker.hxx>
+#include <vcl/UserResourceScanner.hxx>
+#include <unotools/pathoptions.hxx>
+#include <docmodel/theme/ThemeColorType.hxx>
+#include <frozen/bits/defines.h>
+#include <frozen/bits/elsa_std.h>
+#include <frozen/unordered_map.h>
 
 using namespace com::sun::star;
 
 namespace svx
 {
+namespace
+{
+
+class DocumentThemeScanner : public vcl::UserResourceScanner
+{
+private:
+    std::vector<model::ColorSet>& mrColorSets;
+
+public:
+    DocumentThemeScanner(std::vector<model::ColorSet>& rColorSets)
+        : mrColorSets(rColorSets)
+    {}
+
+private:
+    static model::ThemeColorType getThemeColor(std::string_view sColorName)
+    {
+        model::ThemeColorType eTheme = model::ThemeColorType::Unknown;
+
+        static constexpr auto constThemeColorTypeMapping =  
frozen::make_unordered_map<std::string_view, model::ThemeColorType>({
+            { "dark1",  model::ThemeColorType::Dark1 },
+            { "light1",  model::ThemeColorType::Light1 },
+            { "dark2",  model::ThemeColorType::Dark2 },
+            { "light2",  model::ThemeColorType::Light2 },
+            { "accent1",  model::ThemeColorType::Accent1 },
+            { "accent2",  model::ThemeColorType::Accent2 },
+            { "accent3",  model::ThemeColorType::Accent3 },
+            { "accent4",  model::ThemeColorType::Accent4 },
+            { "accent5",  model::ThemeColorType::Accent5 },
+            { "accent6",  model::ThemeColorType::Accent6 },
+            { "hyperlink",  model::ThemeColorType::Hyperlink },
+            { "followed-hyperlink",  model::ThemeColorType::FollowedHyperlink 
},
+        });
+        auto iterator = constThemeColorTypeMapping.find(sColorName);
+        if (iterator != constThemeColorTypeMapping.end())
+            eTheme = iterator->second;
+        return eTheme;
+    }
+
+    bool addResource(const OUString& rPath) override
+    {
+        SvFileStream aFileStream(rPath, StreamMode::READ);
+
+        tools::XmlWalker aWalker;
+        if (!aWalker.open(&aFileStream))
+            return false;
+
+        if (aWalker.name() != "theme")
+            return false;
+
+        OString aThemeNameUTF8 = aWalker.attribute("name"_ostr);
+        OUString aThemeName = OStringToOUString(aThemeNameUTF8, 
RTL_TEXTENCODING_UTF8);
+
+        model::ColorSet aColorSet(aThemeName);
+
+        aWalker.children();
+        while (aWalker.isValid())
+        {
+            if (aWalker.name() == "theme-colors")
+            {
+                aWalker.children();
+                while (aWalker.isValid())
+                {
+                    if (aWalker.name() == "color")
+                    {
+                        OString aName = aWalker.attribute("name"_ostr);
+                        auto eThemeColor = getThemeColor(aName);
+                        OString aColorString = aWalker.attribute("color"_ostr);
+                        Color aColor;
+                        if (eThemeColor != model::ThemeColorType::Unknown && 
color::createFromString(aColorString, aColor))
+                            aColorSet.add(eThemeColor, aColor);
+                    }
+                    aWalker.next();
+                }
+                aWalker.parent();
+            }
+            aWalker.next();
+        }
+        aWalker.parent();
+
+        mrColorSets.push_back(aColorSet);
+
+        return true;
+    }
+
+    bool isValidResource(const OUString& rFilename) override
+    {
+        if (rFilename.isEmpty())
+            return false;
+
+        if (!rFilename.endsWithIgnoreAsciiCase(u".theme"))
+            return false;
+
+        osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type);
+        if (!vcl::file::readFileStatus(aFileStatus, rFilename))
+            return false;
+
+        if (!aFileStatus.isRegular())
+            return false;
+
+        return true;
+    }
+};
+
+} // end anonymous namespace
 
 ColorSets::ColorSets()
 {
@@ -32,121 +147,11 @@ ColorSets& ColorSets::get()
     return *sColorSet;
 }
 
-
 void ColorSets::init()
 {
-    {
-        model::ColorSet aColorSet(u"LibreOffice"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Dark2, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light2, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Accent1, 0x18A303);
-        aColorSet.add(model::ThemeColorType::Accent2, 0x0369A3);
-        aColorSet.add(model::ThemeColorType::Accent3, 0xA33E03);
-        aColorSet.add(model::ThemeColorType::Accent4, 0x8E03A3);
-        aColorSet.add(model::ThemeColorType::Accent5, 0xC99C00);
-        aColorSet.add(model::ThemeColorType::Accent6, 0xC9211E);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x0000EE);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x551A8B);
-        maColorSets.push_back(aColorSet);
-    }
-    {
-        model::ColorSet aColorSet(u"Rainbow"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Dark2, 0x1C1C1C);
-        aColorSet.add(model::ThemeColorType::Light2, 0xDDDDDD);
-        aColorSet.add(model::ThemeColorType::Accent1, 0xFF0000);
-        aColorSet.add(model::ThemeColorType::Accent2, 0xFF8000);
-        aColorSet.add(model::ThemeColorType::Accent3, 0xFFFF00);
-        aColorSet.add(model::ThemeColorType::Accent4, 0x00A933);
-        aColorSet.add(model::ThemeColorType::Accent5, 0x2A6099);
-        aColorSet.add(model::ThemeColorType::Accent6, 0x800080);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x0000EE);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x551A8B);
-        maColorSets.push_back(aColorSet);
-    }
-    {
-        model::ColorSet aColorSet(u"Beach"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Dark2, 0xFFBF00);
-        aColorSet.add(model::ThemeColorType::Light2, 0x333333);
-        aColorSet.add(model::ThemeColorType::Accent1, 0xFFF5CE);
-        aColorSet.add(model::ThemeColorType::Accent2, 0xDEE6EF);
-        aColorSet.add(model::ThemeColorType::Accent3, 0xE8F2A1);
-        aColorSet.add(model::ThemeColorType::Accent4, 0xFFD7D7);
-        aColorSet.add(model::ThemeColorType::Accent5, 0xDEE7E5);
-        aColorSet.add(model::ThemeColorType::Accent6, 0xDDDBB6);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x7777EE);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0xEE77D7);
-        maColorSets.push_back(aColorSet);
-    }
-    {
-        model::ColorSet aColorSet(u"Sunset"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Dark2, 0x492300);
-        aColorSet.add(model::ThemeColorType::Light2, 0xF6F9D4);
-        aColorSet.add(model::ThemeColorType::Accent1, 0xFFFF00);
-        aColorSet.add(model::ThemeColorType::Accent2, 0xFFBF00);
-        aColorSet.add(model::ThemeColorType::Accent3, 0xFF8000);
-        aColorSet.add(model::ThemeColorType::Accent4, 0xFF4000);
-        aColorSet.add(model::ThemeColorType::Accent5, 0xBF0041);
-        aColorSet.add(model::ThemeColorType::Accent6, 0x800080);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x0000EE);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x551A8B);
-        maColorSets.push_back(aColorSet);
-    }
-    {
-        model::ColorSet aColorSet(u"Ocean"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Dark2, 0x2A6099);
-        aColorSet.add(model::ThemeColorType::Light2, 0xCCCCCC);
-        aColorSet.add(model::ThemeColorType::Accent1, 0x800080);
-        aColorSet.add(model::ThemeColorType::Accent2, 0x55308D);
-        aColorSet.add(model::ThemeColorType::Accent3, 0x2A6099);
-        aColorSet.add(model::ThemeColorType::Accent4, 0x158466);
-        aColorSet.add(model::ThemeColorType::Accent5, 0x00A933);
-        aColorSet.add(model::ThemeColorType::Accent6, 0x81D41A);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x0000EE);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x551A8B);
-        maColorSets.push_back(aColorSet);
-    }
-    {
-        model::ColorSet aColorSet(u"Forest"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Dark2, 0x000000);
-        aColorSet.add(model::ThemeColorType::Light2, 0xFFFFFF);
-        aColorSet.add(model::ThemeColorType::Accent1, 0x813709);
-        aColorSet.add(model::ThemeColorType::Accent2, 0x224B12);
-        aColorSet.add(model::ThemeColorType::Accent3, 0x706E0C);
-        aColorSet.add(model::ThemeColorType::Accent4, 0x355269);
-        aColorSet.add(model::ThemeColorType::Accent5, 0xBE480A);
-        aColorSet.add(model::ThemeColorType::Accent6, 0xBE480A);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x2A6099);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x800080);
-        maColorSets.push_back(aColorSet);
-    }
-    {
-        model::ColorSet aColorSet(u"Breeze"_ustr);
-        aColorSet.add(model::ThemeColorType::Dark1, 0x232629);
-        aColorSet.add(model::ThemeColorType::Light1, 0xFCFCFC);
-        aColorSet.add(model::ThemeColorType::Dark2, 0x31363B);
-        aColorSet.add(model::ThemeColorType::Light2, 0xEFF0F1);
-        aColorSet.add(model::ThemeColorType::Accent1, 0xDA4453);
-        aColorSet.add(model::ThemeColorType::Accent2, 0xF47750);
-        aColorSet.add(model::ThemeColorType::Accent3, 0xFDBC4B);
-        aColorSet.add(model::ThemeColorType::Accent4, 0xC9CE3B);
-        aColorSet.add(model::ThemeColorType::Accent5, 0x1CDC9A);
-        aColorSet.add(model::ThemeColorType::Accent6, 0x2ECC71);
-        aColorSet.add(model::ThemeColorType::Hyperlink, 0x1D99F3);
-        aColorSet.add(model::ThemeColorType::FollowedHyperlink, 0x3DAEE9);
-        maColorSets.push_back(aColorSet);
-    }
+    SvtPathOptions aPathOptions;
+    DocumentThemeScanner aScanner(maColorSets);
+    aScanner.addPaths(aPathOptions.GetDocumentThemePath());
 }
 
 model::ColorSet const* ColorSets::getColorSet(std::u16string_view rName) const
diff --git a/svx/uiconfig/themes/Beach.theme b/svx/uiconfig/themes/Beach.theme
new file mode 100644
index 000000000000..1c006dcf9a53
--- /dev/null
+++ b/svx/uiconfig/themes/Beach.theme
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<theme name="Beach">
+    <theme-colors name="Beach">
+        <color name="dark1" color="#000000" />
+        <color name="light1" color="#FFFFFF" />
+        <color name="dark2" color="#FFBF00" />
+        <color name="light2" color="#333333" />
+        <color name="accent1" color="#FFF5CE" />
+        <color name="accent2" color="#DEE6EF" />
+        <color name="accent3" color="#E8F2A1" />
+        <color name="accent4" color="#FFD7D7" />
+        <color name="accent5" color="#DEE7E5" />
+        <color name="accent6" color="#DDDBB6" />
+        <color name="hyperlink" color="#7777EE" />
+        <color name="followed-hyperlink" color="#EE77D7" />
+    </theme-colors>
+</theme>
diff --git a/svx/uiconfig/themes/Breeze.theme b/svx/uiconfig/themes/Breeze.theme
new file mode 100644
index 000000000000..efae704f506c
--- /dev/null
+++ b/svx/uiconfig/themes/Breeze.theme
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<theme name="Breeze">
+    <theme-colors name="Breeze">
+        <color name="dark1" color="#232629" />
+        <color name="light1" color="#FCFCFC" />
+        <color name="dark2" color="#31363B" />
+        <color name="light2" color="#EFF0F1" />
+        <color name="accent1" color="#DA4453" />
+        <color name="accent2" color="#F47750" />
+        <color name="accent3" color="#FDBC4B" />
+        <color name="accent4" color="#C9CE3B" />
+        <color name="accent5" color="#1CDC9A" />
+        <color name="accent6" color="#2ECC71" />
+        <color name="hyperlink" color="#1D99F3" />
+        <color name="followed-hyperlink" color="#3DAEE9" />
+    </theme-colors>
+</theme>
diff --git a/svx/uiconfig/themes/Forest.theme b/svx/uiconfig/themes/Forest.theme
new file mode 100644
index 000000000000..89527577d4e4
--- /dev/null
+++ b/svx/uiconfig/themes/Forest.theme
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<theme name="Forest">
+    <theme-colors name="Forest">
+        <color name="dark1" color="#000000" />
+        <color name="light1" color="#FFFFFF" />
+        <color name="dark2" color="#000000" />
+        <color name="light2" color="#FFFFFF" />
+        <color name="accent1" color="#813709" />
+        <color name="accent2" color="#224B12" />
+        <color name="accent3" color="#706E0C" />
+        <color name="accent4" color="#355269" />
+        <color name="accent5" color="#BE480A" />
+        <color name="accent6" color="#BE480A" />
+        <color name="hyperlink" color="#2A6099" />
+        <color name="followed-hyperlink" color="#800080" />
+    </theme-colors>
+</theme>
diff --git a/svx/uiconfig/themes/libreoffice.theme 
b/svx/uiconfig/themes/Libreoffice.theme
similarity index 100%
rename from svx/uiconfig/themes/libreoffice.theme
rename to svx/uiconfig/themes/Libreoffice.theme
diff --git a/svx/uiconfig/themes/Ocean.theme b/svx/uiconfig/themes/Ocean.theme
new file mode 100644
index 000000000000..5e7dc337b798
--- /dev/null
+++ b/svx/uiconfig/themes/Ocean.theme
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<theme name="Ocean">
+    <theme-colors name="Ocean">
+        <color name="dark1" color="#000000" />
+        <color name="light1" color="#FFFFFF" />
+        <color name="dark2" color="#2A6099" />
+        <color name="light2" color="#CCCCCC" />
+        <color name="accent1" color="#800080" />
+        <color name="accent2" color="#55308D" />
+        <color name="accent3" color="#2A6099" />
+        <color name="accent4" color="#158466" />
+        <color name="accent5" color="#00A933" />
+        <color name="accent6" color="#81D41A" />
+        <color name="hyperlink" color="#0000EE" />
+        <color name="followed-hyperlink" color="#551A8B" />
+    </theme-colors>
+</theme>
diff --git a/svx/uiconfig/themes/Rainbow.theme 
b/svx/uiconfig/themes/Rainbow.theme
new file mode 100644
index 000000000000..4a372d80f8a7
--- /dev/null
+++ b/svx/uiconfig/themes/Rainbow.theme
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<theme name="Rainbow">
+    <theme-colors name="Rainbow">
+        <color name="dark1" color="#000000" />
+        <color name="light1" color="#FFFFFF" />
+        <color name="dark2" color="#1C1C1C" />
+        <color name="light2" color="#DDDDDD" />
+        <color name="accent1" color="#FF0000" />
+        <color name="accent2" color="#FF8000" />
+        <color name="accent3" color="#FFFF00" />
+        <color name="accent4" color="#00A933" />
+        <color name="accent5" color="#2A6099" />
+        <color name="accent6" color="#800080" />
+        <color name="hyperlink" color="#0000EE" />
+        <color name="followed-hyperlink" color="#551A8B" />
+    </theme-colors>
+</theme>
diff --git a/svx/uiconfig/themes/Sunset.theme b/svx/uiconfig/themes/Sunset.theme
new file mode 100644
index 000000000000..107bb1c53fa3
--- /dev/null
+++ b/svx/uiconfig/themes/Sunset.theme
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<theme name="Sunset">
+    <theme-colors name="Sunset">
+        <color name="dark1" color="#000000" />
+        <color name="light1" color="#FFFFFF" />
+        <color name="dark2" color="#492300" />
+        <color name="light2" color="#F6F9D4" />
+        <color name="accent1" color="#FFFF00" />
+        <color name="accent2" color="#FFBF00" />
+        <color name="accent3" color="#FF8000" />
+        <color name="accent4" color="#FF4000" />
+        <color name="accent5" color="#BF0041" />
+        <color name="accent6" color="#800080" />
+        <color name="hyperlink" color="#0000EE" />
+        <color name="followed-hyperlink" color="#551A8B" />
+    </theme-colors>
+</theme>
diff --git a/sw/qa/core/theme/ThemeTest.cxx b/sw/qa/core/theme/ThemeTest.cxx
index 7ae4e2fa2bbf..c93e4a436c77 100644
--- a/sw/qa/core/theme/ThemeTest.cxx
+++ b/sw/qa/core/theme/ThemeTest.cxx
@@ -429,7 +429,8 @@ CPPUNIT_TEST_FIXTURE(SwCoreThemeTest, testThemeChanging)
     // Change theme colors
     {
         auto const& rColorSets = svx::ColorSets::get();
-        auto pNewColorSet = 
std::make_shared<model::ColorSet>(rColorSets.getColorSet(0));
+        auto pNewColorSet
+            = 
std::make_shared<model::ColorSet>(*rColorSets.getColorSet(u"LibreOffice"));
         // check that the theme colors are as expected
         CPPUNIT_ASSERT_EQUAL(u"LibreOffice"_ustr, pNewColorSet->getName());
 

Reply via email to