[Libreoffice-commits] core.git: Branch 'libreoffice-4-0' - xmloff/inc xmloff/source

David Tardon dtardon at redhat.com
Fri Jul 19 07:02:10 PDT 2013


 xmloff/inc/xmloff/unointerfacetouniqueidentifiermapper.hxx  |   29 ++++++--
 xmloff/inc/xmloff/xmlmultiimagehelper.hxx                   |    8 +-
 xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx |   41 +++++++++++-
 xmloff/source/core/xmlmultiimagehelper.cxx                  |   10 ++
 xmloff/source/draw/ximpshap.cxx                             |   37 +++++++++-
 5 files changed, 109 insertions(+), 16 deletions(-)

New commits:
commit 31c3ae3e367bb3403935ac04a134771d3c8096a1
Author: David Tardon <dtardon at redhat.com>
Date:   Fri May 3 06:15:30 2013 +0200

    fdo#60075 open drawings with connector attached to SVG
    
    This problem arises when there is a connector attached to draw:frame
    element with multiple draw:image elements in it. The import code expects
    that they are different representations of the same image (I have not
    found if this is specified in ODF), so it only selects the most
    "suitable" for import. To do that, it imports them all and then removes
    all but the selected one. The image import context,
    SdXMLGraphicObjectShapeContext, shares the parent frame's attributes,
    which means that all the images in a frame have got the same ID. in
    SdXMLGraphicObjectShapeContext::AddShape, the created css::draw::XShape
    is registered with its ID... That means that anything that refers to the
    frame's ID, like a draw:connector, will always get the _first_ image in
    the frame.
    
    Solution is to extend comphelper::UnoInterfaceToUniqueIdentifierMapper
    to allow reserving an identifier and setting an interface for it later.
    That way, SdXMLFrameShapeContext can reserve its own ID before it starts
    importing the first draw:image, and then set the selected XShape at the
    end.
    
    (cherry picked from commit 30b248dfe5bfb8a0649e36f22c943b3feb2f1385)
    Signed-off-by: David Tardon <dtardon at redhat.com>
    
    Conflicts:
    	include/xmloff/unointerfacetouniqueidentifiermapper.hxx
    	include/xmloff/xmlmultiimagehelper.hxx
    	xmloff/source/draw/ximpshap.cxx
    
    Change-Id: I2e11cfd38e1e3534df2b3c01d85da0d755a266c3
    Reviewed-on: https://gerrit.libreoffice.org/4982
    Reviewed-by: Fridrich Strba <fridrich at documentfoundation.org>
    Tested-by: Fridrich Strba <fridrich at documentfoundation.org>

diff --git a/xmloff/inc/xmloff/unointerfacetouniqueidentifiermapper.hxx b/xmloff/inc/xmloff/unointerfacetouniqueidentifiermapper.hxx
index 03d3033..5919296 100644
--- a/xmloff/inc/xmloff/unointerfacetouniqueidentifiermapper.hxx
+++ b/xmloff/inc/xmloff/unointerfacetouniqueidentifiermapper.hxx
@@ -24,6 +24,7 @@
 #include "xmloff/dllapi.h"
 #include "sal/types.h"
 
+#include <deque>
 #include <map>
 #include <rtl/ustring.hxx>
 #include <com/sun/star/uno/XInterface.hpp>
@@ -31,43 +32,59 @@
 namespace comphelper
 {
 
-typedef ::std::map< rtl::OUString, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > IdMap_t;
+typedef ::std::map< OUString, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > IdMap_t;
 
 class XMLOFF_DLLPUBLIC UnoInterfaceToUniqueIdentifierMapper
 {
+    typedef std::deque< rtl::OUString > Reserved_t;
+
 public:
     UnoInterfaceToUniqueIdentifierMapper();
 
     /** returns a unique identifier for the given uno object. IF a uno object is
         registered more than once, the returned identifier is always the same.
     */
-    const rtl::OUString& registerReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface );
+    const OUString& registerReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface );
 
     /** registers the given uno object with the given identifier.
 
         @returns
             false, if the given identifier already exists and is not associated with the given interface
     */
-    bool registerReference( const rtl::OUString& rIdentifier, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface );
+    bool registerReference( const OUString& rIdentifier, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface );
+
+    /** reserves an identifier for later registration.
+
+        @returns
+            false, if the identifier already exists
+      */
+    bool reserveIdentifier( const rtl::OUString& rIdentifier );
+
+    /** registers the given uno object with reserved identifier.
+      */
+    bool registerReservedReference( const rtl::OUString& rIdentifier, const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& rInterface );
 
     /** @returns
             the identifier for the given uno object. If this uno object is not already
             registered, an empty string is returned
     */
-    const rtl::OUString& getIdentifier( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface ) const;
+    const OUString& getIdentifier( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface ) const;
 
     /** @returns
         the uno object that is registered with the given identifier. If no uno object
         is registered with the given identifier, an empty reference is returned.
     */
-    const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& getReference( const rtl::OUString& rIdentifier ) const;
+    const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& getReference( const OUString& rIdentifier ) const;
 
 private:
     bool findReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rInterface, IdMap_t::const_iterator& rIter ) const;
-    bool findIdentifier( const rtl::OUString& rIdentifier, IdMap_t::const_iterator& rIter ) const;
+    bool findIdentifier( const OUString& rIdentifier, IdMap_t::const_iterator& rIter ) const;
+    bool findReserved( const OUString& rIdentifier ) const;
+    bool findReserved( const OUString& rIdentifier, Reserved_t::const_iterator& rIter ) const;
 
     IdMap_t	maEntries;
     sal_Int32 mnNextId;
+    Reserved_t maReserved;
 };
 
 }
diff --git a/xmloff/inc/xmloff/xmlmultiimagehelper.hxx b/xmloff/inc/xmloff/xmlmultiimagehelper.hxx
index 4628677..bbe9ce1 100644
--- a/xmloff/inc/xmloff/xmlmultiimagehelper.hxx
+++ b/xmloff/inc/xmloff/xmlmultiimagehelper.hxx
@@ -33,7 +33,7 @@ private:
 
 protected:
     /// helper to get the created xShape instance, needs to be overloaded
-    virtual rtl::OUString getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const = 0;
+    virtual OUString getGraphicURLFromImportContext(const SvXMLImportContext& rContext) const = 0;
     virtual void removeGraphicFromImportContext(const SvXMLImportContext& rContext) const = 0;
 
 public:
@@ -41,8 +41,10 @@ public:
     virtual ~multiImageImportHelper();
 
     /// solve multiple imported images. The most valuable one is choosen,
-    /// see imlementation for evtl. changing weights and/or adding filetypes
-    void solveMultipleImages();
+    /// see imlementation for evtl. changing weights and/or adding filetypes.
+    ///
+    /// @returns import context of the selected image
+    const SvXMLImportContext* solveMultipleImages();
 
     /// add a content to the remembered image import contexts
     void addContent(const SvXMLImportContext& rSvXMLImportContext);
diff --git a/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx b/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx
index 4b1d133..b76b8a8 100644
--- a/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx
+++ b/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx
@@ -17,6 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <algorithm>
 
 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
 
@@ -72,7 +73,7 @@ bool UnoInterfaceToUniqueIdentifierMapper::registerReference( const OUString& rI
     {
         return rIdentifier != (*aIter).first;
     }
-    else if( findIdentifier( rIdentifier, aIter ) )
+    else if( findIdentifier( rIdentifier, aIter ) || findReserved( rIdentifier ) )
     {
         return false;
     }
@@ -174,6 +175,44 @@ bool UnoInterfaceToUniqueIdentifierMapper::findIdentifier( const OUString& rIden
     return rIter != maEntries.end();
 }
 
+bool UnoInterfaceToUniqueIdentifierMapper::reserveIdentifier( const rtl::OUString& rIdentifier )
+{
+    if ( findReserved( rIdentifier ) )
+        return false;
+
+    maReserved.push_back( rIdentifier );
+    return true;
+}
+
+bool UnoInterfaceToUniqueIdentifierMapper::registerReservedReference(
+        const rtl::OUString& rIdentifier,
+        const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& rInterface )
+{
+    Reserved_t::const_iterator aIt;
+    if ( !findReserved( rIdentifier, aIt ) )
+        return false;
+
+    Reserved_t::iterator aRemoveIt( maReserved.begin() + ( aIt - maReserved.begin() ) );
+    maReserved.erase( aRemoveIt );
+    registerReference( rIdentifier, rInterface );
+
+    return true;
+}
+
+bool UnoInterfaceToUniqueIdentifierMapper::findReserved( const OUString& rIdentifier ) const
+{
+    Reserved_t::const_iterator aDummy;
+    return findReserved( rIdentifier, aDummy );
+}
+
+bool UnoInterfaceToUniqueIdentifierMapper::findReserved(
+        const OUString& rIdentifier,
+        Reserved_t::const_iterator& rIter ) const
+{
+    rIter = std::find( maReserved.begin(), maReserved.end(), rIdentifier );
+    return rIter != maReserved.end();
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/core/xmlmultiimagehelper.cxx b/xmloff/source/core/xmlmultiimagehelper.cxx
index c2214f2..5b9b9f5 100644
--- a/xmloff/source/core/xmlmultiimagehelper.cxx
+++ b/xmloff/source/core/xmlmultiimagehelper.cxx
@@ -89,8 +89,9 @@ multiImageImportHelper::~multiImageImportHelper()
     }
 }
 
-void multiImageImportHelper::solveMultipleImages()
+const SvXMLImportContext* multiImageImportHelper::solveMultipleImages()
 {
+    const SvXMLImportContext* pContext(0);
     if(maImplContextVector.size() > 1)
     {
         // multiple child contexts were imported, decide which is the most valuable one
@@ -118,6 +119,7 @@ void multiImageImportHelper::solveMultipleImages()
 
         // Take out the most valuable one
         const std::vector< SvXMLImportContextRef* >::iterator aRemove(maImplContextVector.begin() + nIndexOfPreferred);
+        pContext = **aRemove;
         delete *aRemove;
         maImplContextVector.erase(aRemove);
 
@@ -127,6 +129,12 @@ void multiImageImportHelper::solveMultipleImages()
             removeGraphicFromImportContext(**maImplContextVector[a]);
         }
     }
+    else if (maImplContextVector.size() == 1)
+    {
+        pContext = *maImplContextVector.front();
+    }
+
+    return pContext;
 }
 
 void multiImageImportHelper::addContent(const SvXMLImportContext& rSvXMLImportContext)
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index e52736c..d60b74d 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -17,6 +17,8 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <cassert>
+
 #include <tools/debug.hxx>
 #include <com/sun/star/document/XEventsSupplier.hpp>
 #include <com/sun/star/container/XNameReplace.hpp>
@@ -3455,6 +3457,9 @@ SvXMLImportContext *SdXMLFrameShapeContext::CreateChildContext( sal_uInt16 nPref
 
         if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(pContext))
         {
+            if ( !maShapeId.isEmpty() )
+                GetImport().getInterfaceToIdentifierMapper().reserveIdentifier( maShapeId );
+
             addContent(*mxImplContext);
         }
     }
@@ -3528,8 +3533,15 @@ void SdXMLFrameShapeContext::StartElement(const uno::Reference< xml::sax::XAttri
 
 void SdXMLFrameShapeContext::EndElement()
 {
-    /// solve if multiple image child contexts were imported
-    solveMultipleImages();
+    // solve if multiple image child contexts were imported
+    const SvXMLImportContext* const pSelectedContext(solveMultipleImages());
+    const SdXMLGraphicObjectShapeContext* pShapeContext( dynamic_cast<const SdXMLGraphicObjectShapeContext*>( pSelectedContext ) );
+    if ( pShapeContext )
+    {
+        assert( mxImplContext.Is() );
+        const uno::Reference< uno::XInterface > xShape( pShapeContext->getShape() );
+        GetImport().getInterfaceToIdentifierMapper().registerReservedReference( maShapeId, xShape );
+    }
 
     if( !mxImplContext.Is() )
     {
@@ -3590,10 +3602,25 @@ void SdXMLFrameShapeContext::EndElement()
     SdXMLShapeContext::EndElement();
 }
 
-void SdXMLFrameShapeContext::processAttribute( sal_uInt16,
-        const ::rtl::OUString&, const ::rtl::OUString& )
+void SdXMLFrameShapeContext::processAttribute( sal_uInt16 nPrefix,
+        const ::rtl::OUString& rLocalName, const ::rtl::OUString& rValue )
 {
-    // ignore
+    bool bId( false );
+
+    switch ( nPrefix )
+    {
+        case XML_NAMESPACE_DRAW :
+        case XML_NAMESPACE_DRAW_EXT :
+            bId = IsXMLToken( rLocalName, XML_ID );
+            break;
+        case XML_NAMESPACE_NONE :
+        case XML_NAMESPACE_XML :
+            bId = IsXMLToken( rLocalName, XML_ID );
+            break;
+    }
+
+    if ( bId )
+        SdXMLShapeContext::processAttribute( nPrefix, rLocalName, rValue );
 }
 
 TYPEINIT1( SdXMLCustomShapeContext, SdXMLShapeContext );


More information about the Libreoffice-commits mailing list