tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / basic / source / uno / dlgcont.cxx
blob0402e9188ed0fffb3a105d66bac9a782991e562b
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>
36 #include <comphelper/diagnose_ex.hxx>
37 #include <o3tl/temporary.hxx>
38 #include <utility>
39 #include <vcl/svapp.hxx>
40 #include <vcl/settings.hxx>
41 #include <xmlscript/xmldlg_imexp.hxx>
42 #include <sot/storage.hxx>
43 #include <svtools/sfxecode.hxx>
44 #include <svtools/ehdl.hxx>
45 #include <vcl/GraphicObject.hxx>
46 #include <i18nlangtag/languagetag.hxx>
48 namespace basic
51 using namespace com::sun::star::document;
52 using namespace com::sun::star::container;
53 using namespace com::sun::star::io;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::ucb;
56 using namespace com::sun::star::lang;
57 using namespace com::sun::star::xml::sax;
58 using namespace com::sun::star;
59 using namespace cppu;
61 using com::sun::star::uno::Reference;
64 // Implementation class SfxDialogLibraryContainer
66 OUString SfxDialogLibraryContainer::getInfoFileName() const
68 static constexpr OUStringLiteral dialog = u"dialog";
69 return dialog;
71 OUString SfxDialogLibraryContainer::getOldInfoFileName() const
73 static constexpr OUStringLiteral dialogs = u"dialogs";
74 return dialogs;
76 OUString SfxDialogLibraryContainer::getLibElementFileExtension() const
78 static constexpr OUStringLiteral xdl = u"xdl";
79 return xdl;
81 OUString SfxDialogLibraryContainer::getLibrariesDir() const
83 static constexpr OUStringLiteral Dialogs = u"Dialogs";
84 return Dialogs;
87 // Ctor for service
88 SfxDialogLibraryContainer::SfxDialogLibraryContainer()
90 // all initialisation has to be done
91 // by calling XInitialization::initialize
94 SfxDialogLibraryContainer::SfxDialogLibraryContainer( const uno::Reference< embed::XStorage >& xStorage )
96 init(OUString(), xStorage, o3tl::temporary(std::unique_lock(m_aMutex)));
99 // Methods to get library instances of the correct type
100 rtl::Reference<SfxLibrary> SfxDialogLibraryContainer::implCreateLibrary( const OUString& aName )
102 return new SfxDialogLibrary( maModifiable, aName, mxSFI, this );
105 rtl::Reference<SfxLibrary> SfxDialogLibraryContainer::implCreateLibraryLink
106 ( const OUString& aName, const OUString& aLibInfoFileURL,
107 const OUString& StorageURL, bool ReadOnly )
109 return new SfxDialogLibrary
110 ( maModifiable, aName, mxSFI, aLibInfoFileURL, StorageURL, ReadOnly, this );
113 Any SfxDialogLibraryContainer::createEmptyLibraryElement()
115 Reference< XInputStreamProvider > xISP;
116 Any aRetAny;
117 aRetAny <<= xISP;
118 return aRetAny;
121 bool SfxDialogLibraryContainer::isLibraryElementValid(const Any& rElement) const
123 return SfxDialogLibrary::containsValidDialog(rElement);
126 static bool writeOasis2OOoLibraryElement(
127 const Reference< XInputStream >& xInput, const Reference< XOutputStream >& xOutput )
129 const Reference< XComponentContext >& xContext(
130 comphelper::getProcessComponentContext() );
132 Reference< lang::XMultiComponentFactory > xSMgr(
133 xContext->getServiceManager() );
135 Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
137 Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
139 xWriter->setOutputStream( xOutput );
141 Sequence<Any> aArgs{ Any(xWriter) };
142 Reference< xml::sax::XDocumentHandler > xHandler(
143 xSMgr->createInstanceWithArgumentsAndContext(
144 u"com.sun.star.comp.Oasis2OOoTransformer"_ustr,
145 aArgs, xContext ),
146 UNO_QUERY );
148 xParser->setDocumentHandler( xHandler );
150 xml::sax::InputSource source;
151 source.aInputStream = xInput;
152 source.sSystemId = "virtual file";
154 xParser->parseStream( source );
156 return true;
159 void SfxDialogLibraryContainer::writeLibraryElement
161 const Reference < XNameContainer >& xLib,
162 const OUString& aElementName,
163 const Reference< XOutputStream >& xOutput
166 Any aElement = xLib->getByName( aElementName );
167 Reference< XInputStreamProvider > xISP;
168 aElement >>= xISP;
169 if( !xISP.is() )
170 return;
172 Reference< XInputStream > xInput( xISP->createInputStream() );
174 bool bComplete = false;
175 if ( mbOasis2OOoFormat )
177 bComplete = writeOasis2OOoLibraryElement( xInput, xOutput );
180 if ( !bComplete )
182 Sequence< sal_Int8 > bytes;
183 sal_Int32 nRead = xInput->readBytes( bytes, xInput->available() );
184 for (;;)
186 if( nRead )
187 xOutput->writeBytes( bytes );
189 nRead = xInput->readBytes( bytes, 1024 );
190 if (! nRead)
191 break;
194 xInput->closeInput();
197 void SfxDialogLibraryContainer::storeLibrariesToStorage( const uno::Reference< embed::XStorage >& xStorage )
199 LibraryContainerMethodGuard aGuard( *this );
200 mbOasis2OOoFormat = false;
202 if ( mxStorage.is() && xStorage.is() )
206 tools::Long nSource = SotStorage::GetVersion( mxStorage );
207 tools::Long nTarget = SotStorage::GetVersion( xStorage );
209 if ( nSource == SOFFICE_FILEFORMAT_CURRENT &&
210 nTarget != SOFFICE_FILEFORMAT_CURRENT )
212 mbOasis2OOoFormat = true;
215 catch (const Exception& )
217 TOOLS_WARN_EXCEPTION("basic", "");
218 // if we cannot get the version then the
219 // Oasis2OOoTransformer will not be used
220 assert(false);
224 SfxLibraryContainer::storeLibrariesToStorage( xStorage );
226 // we need to export out any embedded image object(s)
227 // associated with any Dialogs. First, we need to actually gather any such urls
228 // for each dialog in this container
229 const Sequence< OUString > sLibraries = getElementNames();
230 for ( const OUString& rName : sLibraries )
232 loadLibrary( rName );
233 Reference< XNameContainer > xLib;
234 getByName( rName ) >>= xLib;
235 if ( xLib.is() )
237 Sequence< OUString > sDialogs = xLib->getElementNames();
238 sal_Int32 nDialogs( sDialogs.getLength() );
239 for ( sal_Int32 j=0; j < nDialogs; ++j )
241 // Each Dialog has an associated xISP
242 Reference< io::XInputStreamProvider > xISP;
243 xLib->getByName( sDialogs[ j ] ) >>= xISP;
244 if ( xISP.is() )
246 Reference< io::XInputStream > xInput( xISP->createInputStream() );
247 Reference< XNameContainer > xDialogModel(
248 mxContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.awt.UnoControlDialogModel"_ustr, mxContext),
249 UNO_QUERY );
250 ::xmlscript::importDialogModel( xInput, xDialogModel, mxContext, mxOwnerDocument );
251 std::vector<uno::Reference<graphic::XGraphic>> vxGraphicList;
252 vcl::graphic::SearchForGraphics(Reference<XInterface>(xDialogModel, UNO_QUERY), vxGraphicList);
253 if (!vxGraphicList.empty())
255 // Export the images to the storage
256 Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
257 xGraphicStorageHandler.set(document::GraphicStorageHandler::createWithStorage(mxContext, xStorage));
258 if (xGraphicStorageHandler.is())
260 for (uno::Reference<graphic::XGraphic> const & rxGraphic : vxGraphicList)
262 xGraphicStorageHandler->saveGraphic(rxGraphic);
266 Reference< XComponent > xDialogModelComp(xDialogModel, UNO_QUERY);
267 if (xDialogModelComp)
268 xDialogModelComp->dispose();
273 mbOasis2OOoFormat = false;
277 Any SfxDialogLibraryContainer::importLibraryElement
278 ( const Reference < XNameContainer >& /*xLib*/,
279 const OUString& /*aElementName */, const OUString& aFile,
280 const uno::Reference< io::XInputStream >& xElementStream )
282 Any aRetAny;
284 // TODO: Member because later it will be a component
285 //Reference< XMultiServiceFactory > xMSF( comphelper::getProcessServiceFactory() );
286 //if( !xMSF.is() )
288 // OSL_FAIL( "### couldn't get ProcessServiceFactory" );
289 // return aRetAny;
292 Reference< XParser > xParser = xml::sax::Parser::create( mxContext );
294 Reference< XNameContainer > xDialogModel(
295 mxContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.awt.UnoControlDialogModel"_ustr, mxContext),
296 UNO_QUERY );
297 if( !xDialogModel.is() )
299 OSL_FAIL( "### couldn't create com.sun.star.awt.UnoControlDialogModel component" );
300 return aRetAny;
303 // Read from storage?
304 bool bStorage = xElementStream.is();
305 Reference< XInputStream > xInput;
307 if( bStorage )
309 xInput = xElementStream;
311 else
315 xInput = mxSFI->openFileRead( aFile );
317 catch(const Exception& )
318 //catch( Exception& e )
320 // TODO:
321 //throw WrappedTargetException( e );
324 if( !xInput.is() )
325 return aRetAny;
327 InputSource source;
328 source.aInputStream = std::move(xInput);
329 source.sSystemId = aFile;
331 try {
332 // start parsing
333 xParser->setDocumentHandler( ::xmlscript::importDialogModel( xDialogModel, mxContext, mxOwnerDocument ) );
334 xParser->parseStream( source );
336 catch(const Exception& )
338 OSL_FAIL( "Parsing error" );
339 SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC, aFile );
340 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
341 return aRetAny;
344 // Create InputStream, TODO: Implement own InputStreamProvider
345 // to avoid creating the DialogModel here!
346 Reference< XInputStreamProvider > xISP = ::xmlscript::exportDialogModel( xDialogModel, mxContext, mxOwnerDocument );
347 aRetAny <<= xISP;
349 Reference< XComponent > xDialogModelComp(xDialogModel, UNO_QUERY);
350 if (xDialogModelComp)
351 xDialogModelComp->dispose();
353 return aRetAny;
356 void SfxDialogLibraryContainer::importFromOldStorage( const OUString& )
358 // Nothing to do here, old dialogs cannot be imported
361 rtl::Reference<SfxLibraryContainer> SfxDialogLibraryContainer::createInstanceImpl()
363 return new SfxDialogLibraryContainer();
366 constexpr OUString aResourceFileNameBase = u"DialogStrings"_ustr;
367 constexpr OUString aResourceFileCommentBase = u"# Strings for Dialog Library "_ustr;
369 // Resource handling
370 Reference< css::resource::XStringResourcePersistence >
371 SfxDialogLibraryContainer::implCreateStringResource( SfxDialogLibrary* pDialogLibrary )
373 Reference< resource::XStringResourcePersistence > xRet;
374 OUString aLibName = pDialogLibrary->getName();
375 bool bReadOnly = pDialogLibrary->mbReadOnly;
377 // get ui locale
378 ::com::sun ::star::lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
380 OUString aComment= aResourceFileCommentBase + aLibName;
382 bool bStorage = mxStorage.is();
383 if( bStorage )
385 uno::Reference< embed::XStorage > xLibrariesStor;
386 uno::Reference< embed::XStorage > xLibraryStor;
387 try {
388 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ );
389 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
390 if ( !xLibrariesStor.is() )
391 throw uno::RuntimeException(u"null returned from openStorageElement"_ustr,getXWeak());
393 xLibraryStor = xLibrariesStor->openStorageElement( aLibName, embed::ElementModes::READ );
394 // TODO: Should be READWRITE with new storage concept using store() instead of storeTo()
395 if ( !xLibraryStor.is() )
396 throw uno::RuntimeException(u"null returned from openStorageElement"_ustr,getXWeak());
398 catch(const uno::Exception& )
400 // Something went wrong while trying to get the storage library.
401 // Return an object that supports StringResourceWithStorage, give it a storage location later.
402 xRet = Reference< resource::XStringResourcePersistence >(
403 mxContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.resource.StringResourceWithStorage"_ustr, mxContext),
404 UNO_QUERY );
405 return xRet;
408 xRet = resource::StringResourceWithStorage::create(mxContext, xLibraryStor, bReadOnly, aLocale, aResourceFileNameBase, aComment);
410 else
412 OUString aLocation = createAppLibraryFolder( pDialogLibrary, aLibName );
413 // TODO: Real handler?
414 Reference< task::XInteractionHandler > xDummyHandler;
416 xRet = resource::StringResourceWithLocation::create(mxContext, aLocation, bReadOnly, aLocale, aResourceFileNameBase, aComment, xDummyHandler);
419 return xRet;
422 void SfxDialogLibraryContainer::onNewRootStorage()
424 // the library container is not modified, go through the libraries and check whether they are modified
425 Sequence< OUString > aNames = maNameContainer.getElementNames();
426 const OUString* pNames = aNames.getConstArray();
427 sal_Int32 nNameCount = aNames.getLength();
429 for( sal_Int32 i = 0 ; i < nNameCount ; i++ )
431 OUString aName = pNames[ i ];
432 SfxDialogLibrary* pDialogLibrary = static_cast<SfxDialogLibrary*>( getImplLib( aName ) );
434 Reference< resource::XStringResourcePersistence > xStringResourcePersistence =
435 pDialogLibrary->getStringResourcePersistence();
437 if( xStringResourcePersistence.is() )
439 Reference< embed::XStorage > xLibrariesStor;
440 Reference< embed::XStorage > xLibraryStor;
441 try {
442 xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READWRITE );
443 if ( !xLibrariesStor.is() )
444 throw uno::RuntimeException(u"null returned from openStorageElement"_ustr,getXWeak());
446 OUString aLibName = pDialogLibrary->getName();
447 xLibraryStor = xLibrariesStor->openStorageElement( aLibName, embed::ElementModes::READWRITE );
448 if ( !xLibraryStor.is() )
449 throw uno::RuntimeException(u"null returned from openStorageElement"_ustr,getXWeak());
451 Reference< resource::XStringResourceWithStorage >
452 xStringResourceWithStorage( xStringResourcePersistence, UNO_QUERY );
453 if( xStringResourceWithStorage.is() )
454 xStringResourceWithStorage->setStorage( xLibraryStor );
456 catch(const uno::Exception& )
458 // TODO: Error handling?
464 sal_Bool SAL_CALL
465 SfxDialogLibraryContainer:: HasExecutableCode( const OUString& /*Library*/ )
467 return false; // dialog library has no executable code
470 // Service
472 OUString SAL_CALL SfxDialogLibraryContainer::getImplementationName( )
474 return u"com.sun.star.comp.sfx2.DialogLibraryContainer"_ustr;
477 Sequence< OUString > SAL_CALL SfxDialogLibraryContainer::getSupportedServiceNames( )
479 return {u"com.sun.star.script.DocumentDialogLibraryContainer"_ustr,
480 u"com.sun.star.script.DialogLibraryContainer"_ustr}; // for compatibility
483 // Implementation class SfxDialogLibrary
485 // Ctor
486 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper& _rModifiable,
487 OUString aName,
488 const Reference< XSimpleFileAccess3 >& xSFI,
489 SfxDialogLibraryContainer* pParent )
490 : SfxDialogLibrary_BASE(_rModifiable, cppu::UnoType<XInputStreamProvider>::get(), xSFI)
491 , m_pParent( pParent )
492 , m_aName(std::move( aName ))
496 SfxDialogLibrary::SfxDialogLibrary( ModifiableHelper& _rModifiable,
497 OUString aName,
498 const Reference< XSimpleFileAccess3 >& xSFI,
499 const OUString& aLibInfoFileURL,
500 const OUString& aStorageURL,
501 bool ReadOnly,
502 SfxDialogLibraryContainer* pParent )
503 : SfxDialogLibrary_BASE(_rModifiable, cppu::UnoType<XInputStreamProvider>::get(),
504 xSFI, aLibInfoFileURL, aStorageURL, ReadOnly)
505 , m_pParent( pParent )
506 , m_aName(std::move( aName ))
510 // Provide modify state including resources
511 bool SfxDialogLibrary::isModified()
513 bool bRet = implIsModified();
515 if( !bRet && m_xStringResourcePersistence.is() )
516 bRet = m_xStringResourcePersistence->isModified();
517 // else: Resources not accessed so far -> not modified
519 return bRet;
522 void SfxDialogLibrary::storeResources()
524 if( m_xStringResourcePersistence.is() )
525 m_xStringResourcePersistence->store();
528 void SfxDialogLibrary::storeResourcesAsURL
529 ( const OUString& URL, const OUString& NewName )
531 OUString aComment(aResourceFileCommentBase);
532 m_aName = NewName;
533 aComment += m_aName;
535 if( m_xStringResourcePersistence.is() )
537 m_xStringResourcePersistence->setComment( aComment );
539 Reference< resource::XStringResourceWithLocation >
540 xStringResourceWithLocation( m_xStringResourcePersistence, UNO_QUERY );
541 if( xStringResourceWithLocation.is() )
542 xStringResourceWithLocation->storeAsURL( URL );
546 void SfxDialogLibrary::storeResourcesToURL( const OUString& URL,
547 const Reference< task::XInteractionHandler >& xHandler )
549 OUString aComment = aResourceFileCommentBase + m_aName;
551 if( m_xStringResourcePersistence.is() )
553 m_xStringResourcePersistence->storeToURL
554 ( URL, aResourceFileNameBase, aComment, xHandler );
558 void SfxDialogLibrary::storeResourcesToStorage( const css::uno::Reference< css::embed::XStorage >& xStorage )
560 OUString aComment = aResourceFileCommentBase + m_aName;
562 if( m_xStringResourcePersistence.is() )
564 m_xStringResourcePersistence->storeToStorage
565 ( xStorage, aResourceFileNameBase, aComment );
570 // XStringResourceSupplier
571 Reference< resource::XStringResourceResolver >
572 SAL_CALL SfxDialogLibrary::getStringResource( )
574 if( !m_xStringResourcePersistence.is() )
575 m_xStringResourcePersistence = m_pParent->implCreateStringResource( this );
577 return m_xStringResourcePersistence;
580 bool SfxDialogLibrary::containsValidDialog( const css::uno::Any& aElement )
582 Reference< XInputStreamProvider > xISP;
583 aElement >>= xISP;
584 return xISP.is();
587 bool SfxDialogLibrary::isLibraryElementValid(const css::uno::Any& rElement) const
589 return SfxDialogLibrary::containsValidDialog(rElement);
594 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
595 com_sun_star_comp_sfx2_DialogLibraryContainer_get_implementation(css::uno::XComponentContext*,
596 css::uno::Sequence<css::uno::Any> const &)
598 return cppu::acquire(new basic::SfxDialogLibraryContainer());
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */