[Libreoffice-commits] core.git: 4 commits - include/sfx2 sfx2/source sw/source

Miklos Vajna vmiklos at collabora.co.uk
Wed Feb 24 17:02:50 UTC 2016


 include/sfx2/classificationhelper.hxx     |    6 
 sfx2/source/view/classificationhelper.cxx |   37 +++-
 sw/source/core/edit/edfcol.cxx            |  246 +++++++++++++++++++++++++++---
 3 files changed, 263 insertions(+), 26 deletions(-)

New commits:
commit 9cf13c9f07311731757127ba50bd3f2eb0d22272
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Feb 24 17:11:51 2016 +0100

    sw classification: don't insert multiple watermark objects in header
    
    If the text is different, remove the old shape and then insert the new
    one. Otherwise just don't insert a new (identical) shape.
    
    Delete and insert is needed because the shape size depends on its
    textural content.
    
    Change-Id: I0c8faa0e3e69416ea0b89fa33155826bc2dc7a4f

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 14ef654..9acb496 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -20,6 +20,7 @@
 #include <editsh.hxx>
 
 #include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
 #include <com/sun/star/document/XActionLockable.hpp>
 #include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
@@ -112,6 +113,47 @@ bool lcl_hasField(const uno::Reference<text::XText>& xText, const OUString& rSer
     return false;
 }
 
+/// Search for a frame named rShapeName of type rServiceName in xText.
+uno::Reference<drawing::XShape> lcl_getWatermark(const uno::Reference<text::XText>& xText, const OUString& rServiceName, const OUString& rShapeName)
+{
+    uno::Reference<container::XEnumerationAccess> xParagraphEnumerationAccess(xText, uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParagraphs = xParagraphEnumerationAccess->createEnumeration();
+    while (xParagraphs->hasMoreElements())
+    {
+        uno::Reference<container::XEnumerationAccess> xTextPortionEnumerationAccess(xParagraphs->nextElement(), uno::UNO_QUERY);
+        uno::Reference<container::XEnumeration> xTextPortions = xTextPortionEnumerationAccess->createEnumeration();
+        while (xTextPortions->hasMoreElements())
+        {
+            uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
+            OUString aTextPortionType;
+            xTextPortion->getPropertyValue(UNO_NAME_TEXT_PORTION_TYPE) >>= aTextPortionType;
+            if (aTextPortionType != "Frame")
+                continue;
+
+            uno::Reference<container::XContentEnumerationAccess> xContentEnumerationAccess(xTextPortion, uno::UNO_QUERY);
+            if (!xContentEnumerationAccess.is())
+                continue;
+
+            uno::Reference<container::XEnumeration> xEnumeration = xContentEnumerationAccess->createContentEnumeration("com.sun.star.text.TextContent");
+            if (!xEnumeration->hasMoreElements())
+                continue;
+
+            uno::Reference<lang::XServiceInfo> xWatermark(xEnumeration->nextElement(), uno::UNO_QUERY);
+            if (!xWatermark->supportsService(rServiceName))
+                continue;
+
+            uno::Reference<container::XNamed> xNamed(xWatermark, uno::UNO_QUERY);
+            if (xNamed->getName() != rShapeName)
+                continue;
+
+            uno::Reference<drawing::XShape> xShape(xWatermark, uno::UNO_QUERY);
+            return xShape;
+        }
+    }
+
+    return uno::Reference<drawing::XShape>();
+}
+
 } // anonymous namespace
 
 SwTextFormatColl& SwEditShell::GetDfltTextFormatColl() const
