tdf#129575 DOCX import: fix table style preference

handling by recognizing docDefault properties
instead of default-value based heuristics.

Change-Id: I3bab9d85d77d0e5f1c357121b1caf02cbe4899c4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88457
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
This commit is contained in:
László Németh
2020-02-04 19:31:41 +01:00
parent 1f625b3f74
commit f15d674429
17 changed files with 203 additions and 45 deletions

View File

@@ -325,8 +325,6 @@ DECLARE_OOXMLEXPORT_TEST(testTdf123636_newlinePageBreak4, "tdf123636_newlinePage
assertXPath(pDump, "/root/page[2]/body/txt[1]/Text", 0); assertXPath(pDump, "/root/page[2]/body/txt[1]/Text", 0);
} }
// disabled temporarily, next commit enables it again
#if 0
DECLARE_OOXMLEXPORT_TEST(testTdf118947_tableStyle, "tdf118947_tableStyle.docx") DECLARE_OOXMLEXPORT_TEST(testTdf118947_tableStyle, "tdf118947_tableStyle.docx")
{ {
uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY); uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
@@ -354,7 +352,6 @@ DECLARE_OOXMLEXPORT_TEST(testTdf118947_tableStyle, "tdf118947_tableStyle.docx")
CPPUNIT_ASSERT_EQUAL_MESSAGE("Table style sets 0 right margin", sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaRightMargin")); CPPUNIT_ASSERT_EQUAL_MESSAGE("Table style sets 0 right margin", sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaRightMargin"));
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Table sets 2.5 line-spacing", sal_Int16(250), getProperty<style::LineSpacing>(xPara, "ParaLineSpacing").Height, 1); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Table sets 2.5 line-spacing", sal_Int16(250), getProperty<style::LineSpacing>(xPara, "ParaLineSpacing").Height, 1);
} }
#endif
DECLARE_OOXMLEXPORT_TEST(tdf123912_protectedForm, "tdf123912_protectedForm.odt") DECLARE_OOXMLEXPORT_TEST(tdf123912_protectedForm, "tdf123912_protectedForm.odt")
{ {

View File

@@ -459,9 +459,9 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf128752, "tdf128752.docx")
DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf119054, "tdf119054.docx") DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf119054, "tdf119054.docx")
{ {
xmlDocPtr pXmlDoc = parseExport(); xmlDocPtr pXmlDoc = parseExport();
// Don't overwrite before and after spacing of Heading2 by table style // Overwrite applied table style with before and after spacing of Heading2
assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before"); assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before", "0");
assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after"); assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after", "360");
// Use table style based single line spacing instead of the docDefaults' 254 // Use table style based single line spacing instead of the docDefaults' 254
assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240"); assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240");
} }

View File

