1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <accelerators/presethandler.hxx>
21 #include <uiconfiguration/imagemanager.hxx>
22 #include <uielement/constitemcontainer.hxx>
23 #include <uielement/rootitemcontainer.hxx>
24 #include <uielement/uielementtypenames.hxx>
25 #include <menuconfiguration.hxx>
26 #include <toolboxconfiguration.hxx>
28 #include <statusbarconfiguration.hxx>
30 #include <com/sun/star/ui/UIElementType.hpp>
31 #include <com/sun/star/ui/ConfigurationEvent.hpp>
32 #include <com/sun/star/ui/ModuleAcceleratorConfiguration.hpp>
33 #include <com/sun/star/ui/XModuleUIConfigurationManager2.hpp>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <com/sun/star/lang/IllegalAccessException.hpp>
36 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/embed/ElementModes.hpp>
39 #include <com/sun/star/embed/InvalidStorageException.hpp>
40 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
41 #include <com/sun/star/embed/XTransactedObject.hpp>
42 #include <com/sun/star/container/ElementExistException.hpp>
43 #include <com/sun/star/container/XNameAccess.hpp>
44 #include <com/sun/star/container/XIndexContainer.hpp>
45 #include <com/sun/star/io/IOException.hpp>
46 #include <com/sun/star/io/XStream.hpp>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/lang/XComponent.hpp>
50 #include <comphelper/propertysequence.hxx>
51 #include <comphelper/sequence.hxx>
52 #include <cppuhelper/exc_hlp.hxx>
53 #include <cppuhelper/implbase.hxx>
54 #include <cppuhelper/supportsservice.hxx>
56 #include <vcl/svapp.hxx>
57 #include <sal/log.hxx>
58 #include <comphelper/interfacecontainer4.hxx>
59 #include <comphelper/propertyvalue.hxx>
60 #include <comphelper/sequenceashashmap.hxx>
61 #include <comphelper/servicehelper.hxx>
62 #include <o3tl/string_view.hxx>
65 #include <string_view>
68 using namespace com::sun::star::uno
;
69 using namespace com::sun::star::io
;
70 using namespace com::sun::star::embed
;
71 using namespace com::sun::star::lang
;
72 using namespace com::sun::star::container
;
73 using namespace com::sun::star::beans
;
74 using namespace framework
;
76 constexpr OUStringLiteral RESOURCETYPE_MENUBAR
= u
"menubar";
77 constexpr OUStringLiteral RESOURCETYPE_TOOLBAR
= u
"toolbar";
78 constexpr OUStringLiteral RESOURCETYPE_STATUSBAR
= u
"statusbar";
79 constexpr OUStringLiteral RESOURCETYPE_POPUPMENU
= u
"popupmenu";
83 class ModuleUIConfigurationManager
: public cppu::WeakImplHelper
<
84 css::lang::XServiceInfo
,
85 css::lang::XComponent
,
86 css::ui::XModuleUIConfigurationManager2
>
89 ModuleUIConfigurationManager(
90 const css::uno::Reference
< css::uno::XComponentContext
>& xServiceManager
,
91 const css::uno::Sequence
< css::uno::Any
>& aArguments
);
93 virtual OUString SAL_CALL
getImplementationName() override
95 return u
"com.sun.star.comp.framework.ModuleUIConfigurationManager"_ustr
;
98 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
100 return cppu::supportsService(this, ServiceName
);
103 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
105 return {u
"com.sun.star.ui.ModuleUIConfigurationManager"_ustr
};
109 virtual void SAL_CALL
dispose() override
;
110 virtual void SAL_CALL
addEventListener( const css::uno::Reference
< css::lang::XEventListener
>& xListener
) override
;
111 virtual void SAL_CALL
removeEventListener( const css::uno::Reference
< css::lang::XEventListener
>& aListener
) override
;
114 virtual void SAL_CALL
addConfigurationListener( const css::uno::Reference
< css::ui::XUIConfigurationListener
>& Listener
) override
;
115 virtual void SAL_CALL
removeConfigurationListener( const css::uno::Reference
< css::ui::XUIConfigurationListener
>& Listener
) override
;
117 // XUIConfigurationManager
118 virtual void SAL_CALL
reset() override
;
119 virtual css::uno::Sequence
< css::uno::Sequence
< css::beans::PropertyValue
> > SAL_CALL
getUIElementsInfo( sal_Int16 ElementType
) override
;
120 virtual css::uno::Reference
< css::container::XIndexContainer
> SAL_CALL
createSettings( ) override
;
121 virtual sal_Bool SAL_CALL
hasSettings( const OUString
& ResourceURL
) override
;
122 virtual css::uno::Reference
< css::container::XIndexAccess
> SAL_CALL
getSettings( const OUString
& ResourceURL
, sal_Bool bWriteable
) override
;
123 virtual void SAL_CALL
replaceSettings( const OUString
& ResourceURL
, const css::uno::Reference
< css::container::XIndexAccess
>& aNewData
) override
;
124 virtual void SAL_CALL
removeSettings( const OUString
& ResourceURL
) override
;
125 virtual void SAL_CALL
insertSettings( const OUString
& NewResourceURL
, const css::uno::Reference
< css::container::XIndexAccess
>& aNewData
) override
;
126 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
getImageManager() override
;
127 virtual css::uno::Reference
< css::ui::XAcceleratorConfiguration
> SAL_CALL
getShortCutManager() override
;
128 virtual css::uno::Reference
< css::ui::XAcceleratorConfiguration
> SAL_CALL
createShortCutManager() override
;
129 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
getEventsManager() override
;
131 // XModuleUIConfigurationManager
132 virtual sal_Bool SAL_CALL
isDefaultSettings( const OUString
& ResourceURL
) override
;
133 virtual css::uno::Reference
< css::container::XIndexAccess
> SAL_CALL
getDefaultSettings( const OUString
& ResourceURL
) override
;
135 // XUIConfigurationPersistence
136 virtual void SAL_CALL
reload() override
;
137 virtual void SAL_CALL
store() override
;
138 virtual void SAL_CALL
storeToStorage( const css::uno::Reference
< css::embed::XStorage
>& Storage
) override
;
139 virtual sal_Bool SAL_CALL
isModified() override
;
140 virtual sal_Bool SAL_CALL
isReadOnly() override
;
143 // private data types
160 UIElementInfo( OUString _aResourceURL
, OUString _aUIName
) :
161 aResourceURL(std::move( _aResourceURL
)), aUIName(std::move( _aUIName
)) {}
162 OUString aResourceURL
;
168 UIElementData() : bModified( false ), bDefault( true ), bDefaultNode( true ) {};
170 OUString aResourceURL
;
172 bool bModified
; // has been changed since last storing
173 bool bDefault
; // default settings
174 bool bDefaultNode
; // this is a default layer element data
175 css::uno::Reference
< css::container::XIndexAccess
> xSettings
;
178 typedef std::unordered_map
< OUString
, UIElementData
> UIElementDataHashMap
;
182 UIElementType() : bModified( false ),
184 nElementType( css::ui::UIElementType::UNKNOWN
) {}
188 sal_Int16 nElementType
;
189 UIElementDataHashMap aElementsHashMap
;
190 css::uno::Reference
< css::embed::XStorage
> xStorage
;
193 typedef std::vector
< UIElementType
> UIElementTypesVector
;
194 typedef std::vector
< css::ui::ConfigurationEvent
> ConfigEventNotifyContainer
;
195 typedef std::unordered_map
< OUString
, UIElementInfo
> UIElementInfoHashMap
;
197 void impl_Initialize();
198 void implts_notifyContainerListener( const css::ui::ConfigurationEvent
& aEvent
, NotifyOp eOp
);
199 void impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap
& aUIElementInfoCollection
, sal_Int16 nElementType
);
200 void impl_preloadUIElementTypeList( Layer eLayer
, sal_Int16 nElementType
);
201 UIElementData
* impl_findUIElementData( const OUString
& aResourceURL
, sal_Int16 nElementType
, bool bLoad
= true );
202 void impl_requestUIElementData( sal_Int16 nElementType
, Layer eLayer
, UIElementData
& aUIElementData
);
203 void impl_storeElementTypeData( const css::uno::Reference
< css::embed::XStorage
>& xStorage
, UIElementType
& rElementType
, bool bResetModifyState
= true );
204 void impl_resetElementTypeData( UIElementType
& rUserElementType
, UIElementType
const & rDefaultElementType
, ConfigEventNotifyContainer
& rRemoveNotifyContainer
, ConfigEventNotifyContainer
& rReplaceNotifyContainer
);
205 void impl_reloadElementTypeData( UIElementType
& rUserElementType
, UIElementType
const & rDefaultElementType
, ConfigEventNotifyContainer
& rRemoveNotifyContainer
, ConfigEventNotifyContainer
& rReplaceNotifyContainer
);
207 UIElementTypesVector m_aUIElements
[LAYER_COUNT
];
208 std::unique_ptr
<PresetHandler
> m_pStorageHandler
[css::ui::UIElementType::COUNT
];
209 css::uno::Reference
< css::embed::XStorage
> m_xDefaultConfigStorage
;
210 css::uno::Reference
< css::embed::XStorage
> m_xUserConfigStorage
;
214 OUString m_aXMLPostfix
;
215 OUString m_aPropUIName
;
216 OUString m_aModuleIdentifier
;
217 css::uno::Reference
< css::embed::XTransactedObject
> m_xUserRootCommit
;
218 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
220 comphelper::OInterfaceContainerHelper4
<css::lang::XEventListener
> m_aEventListeners
;
221 comphelper::OInterfaceContainerHelper4
<css::ui::XUIConfigurationListener
> m_aConfigListeners
;
222 rtl::Reference
< ImageManager
> m_xModuleImageManager
;
223 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> m_xModuleAcceleratorManager
;
226 // important: The order and position of the elements must match the constant
227 // definition of "css::ui::UIElementType"
228 std::u16string_view UIELEMENTTYPENAMES
[] =
230 u
"", // Dummy value for unknown!
231 u
"" UIELEMENTTYPE_MENUBAR_NAME
,
232 u
"" UIELEMENTTYPE_POPUPMENU_NAME
,
233 u
"" UIELEMENTTYPE_TOOLBAR_NAME
,
234 u
"" UIELEMENTTYPE_STATUSBAR_NAME
,
235 u
"" UIELEMENTTYPE_FLOATINGWINDOW_NAME
,
236 u
"" UIELEMENTTYPE_PROGRESSBAR_NAME
,
237 u
"" UIELEMENTTYPE_TOOLPANEL_NAME
240 constexpr std::u16string_view RESOURCEURL_PREFIX
= u
"private:resource/";
242 sal_Int16
RetrieveTypeFromResourceURL( std::u16string_view aResourceURL
)
245 if (( o3tl::starts_with(aResourceURL
, RESOURCEURL_PREFIX
) ) &&
246 ( aResourceURL
.size() > RESOURCEURL_PREFIX
.size() ))
248 std::u16string_view aTmpStr
= aResourceURL
.substr( RESOURCEURL_PREFIX
.size() );
249 size_t nIndex
= aTmpStr
.find( '/' );
250 if (( nIndex
> 0 ) && ( aTmpStr
.size() > nIndex
))
252 std::u16string_view
aTypeStr( aTmpStr
.substr( 0, nIndex
));
253 for ( int i
= 0; i
< ui::UIElementType::COUNT
; i
++ )
255 if ( aTypeStr
== UIELEMENTTYPENAMES
[i
] )
256 return sal_Int16( i
);
261 return ui::UIElementType::UNKNOWN
;
264 OUString
RetrieveNameFromResourceURL( std::u16string_view aResourceURL
)
266 if (( o3tl::starts_with(aResourceURL
, RESOURCEURL_PREFIX
) ) &&
267 ( aResourceURL
.size() > RESOURCEURL_PREFIX
.size() ))
269 size_t nIndex
= aResourceURL
.rfind( '/' );
271 if ( nIndex
> 0 && nIndex
!= std::u16string_view::npos
&& (( nIndex
+1 ) < aResourceURL
.size()) )
272 return OUString(aResourceURL
.substr( nIndex
+1 ));
278 void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap
& aUIElementInfoCollection
, sal_Int16 nElementType
)
280 // preload list of element types on demand
281 impl_preloadUIElementTypeList( LAYER_USERDEFINED
, nElementType
);
282 impl_preloadUIElementTypeList( LAYER_DEFAULT
, nElementType
);
284 UIElementDataHashMap
& rUserElements
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
].aElementsHashMap
;
286 OUString
aCustomUrlPrefix( u
"custom_"_ustr
);
287 for (auto const& userElement
: rUserElements
)
289 sal_Int32 nIndex
= userElement
.second
.aResourceURL
.indexOf( aCustomUrlPrefix
, RESOURCEURL_PREFIX
.size() );
290 if ( nIndex
> static_cast<sal_Int32
>(RESOURCEURL_PREFIX
.size()) )
292 // Performance: Retrieve user interface name only for custom user interface elements.
293 // It's only used by them!
294 UIElementData
* pDataSettings
= impl_findUIElementData( userElement
.second
.aResourceURL
, nElementType
);
297 // Retrieve user interface name from XPropertySet interface
299 Reference
< XPropertySet
> xPropSet( pDataSettings
->xSettings
, UNO_QUERY
);
302 Any a
= xPropSet
->getPropertyValue( m_aPropUIName
);
306 UIElementInfo
aInfo( userElement
.second
.aResourceURL
, aUIName
);
307 aUIElementInfoCollection
.emplace( userElement
.second
.aResourceURL
, aInfo
);
312 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
313 UIElementInfo
aInfo( userElement
.second
.aResourceURL
, OUString() );
314 aUIElementInfoCollection
.emplace( userElement
.second
.aResourceURL
, aInfo
);
318 UIElementDataHashMap
& rDefaultElements
= m_aUIElements
[LAYER_DEFAULT
][nElementType
].aElementsHashMap
;
320 for (auto const& defaultElement
: rDefaultElements
)
322 UIElementInfoHashMap::const_iterator pIterInfo
= aUIElementInfoCollection
.find( defaultElement
.second
.aResourceURL
);
323 if ( pIterInfo
== aUIElementInfoCollection
.end() )
325 sal_Int32 nIndex
= defaultElement
.second
.aResourceURL
.indexOf( aCustomUrlPrefix
, RESOURCEURL_PREFIX
.size() );
326 if ( nIndex
> static_cast<sal_Int32
>(RESOURCEURL_PREFIX
.size()) )
328 // Performance: Retrieve user interface name only for custom user interface elements.
329 // It's only used by them!
330 UIElementData
* pDataSettings
= impl_findUIElementData( defaultElement
.second
.aResourceURL
, nElementType
);
333 // Retrieve user interface name from XPropertySet interface
335 Reference
< XPropertySet
> xPropSet( pDataSettings
->xSettings
, UNO_QUERY
);
338 Any a
= xPropSet
->getPropertyValue( m_aPropUIName
);
341 UIElementInfo
aInfo( defaultElement
.second
.aResourceURL
, aUIName
);
342 aUIElementInfoCollection
.emplace( defaultElement
.second
.aResourceURL
, aInfo
);
347 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
348 UIElementInfo
aInfo( defaultElement
.second
.aResourceURL
, OUString() );
349 aUIElementInfoCollection
.emplace( defaultElement
.second
.aResourceURL
, aInfo
);
355 void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer
, sal_Int16 nElementType
)
357 UIElementType
& rElementTypeData
= m_aUIElements
[eLayer
][nElementType
];
359 if ( rElementTypeData
.bLoaded
)
362 Reference
< XStorage
> xElementTypeStorage
= rElementTypeData
.xStorage
;
363 if ( !xElementTypeStorage
.is() )
366 OUString aResURLPrefix
=
367 OUString::Concat(RESOURCEURL_PREFIX
) +
368 UIELEMENTTYPENAMES
[ nElementType
] +
371 UIElementDataHashMap
& rHashMap
= rElementTypeData
.aElementsHashMap
;
372 const Sequence
< OUString
> aUIElementNames
= xElementTypeStorage
->getElementNames();
373 for ( OUString
const & rElementName
: aUIElementNames
)
375 UIElementData aUIElementData
;
377 // Resource name must be without ".xml"
378 sal_Int32 nIndex
= rElementName
.lastIndexOf( '.' );
379 if (( nIndex
> 0 ) && ( nIndex
< rElementName
.getLength() ))
381 std::u16string_view
aExtension( rElementName
.subView( nIndex
+1 ));
382 std::u16string_view
aUIElementName( rElementName
.subView( 0, nIndex
));
384 if (!aUIElementName
.empty() &&
385 ( o3tl::equalsIgnoreAsciiCase(aExtension
, u
"xml")))
387 aUIElementData
.aResourceURL
= aResURLPrefix
+ aUIElementName
;
388 aUIElementData
.aName
= rElementName
;
390 if ( eLayer
== LAYER_USERDEFINED
)
392 aUIElementData
.bModified
= false;
393 aUIElementData
.bDefault
= false;
394 aUIElementData
.bDefaultNode
= false;
397 // Create std::unordered_map entries for all user interface elements inside the storage. We don't load the
398 // settings to speed up the process.
399 rHashMap
.emplace( aUIElementData
.aResourceURL
, aUIElementData
);
402 rElementTypeData
.bLoaded
= true;
407 void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType
, Layer eLayer
, UIElementData
& aUIElementData
)
409 UIElementType
& rElementTypeData
= m_aUIElements
[eLayer
][nElementType
];
411 Reference
< XStorage
> xElementTypeStorage
= rElementTypeData
.xStorage
;
412 if ( xElementTypeStorage
.is() && !aUIElementData
.aName
.isEmpty() )
416 Reference
< XStream
> xStream
= xElementTypeStorage
->openStreamElement( aUIElementData
.aName
, ElementModes::READ
);
417 Reference
< XInputStream
> xInputStream
= xStream
->getInputStream();
419 if ( xInputStream
.is() )
421 switch ( nElementType
)
423 case css::ui::UIElementType::UNKNOWN
:
426 case css::ui::UIElementType::MENUBAR
:
427 case css::ui::UIElementType::POPUPMENU
:
431 MenuConfiguration
aMenuCfg( m_xContext
);
432 Reference
< XIndexAccess
> xContainer( aMenuCfg
.CreateMenuBarConfigurationFromXML( xInputStream
));
433 auto pRootItemContainer
= dynamic_cast<RootItemContainer
*>( xContainer
.get() );
434 if ( pRootItemContainer
)
435 aUIElementData
.xSettings
= new ConstItemContainer( pRootItemContainer
, true );
437 aUIElementData
.xSettings
= new ConstItemContainer( xContainer
, true );
440 catch ( const css::lang::WrappedTargetException
& )
446 case css::ui::UIElementType::TOOLBAR
:
450 Reference
< XIndexContainer
> xIndexContainer( new RootItemContainer() );
451 ToolBoxConfiguration::LoadToolBox( m_xContext
, xInputStream
, xIndexContainer
);
452 auto pRootItemContainer
= dynamic_cast<RootItemContainer
*>( xIndexContainer
.get() );
453 aUIElementData
.xSettings
= new ConstItemContainer( pRootItemContainer
, true );
456 catch ( const css::lang::WrappedTargetException
& )
463 case css::ui::UIElementType::STATUSBAR
:
467 Reference
< XIndexContainer
> xIndexContainer( new RootItemContainer() );
468 StatusBarConfiguration::LoadStatusBar( m_xContext
, xInputStream
, xIndexContainer
);
469 auto pRootItemContainer
= dynamic_cast<RootItemContainer
*>( xIndexContainer
.get() );
470 aUIElementData
.xSettings
= new ConstItemContainer( pRootItemContainer
, true );
473 catch ( const css::lang::WrappedTargetException
& )
480 case css::ui::UIElementType::FLOATINGWINDOW
:
487 catch ( const css::embed::InvalidStorageException
& )
490 catch ( const css::lang::IllegalArgumentException
& )
493 catch ( const css::io::IOException
& )
496 catch ( const css::embed::StorageWrappedTargetException
& )
501 // At least we provide an empty settings container!
502 aUIElementData
.xSettings
= new ConstItemContainer();
505 ModuleUIConfigurationManager::UIElementData
* ModuleUIConfigurationManager::impl_findUIElementData( const OUString
& aResourceURL
, sal_Int16 nElementType
, bool bLoad
)
507 // preload list of element types on demand
508 impl_preloadUIElementTypeList( LAYER_USERDEFINED
, nElementType
);
509 impl_preloadUIElementTypeList( LAYER_DEFAULT
, nElementType
);
511 // first try to look into our user-defined vector/unordered_map combination
512 UIElementDataHashMap
& rUserHashMap
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
].aElementsHashMap
;
513 UIElementDataHashMap::iterator pIter
= rUserHashMap
.find( aResourceURL
);
514 if ( pIter
!= rUserHashMap
.end() )
516 // Default data settings data must be retrieved from the default layer!
517 if ( !pIter
->second
.bDefault
)
519 if ( !pIter
->second
.xSettings
.is() && bLoad
)
520 impl_requestUIElementData( nElementType
, LAYER_USERDEFINED
, pIter
->second
);
521 return &(pIter
->second
);
525 // Not successful, we have to look into our default vector/unordered_map combination
526 UIElementDataHashMap
& rDefaultHashMap
= m_aUIElements
[LAYER_DEFAULT
][nElementType
].aElementsHashMap
;
527 pIter
= rDefaultHashMap
.find( aResourceURL
);
528 if ( pIter
!= rDefaultHashMap
.end() )
530 if ( !pIter
->second
.xSettings
.is() && bLoad
)
531 impl_requestUIElementData( nElementType
, LAYER_DEFAULT
, pIter
->second
);
532 return &(pIter
->second
);
535 // Nothing has been found!
539 void ModuleUIConfigurationManager::impl_storeElementTypeData( const Reference
< XStorage
>& xStorage
, UIElementType
& rElementType
, bool bResetModifyState
)
541 UIElementDataHashMap
& rHashMap
= rElementType
.aElementsHashMap
;
543 for (auto & elem
: rHashMap
)
545 UIElementData
& rElement
= elem
.second
;
546 if ( rElement
.bModified
)
548 if ( rElement
.bDefault
)
550 xStorage
->removeElement( rElement
.aName
);
551 rElement
.bModified
= false; // mark as not modified
555 Reference
< XStream
> xStream
= xStorage
->openStreamElement( rElement
.aName
, ElementModes::WRITE
|ElementModes::TRUNCATE
);
556 Reference
< XOutputStream
> xOutputStream( xStream
->getOutputStream() );
558 if ( xOutputStream
.is() )
560 switch( rElementType
.nElementType
)
562 case css::ui::UIElementType::MENUBAR
:
563 case css::ui::UIElementType::POPUPMENU
:
567 MenuConfiguration
aMenuCfg( m_xContext
);
568 aMenuCfg
.StoreMenuBarConfigurationToXML(
569 rElement
.xSettings
, xOutputStream
, rElementType
.nElementType
== css::ui::UIElementType::MENUBAR
);
571 catch ( const css::lang::WrappedTargetException
& )
577 case css::ui::UIElementType::TOOLBAR
:
581 ToolBoxConfiguration::StoreToolBox( m_xContext
, xOutputStream
, rElement
.xSettings
);
583 catch ( const css::lang::WrappedTargetException
& )
589 case css::ui::UIElementType::STATUSBAR
:
593 StatusBarConfiguration::StoreStatusBar( m_xContext
, xOutputStream
, rElement
.xSettings
);
595 catch ( const css::lang::WrappedTargetException
& )
606 // mark as not modified if we store to our own storage
607 if ( bResetModifyState
)
608 rElement
.bModified
= false;
613 // commit element type storage
614 Reference
< XTransactedObject
> xTransactedObject( xStorage
, UNO_QUERY
);
615 if ( xTransactedObject
.is() )
616 xTransactedObject
->commit();
618 // mark UIElementType as not modified if we store to our own storage
619 if ( bResetModifyState
)
620 rElementType
.bModified
= false;
623 // This is only allowed to be called on the LAYER_USER_DEFINED!
624 void ModuleUIConfigurationManager::impl_resetElementTypeData(
625 UIElementType
& rUserElementType
,
626 UIElementType
const & rDefaultElementType
,
627 ConfigEventNotifyContainer
& rRemoveNotifyContainer
,
628 ConfigEventNotifyContainer
& rReplaceNotifyContainer
)
630 UIElementDataHashMap
& rHashMap
= rUserElementType
.aElementsHashMap
;
632 Reference
< XUIConfigurationManager
> xThis(this);
633 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
634 sal_Int16 nType
= rUserElementType
.nElementType
;
636 // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
638 for (auto & elem
: rHashMap
)
640 UIElementData
& rElement
= elem
.second
;
641 if ( !rElement
.bDefault
)
643 if ( rDefaultElementType
.xStorage
->hasByName( rElement
.aName
))
645 // Replace settings with data from default layer
646 Reference
< XIndexAccess
> xOldSettings( rElement
.xSettings
);
647 impl_requestUIElementData( nType
, LAYER_DEFAULT
, rElement
);
649 ui::ConfigurationEvent aReplaceEvent
;
650 aReplaceEvent
.ResourceURL
= rElement
.aResourceURL
;
651 aReplaceEvent
.Accessor
<<= xThis
;
652 aReplaceEvent
.Source
= xIfac
;
653 aReplaceEvent
.ReplacedElement
<<= xOldSettings
;
654 aReplaceEvent
.Element
<<= rElement
.xSettings
;
656 rReplaceNotifyContainer
.push_back( aReplaceEvent
);
658 // Mark element as default and not modified. That means "not active"
659 // in the user layer anymore.
660 rElement
.bModified
= false;
661 rElement
.bDefault
= true;
665 // Remove user-defined settings from user layer
666 ui::ConfigurationEvent aEvent
;
667 aEvent
.ResourceURL
= rElement
.aResourceURL
;
668 aEvent
.Accessor
<<= xThis
;
669 aEvent
.Source
= xIfac
;
670 aEvent
.Element
<<= rElement
.xSettings
;
672 rRemoveNotifyContainer
.push_back( aEvent
);
674 // Mark element as default and not modified. That means "not active"
675 // in the user layer anymore.
676 rElement
.bModified
= false;
677 rElement
.bDefault
= true;
682 // Remove all settings from our user interface elements
686 void ModuleUIConfigurationManager::impl_reloadElementTypeData(
687 UIElementType
& rUserElementType
,
688 UIElementType
const & rDefaultElementType
,
689 ConfigEventNotifyContainer
& rRemoveNotifyContainer
,
690 ConfigEventNotifyContainer
& rReplaceNotifyContainer
)
692 UIElementDataHashMap
& rHashMap
= rUserElementType
.aElementsHashMap
;
694 Reference
< XUIConfigurationManager
> xThis(this);
695 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
696 sal_Int16 nType
= rUserElementType
.nElementType
;
698 for (auto & elem
: rHashMap
)
700 UIElementData
& rElement
= elem
.second
;
701 if ( rElement
.bModified
)
703 if ( rUserElementType
.xStorage
->hasByName( rElement
.aName
))
705 // Replace settings with data from user layer
706 Reference
< XIndexAccess
> xOldSettings( rElement
.xSettings
);
708 impl_requestUIElementData( nType
, LAYER_USERDEFINED
, rElement
);
710 ui::ConfigurationEvent aReplaceEvent
;
712 aReplaceEvent
.ResourceURL
= rElement
.aResourceURL
;
713 aReplaceEvent
.Accessor
<<= xThis
;
714 aReplaceEvent
.Source
= xIfac
;
715 aReplaceEvent
.ReplacedElement
<<= xOldSettings
;
716 aReplaceEvent
.Element
<<= rElement
.xSettings
;
717 rReplaceNotifyContainer
.push_back( aReplaceEvent
);
719 rElement
.bModified
= false;
721 else if ( rDefaultElementType
.xStorage
->hasByName( rElement
.aName
))
723 // Replace settings with data from default layer
724 Reference
< XIndexAccess
> xOldSettings( rElement
.xSettings
);
726 impl_requestUIElementData( nType
, LAYER_DEFAULT
, rElement
);
728 ui::ConfigurationEvent aReplaceEvent
;
730 aReplaceEvent
.ResourceURL
= rElement
.aResourceURL
;
731 aReplaceEvent
.Accessor
<<= xThis
;
732 aReplaceEvent
.Source
= xIfac
;
733 aReplaceEvent
.ReplacedElement
<<= xOldSettings
;
734 aReplaceEvent
.Element
<<= rElement
.xSettings
;
735 rReplaceNotifyContainer
.push_back( aReplaceEvent
);
737 // Mark element as default and not modified. That means "not active"
738 // in the user layer anymore.
739 rElement
.bModified
= false;
740 rElement
.bDefault
= true;
744 // Element settings are not in any storage => remove
745 ui::ConfigurationEvent aRemoveEvent
;
747 aRemoveEvent
.ResourceURL
= rElement
.aResourceURL
;
748 aRemoveEvent
.Accessor
<<= xThis
;
749 aRemoveEvent
.Source
= xIfac
;
750 aRemoveEvent
.Element
<<= rElement
.xSettings
;
752 rRemoveNotifyContainer
.push_back( aRemoveEvent
);
754 // Mark element as default and not modified. That means "not active"
755 // in the user layer anymore.
756 rElement
.bModified
= false;
757 rElement
.bDefault
= true;
762 rUserElementType
.bModified
= false;
765 void ModuleUIConfigurationManager::impl_Initialize()
767 // Initialize the top-level structures with the storage data
768 if ( m_xUserConfigStorage
.is() )
770 // Try to access our module sub folder
771 for ( sal_Int16 i
= 1; i
< css::ui::UIElementType::COUNT
;
774 Reference
< XStorage
> xElementTypeStorage
;
777 if ( m_pStorageHandler
[i
] )
778 xElementTypeStorage
= m_pStorageHandler
[i
]->getWorkingStorageUser();
780 catch ( const css::container::NoSuchElementException
& )
783 catch ( const css::embed::InvalidStorageException
& )
786 catch ( const css::lang::IllegalArgumentException
& )
789 catch ( const css::io::IOException
& )
792 catch ( const css::embed::StorageWrappedTargetException
& )
796 m_aUIElements
[LAYER_USERDEFINED
][i
].nElementType
= i
;
797 m_aUIElements
[LAYER_USERDEFINED
][i
].bModified
= false;
798 m_aUIElements
[LAYER_USERDEFINED
][i
].xStorage
= std::move(xElementTypeStorage
);
802 if ( !m_xDefaultConfigStorage
.is() )
805 Reference
< XNameAccess
> xNameAccess( m_xDefaultConfigStorage
, UNO_QUERY_THROW
);
807 // Try to access our module sub folder
808 for ( sal_Int16 i
= 1; i
< css::ui::UIElementType::COUNT
;
811 Reference
< XStorage
> xElementTypeStorage
;
814 const OUString
sName( UIELEMENTTYPENAMES
[i
] );
815 if( xNameAccess
->hasByName( sName
) )
816 xNameAccess
->getByName( sName
) >>= xElementTypeStorage
;
818 catch ( const css::container::NoSuchElementException
& )
822 m_aUIElements
[LAYER_DEFAULT
][i
].nElementType
= i
;
823 m_aUIElements
[LAYER_DEFAULT
][i
].bModified
= false;
824 m_aUIElements
[LAYER_DEFAULT
][i
].xStorage
= std::move(xElementTypeStorage
);
828 ModuleUIConfigurationManager::ModuleUIConfigurationManager(
829 const Reference
< XComponentContext
>& xContext
,
830 const css::uno::Sequence
< css::uno::Any
>& aArguments
)
831 : m_bReadOnly( true )
832 , m_bModified( false )
833 , m_bDisposed( false )
834 , m_aXMLPostfix( u
".xml"_ustr
)
835 , m_aPropUIName( u
"UIName"_ustr
)
836 , m_xContext( xContext
)
838 // Make sure we have a default initialized entry for every layer and user interface element type!
839 // The following code depends on this!
840 m_aUIElements
[LAYER_DEFAULT
].resize( css::ui::UIElementType::COUNT
);
841 m_aUIElements
[LAYER_USERDEFINED
].resize( css::ui::UIElementType::COUNT
);
845 OUString aModuleShortName
;
846 if( aArguments
.getLength() == 2 && (aArguments
[0] >>= aModuleShortName
) && (aArguments
[1] >>= m_aModuleIdentifier
))
851 ::comphelper::SequenceAsHashMap
lArgs(aArguments
);
852 aModuleShortName
= lArgs
.getUnpackedValueOrDefault(u
"ModuleShortName"_ustr
, OUString());
853 m_aModuleIdentifier
= lArgs
.getUnpackedValueOrDefault(u
"ModuleIdentifier"_ustr
, OUString());
856 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
858 OUString aResourceType
;
859 if ( i
== css::ui::UIElementType::MENUBAR
)
860 aResourceType
= RESOURCETYPE_MENUBAR
;
861 else if ( i
== css::ui::UIElementType::TOOLBAR
)
862 aResourceType
= RESOURCETYPE_TOOLBAR
;
863 else if ( i
== css::ui::UIElementType::STATUSBAR
)
864 aResourceType
= RESOURCETYPE_STATUSBAR
;
865 else if ( i
== css::ui::UIElementType::POPUPMENU
)
866 aResourceType
= RESOURCETYPE_POPUPMENU
;
868 if ( !aResourceType
.isEmpty() )
870 m_pStorageHandler
[i
].reset( new PresetHandler( m_xContext
) );
871 m_pStorageHandler
[i
]->connectToResource( PresetHandler::E_MODULES
,
872 aResourceType
, // this path won't be used later... see next lines!
874 css::uno::Reference
< css::embed::XStorage
>()); // no document root used here!
878 // initialize root storages for all resource types
879 m_xUserRootCommit
.set( m_pStorageHandler
[css::ui::UIElementType::MENUBAR
]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY
); // can be empty
880 m_xDefaultConfigStorage
= m_pStorageHandler
[css::ui::UIElementType::MENUBAR
]->getParentStorageShare();
881 m_xUserConfigStorage
= m_pStorageHandler
[css::ui::UIElementType::MENUBAR
]->getParentStorageUser();
883 if ( m_xUserConfigStorage
.is() )
885 Reference
< XPropertySet
> xPropSet( m_xUserConfigStorage
, UNO_QUERY
);
888 tools::Long nOpenMode
= 0;
889 Any a
= xPropSet
->getPropertyValue(u
"OpenMode"_ustr
);
890 if ( a
>>= nOpenMode
)
891 m_bReadOnly
= !( nOpenMode
& ElementModes::WRITE
);
899 void SAL_CALL
ModuleUIConfigurationManager::dispose()
901 Reference
< XComponent
> xThis(this);
903 css::lang::EventObject
aEvent( xThis
);
905 std::unique_lock
aGuard(m_mutex
);
906 m_aEventListeners
.disposeAndClear( aGuard
, aEvent
);
909 std::unique_lock
aGuard(m_mutex
);
910 m_aConfigListeners
.disposeAndClear( aGuard
, aEvent
);
913 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
914 SolarMutexClearableGuard aGuard
;
915 Reference
< XComponent
> xModuleImageManager( m_xModuleImageManager
);
916 m_xModuleImageManager
.clear();
917 m_xModuleAcceleratorManager
.clear();
918 m_aUIElements
[LAYER_USERDEFINED
].clear();
919 m_aUIElements
[LAYER_DEFAULT
].clear();
920 m_xDefaultConfigStorage
.clear();
921 m_xUserConfigStorage
.clear();
922 m_xUserRootCommit
.clear();
926 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
930 if ( xModuleImageManager
.is() )
931 xModuleImageManager
->dispose();
933 catch ( const Exception
& )
938 void SAL_CALL
ModuleUIConfigurationManager::addEventListener( const Reference
< XEventListener
>& xListener
)
943 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
945 throw DisposedException();
948 std::unique_lock
aGuard(m_mutex
);
949 m_aEventListeners
.addInterface( aGuard
, xListener
);
952 void SAL_CALL
ModuleUIConfigurationManager::removeEventListener( const Reference
< XEventListener
>& xListener
)
954 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
955 std::unique_lock
aGuard(m_mutex
);
956 m_aEventListeners
.removeInterface( aGuard
, xListener
);
960 void SAL_CALL
ModuleUIConfigurationManager::addConfigurationListener( const Reference
< css::ui::XUIConfigurationListener
>& xListener
)
965 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
967 throw DisposedException();
970 std::unique_lock
aGuard(m_mutex
);
971 m_aConfigListeners
.addInterface( aGuard
, xListener
);
974 void SAL_CALL
ModuleUIConfigurationManager::removeConfigurationListener( const Reference
< css::ui::XUIConfigurationListener
>& xListener
)
976 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
977 std::unique_lock
aGuard(m_mutex
);
978 m_aConfigListeners
.removeInterface( aGuard
, xListener
);
981 // XUIConfigurationManager
982 void SAL_CALL
ModuleUIConfigurationManager::reset()
984 SolarMutexClearableGuard aGuard
;
986 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
988 throw DisposedException();
993 // Remove all elements from our user-defined storage!
996 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
998 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1000 if ( rElementType
.xStorage
.is() )
1002 bool bCommitSubStorage( false );
1003 const Sequence
< OUString
> aUIElementStreamNames
= rElementType
.xStorage
->getElementNames();
1004 for ( OUString
const & rName
: aUIElementStreamNames
)
1006 rElementType
.xStorage
->removeElement( rName
);
1007 bCommitSubStorage
= true;
1010 if ( bCommitSubStorage
)
1012 Reference
< XTransactedObject
> xTransactedObject( rElementType
.xStorage
, UNO_QUERY
);
1013 if ( xTransactedObject
.is() )
1014 xTransactedObject
->commit();
1015 m_pStorageHandler
[i
]->commitUserChanges();
1020 // remove settings from user defined layer and notify listener about removed settings data!
1021 ConfigEventNotifyContainer aRemoveEventNotifyContainer
;
1022 ConfigEventNotifyContainer aReplaceEventNotifyContainer
;
1023 for ( sal_Int16 j
= 1; j
< css::ui::UIElementType::COUNT
; j
++ )
1027 UIElementType
& rUserElementType
= m_aUIElements
[LAYER_USERDEFINED
][j
];
1028 UIElementType
& rDefaultElementType
= m_aUIElements
[LAYER_DEFAULT
][j
];
1030 impl_resetElementTypeData( rUserElementType
, rDefaultElementType
, aRemoveEventNotifyContainer
, aReplaceEventNotifyContainer
);
1031 rUserElementType
.bModified
= false;
1033 catch (const Exception
&)
1035 css::uno::Any anyEx
= cppu::getCaughtException();
1036 throw css::lang::WrappedTargetRuntimeException(
1037 u
"ModuleUIConfigurationManager::reset exception"_ustr
,
1038 css::uno::Reference
<css::uno::XInterface
>(*this), anyEx
);
1042 m_bModified
= false;
1044 // Unlock mutex before notify our listeners
1047 // Notify our listeners
1048 for ( auto const & k
: aRemoveEventNotifyContainer
)
1049 implts_notifyContainerListener( k
, NotifyOp_Remove
);
1050 for ( auto const & k
: aReplaceEventNotifyContainer
)
1051 implts_notifyContainerListener( k
, NotifyOp_Replace
);
1053 catch ( const css::lang::IllegalArgumentException
& )
1056 catch ( const css::container::NoSuchElementException
& )
1059 catch ( const css::embed::InvalidStorageException
& )
1062 catch ( const css::embed::StorageWrappedTargetException
& )
1067 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType
)
1069 if (( ElementType
< 0 ) || ( ElementType
>= css::ui::UIElementType::COUNT
))
1070 throw IllegalArgumentException();
1074 throw DisposedException();
1076 std::vector
< Sequence
< PropertyValue
> > aElementInfoSeq
;
1077 UIElementInfoHashMap aUIElementInfoCollection
;
1079 if ( ElementType
== css::ui::UIElementType::UNKNOWN
)
1081 for ( sal_Int16 i
= 0; i
< css::ui::UIElementType::COUNT
; i
++ )
1082 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection
, i
);
1085 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection
, ElementType
);
1087 aElementInfoSeq
.resize( aUIElementInfoCollection
.size() );
1090 for (auto const& elem
: aUIElementInfoCollection
)
1092 aElementInfoSeq
[n
++] = Sequence
<PropertyValue
> {
1093 comphelper::makePropertyValue(u
"ResourceURL"_ustr
, elem
.second
.aResourceURL
),
1094 comphelper::makePropertyValue(m_aPropUIName
, elem
.second
.aUIName
)
1098 return comphelper::containerToSequence(aElementInfoSeq
);
1101 Reference
< XIndexContainer
> SAL_CALL
ModuleUIConfigurationManager::createSettings()
1106 throw DisposedException();
1108 // Creates an empty item container which can be filled from outside
1109 return Reference
< XIndexContainer
>( new RootItemContainer() );
1112 sal_Bool SAL_CALL
ModuleUIConfigurationManager::hasSettings( const OUString
& ResourceURL
)
1114 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1116 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1117 ( nElementType
>= css::ui::UIElementType::COUNT
))
1118 throw IllegalArgumentException();
1123 throw DisposedException();
1125 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
, false );
1126 if ( pDataSettings
)
1132 Reference
< XIndexAccess
> SAL_CALL
ModuleUIConfigurationManager::getSettings( const OUString
& ResourceURL
, sal_Bool bWriteable
)
1134 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1136 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1137 ( nElementType
>= css::ui::UIElementType::COUNT
))
1138 throw IllegalArgumentException();
1143 throw DisposedException();
1145 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1146 if ( pDataSettings
)
1148 // Create a copy of our data if someone wants to change the data.
1150 return Reference
< XIndexAccess
>( new RootItemContainer( pDataSettings
->xSettings
) );
1152 return pDataSettings
->xSettings
;
1155 throw NoSuchElementException();
1158 void SAL_CALL
ModuleUIConfigurationManager::replaceSettings( const OUString
& ResourceURL
, const Reference
< css::container::XIndexAccess
>& aNewData
)
1160 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1162 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1163 ( nElementType
>= css::ui::UIElementType::COUNT
))
1164 throw IllegalArgumentException();
1165 else if ( m_bReadOnly
)
1166 throw IllegalAccessException();
1169 SolarMutexClearableGuard aGuard
;
1172 throw DisposedException();
1174 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1175 if ( !pDataSettings
)
1176 throw NoSuchElementException();
1177 if ( !pDataSettings
->bDefaultNode
)
1179 // we have a settings entry in our user-defined layer - replace
1180 Reference
< XIndexAccess
> xOldSettings
= pDataSettings
->xSettings
;
1182 // Create a copy of the data if the container is not const
1183 Reference
< XIndexReplace
> xReplace( aNewData
, UNO_QUERY
);
1184 if ( xReplace
.is() )
1185 pDataSettings
->xSettings
= new ConstItemContainer( aNewData
);
1187 pDataSettings
->xSettings
= aNewData
;
1188 pDataSettings
->bDefault
= false;
1189 pDataSettings
->bModified
= true;
1192 // Modify type container
1193 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1194 rElementType
.bModified
= true;
1196 Reference
< XUIConfigurationManager
> xThis(this);
1198 // Create event to notify listener about replaced element settings
1199 ui::ConfigurationEvent aEvent
;
1200 aEvent
.ResourceURL
= ResourceURL
;
1201 aEvent
.Accessor
<<= xThis
;
1202 aEvent
.Source
.set(xThis
, UNO_QUERY
);
1203 aEvent
.ReplacedElement
<<= xOldSettings
;
1204 aEvent
.Element
<<= pDataSettings
->xSettings
;
1208 implts_notifyContainerListener( aEvent
, NotifyOp_Replace
);
1212 // we have no settings in our user-defined layer - insert
1213 UIElementData aUIElementData
;
1215 aUIElementData
.bDefault
= false;
1216 aUIElementData
.bDefaultNode
= false;
1217 aUIElementData
.bModified
= true;
1219 // Create a copy of the data if the container is not const
1220 Reference
< XIndexReplace
> xReplace( aNewData
, UNO_QUERY
);
1221 if ( xReplace
.is() )
1222 aUIElementData
.xSettings
= new ConstItemContainer( aNewData
);
1224 aUIElementData
.xSettings
= aNewData
;
1225 aUIElementData
.aName
= RetrieveNameFromResourceURL( ResourceURL
) + m_aXMLPostfix
;
1226 aUIElementData
.aResourceURL
= ResourceURL
;
1229 // Modify type container
1230 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1231 rElementType
.bModified
= true;
1233 UIElementDataHashMap
& rElements
= rElementType
.aElementsHashMap
;
1235 // Check our user element settings hash map as it can already contain settings that have been set to default!
1236 // If no node can be found, we have to insert it.
1237 UIElementDataHashMap::iterator pIter
= rElements
.find( ResourceURL
);
1238 if ( pIter
!= rElements
.end() )
1239 pIter
->second
= aUIElementData
;
1241 rElements
.emplace( ResourceURL
, aUIElementData
);
1243 Reference
< XUIConfigurationManager
> xThis(this);
1245 // Create event to notify listener about replaced element settings
1246 ui::ConfigurationEvent aEvent
;
1248 aEvent
.ResourceURL
= ResourceURL
;
1249 aEvent
.Accessor
<<= xThis
;
1250 aEvent
.Source
.set(xThis
, UNO_QUERY
);
1251 aEvent
.ReplacedElement
<<= pDataSettings
->xSettings
;
1252 aEvent
.Element
<<= aUIElementData
.xSettings
;
1256 implts_notifyContainerListener( aEvent
, NotifyOp_Replace
);
1261 void SAL_CALL
ModuleUIConfigurationManager::removeSettings( const OUString
& ResourceURL
)
1263 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1265 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1266 ( nElementType
>= css::ui::UIElementType::COUNT
))
1267 throw IllegalArgumentException( "The ResourceURL is not valid or "
1268 "describes an unknown type. "
1269 "ResourceURL: " + ResourceURL
, nullptr, 0 );
1270 else if ( m_bReadOnly
)
1271 throw IllegalAccessException( "The configuration manager is read-only. "
1272 "ResourceURL: " + ResourceURL
, nullptr );
1275 SolarMutexClearableGuard aGuard
;
1278 throw DisposedException( "The configuration manager has been disposed, "
1279 "and can't uphold its method specification anymore. "
1280 "ResourceURL: " + ResourceURL
, nullptr );
1282 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1283 if ( !pDataSettings
)
1284 throw NoSuchElementException( "The settings data cannot be found. "
1285 "ResourceURL: " + ResourceURL
, nullptr );
1286 // If element settings are default, we don't need to change anything!
1287 if ( pDataSettings
->bDefault
)
1291 Reference
< XIndexAccess
> xRemovedSettings
= pDataSettings
->xSettings
;
1292 pDataSettings
->bDefault
= true;
1294 // check if this is a default layer node
1295 if ( !pDataSettings
->bDefaultNode
)
1296 pDataSettings
->bModified
= true; // we have to remove this node from the user layer!
1297 pDataSettings
->xSettings
.clear();
1298 m_bModified
= true; // user layer must be written
1300 // Modify type container
1301 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1302 rElementType
.bModified
= true;
1304 Reference
< XUIConfigurationManager
> xThis(this);
1305 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
1307 // Check if we have settings in the default layer which replaces the user-defined one!
1308 UIElementData
* pDefaultDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1309 if ( pDefaultDataSettings
)
1311 // Create event to notify listener about replaced element settings
1312 ui::ConfigurationEvent aEvent
;
1314 aEvent
.ResourceURL
= ResourceURL
;
1315 aEvent
.Accessor
<<= xThis
;
1316 aEvent
.Source
= std::move(xIfac
);
1317 aEvent
.Element
<<= xRemovedSettings
;
1318 aEvent
.ReplacedElement
<<= pDefaultDataSettings
->xSettings
;
1322 implts_notifyContainerListener( aEvent
, NotifyOp_Replace
);
1326 // Create event to notify listener about removed element settings
1327 ui::ConfigurationEvent aEvent
;
1329 aEvent
.ResourceURL
= ResourceURL
;
1330 aEvent
.Accessor
<<= xThis
;
1331 aEvent
.Source
= std::move(xIfac
);
1332 aEvent
.Element
<<= xRemovedSettings
;
1336 implts_notifyContainerListener( aEvent
, NotifyOp_Remove
);
1342 void SAL_CALL
ModuleUIConfigurationManager::insertSettings( const OUString
& NewResourceURL
, const Reference
< XIndexAccess
>& aNewData
)
1344 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( NewResourceURL
);
1346 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1347 ( nElementType
>= css::ui::UIElementType::COUNT
))
1348 throw IllegalArgumentException();
1349 else if ( m_bReadOnly
)
1350 throw IllegalAccessException();
1353 SolarMutexClearableGuard aGuard
;
1356 throw DisposedException();
1358 UIElementData
* pDataSettings
= impl_findUIElementData( NewResourceURL
, nElementType
);
1359 if ( !(!pDataSettings
) )
1360 throw ElementExistException();
1361 UIElementData aUIElementData
;
1363 aUIElementData
.bDefault
= false;
1364 aUIElementData
.bDefaultNode
= false;
1365 aUIElementData
.bModified
= true;
1367 // Create a copy of the data if the container is not const
1368 Reference
< XIndexReplace
> xReplace( aNewData
, UNO_QUERY
);
1369 if ( xReplace
.is() )
1370 aUIElementData
.xSettings
= new ConstItemContainer( aNewData
);
1372 aUIElementData
.xSettings
= aNewData
;
1373 aUIElementData
.aName
= RetrieveNameFromResourceURL( NewResourceURL
) + m_aXMLPostfix
;
1374 aUIElementData
.aResourceURL
= NewResourceURL
;
1377 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1378 rElementType
.bModified
= true;
1380 UIElementDataHashMap
& rElements
= rElementType
.aElementsHashMap
;
1381 rElements
.emplace( NewResourceURL
, aUIElementData
);
1383 Reference
< XIndexAccess
> xInsertSettings( aUIElementData
.xSettings
);
1384 Reference
< XUIConfigurationManager
> xThis(this);
1386 // Create event to notify listener about removed element settings
1387 ui::ConfigurationEvent aEvent
;
1389 aEvent
.ResourceURL
= NewResourceURL
;
1390 aEvent
.Accessor
<<= xThis
;
1391 aEvent
.Source
= xThis
;
1392 aEvent
.Element
<<= xInsertSettings
;
1396 implts_notifyContainerListener( aEvent
, NotifyOp_Insert
);
1400 Reference
< XInterface
> SAL_CALL
ModuleUIConfigurationManager::getImageManager()
1405 throw DisposedException();
1407 if ( !m_xModuleImageManager
.is() )
1409 m_xModuleImageManager
= new ImageManager( m_xContext
, /*bForModule*/true );
1411 uno::Sequence
<uno::Any
> aPropSeq(comphelper::InitAnyPropertySequence(
1413 {"UserConfigStorage", uno::Any(m_xUserConfigStorage
)},
1414 {"ModuleIdentifier", uno::Any(m_aModuleIdentifier
)},
1415 {"UserRootCommit", uno::Any(m_xUserRootCommit
)},
1417 m_xModuleImageManager
->initialize( aPropSeq
);
1420 return Reference
< XInterface
>( static_cast<cppu::OWeakObject
*>(m_xModuleImageManager
.get()), UNO_QUERY
);
1423 Reference
< ui::XAcceleratorConfiguration
> SAL_CALL
ModuleUIConfigurationManager::createShortCutManager()
1425 return ui::ModuleAcceleratorConfiguration::createWithModuleIdentifier(m_xContext
, m_aModuleIdentifier
);
1428 Reference
< ui::XAcceleratorConfiguration
> SAL_CALL
ModuleUIConfigurationManager::getShortCutManager()
1433 throw DisposedException();
1435 if ( !m_xModuleAcceleratorManager
.is() ) try
1437 m_xModuleAcceleratorManager
= ui::ModuleAcceleratorConfiguration::
1438 createWithModuleIdentifier(m_xContext
, m_aModuleIdentifier
);
1440 catch ( const css::uno::DeploymentException
& )
1442 SAL_WARN("fwk.uiconfiguration", "ModuleAcceleratorConfiguration"
1443 " not available. This should happen only on mobile platforms.");
1446 return m_xModuleAcceleratorManager
;
1449 Reference
< XInterface
> SAL_CALL
ModuleUIConfigurationManager::getEventsManager()
1451 return Reference
< XInterface
>();
1454 // XModuleUIConfigurationManager
1455 sal_Bool SAL_CALL
ModuleUIConfigurationManager::isDefaultSettings( const OUString
& ResourceURL
)
1457 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1459 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1460 ( nElementType
>= css::ui::UIElementType::COUNT
))
1461 throw IllegalArgumentException();
1466 throw DisposedException();
1468 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
, false );
1469 if ( pDataSettings
&& pDataSettings
->bDefaultNode
)
1475 Reference
< XIndexAccess
> SAL_CALL
ModuleUIConfigurationManager::getDefaultSettings( const OUString
& ResourceURL
)
1477 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1479 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1480 ( nElementType
>= css::ui::UIElementType::COUNT
))
1481 throw IllegalArgumentException();
1486 throw DisposedException();
1488 // preload list of element types on demand
1489 impl_preloadUIElementTypeList( LAYER_DEFAULT
, nElementType
);
1491 // Look into our default vector/unordered_map combination
1492 UIElementDataHashMap
& rDefaultHashMap
= m_aUIElements
[LAYER_DEFAULT
][nElementType
].aElementsHashMap
;
1493 UIElementDataHashMap::iterator pIter
= rDefaultHashMap
.find( ResourceURL
);
1494 if ( pIter
!= rDefaultHashMap
.end() )
1496 if ( !pIter
->second
.xSettings
.is() )
1497 impl_requestUIElementData( nElementType
, LAYER_DEFAULT
, pIter
->second
);
1498 return pIter
->second
.xSettings
;
1501 // Nothing has been found!
1502 throw NoSuchElementException();
1505 // XUIConfigurationPersistence
1506 void SAL_CALL
ModuleUIConfigurationManager::reload()
1508 SolarMutexClearableGuard aGuard
;
1511 throw DisposedException();
1513 if ( !m_xUserConfigStorage
.is() || !m_bModified
|| m_bReadOnly
)
1516 // Try to access our module sub folder
1517 ConfigEventNotifyContainer aRemoveNotifyContainer
;
1518 ConfigEventNotifyContainer aReplaceNotifyContainer
;
1519 for ( sal_Int16 i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
1523 UIElementType
& rUserElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1525 if ( rUserElementType
.bModified
)
1527 UIElementType
& rDefaultElementType
= m_aUIElements
[LAYER_DEFAULT
][i
];
1528 impl_reloadElementTypeData( rUserElementType
, rDefaultElementType
, aRemoveNotifyContainer
, aReplaceNotifyContainer
);
1531 catch ( const Exception
& )
1533 throw IOException();
1537 m_bModified
= false;
1539 // Unlock mutex before notify our listeners
1542 // Notify our listeners
1543 for (const ui::ConfigurationEvent
& j
: aRemoveNotifyContainer
)
1544 implts_notifyContainerListener( j
, NotifyOp_Remove
);
1545 for (const ui::ConfigurationEvent
& k
: aReplaceNotifyContainer
)
1546 implts_notifyContainerListener( k
, NotifyOp_Replace
);
1549 void SAL_CALL
ModuleUIConfigurationManager::store()
1554 throw DisposedException();
1556 if ( !m_xUserConfigStorage
.is() || !m_bModified
|| m_bReadOnly
)
1559 // Try to access our module sub folder
1560 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
1564 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1566 if ( rElementType
.bModified
&& rElementType
.xStorage
.is() )
1568 impl_storeElementTypeData( rElementType
.xStorage
, rElementType
);
1569 m_pStorageHandler
[i
]->commitUserChanges();
1572 catch ( const Exception
& )
1574 throw IOException();
1578 m_bModified
= false;
1581 void SAL_CALL
ModuleUIConfigurationManager::storeToStorage( const Reference
< XStorage
>& Storage
)
1586 throw DisposedException();
1588 if ( !m_xUserConfigStorage
.is() || !m_bModified
|| m_bReadOnly
)
1591 // Try to access our module sub folder
1592 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
1596 Reference
< XStorage
> xElementTypeStorage( Storage
->openStorageElement(
1597 OUString(UIELEMENTTYPENAMES
[i
]), ElementModes::READWRITE
));
1598 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1600 if ( rElementType
.bModified
&& xElementTypeStorage
.is() )
1601 impl_storeElementTypeData( xElementTypeStorage
, rElementType
, false ); // store data to storage, but don't reset modify flag!
1603 catch ( const Exception
& )
1605 throw IOException();
1609 Reference
< XTransactedObject
> xTransactedObject( Storage
, UNO_QUERY
);
1610 if ( xTransactedObject
.is() )
1611 xTransactedObject
->commit();
1614 sal_Bool SAL_CALL
ModuleUIConfigurationManager::isModified()
1621 sal_Bool SAL_CALL
ModuleUIConfigurationManager::isReadOnly()
1628 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ui::ConfigurationEvent
& aEvent
, NotifyOp eOp
)
1630 std::unique_lock
aGuard(m_mutex
);
1631 using ListenerMethodType
= void (SAL_CALL
css::ui::XUIConfigurationListener::*)(const ui::ConfigurationEvent
&);
1632 ListenerMethodType aListenerMethod
{};
1635 case NotifyOp_Replace
:
1636 aListenerMethod
= &css::ui::XUIConfigurationListener::elementReplaced
;
1638 case NotifyOp_Insert
:
1639 aListenerMethod
= &css::ui::XUIConfigurationListener::elementInserted
;
1641 case NotifyOp_Remove
:
1642 aListenerMethod
= &css::ui::XUIConfigurationListener::elementRemoved
;
1645 m_aConfigListeners
.notifyEach(aGuard
, aListenerMethod
, aEvent
);
1650 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1651 com_sun_star_comp_framework_ModuleUIConfigurationManager_get_implementation(
1652 css::uno::XComponentContext
*context
,
1653 css::uno::Sequence
<css::uno::Any
> const &arguments
)
1655 return cppu::acquire(new ModuleUIConfigurationManager(context
, arguments
));
1658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */