[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