@@ -184,103 +226,122 @@ void SwEditShell::SetClassification(const OUString& rName)
 
             if (!aWatermark.isEmpty())
             {
-                // Calc the ratio.
-                double fRatio = 0;
-                OutputDevice* pOut = Application::GetDefaultDevice();
-                vcl::Font aFont(pOut->GetFont());
-                fRatio = aFont.GetFontSize().Height();
-                fRatio /= pOut->GetTextWidth(aWatermark);
-
-                // Calc the size.
-                sal_Int32 nWidth = 0;
-                awt::Size aSize;
-                xPageStyle->getPropertyValue(UNO_NAME_SIZE) >>= aSize;
-                if (aSize.Width < aSize.Height)
+                OUString aShapeServiceName = "com.sun.star.drawing.CustomShape";
+                uno::Reference<drawing::XShape> xWatermark = lcl_getWatermark(xHeaderText, aShapeServiceName, SfxClassificationHelper::PROP_DOCWATERMARK());
+
+                if (xWatermark.is())
                 {
-                    // Portrait.
-                    sal_Int32 nLeftMargin = 0;
-                    xPageStyle->getPropertyValue(UNO_NAME_LEFT_MARGIN) >>= nLeftMargin;
-                    sal_Int32 nRightMargin = 0;
-                    xPageStyle->getPropertyValue(UNO_NAME_RIGHT_MARGIN) >>= nRightMargin;
-                    nWidth = aSize.Width - nLeftMargin - nRightMargin;
+                    // If the header already contains a watermark, see if it its text is up to date.
+                    uno::Reference<text::XTextRange> xTextRange(xWatermark, uno::UNO_QUERY);
+                    if (xTextRange->getString() != aWatermark)
+                    {
+                        // No: delete it and we'll insert a replacement.
+                        uno::Reference<lang::XComponent> xComponent(xWatermark, uno::UNO_QUERY);
+                        xComponent->dispose();
+                        xWatermark.clear();
+                    }
                 }
-                else
+
+                if (!xWatermark.is())
                 {
-                    // Landscape.
-                    sal_Int32 nTopMargin = 0;
-                    xPageStyle->getPropertyValue(UNO_NAME_TOP_MARGIN) >>= nTopMargin;
-                    sal_Int32 nBottomMargin = 0;
-                    xPageStyle->getPropertyValue(UNO_NAME_BOTTOM_MARGIN) >>= nBottomMargin;
-                    nWidth = aSize.Height - nTopMargin - nBottomMargin;
+                    // Calc the ratio.
+                    double fRatio = 0;
+                    OutputDevice* pOut = Application::GetDefaultDevice();
+                    vcl::Font aFont(pOut->GetFont());
+                    fRatio = aFont.GetFontSize().Height();
+                    fRatio /= pOut->GetTextWidth(aWatermark);
+
+                    // Calc the size.
+                    sal_Int32 nWidth = 0;
+                    awt::Size aSize;
+                    xPageStyle->getPropertyValue(UNO_NAME_SIZE) >>= aSize;
+                    if (aSize.Width < aSize.Height)
+                    {
+                        // Portrait.
+                        sal_Int32 nLeftMargin = 0;
+                        xPageStyle->getPropertyValue(UNO_NAME_LEFT_MARGIN) >>= nLeftMargin;
+                        sal_Int32 nRightMargin = 0;
+                        xPageStyle->getPropertyValue(UNO_NAME_RIGHT_MARGIN) >>= nRightMargin;
+                        nWidth = aSize.Width - nLeftMargin - nRightMargin;
+                    }
+                    else
+                    {
+                        // Landscape.
+                        sal_Int32 nTopMargin = 0;
+                        xPageStyle->getPropertyValue(UNO_NAME_TOP_MARGIN) >>= nTopMargin;
+                        sal_Int32 nBottomMargin = 0;
+                        xPageStyle->getPropertyValue(UNO_NAME_BOTTOM_MARGIN) >>= nBottomMargin;
+                        nWidth = aSize.Height - nTopMargin - nBottomMargin;
+                    }
+                    sal_Int32 nHeight = nWidth * fRatio;
+
+                    // Create and insert the shape.
+                    uno::Reference<drawing::XShape> xShape(xMultiServiceFactory->createInstance(aShapeServiceName), uno::UNO_QUERY);
+                    basegfx::B2DHomMatrix aTransformation;
+                    aTransformation.identity();
+                    aTransformation.scale(nWidth, nHeight);
+                    aTransformation.rotate(F_PI180 * -45);
+                    drawing::HomogenMatrix3 aMatrix;
+                    aMatrix.Line1.Column1 = aTransformation.get(0, 0);
+                    aMatrix.Line1.Column2 = aTransformation.get(0, 1);
+                    aMatrix.Line1.Column3 = aTransformation.get(0, 2);
+                    aMatrix.Line2.Column1 = aTransformation.get(1, 0);
+                    aMatrix.Line2.Column2 = aTransformation.get(1, 1);
+                    aMatrix.Line2.Column3 = aTransformation.get(1, 2);
+                    aMatrix.Line3.Column1 = aTransformation.get(2, 0);
+                    aMatrix.Line3.Column2 = aTransformation.get(2, 1);
+                    aMatrix.Line3.Column3 = aTransformation.get(2, 2);
+                    uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+                    xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
+                    uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY);
+                    xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, false);
+
+                    // The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering.
+                    uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY);
+                    xLockable->addActionLock();
+                    xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(0xc0c0c0)));
+                    xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::makeAny(drawing::FillStyle_SOLID));
+                    xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(static_cast<sal_Int16>(50)));
+                    xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA)));
+                    xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::makeAny(drawing::LineStyle_NONE));
+                    xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::makeAny(false));
+                    xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny(false));
+                    xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny(false));
+                    xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::makeAny(nHeight));
+                    xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::makeAny(nWidth));
+                    xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::makeAny(text::WrapTextMode_THROUGHT));
+                    xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA)));
+                    xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(OUString("Liberation Sans")));
+                    xPropertySet->setPropertyValue("Transformation", uno::makeAny(aMatrix));
+                    xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::HoriOrientation::CENTER)));
+                    xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::VertOrientation::CENTER)));
+
+                    uno::Reference<text::XTextRange> xTextRange(xShape, uno::UNO_QUERY);
+                    xTextRange->setString(aWatermark);
+
+                    uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
+                    xDefaulter->createCustomShapeDefaults("fontwork-plain-text");
+
+                    auto aGeomPropSeq = xPropertySet->getPropertyValue("CustomShapeGeometry").get< uno::Sequence<beans::PropertyValue> >();
+                    auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq);
+                    uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+                    {
+                        {"TextPath", uno::makeAny(true)},
+                    }));
+                    auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue)
+                    {
+                        return rValue.Name == "TextPath";
+                    });
+                    if (it == aGeomPropVec.end())
+                        aGeomPropVec.push_back(comphelper::makePropertyValue("TextPath", aPropertyValues));
+                    else
+                        it->Value <<= aPropertyValues;
+                    xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
+
+                    uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
+                    xNamed->setName(SfxClassificationHelper::PROP_DOCWATERMARK());
+                    xLockable->removeActionLock();
                 }
-                sal_Int32 nHeight = nWidth * fRatio;
-
-                // Create and insert the shape.
-                uno::Reference<drawing::XShape> xShape(xMultiServiceFactory->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY);
-                basegfx::B2DHomMatrix aTransformation;
-                aTransformation.identity();
-                aTransformation.scale(nWidth, nHeight);
-                aTransformation.rotate(F_PI180 * -45);
-                drawing::HomogenMatrix3 aMatrix;
-                aMatrix.Line1.Column1 = aTransformation.get(0, 0);
-                aMatrix.Line1.Column2 = aTransformation.get(0, 1);
-                aMatrix.Line1.Column3 = aTransformation.get(0, 2);
-                aMatrix.Line2.Column1 = aTransformation.get(1, 0);
-                aMatrix.Line2.Column2 = aTransformation.get(1, 1);
-                aMatrix.Line2.Column3 = aTransformation.get(1, 2);
-                aMatrix.Line3.Column1 = aTransformation.get(2, 0);
-                aMatrix.Line3.Column2 = aTransformation.get(2, 1);
-                aMatrix.Line3.Column3 = aTransformation.get(2, 2);
-                uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
-                xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
-                uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY);
-                xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, false);
-
-                // The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering.
-                uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY);
-                xLockable->addActionLock();
-                xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(0xc0c0c0)));
-                xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::makeAny(drawing::FillStyle_SOLID));
-                xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(static_cast<sal_Int16>(50)));
-                xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA)));
-                xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::makeAny(drawing::LineStyle_NONE));
-                xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::makeAny(false));
-                xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny(false));
-                xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny(false));
-                xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::makeAny(nHeight));
-                xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::makeAny(nWidth));
-                xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::makeAny(text::WrapTextMode_THROUGHT));
-                xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA)));
-                xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(OUString("Liberation Sans")));
-                xPropertySet->setPropertyValue("Transformation", uno::makeAny(aMatrix));
-                xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::HoriOrientation::CENTER)));
-                xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::VertOrientation::CENTER)));
-
-                uno::Reference<text::XTextRange> xTextRange(xShape, uno::UNO_QUERY);
-                xTextRange->setString(aWatermark);
-
-                uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
-                xDefaulter->createCustomShapeDefaults("fontwork-plain-text");
-
-                auto aGeomPropSeq = xPropertySet->getPropertyValue("CustomShapeGeometry").get< uno::Sequence<beans::PropertyValue> >();
-                auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq);
-                uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
-                {
-                    {"TextPath", uno::makeAny(true)},
-                }));
-                auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue)
-                {
-                    return rValue.Name == "TextPath";
-                });
-                if (it == aGeomPropVec.end())
-                    aGeomPropVec.push_back(comphelper::makePropertyValue("TextPath", aPropertyValues));
-                else
-                    it->Value <<= aPropertyValues;
-                xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
-
-                uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
-                xNamed->setName(SfxClassificationHelper::PROP_DOCWATERMARK());
-                xLockable->removeActionLock();
             }
         }
 
