[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-4+backports' - 2 commits - include/editeng include/oox include/svl include/svx oox/source sc/source svx/source sw/qa sw/sdi sw/source sw/uiconfig writerfilter/source xmloff/source

Samuel Mehrbrodt (via logerrit) logerrit at kemper.freedesktop.org
Sun Aug 1 13:19:01 UTC 2021


 include/editeng/unoprnms.hxx                         |    2 
 include/oox/vml/vmlshape.hxx                         |    1 
 include/oox/vml/vmlshapecontext.hxx                  |    2 
 include/svl/solar.hrc                                |    2 
 include/svx/svdobj.hxx                               |    5 +
 include/svx/unoshprp.hxx                             |    6 +
 oox/source/export/vmlexport.cxx                      |    4 +
 oox/source/token/properties.txt                      |    1 
 oox/source/vml/vmlshape.cxx                          |    4 +
 oox/source/vml/vmlshapecontext.cxx                   |    6 +
 sc/source/filter/xml/xmlexprt.cxx                    |   34 --------
 svx/source/svdraw/svdview.cxx                        |    7 +
 svx/source/unodraw/unoshape.cxx                      |   18 ++++
 sw/qa/extras/odfexport/data/shape-with-hyperlink.odt |binary
 sw/qa/extras/odfexport/odfexport.cxx                 |   10 ++
 sw/qa/extras/ooxmlexport/data/hyperlinkshape.docx    |binary
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx            |    7 +
 sw/sdi/_drwbase.sdi                                  |   33 ++++++++
 sw/source/filter/ww8/docxsdrexport.cxx               |   18 ++++
 sw/source/uibase/shells/drwbassh.cxx                 |   74 +++++++++++++++++++
 sw/uiconfig/sglobal/popupmenu/draw.xml               |    5 +
 sw/uiconfig/swform/popupmenu/draw.xml                |    5 +
 sw/uiconfig/swreport/popupmenu/draw.xml              |    5 +
 sw/uiconfig/swriter/popupmenu/draw.xml               |    5 +
 sw/uiconfig/swxform/popupmenu/draw.xml               |    5 +
 writerfilter/source/dmapper/GraphicImport.cxx        |   16 +++-
 writerfilter/source/dmapper/PropertyIds.cxx          |    1 
 writerfilter/source/dmapper/PropertyIds.hxx          |    1 
 xmloff/source/draw/shapeexport.cxx                   |   26 ++++++
 xmloff/source/text/XMLTextFrameContext.cxx           |    4 +
 xmloff/source/text/XMLTextFrameHyperlinkContext.cxx  |   16 +++-
 xmloff/source/text/XMLTextFrameHyperlinkContext.hxx  |    1 
 32 files changed, 279 insertions(+), 45 deletions(-)

New commits:
commit a95da79d6b60885bf104adb32e9afd0fc964047c
Author:     Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
AuthorDate: Tue Jul 27 13:50:26 2021 +0200
Commit:     Thorsten Behrens <thorsten.behrens at allotropia.de>
CommitDate: Sun Aug 1 15:18:37 2021 +0200

    tdf#123626 Allow opening shape hyperlink with Ctrl-Click
    
    Change-Id: I43201cd1fb7022fe5ff1479c66916c65adc554fa
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119550
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
    (cherry picked from commit 9a04703b22f9ffb11256d715f65e79a6a2417e18)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119586
    Tested-by: Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behrens at allotropia.de>

diff --git a/svx/source/svdraw/svdview.cxx b/svx/source/svdraw/svdview.cxx
index 76222cd30158..ad7bd17ed6de 100644
--- a/svx/source/svdraw/svdview.cxx
+++ b/svx/source/svdraw/svdview.cxx
@@ -507,6 +507,13 @@ SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) co
                 }
             }
         }
