[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 2 commits - include/sfx2 officecfg/registry sfx2/inc sfx2/Library_sfx.mk sfx2/sdi sfx2/source sfx2/uiconfig sfx2/UIConfig_sfx.mk solenv/sanitizers

Muhammet Kara (via logerrit) logerrit at kemper.freedesktop.org
Mon Jun 17 21:30:04 UTC 2019


 include/sfx2/autoredactdialog.hxx                                    |  104 +++
 include/sfx2/sfxsids.hrc                                             |    3 
 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu |   14 
 sfx2/Library_sfx.mk                                                  |    1 
 sfx2/UIConfig_sfx.mk                                                 |    1 
 sfx2/inc/SfxRedactionHelper.hxx                                      |   20 
 sfx2/sdi/docslots.sdi                                                |    5 
 sfx2/sdi/sfx.sdi                                                     |   17 
 sfx2/source/appl/appuno.cxx                                          |    5 
 sfx2/source/doc/SfxRedactionHelper.cxx                               |  148 ++++
 sfx2/source/doc/autoredactdialog.cxx                                 |  181 +++++
 sfx2/source/doc/objserv.cxx                                          |   19 
 sfx2/uiconfig/ui/autoredactdialog.ui                                 |  339 ++++++++++
 solenv/sanitizers/ui/sfx.suppr                                       |    2 
 14 files changed, 856 insertions(+), 3 deletions(-)

New commits:
commit f13fef733a5e53fc64bc66ebb9e08dd1f01f306e
Author:     Muhammet Kara <muhammet.kara at collabora.com>
AuthorDate: Mon May 27 17:44:10 2019 +0300
Commit:     Muhammet Kara <muhammet.kara at collabora.com>
CommitDate: Mon Jun 17 23:29:34 2019 +0200

    Auto redaction dialog first iteration
    
    * Add the uno command .uno:AutoRedact with the name 'Auto-Redact'
    * Add the dialog SfxAutoRedactDialog
    * Implement the basic functionality to show up when clicked on the
      menu/toolbar item.
    * Add the class TargetsTable to control the weld::TreeView
      which is used to list the targets
    * Add the struct RedactionTarget to keep info for individual targets
    
    Change-Id: Ic02dfb009590c0928a2ea7b0f8b19b4febca221a
    Reviewed-on: https://gerrit.libreoffice.org/72254
    Tested-by: Jenkins
    Reviewed-by: Muhammet Kara <muhammet.kara at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/74226
    Tested-by: Muhammet Kara <muhammet.kara at collabora.com>

diff --git a/include/sfx2/autoredactdialog.hxx b/include/sfx2/autoredactdialog.hxx
new file mode 100644
index 000000000000..8de264871154
--- /dev/null
+++ b/include/sfx2/autoredactdialog.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SFX2_AUTOREDACTDIALOG_HXX
+#define INCLUDED_SFX2_AUTOREDACTDIALOG_HXX
+
+#include <memory>
+#include <sal/config.h>
+#include <sfx2/dllapi.h>
+#include <sfx2/basedlgs.hxx>
+#include <sfx2/objsh.hxx>
+
+#include <vcl/idle.hxx>
+#include <o3tl/typed_flags_set.hxx>
+
+namespace weld
+{
+class Button;
+}
+namespace weld
+{
+class Label;
+}
+namespace weld
+{
+class Window;
+}
+namespace weld
+{
+class TreeView;
+}
+
+struct RedactionTarget
+{
+    sal_uInt32 nID;
+    OUString sName;
+    OUString sType;
+    bool bCaseSensitive;
+    bool bWholeWords;
+    OUString sDescription;
+};
+
+class TargetsTable
+{
+    std::unique_ptr<weld::TreeView> m_xControl;
+    int GetRowByTargetName(const OUString& sName);
+
+public:
+    TargetsTable(std::unique_ptr<weld::TreeView> xControl);
+    void InsertTarget(RedactionTarget* pTarget);
+    void SelectByName(const OUString& sName);
+    RedactionTarget* GetTargetByName(const OUString& sName);
+    OUString GetNameProposal();
+
+    void unselect_all() { m_xControl->unselect_all(); }
+    bool has_focus() const { return m_xControl->has_focus(); }
+    int n_children() const { return m_xControl->n_children(); }
+    int get_selected_index() const { return m_xControl->get_selected_index(); }
+    std::vector<int> get_selected_rows() const { return m_xControl->get_selected_rows(); }
+    void clear() { m_xControl->clear(); }
+    void remove(int nRow) { m_xControl->remove(nRow); }
+    void select(int nRow) { m_xControl->select(nRow); }
+    OUString get_id(int nRow) const { return m_xControl->get_id(nRow); }
+
+    //void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xControl->connect_changed(rLink); }
+    //void connect_row_activated(const Link<weld::TreeView&, void>& rLink) { m_xControl->connect_row_activated(rLink); }
+};
+
+class SFX2_DLLPUBLIC SfxAutoRedactDialog : public SfxDialogController
+{
+    SfxObjectShellLock m_xDocShell;
+    std::vector<std::pair<TargetsTable*, OUString>> m_aTableTargets;
+
+    std::unique_ptr<weld::Label> m_xRedactionTargetsLabel;
+    std::unique_ptr<TargetsTable> m_xTargetsBox;
+    std::unique_ptr<weld::Button> m_xLoadBtn;
+    std::unique_ptr<weld::Button> m_xSaveBtn;
+    std::unique_ptr<weld::Button> m_xAddBtn;
+    std::unique_ptr<weld::Button> m_xEditBtn;
+    std::unique_ptr<weld::Button> m_xDeleteBtn;
+
+public:
+    SfxAutoRedactDialog(weld::Window* pParent);
+    virtual ~SfxAutoRedactDialog() override;
+
+    /*
+     * Check if the dialog has any valid redaction targets.
+     */
+    bool hasTargets() const;
+
+    // TODO: Some method(s) to check emptiness/validity
+    // TODO: Some method(s) to get the search params/objects
+    // TODO: Some method(s) to load/save redaction target sets
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index 24f7d569e5db..14ded948873b 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -135,6 +135,7 @@ class SfxDocumentInfoItem;
 #define SID_EXPORTDOCASEPUB                 (SID_SFX_START + 1677)
 #define SID_DIRECTEXPORTDOCASEPUB           (SID_SFX_START + 1678)
 #define SID_REDACTDOC                       (SID_SFX_START + 1732)
+#define SID_AUTOREDACTDOC                   (SID_SFX_START + 1735)
 #define SID_UPDATEDOCMODE                   (SID_SFX_START + 1668)
 #define SID_CHECKOUT                        (SID_SFX_START + 512)
 #define SID_CANCELCHECKOUT                  (SID_SFX_START + 513)
@@ -259,7 +260,7 @@ class SfxDocumentInfoItem;
 #define SID_IS_REDACT_MODE                  (SID_SFX_START + 1733)
 #define SID_REDACTION_STYLE                 (SID_SFX_START + 1734)
 
-//      SID_SFX_free_START                  (SID_SFX_START + 1735)
+//      SID_SFX_free_START                  (SID_SFX_START + 1736)
 //      SID_SFX_free_END                    (SID_SFX_START + 3999)
 
 #define SID_OPEN_NEW_VIEW                   (SID_SFX_START + 520)
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
index bcbeadb3ebdc..2bc7f9584a3a 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
@@ -5047,6 +5047,20 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:AutoRedactDoc" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Auto-Redact</value>
+        </prop>
+        <prop oor:name="ContextLabel" oor:type="xs:string">
+          <value xml:lang="en-US">Auto-Redact</value>
+        </prop>
+        <prop oor:name="TooltipLabel" oor:type="xs:string">
+          <value xml:lang="en-US">Auto-Redact Document</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:ConfigureDialog" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">~Customize...</value>
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk
index a9ba3a144582..50a1d4bfd778 100644
--- a/sfx2/Library_sfx.mk
+++ b/sfx2/Library_sfx.mk
@@ -198,6 +198,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\
     sfx2/source/doc/Metadatable \
     sfx2/source/doc/QuerySaveDocument \
     sfx2/source/doc/SfxDocumentMetaData \
+    sfx2/source/doc/autoredactdialog \
     sfx2/source/doc/docfac \
     sfx2/source/doc/docfile \
     sfx2/source/doc/docfilt \
diff --git a/sfx2/UIConfig_sfx.mk b/sfx2/UIConfig_sfx.mk
index 25fa661c203b..d6ff78053025 100644
--- a/sfx2/UIConfig_sfx.mk
+++ b/sfx2/UIConfig_sfx.mk
@@ -11,6 +11,7 @@ $(eval $(call gb_UIConfig_UIConfig,sfx))
 
 $(eval $(call gb_UIConfig_add_uifiles,sfx,\
 	sfx2/uiconfig/ui/alienwarndialog \
+	sfx2/uiconfig/ui/autoredactdialog \
 	sfx2/uiconfig/ui/bookmarkdialog \
 	sfx2/uiconfig/ui/bookmarkmenu \
 	sfx2/uiconfig/ui/charmapcontrol \
diff --git a/sfx2/sdi/docslots.sdi b/sfx2/sdi/docslots.sdi
index 5b878b8ff051..082baef0f5d5 100644
--- a/sfx2/sdi/docslots.sdi
+++ b/sfx2/sdi/docslots.sdi
@@ -253,6 +253,11 @@ shell SfxObjectShell
         ExecMethod = ExecFile_Impl ;
         StateMethod = GetState_Impl ;
     ]
+    SID_AUTOREDACTDOC
+    [
+        ExecMethod = ExecFile_Impl ;
+        StateMethod = GetState_Impl ;
+    ]
     SID_SIGNATURE
     [
         ExecMethod = ExecFile_Impl;
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index 1794527ef78d..56d59c0053d0 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -4832,6 +4832,23 @@ SfxVoidItem RedactDoc SID_REDACTDOC
     GroupId = SfxGroupId::Document;
 ]
 
+SfxVoidItem AutoRedactDoc SID_AUTOREDACTDOC
+(SfxStringItem URL SID_FILE_NAME, SfxStringItem FilterName SID_FILTER_NAME)
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = TRUE,
+    Toggle = FALSE,
+    Container = TRUE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Document;
+]
+
 SfxImageItem ImageOrientation SID_IMAGE_ORIENTATION
 
 [
diff --git a/sfx2/source/appl/appuno.cxx b/sfx2/source/appl/appuno.cxx
index 55ec01a7995d..d4daf2cefed7 100644
--- a/sfx2/source/appl/appuno.cxx
+++ b/sfx2/source/appl/appuno.cxx
@@ -177,7 +177,8 @@ static bool isMediaDescriptor( sal_uInt16 nSlotId )
              nSlotId == SID_SAVETO || nSlotId == SID_SAVEACOPY ||
              nSlotId == SID_EXPORTDOCASPDF || nSlotId == SID_DIRECTEXPORTDOCASPDF ||
              nSlotId == SID_EXPORTDOCASEPUB || nSlotId == SID_DIRECTEXPORTDOCASEPUB ||
-             nSlotId == SID_REDACTDOC || nSlotId == SID_SAVEACOPYITEM);
+             nSlotId == SID_REDACTDOC || nSlotId == SID_AUTOREDACTDOC ||
+             nSlotId == SID_SAVEACOPYITEM);
 }
 
 void TransformParameters( sal_uInt16 nSlotId, const uno::Sequence<beans::PropertyValue>& rArgs, SfxAllItemSet& rSet, const SfxSlot* pSlot )
@@ -1340,7 +1341,7 @@ void TransformItems( sal_uInt16 nSlotId, const SfxItemSet& rSet, uno::Sequence<b
     if ( nSlotId == SID_OPENDOC || nSlotId == SID_EXPORTDOC || nSlotId == SID_SAVEASDOC ||  nSlotId == SID_SAVEDOC ||
          nSlotId == SID_SAVETO || nSlotId == SID_EXPORTDOCASPDF || nSlotId == SID_DIRECTEXPORTDOCASPDF ||
          nSlotId == SID_EXPORTDOCASEPUB || nSlotId == SID_DIRECTEXPORTDOCASEPUB ||
-         nSlotId == SID_REDACTDOC || nSlotId == SID_SAVEACOPY )
+         nSlotId == SID_REDACTDOC || nSlotId == SID_AUTOREDACTDOC || nSlotId == SID_SAVEACOPY )
     {
         const SfxPoolItem *pItem=nullptr;
         if ( rSet.GetItemState( SID_COMPONENTDATA, false, &pItem ) == SfxItemState::SET )
diff --git a/sfx2/source/doc/autoredactdialog.cxx b/sfx2/source/doc/autoredactdialog.cxx
new file mode 100644
index 000000000000..0974a4f03b27
--- /dev/null
+++ b/sfx2/source/doc/autoredactdialog.cxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <osl/file.hxx>
+#include <sfx2/autoredactdialog.hxx>
+#include <vcl/layout.hxx>
+#include <vcl/idle.hxx>
+#include <vcl/gdimtf.hxx>
+#include <svl/itemset.hxx>
+#include <svl/eitem.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svtools/ehdl.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/debug.hxx>
+
+#include <sfx2/strings.hrc>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/app.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/docfile.hxx>
+#include <preview.hxx>
+#include <sfx2/printer.hxx>
+#include <unotools/viewoptions.hxx>
+#include <vcl/waitobj.hxx>
+#include <vcl/weld.hxx>
+
+#include <sal/log.hxx>
+
+int TargetsTable::GetRowByTargetName(const OUString& sName)
+{
+    for (int i = 0, nCount = m_xControl->n_children(); i < nCount; ++i)
+    {
+        RedactionTarget* pTarget
+            = reinterpret_cast<RedactionTarget*>(m_xControl->get_id(i).toInt64());
+        if (pTarget->sName == sName)
+        {
+            return i;
+        }
+    }
+    return -1;
+}
+
+TargetsTable::TargetsTable(std::unique_ptr<weld::TreeView> xControl)
+    : m_xControl(std::move(xControl))
+{
+    m_xControl->set_size_request(550, 250);
+    std::vector<int> aWidths;
+    aWidths.push_back(100);
+    aWidths.push_back(45);
+    aWidths.push_back(110);
+    aWidths.push_back(105);
+    aWidths.push_back(150);
+    m_xControl->set_column_fixed_widths(aWidths);
+    m_xControl->set_selection_mode(SelectionMode::Multiple);
+}
+
+void TargetsTable::InsertTarget(RedactionTarget* pTarget)
+{
+    if (!pTarget)
+    {
+        SAL_WARN("sfx.doc", "pTarget is null in TargetsTable::InsertTarget()");
+        return;
+    }
+
+    // Check if the name is empty or invalid (clashing with another entry's name)
+    if (pTarget->sName.isEmpty() || GetRowByTargetName(pTarget->sName) != -1)
+    {
+        pTarget->sName = GetNameProposal();
+    }
+
+    // Add to the end
+    int nRow = m_xControl->n_children();
+    m_xControl->append(OUString::number(reinterpret_cast<sal_Int64>(pTarget)), pTarget->sName);
+    m_xControl->set_text(nRow, pTarget->sType, 1);
+    m_xControl->set_text(nRow, pTarget->bCaseSensitive ? OUString("Yes") : OUString("No"), 2);
+    m_xControl->set_text(nRow, pTarget->bWholeWords ? OUString("Yes") : OUString("No"), 3);
+    m_xControl->set_text(nRow, pTarget->sDescription, 4);
+}
+
+void TargetsTable::SelectByName(const OUString& sName)
+{
+    int nEntry = GetRowByTargetName(sName);
+    if (nEntry == -1)
+        return;
+    select(nEntry);
+}
+
+RedactionTarget* TargetsTable::GetTargetByName(const OUString& sName)
+{
+    int nEntry = GetRowByTargetName(sName);
+    if (nEntry == -1)
+        return nullptr;
+
+    return reinterpret_cast<RedactionTarget*>(m_xControl->get_id(nEntry).toInt64());
+}
+
+OUString TargetsTable::GetNameProposal()
+{
+    //TODO: Define a translatable string
+    OUString sDefaultTargetName("Target");
+    sal_Int32 nHighestTargetId = 0;
+    for (int i = 0, nCount = m_xControl->n_children(); i < nCount; ++i)
+    {
+        RedactionTarget* pTarget
+            = reinterpret_cast<RedactionTarget*>(m_xControl->get_id(i).toInt64());
+        const OUString& sName = pTarget->sName;
+        sal_Int32 nIndex = 0;
+        if (sName.getToken(0, ' ', nIndex) == sDefaultTargetName)
+        {
+            sal_Int32 nCurrTargetId = sName.getToken(0, ' ', nIndex).toInt32();
+            nHighestTargetId = std::max<sal_Int32>(nHighestTargetId, nCurrTargetId);
+        }
+    }
+    return sDefaultTargetName + " " + OUString::number(nHighestTargetId + 1);
+}
+
+SfxAutoRedactDialog::SfxAutoRedactDialog(weld::Window* pParent)
+    : SfxDialogController(pParent, "sfx/ui/autoredactdialog.ui", "AutoRedactDialog")
+    , m_xRedactionTargetsLabel(m_xBuilder->weld_label("labelRedactionTargets"))
+    , m_xTargetsBox(new TargetsTable(m_xBuilder->weld_tree_view("targets")))
+    , m_xLoadBtn(m_xBuilder->weld_button("btnLoadTargets"))
+    , m_xSaveBtn(m_xBuilder->weld_button("btnSaveTargets"))
+    , m_xAddBtn(m_xBuilder->weld_button("add"))
+    , m_xEditBtn(m_xBuilder->weld_button("edit"))
+    , m_xDeleteBtn(m_xBuilder->weld_button("delete"))
+{
+    // Can be used to remmeber the last set of redaction targets?
+    OUString sExtraData;
+    SvtViewOptions aDlgOpt(EViewType::Dialog,
+                           OStringToOUString(m_xDialog->get_help_id(), RTL_TEXTENCODING_UTF8));
+    if (aDlgOpt.Exists())
+    {
+        css::uno::Any aUserItem = aDlgOpt.GetUserItem("UserItem");
+        aUserItem >>= sExtraData;
+    }
+
+    // update the targets configuration if necessary
+    {
+        weld::WaitObject aWaitCursor(m_xDialog.get());
+        //m_aTargets.Update();
+    }
+
+    // fill the targets box
+    /*const sal_uInt16 nCount = m_aTemplates.GetRegionCount();
+    if (nCount)
+    {
+        for(sal_uInt16 i = 0; i < nCount; ++i)
+            m_xRegionLb->append_text(m_aTemplates.GetFullRegionName(i));
+        m_xRegionLb->connect_changed(LINK(this, SfxNewFileDialog, RegionSelect));
+    }*/
+
+    /*RedactionTarget* redactiontarget
+        = new RedactionTarget({ 0, "Target 1", "String", true, false, "Some description" });
+
+    m_xTargetsBox->InsertTarget(redactiontarget);*/
+}
+
+SfxAutoRedactDialog::~SfxAutoRedactDialog()
+{
+    // Store the view options
+    /*SvtViewOptions aDlgOpt(EViewType::Dialog, OStringToOUString(m_xDialog->get_help_id(), RTL_TEXTENCODING_UTF8));
+    aDlgOpt.SetUserItem("UserItem", css::uno::makeAny(m_xMoreBt->get_expanded() ? OUString("Y") : OUString("N")));*/
+}
+
+bool SfxAutoRedactDialog::hasTargets() const
+{
+    //TODO: Add also some validity checks?
+    if (m_aTableTargets.empty())
+        return false;
+
+    return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index e3d2b3b5b706..1e5727c489b0 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -122,6 +122,8 @@
 #include <svx/unoshape.hxx>
 #include <com/sun/star/util/Color.hpp>
 
+#include <sfx2/autoredactdialog.hxx>
+
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::uno;
@@ -543,6 +545,22 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
             return;
         }
 
+        case SID_AUTOREDACTDOC:
+        {
+            //TODO: Implement
+            SfxAutoRedactDialog aDlg(pDialogParent);
+            sal_uInt16 nResult = aDlg.run();
+
+            if (nResult != RET_OK || !aDlg.hasTargets())
+            {
+                //Do nothing
+                return;
+            }
+
+            // else continue with normal redaction
+            [[fallthrough]];
+        }
+
         case SID_REDACTDOC:
         {
             css::uno::Reference<css::frame::XModel> xModel = GetModel();
@@ -1237,6 +1255,7 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
             case SID_EXPORTDOCASEPUB:
             case SID_DIRECTEXPORTDOCASEPUB:
             case SID_REDACTDOC:
+            case SID_AUTOREDACTDOC:
             {
                 break;
             }
diff --git a/sfx2/uiconfig/ui/autoredactdialog.ui b/sfx2/uiconfig/ui/autoredactdialog.ui
new file mode 100644
index 000000000000..01c0dc6e9592
--- /dev/null
+++ b/sfx2/uiconfig/ui/autoredactdialog.ui
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="sfx">
+  <requires lib="gtk+" version="3.18"/>
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name sTargetName -->
+      <column type="gchararray"/>
+      <!-- column-name sType -->
+      <column type="gchararray"/>
+      <!-- column-name bIsCaseSensitive -->
+      <column type="gchararray"/>
+      <!-- column-name bWholeWords -->
+      <column type="gchararray"/>
+      <!-- column-name sDescription -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="AutoRedactDialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">6</property>
+    <property name="title" translatable="yes" context="insertbookmark|InsertBookmarkDialog">Automatic Redaction</property>
+    <property name="modal">True</property>
+    <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButton" id="help">
+                <property name="label">gtk-help</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">5</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="targets">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_right">5</property>
+                    <property name="margin_bottom">5</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="model">liststore1</property>
+                    <property name="search_column">0</property>
+                    <property name="show_expanders">False</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn0">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="autoredactdialog|target">Target Name</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer0"/>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="autoredactdialog|description">Type</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer1"/>
+                          <attributes>
+                            <attribute name="text">1</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="autoredactdialog|target">Case Sensitive</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer2"/>
+                          <attributes>
+                            <attribute name="text">2</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="autoredactdialog|target">Whole Words</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer3"/>
+                          <attributes>
+                            <attribute name="text">3</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+                        <property name="resizable">True</property>
+                        <property name="spacing">6</property>
+                        <property name="title" translatable="yes" context="autoredactdialog|target">Description</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="cellrenderer4"/>
+                          <attributes>
+                            <attribute name="text">4</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="labelRedactionTargets"/>
+                    </accessibility>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="labelRedactionTargets">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="valign">center</property>
+                <property name="margin_right">1</property>
+                <property name="margin_bottom">1</property>
+                <property name="label" translatable="yes" context="menuassignpage|contentslabel">_Redaction Targets</property>
+                <property name="use_underline">True</property>
+                <accessibility>
+                  <relation type="label-for" target="targets"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButtonBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="layout_style">start</property>
+                <child>
+                  <object class="GtkButton" id="btnLoadTargets">
+                    <property name="label" translatable="yes" context="autoredactdialog|btnLoadTargets">Load Targets</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_bottom">3</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="padding">5</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="btnSaveTargets">
+                    <property name="label" translatable="yes" context="autoredactdialog|btnSaveTargets">Save Targets</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="margin_top">3</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="padding">5</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkButton" id="add">
+                <property name="label" translatable="yes" context="autoredactdialog|add">Add</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="edit">
+                <property name="label" translatable="yes" context="autoredactdialog|edit">Edit</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="delete">
+                <property name="label" translatable="yes" context="autoredactdialog|delete">Delete</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-11">help</action-widget>
+      <action-widget response="-5">ok</action-widget>
+      <action-widget response="-6">cancel</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkSizeGroup" id="TargetButtons">
+    <property name="mode">both</property>
+    <widgets>
+      <widget name="btnLoadTargets"/>
+      <widget name="btnSaveTargets"/>
+    </widgets>
+  </object>
+  <object class="GtkSizeGroup" id="otherbuttons">
+    <widgets>
+      <widget name="add"/>
+      <widget name="edit"/>
+      <widget name="delete"/>
+      <widget name="ok"/>
+      <widget name="cancel"/>
+      <widget name="help"/>
+    </widgets>
+  </object>
+</interface>
diff --git a/solenv/sanitizers/ui/sfx.suppr b/solenv/sanitizers/ui/sfx.suppr
index 66b8d3725202..3aa29105818d 100644
--- a/solenv/sanitizers/ui/sfx.suppr
+++ b/solenv/sanitizers/ui/sfx.suppr
@@ -62,6 +62,8 @@ sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='nameed'] orphan-label
 sfx2/uiconfig/ui/licensedialog.ui://GtkLabel[@id='label'] orphan-label
 sfx2/uiconfig/ui/loadtemplatedialog.ui://GtkLabel[@id='alttitle'] orphan-label
 sfx2/uiconfig/ui/loadtemplatedialog.ui://GtkDrawingArea[@id='image'] no-labelled-by
+sfx2/uiconfig/ui/autoredactdialog.ui://GtkLabel[@id='alttitle'] orphan-label
+sfx2/uiconfig/ui/autoredactdialog.ui://GtkDrawingArea[@id='image'] no-labelled-by
 sfx2/uiconfig/ui/managestylepage.ui://GtkLabel[@id='desc'] orphan-label
 sfx2/uiconfig/ui/newstyle.ui://GtkEntry[@id='entry'] no-labelled-by
 sfx2/uiconfig/ui/optprintpage.ui://GtkSpinButton[@id='reducegradstep'] no-labelled-by
commit 92cf40373ab3ece54f278c8987ad2bf68b92b98b
Author:     Muhammet Kara <muhammet.kara at collabora.com>
AuthorDate: Fri Mar 1 21:56:31 2019 +0300
Commit:     Muhammet Kara <muhammet.kara at collabora.com>
CommitDate: Mon Jun 17 23:29:19 2019 +0200

    Auto-redact - First stab
    
    Add a SfxRedactionHelper::autoRedactPage method which searches for the given term
    through the gdimetafile which has the whole content of an xPage (a Draw page),
    and draws redaction rectangles at proper positions with proper sizes.
    
    The search is case sensitive, and finds only the first occurences on a line.
    Will switch to a proper search provider via a follow-up patch.
    
    Change-Id: If3db62e50994670143785b6727fdcf1ccd4c6f8e
    Reviewed-on: https://gerrit.libreoffice.org/68597
    Tested-by: Jenkins
    Reviewed-by: Muhammet Kara <muhammet.kara at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/74225
    Tested-by: Muhammet Kara <muhammet.kara at collabora.com>

diff --git a/sfx2/inc/SfxRedactionHelper.hxx b/sfx2/inc/SfxRedactionHelper.hxx
index ac15bb790fe9..44a78ab9b877 100644
--- a/sfx2/inc/SfxRedactionHelper.hxx
+++ b/sfx2/inc/SfxRedactionHelper.hxx
@@ -14,6 +14,7 @@
 #include <com/sun/star/lang/XComponent.hpp>
 #include <com/sun/star/frame/XModel.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
 
 #include <sal/types.h>
 #include <rtl/ustring.hxx>
@@ -87,6 +88,25 @@ public:
      * pages inserted into Draw for redaction.
      * */
     static PageMargins getPageMarginsForCalc(css::uno::Reference<css::frame::XModel>& xModel);
+
+    static void searchInMetaFile(const OUString& sSearchTerm, const GDIMetaFile& rMtf,
+                                 std::vector<tools::Rectangle>& aRedactionRectangles,
+                                 uno::Reference<XComponent>& xComponent);
+
+    /*
+     * Draws a redaction rectangle on the draw page referenced with its page number (0-based)
+     * */
+    static void addRedactionRectToPage(uno::Reference<XComponent>& xComponent,
+                                       uno::Reference<drawing::XDrawPage>& xPage,
+                                       const std::vector<tools::Rectangle>& aNewRectangles);
+
+    /*
+     * Search for the given term through the gdimetafile, which has the whole content of a draw page,
+     * and draw redaction rectangles to the appropriate positions with suitable sizes.
+     * */
+    static void autoRedactPage(const OUString& sRedactionTerm, const GDIMetaFile& rGDIMetaFile,
+                               uno::Reference<drawing::XDrawPage>& xPage,
+                               uno::Reference<XComponent>& xComponent);
 };
 
 #endif // INCLUDED_CUI_SOURCE_INC_SFXREDACTIONHELPER_HXX
diff --git a/sfx2/source/doc/SfxRedactionHelper.cxx b/sfx2/source/doc/SfxRedactionHelper.cxx
index 457ed41d1b9a..35d3acdc0067 100644
--- a/sfx2/source/doc/SfxRedactionHelper.cxx
+++ b/sfx2/source/doc/SfxRedactionHelper.cxx
@@ -10,6 +10,7 @@
 #include <SfxRedactionHelper.hxx>
 
 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/graphic/XGraphic.hpp>
 #include <com/sun/star/frame/XLayoutManager.hpp>
@@ -31,11 +32,16 @@
 
 #include <svtools/DocumentToGraphicRenderer.hxx>
 
+#include <tools/gen.hxx>
+
 #include <vcl/gdimtf.hxx>
 #include <vcl/graph.hxx>
 
 #include <vcl/wmf.hxx>
 #include <vcl/gdimetafiletools.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/vcllayout.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::lang;
@@ -104,8 +110,66 @@ void setPageMargins(uno::Reference<beans::XPropertySet>& xPageProperySet,
     xPageProperySet->setPropertyValue("BorderLeft", css::uno::makeAny(aPageMargins.nLeft));
     xPageProperySet->setPropertyValue("BorderRight", css::uno::makeAny(aPageMargins.nRight));
 }