commit bff9f2d469736d20261ba8ff488dd98452e3fe88
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Feb 24 16:45:01 2016 +0100

    sw classification: name watermark objects, so later it's possible to find them
    
    Given that they are not fields, it's necessary to re-create them every
    time their textural content would change.
    
    Change-Id: I1276ef686b1b622dccaa8ac4996af8e4cb4de329

diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx
index 1f37cb7..c84f7ce 100644
--- a/include/sfx2/classificationhelper.hxx
+++ b/include/sfx2/classificationhelper.hxx
@@ -51,6 +51,8 @@ public:
     static const OUString& PROP_DOCHEADER();
     /// Brief text located at the bottom of each document's pages.
     static const OUString& PROP_DOCFOOTER();
+    /// Brief text formatted as a watermark on each document's page.
+    static const OUString& PROP_DOCWATERMARK();
 };
 
 #endif
diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx
index d2e123d..3ff9047 100644
--- a/sfx2/source/view/classificationhelper.cxx
+++ b/sfx2/source/view/classificationhelper.cxx
@@ -165,7 +165,7 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:4"].clear();
             rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCHEADER()].clear();
             rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()].clear();
-            rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"].clear();
+            rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCWATERMARK()].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-first-line-of-text"].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-last-line-of-text"].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-subject-prefix"].clear();
@@ -239,7 +239,7 @@ void SAL_CALL SfxClassificationParser::endElement(const OUString& rName) throw (
             else if (m_aIdentifier == "Document: Footer")
                 m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()] = m_aValue;
             else if (m_aIdentifier == "Document: Watermark")
-                m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"] = m_aValue;
+                m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCWATERMARK()] = m_aValue;
         }
     }
 }
@@ -486,7 +486,7 @@ basegfx::BColor SfxClassificationHelper::GetImpactLevelColor()
 
 OUString SfxClassificationHelper::GetDocumentWatermark()
 {
-    std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find("urn:bails:IntellectualProperty:Marking:document-watermark");
+    std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find(SfxClassificationHelper::PROP_DOCWATERMARK());
     if (it != m_pImpl->m_aLabels.end())
         return it->second;
 
@@ -542,4 +542,10 @@ const OUString& SfxClassificationHelper::PROP_DOCFOOTER()
     return sProp;
 }
 
+const OUString& SfxClassificationHelper::PROP_DOCWATERMARK()
+{
+    static OUString sProp("urn:bails:IntellectualProperty:Marking:document-watermark");
+    return sProp;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 62403d8..14ef654 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -277,6 +277,9 @@ void SwEditShell::SetClassification(const OUString& rName)
                 else
                     it->Value <<= aPropertyValues;
                 xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
+
+                uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
+                xNamed->setName(SfxClassificationHelper::PROP_DOCWATERMARK());
                 xLockable->removeActionLock();
             }
         }
commit cc3d29dc412902ea8d6a85426ba72b77166a8c95
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Feb 24 16:15:54 2016 +0100

    sw classification: put watermark shape to the header if policy wants so
    
    Change-Id: Ib22b2066bb3f4059425b8c71b5fc737e160aef0b

diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 43a1390..62403d8 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -19,13 +19,29 @@
 
 #include <editsh.hxx>
 
-#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/document/XActionLockable.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
-
-#include <hintids.hxx>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
 #include <editeng/formatbreakitem.hxx>