@@ -30,6 +30,7 @@
#include <com/sun/star/view/XSelectionSupplier.hpp> #include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/style/LineSpacing.hpp> #include <com/sun/star/style/LineSpacing.hpp>
#include <com/sun/star/style/LineSpacingMode.hpp> #include <com/sun/star/style/LineSpacingMode.hpp>
//#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp> #include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/drawing/XControlShape.hpp> #include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp> #include <com/sun/star/text/TextContentAnchorType.hpp>
@@ -184,6 +185,70 @@ DECLARE_OOXMLEXPORT_TEST(testTdf106690Cell, "tdf106690-cell.docx")
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), "ParaBottomMargin")); CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(494), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), "ParaBottomMargin"));
} }
DECLARE_OOXMLEXPORT_TEST(testTdf129575_directBefore, "tdf129575-directBefore.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
// direct paragraph formatting
// This was 212 twips from the table style, but always direct paragraph formatting wins, in the case of the default 0 margin, too
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaTopMargin"));
// default margin
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf129575_directAfter, "tdf129575-directAfter.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
// from table style
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(212), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaTopMargin"));
// direct paragraph formatting
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf129575_styleAfter, "tdf129575-styleAfter.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
// direct paragraph formatting
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaTopMargin"));
// from table style
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(212), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf129575_docDefault, "tdf129575-docDefault.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
// docDefault defines both bottom margin and line spacing, but
// applied bottom margin values are based on non-docDefault paragraph styles, line spacing is based on table style
// docDefault: <w:spacing w:after="160" w:line="320" w:lineRule="auto"/>
// table style: <w:spacing w:after="0" w:line="240" w:lineRule="auto"/> (single line space, overwriting bigger docDefault)
// Paragraph style Normal: <w:spacing w:after="160"/> (same as docDefault),
// table style based single line spacing
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(282), getProperty<sal_Int32>(getParagraphOfText(1, xCell->getText()), "ParaBottomMargin"));
style::LineSpacing aLineSpacing = getProperty<style::LineSpacing>(getParagraphOfText(1, xCell->getText()), "ParaLineSpacing");
CPPUNIT_ASSERT_EQUAL(sal_Int16(style::LineSpacingMode::PROP), aLineSpacing.Mode);
CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aLineSpacing.Height);
// Heading 2: <w:spacing w:after="360"/> (different from docDefault),
// table style based single line spacing
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(635), getProperty<sal_Int32>(getParagraphOfText(2, xCell->getText()), "ParaBottomMargin"));
aLineSpacing = getProperty<style::LineSpacing>(getParagraphOfText(1, xCell->getText()), "ParaLineSpacing");
CPPUNIT_ASSERT_EQUAL(sal_Int16(style::LineSpacingMode::PROP), aLineSpacing.Mode);
CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aLineSpacing.Height);
}
DECLARE_OOXMLEXPORT_TEST(testTdf106970, "tdf106970.docx") DECLARE_OOXMLEXPORT_TEST(testTdf106970, "tdf106970.docx")
{ {
// The second paragraph (first numbered one) had 0 bottom margin: // The second paragraph (first numbered one) had 0 bottom margin:

View File

@@ -59,6 +59,7 @@ using namespace ::std;
#define CNF_FIRST_ROW_FIRST_COLUMN 0x004 #define CNF_FIRST_ROW_FIRST_COLUMN 0x004
#define CNF_LAST_ROW_LAST_COLUMN 0x002 #define CNF_LAST_ROW_LAST_COLUMN 0x002
#define CNF_LAST_ROW_FIRST_COLUMN 0x001 #define CNF_LAST_ROW_FIRST_COLUMN 0x001
#define CNF_ALL 0xFFF
DomainMapperTableHandler::DomainMapperTableHandler( DomainMapperTableHandler::DomainMapperTableHandler(
css::uno::Reference<css::text::XTextAppendAndConvert> const& xText, css::uno::Reference<css::text::XTextAppendAndConvert> const& xText,
@@ -225,6 +226,7 @@ struct TableInfo
PropertyMapPtr pTableBorders; PropertyMapPtr pTableBorders;
TableStyleSheetEntry* pTableStyle; TableStyleSheetEntry* pTableStyle;
css::beans::PropertyValues aTableProperties; css::beans::PropertyValues aTableProperties;
std::vector< PropertyIds > aTablePropertyIds;
TableInfo() TableInfo()
: nLeftBorderDistance(DEF_BORDER_DIST) : nLeftBorderDistance(DEF_BORDER_DIST)
@@ -664,6 +666,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
} }
rInfo.aTableProperties = m_aTableProperties->GetPropertyValues(); rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
rInfo.aTablePropertyIds = m_aTableProperties->GetPropertyIds();
#ifdef DBG_UTIL #ifdef DBG_UTIL
TagLogger::getInstance().startElement("debug.tableprops"); TagLogger::getInstance().startElement("debug.tableprops");
@@ -863,9 +866,6 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
// Remove properties from style/row that aren't allowed in cells // Remove properties from style/row that aren't allowed in cells
pAllCellProps->Erase( PROP_HEADER_ROW_COUNT ); pAllCellProps->Erase( PROP_HEADER_ROW_COUNT );
pAllCellProps->Erase( PROP_TBL_HEADER ); pAllCellProps->Erase( PROP_TBL_HEADER );
// Remove paragraph properties from style/row that paragraph style can overwrite
pAllCellProps->Erase( PROP_PARA_BOTTOM_MARGIN );
pAllCellProps->Erase( PROP_PARA_LINE_SPACING );
// Then add the cell properties // Then add the cell properties
pAllCellProps->InsertProps(*aCellIterator); pAllCellProps->InsertProps(*aCellIterator);
@@ -1066,29 +1066,59 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl
// table style has got bigger precedence than docDefault style, // table style has got bigger precedence than docDefault style,
// but lower precedence than the paragraph styles and direct paragraph formatting // but lower precedence than the paragraph styles and direct paragraph formatting
void DomainMapperTableHandler::ApplyParaProperty(css::beans::PropertyValues aTableProperties, PropertyIds eId) void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo)
{ {
OUString sPropertyName = getPropertyName(eId); for( auto const& eId : rInfo.aTablePropertyIds )
auto pTableProp = std::find_if(aTableProperties.begin(), aTableProperties.end(),
[&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
if (pTableProp != aTableProperties.end())
{ {
uno::Any aValue = pTableProp->Value; // apply paragraph and character properties of the table style on table paragraphs
if ( isParagraphProperty(eId) || isCharacterProperty(eId) )
{
// check all paragraphs of the table
for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable) for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable)
{ {
// there is no direct paragraph formatting // there is no direct paragraph formatting
if (!rParaProp.m_pPropertyMap->isSet(eId)) if (!rParaProp.m_pPropertyMap->isSet(eId))
{ {
bool bDocDefault;
OUString sParaStyleName; OUString sParaStyleName;
rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName; rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName); StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
uno::Any aMargin = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true); uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
uno::Any aMarginDocDefault = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, nullptr, true, true); // use table style when a docDefault value is applied instead of it,
// use table style only when 1) both values are empty (no docDefault and paragraph style definitions) or // and there is no associated TableStyleSheetEntry
// 2) both non-empty values are equal (docDefault paragraph properties are copied to the base paragraph style during import) // TODO: replace CNF_ALL with the actual mask
// TODO check the case, when two parent styles modify the docDefault and the last one set back the docDefault value if ( (aParaStyle == uno::Any() || bDocDefault) && !rInfo.pTableStyle->GetProperties(CNF_ALL)->getProperty(eId) )
if (aMargin == aMarginDocDefault) {
rParaProp.m_rPropertySet->setPropertyValue(sPropertyName, aValue); OUString sPropertyName = getPropertyName(eId);
auto pTableProp = std::find_if(rInfo.aTableProperties.begin(), rInfo.aTableProperties.end(),
[&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
if (pTableProp != rInfo.aTableProperties.end())
{
try
{
rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pTableProp->Value );
}
catch ( const uno::Exception & )
{
TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
}
}
}
// table style can overwrite paragraph style, when the paragraph style property has a default value, restore it
// TODO remove the associated TableStyleSheetEntry styles, if needed
else if ( aParaStyle != uno::Any() && !bDocDefault )
{
OUString sPropertyName = getPropertyName(eId);
try
{
rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, aParaStyle );
}
catch ( const uno::Exception & )
{
TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
}
}
}
} }
} }
} }
@@ -1192,9 +1222,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
} }
} }
// OOXML table style may container paragraph properties, apply these now. // OOXML table style may contain paragraph properties, apply these now.
ApplyParaProperty(aTableInfo.aTableProperties, PROP_PARA_BOTTOM_MARGIN); ApplyParagraphPropertiesFromTableStyle(aTableInfo);
ApplyParaProperty(aTableInfo.aTableProperties, PROP_PARA_LINE_SPACING);
} }
} }
catch ( const lang::IllegalArgumentException & ) catch ( const lang::IllegalArgumentException & )

