[Libreoffice-commits] core.git: Branch 'libreoffice-4-3' - sw/qa writerfilter/source

Luboš Luňák l.lunak at collabora.com
Fri Aug 22 05:57:03 PDT 2014


 sw/qa/extras/ooxmlimport/data/bnc519228_odd-breaks.docx |binary
 sw/qa/extras/ooxmlimport/ooxmlimport.cxx                |   31 ++
 writerfilter/source/dmapper/PropertyMap.cxx             |  180 +++++++++-------
 writerfilter/source/dmapper/PropertyMap.hxx             |    2 
 4 files changed, 138 insertions(+), 75 deletions(-)

New commits:
commit 3680f2d74964c38f153fd26a09d773a0592a1aa6
Author: Luboš Luňák <l.lunak at collabora.com>
Date:   Sun Aug 17 21:35:48 2014 +0200

    fix reading even/odd page breaks from .docx (bnc#519228)
    
    We map Word's even/odd page breaks to Writer's left/right page styles. And we cannot
    just set any page style to be left/right, because that could set e.g. the default
    page style as such, which would make all normal pages that way. So instead we need
    to make a copy of the relevant page style, as the original page style as its follow,
    copy all the properties and headers/footers, and use this copy to get the page break.
    
    (cherry picked from commit b32881b6723072c8d1a652ea147d12e75766d504)
    
    Conflicts:
    	sw/qa/extras/ooxmlimport/ooxmlimport.cxx
    
    Change-Id: Id0d2568de91ac2de4afb0ba3a6eedd9cec46f878
    Reviewed-on: https://gerrit.libreoffice.org/11025
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/extras/ooxmlimport/data/bnc519228_odd-breaks.docx b/sw/qa/extras/ooxmlimport/data/bnc519228_odd-breaks.docx
new file mode 100644
index 0000000..8711d62
Binary files /dev/null and b/sw/qa/extras/ooxmlimport/data/bnc519228_odd-breaks.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index fb82c8f..9dab8ea 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -52,6 +52,7 @@
 #include <com/sun/star/xml/dom/XDocument.hpp>
 #include <com/sun/star/text/XDocumentIndex.hpp>
 #include <com/sun/star/style/CaseMap.hpp>
+#include <com/sun/star/style/PageStyleLayout.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
 #include <vcl/svapp.hxx>
 #include <unotools/fltrcfg.hxx>
@@ -2233,6 +2234,36 @@ DECLARE_OOXMLIMPORT_TEST(testHidemark, "hidemark.docx")
     CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX, getProperty<sal_Int16>(xTableRows->getByIndex(1), "SizeType"));
 }
 