+#include <editeng/unoprnms.hxx>
 #include <sfx2/classificationhelper.hxx>
+#include <vcl/svapp.hxx>
+
+#include <hintids.hxx>
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
 #include <edimp.hxx>
@@ -125,35 +141,40 @@ void SwEditShell::SetClassification(const OUString& rName)
 
     bool bHeaderIsNeeded = aHelper.HasDocumentHeader();
     bool bFooterIsNeeded = aHelper.HasDocumentFooter();
+    OUString aWatermark = aHelper.GetDocumentWatermark();
 
-    if (bHeaderIsNeeded || bFooterIsNeeded)
+    if (!bHeaderIsNeeded && !bFooterIsNeeded && aWatermark.isEmpty())
+        return;
+
+    uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
+    uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY);
+    uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY);
+    uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY);
+
+    std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this);
+    for (const OUString& rPageStyleName : aUsedPageStyles)
     {
-        uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
-        uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY);
-        uno::Reference<container::XNameAccess> xStyleFamilies(xStyleFamiliesSupplier->getStyleFamilies(), uno::UNO_QUERY);
-        uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
+        OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom";
+        uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
 
-        std::set<OUString> aUsedPageStyles = lcl_getUsedPageStyles(this);
-        for (const OUString& rPageStyleName : aUsedPageStyles)
+        if (bHeaderIsNeeded || !aWatermark.isEmpty())
         {
-            uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
-            OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom";
+            // If the header is off, turn it on.
+            bool bHeaderIsOn = false;
+            xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn;
+            if (!bHeaderIsOn)
+                xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true));
+
+            // If the header already contains a document header field, no need to do anything.
+            uno::Reference<text::XText> xHeaderText;
+            xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
 
             if (bHeaderIsNeeded)
             {
-                // If the header is off, turn it on.
-                bool bHeaderIsOn = false;
-                xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn;
-                if (!bHeaderIsOn)
-                    xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true));
-
-                // If the header already contains a document header field, no need to do anything.
-                uno::Reference<text::XText> xHeaderText;
-                xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
                 if (!lcl_hasField(xHeaderText, aServiceName, SfxClassificationHelper::PROP_DOCHEADER()))
                 {
                     // Append a field to the end of the header text.
-                    uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
                     uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY);
                     xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCHEADER()));
                     uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
@@ -161,26 +182,123 @@ void SwEditShell::SetClassification(const OUString& rName)
                 }
             }
 
-            if (bFooterIsNeeded)
+            if (!aWatermark.isEmpty())
             {
-                // If the footer is off, turn it on.
-                bool bFooterIsOn = false;
-                xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn;
-                if (!bFooterIsOn)
-                    xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true));
-
-                // If the footer already contains a document header field, no need to do anything.
-                uno::Reference<text::XText> xFooterText;
-                xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText;
-                if (!lcl_hasField(xFooterText, aServiceName, SfxClassificationHelper::PROP_DOCFOOTER()))
+                // Calc the ratio.
+                double fRatio = 0;
+                OutputDevice* pOut = Application::GetDefaultDevice();
+                vcl::Font aFont(pOut->GetFont());
+                fRatio = aFont.GetFontSize().Height();
+                fRatio /= pOut->GetTextWidth(aWatermark);
+
+                // Calc the size.
+                sal_Int32 nWidth = 0;
+                awt::Size aSize;
+                xPageStyle->getPropertyValue(UNO_NAME_SIZE) >>= aSize;
+                if (aSize.Width < aSize.Height)
                 {
-                    // Append a field to the end of the footer text.
-                    uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
-                    uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY);
-                    xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCFOOTER()));
-                    uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
-                    xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false);
+                    // Portrait.
+                    sal_Int32 nLeftMargin = 0;
+                    xPageStyle->getPropertyValue(UNO_NAME_LEFT_MARGIN) >>= nLeftMargin;
+                    sal_Int32 nRightMargin = 0;
+                    xPageStyle->getPropertyValue(UNO_NAME_RIGHT_MARGIN) >>= nRightMargin;
+                    nWidth = aSize.Width - nLeftMargin - nRightMargin;
+                }
+                else
+                {
+                    // Landscape.
+                    sal_Int32 nTopMargin = 0;
+                    xPageStyle->getPropertyValue(UNO_NAME_TOP_MARGIN) >>= nTopMargin;
+                    sal_Int32 nBottomMargin = 0;
+                    xPageStyle->getPropertyValue(UNO_NAME_BOTTOM_MARGIN) >>= nBottomMargin;
+                    nWidth = aSize.Height - nTopMargin - nBottomMargin;
                 }