+        if (eHit==SdrHitKind::UnmarkedObject && !pHitObj->getHyperlink().isEmpty())
+        {
+            static SvxURLField aSvxURLField;
+            aSvxURLField.SetURL(pHitObj->getHyperlink());
+            rVEvt.pURLField = &aSvxURLField;
+            eHit = SdrHitKind::UrlField;
+        }
     }
 
     if (bHitPassDirect &&
commit 3b53c908d044f63acbe1a7cbf8ecd189954d546e
Author:     Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
AuthorDate: Mon Jul 19 08:11:43 2021 +0200
Commit:     Thorsten Behrens <thorsten.behrens at allotropia.de>
CommitDate: Sun Aug 1 15:18:24 2021 +0200

    tdf#123626 Allow adding hyperlinks to shapes
    
    * Support hyperlinks on Shapes in Writer
    * Add menu items
    * Add context menu items
    * ODF import/export + test
    * OOXML import/export + test
    
    Change-Id: I7269064c4cabd16fdb8259a48429c508184d3ccf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119164
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
    (cherry picked from commit a23b44fd9f0119f7ea3523e32875f55c1a07c1cd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119584
    Tested-by: Samuel Mehrbrodt <samuel.mehrbrodt at allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behrens at allotropia.de>

diff --git a/include/editeng/unoprnms.hxx b/include/editeng/unoprnms.hxx
index ca3b977afeee..cee3ea02993d 100644
--- a/include/editeng/unoprnms.hxx
+++ b/include/editeng/unoprnms.hxx
@@ -160,6 +160,8 @@
 #define UNO_NAME_MISC_OBJ_TITLE                 "Title"
 #define UNO_NAME_MISC_OBJ_DESCRIPTION           "Description"
 
+#define UNO_NAME_HYPERLINK                      "Hyperlink"
+
 #define UNO_NAME_GRAPHOBJ_FILLBITMAP            "GraphicObjectFillBitmap"
 #define UNO_NAME_GRAPHOBJ_REPLACEMENT_GRAPHIC   "ReplacementGraphic"
 #define UNO_NAME_GRAPHOBJ_GRAFSTREAMURL         "GraphicStreamURL"
diff --git a/include/oox/vml/vmlshape.hxx b/include/oox/vml/vmlshape.hxx
index 2b3677df106d..4b0068f1175b 100644
--- a/include/oox/vml/vmlshape.hxx
+++ b/include/oox/vml/vmlshape.hxx
@@ -113,6 +113,7 @@ struct OOX_DLLPUBLIC ShapeTypeModel
     OptValue<OUString> moCropRight; ///< Specifies how much to crop the image from the right in as a fraction of picture size.
     OptValue<OUString> moCropTop; ///< Specifies how much to crop the image from the top down as a fraction of picture size.
     OUString maLayoutFlowAlt; ///< Specifies the alternate layout flow for text in textboxes.
+    OUString maHyperlink; ///< The hyperlink assigned to the shape
 
     explicit            ShapeTypeModel();
 
diff --git a/include/oox/vml/vmlshapecontext.hxx b/include/oox/vml/vmlshapecontext.hxx
index c07bcf12e84f..4cdcd78b2031 100644
--- a/include/oox/vml/vmlshapecontext.hxx
+++ b/include/oox/vml/vmlshapecontext.hxx
@@ -108,6 +108,8 @@ public:
 private:
     /** Processes the 'style' attribute. */
     void                setStyle( const OUString& rStyle );
+    /** Processes the 'href' attribute. */
+    void                setHyperlink( const OUString& rHyperlink );
 
     /** Resolve a relation identifier to a fragment path. */
     OptValue< OUString > decodeFragmentPath( const AttributeList& rAttribs, sal_Int32 nToken ) const;
diff --git a/include/svl/solar.hrc b/include/svl/solar.hrc
index 6b4cb07bbc33..317d45a84bc1 100644
--- a/include/svl/solar.hrc
+++ b/include/svl/solar.hrc
@@ -23,7 +23,7 @@
 // defines ------------------------------------------------------------------
 
 #define OWN_ATTR_VALUE_START                    3900
-#define OWN_ATTR_VALUE_END                      4004
+#define OWN_ATTR_VALUE_END                      4005
 
 #define RID_LIB_START               10000
 #define RID_LIB_END                 19999
diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx
index 361062554a87..431bc4cd912e 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -917,6 +917,9 @@ public:
 
     void setSuitableOutlinerBg(Outliner& rOutliner) const;
 
+    OUString getHyperlink() const { return msHyperlink; }
+    void setHyperlink(const OUString& sHyperlink) { msHyperlink = sHyperlink; }
+
 protected:
     tools::Rectangle            aOutRect;     // surrounding rectangle for Paint (incl. LineWidth, ...)
     Point                       aAnchor;      // anchor position (Writer)
@@ -1024,6 +1027,8 @@ private:
     // HACK: Do not automatically insert newly created object into a page.
     // The user needs to do it manually later.
     bool                        mbDoNotInsertIntoPageAutomatically;
+    // Hyperlink for the whole shape
+    OUString msHyperlink;
 
     // only for internal use!
     SvxShape* getSvxShape();
diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx
index 0861844be16d..c322b7d1697d 100644
--- a/include/svx/unoshprp.hxx
+++ b/include/svx/unoshprp.hxx
@@ -192,7 +192,8 @@
 #define OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE   (OWN_ATTR_VALUE_START+102)
 #define OWN_ATTR_SIGNATURELINE_IS_SIGNED        (OWN_ATTR_VALUE_START+103)
 #define OWN_ATTR_QRCODE                         (OWN_ATTR_VALUE_START+104)
-// ATTENTION: maximum is OWN_ATTR_VALUE_START+104 svx, see include/svl/solar.hrc
+#define OWN_ATTR_HYPERLINK                      (OWN_ATTR_VALUE_START+105)
+// ATTENTION: maximum is OWN_ATTR_VALUE_START+105 svx, see include/svl/solar.hrc
 
 // #FontWork#
 #define FONTWORK_PROPERTIES \
@@ -340,7 +341,8 @@
     { OUString("UINamePlural"),                 OWN_ATTR_UINAME_PLURAL          , ::cppu::UnoType<OUString>::get(),    css::beans::PropertyAttribute::READONLY,   0}, \
     /* #i68101# */ \
     { OUString(UNO_NAME_MISC_OBJ_TITLE),        OWN_ATTR_MISC_OBJ_TITLE         , ::cppu::UnoType<OUString>::get(),    0,  0}, \
-    { OUString(UNO_NAME_MISC_OBJ_DESCRIPTION),  OWN_ATTR_MISC_OBJ_DESCRIPTION   , ::cppu::UnoType<OUString>::get(),    0,  0},
+    { OUString(UNO_NAME_MISC_OBJ_DESCRIPTION),  OWN_ATTR_MISC_OBJ_DESCRIPTION   , ::cppu::UnoType<OUString>::get(),    0,  0}, \
+    { OUString(UNO_NAME_HYPERLINK),             OWN_ATTR_HYPERLINK              , ::cppu::UnoType<OUString>::get(),    0,  0},
 
 #define LINKTARGET_PROPERTIES \
     { OUString(UNO_NAME_LINKDISPLAYNAME),   OWN_ATTR_LDNAME             , ::cppu::UnoType<OUString>::get(),    css::beans::PropertyAttribute::READONLY, 0}, \
diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx
index 98f3243e5461..d289b74d0cd1 100644
--- a/oox/source/export/vmlexport.cxx
+++ b/oox/source/export/vmlexport.cxx
@@ -1325,6 +1325,10 @@ sal_Int32 VMLExport::StartShape()
             break;
     }
 
+    if (!m_pSdrObject->getHyperlink().isEmpty())
+        m_pShapeAttrList->add(
+            XML_href, OUStringToOString(m_pSdrObject->getHyperlink(), RTL_TEXTENCODING_UTF8));
+
     // add style
     m_pShapeAttrList->add( XML_style, m_ShapeStyle.makeStringAndClear() );
 
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index f53b73f8b79e..70f15974045e 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -245,6 +245,7 @@ HoriOrientPosition
 HoriOrientRelation
 HorizontalSplitMode
 HorizontalSplitPositionTwips
+Hyperlink
 IgnoreBlankCells
 IgnoreCase
 IgnoreLeadingSpaces
diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx
index e1c857f5528e..dcb231727535 100644
--- a/oox/source/vml/vmlshape.cxx
+++ b/oox/source/vml/vmlshape.cxx
@@ -784,6 +784,10 @@ Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes
             eTextVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM;
         PropertySet(xShape).setAnyProperty(PROP_TextVerticalAdjust, makeAny(eTextVerticalAdjust));
 
+        // tdf#123626
+        if (!maTypeModel.maHyperlink.isEmpty())
+            PropertySet(xShape).setAnyProperty(PROP_Hyperlink, makeAny(maTypeModel.maHyperlink));
+
         PropertySet(xShape).setAnyProperty(PROP_TextAutoGrowHeight,
                                            makeAny(maTypeModel.mbAutoHeight));
 
diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx
index d27839a79084..94db859ff988 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -303,6 +303,7 @@ ShapeTypeContext::ShapeTypeContext(ContextHandler2Helper const & rParent,
     mrTypeModel.moCoordPos = lclDecodeInt32Pair( rAttribs, XML_coordorigin );
     mrTypeModel.moCoordSize = lclDecodeInt32Pair( rAttribs, XML_coordsize );
     setStyle( rAttribs.getString( XML_style, OUString() ) );
+    setHyperlink( rAttribs.getString( XML_href, OUString() ) );
     if( lclDecodeBool( rAttribs, O_TOKEN( hr )).get( false ))
     {   // MSO's handling of o:hr width is nowhere near what the spec says:
         // - o:hrpct is not in % but in 0.1%
@@ -460,6 +461,11 @@ void ShapeTypeContext::setStyle( const OUString& rStyle )
     }
 }
 
+void ShapeTypeContext::setHyperlink( const OUString& rHyperlink )
+{
+    mrTypeModel.maHyperlink = rHyperlink;
+}
+
 ShapeContext::ShapeContext(ContextHandler2Helper const& rParent,
                            const std::shared_ptr<ShapeBase>& pShape, const AttributeList& rAttribs)
     : ShapeTypeContext(rParent, pShape, rAttribs)
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 2d16318bac7e..f9827bb63617 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -3424,40 +3424,8 @@ void ScXMLExport::ExportShape(const uno::Reference < drawing::XShape >& xShape,
         }
     }
     if (!bIsChart)