+DECLARE_OOXMLIMPORT_TEST(testBnc519228OddBreaks, "bnc519228_odd-breaks.docx")
+{
+    // Check that all the normal styles are not set as right-only, those should be only those used after odd page breaks.
+    uno::Reference<beans::XPropertySet> defaultStyle(getStyles("PageStyles")->getByName(DEFAULT_STYLE), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(uno::makeAny(style::PageStyleLayout_ALL), defaultStyle->getPropertyValue("PageStyleLayout"));
+    uno::Reference<beans::XPropertySet> firstPage( getStyles("PageStyles")->getByName("First Page"), uno::UNO_QUERY );
+    CPPUNIT_ASSERT_EQUAL(uno::makeAny(style::PageStyleLayout_ALL), firstPage->getPropertyValue("PageStyleLayout"));
+
+    OUString page1StyleName = getProperty<OUString>( getParagraph( 1, "This is the first page." ), "PageDescName");
+    uno::Reference<beans::XPropertySet> page1Style(getStyles("PageStyles")->getByName(page1StyleName), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(uno::makeAny(style::PageStyleLayout_RIGHT), page1Style->getPropertyValue("PageStyleLayout"));
+    getParagraphOfText( 1, getProperty< uno::Reference<text::XText> >(page1Style, "HeaderText"), "This is the header for odd pages");
+
+    // Page2 comes from follow of style for page 1 and should be a normal page. Also check the two page style have the same properties,
+    // since page style for page1 was created from page style for page 2.
+    OUString page2StyleName = getProperty<OUString>( getParagraph( 3, "This is page 2, which is obviously an even page." ), "PageDescName");
+    CPPUNIT_ASSERT_EQUAL(OUString(), page2StyleName);
+    page2StyleName = getProperty<OUString>( page1Style, "FollowStyle" );
+    uno::Reference<beans::XPropertySet> page2Style(getStyles("PageStyles")->getByName(page2StyleName), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(uno::makeAny(style::PageStyleLayout_ALL), page2Style->getPropertyValue("PageStyleLayout"));
+    getParagraphOfText( 1, getProperty< uno::Reference<text::XText> >(page2Style, "HeaderTextLeft"), "This is the even header");
+    getParagraphOfText( 1, getProperty< uno::Reference<text::XText> >(page2Style, "HeaderTextRight"), "This is the header for odd pages");
+    CPPUNIT_ASSERT_EQUAL(getProperty<sal_Int32>(page1Style, "TopMargin"), getProperty<sal_Int32>(page2Style, "TopMargin"));
+
+    OUString page5StyleName = getProperty<OUString>( getParagraph( 5, "Then an odd break after an odd page, should lead us to page #5." ), "PageDescName");
+    uno::Reference<beans::XPropertySet> page5Style(getStyles("PageStyles")->getByName(page5StyleName), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(uno::makeAny(style::PageStyleLayout_RIGHT), page5Style->getPropertyValue("PageStyleLayout"));
+    getParagraphOfText( 1, getProperty< uno::Reference<text::XText> >(page5Style, "HeaderText"), "This is the header for odd pages");
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index 0b47cad..2512a9d 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -22,6 +22,7 @@
 #include <ConversionHelper.hxx>
 #include <i18nutil/paper.hxx>
 #include <rtl/ustring.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/beans/XMultiPropertySet.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
@@ -31,6 +32,7 @@
 #include <com/sun/star/container/XNameContainer.hpp>
 #include <com/sun/star/style/BreakType.hpp>
 #include <com/sun/star/style/PageStyleLayout.hpp>
+#include <com/sun/star/style/XStyle.hpp>
 #include <com/sun/star/table/ShadowFormat.hpp>
 #include <com/sun/star/text/RelOrientation.hpp>
 #include <com/sun/star/text/WritingMode.hpp>
@@ -713,6 +715,74 @@ bool SectionPropertyMap::HasFooter(bool bFirstPage) const
 
 #define MIN_HEAD_FOOT_HEIGHT 100 //minimum header/footer height
 
+void SectionPropertyMap::CopyHeaderFooter( uno::Reference< beans::XPropertySet > xPrevStyle,
+    uno::Reference< beans::XPropertySet > xStyle )
+{
+    PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
+
+    try {
+        // Loop over the Header and Footer properties to copy them
+        static const PropertyIds aProperties[] =
+        {
+            PROP_HEADER_TEXT,
+            PROP_FOOTER_TEXT,
+        };
+
+        bool bHasPrevHeader = false;
+        bool bHasHeader = false;
+
+        OUString sHeaderIsOn = rPropNameSupplier.GetName( PROP_HEADER_IS_ON );
+        if (xPrevStyle.is())
+            xPrevStyle->getPropertyValue( sHeaderIsOn ) >>= bHasPrevHeader;
+        if (xStyle.is())
+            xStyle->getPropertyValue( sHeaderIsOn ) >>= bHasHeader;
+        bool bCopyHeader = bHasPrevHeader && !bHasHeader;
+
+        if ( bCopyHeader )
+            xStyle->setPropertyValue( sHeaderIsOn, uno::makeAny( sal_True ) );
+
+        bool bHasPrevFooter = false;
+        bool bHasFooter = false;
+
+        OUString sFooterIsOn = rPropNameSupplier.GetName( PROP_FOOTER_IS_ON );
+        if (xPrevStyle.is())
+            xPrevStyle->getPropertyValue( sFooterIsOn ) >>= bHasPrevFooter;
+        if (xStyle.is())
+            xStyle->getPropertyValue( sFooterIsOn ) >>= bHasFooter;
+        bool bCopyFooter = bHasPrevFooter && !bHasFooter;
+
+        if ( bCopyFooter && xStyle.is() )
+            xStyle->setPropertyValue( sFooterIsOn, uno::makeAny( sal_True ) );
+
+        // Copying the text properties
+        for ( int i = 0, nNbProps = 2; i < nNbProps; i++ )
+        {
+            bool bIsHeader = ( i < nNbProps / 2 );
+            PropertyIds aPropId = aProperties[i];
+            OUString sName = rPropNameSupplier.GetName( aPropId );
+
+            if ( ( bIsHeader && bCopyHeader ) || ( !bIsHeader && bCopyFooter ) )
+            {
+                SAL_INFO("writerfilter", "Copying " << sName);
+                // TODO has to be copied
+                uno::Reference< text::XTextCopy > xTxt;
+                if (xStyle.is())
+                    xTxt.set(xStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW );
+
+                uno::Reference< text::XTextCopy > xPrevTxt;
+                if (xPrevStyle.is())
+                    xPrevTxt.set(xPrevStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW );
+
+                xTxt->copyText( xPrevTxt );
+            }
+        }
+    }
+    catch ( const uno::Exception& e )
+    {
+        SAL_INFO("writerfilter", "An exception occurred in SectionPropertyMap::CopyHeaderFooter( ) - " << e.Message);
+    }
+}
+
 void SectionPropertyMap::CopyLastHeaderFooter( bool bFirstPage, DomainMapper_Impl& rDM_Impl )
 {
     SAL_INFO("writerfilter", "START>>> SectionPropertyMap::CopyLastHeaderFooter()");
@@ -727,70 +797,7 @@ void SectionPropertyMap::CopyLastHeaderFooter( bool bFirstPage, DomainMapper_Imp
                 rDM_Impl.GetPageStyles(),
                 rDM_Impl.GetTextFactory(),
                 bFirstPage );
-
-        PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
-
-        try {
-            // Loop over the Header and Footer properties to copy them
-            static const PropertyIds aProperties[] =
-            {
-                PROP_HEADER_TEXT,
-                PROP_FOOTER_TEXT,
-            };
-
-            bool bHasPrevHeader = false;
-            bool bHasHeader = false;
-
-            OUString sHeaderIsOn = rPropNameSupplier.GetName( PROP_HEADER_IS_ON );
-            if (xPrevStyle.is())
-                xPrevStyle->getPropertyValue( sHeaderIsOn ) >>= bHasPrevHeader;
-            if (xStyle.is())
-                xStyle->getPropertyValue( sHeaderIsOn ) >>= bHasHeader;
-            bool bCopyHeader = bHasPrevHeader && !bHasHeader;
-
-            if ( bCopyHeader )
-                xStyle->setPropertyValue( sHeaderIsOn, uno::makeAny( sal_True ) );
-
-            bool bHasPrevFooter = false;
-            bool bHasFooter = false;
-
-            OUString sFooterIsOn = rPropNameSupplier.GetName( PROP_FOOTER_IS_ON );
-            if (xPrevStyle.is())
-                xPrevStyle->getPropertyValue( sFooterIsOn ) >>= bHasPrevFooter;
-            if (xStyle.is())
-                xStyle->getPropertyValue( sFooterIsOn ) >>= bHasFooter;
-            bool bCopyFooter = bHasPrevFooter && !bHasFooter;
-
-            if ( bCopyFooter && xStyle.is() )
-                xStyle->setPropertyValue( sFooterIsOn, uno::makeAny( sal_True ) );
-
-            // Copying the text properties
-            for ( int i = 0, nNbProps = 2; i < nNbProps; i++ )
-            {
-                bool bIsHeader = ( i < nNbProps / 2 );
-                PropertyIds aPropId = aProperties[i];
-                OUString sName = rPropNameSupplier.GetName( aPropId );
-
-                if ( ( bIsHeader && bCopyHeader ) || ( !bIsHeader && bCopyFooter ) )
-                {
-                    SAL_INFO("writerfilter", "Copying " << sName);
-                    // TODO has to be copied
-                    uno::Reference< text::XTextCopy > xTxt;
-                    if (xStyle.is())
-                        xTxt.set(xStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW );
-
-                    uno::Reference< text::XTextCopy > xPrevTxt;
-                    if (xPrevStyle.is())
-                        xPrevTxt.set(xPrevStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW );
-
-                    xTxt->copyText( xPrevTxt );
-                }
-            }
-        }
-        catch ( const uno::Exception& e )
-        {
-            SAL_INFO("writerfilter", "An exception occurred in SectionPropertyMap::CopyLastHeaderFooter( ) - " << e.Message);
-        }
+        CopyHeaderFooter( xPrevStyle, xStyle );
     }
     SAL_INFO("writerfilter", "END>>> SectionPropertyMap::CopyLastHeaderFooter()");
 }
@@ -963,7 +970,8 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
         }
     }
 
-    //depending on the break type no page styles should be created
+    // break type : 0 - No break 1 - New Column 2 - New page 3 - Even page 4 - odd page
+    // depending on the break type no page styles should be created
     // If the section type is missing, but we have columns, then this should be
     // handled as a continuous section break.
     if(m_nBreakType == 0 || (m_nBreakType == -1 && m_nColumnCount > 0))
@@ -1138,22 +1146,44 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
             {
                 //now apply this break at the first paragraph of this section
                 uno::Reference<beans::XPropertySet> xRangeProperties(lcl_GetRangeProperties(m_bIsFirstSection, rDM_Impl, m_xStartingRange));
-            /* break type
-            0 - No break 1 - New Column 2 - New page 3 - Even page 4 - odd page */
+
+                // Handle page breaks with odd/even page numbering. We need to use an extra page style for setting the page style
+                // to left/right, because if we set it to the normal style, we'd set it to "First Page"/"Default Style", which would
+                // break them (all default pages would be only left or right).
+                if (m_nBreakType == 3 || m_nBreakType == 4)
+                {
+                    OUString* pageStyle = m_bTitlePage ? &m_sFirstPageStyleName : &m_sFollowPageStyleName;
+                    OUString evenOddStyleName = lcl_FindUnusedPageStyleName(rDM_Impl.GetPageStyles()->getElementNames());
+                    uno::Reference< beans::XPropertySet > evenOddStyle(
+                            rDM_Impl.GetTextFactory()->createInstance("com.sun.star.style.PageStyle"),
+                            uno::UNO_QUERY);
+                    // Unfortunately using setParent() does not work for page styles, so make a deep copy of the page style.
+                    uno::Reference< beans::XPropertySet > pageProperties( m_bTitlePage ? m_aFirstPageStyle : m_aFollowPageStyle );
+                    uno::Reference< beans::XPropertySetInfo > pagePropertiesInfo( pageProperties->getPropertySetInfo());
+                    uno::Sequence< beans::Property > propertyList( pagePropertiesInfo->getProperties());
+                    for( int i = 0; i < propertyList.getLength(); ++i )
+                    {
+                        if(( propertyList[i].Attributes & beans::PropertyAttribute::READONLY ) == 0 )
+                            evenOddStyle->setPropertyValue( propertyList[ i ].Name, pageProperties->getPropertyValue( propertyList[ i ].Name ));
+                    }
+                    evenOddStyle->setPropertyValue("FollowStyle", uno::makeAny(*pageStyle));
+                    rDM_Impl.GetPageStyles()->insertByName( evenOddStyleName, uno::makeAny( evenOddStyle ) );
+                    evenOddStyle->setPropertyValue("HeaderIsOn", uno::makeAny(sal_False));
+                    evenOddStyle->setPropertyValue("FooterIsOn", uno::makeAny(sal_False));
+                    CopyHeaderFooter( pageProperties, evenOddStyle );
+                    *pageStyle = evenOddStyleName; // And use it instead of the original one (which is set as follow of this one).
+                    if (m_nBreakType == 3)
+                        evenOddStyle->setPropertyValue(rPropNameSupplier.GetName(PROP_PAGE_STYLE_LAYOUT), uno::makeAny(style::PageStyleLayout_LEFT));
+                    else if (m_nBreakType == 4)
+                        evenOddStyle->setPropertyValue(rPropNameSupplier.GetName(PROP_PAGE_STYLE_LAYOUT), uno::makeAny(style::PageStyleLayout_RIGHT));
+                }
+
                 if (xRangeProperties.is() && rDM_Impl.IsNewDoc())
                     xRangeProperties->setPropertyValue(
                         rPropNameSupplier.GetName( PROP_PAGE_DESC_NAME ),
                         uno::makeAny( m_bTitlePage ?  m_sFirstPageStyleName
                                       : m_sFollowPageStyleName ));
 
-                // handle page breaks with odd/even page numbering
-                style::PageStyleLayout nPageStyleLayout(style::PageStyleLayout_ALL);
-                if (m_nBreakType == 3)
-                    nPageStyleLayout = style::PageStyleLayout_LEFT;
-                else if (m_nBreakType == 4)
-                    nPageStyleLayout = style::PageStyleLayout_RIGHT;
-                if (nPageStyleLayout)
-                    xFollowPageStyle->setPropertyValue(rPropNameSupplier.GetName(PROP_PAGE_STYLE_LAYOUT), uno::makeAny(nPageStyleLayout));
                 if(m_bPageNoRestart || m_nPageNumber >= 0)
                 {
                     sal_Int16 nPageNumber = m_nPageNumber >= 0 ? static_cast< sal_Int16 >(m_nPageNumber) : 1;
diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx
index ccfb897..5c12df2 100644
--- a/writerfilter/source/dmapper/PropertyMap.hxx
+++ b/writerfilter/source/dmapper/PropertyMap.hxx
@@ -205,6 +205,8 @@ class SectionPropertyMap : public PropertyMap
     ::com::sun::star::uno::Reference< com::sun::star::text::XTextColumns > ApplyColumnProperties(
             ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xFollowPageStyle );
     void CopyLastHeaderFooter( bool bFirstPage, DomainMapper_Impl& rDM_Impl );
+    void CopyHeaderFooter( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPrevStyle,
+        ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xStyle );
     void PrepareHeaderFooterProperties( bool bFirstPage );
     bool HasHeader( bool bFirstPage ) const;
     bool HasFooter( bool bFirstPage ) const;


More information about the Libreoffice-commits mailing list