From 89c27a63a70f46ad290fc8cd34a08fae8fe94c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Vajngerl?= Date: Tue, 21 Jan 2025 19:08:33 +0900 Subject: [PATCH] docthemes: Save themes def. to a file when added to ColorSets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Color themes will be written to the user folder. Change-Id: I58e650550044bd35a5054a303ce41789d3d51d32 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180542 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl --- include/svx/ColorSets.hxx | 4 ++ include/vcl/UserResourceScanner.hxx | 2 + svx/source/styles/ColorSets.cxx | 62 +++++++++++++++++++++++++- vcl/source/app/UserResourceScanner.cxx | 26 +++++------ 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/include/svx/ColorSets.hxx b/include/svx/ColorSets.hxx index 4cf3313e0855..6bf29c4ea196 100644 --- a/include/svx/ColorSets.hxx +++ b/include/svx/ColorSets.hxx @@ -19,6 +19,8 @@ class SVXCORE_DLLPUBLIC ColorSets { private: std::vector maColorSets; + OUString maUserFolder; + ColorSets(); void init(); public: @@ -38,6 +40,8 @@ public: model::ColorSet const* getColorSet(std::u16string_view rName) const; void insert(model::ColorSet const& rColorSet, IdenticalNameAction eAction); + void writeToUserFolder(model::ColorSet const& rNewColorSet); + }; } // end of namespace svx diff --git a/include/vcl/UserResourceScanner.hxx b/include/vcl/UserResourceScanner.hxx index db7da3accc90..2b2d4da0e7c5 100644 --- a/include/vcl/UserResourceScanner.hxx +++ b/include/vcl/UserResourceScanner.hxx @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace vcl @@ -20,6 +21,7 @@ namespace vcl namespace file { VCL_DLLPUBLIC bool readFileStatus(osl::FileStatus& rStatus, const OUString& rFile); +VCL_DLLPUBLIC void splitPathString(std::u16string_view aPathString, std::deque& rPaths); } class VCL_DLLPUBLIC UserResourceScanner diff --git a/svx/source/styles/ColorSets.cxx b/svx/source/styles/ColorSets.cxx index 57c4b44227a2..5143854e1823 100644 --- a/svx/source/styles/ColorSets.cxx +++ b/svx/source/styles/ColorSets.cxx @@ -15,12 +15,14 @@ #include #include +#include #include #include #include +#include #include #include -#include +#include #include #include #include @@ -150,8 +152,15 @@ ColorSets& ColorSets::get() void ColorSets::init() { SvtPathOptions aPathOptions; + OUString aURLString = aPathOptions.GetDocumentThemePath(); + DocumentThemeScanner aScanner(maColorSets); - aScanner.addPaths(aPathOptions.GetDocumentThemePath()); + aScanner.addPaths(aURLString); + + std::deque aURLs; + vcl::file::splitPathString(aURLString, aURLs); + if (aURLs.size() > 0) + maUserFolder = aURLs[0]; } model::ColorSet const* ColorSets::getColorSet(std::u16string_view rName) const @@ -200,6 +209,7 @@ void ColorSets::insert(model::ColorSet const& rNewColorSet, IdenticalNameAction } // color set not found, so insert it maColorSets.push_back(rNewColorSet); + writeToUserFolder(rNewColorSet); } else if (eAction == IdenticalNameAction::AutoRename) { @@ -211,10 +221,58 @@ void ColorSets::insert(model::ColorSet const& rNewColorSet, IdenticalNameAction model::ColorSet aNewColorSet = rNewColorSet; aNewColorSet.setName(aName); + maColorSets.push_back(aNewColorSet); + writeToUserFolder(aNewColorSet); } } +void ColorSets::writeToUserFolder(model::ColorSet const& rNewColorSet) +{ + static constexpr auto constThemeColorTypeToName = frozen::make_unordered_map({ + { model::ThemeColorType::Dark1, "dark1" }, + { model::ThemeColorType::Light1, "light1" }, + { model::ThemeColorType::Dark2, "dark2" }, + { model::ThemeColorType::Light2, "light2" }, + { model::ThemeColorType::Accent1, "accent1" }, + { model::ThemeColorType::Accent2, "accent2" }, + { model::ThemeColorType::Accent3, "accent3" }, + { model::ThemeColorType::Accent4, "accent4" }, + { model::ThemeColorType::Accent5, "accent5" }, + { model::ThemeColorType::Accent6, "accent6" }, + { model::ThemeColorType::Hyperlink, "hyperlink" }, + { model::ThemeColorType::FollowedHyperlink, "followed-hyperlink" } + }); + + SvFileStream aFileStream(maUserFolder + "/" + rNewColorSet.getName() + ".theme", StreamMode::WRITE | StreamMode::TRUNC); + + tools::XmlWriter aWriter(&aFileStream); + aWriter.startDocument(); + aWriter.startElement("theme"); + aWriter.attribute("name", rNewColorSet.getName()); + + aWriter.startElement("theme-colors"); + aWriter.attribute("name", rNewColorSet.getName()); + + for (auto eThemeColorType : o3tl::enumrange()) + { + auto iterator = constThemeColorTypeToName.find(eThemeColorType); + if (iterator != constThemeColorTypeToName.end()) + { + Color aColor = rNewColorSet.getColor(eThemeColorType); + aWriter.startElement("color"); + aWriter.attribute("name", OString(iterator->second)); + aWriter.attribute("color", "#"_ostr + aColor.AsRGBHexString().toUtf8()); + aWriter.endElement(); + } + } + + aWriter.endElement(); + + aWriter.endElement(); + aWriter.endDocument(); +} + } // end of namespace svx /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/UserResourceScanner.cxx b/vcl/source/app/UserResourceScanner.cxx index 0e01da5b3b0d..5dd42c9830c1 100644 --- a/vcl/source/app/UserResourceScanner.cxx +++ b/vcl/source/app/UserResourceScanner.cxx @@ -37,15 +37,6 @@ OUString convertToAbsolutePath(const OUString& path) } return resolver.m_aStatus.getFileURL(); } - -void splitPathString(std::u16string_view aPathString, std::deque& rPaths) -{ - sal_Int32 nIndex = 0; - do - { - rPaths.push_front(OUString(o3tl::getToken(aPathString, 0, ';', nIndex))); - } while (nIndex >= 0); -} } namespace file @@ -68,6 +59,15 @@ bool readFileStatus(osl::FileStatus& status, const OUString& file) } return true; } + +void splitPathString(std::u16string_view aPathString, std::deque& rPaths) +{ + sal_Int32 nIndex = 0; + do + { + rPaths.push_front(OUString(o3tl::getToken(aPathString, 0, ';', nIndex))); + } while (nIndex >= 0); +} } UserResourceScanner::UserResourceScanner() = default; @@ -75,7 +75,7 @@ UserResourceScanner::UserResourceScanner() = default; void UserResourceScanner::addPaths(std::u16string_view aPathString) { std::deque aPaths; - splitPathString(aPathString, aPaths); + vcl::file::splitPathString(aPathString, aPaths); for (const auto& path : aPaths) { @@ -86,8 +86,8 @@ void UserResourceScanner::addPaths(std::u16string_view aPathString) if (!aFileStatus.isDirectory()) { - SAL_INFO("vcl.app", - "Cannot search for icon themes in '" << path << "'. It is not a directory."); + SAL_INFO("vcl.app", "Cannot search for resaource files in '" + << path << "'. It is not a directory."); continue; } @@ -96,7 +96,7 @@ void UserResourceScanner::addPaths(std::u16string_view aPathString) if (aResourcePaths.empty()) { SAL_WARN("vcl.app", - "Could not find any icon themes in the provided directory ('" << path << "'."); + "Could not find any file in the provided directory ('" << path << "'."); continue; }