+                sal_Int32 nHeight = nWidth * fRatio;
+
+                // Create and insert the shape.
+                uno::Reference<drawing::XShape> xShape(xMultiServiceFactory->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY);
+                basegfx::B2DHomMatrix aTransformation;
+                aTransformation.identity();
+                aTransformation.scale(nWidth, nHeight);
+                aTransformation.rotate(F_PI180 * -45);
+                drawing::HomogenMatrix3 aMatrix;
+                aMatrix.Line1.Column1 = aTransformation.get(0, 0);
+                aMatrix.Line1.Column2 = aTransformation.get(0, 1);
+                aMatrix.Line1.Column3 = aTransformation.get(0, 2);
+                aMatrix.Line2.Column1 = aTransformation.get(1, 0);
+                aMatrix.Line2.Column2 = aTransformation.get(1, 1);
+                aMatrix.Line2.Column3 = aTransformation.get(1, 2);
+                aMatrix.Line3.Column1 = aTransformation.get(2, 0);
+                aMatrix.Line3.Column2 = aTransformation.get(2, 1);
+                aMatrix.Line3.Column3 = aTransformation.get(2, 2);
+                uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+                xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
+                uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY);
+                xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, false);
+
+                // The remaining properties have to be set after the shape is inserted: do that in one batch to avoid flickering.
+                uno::Reference<document::XActionLockable> xLockable(xShape, uno::UNO_QUERY);
+                xLockable->addActionLock();
+                xPropertySet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::makeAny(static_cast<sal_Int32>(0xc0c0c0)));
+                xPropertySet->setPropertyValue(UNO_NAME_FILLSTYLE, uno::makeAny(drawing::FillStyle_SOLID));
+                xPropertySet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, uno::makeAny(static_cast<sal_Int16>(50)));
+                xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA)));
+                xPropertySet->setPropertyValue(UNO_NAME_LINESTYLE, uno::makeAny(drawing::LineStyle_NONE));
+                xPropertySet->setPropertyValue(UNO_NAME_OPAQUE, uno::makeAny(false));
+                xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny(false));
+                xPropertySet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny(false));
+                xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEHEIGHT, uno::makeAny(nHeight));
+                xPropertySet->setPropertyValue(UNO_NAME_TEXT_MINFRAMEWIDTH, uno::makeAny(nWidth));
+                xPropertySet->setPropertyValue(UNO_NAME_TEXT_WRAP, uno::makeAny(text::WrapTextMode_THROUGHT));
+                xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION, uno::makeAny(static_cast<sal_Int16>(text::RelOrientation::PAGE_PRINT_AREA)));
+                xPropertySet->setPropertyValue(UNO_NAME_CHAR_FONT_NAME, uno::makeAny(OUString("Liberation Sans")));
+                xPropertySet->setPropertyValue("Transformation", uno::makeAny(aMatrix));
+                xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::HoriOrientation::CENTER)));
+                xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT, uno::makeAny(static_cast<sal_Int16>(text::VertOrientation::CENTER)));
+
+                uno::Reference<text::XTextRange> xTextRange(xShape, uno::UNO_QUERY);
+                xTextRange->setString(aWatermark);
+
+                uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
+                xDefaulter->createCustomShapeDefaults("fontwork-plain-text");
+
+                auto aGeomPropSeq = xPropertySet->getPropertyValue("CustomShapeGeometry").get< uno::Sequence<beans::PropertyValue> >();
+                auto aGeomPropVec = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aGeomPropSeq);
+                uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+                {
+                    {"TextPath", uno::makeAny(true)},
+                }));
+                auto it = std::find_if(aGeomPropVec.begin(), aGeomPropVec.end(), [](const beans::PropertyValue& rValue)
+                {
+                    return rValue.Name == "TextPath";
+                });
+                if (it == aGeomPropVec.end())
+                    aGeomPropVec.push_back(comphelper::makePropertyValue("TextPath", aPropertyValues));
+                else
+                    it->Value <<= aPropertyValues;
+                xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
+                xLockable->removeActionLock();
+            }
+        }
+
+        if (bFooterIsNeeded)
+        {
+            // If the footer is off, turn it on.
+            bool bFooterIsOn = false;
+            xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn;
+            if (!bFooterIsOn)
+                xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true));
+
+            // If the footer already contains a document header field, no need to do anything.
+            uno::Reference<text::XText> xFooterText;
+            xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText;
+            if (!lcl_hasField(xFooterText, aServiceName, SfxClassificationHelper::PROP_DOCFOOTER()))
+            {
+                // Append a field to the end of the footer text.
+                uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY);
+                xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCFOOTER()));
+                uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
+                xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false);
             }
         }
     }