View File

@@ -91,7 +91,7 @@ public:
*/ */
void startTable(const TablePropertyMapPtr& pProps); void startTable(const TablePropertyMapPtr& pProps);
void ApplyParaProperty(css::beans::PropertyValues aTableProperties, PropertyIds eId); void ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo);
/// Handle end of table. /// Handle end of table.
void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart); void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart);

View File

@@ -807,7 +807,7 @@ OUString DomainMapper_Impl::GetDefaultParaStyleName()
return m_sDefaultParaStyleName; return m_sDefaultParaStyleName;
} }
uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara) uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, bool* pIsDocDefault)
{ {
while(pEntry.get( ) ) while(pEntry.get( ) )
{ {
@@ -817,6 +817,9 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
pEntry->pProperties->getProperty(eId); pEntry->pProperties->getProperty(eId);
if( aProperty ) if( aProperty )
{ {
if (pIsDocDefault)
*pIsDocDefault = pEntry->pProperties->isDocDefault(eId);
return aProperty->second; return aProperty->second;
} }
} }
@@ -840,9 +843,14 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
{ {
o3tl::optional<PropertyMap::Property> aProperty = pDefaultParaProps->getProperty(eId); o3tl::optional<PropertyMap::Property> aProperty = pDefaultParaProps->getProperty(eId);
if ( aProperty ) if ( aProperty )
{
if (pIsDocDefault)
*pIsDocDefault = true;
return aProperty->second; return aProperty->second;
} }
} }
}
if ( bDocDefaults && isCharacterProperty(eId) ) if ( bDocDefaults && isCharacterProperty(eId) )
{ {
const PropertyMapPtr& pDefaultCharProps = GetStyleSheetTable()->GetDefaultCharProps(); const PropertyMapPtr& pDefaultCharProps = GetStyleSheetTable()->GetDefaultCharProps();
@@ -850,9 +858,18 @@ uno::Any DomainMapper_Impl::GetPropertyFromStyleSheet(PropertyIds eId, StyleShee
{ {
o3tl::optional<PropertyMap::Property> aProperty = pDefaultCharProps->getProperty(eId); o3tl::optional<PropertyMap::Property> aProperty = pDefaultCharProps->getProperty(eId);
if ( aProperty ) if ( aProperty )
{
if (pIsDocDefault)
*pIsDocDefault = true;
return aProperty->second; return aProperty->second;
} }
} }
}
if (pIsDocDefault)
*pIsDocDefault = false;
return uno::Any(); return uno::Any();
} }