+
+// #i10613# Extracted from ImplCheckRect::ImplCreate
+tools::Rectangle ImplCalcActionBounds(const MetaAction& rAct, const OutputDevice& rOut,
+                                      const OUString& sSubString, const sal_Int32& nStrPos)
+{
+    tools::Rectangle aActionBounds;
+
+    switch (rAct.GetType())
+    {
+        case MetaActionType::TEXTARRAY:
+        {
+            const MetaTextArrayAction& rTextAct = static_cast<const MetaTextArrayAction&>(rAct);
+            const OUString aString(rTextAct.GetText().copy(rTextAct.GetIndex(), rTextAct.GetLen()));
+
+            if (!aString.isEmpty())
+            {
+                // #105987# ImplLayout takes everything in logical coordinates
+                std::unique_ptr<SalLayout> pSalLayout1 = rOut.ImplLayout(
+                    aString, 0, nStrPos, rTextAct.GetPoint(), 0, rTextAct.GetDXArray());
+                std::unique_ptr<SalLayout> pSalLayout2
+                    = rOut.ImplLayout(aString, 0, nStrPos + sSubString.getLength(),
+                                      rTextAct.GetPoint(), 0, rTextAct.GetDXArray());
+                if (pSalLayout2)
+                {
+                    tools::Rectangle aBoundRect2(
+                        const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect(*pSalLayout2));
+                    aActionBounds = rOut.PixelToLogic(aBoundRect2);
+                }
+                if (pSalLayout1 && nStrPos > 0)
+                {
+                    tools::Rectangle aBoundRect1(
+                        const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect(*pSalLayout1));
+                    aActionBounds.SetLeft(rOut.PixelToLogic(aBoundRect1).getX()
+                                          + rOut.PixelToLogic(aBoundRect1).getWidth());
+                }
+
+                // FIXME: Is this really needed?
+                aActionBounds.SetTop(aActionBounds.getY() + 100);
+            }
+        }
+        break;
+
+        default:
+            break;
+    }
+
+    if (!aActionBounds.IsEmpty())
+    {
+        // fdo#40421 limit current action's output to clipped area
+        if (rOut.IsClipRegion())
+            return rOut.GetClipRegion().GetBoundRect().Intersection(aActionBounds);
+        else
+            return aActionBounds;
+    }
+    else
+        return aActionBounds;
 }
 
