sc/inc/unonames.hxx                       |    1 
 sc/qa/extras/scspreadsheetsettingsobj.cxx |   19 +-----
 sc/qa/unit/ThemeImportExportTest.cxx      |   85 +++++++++++++++++++++++++++++-
 sc/source/filter/xml/xmlexprt.cxx         |   21 +++++++
 sc/source/filter/xml/xmlexprt.hxx         |    2 
 sc/source/ui/unoobj/docuno.cxx            |   23 ++++++++
 xmloff/inc/XMLThemeContext.hxx            |    6 +-
 xmloff/source/style/XMLThemeContext.cxx   |    6 +-
 xmloff/source/style/xmlstyle.cxx          |   22 ++++---
 9 files changed, 154 insertions(+), 31 deletions(-)

New commits:
commit 72dc179044bafdfbc577fdd2a69f19bb8f08c958
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Aug 31 22:29:46 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Sep 4 09:15:21 2023 +0200

    sc: add ODF import/export of the Theme + tests
    
    One missing thing is the support in calc to save the Theme into
    the ODS document and read that back. The theme element is added as
    a child element to the office:styles - the same as it already is
    added in Writer.
    
    Also adds "Theme" property as a top level document property
    so it is possible to get and set the theme in xmloff.
    
    Also tests have been added to cover this usecases.
    
    Change-Id: Ic214ff5e945b77d50e6c881def9d49509560a0e0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156363
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit b36f7769dd07a6b6f55cdf4ce76e2f39ed186e89)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156456
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx
index c644dc32391a..57f75c3d9293 100644
--- a/sc/inc/unonames.hxx
+++ b/sc/inc/unonames.hxx
@@ -47,6 +47,7 @@ inline constexpr OUStringLiteral SC_UNO_ROWLABELRNG          
= u"RowLabelRanges"
 inline constexpr OUStringLiteral SC_UNO_SHEETLINKS           = u"SheetLinks";
 inline constexpr OUStringLiteral SC_UNO_FORBIDDEN            = 
u"ForbiddenCharacters";
 inline constexpr OUStringLiteral SC_UNO_HASDRAWPAGES         = u"HasDrawPages";
+inline constexpr OUStringLiteral SC_UNO_THEME                = u"Theme";
 
 //  CharacterProperties
 inline constexpr OUStringLiteral SC_UNONAME_CCOLOR           = u"CharColor";
diff --git a/sc/qa/extras/scspreadsheetsettingsobj.cxx 
b/sc/qa/extras/scspreadsheetsettingsobj.cxx
index 117fc4d4a097..9173a80ba178 100644
--- a/sc/qa/extras/scspreadsheetsettingsobj.cxx
+++ b/sc/qa/extras/scspreadsheetsettingsobj.cxx
@@ -48,21 +48,10 @@ public:
 
 ScSpreadsheetSettingsObj::ScSpreadsheetSettingsObj()
     : UnoApiTest("/sc/qa/extras/testdocuments")
-    , XPropertySet({
-          "AreaLinks",
-          "CharLocale",
-          "CharLocaleAsian",
-          "CharLocaleComplex",
-          "ColumnLabelRanges",
-          "DDELinks",
-          "DatabaseRanges",
-          "ExternalDocLinks",
-          "InteropGrabBag",
-          "NamedRanges",
-          "NullDate",
-          "RowLabelRanges",
-          "SheetLinks",
-      })
+    , XPropertySet({ "AreaLinks", "CharLocale", "CharLocaleAsian", 
"CharLocaleComplex",
+                     "ColumnLabelRanges", "DDELinks", "DatabaseRanges", 
"ExternalDocLinks",
+                     "InteropGrabBag", "NamedRanges", "NullDate", 
"RowLabelRanges", "SheetLinks",
+                     "Theme" })
 {
 }
 