View File

@@ -761,7 +761,7 @@ public:
OUString GetDefaultParaStyleName(); OUString GetDefaultParaStyleName();
// specified style - including inherited properties. Indicate whether paragraph defaults should be checked. // specified style - including inherited properties. Indicate whether paragraph defaults should be checked.
css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara); css::uno::Any GetPropertyFromStyleSheet(PropertyIds eId, StyleSheetEntryPtr pEntry, const bool bDocDefaults, const bool bPara, bool* bIsDocDefault = nullptr);
// current paragraph style - including inherited properties // current paragraph style - including inherited properties
css::uno::Any GetPropertyFromParaStyleSheet(PropertyIds eId); css::uno::Any GetPropertyFromParaStyleSheet(PropertyIds eId);
// context's character style - including inherited properties // context's character style - including inherited properties

View File

@@ -364,6 +364,11 @@ bool isCharacterProperty( const PropertyIds eId )
return eId > PROP_CHARACTER_STYLES && eId < PROP_CHARACTER_END; return eId > PROP_CHARACTER_STYLES && eId < PROP_CHARACTER_END;
} }
bool isParagraphProperty( const PropertyIds eId )
{
return eId >= PROP_PARA_ADJUST && eId <= PROP_PARA_WIDOWS;
}
} //namespace writerfilter } //namespace writerfilter
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -362,6 +362,8 @@ OUString getPropertyName(PropertyIds eId);
bool isCharacterProperty(const PropertyIds eId); bool isCharacterProperty(const PropertyIds eId);
bool isParagraphProperty(const PropertyIds eId);
} //namespace dmapper } //namespace dmapper
} // namespace writerfilter } // namespace writerfilter
#endif #endif

View File