+} // End of anon namespace
+
 void SfxRedactionHelper::getPageMetaFilesFromDoc(std::vector<GDIMetaFile>& aMetaFiles,
                                                  std::vector<::Size>& aPageSizes,
                                                  const sal_Int32& nPages,
@@ -183,6 +247,8 @@ void SfxRedactionHelper::addPagesToDraw(uno::Reference<XComponent>& xComponent,
             awt::Size(rGDIMetaFile.GetPrefSize().Width(), rGDIMetaFile.GetPrefSize().Height()));
 
         xPage->add(xShape);
+
+        //autoRedactPage("deployment", rGDIMetaFile, xPage, xComponent);
     }
 
     // Remove the extra page at the beginning
@@ -333,4 +399,86 @@ SfxRedactionHelper::getPageMarginsForCalc(css::uno::Reference<css::frame::XModel
     return aPageMargins;
 }
 
+void SfxRedactionHelper::searchInMetaFile(const rtl::OUString& sSearchTerm, const GDIMetaFile& rMtf,
+                                          std::vector<::tools::Rectangle>& aRedactionRectangles,
+                                          uno::Reference<XComponent>& xComponent)
+{
+    MetaAction* pCurrAct;
+
+    // Watch for TEXTARRAY actions.
+    // They contain the text of paragraphes.
+    for (pCurrAct = const_cast<GDIMetaFile&>(rMtf).FirstAction(); pCurrAct;
+         pCurrAct = const_cast<GDIMetaFile&>(rMtf).NextAction())
+    {
+        if (pCurrAct->GetType() == MetaActionType::TEXTARRAY)
+        {
+            MetaTextArrayAction* pMetaTextArrayAction = static_cast<MetaTextArrayAction*>(pCurrAct);
+
+            //sal_Int32 aIndex = pMetaTextArrayAction->GetIndex();
+            //sal_Int32 aLength = pMetaTextArrayAction->GetLen();
+            //Point aPoint = pMetaTextArrayAction->GetPoint();
+            OUString sText = pMetaTextArrayAction->GetText();
+            sal_Int32 nFoundIndex = sText.indexOf(sSearchTerm);
+
+            // If found the string, add the corresponding rectangle to the collection
+            if (nFoundIndex >= 0)
+            {
+                OutputDevice* pOutputDevice
+                    = SfxObjectShell::GetShellFromComponent(xComponent)->GetDocumentRefDev();
+                tools::Rectangle aNewRect(ImplCalcActionBounds(
+                    *pMetaTextArrayAction, *pOutputDevice, sSearchTerm, nFoundIndex));
+
+                if (!aNewRect.IsEmpty())
+                    aRedactionRectangles.push_back(aNewRect);
+            }
+        }
+    }
+}
+
+void SfxRedactionHelper::addRedactionRectToPage(
+    uno::Reference<XComponent>& xComponent, uno::Reference<drawing::XDrawPage>& xPage,
+    const std::vector<::tools::Rectangle>& aNewRectangles)
+{
+    if (!xComponent.is() || !xPage.is())
+        return;
+
+    if (aNewRectangles.empty())
+        return;
+
+    uno::Reference<css::lang::XMultiServiceFactory> xFactory(xComponent, uno::UNO_QUERY);
+
+    for (auto const& aNewRectangle : aNewRectangles)
+    {
+        uno::Reference<drawing::XShape> xRectShape(
+            xFactory->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xRectShapeProperySet(xRectShape, uno::UNO_QUERY);
+
+        xRectShapeProperySet->setPropertyValue("Name",
+                                               uno::Any(OUString("RectangleRedactionShape")));
+        xRectShapeProperySet->setPropertyValue("FillTransparence",
+                                               css::uno::makeAny(static_cast<sal_Int16>(50)));
+        xRectShapeProperySet->setPropertyValue("FillColor", css::uno::makeAny(COL_GRAY7));
+        xRectShapeProperySet->setPropertyValue(
+            "LineStyle", css::uno::makeAny(css::drawing::LineStyle::LineStyle_NONE));
+
+        xRectShape->setSize(awt::Size(aNewRectangle.GetWidth(), aNewRectangle.GetHeight()));
+        xRectShape->setPosition(awt::Point(aNewRectangle.getX(), aNewRectangle.getY()));
+
+        xPage->add(xRectShape);
+    }
+}
+
+void SfxRedactionHelper::autoRedactPage(const OUString& sRedactionTerm,
+                                        const GDIMetaFile& rGDIMetaFile,
+                                        uno::Reference<drawing::XDrawPage>& xPage,
+                                        uno::Reference<XComponent>& xComponent)
+{
+    // Search for the redaction strings, and get the rectangle coordinates
+    std::vector<::tools::Rectangle> aRedactionRectangles;
+    searchInMetaFile(sRedactionTerm, rGDIMetaFile, aRedactionRectangles, xComponent);
+
+    // Add the redaction rectangles to the page
+    addRedactionRectToPage(xComponent, xPage, aRedactionRectangles);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */


More information about the Libreoffice-commits mailing list