commit fa72b6e97c5c60eae4a97541cde150ee0d8c0443
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Feb 24 14:25:19 2016 +0100

    sw classification: put the relevant field to the footer if policy wants so
    
    Change-Id: I61c235660366ec1aba137097600605aae76c39a7

diff --git a/include/sfx2/classificationhelper.hxx b/include/sfx2/classificationhelper.hxx
index 0e279c7..1f37cb7 100644
--- a/include/sfx2/classificationhelper.hxx
+++ b/include/sfx2/classificationhelper.hxx
@@ -43,10 +43,14 @@ public:
     OUString GetDocumentWatermark();
     /// The selected category has some content for the document header.
     bool HasDocumentHeader();
+    /// The selected category has some content for the document footer.
+    bool HasDocumentFooter();
     void UpdateInfobar(SfxViewFrame& rViewFrame);
 
     /// Brief text located at the top of each document's pages.
     static const OUString& PROP_DOCHEADER();
+    /// Brief text located at the bottom of each document's pages.
+    static const OUString& PROP_DOCFOOTER();
 };
 
 #endif
diff --git a/sfx2/source/view/classificationhelper.cxx b/sfx2/source/view/classificationhelper.cxx
index 5680e1a..d2e123d 100644
--- a/sfx2/source/view/classificationhelper.cxx
+++ b/sfx2/source/view/classificationhelper.cxx
@@ -163,8 +163,8 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:2"].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:3"].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:general-distribution-statement:ext:4"].clear();
-            rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-footer"].clear();
-            rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-header"].clear();
+            rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCHEADER()].clear();
+            rCategory.m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-first-line-of-text"].clear();
             rCategory.m_aLabels["urn:bails:IntellectualProperty:Marking:email-last-line-of-text"].clear();
@@ -235,9 +235,9 @@ void SAL_CALL SfxClassificationParser::endElement(const OUString& rName) throw (
         if (m_pCategory)
         {
             if (m_aIdentifier == "Document: Header")
-                m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-header"] = m_aValue;
+                m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCHEADER()] = m_aValue;
             else if (m_aIdentifier == "Document: Footer")
-                m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-footer"] = m_aValue;
+                m_pCategory->m_aLabels[SfxClassificationHelper::PROP_DOCFOOTER()] = m_aValue;
             else if (m_aIdentifier == "Document: Watermark")
                 m_pCategory->m_aLabels["urn:bails:IntellectualProperty:Marking:document-watermark"] = m_aValue;
         }
@@ -418,7 +418,16 @@ bool SfxClassificationHelper::HasImpactLevel()
 
 bool SfxClassificationHelper::HasDocumentHeader()
 {
-    std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find("urn:bails:IntellectualProperty:Marking:document-header");
+    std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find(SfxClassificationHelper::PROP_DOCHEADER());
+    if (it == m_pImpl->m_aLabels.end() || it->second.isEmpty())
+        return false;
+
+    return true;
+}
+
+bool SfxClassificationHelper::HasDocumentFooter()
+{
+    std::map<OUString, OUString>::iterator it = m_pImpl->m_aLabels.find(SfxClassificationHelper::PROP_DOCFOOTER());
     if (it == m_pImpl->m_aLabels.end() || it->second.isEmpty())
         return false;
 
@@ -527,4 +536,10 @@ const OUString& SfxClassificationHelper::PROP_DOCHEADER()
     return sProp;
 }
 
+const OUString& SfxClassificationHelper::PROP_DOCFOOTER()
+{
+    static OUString sProp("urn:bails:IntellectualProperty:Marking:document-footer");
+    return sProp;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index cb8124c..43a1390 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -123,7 +123,10 @@ void SwEditShell::SetClassification(const OUString& rName)
     // This updates the infobar as well.
     aHelper.SetBACName(rName);
 
-    if (aHelper.HasDocumentHeader())
+    bool bHeaderIsNeeded = aHelper.HasDocumentHeader();
+    bool bFooterIsNeeded = aHelper.HasDocumentFooter();
+
+    if (bHeaderIsNeeded || bFooterIsNeeded)
     {
         uno::Reference<frame::XModel> xModel = pDocShell->GetBaseModel();
         uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, uno::UNO_QUERY);
@@ -134,25 +137,50 @@ void SwEditShell::SetClassification(const OUString& rName)
         for (const OUString& rPageStyleName : aUsedPageStyles)
         {
             uno::Reference<beans::XPropertySet> xPageStyle(xStyleFamily->getByName(rPageStyleName), uno::UNO_QUERY);
+            OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom";
 
-            // If the header is off, turn it on.
-            bool bHeaderIsOn = false;
-            xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn;
-            if (!bHeaderIsOn)
-                xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true));
+            if (bHeaderIsNeeded)
+            {
+                // If the header is off, turn it on.
+                bool bHeaderIsOn = false;
+                xPageStyle->getPropertyValue(UNO_NAME_HEADER_IS_ON) >>= bHeaderIsOn;
+                if (!bHeaderIsOn)
+                    xPageStyle->setPropertyValue(UNO_NAME_HEADER_IS_ON, uno::makeAny(true));
+
+                // If the header already contains a document header field, no need to do anything.
+                uno::Reference<text::XText> xHeaderText;
+                xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
+                if (!lcl_hasField(xHeaderText, aServiceName, SfxClassificationHelper::PROP_DOCHEADER()))
+                {
+                    // Append a field to the end of the header text.
+                    uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
+                    uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY);
+                    xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCHEADER()));
+                    uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
+                    xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, /*bAbsorb=*/false);
+                }
+            }
 
-            // If the header already contains a document header field, no need to do anything.
-            uno::Reference<text::XText> xHeaderText;
-            xPageStyle->getPropertyValue(UNO_NAME_HEADER_TEXT) >>= xHeaderText;
-            OUString aServiceName = "com.sun.star.text.TextField.DocInfo.Custom";
-            if (!lcl_hasField(xHeaderText, aServiceName, SfxClassificationHelper::PROP_DOCHEADER()))
+            if (bFooterIsNeeded)
             {
-                // Append a field to the end of the header text.
-                uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
-                uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY);
-                xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCHEADER()));
-                uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
-                xHeaderText->insertTextContent(xHeaderText->getEnd(), xTextContent, /*bAbsorb=*/false);
+                // If the footer is off, turn it on.
+                bool bFooterIsOn = false;
+                xPageStyle->getPropertyValue(UNO_NAME_FOOTER_IS_ON) >>= bFooterIsOn;
+                if (!bFooterIsOn)
+                    xPageStyle->setPropertyValue(UNO_NAME_FOOTER_IS_ON, uno::makeAny(true));
+
+                // If the footer already contains a document header field, no need to do anything.
+                uno::Reference<text::XText> xFooterText;
+                xPageStyle->getPropertyValue(UNO_NAME_FOOTER_TEXT) >>= xFooterText;
+                if (!lcl_hasField(xFooterText, aServiceName, SfxClassificationHelper::PROP_DOCFOOTER()))
+                {
+                    // Append a field to the end of the footer text.
+                    uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xModel, uno::UNO_QUERY);
+                    uno::Reference<beans::XPropertySet> xField(xMultiServiceFactory->createInstance(aServiceName), uno::UNO_QUERY);
+                    xField->setPropertyValue(UNO_NAME_NAME, uno::makeAny(SfxClassificationHelper::PROP_DOCFOOTER()));
+                    uno::Reference<text::XTextContent> xTextContent(xField, uno::UNO_QUERY);
+                    xFooterText->insertTextContent(xFooterText->getEnd(), xTextContent, /*bAbsorb=*/false);
+                }
             }
         }
     }


More information about the Libreoffice-commits mailing list