summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Monastirsky <momonasmon@gmail.com>2022-11-13 11:05:28 +0200
committerMaxim Monastirsky <momonasmon@gmail.com>2022-11-21 14:38:59 +0100
commit5d683e8f6c9e677d7b6bc829a4ce9ee384f4fbd8 (patch)
treeab8bc64934e52293f3289461ae906f88de039fca
parent9e4b47190eb762f3aea80920846fe5135b7d76fc (diff)
Export modified table styles
In addition to actually used styles, we want to export user defined styles, as well as built in styles that were modified. Detecting the real modification state might be challenging in some cases, e.g. when importing the style from an existing document. So for simplicity, we consider a style as "modified" if at least one of its child cell styles is user defined. The UI for modifying cell styles will be implemented in such a way that built in styles will never be modified themselves. Instead, a user defined style will be created on the fly, with the corresponding built in style set as its parent, and only that new style will be modified. It is still possible to modify built in cell styles via the UNO API, but such styles won't be exported unless actually used in the document. Change-Id: Ic73eb460fd024f23016553e134397e07259f5c90 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143011 Tested-by: Jenkins Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
-rw-r--r--sd/qa/unit/data/odg/tablestyles.fodg22
-rw-r--r--sd/qa/unit/export-tests.cxx35
-rw-r--r--sd/source/core/drawdoc4.cxx5
-rw-r--r--sd/source/core/stlsheet.cxx9
-rw-r--r--svx/source/table/tabledesign.cxx87
-rw-r--r--xmloff/source/table/XMLTableExport.cxx14
6 files changed, 167 insertions, 5 deletions
diff --git a/sd/qa/unit/data/odg/tablestyles.fodg b/sd/qa/unit/data/odg/tablestyles.fodg
index 7b54e73955f9..3672ad8e4a70 100644
--- a/sd/qa/unit/data/odg/tablestyles.fodg
+++ b/sd/qa/unit/data/odg/tablestyles.fodg
@@ -2,6 +2,28 @@
<office:document xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.graphics">
<office:scripts/>
<office:font-face-decls/>
+ <office:styles>
+ <style:style style:name="default" style:family="table-cell"/>
+ <style:style style:name="userdefined" style:family="table-cell"/>
+ <table:table-template table:name="default">
+ <table:first-row table:style-name="userdefined"/>
+ <table:last-row table:style-name="userdefined"/>
+ <table:first-column table:style-name="userdefined"/>
+ <table:last-column table:style-name="userdefined"/>
+ <table:body table:style-name="userdefined"/>
+ <table:odd-rows table:style-name="userdefined"/>
+ <table:odd-columns table:style-name="userdefined"/>
+ </table:table-template>
+ <table:table-template table:name="userdefined">
+ <table:first-row table:style-name="default"/>
+ <table:last-row table:style-name="default"/>
+ <table:first-column table:style-name="default"/>
+ <table:last-column table:style-name="default"/>
+ <table:body table:style-name="default"/>
+ <table:odd-rows table:style-name="default"/>
+ <table:odd-columns table:style-name="default"/>
+ </table:table-template>
+ </office:styles>
<office:automatic-styles>
<style:page-layout style:name="PM0">
<style:page-layout-properties fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="1cm" fo:margin-right="1cm" fo:page-width="21.59cm" fo:page-height="27.94cm" style:print-orientation="portrait"/>
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index 288e9acacf99..7d7f5c747cf9 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -102,6 +102,7 @@ public:
void testColumnsODG();
void testTdf112126();
void testCellProperties();
+ void testUserTableStyles();
CPPUNIT_TEST_SUITE(SdExportTest);
@@ -151,6 +152,7 @@ public:
CPPUNIT_TEST(testColumnsODG);
CPPUNIT_TEST(testTdf112126);
CPPUNIT_TEST(testCellProperties);
+ CPPUNIT_TEST(testUserTableStyles);
CPPUNIT_TEST_SUITE_END();
virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override
@@ -1767,6 +1769,11 @@ void SdExportTest::testTdf112126()
void SdExportTest::testCellProperties()
{
+ // Silence unrelated failure:
+ // Error: element "table:table-template" is missing "first-row-start-column" attribute
+ // Looks like an oversight in the schema, as the docs claim this attribute is deprecated.
+ skipValidation();
+
loadFromURL(u"odg/tablestyles.fodg");
saveAndReload("draw8");
@@ -1792,6 +1799,34 @@ void SdExportTest::testCellProperties()
CPPUNIT_ASSERT_EQUAL(drawing::TextVerticalAdjust::TextVerticalAdjust_CENTER, aTextAdjust);
}
+void SdExportTest::testUserTableStyles()
+{
+ // Silence unrelated failure:
+ // Error: element "table:table-template" is missing "first-row-start-column" attribute
+ // Looks like an oversight in the schema, as the docs claim this attribute is deprecated.
+ skipValidation();
+
+ loadFromURL(u"odg/tablestyles.fodg");
+ saveAndReload("draw8");
+
+ uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent,
+ uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xStyleFamily(
+ xStyleFamiliesSupplier->getStyleFamilies()->getByName("table"), uno::UNO_QUERY);
+
+ uno::Reference<style::XStyle> xTableStyle(xStyleFamily->getByName("default"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(!xTableStyle->isUserDefined());
+
+ uno::Reference<container::XNameAccess> xNameAccess(xTableStyle, uno::UNO_QUERY);
+ uno::Reference<style::XStyle> xCellStyle(xNameAccess->getByName("first-row"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xCellStyle);
+ CPPUNIT_ASSERT_EQUAL(OUString("userdefined"), xCellStyle->getName());
+
+ CPPUNIT_ASSERT(xStyleFamily->hasByName("userdefined"));
+ xTableStyle.set(xStyleFamily->getByName("userdefined"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xTableStyle->isUserDefined());
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SdExportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/core/drawdoc4.cxx b/sd/source/core/drawdoc4.cxx
index a4e1eb5a0c7c..0b8898e3095b 100644
--- a/sd/source/core/drawdoc4.cxx
+++ b/sd/source/core/drawdoc4.cxx
@@ -21,6 +21,7 @@
#include <com/sun/star/style/XStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/form/XReset.hpp>
#include <i18nlangtag/languagetag.hxx>
#include <i18nlangtag/mslangid.hxx>
#include <sfx2/dispatch.hxx>
@@ -785,6 +786,10 @@ void SdDrawDocument::CreateDefaultCellStyles()
Any aYellow3( implMakeSolidCellStyle( pSSPool, "yellow3" , aDefaultCellStyleName, Color(255,204,153)));
implCreateTableTemplate( xTableFamily, "yellow" , aYellow1, aYellow3, aYellow2 );
+
+ Reference<form::XReset> xReset(xTableFamily, UNO_QUERY);
+ if (xReset)
+ xReset->reset();
}
// Number of pages that reference a master page
diff --git a/sd/source/core/stlsheet.cxx b/sd/source/core/stlsheet.cxx
index 71cf76709ed1..14a0b13dd15c 100644
--- a/sd/source/core/stlsheet.cxx
+++ b/sd/source/core/stlsheet.cxx
@@ -309,6 +309,15 @@ bool SdStyleSheet::IsUsed() const
bResult = std::any_of(aModifyListeners.begin(), aModifyListeners.end(),
[](const Reference<XInterface>& rListener) {
Reference< XStyle > xStyle( rListener, UNO_QUERY );
+ try
+ {
+ Reference<XPropertySet> xPropertySet(xStyle, UNO_QUERY_THROW);
+ if (xPropertySet->getPropertyValue("IsPhysical").get<bool>())
+ return true;
+ }
+ catch (const Exception&)
+ {
+ }
return xStyle.is() && xStyle->isInUse();
});
}
diff --git a/svx/source/table/tabledesign.cxx b/svx/source/table/tabledesign.cxx
index ec316972232d..d4fe8cda4460 100644
--- a/svx/source/table/tabledesign.cxx
+++ b/svx/source/table/tabledesign.cxx
@@ -28,6 +28,7 @@
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/util/XModifyBroadcaster.hpp>
#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/form/XReset.hpp>
#include <vcl/svapp.hxx>
@@ -47,6 +48,7 @@
#include <map>
+using namespace css;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::lang;
@@ -58,7 +60,7 @@ namespace sdr::table {
typedef std::map< OUString, sal_Int32 > CellStyleNameMap;
-typedef ::comphelper::WeakComponentImplHelper< XStyle, XNameReplace, XServiceInfo, XIndexAccess, XModifyBroadcaster, XModifyListener > TableDesignStyleBase;
+typedef ::comphelper::WeakComponentImplHelper< XStyle, XNameReplace, XServiceInfo, XIndexAccess, XModifyBroadcaster, XModifyListener, XPropertySet > TableDesignStyleBase;
namespace {
@@ -98,6 +100,15 @@ public:
// XNameReplace
virtual void SAL_CALL replaceByName( const OUString& aName, const Any& aElement ) override;
+ // XPropertySet
+ virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const Any& aValue ) override;
+ virtual Any SAL_CALL getPropertyValue( const OUString& PropertyName ) override;
+ virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const Reference<XPropertyChangeListener>& xListener ) override;
+ virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener ) override;
+ virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener>& aListener ) override;
+ virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName,const Reference<XVetoableChangeListener>&aListener ) override;
+
// XModifyBroadcaster
virtual void SAL_CALL addModifyListener( const Reference< XModifyListener >& aListener ) override;
virtual void SAL_CALL removeModifyListener( const Reference< XModifyListener >& aListener ) override;
@@ -107,12 +118,14 @@ public:
virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
void notifyModifyListener();
+ void resetUserDefined();
// this function is called upon disposing the component
virtual void disposing(std::unique_lock<std::mutex>& aGuard) override;
static const CellStyleNameMap& getCellStyleNameMap();
+ bool mbUserDefined, mbModified;
OUString msName;
Reference< XStyle > maCellStyles[style_count];
comphelper::OInterfaceContainerHelper4<XModifyListener> maModifyListeners;
@@ -124,7 +137,7 @@ typedef std::vector< Reference< XStyle > > TableDesignStyleVector;
namespace {
-class TableDesignFamily : public ::cppu::WeakImplHelper< XNameContainer, XNamed, XIndexAccess, XSingleServiceFactory, XServiceInfo, XComponent, XPropertySet >
+class TableDesignFamily : public ::cppu::WeakImplHelper< XNameContainer, XNamed, XIndexAccess, XSingleServiceFactory, XServiceInfo, XComponent, XPropertySet, form::XReset >
{
public:
// XServiceInfo
@@ -174,12 +187,19 @@ public:
virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener>& aListener ) override;
virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName,const Reference<XVetoableChangeListener>&aListener ) override;
+ // XReset
+ virtual void SAL_CALL reset() override;
+ virtual void SAL_CALL addResetListener( const Reference<form::XResetListener>& aListener ) override;
+ virtual void SAL_CALL removeResetListener( const Reference<form::XResetListener>& aListener ) override;
+
TableDesignStyleVector maDesigns;
};
}
TableDesignStyle::TableDesignStyle()
+ : mbUserDefined(true)
+ , mbModified(false)
{
}
@@ -221,7 +241,12 @@ Sequence< OUString > SAL_CALL TableDesignStyle::getSupportedServiceNames()
// XStyle
sal_Bool SAL_CALL TableDesignStyle::isUserDefined()
{
- return false;
+ return mbUserDefined;
+}
+
+void TableDesignStyle::resetUserDefined()
+{
+ mbUserDefined = false;
}
sal_Bool SAL_CALL TableDesignStyle::isInUse()
@@ -367,6 +392,9 @@ void SAL_CALL TableDesignStyle::replaceByName( const OUString& rName, const Any&
if( xNewBroadcaster.is() )
xNewBroadcaster->addModifyListener( xListener );
+ if (xNewStyle && xNewStyle->isUserDefined())
+ mbModified = true;
+
maCellStyles[nIndex] = xNewStyle;
}
@@ -387,6 +415,41 @@ void TableDesignStyle::disposing(std::unique_lock<std::mutex>& aGuard)
}
}
+// XPropertySet
+
+Reference<XPropertySetInfo> TableDesignStyle::getPropertySetInfo()
+{
+ return {};
+}
+
+void TableDesignStyle::setPropertyValue( const OUString&, const Any& )
+{
+}
+
+Any TableDesignStyle::getPropertyValue( const OUString& PropertyName )
+{
+ if (PropertyName != "IsPhysical")
+ throw UnknownPropertyException("unknown property: " + PropertyName, static_cast<OWeakObject *>(this));
+
+ return Any(mbModified || mbUserDefined);
+}
+
+void TableDesignStyle::addPropertyChangeListener( const OUString&, const Reference<XPropertyChangeListener>& )
+{
+}
+
+void TableDesignStyle::removePropertyChangeListener( const OUString&, const Reference<XPropertyChangeListener>& )
+{
+}
+
+void TableDesignStyle::addVetoableChangeListener( const OUString&, const Reference<XVetoableChangeListener>& )
+{
+}
+
+void TableDesignStyle::removeVetoableChangeListener( const OUString&,const Reference<XVetoableChangeListener>& )
+{
+}
+
// XModifyBroadcaster
@@ -602,6 +665,9 @@ void SAL_CALL TableDesignFamily::replaceByName( const OUString& rName, const Any
[&rName](const Reference<XStyle>& rpStyle) { return rpStyle->getName() == rName; });
if (iter != maDesigns.end())
{
+ if (!(*iter)->isUserDefined())
+ static_cast<TableDesignStyle*>(xStyle.get())->resetUserDefined();
+
Reference<XComponent> xComponent(*iter, UNO_QUERY);
if (xComponent)
xComponent->dispose();
@@ -707,6 +773,21 @@ void TableDesignFamily::removeVetoableChangeListener( const OUString& , const Re
OSL_FAIL( "###unexpected!" );
}
+// XReset
+
+void TableDesignFamily::reset()
+{
+ for (const auto& aDesign : maDesigns)
+ static_cast<TableDesignStyle*>(aDesign.get())->resetUserDefined();
+}
+
+void TableDesignFamily::addResetListener( const Reference<form::XResetListener>& )
+{
+}
+
+void TableDesignFamily::removeResetListener( const Reference<form::XResetListener>& )
+{
+}
Reference< XNameAccess > CreateTableDesignFamily()
{
diff --git a/xmloff/source/table/XMLTableExport.cxx b/xmloff/source/table/XMLTableExport.cxx
index 54bfb268d054..f415bb171af9 100644
--- a/xmloff/source/table/XMLTableExport.cxx
+++ b/xmloff/source/table/XMLTableExport.cxx
@@ -598,14 +598,24 @@ void XMLTableExport::exportTableTemplates()
SvtSaveOptions::ODFSaneDefaultVersion eVersion = mrExport.getSaneDefaultVersion();
Reference< XStyle > xTableStyle( xTableFamily->getByIndex( nIndex ), UNO_QUERY_THROW );
- if( !xTableStyle->isInUse() )
+ Reference<XPropertySet> xTableStylePropSet( xTableStyle, UNO_QUERY_THROW );
+ bool bPhysical = false;
+
+ try
+ {
+ xTableStylePropSet->getPropertyValue("IsPhysical") >>= bPhysical;
+ }
+ catch(const Exception&)
+ {
+ }
+
+ if (!xTableStyle->isInUse() && !bPhysical)
continue;
const TableStyleElement* pElements;
if (mbWriter)
{
mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, xTableStyle->getName());
- Reference<XPropertySet> xTableStylePropSet(xTableStyle, UNO_QUERY_THROW);
pElements = getWriterSpecificTableStyleAttributes();
while(pElements->meElement != XML_TOKEN_END)
{