[Libreoffice-commits] .: basic/source dbaccess/source svtools/inc svtools/source

Noel Power noelp at kemper.freedesktop.org
Mon Aug 22 07:43:41 PDT 2011


 basic/source/uno/dlgcont.cxx                         |   33 ------
 dbaccess/source/core/dataaccess/databasedocument.cxx |  104 +++++++++++++++++++
 svtools/inc/svtools/grfmgr.hxx                       |    5 
 svtools/source/graphic/grfmgr.cxx                    |   40 +++++++
 4 files changed, 151 insertions(+), 31 deletions(-)

New commits:
commit 117281ba12e703fcd04ca87309dfd4a31432d1c5
Author: Noel Power <noel.power at novell.com>
Date:   Mon Aug 22 15:41:30 2011 +0100

    fix leaking 'Pictures' streams from basic dialogs in base
    
    With database document, any contents of the Pictures folder ( afaics only basic dialogs store content here ) is never cleaned up between saves.

diff --git a/basic/source/uno/dlgcont.cxx b/basic/source/uno/dlgcont.cxx
index b4f4470..6378a95 100644
--- a/basic/source/uno/dlgcont.cxx
+++ b/basic/source/uno/dlgcont.cxx
@@ -55,7 +55,7 @@
 #include <cppuhelper/factory.hxx>
 #include <svtools/sfxecode.hxx>
 #include <svtools/ehdl.hxx>
-
+#include <svtools/grfmgr.hxx>
 
 namespace basic
 {
@@ -229,35 +229,6 @@ void SAL_CALL SfxDialogLibraryContainer::writeLibraryElement
     xInput->closeInput();
 }
 
-void lcl_deepInspectForEmbeddedImages( const Reference< XInterface >& xIf,  std::vector< rtl::OUString >& rvEmbedImgUrls )
-{
-    static rtl::OUString sImageURL= OUString(RTL_CONSTASCII_USTRINGPARAM( "ImageURL" ) );
-    Reference< beans::XPropertySet > xProps( xIf, UNO_QUERY );
-    if ( xProps.is() )
-    {
-
-        if ( xProps->getPropertySetInfo()->hasPropertyByName( sImageURL ) )
-        {
-            rtl::OUString sURL;
-            xProps->getPropertyValue( sImageURL ) >>= sURL;
-            if ( sURL.getLength() && sURL.compareToAscii( GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( GRAPHOBJ_URLPREFIX ) ) == 0 )
-                rvEmbedImgUrls.push_back( sURL );
-        }
-    }
-    Reference< XNameContainer > xContainer( xIf, UNO_QUERY );
-    if ( xContainer.is() )
-    {
-        Sequence< rtl::OUString > sNames = xContainer->getElementNames();
-        sal_Int32 nContainees = sNames.getLength();
-        for ( sal_Int32 index = 0; index < nContainees; ++index )
-        {
-            Reference< XInterface > xCtrl;
-            xContainer->getByName( sNames[ index ] ) >>= xCtrl;
-            lcl_deepInspectForEmbeddedImages( xCtrl, rvEmbedImgUrls );
-        }
-    }
-}
-
 void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference< embed::XStorage >& xStorage ) throw ( RuntimeException )
 {
     LibraryContainerMethodGuard aGuard( *this );
@@ -315,7 +286,7 @@ void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference< e
                     OSL_VERIFY( xProps->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext );
                     ::xmlscript::importDialogModel( xInput, xDialogModel, xContext, mxOwnerDocument );
                     std::vector< rtl::OUString > vEmbeddedImageURLs;
-                    lcl_deepInspectForEmbeddedImages( Reference< XInterface >( xDialogModel, UNO_QUERY ),  vEmbeddedImageURLs );
+                    GraphicObject::InspectForGraphicObjectImageURL( Reference< XInterface >( xDialogModel, UNO_QUERY ),  vEmbeddedImageURLs );
                     if ( !vEmbeddedImageURLs.empty() )
                     {
                         // Export the images to the storage
diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx
index d8132a5..37f6091 100644
--- a/dbaccess/source/core/dataaccess/databasedocument.cxx
+++ b/dbaccess/source/core/dataaccess/databasedocument.cxx
@@ -64,6 +64,12 @@
 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
 #include <com/sun/star/ucb/XContent.hpp>
 #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+
+#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/awt/XDialogProvider.hpp>
+#include <com/sun/star/document/XGraphicObjectResolver.hpp>
+
 /** === end UNO includes === **/
 
 #include <comphelper/documentconstants.hxx>
@@ -95,6 +101,7 @@
 #include <functional>
 #include <list>
 
+#include <svtools/grfmgr.hxx>
 #define MAP_LEN(x) x, sizeof(x) - 1
 
 using namespace ::com::sun::star::uno;
@@ -384,6 +391,85 @@ namespace
     }
 }
 
+static rtl::OUString sPictures( RTL_CONSTASCII_USTRINGPARAM("Pictures") );
+
+// base documents seem to have a different behaviour to other documents, the
+// root storage contents at least seem to be re-used over different saves, thus if there is a
+// top level Picture directory it is never cleared.
+// If we delete the 'Pictures' directory then the dialog library storage which does store
+// any embed images will not work properly. ( this is due to the fact it will
+// try to load the dialog which will try and access the embed images, if those images are not cached in
+//  memory it will try to read them from the Picture directory which is now gone, so... we have to use this
+// inglorious hack below which basically will
+// a) create a temp storage
+// b) introspect any dialogs for any embed graphics and grab the associate URL(s)
+// c) populate the temp storage with the associated embed images ( will be stored in a 'Pictures' folder )
+// d) delete the 'Picture' element from the root storage
+// e) copy the Pictures element of the temp storage to the root storage
+//
+// this assumes that we don't use the Pictures folder in the root of the base
+// document for anything, I believe this is a valid assumption ( as much as
+// I could check anyway )
+
+void lcl_uglyHackToStoreDialogeEmbedImages( const Reference< XStorageBasedLibraryContainer >& xDlgCont, const Reference< XStorage >& xStorage, const Reference< XModel >& rxModel, const ::comphelper::ComponentContext& aContext ) throw ( RuntimeException )
+{
+    Sequence< rtl::OUString > sLibraries = xDlgCont->getElementNames();
+    Reference< XStorage > xTmpPic = xStorage->openStorageElement( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("tempPictures") ), ElementModes::READWRITE  );
+
+    std::vector< rtl::OUString > vEmbedImgUrls;
+    for ( sal_Int32 i=0; i < sLibraries.getLength(); ++i )
+    {
+        rtl::OUString sLibrary( sLibraries[ i ] );
+        xDlgCont->loadLibrary( sLibrary );
+        Reference< XNameContainer > xLib;
+        xDlgCont->getByName( sLibrary ) >>= xLib;
+        if ( xLib.is() )
+        {
+            Sequence< rtl::OUString > sDialogs = xLib->getElementNames();
+            sal_Int32 nDialogs( sDialogs.getLength() );
+            for ( sal_Int32 j=0; j < nDialogs; ++j )
+            {
+                Reference < ::com::sun::star::awt::XDialogProvider > xDlgPrv;
+                Sequence< Any > aArgs(1);
+                aArgs[ 0 ] <<= rxModel;
+                xDlgPrv.set( aContext.createComponentWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.DialogProvider")) , aArgs), UNO_QUERY );
+                rtl::OUString sDialogUrl = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.script:") );
+                sDialogUrl = sDialogUrl.concat( sLibraries[ i ] ).concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("." ) ) ).concat (  sDialogs[ j ]  ).concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("?location=document") ) );
+
+                Reference< ::com::sun::star::awt::XControl > xDialog( xDlgPrv->createDialog( sDialogUrl ), UNO_QUERY );
+                Reference< XInterface > xModel = xDialog->getModel();
+                GraphicObject::InspectForGraphicObjectImageURL( xModel, vEmbedImgUrls );
+            }
+        }
+    }
+    // if we have any image urls, make sure we copy the associated images into tempPictures
+    if ( vEmbedImgUrls.size() )
+    {
+        // Export the images to the storage
+        Sequence< Any > aArgs( 1 );
+        aArgs[ 0 ] <<= xTmpPic;
+        Reference< XGraphicObjectResolver > xGraphicResolver(
+                aContext.createComponentWithArguments( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Svx.GraphicExportHelper" ) ), aArgs ), UNO_QUERY );
+        std::vector< rtl::OUString >::iterator it = vEmbedImgUrls.begin();
+        std::vector< rtl::OUString >::iterator it_end = vEmbedImgUrls.end();
+        if ( xGraphicResolver.is() )
+        {
+            for ( sal_Int32 count = 0; it != it_end; ++it, ++count )
+                xGraphicResolver->resolveGraphicObjectURL( *it );
+        }
+
+        // delete old 'Pictures' storage and copy the contents of tempPictures into xStorage
+        xStorage->removeElement( sPictures );
+        xTmpPic->copyElementTo( sPictures, xStorage, sPictures );
+    }
+    else
+    {
+        // clean up an existing Pictures dir
+        if ( xStorage->isStorageElement( sPictures ) )
+            xStorage->removeElement( sPictures );
+    }
+}
+
 void ODatabaseDocument::impl_setInitialized()
 {
     m_eInitState = Initialized;
@@ -1600,6 +1686,24 @@ void ODatabaseDocument::impl_writeStorage_throw( const Reference< XStorage >& _r
     WriteThroughComponent( xComponent, "content.xml", "com.sun.star.comp.sdb.DBExportFilter",
         aDelegatorArguments, aMediaDescriptor, _rxTargetStorage );
 
+    if ( _rxTargetStorage->hasByName ( sPictures ) )
+    {
+        try
+        {
+           // Delete any previously existing Pictures folder and regenerate
+           // any needed content if needed
+           Reference< XStorageBasedLibraryContainer > xDlgs = m_pImpl->getLibraryContainer( false );
+           if ( xDlgs.is() )
+           {
+               Reference< XModel > xModel(const_cast< ODatabaseDocument*>(this));
+               lcl_uglyHackToStoreDialogeEmbedImages( m_pImpl->getLibraryContainer(false), _rxTargetStorage, xModel, m_pImpl->m_aContext );
+           }
+       }
+       catch ( const Exception& )
+       {
+            DBG_UNHANDLED_EXCEPTION();
+       }
+    }
     m_pImpl->storeLibraryContainersTo( _rxTargetStorage );
 }
 
diff --git a/svtools/inc/svtools/grfmgr.hxx b/svtools/inc/svtools/grfmgr.hxx
index 25d8929..f43aec4 100644
--- a/svtools/inc/svtools/grfmgr.hxx
+++ b/svtools/inc/svtools/grfmgr.hxx
@@ -536,6 +536,11 @@ public:
     friend SvStream&        operator>>( SvStream& rIStm, GraphicObject& rGraphicObj );
 
     static GraphicObject    CreateGraphicObjectFromURL( const ::rtl::OUString &rURL );
+    // will inspect an object ( e.g. a control ) for any 'ImageURL'
+    // properties and return these in a vector. Note: this implementation
+    // will cater for XNameContainer objects and deepinspect any containees
+    // if they exist
+    static void InspectForGraphicObjectImageURL( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIf, std::vector< rtl::OUString >& rvEmbedImgUrls );
 };
 
 // ------------------
diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx
index f41b26e..43b8687 100644
--- a/svtools/source/graphic/grfmgr.cxx
+++ b/svtools/source/graphic/grfmgr.cxx
@@ -47,9 +47,19 @@
 
 #include <vcl/pdfextoutdevdata.hxx>
 
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
 #define WATERMARK_LUM_OFFSET                50
 #define WATERMARK_CON_OFFSET                -70
 
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Sequence;
+using com::sun::star::container::XNameContainer;
+using com::sun::star::beans::XPropertySet;
+
 GraphicManager* GraphicObject::mpGlobalMgr = NULL;
 
 struct GrfSimpleCacheObj
@@ -1183,4 +1193,34 @@ GraphicObject GraphicObject::CreateGraphicObjectFromURL( const ::rtl::OUString &
     }
 }
 
+void
+GraphicObject::InspectForGraphicObjectImageURL( const Reference< XInterface >& xIf,  std::vector< rtl::OUString >& rvEmbedImgUrls )
+{
+    static rtl::OUString sImageURL(RTL_CONSTASCII_USTRINGPARAM( "ImageURL" ) );
+    Reference< XPropertySet > xProps( xIf, UNO_QUERY );
+    if ( xProps.is() )
+    {
+
+        if ( xProps->getPropertySetInfo()->hasPropertyByName( sImageURL ) )
+        {
+            rtl::OUString sURL;
+            xProps->getPropertyValue( sImageURL ) >>= sURL;
+            if ( sURL.getLength() && sURL.compareToAscii( UNO_NAME_GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( UNO_NAME_GRAPHOBJ_URLPREFIX ) ) == 0 )
+                rvEmbedImgUrls.push_back( sURL );
+        }
+    }
+    Reference< XNameContainer > xContainer( xIf, UNO_QUERY );
+    if ( xContainer.is() )
+    {
+        Sequence< rtl::OUString > sNames = xContainer->getElementNames();
+        sal_Int32 nContainees = sNames.getLength();
+        for ( sal_Int32 index = 0; index < nContainees; ++index )
+        {
+            Reference< XInterface > xCtrl;
+            xContainer->getByName( sNames[ index ] ) >>= xCtrl;
+            InspectForGraphicObjectImageURL( xCtrl, rvEmbedImgUrls );
+        }
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list