-    {
-        OUString sHlink;
-        try
-        {
-            uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
-            if ( xProps.is() )
-                xProps->getPropertyValue( SC_UNONAME_HYPERLINK ) >>= sHlink;
-        }
-        catch ( const beans::UnknownPropertyException& )
-        {
-            // no hyperlink property
-        }
-
-        std::unique_ptr< SvXMLElementExport > pDrawA;
-        // enclose shapes with <draw:a> element only if sHlink contains something
-        if ( !sHlink.isEmpty() )
-        {
-            // need to get delete the attributes that are pre-loaded
-            // for the shape export ( otherwise they will become
-            // attributes of the draw:a element ) This *shouldn't*
-            // affect performance adversely as there are only a
-            // couple of attributes involved
-            uno::Reference< xml::sax::XAttributeList > xSaveAttribs( new  SvXMLAttributeList( GetAttrList() ) );
-            ClearAttrList();
-            // Add Hlink
-            AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
-            AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sHlink);
-            pDrawA.reset( new SvXMLElementExport( *this, XML_NAMESPACE_DRAW, XML_A, false, false ) );
-            // Attribute list has been cleared by previous operation
-            // re-add pre-loaded attributes
-            AddAttributeList( xSaveAttribs );
-        }
         GetShapeExport()->exportShape(xShape, SEF_DEFAULT, pPoint);
-    }
+
     IncrementProgressBar(false);
 }
 
diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx
index 3f07f5ab9a82..0adc5e54622e 100644
--- a/svx/source/unodraw/unoshape.cxx
+++ b/svx/source/unodraw/unoshape.cxx
@@ -2488,6 +2488,18 @@ bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertySimpl
             return false;
         }
     }
+
+    case OWN_ATTR_HYPERLINK:
+    {
+        OUString sHyperlink;
+        if (rValue >>= sHyperlink)
+        {
+            GetSdrObject()->setHyperlink(sHyperlink);
+            return true;
+        }
+        break;
+    }
+
     default:
     {
         return false;
@@ -2883,6 +2895,12 @@ bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertySimpl
     }
 
 
+    case OWN_ATTR_HYPERLINK:
+    {
+        rValue <<= GetSdrObject()->getHyperlink();
+        break;
+    }
+
     default:
         return false;
     }
diff --git a/sw/qa/extras/odfexport/data/shape-with-hyperlink.odt b/sw/qa/extras/odfexport/data/shape-with-hyperlink.odt
new file mode 100644
index 000000000000..7b112782845f
Binary files /dev/null and b/sw/qa/extras/odfexport/data/shape-with-hyperlink.odt differ
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index 3045586f991f..9939a2cd2830 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -1137,6 +1137,16 @@ DECLARE_ODFEXPORT_TEST(testTextboxRoundedCorners, "textbox-rounded-corners.odt")
         assertXPath(pXmlDoc, "//draw:custom-shape/loext:table", "name", "Table1");
 }
 
+DECLARE_ODFEXPORT_TEST(testShapeWithHyperlink, "shape-with-hyperlink.odt")
+{
+    if (xmlDocPtr pXmlDoc = parseExport("content.xml"))
+    {
+        // Check how conversion from prefix/suffix to list format did work
+        assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p/draw:a",
+                    "href", "http://shape.com/");
+    }
+}
+
 // test that import whitespace collapsing is compatible with old docs
 DECLARE_ODFEXPORT_TEST(testWhitespace, "whitespace.odt")
 {
diff --git a/sw/qa/extras/ooxmlexport/data/hyperlinkshape.docx b/sw/qa/extras/ooxmlexport/data/hyperlinkshape.docx
new file mode 100644
index 000000000000..3bf4f8c5c498
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/hyperlinkshape.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index ece282f437aa..b9965be36431 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -1192,6 +1192,13 @@ DECLARE_OOXMLEXPORT_TEST(testActiveXControlAtRunEnd, "activex_control_at_run_end
     CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,getProperty<text::TextContentAnchorType>(xPropertySet2,"AnchorType"));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testShapeHyperlink, "hyperlinkshape.docx")
+{
+    // Test import/export of hyperlink property on shapes
+    auto xShape(getShape(1));
+    CPPUNIT_ASSERT_EQUAL(OUString("https://libreoffice.org/"), getProperty<OUString>(xShape, "Hyperlink"));
+}
+
 DECLARE_OOXMLEXPORT_TEST(testActiveXOptionButtonGroup, "activex_option_button_group.docx")
 {
     // Optionbutton groups were not handled
diff --git a/sw/sdi/_drwbase.sdi b/sw/sdi/_drwbase.sdi
index eae02c15312c..e90d50cb92fb 100644
--- a/sw/sdi/_drwbase.sdi
+++ b/sw/sdi/_drwbase.sdi
@@ -117,5 +117,38 @@ interface BaseTextDrawBase
         StateMethod = GetState ;
         DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
     ]
+    SID_EDIT_HYPERLINK
+    [
+        ExecMethod = Execute ;
+        StateMethod = GetState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
+    SID_HYPERLINK_DIALOG
+    [
+        ExecMethod = Execute;
+        StateMethod = GetState;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
+    SID_HYPERLINK_SETLINK // status()
+    [
+        ExecMethod = Execute ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
+    SID_HYPERLINK_GETLINK // status()
+    [
+        StateMethod = GetState ;
+    ]
+    SID_REMOVE_HYPERLINK
+    [
+        ExecMethod = Execute ;
+        StateMethod = GetState;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
+    SID_COPY_HYPERLINK_LOCATION
+    [
+        ExecMethod = Execute ;
+        StateMethod = GetState;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
 }
 
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index 7cacc4eb3173..68e67be808dd 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -17,6 +17,7 @@
 #include <editeng/boxitem.hxx>
 #include <svx/svdogrp.hxx>
 #include <oox/token/namespaces.hxx>
+#include <oox/token/relationship.hxx>
 #include <textboxhelper.hxx>
 #include <fmtanchr.hxx>
 #include <fmtsrnd.hxx>
@@ -873,8 +874,21 @@ void DocxSdrExport::writeDMLDrawing(const SdrObject* pSdrObject, const SwFrameFo
         && pFrameFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR)
 
         pDocPrAttrList->add(XML_hidden, OString::number(1).getStr());
-    sax_fastparser::XFastAttributeListRef xDocPrAttrListRef(pDocPrAttrList);
-    pFS->singleElementNS(XML_wp, XML_docPr, xDocPrAttrListRef);
+
+    pFS->startElementNS(XML_wp, XML_docPr, pDocPrAttrList);
+    OUString sHyperlink = pSdrObject->getHyperlink();
+    if (!sHyperlink.isEmpty())
+    {
+        OUString sRelId = m_pImpl->getExport().GetFilter().addRelation(
+            pFS->getOutputStream(), oox::getRelationship(Relationship::HYPERLINK),
+            oox::drawingml::URLTransformer().getTransformedString(sHyperlink),
+            oox::drawingml::URLTransformer().isExternalURL(sHyperlink));
+        pFS->singleElementNS(
+            XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId.toUtf8().getStr(),
+            FSNS(XML_xmlns, XML_a),
+            m_pImpl->getExport().GetFilter().getNamespaceURL(OOX_NS(dml)).toUtf8());
+    }
+    pFS->endElementNS(XML_wp, XML_docPr);
 
     uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY_THROW);
     const char* pNamespace = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
diff --git a/sw/source/uibase/shells/drwbassh.cxx b/sw/source/uibase/shells/drwbassh.cxx
index 12d87bab691b..c1ebca01d1c0 100644
--- a/sw/source/uibase/shells/drwbassh.cxx
+++ b/sw/source/uibase/shells/drwbassh.cxx
@@ -30,6 +30,7 @@
 #include <svx/swframevalidation.hxx>
 #include <svx/anchorid.hxx>
 #include <sfx2/htmlmode.hxx>
+#include <svx/hlnkitem.hxx>
 #include <drawdoc.hxx>
 #include <uitool.hxx>
 #include <fmtornt.hxx>
@@ -54,16 +55,23 @@
 #include <swslots.hxx>
 #include <svx/svxdlg.hxx>
 #include <svx/dialogs.hrc>
+#include <vcl/unohelp2.hxx>
 #include <swabstdlg.hxx>
 #include <swundo.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
 #include <com/sun/star/text/HoriOrientation.hpp>
 #include <com/sun/star/text/VertOrientation.hpp>
 #include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/uno/Reference.hxx>
 #include <IDocumentDrawModelAccess.hxx>
 #include <memory>
 #include <fmtfollowtextflow.hxx>
 
 using namespace ::com::sun::star;
+using namespace css::beans;
+using namespace css::drawing;
+using namespace css::uno;
 
 SFX_IMPL_SUPERCLASS_INTERFACE(SwDrawBaseShell, SwBaseShell)
 
@@ -603,6 +611,43 @@ void SwDrawBaseShell::Execute(SfxRequest const &rReq)
             break;
         }
 
+        case SID_EDIT_HYPERLINK:
+        case SID_HYPERLINK_DIALOG:
+        {
+            GetView().GetViewFrame()->SetChildWindow(SID_HYPERLINK_DIALOG, true);
+            break;
+        }
+
+        case SID_HYPERLINK_SETLINK:
+        {
+            if(pItem)
+            {
+                const SvxHyperlinkItem& rHLinkItem = *static_cast<const SvxHyperlinkItem *>(pItem);
+                const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+                SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+                pObj->setHyperlink(rHLinkItem.GetURL());
+            }
+            break;
+        }
+
+        case SID_REMOVE_HYPERLINK:
+        {
+            const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+            pObj->setHyperlink(OUString());
+            break;
+        }
+
+        case SID_COPY_HYPERLINK_LOCATION:
+        {
+            const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+            uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
+                = GetView().GetEditWin().GetClipboard();
+            vcl::unohelper::TextDataObject::CopyStringTo(pObj->getHyperlink(), xClipboard);
+            break;
+        }
+
         default:
             OSL_ENSURE(false, "wrong Dispatcher");
             return;
@@ -736,6 +781,35 @@ void SwDrawBaseShell::GetState(SfxItemSet& rSet)
                     }
                 }
                 break;
+
+            case SID_EDIT_HYPERLINK:
+            case SID_HYPERLINK_DIALOG:
+            case SID_REMOVE_HYPERLINK:
+            case SID_COPY_HYPERLINK_LOCATION:
+            {
+                if (pSdrView->GetMarkedObjectCount() != 1)
+                    rSet.DisableItem(nWhich);
+                else if (nWhich == SID_REMOVE_HYPERLINK || nWhich == SID_EDIT_HYPERLINK
+                         || nWhich == SID_COPY_HYPERLINK_LOCATION)
+                {
+                    const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+                    SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+                    if (pObj->getHyperlink().isEmpty())
+                        rSet.DisableItem(nWhich);
+                }
+            }
+            break;
+
+            case SID_HYPERLINK_GETLINK:
+            {
+                const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+                SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
+                OUString sHyperLink = pObj->getHyperlink();
+                SvxHyperlinkItem aHLinkItem;
+                aHLinkItem.SetURL(sHyperLink);
+                rSet.Put(aHLinkItem);
+            }
+            break;
         }
         nWhich = aIter.NextWhich();
     }