diff --git a/sc/qa/unit/ThemeImportExportTest.cxx 
b/sc/qa/unit/ThemeImportExportTest.cxx
index 7e054ce5fe92..7d0eb47ee2c9 100644
--- a/sc/qa/unit/ThemeImportExportTest.cxx
+++ b/sc/qa/unit/ThemeImportExportTest.cxx
@@ -15,6 +15,11 @@
 #include <editeng/colritem.hxx>
 #include <editeng/borderline.hxx>
 
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XTheme.hpp>
+#include <docmodel/uno/UnoTheme.hxx>
+#include <docmodel/theme/Theme.hxx>
+
 using namespace css;
 
 namespace
@@ -28,7 +33,85 @@ public:
     }
 };
 
-CPPUNIT_TEST_FIXTURE(ThemeImportExportTest, testThemeExport)
+CPPUNIT_TEST_FIXTURE(ThemeImportExportTest, testThemeExportAndImport)
+{
+    mxComponent = loadFromDesktop("private:factory/scalc");
+    {
+        uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, 
uno::UNO_QUERY_THROW);
+
+        auto pTheme = std::make_shared<model::Theme>("MyTheme");
+        auto pColorSet = std::make_shared<model::ColorSet>("MyColorSet");
+        pColorSet->add(model::ThemeColorType::Dark1, 0x111111);
+        pColorSet->add(model::ThemeColorType::Light1, 0x222222);
+        pColorSet->add(model::ThemeColorType::Dark2, 0x333333);
+        pColorSet->add(model::ThemeColorType::Light2, 0x444444);
+        pColorSet->add(model::ThemeColorType::Accent1, 0x555555);
+        pColorSet->add(model::ThemeColorType::Accent2, 0x666666);
+        pColorSet->add(model::ThemeColorType::Accent3, 0x777777);
+        pColorSet->add(model::ThemeColorType::Accent4, 0x888888);
+        pColorSet->add(model::ThemeColorType::Accent5, 0x999999);
+        pColorSet->add(model::ThemeColorType::Accent6, 0xaaaaaa);
+        pColorSet->add(model::ThemeColorType::Hyperlink, 0xbbbbbb);
+        pColorSet->add(model::ThemeColorType::FollowedHyperlink, 0xcccccc);
+        pTheme->setColorSet(pColorSet);
+
+        xPropertySet->setPropertyValue("Theme", 
uno::Any(model::theme::createXTheme(pTheme)));
+    }
+
+    // Check the "Theme" property
+    {
+        uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<util::XTheme> 
xTheme(xPropertySet->getPropertyValue("Theme"),
+                                            uno::UNO_QUERY_THROW);
+        CPPUNIT_ASSERT(xTheme.is());
+        auto* pUnoTheme = dynamic_cast<UnoTheme*>(xTheme.get());
+        CPPUNIT_ASSERT(pUnoTheme);
+        auto pTheme = pUnoTheme->getTheme();
+
+        CPPUNIT_ASSERT_EQUAL(OUString("MyTheme"), pTheme->GetName());
+        CPPUNIT_ASSERT_EQUAL(OUString("MyColorSet"), 
pTheme->getColorSet()->getName());
+        CPPUNIT_ASSERT_EQUAL(OUString("Office"), 
pTheme->getFontScheme().getName());
+        CPPUNIT_ASSERT_EQUAL(OUString(""), 
pTheme->getFormatScheme().getName());
+    }
+
+    saveAndReload("calc8");
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseExport("styles.xml");
+        static constexpr OStringLiteral sThemePath = 
"//office:styles/loext:theme";
+        assertXPath(pXmlDoc, sThemePath, 1);
+        assertXPath(pXmlDoc, sThemePath + "[@loext:name='MyTheme']");
+        const OString sThemeColorsPath = sThemePath + "/loext:theme-colors";
+        assertXPath(pXmlDoc, sThemeColorsPath, 1);
+        assertXPath(pXmlDoc, sThemeColorsPath + "[@loext:name='MyColorSet']");
+        const OString sThemeColorPath = sThemeColorsPath + "/loext:color";
+        assertXPath(pXmlDoc, sThemeColorPath, 12);
+        assertXPath(pXmlDoc, sThemeColorPath + "[3]", "name", "dark2");
+        assertXPath(pXmlDoc, sThemeColorPath + "[3]", "color", "#333333");
+        assertXPath(pXmlDoc, sThemeColorPath + "[9]", "name", "accent5");
+        assertXPath(pXmlDoc, sThemeColorPath + "[9]", "color", "#999999");
+        assertXPath(pXmlDoc, sThemeColorPath + "[12]", "name", 
"followed-hyperlink");
+        assertXPath(pXmlDoc, sThemeColorPath + "[12]", "color", "#cccccc");
+    }
+
+    // Check the theme after import/export cycle
+    {
+        uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<util::XTheme> 
xTheme(xPropertySet->getPropertyValue("Theme"),
+                                            uno::UNO_QUERY_THROW);
+        CPPUNIT_ASSERT(xTheme.is());
+        auto* pUnoTheme = dynamic_cast<UnoTheme*>(xTheme.get());
+        CPPUNIT_ASSERT(pUnoTheme);
+        auto pTheme = pUnoTheme->getTheme();
+
+        CPPUNIT_ASSERT_EQUAL(OUString("MyTheme"), pTheme->GetName());
+        CPPUNIT_ASSERT_EQUAL(OUString("MyColorSet"), 
pTheme->getColorSet()->getName());
+        CPPUNIT_ASSERT_EQUAL(OUString("Office"), 
pTheme->getFontScheme().getName());
+        CPPUNIT_ASSERT_EQUAL(OUString(""), 
pTheme->getFormatScheme().getName());
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ThemeImportExportTest, testThemeExportOOXML)
 {
     loadFromURL(u"xlsx/CalcThemeTest.xlsx");
 
diff --git a/sc/source/filter/xml/xmlexprt.cxx 
b/sc/source/filter/xml/xmlexprt.cxx
index 9fba6fd02604..4a9b9db6662a 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -120,7 +120,9 @@
 #include <svx/svdoashp.hxx>
 #include <svx/svdobj.hxx>
 #include <svx/svdocapt.hxx>
+#include <svx/svdmodel.hxx>
 #include <vcl/svapp.hxx>
+#include <docmodel/theme/Theme.hxx>
 
 #include <comphelper/processfactory.hxx>
 #include <com/sun/star/beans/XPropertySet.hpp>
@@ -1993,6 +1995,25 @@ void ScXMLExport::ExportStyles_( bool bUsed )
         OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME), 
xCellStylesExportPropertySetMapper, false, XmlStyleFamily::TABLE_CELL);
 
     SvXMLExport::ExportStyles_(bUsed);
+
+    exportTheme();
+}
+
+void ScXMLExport::exportTheme()
+{
+    if ((getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) == 0)
+        return;
+
+    SdrModel* pModel = GetDocument()->GetDrawLayer();
+
+    if (!pModel)
+        return;
+
+    auto const& pTheme = pModel->getTheme();
+    if (!pTheme)
+        return;
+
+    ExportThemeElement(pTheme);
 }
 
 void ScXMLExport::AddStyleFromCells(const uno::Reference<beans::XPropertySet>& 
xProperties,
diff --git a/sc/source/filter/xml/xmlexprt.hxx 
b/sc/source/filter/xml/xmlexprt.hxx
index 8ab8901d4671..0f6ad0547da6 100644
--- a/sc/source/filter/xml/xmlexprt.hxx
+++ b/sc/source/filter/xml/xmlexprt.hxx
@@ -222,6 +222,8 @@ class ScXMLExport : public SvXMLExport
 
     const ScXMLEditAttributeMap& GetEditAttributeMap() const;
 
+    void exportTheme();
+
 protected:
     virtual SvXMLAutoStylePoolP* CreateAutoStylePool() override;
     virtual XMLPageExport* CreatePageExport() override;
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index d044e197235c..c901c77f7b25 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -57,6 +57,7 @@
 
 #include <com/sun/star/beans/PropertyAttribute.hpp>
 #include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/XTheme.hpp>
 #include <com/sun/star/sheet/XNamedRanges.hpp>
 #include <com/sun/star/sheet/XLabelRanges.hpp>
 #include <com/sun/star/sheet/XSelectedSheetsSupplier.hpp>
@@ -82,6 +83,8 @@
 #include <sfx2/lokhelper.hxx>
 #include <sfx2/lokcomponenthelpers.hxx>
 #include <sfx2/LokControlHandler.hxx>
+#include <docmodel/uno/UnoTheme.hxx>
+#include <docmodel/theme/Theme.hxx>
 
 #include <cellsuno.hxx>
 #include <columnspanset.hxx>
@@ -165,6 +168,7 @@ static o3tl::span<const SfxItemPropertyMapEntry> 
lcl_GetDocOptPropertyMap()
         { SC_UNO_LOOKUPLABELS,            PROP_UNO_LOOKUPLABELS, 
cppu::UnoType<bool>::get(),                         0, 0},
         { SC_UNO_MATCHWHOLE,              PROP_UNO_MATCHWHOLE, 
cppu::UnoType<bool>::get(),                           0, 0},
         { SC_UNO_NAMEDRANGES,             0, 
cppu::UnoType<sheet::XNamedRanges>::get(),             0, 0},
+        { SC_UNO_THEME,                   0, 
cppu::UnoType<util::XTheme>::get(), 0,  0},
         { SC_UNO_DATABASERNG,             0, 
cppu::UnoType<sheet::XDatabaseRanges>::get(),          0, 0},
         { SC_UNO_NULLDATE,                PROP_UNO_NULLDATE, 
cppu::UnoType<util::Date>::get(),                      0, 0},
         { SC_UNO_ROWLABELRNG,             0, 
cppu::UnoType<sheet::XLabelRanges>::get(),             0, 0},
@@ -2837,6 +2841,16 @@ void SAL_CALL ScModelObj::setPropertyValue(
     {
         setGrabBagItem(aValue);
     }
+    else if (aPropertyName == SC_UNO_THEME)
+    {
+        SdrModel& rSdrModel = getSdrModelFromUnoModel();
+        uno::Reference<util::XTheme> xTheme;
+        if (aValue >>= xTheme)
+        {
+            auto& rUnoTheme = dynamic_cast<UnoTheme&>(*xTheme);
+            rSdrModel.setTheme(rUnoTheme.getTheme());
+        }
+    }
 
     if ( aNewOpt != rOldOpt )
     {
@@ -3023,6 +3037,15 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const 
OUString& aPropertyName )
         {
             getGrabBagItem(aRet);
         }
+        else if (aPropertyName == SC_UNO_THEME)
+        {
+            SdrModel& rSdrModel = getSdrModelFromUnoModel();
+            css::uno::Reference<css::util::XTheme> xTheme;
+            auto pTheme = rSdrModel.getTheme();
+            if (pTheme)
+                xTheme = model::theme::createXTheme(pTheme);
+            aRet <<= xTheme;
+        }
     }
 
     return aRet;
diff --git a/xmloff/inc/XMLThemeContext.hxx b/xmloff/inc/XMLThemeContext.hxx
index ce6f5ec9bbb6..f8ee08d5d4e8 100644
--- a/xmloff/inc/XMLThemeContext.hxx
+++ b/xmloff/inc/XMLThemeContext.hxx
@@ -10,7 +10,7 @@
 #include <utility>
 #include <xmloff/xmlprcon.hxx>
 
-#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
 #include <com/sun/star/util/Color.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
 
@@ -24,13 +24,13 @@ class Theme;
 /// Imports the theme
 class XMLThemeContext : public SvXMLImportContext
 {
-    css::uno::Reference<css::drawing::XDrawPage> m_xPage;
+    css::uno::Reference<css::uno::XInterface> m_xObject;
     std::shared_ptr<model::Theme> mpTheme;
 
 public:
     XMLThemeContext(SvXMLImport& rImport,
                     css::uno::Reference<css::xml::sax::XFastAttributeList> 
const& xAttrList,
-                    css::uno::Reference<css::drawing::XDrawPage> const& xPage);
+                    css::uno::Reference<css::uno::XInterface> const& xObject);
     ~XMLThemeContext();
 
     css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL 
createFastChildContext(
diff --git a/xmloff/source/style/XMLThemeContext.cxx 
b/xmloff/source/style/XMLThemeContext.cxx
index 1579af468003..5c210c7a48dc 100644
--- a/xmloff/source/style/XMLThemeContext.cxx
+++ b/xmloff/source/style/XMLThemeContext.cxx
@@ -33,9 +33,9 @@ using namespace xmloff::token;
 
 XMLThemeContext::XMLThemeContext(SvXMLImport& rImport,
                                  const 
uno::Reference<xml::sax::XFastAttributeList>& xAttrList,
-                                 css::uno::Reference<css::drawing::XDrawPage> 
const& xPage)
+                                 css::uno::Reference<css::uno::XInterface> 
const& xObject)
     : SvXMLImportContext(rImport)
-    , m_xPage(xPage)
+    , m_xObject(xObject)
     , mpTheme(new model::Theme)
 {
     for (const auto& rAttribute : 
sax_fastparser::castToFastAttributeList(xAttrList))
@@ -56,7 +56,7 @@ XMLThemeContext::~XMLThemeContext()
 {
     if (mpTheme && mpTheme->getColorSet())
     {
-        uno::Reference<beans::XPropertySet> xPropertySet(m_xPage, 
uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xPropertySet(m_xObject, 
uno::UNO_QUERY);
         auto xTheme = model::theme::createXTheme(mpTheme);
         xPropertySet->setPropertyValue("Theme", uno::Any(xTheme));
     }
diff --git a/xmloff/source/style/xmlstyle.cxx b/xmloff/source/style/xmlstyle.cxx
index c72684102a5f..add2e79ac5b9 100644
--- a/xmloff/source/style/xmlstyle.cxx
+++ b/xmloff/source/style/xmlstyle.cxx
@@ -710,22 +710,26 @@ SvXMLStylesContext::~SvXMLStylesContext()
 css::uno::Reference< css::xml::sax::XFastContextHandler > 
SvXMLStylesContext::createFastChildContext(
         sal_Int32 nElement, const css::uno::Reference< 
css::xml::sax::XFastAttributeList >& xAttrList )
 {
-    SvXMLStyleContext* pStyle = CreateStyleChildContext( nElement, xAttrList );
-    if (pStyle)
-    {
-        if (!pStyle->IsTransient())
-            mpImpl->AddStyle(pStyle);
-        return pStyle;
-    }
-    else if (nElement ==  XML_ELEMENT(LO_EXT, XML_THEME))
+    if (nElement ==  XML_ELEMENT(LO_EXT, XML_THEME))
     {
+        uno::Reference<uno::XInterface> xObject(GetImport().GetModel(), 
uno::UNO_QUERY);
         uno::Reference<drawing::XDrawPageSupplier> const 
xDrawPageSupplier(GetImport().GetModel(), uno::UNO_QUERY);
         if (xDrawPageSupplier.is())
         {
             uno::Reference<drawing::XDrawPage> xPage = 
xDrawPageSupplier->getDrawPage();
             if (xPage.is())
-                return new XMLThemeContext(GetImport(), xAttrList, xPage);
+                xObject = xPage;
         }
+
+        return new XMLThemeContext(GetImport(), xAttrList, xObject);
+    }
+
+    SvXMLStyleContext* pStyle = CreateStyleChildContext( nElement, xAttrList );
+    if (pStyle)
+    {
+        if (!pStyle->IsTransient())
+            mpImpl->AddStyle(pStyle);
+        return pStyle;
     }
 
     return nullptr;

Reply via email to