@@ -185,6 +185,14 @@ uno::Sequence< beans::PropertyValue > PropertyMap::GetPropertyValues( bool bChar
return comphelper::containerToSequence( m_aValues ); return comphelper::containerToSequence( m_aValues );
} }
std::vector< PropertyIds > PropertyMap::GetPropertyIds()
{
std::vector< PropertyIds > aRet;
for ( const auto& rPropPair : m_vMap )
aRet.push_back( rPropPair.first );
return aRet;
}
#ifdef DBG_UTIL #ifdef DBG_UTIL
static void lcl_AnyToTag( const uno::Any& rAny ) static void lcl_AnyToTag( const uno::Any& rAny )
{ {
@@ -223,7 +231,7 @@ static void lcl_AnyToTag( const uno::Any& rAny )
} }
#endif #endif
void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite, GrabBagType i_GrabBagType ) void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite, GrabBagType i_GrabBagType, bool bDocDefault )
{ {
#ifdef DBG_UTIL #ifdef DBG_UTIL
const OUString& rInsert = getPropertyName(eId); const OUString& rInsert = getPropertyName(eId);
@@ -235,7 +243,7 @@ void PropertyMap::Insert( PropertyIds eId, const uno::Any& rAny, bool bOverwrite
#endif #endif
if ( !bOverwrite ) if ( !bOverwrite )
m_vMap.insert(std::make_pair(eId, PropValue(rAny, i_GrabBagType))); m_vMap.insert(std::make_pair(eId, PropValue(rAny, i_GrabBagType, bDocDefault)));
else else
m_vMap[eId] = PropValue(rAny, i_GrabBagType); m_vMap[eId] = PropValue(rAny, i_GrabBagType);
@@ -264,6 +272,15 @@ bool PropertyMap::isSet( PropertyIds eId) const
return m_vMap.find( eId ) != m_vMap.end(); return m_vMap.find( eId ) != m_vMap.end();
} }
bool PropertyMap::isDocDefault( PropertyIds eId ) const
{
std::map< PropertyIds, PropValue >::const_iterator aIter = m_vMap.find( eId );
if ( aIter == m_vMap.end() )
return false;
else
return aIter->second.getIsDocDefault();
}
#ifdef DBG_UTIL #ifdef DBG_UTIL
void PropertyMap::dumpXml() const void PropertyMap::dumpXml() const
{ {
@@ -320,8 +337,13 @@ void PropertyMap::InsertProps( const PropertyMapPtr& rMap, const bool bOverwrite
for ( const auto& rPropPair : rMap->m_vMap ) for ( const auto& rPropPair : rMap->m_vMap )
{ {
if ( bOverwrite || !m_vMap.count(rPropPair.first) ) if ( bOverwrite || !m_vMap.count(rPropPair.first) )
{
if ( !bOverwrite && !rPropPair.second.getIsDocDefault() )
m_vMap.insert(std::make_pair(rPropPair.first, PropValue(rPropPair.second.getValue(), rPropPair.second.getGrabBagType(), true)));
else
m_vMap[rPropPair.first] = rPropPair.second; m_vMap[rPropPair.first] = rPropPair.second;
} }
}
insertTableProperties( rMap.get(), bOverwrite ); insertTableProperties( rMap.get(), bOverwrite );

View File

@@ -95,23 +95,35 @@ class PropValue
private: private:
css::uno::Any m_aValue; css::uno::Any m_aValue;
GrabBagType m_GrabBagType; GrabBagType m_GrabBagType;
bool m_bIsDocDefault;
public: public:
PropValue( const css::uno::Any& rValue, GrabBagType i_GrabBagType, bool bDocDefault )
: m_aValue( rValue )
, m_GrabBagType( i_GrabBagType )
, m_bIsDocDefault( bDocDefault )
{
}
PropValue( const css::uno::Any& rValue, GrabBagType i_GrabBagType ) PropValue( const css::uno::Any& rValue, GrabBagType i_GrabBagType )
: m_aValue( rValue ) : m_aValue( rValue )
, m_GrabBagType( i_GrabBagType ) , m_GrabBagType( i_GrabBagType )
, m_bIsDocDefault( false )
{ {
} }
PropValue() PropValue()
: m_aValue() : m_aValue()
, m_GrabBagType( NO_GRAB_BAG ) , m_GrabBagType( NO_GRAB_BAG )
, m_bIsDocDefault( false )
{ {
} }
const css::uno::Any& getValue() const { return m_aValue; } const css::uno::Any& getValue() const { return m_aValue; }
GrabBagType getGrabBagType() const { return m_GrabBagType; } GrabBagType getGrabBagType() const { return m_GrabBagType; }
bool getIsDocDefault() const { return m_bIsDocDefault; }
}; };
class PropertyMap; class PropertyMap;
@@ -139,13 +151,15 @@ public:
// the contained properties are their Value. // the contained properties are their Value.
css::uno::Sequence< css::beans::PropertyValue > GetPropertyValues( bool bCharGrabBag = true ); css::uno::Sequence< css::beans::PropertyValue > GetPropertyValues( bool bCharGrabBag = true );
std::vector< PropertyIds > GetPropertyIds();
// Add property, optionally overwriting existing attributes // Add property, optionally overwriting existing attributes
void Insert( PropertyIds eId, const css::uno::Any& rAny, bool bOverwrite = true, GrabBagType i_GrabBagType = NO_GRAB_BAG ); void Insert( PropertyIds eId, const css::uno::Any& rAny, bool bOverwrite = true, GrabBagType i_GrabBagType = NO_GRAB_BAG, bool bDocDefault = false );
// Remove a named property from *this, does nothing if the property id has not been set // Remove a named property from *this, does nothing if the property id has not been set
void Erase( PropertyIds eId); void Erase( PropertyIds eId);
// Imports properties from pMap // Imports properties from pMap (bOverwrite==false means m_bIsDocDefault=true setting)
void InsertProps( const PropertyMapPtr& rMap, const bool bOverwrite = true ); void InsertProps( const PropertyMapPtr& rMap, const bool bOverwrite = true );
// Returns a copy of the property if it exists, .first is its PropertyIds and .second is its Value (type css::uno::Any) // Returns a copy of the property if it exists, .first is its PropertyIds and .second is its Value (type css::uno::Any)
@@ -153,6 +167,7 @@ public:
// Has the property named been set (via Insert)? // Has the property named been set (via Insert)?
bool isSet( PropertyIds eId ) const; bool isSet( PropertyIds eId ) const;
bool isDocDefault( PropertyIds eId ) const;
const css::uno::Reference< css::text::XFootnote >& GetFootnote() const { return m_xFootnote; } const css::uno::Reference< css::text::XFootnote >& GetFootnote() const { return m_xFootnote; }
const OUString& GetFootnoteStyle() const { return m_sFootnoteCharStyleName; } const OUString& GetFootnoteStyle() const { return m_sFootnoteCharStyleName; }

View File

@@ -396,6 +396,11 @@ StyleSheetTable::~StyleSheetTable()
{ {
} }
void StyleSheetTable::SetDefaultParaProps(PropertyIds eId, const css::uno::Any& rAny)
{
m_pImpl->m_pDefaultParaProps->Insert(eId, rAny, /*bOverwrite=*/false, NO_GRAB_BAG, /*bDocDefault=*/true);
}
PropertyMapPtr const & StyleSheetTable::GetDefaultParaProps() const PropertyMapPtr const & StyleSheetTable::GetDefaultParaProps() const
{ {
return m_pImpl->m_pDefaultParaProps; return m_pImpl->m_pDefaultParaProps;
@@ -691,7 +696,7 @@ void StyleSheetTable::lcl_sprm(Sprm & rSprm)
if ( nSprmId == NS_ooxml::LN_CT_DocDefaults_pPrDefault && m_pImpl->m_pDefaultParaProps.get() && if ( nSprmId == NS_ooxml::LN_CT_DocDefaults_pPrDefault && m_pImpl->m_pDefaultParaProps.get() &&
!m_pImpl->m_pDefaultParaProps->isSet( PROP_PARA_TOP_MARGIN ) ) !m_pImpl->m_pDefaultParaProps->isSet( PROP_PARA_TOP_MARGIN ) )
{ {
m_pImpl->m_pDefaultParaProps->Insert( PROP_PARA_TOP_MARGIN, uno::makeAny( sal_Int32(0) ) ); SetDefaultParaProps( PROP_PARA_TOP_MARGIN, uno::makeAny( sal_Int32(0) ) );
} }
m_pImpl->m_rDMapper.PopStyleSheetProperties(); m_pImpl->m_rDMapper.PopStyleSheetProperties();
applyDefaults( true ); applyDefaults( true );
@@ -990,7 +995,7 @@ void StyleSheetTable::ApplyStyleSheets( const FontTablePtr& rFontTable )
else if( bParaStyle ) else if( bParaStyle )
{ {
// Paragraph styles that don't inherit from some parent need to apply the DocDefaults // Paragraph styles that don't inherit from some parent need to apply the DocDefaults
pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bAllowOverwrite=*/false ); pEntry->pProperties->InsertProps( m_pImpl->m_pDefaultParaProps, /*bOverwrite=*/false );
//now it's time to set the default parameters - for paragraph styles //now it's time to set the default parameters - for paragraph styles
//Fonts: Western first entry in font table //Fonts: Western first entry in font table
@@ -1454,13 +1459,13 @@ void StyleSheetTable::applyDefaults(bool bParaProperties)
if( bParaProperties && m_pImpl->m_pDefaultParaProps.get()) if( bParaProperties && m_pImpl->m_pDefaultParaProps.get())
{ {
// tdf#87533 LO will have different defaults here, depending on the locale. Import with documented defaults // tdf#87533 LO will have different defaults here, depending on the locale. Import with documented defaults
m_pImpl->m_pDefaultParaProps->Insert(PROP_WRITING_MODE, uno::makeAny(sal_Int16(text::WritingMode_LR_TB)), /*bOverwrite=*/false); SetDefaultParaProps(PROP_WRITING_MODE, uno::makeAny(sal_Int16(text::WritingMode_LR_TB)));
m_pImpl->m_pDefaultParaProps->Insert(PROP_PARA_ADJUST, uno::makeAny(sal_Int16(style::ParagraphAdjust_LEFT)), false); SetDefaultParaProps(PROP_PARA_ADJUST, uno::makeAny(sal_Int16(style::ParagraphAdjust_LEFT)));
// Widow/Orphan -> set both to two if not already set // Widow/Orphan -> set both to two if not already set
uno::Any aTwo = uno::makeAny(sal_Int8(2)); uno::Any aTwo = uno::makeAny(sal_Int8(2));
m_pImpl->m_pDefaultParaProps->Insert(PROP_PARA_WIDOWS, aTwo, /*bOverwrite=*/false); SetDefaultParaProps(PROP_PARA_WIDOWS, aTwo);
m_pImpl->m_pDefaultParaProps->Insert(PROP_PARA_ORPHANS, aTwo, false); SetDefaultParaProps(PROP_PARA_ORPHANS, aTwo);
uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier(m_pImpl->m_xTextDocument, uno::UNO_QUERY); uno::Reference<style::XStyleFamiliesSupplier> xStylesSupplier(m_pImpl->m_xTextDocument, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xStyleFamilies = xStylesSupplier->getStyleFamilies(); uno::Reference<container::XNameAccess> xStyleFamilies = xStylesSupplier->getStyleFamilies();

View File

@@ -102,6 +102,7 @@ public:
OUString getOrCreateCharStyle( PropertyValueVector_t& rCharProperties, bool bAlwaysCreate ); OUString getOrCreateCharStyle( PropertyValueVector_t& rCharProperties, bool bAlwaysCreate );
void SetDefaultParaProps(PropertyIds eId, const css::uno::Any& rAny);
PropertyMapPtr const & GetDefaultParaProps() const; PropertyMapPtr const & GetDefaultParaProps() const;
/// Returns the default character properties. /// Returns the default character properties.
PropertyMapPtr const & GetDefaultCharProps() const; PropertyMapPtr const & GetDefaultCharProps() const;