diff --git a/sw/uiconfig/sglobal/popupmenu/draw.xml b/sw/uiconfig/sglobal/popupmenu/draw.xml
index d119c1add5cf..799c02cc5e2e 100644
--- a/sw/uiconfig/sglobal/popupmenu/draw.xml
+++ b/sw/uiconfig/sglobal/popupmenu/draw.xml
@@ -71,6 +71,11 @@
   <menu:menuitem menu:id=".uno:EnterGroup"/>
   <menu:menuitem menu:id=".uno:LeaveGroup"/>
   <menu:menuseparator/>
+  <menu:menuitem menu:id=".uno:OpenHyperlinkOnCursor"/>
+  <menu:menuitem menu:id=".uno:EditHyperlink"/>
+  <menu:menuitem menu:id=".uno:CopyHyperlinkLocation"/>
+  <menu:menuitem menu:id=".uno:RemoveHyperlink"/>
+  <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:AddTextBox"/>
   <menu:menuitem menu:id=".uno:RemoveTextBox"/>
   <menu:menuitem menu:id=".uno:EditSignatureLine"/>
diff --git a/sw/uiconfig/swform/popupmenu/draw.xml b/sw/uiconfig/swform/popupmenu/draw.xml
index d119c1add5cf..799c02cc5e2e 100644
--- a/sw/uiconfig/swform/popupmenu/draw.xml
+++ b/sw/uiconfig/swform/popupmenu/draw.xml
@@ -71,6 +71,11 @@
   <menu:menuitem menu:id=".uno:EnterGroup"/>
   <menu:menuitem menu:id=".uno:LeaveGroup"/>
   <menu:menuseparator/>
+  <menu:menuitem menu:id=".uno:OpenHyperlinkOnCursor"/>
+  <menu:menuitem menu:id=".uno:EditHyperlink"/>
+  <menu:menuitem menu:id=".uno:CopyHyperlinkLocation"/>
+  <menu:menuitem menu:id=".uno:RemoveHyperlink"/>
+  <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:AddTextBox"/>
   <menu:menuitem menu:id=".uno:RemoveTextBox"/>
   <menu:menuitem menu:id=".uno:EditSignatureLine"/>
diff --git a/sw/uiconfig/swreport/popupmenu/draw.xml b/sw/uiconfig/swreport/popupmenu/draw.xml
index d119c1add5cf..799c02cc5e2e 100644
--- a/sw/uiconfig/swreport/popupmenu/draw.xml
+++ b/sw/uiconfig/swreport/popupmenu/draw.xml
@@ -71,6 +71,11 @@
   <menu:menuitem menu:id=".uno:EnterGroup"/>
   <menu:menuitem menu:id=".uno:LeaveGroup"/>
   <menu:menuseparator/>
+  <menu:menuitem menu:id=".uno:OpenHyperlinkOnCursor"/>
+  <menu:menuitem menu:id=".uno:EditHyperlink"/>
+  <menu:menuitem menu:id=".uno:CopyHyperlinkLocation"/>
+  <menu:menuitem menu:id=".uno:RemoveHyperlink"/>
+  <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:AddTextBox"/>
   <menu:menuitem menu:id=".uno:RemoveTextBox"/>
   <menu:menuitem menu:id=".uno:EditSignatureLine"/>
diff --git a/sw/uiconfig/swriter/popupmenu/draw.xml b/sw/uiconfig/swriter/popupmenu/draw.xml
index d119c1add5cf..799c02cc5e2e 100644
--- a/sw/uiconfig/swriter/popupmenu/draw.xml
+++ b/sw/uiconfig/swriter/popupmenu/draw.xml
@@ -71,6 +71,11 @@
   <menu:menuitem menu:id=".uno:EnterGroup"/>
   <menu:menuitem menu:id=".uno:LeaveGroup"/>
   <menu:menuseparator/>
+  <menu:menuitem menu:id=".uno:OpenHyperlinkOnCursor"/>
+  <menu:menuitem menu:id=".uno:EditHyperlink"/>
+  <menu:menuitem menu:id=".uno:CopyHyperlinkLocation"/>
+  <menu:menuitem menu:id=".uno:RemoveHyperlink"/>
+  <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:AddTextBox"/>
   <menu:menuitem menu:id=".uno:RemoveTextBox"/>
   <menu:menuitem menu:id=".uno:EditSignatureLine"/>
diff --git a/sw/uiconfig/swxform/popupmenu/draw.xml b/sw/uiconfig/swxform/popupmenu/draw.xml
index d119c1add5cf..799c02cc5e2e 100644
--- a/sw/uiconfig/swxform/popupmenu/draw.xml
+++ b/sw/uiconfig/swxform/popupmenu/draw.xml
@@ -71,6 +71,11 @@
   <menu:menuitem menu:id=".uno:EnterGroup"/>
   <menu:menuitem menu:id=".uno:LeaveGroup"/>
   <menu:menuseparator/>
+  <menu:menuitem menu:id=".uno:OpenHyperlinkOnCursor"/>
+  <menu:menuitem menu:id=".uno:EditHyperlink"/>
+  <menu:menuitem menu:id=".uno:CopyHyperlinkLocation"/>
+  <menu:menuitem menu:id=".uno:RemoveHyperlink"/>
+  <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:AddTextBox"/>
   <menu:menuitem menu:id=".uno:RemoveTextBox"/>
   <menu:menuitem menu:id=".uno:EditSignatureLine"/>
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index b69f4565fb13..f9c8b453a617 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -373,9 +373,6 @@ public:
             uno::Reference< container::XNamed > xNamed( xGraphicObjectProperties, uno::UNO_QUERY_THROW );
             xNamed->setName(rDomainMapper.GetGraphicNamingHelper().NameGraphic(sName));
 
-            if ( sHyperlinkURL.getLength() > 0 )
-                xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_HYPER_LINK_U_R_L ),
-                    uno::makeAny ( sHyperlinkURL ));
             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_DESCRIPTION ),
                 uno::makeAny( sAlternativeText ));
             xGraphicObjectProperties->setPropertyValue(getPropertyName( PROP_TITLE ),
@@ -387,6 +384,17 @@ public:
         }
     }
 
+    void applyHyperlink(uno::Reference<beans::XPropertySet> const & xShapeProps, bool bIsShape)
+    {
+        // Graphic objects have a different hyperlink prop than shapes
+        auto aHyperlinkProp = bIsShape ? PROP_HYPERLINK : PROP_HYPER_LINK_U_R_L;
+        if (!sHyperlinkURL.isEmpty())
+        {
+            xShapeProps->setPropertyValue(
+                getPropertyName(aHyperlinkProp), uno::makeAny(sHyperlinkURL));
+        }
+    }
+
     /// Getter for m_aInteropGrabBag, but also merges in the values from other members if they are set.
     comphelper::SequenceAsHashMap const & getInteropGrabBag()
     {
@@ -886,6 +894,7 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue)
                         xShapeProps->setPropertyValue("Surround", uno::makeAny(static_cast<sal_Int32>(m_pImpl->nWrap)));
                         m_pImpl->applyZOrder(xShapeProps);
                         m_pImpl->applyName(xShapeProps);
+                        m_pImpl->applyHyperlink(xShapeProps, bUseShape);
                         xShapeProps->setPropertyValue("AllowOverlap",
                                                       uno::makeAny(m_pImpl->bAllowOverlap));
 
@@ -1412,6 +1421,7 @@ uno::Reference<text::XTextContent> GraphicImport::createGraphicObject(uno::Refer
                         uno::makeAny( awt::Size( m_pImpl->getXSize(), m_pImpl->getYSize() )));
                 m_pImpl->applyMargins(xGraphicObjectProperties);
                 m_pImpl->applyName(xGraphicObjectProperties);
+                m_pImpl->applyHyperlink(xGraphicObjectProperties, false);
             }
 
             // Handle horizontal flip.
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index 6fecf7fe2be4..6d9bdb808e14 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -128,6 +128,7 @@ OUString getPropertyName( PropertyIds eId )
         case PROP_SUB_TYPE              :    sName = "SubType"; break;
         case PROP_FILE_FORMAT           :    sName = "FileFormat"; break;
         case PROP_HYPER_LINK_U_R_L      :    sName = "HyperLinkURL"; break;
+        case PROP_HYPERLINK             :    sName = "Hyperlink"; break;
         case PROP_NUMBER_FORMAT         :    sName = "NumberFormat"; break;
         case PROP_NAME                  :    sName = "Name"; break;
         case PROP_IS_INPUT              :    sName = "IsInput"; break;
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index d511fd737238..347929e54e16 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -185,6 +185,7 @@ enum PropertyIds
         ,PROP_HORI_ORIENT_POSITION
         ,PROP_HORI_ORIENT_RELATION
         ,PROP_HYPER_LINK_U_R_L
+        ,PROP_HYPERLINK
         ,PROP_INDENT_AT
         ,PROP_INPUT_STREAM
         ,PROP_INSERT
diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx
index ddd128d1d8b0..14ec1ca6f4d0 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -167,6 +167,7 @@ static const OUStringLiteral gsVerb( "Verb" );
 static const OUStringLiteral gsSoundURL( "SoundURL" );
 static const OUStringLiteral gsSpeed( "Speed" );
 static const OUStringLiteral gsStarBasic( "StarBasic" );
+static const OUStringLiteral gsHyperlink( "Hyperlink" );
 
 XMLShapeExport::XMLShapeExport(SvXMLExport& rExp,
                                 SvXMLExportPropertyMapper *pExtMapper )
@@ -588,13 +589,26 @@ void XMLShapeExport::exportShape(const uno::Reference< drawing::XShape >& xShape
     }
     sal_Int32 nZIndex = 0;
     uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY );
+    OUString sHyperlink;
+    try
+    {
+        xSet->getPropertyValue(gsHyperlink) >>= sHyperlink;
+    }
+    catch (beans::UnknownPropertyException)
+    {
+    }
 
     std::unique_ptr< SvXMLElementExport >  pHyperlinkElement;
 
-    // export hyperlinks with <a><shape/></a>. Currently only in draw since draw
-    // does not support document events
+    // Need to stash the attributes that are pre-loaded for the shape export
+    // (otherwise they will become attributes of the draw:a element)
+    uno::Reference<xml::sax::XAttributeList> xSaveAttribs(
+        new SvXMLAttributeList(GetExport().GetAttrList()));
+    GetExport().ClearAttrList();
     if( xSet.is() && (GetExport().GetModelType() == SvtModuleOptions::EFactory::DRAW) ) try
     {
+        // export hyperlinks with <a><shape/></a>. Currently only in draw since draw
+        // does not support document events
         presentation::ClickAction eAction = presentation::ClickAction_NONE;
         xSet->getPropertyValue("OnClick") >>= eAction;
 
@@ -617,6 +631,14 @@ void XMLShapeExport::exportShape(const uno::Reference< drawing::XShape >& xShape
     {
         TOOLS_WARN_EXCEPTION("xmloff", "XMLShapeExport::exportShape(): exception during hyperlink export");
     }
+    else if (xSet.is() && !sHyperlink.isEmpty())
+    {
+        mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sHyperlink );
+        mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
+        pHyperlinkElement.reset( new SvXMLElementExport(mrExport, XML_NAMESPACE_DRAW, XML_A, true, true) );
+    }
+    // re-add stashed attributes
+    GetExport().AddAttributeList(xSaveAttribs);
 
     if( xSet.is() )
         xSet->getPropertyValue(gsZIndex) >>= nZIndex;
diff --git a/xmloff/source/text/XMLTextFrameContext.cxx b/xmloff/source/text/XMLTextFrameContext.cxx
index 0f33c760a6ac..7f0ce41a1d74 100644
--- a/xmloff/source/text/XMLTextFrameContext.cxx
+++ b/xmloff/source/text/XMLTextFrameContext.cxx
@@ -1675,6 +1675,10 @@ SvXMLImportContextRef XMLTextFrameContext::CreateChildContext(
         }
         xContext = m_xImplContext->CreateChildContext(p_nPrefix, rLocalName, xAttrList);
     }
+    else if (p_nPrefix == XML_NAMESPACE_DRAW && (IsXMLToken(rLocalName, XML_A)))
+    {
+        xContext = m_xImplContext->CreateChildContext(p_nPrefix, rLocalName, xAttrList);
+    }
     else
     {
         // the child is a drawing shape
diff --git a/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx b/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx
index bd4bdd52be7a..c475543bafec 100644
--- a/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx
+++ b/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx
@@ -19,6 +19,7 @@
 
 #include <sax/tools/converter.hxx>
 
+#include <xmloff/shapeimport.hxx>
 #include <xmloff/xmlimp.hxx>
 #include <xmloff/nmspmap.hxx>
 #include <xmloff/xmlnmspe.hxx>
@@ -26,6 +27,9 @@
 #include "XMLTextFrameContext.hxx"
 #include "XMLTextFrameHyperlinkContext.hxx"
 
+#include <com/sun/star/drawing/XShapes.hpp>
+
+using namespace ::com::sun::star::drawing;
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::text;
 using namespace ::com::sun::star::xml::sax;
@@ -115,6 +119,15 @@ SvXMLImportContextRef XMLTextFrameHyperlinkContext::CreateChildContext(
             pTextFrameContext = new XMLTextFrameContext( GetImport(), nPrefix,
                                                 rLocalName, xAttrList,
                                                 eDefaultAnchorType );
+        else if( IsXMLToken( rLocalName, XML_CUSTOM_SHAPE ) )
+        {
+            Reference<XShapes> xShapes;
+            SvXMLShapeContext* pShapeContext
+                = GetImport().GetShapeImport()->CreateGroupChildContext(GetImport(), nPrefix,
+                                                rLocalName, xAttrList, xShapes);
+            pShapeContext->setHyperlink(sHRef);
+            pContext = pShapeContext;
+        }
     }
 
     if( pTextFrameContext )
@@ -123,9 +136,8 @@ SvXMLImportContextRef XMLTextFrameHyperlinkContext::CreateChildContext(
         pContext = pTextFrameContext;
         xFrameContext = pContext;
     }
-    else
+    else if (!pContext)
         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
-
     return pContext;
 }
 
diff --git a/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx b/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx
index 132db87150f2..5aeb141e6bd0 100644
--- a/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx
+++ b/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx
@@ -30,6 +30,7 @@ namespace com { namespace sun { namespace star {
     namespace beans { class XPropertySet; }
 } } }
 
+/// Used for hyperlinks attached to objects (drawing objects, text boxes, Writer frames)
 class XMLTextFrameHyperlinkContext : public SvXMLImportContext
 {
     OUString              sHRef;


More information about the Libreoffice-commits mailing list