Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / basic / source / uno / dlgcont.cxx
blobe066b000a078505fb5bdf130dbb176fe4cb5b7d0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/container/XNameContainer.hpp>
21 #include <com/sun/star/xml/sax/Parser.hpp>
22 #include <com/sun/star/xml/sax/InputSource.hpp>
23 #include <com/sun/star/xml/sax/Writer.hpp>
24 #include <com/sun/star/io/XOutputStream.hpp>
25 #include <com/sun/star/io/XInputStream.hpp>
26 #include <com/sun/star/io/XInputStreamProvider.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
29 #include <com/sun/star/resource/StringResourceWithStorage.hpp>
30 #include <com/sun/star/resource/StringResourceWithLocation.hpp>
31 #include <com/sun/star/document/GraphicStorageHandler.hpp>
32 #include <com/sun/star/document/XGraphicStorageHandler.hpp>
33 #include <dlgcont.hxx>
34 #include <comphelper/fileformat.h>
35 #include <comphelper/processfactory.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/settings.hxx>
39 #include <xmlscript/xmldlg_imexp.hxx>
40 #include <sot/storage.hxx>
41 #include <svtools/sfxecode.hxx>
42 #include <svtools/ehdl.hxx>
43 #include <vcl/GraphicObject.hxx>
44 #include <i18nlangtag/languagetag.hxx>
46 namespace basic
49 using namespace com::sun::star::document;
50 using namespace com::sun::star::container;
51 using namespace com::sun::star::io;
52 using namespace com::sun::star::uno;
53 using namespace com::sun::star::ucb;
54 using namespace com::sun::star::lang;
55 using namespace com::sun::star::script;
56 using namespace com::sun::star::xml::sax;
57 using namespace com::sun::star;
58 using namespace cppu;
60 using com::sun::star::uno::Reference;
63 // Implementation class SfxDialogLibraryContainer
65 const sal_Char* SfxDialogLibraryContainer::getInfoFileName() const { return "dialog"; }
66 const sal_Char* SfxDialogLibraryContainer::getOldInfoFileName() const { return "dialogs"; }
67 const sal_Char* SfxDialogLibraryContainer::getLibElementFileExtension() const { return "xdl"; }
68 const sal_Char* SfxDialogLibraryContainer::getLibrariesDir() const { return "Dialogs"; }
70 // Ctor for service
71 SfxDialogLibraryContainer::SfxDialogLibraryContainer()
73 // all initialisation has to be done
74 // by calling XInitialization::initialize
77 SfxDialogLibraryContainer::SfxDialogLibraryContainer( const uno::Reference< embed::XStorage >& xStorage )
79 init( OUString(), xStorage );
82 // Methods to get library instances of the correct type
83 SfxLibrary* SfxDialogLibraryContainer::implCreateLibrary( const OUString& aName )
85 SfxLibrary* pRet = new SfxDialogLibrary( maModifiable, aName, mxSFI, this );
86 return pRet;
89 SfxLibrary* SfxDialogLibraryContainer::implCreateLibraryLink
90 ( const OUString& aName, const OUString& aLibInfoFileURL,
91 const OUString& StorageURL, bool ReadOnly )
93 SfxLibrary* pRet = new SfxDialogLibrary
94 ( maModifiable, aName, mxSFI, aLibInfoFileURL, StorageURL, ReadOnly, this );
95 return pRet;
98 Any SfxDialogLibraryContainer::createEmptyLibraryElement()
100 Reference< XInputStreamProvider > xISP;
101 Any aRetAny;
102 aRetAny <<= xISP;
103 return aRetAny;
106 bool SfxDialogLibraryContainer::isLibraryElementValid(const Any& rElement) const
108 return SfxDialogLibrary::containsValidDialog(rElement);
111 static bool writeOasis2OOoLibraryElement(
112 const Reference< XInputStream >& xInput, const Reference< XOutputStream >& xOutput )
114 Reference< XComponentContext > xContext(
115 comphelper::getProcessComponentContext() );
117 Reference< lang::XMultiComponentFactory > xSMgr(
118 xContext->getServiceManager() );
120 Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
122 Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
124 xWriter->setOutputStream( xOutput );
126 Sequence<Any> aArgs( 1 );
127 aArgs[0] <<= xWriter;
129 Reference< xml::sax::XDocumentHandler > xHandler(
130 xSMgr->createInstanceWithArgumentsAndContext(
131 "com.sun.star.comp.Oasis2OOoTransformer",
132 aArgs, xContext ),
133 UNO_QUERY );
135 xParser->setDocumentHandler( xHandler );
137 xml::sax::InputSource source;
138 source.aInputStream = xInput;
139 source.sSystemId = "virtual file";
141 xParser->parseStream( source );
143 return true;
146 void SfxDialogLibraryContainer::writeLibraryElement
148 const Reference < XNameContainer >& xLib,
149 const OUString& aElementName,
150 const Reference< XOutputStream >& xOutput
153 Any aElement = xLib->getByName( aElementName );
154 Reference< XInputStreamProvider > xISP;
155 aElement >>= xISP;
156 if( !xISP.is() )
157 return;
159 Reference< XInputStream > xInput( xISP->createInputStream() );
161 bool bComplete = false;
162 if ( mbOasis2OOoFormat )
164 bComplete = writeOasis2OOoLibraryElement( xInput, xOutput );
167 if ( !bComplete )
169 Sequence< sal_Int8 > bytes;
170 sal_Int32 nRead = xInput->readBytes( bytes, xInput->available() );
171 for (;;)
173 if( nRead )
174 xOutput->writeBytes( bytes );
176 nRead = xInput->readBytes( bytes, 1024 );
177 if (! nRead)
178 break;
181 xInput->closeInput();
184 void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference< embed::XStorage >& xStorage )
186 LibraryContainerMethodGuard aGuard( *this );
187 mbOasis2OOoFormat = false;
189 if ( mxStorage.is() && xStorage.is() )
193 long nSource = SotStorage::GetVersion( mxStorage );
194 long nTarget = SotStorage::GetVersion( xStorage );
196 if ( nSource == SOFFICE_FILEFORMAT_CURRENT &&
197 nTarget != SOFFICE_FILEFORMAT_CURRENT )
199 mbOasis2OOoFormat = true;
202 catch (const Exception& )
204 // if we cannot get the version then the
205 // Oasis2OOoTransformer will not be used
206 OSL_ASSERT(false);
210 SfxLibraryContainer::storeLibrariesToStorage( xStorage );
212 // we need to export out any embedded image object(s)
213 // associated with any Dialogs. First, we need to actually gather any such urls
214 // for each dialog in this container
215 Sequence< OUString > sLibraries = getElementNames();
216 for ( sal_Int32 i=0; i < sLibraries.getLength(); ++i )
218 loadLibrary( sLibraries[ i ] );
219 Reference< XNameContainer > xLib;
220 getByName( sLibraries[ i ] ) >>= xLib;
221 if ( xLib.is() )
223 Sequence< OUString > sDialogs = xLib->getElementNames();
224 sal_Int32 nDialogs( sDialogs.getLength() );
225 for ( sal_Int32 j=0; j < nDialogs; ++j )
227 // Each Dialog has an associated xISP
228 Reference< io::XInputStreamProvider > xISP;
229 xLib->getByName( sDialogs[ j ] ) >>= xISP;
230 if ( xISP.is() )
232 Reference< io::XInputStream > xInput( xISP->createInputStream() );
233 Reference< XNameContainer > xDialogModel(
234 mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", mxContext),
235 UNO_QUERY );
236 ::xmlscript::importDialogModel( xInput, xDialogModel, mxContext, mxOwnerDocument );
237 std::vector<uno::Reference<graphic::XGraphic>> vxGraphicList;
238 vcl::graphic::SearchForGraphics(Reference<XInterface>(xDialogModel, UNO_QUERY), vxGraphicList);
239 if (!vxGraphicList.empty())
241 // Export the images to the storage
242 Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
243 xGraphicStorageHandler.set(document::GraphicStorageHandler::createWithStorage(mxContext, xStorage));
244 if (xGraphicStorageHandler.is())
246 for (uno::Reference<graphic::XGraphic> const & rxGraphic : vxGraphicList)
248 xGraphicStorageHandler->saveGraphic(rxGraphic);
256 mbOasis2OOoFormat = false;
260 Any SfxDialogLibraryContainer::importLibraryElement
261 ( const Reference < XNameContainer >& /*xLib*/,
262 const OUString& /*aElementName */, const OUString& aFile,
263 const uno::Reference< io::XInputStream >& xElementStream )
265 Any aRetAny;
267 // TODO: Member because later it will be a component
268 //Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() );
269 //if( !xMSF.is() )
271 // OSL_FAIL( "### couldn't get ProcessServiceFactory" );
272 // return aRetAny;
275 Reference< XParser > xParser = xml::sax::Parser::create( mxContext );
277 Reference< XNameContainer > xDialogModel(
278 mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", mxContext),
279 UNO_QUERY );
280 if( !xDialogModel.is() )
282 OSL_FAIL( "### couldn't create com.sun.star.awt.UnoControlDialogModel component" );
283 return aRetAny;
286 // Read from storage?
287 bool bStorage = xElementStream.is();
288 Reference< XInputStream > xInput;
290 if( bStorage )
292 xInput = xElementStream;
294 else
298 xInput = mxSFI->openFileRead( aFile );
300 catch(const Exception& )
301 //catch( Exception& e )
303 // TODO:
304 //throw WrappedTargetException( e );
307 if( !xInput.is() )
308 return aRetAny;
310 InputSource source;
311 source.aInputStream = xInput;
312 source.sSystemId = aFile;
314 try {
315 // start parsing
316 xParser->setDocumentHandler( ::xmlscript::importDialogModel( xDialogModel, mxContext, mxOwnerDocument ) );
317 xParser->parseStream( source );
319 catch(const Exception& )
321 OSL_FAIL( "Parsing error" );
322 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile );
323 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
324 return aRetAny;
327 // Create InputStream, TODO: Implement own InputStreamProvider
328 // to avoid creating the DialogModel here!
329 Reference< XInputStreamProvider > xISP = ::xmlscript::exportDialogModel( xDialogModel, mxContext, mxOwnerDocument );
330 aRetAny <<= xISP;
331 return aRetAny;
334 void SfxDialogLibraryContainer::importFromOldStorage( const OUString& )
336 // Nothing to do here, old dialogs cannot be imported
339 SfxLibraryContainer* SfxDialogLibraryContainer::createInstanceImpl()
341 return new SfxDialogLibraryContainer();
344 const char aResourceFileNameBase[] = "DialogStrings";
345 const char aResourceFileCommentBase[] = "# Strings for Dialog Library ";
347 // Resource handling
348 Reference< css::resource::XStringResourcePersistence >
349 SfxDialogLibraryContainer::implCreateStringResource( SfxDialogLibrary* pDialogLibrary )
351 Reference< resource::XStringResourcePersistence > xRet;
352 OUString aLibName = pDialogLibrary->getName();
353 bool bReadOnly = pDialogLibrary->mbReadOnly;
355 // get ui locale
356 ::com::sun ::star::lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
358 OUString aComment= aResourceFileCommentBase + aLibName;
360 bool bStorage = mxStorage.is();
361 if( bStorage )
363 uno::Reference< embed::XStorage > xLibrariesStor;
364 uno::Reference< embed::XStorage > xLibraryStor;
365 try {
366 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
367 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
368 if ( !xLibrariesStor.is() )
369 throw uno::RuntimeException("null returned from openStorageElement");
371 xLibraryStor = xLibrariesStor->openStorageElement( aLibName, embed::ElementModes::READ );
372 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
373 if ( !xLibraryStor.is() )
374 throw uno::RuntimeException("null returned from openStorageElement");
376 catch(const uno::Exception& )
378 // Something went wrong while trying to get the storage library.
379 // Return an object that supports StringResourceWithStorage, give it a storage location later.
380 xRet = Reference< resource::XStringResourcePersistence >(
381 mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.resource.StringResourceWithStorage", mxContext),
382 UNO_QUERY );
383 return xRet;
386 xRet = resource::StringResourceWithStorage::create(mxContext, xLibraryStor, bReadOnly, aLocale, aResourceFileNameBase, aComment);
388 else
390 OUString aLocation = createAppLibraryFolder( pDialogLibrary, aLibName );
391 // TODO: Real handler?
392 Reference< task::XInteractionHandler > xDummyHandler;
394 xRet = resource::StringResourceWithLocation::create(mxContext, aLocation, bReadOnly, aLocale, aResourceFileNameBase, aComment, xDummyHandler);
397 return xRet;
400 void SfxDialogLibraryContainer::onNewRootStorage()
402 // the library container is not modified, go through the libraries and check whether they are modified
403 Sequence< OUString > aNames = maNameContainer->getElementNames();
404 const OUString* pNames = aNames.getConstArray();
405 sal_Int32 nNameCount = aNames.getLength();
407 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
409 OUString aName = pNames[ i ];
410 SfxDialogLibrary* pDialogLibrary = static_cast<SfxDialogLibrary*>( getImplLib( aName ) );
412 Reference< resource::XStringResourcePersistence > xStringResourcePersistence =
413 pDialogLibrary->getStringResourcePersistence();
415 if( xStringResourcePersistence.is() )
417 Reference< embed::XStorage > xLibrariesStor;
418 Reference< embed::XStorage > xLibraryStor;
419 try {
420 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READWRITE );
421 if ( !xLibrariesStor.is() )
422 throw uno::RuntimeException("null returned from openStorageElement");
424 OUString aLibName = pDialogLibrary->getName();
425 xLibraryStor = xLibrariesStor->openStorageElement( aLibName, embed::ElementModes::READWRITE );
426 if ( !xLibraryStor.is() )
427 throw uno::RuntimeException("null returned from openStorageElement");
429 Reference< resource::XStringResourceWithStorage >
430 xStringResourceWithStorage( xStringResourcePersistence, UNO_QUERY );
431 if( xStringResourceWithStorage.is() )
432 xStringResourceWithStorage->setStorage( xLibraryStor );
434 catch(const uno::Exception& )
436 // TODO: Error handling?
442 sal_Bool SAL_CALL
443 SfxDialogLibraryContainer:: HasExecutableCode( const OUString& /*Library*/ )
445 return false; // dialog library has no executable code
448 // Service
450 OUString SAL_CALL SfxDialogLibraryContainer::getImplementationName( )
452 return "com.sun.star.comp.sfx2.DialogLibraryContainer";
455 Sequence< OUString > SAL_CALL SfxDialogLibraryContainer::getSupportedServiceNames( )
457 return {"com.sun.star.script.DocumentDialogLibraryContainer",
458 "com.sun.star.script.DialogLibraryContainer"}; // for compatibility
461 // Implementation class SfxDialogLibrary
463 // Ctor
464 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper& _rModifiable,
465 const OUString& aName,
466 const Reference< XSimpleFileAccess3 >& xSFI,
467 SfxDialogLibraryContainer* pParent )
468 : SfxLibrary( _rModifiable, cppu::UnoType<XInputStreamProvider>::get(), xSFI )
469 , m_pParent( pParent )
470 , m_aName( aName )
474 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper& _rModifiable,
475 const OUString& aName,
476 const Reference< XSimpleFileAccess3 >& xSFI,
477 const OUString& aLibInfoFileURL,
478 const OUString& aStorageURL,
479 bool ReadOnly,
480 SfxDialogLibraryContainer* pParent )
481 : SfxLibrary( _rModifiable, cppu::UnoType<XInputStreamProvider>::get(),
482 xSFI, aLibInfoFileURL, aStorageURL, ReadOnly)
483 , m_pParent( pParent )
484 , m_aName( aName )
488 IMPLEMENT_FORWARD_XINTERFACE2( SfxDialogLibrary, SfxLibrary, SfxDialogLibrary_BASE );
489 IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxDialogLibrary, SfxLibrary, SfxDialogLibrary_BASE );
491 // Provide modify state including resources
492 bool SfxDialogLibrary::isModified()
494 bool bRet = implIsModified();
496 if( !bRet && m_xStringResourcePersistence.is() )
497 bRet = m_xStringResourcePersistence->isModified();
498 // else: Resources not accessed so far -> not modified
500 return bRet;
503 void SfxDialogLibrary::storeResources()
505 if( m_xStringResourcePersistence.is() )
506 m_xStringResourcePersistence->store();
509 void SfxDialogLibrary::storeResourcesAsURL
510 ( const OUString& URL, const OUString& NewName )
512 OUString aComment(aResourceFileCommentBase);
513 m_aName = NewName;
514 aComment += m_aName;
516 if( m_xStringResourcePersistence.is() )
518 m_xStringResourcePersistence->setComment( aComment );
520 Reference< resource::XStringResourceWithLocation >
521 xStringResourceWithLocation( m_xStringResourcePersistence, UNO_QUERY );
522 if( xStringResourceWithLocation.is() )
523 xStringResourceWithLocation->storeAsURL( URL );
527 void SfxDialogLibrary::storeResourcesToURL( const OUString& URL,
528 const Reference< task::XInteractionHandler >& xHandler )
530 OUString aComment = aResourceFileCommentBase + m_aName;
532 if( m_xStringResourcePersistence.is() )
534 m_xStringResourcePersistence->storeToURL
535 ( URL, aResourceFileNameBase, aComment, xHandler );
539 void SfxDialogLibrary::storeResourcesToStorage( const css::uno::Reference< css::embed::XStorage >& xStorage )
541 OUString aComment = aResourceFileCommentBase + m_aName;
543 if( m_xStringResourcePersistence.is() )
545 m_xStringResourcePersistence->storeToStorage
546 ( xStorage, aResourceFileNameBase, aComment );
551 // XStringResourceSupplier
552 Reference< resource::XStringResourceResolver >
553 SAL_CALL SfxDialogLibrary::getStringResource( )
555 if( !m_xStringResourcePersistence.is() )
556 m_xStringResourcePersistence = m_pParent->implCreateStringResource( this );
558 return m_xStringResourcePersistence;
561 bool SfxDialogLibrary::containsValidDialog( const css::uno::Any& aElement )
563 Reference< XInputStreamProvider > xISP;
564 aElement >>= xISP;
565 return xISP.is();
568 bool SfxDialogLibrary::isLibraryElementValid(const css::uno::Any& rElement) const
570 return SfxDialogLibrary::containsValidDialog(rElement);
575 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
576 com_sun_star_comp_sfx2_DialogLibraryContainer_get_implementation(css::uno::XComponentContext*,
577 css::uno::Sequence<css::uno::Any> const &)
579 return cppu::acquire(new basic::SfxDialogLibraryContainer());
583 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */