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/moduleimagemanager.hxx>
23 #include <uielement/constitemcontainer.hxx>
24 #include <uielement/rootitemcontainer.hxx>
25 #include <uielement/uielementtypenames.hxx>
26 #include <framework/menuconfiguration.hxx>
27 #include <framework/toolboxconfiguration.hxx>
29 #include <framework/statusbarconfiguration.hxx>
31 #include <com/sun/star/ui/UIElementType.hpp>
32 #include <com/sun/star/ui/ConfigurationEvent.hpp>
33 #include <com/sun/star/ui/ModuleAcceleratorConfiguration.hpp>
34 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
35 #include <com/sun/star/ui/XModuleUIConfigurationManager2.hpp>
36 #include <com/sun/star/lang/DisposedException.hpp>
37 #include <com/sun/star/lang/IllegalAccessException.hpp>
38 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/embed/ElementModes.hpp>
41 #include <com/sun/star/embed/InvalidStorageException.hpp>
42 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
43 #include <com/sun/star/embed/XTransactedObject.hpp>
44 #include <com/sun/star/container/ElementExistException.hpp>
45 #include <com/sun/star/container/XNameAccess.hpp>
46 #include <com/sun/star/container/XIndexContainer.hpp>
47 #include <com/sun/star/io/IOException.hpp>
48 #include <com/sun/star/io/XStream.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
50 #include <com/sun/star/lang/XComponent.hpp>
52 #include <comphelper/propertysequence.hxx>
53 #include <comphelper/sequence.hxx>
54 #include <cppuhelper/exc_hlp.hxx>
55 #include <cppuhelper/implbase.hxx>
56 #include <cppuhelper/interfacecontainer.hxx>
57 #include <cppuhelper/supportsservice.hxx>
58 #include <vcl/svapp.hxx>
59 #include <rtl/ref.hxx>
60 #include <rtl/ustrbuf.hxx>
61 #include <sal/log.hxx>
62 #include <comphelper/sequenceashashmap.hxx>
63 #include <comphelper/servicehelper.hxx>
67 using namespace com::sun::star::uno
;
68 using namespace com::sun::star::io
;
69 using namespace com::sun::star::embed
;
70 using namespace com::sun::star::lang
;
71 using namespace com::sun::star::container
;
72 using namespace com::sun::star::beans
;
73 using namespace framework
;
75 #define RESOURCETYPE_MENUBAR "menubar"
76 #define RESOURCETYPE_TOOLBAR "toolbar"
77 #define RESOURCETYPE_STATUSBAR "statusbar"
78 #define RESOURCETYPE_POPUPMENU "popupmenu"
82 class ModuleUIConfigurationManager
: public cppu::WeakImplHelper
<
83 css::lang::XServiceInfo
,
84 css::lang::XComponent
,
85 css::ui::XModuleUIConfigurationManager2
>
88 ModuleUIConfigurationManager(
89 const css::uno::Reference
< css::uno::XComponentContext
>& xServiceManager
,
90 const css::uno::Sequence
< css::uno::Any
>& aArguments
);
92 virtual OUString SAL_CALL
getImplementationName() override
94 return "com.sun.star.comp.framework.ModuleUIConfigurationManager";
97 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
99 return cppu::supportsService(this, ServiceName
);
102 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
104 return {"com.sun.star.ui.ModuleUIConfigurationManager"};
108 virtual void SAL_CALL
dispose() override
;
109 virtual void SAL_CALL
addEventListener( const css::uno::Reference
< css::lang::XEventListener
>& xListener
) override
;
110 virtual void SAL_CALL
removeEventListener( const css::uno::Reference
< css::lang::XEventListener
>& aListener
) override
;
113 virtual void SAL_CALL
addConfigurationListener( const css::uno::Reference
< css::ui::XUIConfigurationListener
>& Listener
) override
;
114 virtual void SAL_CALL
removeConfigurationListener( const css::uno::Reference
< css::ui::XUIConfigurationListener
>& Listener
) override
;
116 // XUIConfigurationManager
117 virtual void SAL_CALL
reset() override
;
118 virtual css::uno::Sequence
< css::uno::Sequence
< css::beans::PropertyValue
> > SAL_CALL
getUIElementsInfo( sal_Int16 ElementType
) override
;
119 virtual css::uno::Reference
< css::container::XIndexContainer
> SAL_CALL
createSettings( ) override
;
120 virtual sal_Bool SAL_CALL
hasSettings( const OUString
& ResourceURL
) override
;
121 virtual css::uno::Reference
< css::container::XIndexAccess
> SAL_CALL
getSettings( const OUString
& ResourceURL
, sal_Bool bWriteable
) override
;
122 virtual void SAL_CALL
replaceSettings( const OUString
& ResourceURL
, const css::uno::Reference
< css::container::XIndexAccess
>& aNewData
) override
;
123 virtual void SAL_CALL
removeSettings( const OUString
& ResourceURL
) override
;
124 virtual void SAL_CALL
insertSettings( const OUString
& NewResourceURL
, const css::uno::Reference
< css::container::XIndexAccess
>& aNewData
) override
;
125 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
getImageManager() override
;
126 virtual css::uno::Reference
< css::ui::XAcceleratorConfiguration
> SAL_CALL
getShortCutManager() override
;
127 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
getEventsManager() override
;
129 // XModuleUIConfigurationManager
130 virtual sal_Bool SAL_CALL
isDefaultSettings( const OUString
& ResourceURL
) override
;
131 virtual css::uno::Reference
< css::container::XIndexAccess
> SAL_CALL
getDefaultSettings( const OUString
& ResourceURL
) override
;
133 // XUIConfigurationPersistence
134 virtual void SAL_CALL
reload() override
;
135 virtual void SAL_CALL
store() override
;
136 virtual void SAL_CALL
storeToStorage( const css::uno::Reference
< css::embed::XStorage
>& Storage
) override
;
137 virtual sal_Bool SAL_CALL
isModified() override
;
138 virtual sal_Bool SAL_CALL
isReadOnly() override
;
141 // private data types
158 UIElementInfo( const OUString
& rResourceURL
, const OUString
& rUIName
) :
159 aResourceURL( rResourceURL
), aUIName( rUIName
) {}
160 OUString aResourceURL
;
166 UIElementData() : bModified( false ), bDefault( true ), bDefaultNode( true ) {};
168 OUString aResourceURL
;
170 bool bModified
; // has been changed since last storing
171 bool bDefault
; // default settings
172 bool bDefaultNode
; // this is a default layer element data
173 css::uno::Reference
< css::container::XIndexAccess
> xSettings
;
176 typedef std::unordered_map
< OUString
, UIElementData
> UIElementDataHashMap
;
180 UIElementType() : bModified( false ),
182 nElementType( css::ui::UIElementType::UNKNOWN
) {}
186 sal_Int16 nElementType
;
187 UIElementDataHashMap aElementsHashMap
;
188 css::uno::Reference
< css::embed::XStorage
> xStorage
;
191 typedef std::vector
< UIElementType
> UIElementTypesVector
;
192 typedef std::vector
< css::ui::ConfigurationEvent
> ConfigEventNotifyContainer
;
193 typedef std::unordered_map
< OUString
, UIElementInfo
> UIElementInfoHashMap
;
195 void impl_Initialize();
196 void implts_notifyContainerListener( const css::ui::ConfigurationEvent
& aEvent
, NotifyOp eOp
);
197 void impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap
& aUIElementInfoCollection
, sal_Int16 nElementType
);
198 void impl_preloadUIElementTypeList( Layer eLayer
, sal_Int16 nElementType
);
199 UIElementData
* impl_findUIElementData( const OUString
& aResourceURL
, sal_Int16 nElementType
, bool bLoad
= true );
200 void impl_requestUIElementData( sal_Int16 nElementType
, Layer eLayer
, UIElementData
& aUIElementData
);
201 void impl_storeElementTypeData( const css::uno::Reference
< css::embed::XStorage
>& xStorage
, UIElementType
& rElementType
, bool bResetModifyState
= true );
202 void impl_resetElementTypeData( UIElementType
& rUserElementType
, UIElementType
const & rDefaultElementType
, ConfigEventNotifyContainer
& rRemoveNotifyContainer
, ConfigEventNotifyContainer
& rReplaceNotifyContainer
);
203 void impl_reloadElementTypeData( UIElementType
& rUserElementType
, UIElementType
const & rDefaultElementType
, ConfigEventNotifyContainer
& rRemoveNotifyContainer
, ConfigEventNotifyContainer
& rReplaceNotifyContainer
);
205 UIElementTypesVector m_aUIElements
[LAYER_COUNT
];
206 std::unique_ptr
<PresetHandler
> m_pStorageHandler
[css::ui::UIElementType::COUNT
];
207 css::uno::Reference
< css::embed::XStorage
> m_xDefaultConfigStorage
;
208 css::uno::Reference
< css::embed::XStorage
> m_xUserConfigStorage
;
212 OUString m_aXMLPostfix
;
213 OUString m_aPropUIName
;
214 OUString m_aModuleIdentifier
;
215 css::uno::Reference
< css::embed::XTransactedObject
> m_xUserRootCommit
;
216 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
218 ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer
; /// container for ALL Listener
219 css::uno::Reference
< css::lang::XComponent
> m_xModuleImageManager
;
220 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> m_xModuleAcceleratorManager
;
223 // important: The order and position of the elements must match the constant
224 // definition of "css::ui::UIElementType"
225 static OUStringLiteral UIELEMENTTYPENAMES
[] =
227 "", // Dummy value for unknown!
228 UIELEMENTTYPE_MENUBAR_NAME
,
229 UIELEMENTTYPE_POPUPMENU_NAME
,
230 UIELEMENTTYPE_TOOLBAR_NAME
,
231 UIELEMENTTYPE_STATUSBAR_NAME
,
232 UIELEMENTTYPE_FLOATINGWINDOW_NAME
,
233 UIELEMENTTYPE_PROGRESSBAR_NAME
,
234 UIELEMENTTYPE_TOOLPANEL_NAME
237 static const char RESOURCEURL_PREFIX
[] = "private:resource/";
238 static const sal_Int32 RESOURCEURL_PREFIX_SIZE
= strlen(RESOURCEURL_PREFIX
);
240 sal_Int16
RetrieveTypeFromResourceURL( const OUString
& aResourceURL
)
243 if (( aResourceURL
.startsWith( RESOURCEURL_PREFIX
) ) &&
244 ( aResourceURL
.getLength() > RESOURCEURL_PREFIX_SIZE
))
246 OUString aTmpStr
= aResourceURL
.copy( RESOURCEURL_PREFIX_SIZE
);
247 sal_Int32 nIndex
= aTmpStr
.indexOf( '/' );
248 if (( nIndex
> 0 ) && ( aTmpStr
.getLength() > nIndex
))
250 OUString
aTypeStr( aTmpStr
.copy( 0, nIndex
));
251 for ( int i
= 0; i
< ui::UIElementType::COUNT
; i
++ )
253 if ( aTypeStr
== UIELEMENTTYPENAMES
[i
] )
254 return sal_Int16( i
);
259 return ui::UIElementType::UNKNOWN
;
262 OUString
RetrieveNameFromResourceURL( const OUString
& aResourceURL
)
264 if (( aResourceURL
.startsWith( RESOURCEURL_PREFIX
) ) &&
265 ( aResourceURL
.getLength() > RESOURCEURL_PREFIX_SIZE
))
267 sal_Int32 nIndex
= aResourceURL
.lastIndexOf( '/' );
268 if (( nIndex
> 0 ) && (( nIndex
+1 ) < aResourceURL
.getLength()))
269 return aResourceURL
.copy( nIndex
+1 );
275 void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap
& aUIElementInfoCollection
, sal_Int16 nElementType
)
277 // preload list of element types on demand
278 impl_preloadUIElementTypeList( LAYER_USERDEFINED
, nElementType
);
279 impl_preloadUIElementTypeList( LAYER_DEFAULT
, nElementType
);
281 UIElementDataHashMap
& rUserElements
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
].aElementsHashMap
;
283 OUString
aCustomUrlPrefix( "custom_" );
284 for (auto const& userElement
: rUserElements
)
286 sal_Int32 nIndex
= userElement
.second
.aResourceURL
.indexOf( aCustomUrlPrefix
, RESOURCEURL_PREFIX_SIZE
);
287 if ( nIndex
> RESOURCEURL_PREFIX_SIZE
)
289 // Performance: Retrieve user interface name only for custom user interface elements.
290 // It's only used by them!
291 UIElementData
* pDataSettings
= impl_findUIElementData( userElement
.second
.aResourceURL
, nElementType
);
294 // Retrieve user interface name from XPropertySet interface
296 Reference
< XPropertySet
> xPropSet( pDataSettings
->xSettings
, UNO_QUERY
);
299 Any a
= xPropSet
->getPropertyValue( m_aPropUIName
);
303 UIElementInfo
aInfo( userElement
.second
.aResourceURL
, aUIName
);
304 aUIElementInfoCollection
.emplace( userElement
.second
.aResourceURL
, aInfo
);
309 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
310 UIElementInfo
aInfo( userElement
.second
.aResourceURL
, OUString() );
311 aUIElementInfoCollection
.emplace( userElement
.second
.aResourceURL
, aInfo
);
315 UIElementDataHashMap
& rDefaultElements
= m_aUIElements
[LAYER_DEFAULT
][nElementType
].aElementsHashMap
;
317 for (auto const& defaultElement
: rDefaultElements
)
319 UIElementInfoHashMap::const_iterator pIterInfo
= aUIElementInfoCollection
.find( defaultElement
.second
.aResourceURL
);
320 if ( pIterInfo
== aUIElementInfoCollection
.end() )
322 sal_Int32 nIndex
= defaultElement
.second
.aResourceURL
.indexOf( aCustomUrlPrefix
, RESOURCEURL_PREFIX_SIZE
);
323 if ( nIndex
> RESOURCEURL_PREFIX_SIZE
)
325 // Performance: Retrieve user interface name only for custom user interface elements.
326 // It's only used by them!
327 UIElementData
* pDataSettings
= impl_findUIElementData( defaultElement
.second
.aResourceURL
, nElementType
);
330 // Retrieve user interface name from XPropertySet interface
332 Reference
< XPropertySet
> xPropSet( pDataSettings
->xSettings
, UNO_QUERY
);
335 Any a
= xPropSet
->getPropertyValue( m_aPropUIName
);
338 UIElementInfo
aInfo( defaultElement
.second
.aResourceURL
, aUIName
);
339 aUIElementInfoCollection
.emplace( defaultElement
.second
.aResourceURL
, aInfo
);
344 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
345 UIElementInfo
aInfo( defaultElement
.second
.aResourceURL
, OUString() );
346 aUIElementInfoCollection
.emplace( defaultElement
.second
.aResourceURL
, aInfo
);
352 void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer
, sal_Int16 nElementType
)
354 UIElementType
& rElementTypeData
= m_aUIElements
[eLayer
][nElementType
];
356 if ( !rElementTypeData
.bLoaded
)
358 Reference
< XStorage
> xElementTypeStorage
= rElementTypeData
.xStorage
;
359 if ( xElementTypeStorage
.is() )
361 OUString aResURLPrefix
=
363 UIELEMENTTYPENAMES
[ nElementType
] +
366 UIElementDataHashMap
& rHashMap
= rElementTypeData
.aElementsHashMap
;
367 Sequence
< OUString
> aUIElementNames
= xElementTypeStorage
->getElementNames();
368 for ( sal_Int32 n
= 0; n
< aUIElementNames
.getLength(); n
++ )
370 UIElementData aUIElementData
;
372 // Resource name must be without ".xml"
373 sal_Int32 nIndex
= aUIElementNames
[n
].lastIndexOf( '.' );
374 if (( nIndex
> 0 ) && ( nIndex
< aUIElementNames
[n
].getLength() ))
376 OUString
aExtension( aUIElementNames
[n
].copy( nIndex
+1 ));
377 OUString
aUIElementName( aUIElementNames
[n
].copy( 0, nIndex
));
379 if (!aUIElementName
.isEmpty() &&
380 ( aExtension
.equalsIgnoreAsciiCase("xml")))
382 aUIElementData
.aResourceURL
= aResURLPrefix
+ aUIElementName
;
383 aUIElementData
.aName
= aUIElementNames
[n
];
385 if ( eLayer
== LAYER_USERDEFINED
)
387 aUIElementData
.bModified
= false;
388 aUIElementData
.bDefault
= false;
389 aUIElementData
.bDefaultNode
= false;
392 // Create std::unordered_map entries for all user interface elements inside the storage. We don't load the
393 // settings to speed up the process.
394 rHashMap
.emplace( aUIElementData
.aResourceURL
, aUIElementData
);
397 rElementTypeData
.bLoaded
= true;
404 void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType
, Layer eLayer
, UIElementData
& aUIElementData
)
406 UIElementType
& rElementTypeData
= m_aUIElements
[eLayer
][nElementType
];
408 Reference
< XStorage
> xElementTypeStorage
= rElementTypeData
.xStorage
;
409 if ( xElementTypeStorage
.is() && !aUIElementData
.aName
.isEmpty() )
413 Reference
< XStream
> xStream
= xElementTypeStorage
->openStreamElement( aUIElementData
.aName
, ElementModes::READ
);
414 Reference
< XInputStream
> xInputStream
= xStream
->getInputStream();
416 if ( xInputStream
.is() )
418 switch ( nElementType
)
420 case css::ui::UIElementType::UNKNOWN
:
423 case css::ui::UIElementType::MENUBAR
:
424 case css::ui::UIElementType::POPUPMENU
:
428 MenuConfiguration
aMenuCfg( m_xContext
);
429 Reference
< XIndexAccess
> xContainer( aMenuCfg
.CreateMenuBarConfigurationFromXML( xInputStream
));
430 auto pRootItemContainer
= comphelper::getUnoTunnelImplementation
<RootItemContainer
>( xContainer
);
431 if ( pRootItemContainer
)
432 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( pRootItemContainer
, true ) ), UNO_QUERY
);
434 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( xContainer
, true ) ), UNO_QUERY
);
437 catch ( const css::lang::WrappedTargetException
& )
443 case css::ui::UIElementType::TOOLBAR
:
447 Reference
< XIndexContainer
> xIndexContainer( static_cast< OWeakObject
* >( new RootItemContainer() ), UNO_QUERY
);
448 ToolBoxConfiguration::LoadToolBox( m_xContext
, xInputStream
, xIndexContainer
);
449 auto pRootItemContainer
= comphelper::getUnoTunnelImplementation
<RootItemContainer
>( xIndexContainer
);
450 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( pRootItemContainer
, true ) ), UNO_QUERY
);
453 catch ( const css::lang::WrappedTargetException
& )
460 case css::ui::UIElementType::STATUSBAR
:
464 Reference
< XIndexContainer
> xIndexContainer( static_cast< OWeakObject
* >( new RootItemContainer() ), UNO_QUERY
);
465 StatusBarConfiguration::LoadStatusBar( m_xContext
, xInputStream
, xIndexContainer
);
466 auto pRootItemContainer
= comphelper::getUnoTunnelImplementation
<RootItemContainer
>( xIndexContainer
);
467 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( pRootItemContainer
, true ) ), UNO_QUERY
);
470 catch ( const css::lang::WrappedTargetException
& )
477 case css::ui::UIElementType::FLOATINGWINDOW
:
484 catch ( const css::embed::InvalidStorageException
& )
487 catch ( const css::lang::IllegalArgumentException
& )
490 catch ( const css::io::IOException
& )
493 catch ( const css::embed::StorageWrappedTargetException
& )
498 // At least we provide an empty settings container!
499 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer() ), UNO_QUERY
);
502 ModuleUIConfigurationManager::UIElementData
* ModuleUIConfigurationManager::impl_findUIElementData( const OUString
& aResourceURL
, sal_Int16 nElementType
, bool bLoad
)
504 // preload list of element types on demand
505 impl_preloadUIElementTypeList( LAYER_USERDEFINED
, nElementType
);
506 impl_preloadUIElementTypeList( LAYER_DEFAULT
, nElementType
);
508 // first try to look into our user-defined vector/unordered_map combination
509 UIElementDataHashMap
& rUserHashMap
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
].aElementsHashMap
;
510 UIElementDataHashMap::iterator pIter
= rUserHashMap
.find( aResourceURL
);
511 if ( pIter
!= rUserHashMap
.end() )
513 // Default data settings data must be retrieved from the default layer!
514 if ( !pIter
->second
.bDefault
)
516 if ( !pIter
->second
.xSettings
.is() && bLoad
)
517 impl_requestUIElementData( nElementType
, LAYER_USERDEFINED
, pIter
->second
);
518 return &(pIter
->second
);
522 // Not successful, we have to look into our default vector/unordered_map combination
523 UIElementDataHashMap
& rDefaultHashMap
= m_aUIElements
[LAYER_DEFAULT
][nElementType
].aElementsHashMap
;
524 pIter
= rDefaultHashMap
.find( aResourceURL
);
525 if ( pIter
!= rDefaultHashMap
.end() )
527 if ( !pIter
->second
.xSettings
.is() && bLoad
)
528 impl_requestUIElementData( nElementType
, LAYER_DEFAULT
, pIter
->second
);
529 return &(pIter
->second
);
532 // Nothing has been found!
536 void ModuleUIConfigurationManager::impl_storeElementTypeData( const Reference
< XStorage
>& xStorage
, UIElementType
& rElementType
, bool bResetModifyState
)
538 UIElementDataHashMap
& rHashMap
= rElementType
.aElementsHashMap
;
540 for (auto & elem
: rHashMap
)
542 UIElementData
& rElement
= elem
.second
;
543 if ( rElement
.bModified
)
545 if ( rElement
.bDefault
)
547 xStorage
->removeElement( rElement
.aName
);
548 rElement
.bModified
= false; // mark as not modified
552 Reference
< XStream
> xStream
= xStorage
->openStreamElement( rElement
.aName
, ElementModes::WRITE
|ElementModes::TRUNCATE
);
553 Reference
< XOutputStream
> xOutputStream( xStream
->getOutputStream() );
555 if ( xOutputStream
.is() )
557 switch( rElementType
.nElementType
)
559 case css::ui::UIElementType::MENUBAR
:
560 case css::ui::UIElementType::POPUPMENU
:
564 MenuConfiguration
aMenuCfg( m_xContext
);
565 aMenuCfg
.StoreMenuBarConfigurationToXML(
566 rElement
.xSettings
, xOutputStream
, rElementType
.nElementType
== css::ui::UIElementType::MENUBAR
);
568 catch ( const css::lang::WrappedTargetException
& )
574 case css::ui::UIElementType::TOOLBAR
:
578 ToolBoxConfiguration::StoreToolBox( m_xContext
, xOutputStream
, rElement
.xSettings
);
580 catch ( const css::lang::WrappedTargetException
& )
586 case css::ui::UIElementType::STATUSBAR
:
590 StatusBarConfiguration::StoreStatusBar( m_xContext
, xOutputStream
, rElement
.xSettings
);
592 catch ( const css::lang::WrappedTargetException
& )
603 // mark as not modified if we store to our own storage
604 if ( bResetModifyState
)
605 rElement
.bModified
= false;
610 // commit element type storage
611 Reference
< XTransactedObject
> xTransactedObject( xStorage
, UNO_QUERY
);
612 if ( xTransactedObject
.is() )
613 xTransactedObject
->commit();
615 // mark UIElementType as not modified if we store to our own storage
616 if ( bResetModifyState
)
617 rElementType
.bModified
= false;
620 // This is only allowed to be called on the LAYER_USER_DEFINED!
621 void ModuleUIConfigurationManager::impl_resetElementTypeData(
622 UIElementType
& rUserElementType
,
623 UIElementType
const & rDefaultElementType
,
624 ConfigEventNotifyContainer
& rRemoveNotifyContainer
,
625 ConfigEventNotifyContainer
& rReplaceNotifyContainer
)
627 UIElementDataHashMap
& rHashMap
= rUserElementType
.aElementsHashMap
;
629 Reference
< XUIConfigurationManager
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
630 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
631 sal_Int16 nType
= rUserElementType
.nElementType
;
633 // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
635 for (auto & elem
: rHashMap
)
637 UIElementData
& rElement
= elem
.second
;
638 if ( !rElement
.bDefault
)
640 if ( rDefaultElementType
.xStorage
->hasByName( rElement
.aName
))
642 // Replace settings with data from default layer
643 Reference
< XIndexAccess
> xOldSettings( rElement
.xSettings
);
644 impl_requestUIElementData( nType
, LAYER_DEFAULT
, rElement
);
646 ui::ConfigurationEvent aReplaceEvent
;
647 aReplaceEvent
.ResourceURL
= rElement
.aResourceURL
;
648 aReplaceEvent
.Accessor
<<= xThis
;
649 aReplaceEvent
.Source
= xIfac
;
650 aReplaceEvent
.ReplacedElement
<<= xOldSettings
;
651 aReplaceEvent
.Element
<<= rElement
.xSettings
;
653 rReplaceNotifyContainer
.push_back( aReplaceEvent
);
655 // Mark element as default and not modified. That means "not active"
656 // in the user layer anymore.
657 rElement
.bModified
= false;
658 rElement
.bDefault
= true;
662 // Remove user-defined settings from user layer
663 ui::ConfigurationEvent aEvent
;
664 aEvent
.ResourceURL
= rElement
.aResourceURL
;
665 aEvent
.Accessor
<<= xThis
;
666 aEvent
.Source
= xIfac
;
667 aEvent
.Element
<<= rElement
.xSettings
;
669 rRemoveNotifyContainer
.push_back( aEvent
);
671 // Mark element as default and not modified. That means "not active"
672 // in the user layer anymore.
673 rElement
.bModified
= false;
674 rElement
.bDefault
= true;
679 // Remove all settings from our user interface elements
683 void ModuleUIConfigurationManager::impl_reloadElementTypeData(
684 UIElementType
& rUserElementType
,
685 UIElementType
const & rDefaultElementType
,
686 ConfigEventNotifyContainer
& rRemoveNotifyContainer
,
687 ConfigEventNotifyContainer
& rReplaceNotifyContainer
)
689 UIElementDataHashMap
& rHashMap
= rUserElementType
.aElementsHashMap
;
691 Reference
< XUIConfigurationManager
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
692 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
693 sal_Int16 nType
= rUserElementType
.nElementType
;
695 for (auto & elem
: rHashMap
)
697 UIElementData
& rElement
= elem
.second
;
698 if ( rElement
.bModified
)
700 if ( rUserElementType
.xStorage
->hasByName( rElement
.aName
))
702 // Replace settings with data from user layer
703 Reference
< XIndexAccess
> xOldSettings( rElement
.xSettings
);
705 impl_requestUIElementData( nType
, LAYER_USERDEFINED
, rElement
);
707 ui::ConfigurationEvent aReplaceEvent
;
709 aReplaceEvent
.ResourceURL
= rElement
.aResourceURL
;
710 aReplaceEvent
.Accessor
<<= xThis
;
711 aReplaceEvent
.Source
= xIfac
;
712 aReplaceEvent
.ReplacedElement
<<= xOldSettings
;
713 aReplaceEvent
.Element
<<= rElement
.xSettings
;
714 rReplaceNotifyContainer
.push_back( aReplaceEvent
);
716 rElement
.bModified
= false;
718 else if ( rDefaultElementType
.xStorage
->hasByName( rElement
.aName
))
720 // Replace settings with data from default layer
721 Reference
< XIndexAccess
> xOldSettings( rElement
.xSettings
);
723 impl_requestUIElementData( nType
, LAYER_DEFAULT
, rElement
);
725 ui::ConfigurationEvent aReplaceEvent
;
727 aReplaceEvent
.ResourceURL
= rElement
.aResourceURL
;
728 aReplaceEvent
.Accessor
<<= xThis
;
729 aReplaceEvent
.Source
= xIfac
;
730 aReplaceEvent
.ReplacedElement
<<= xOldSettings
;
731 aReplaceEvent
.Element
<<= rElement
.xSettings
;
732 rReplaceNotifyContainer
.push_back( aReplaceEvent
);
734 // Mark element as default and not modified. That means "not active"
735 // in the user layer anymore.
736 rElement
.bModified
= false;
737 rElement
.bDefault
= true;
741 // Element settings are not in any storage => remove
742 ui::ConfigurationEvent aRemoveEvent
;
744 aRemoveEvent
.ResourceURL
= rElement
.aResourceURL
;
745 aRemoveEvent
.Accessor
<<= xThis
;
746 aRemoveEvent
.Source
= xIfac
;
747 aRemoveEvent
.Element
<<= rElement
.xSettings
;
749 rRemoveNotifyContainer
.push_back( aRemoveEvent
);
751 // Mark element as default and not modified. That means "not active"
752 // in the user layer anymore.
753 rElement
.bModified
= false;
754 rElement
.bDefault
= true;
759 rUserElementType
.bModified
= false;
762 void ModuleUIConfigurationManager::impl_Initialize()
764 // Initialize the top-level structures with the storage data
765 if ( m_xUserConfigStorage
.is() )
767 // Try to access our module sub folder
768 for ( sal_Int16 i
= 1; i
< css::ui::UIElementType::COUNT
;
771 Reference
< XStorage
> xElementTypeStorage
;
774 if ( m_pStorageHandler
[i
] )
775 xElementTypeStorage
= m_pStorageHandler
[i
]->getWorkingStorageUser();
777 catch ( const css::container::NoSuchElementException
& )
780 catch ( const css::embed::InvalidStorageException
& )
783 catch ( const css::lang::IllegalArgumentException
& )
786 catch ( const css::io::IOException
& )
789 catch ( const css::embed::StorageWrappedTargetException
& )
793 m_aUIElements
[LAYER_USERDEFINED
][i
].nElementType
= i
;
794 m_aUIElements
[LAYER_USERDEFINED
][i
].bModified
= false;
795 m_aUIElements
[LAYER_USERDEFINED
][i
].xStorage
= xElementTypeStorage
;
799 if ( m_xDefaultConfigStorage
.is() )
801 Reference
< XNameAccess
> xNameAccess( m_xDefaultConfigStorage
, UNO_QUERY_THROW
);
803 // Try to access our module sub folder
804 for ( sal_Int16 i
= 1; i
< css::ui::UIElementType::COUNT
;
807 Reference
< XStorage
> xElementTypeStorage
;
810 const OUString
sName( UIELEMENTTYPENAMES
[i
] );
811 if( xNameAccess
->hasByName( sName
) )
812 xNameAccess
->getByName( sName
) >>= xElementTypeStorage
;
814 catch ( const css::container::NoSuchElementException
& )
818 m_aUIElements
[LAYER_DEFAULT
][i
].nElementType
= i
;
819 m_aUIElements
[LAYER_DEFAULT
][i
].bModified
= false;
820 m_aUIElements
[LAYER_DEFAULT
][i
].xStorage
= xElementTypeStorage
;
825 ModuleUIConfigurationManager::ModuleUIConfigurationManager(
826 const Reference
< XComponentContext
>& xContext
,
827 const css::uno::Sequence
< css::uno::Any
>& aArguments
)
828 : m_bReadOnly( true )
829 , m_bModified( false )
830 , m_bDisposed( false )
831 , m_aXMLPostfix( ".xml" )
832 , m_aPropUIName( "UIName" )
833 , m_xContext( xContext
)
834 , m_aListenerContainer( m_mutex
)
836 // Make sure we have a default initialized entry for every layer and user interface element type!
837 // The following code depends on this!
838 m_aUIElements
[LAYER_DEFAULT
].resize( css::ui::UIElementType::COUNT
);
839 m_aUIElements
[LAYER_USERDEFINED
].resize( css::ui::UIElementType::COUNT
);
843 OUString aModuleShortName
;
844 if( aArguments
.getLength() == 2 && (aArguments
[0] >>= aModuleShortName
) && (aArguments
[1] >>= m_aModuleIdentifier
))
849 ::comphelper::SequenceAsHashMap
lArgs(aArguments
);
850 aModuleShortName
= lArgs
.getUnpackedValueOrDefault("ModuleShortName", OUString());
851 m_aModuleIdentifier
= lArgs
.getUnpackedValueOrDefault("ModuleIdentifier", OUString());
854 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
856 OUString aResourceType
;
857 if ( i
== css::ui::UIElementType::MENUBAR
)
858 aResourceType
= RESOURCETYPE_MENUBAR
;
859 else if ( i
== css::ui::UIElementType::TOOLBAR
)
860 aResourceType
= RESOURCETYPE_TOOLBAR
;
861 else if ( i
== css::ui::UIElementType::STATUSBAR
)
862 aResourceType
= RESOURCETYPE_STATUSBAR
;
863 else if ( i
== css::ui::UIElementType::POPUPMENU
)
864 aResourceType
= RESOURCETYPE_POPUPMENU
;
866 if ( !aResourceType
.isEmpty() )
868 m_pStorageHandler
[i
].reset( new PresetHandler( m_xContext
) );
869 m_pStorageHandler
[i
]->connectToResource( PresetHandler::E_MODULES
,
870 aResourceType
, // this path won't be used later... see next lines!
872 css::uno::Reference
< css::embed::XStorage
>()); // no document root used here!
876 // initialize root storages for all resource types
877 m_xUserRootCommit
.set( m_pStorageHandler
[css::ui::UIElementType::MENUBAR
]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY
); // can be empty
878 m_xDefaultConfigStorage
= m_pStorageHandler
[css::ui::UIElementType::MENUBAR
]->getParentStorageShare();
879 m_xUserConfigStorage
= m_pStorageHandler
[css::ui::UIElementType::MENUBAR
]->getParentStorageUser();
881 if ( m_xUserConfigStorage
.is() )
883 Reference
< XPropertySet
> xPropSet( m_xUserConfigStorage
, UNO_QUERY
);
887 Any a
= xPropSet
->getPropertyValue("OpenMode");
888 if ( a
>>= nOpenMode
)
889 m_bReadOnly
= !( nOpenMode
& ElementModes::WRITE
);
897 void SAL_CALL
ModuleUIConfigurationManager::dispose()
899 Reference
< XComponent
> xThis( static_cast< OWeakObject
* >(this), UNO_QUERY
);
901 css::lang::EventObject
aEvent( xThis
);
902 m_aListenerContainer
.disposeAndClear( aEvent
);
904 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
905 SolarMutexClearableGuard aGuard
;
906 Reference
< XComponent
> xModuleImageManager( m_xModuleImageManager
);
907 m_xModuleImageManager
.clear();
908 m_xModuleAcceleratorManager
.clear();
909 m_aUIElements
[LAYER_USERDEFINED
].clear();
910 m_aUIElements
[LAYER_DEFAULT
].clear();
911 m_xDefaultConfigStorage
.clear();
912 m_xUserConfigStorage
.clear();
913 m_xUserRootCommit
.clear();
917 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
921 if ( xModuleImageManager
.is() )
922 xModuleImageManager
->dispose();
924 catch ( const Exception
& )
929 void SAL_CALL
ModuleUIConfigurationManager::addEventListener( const Reference
< XEventListener
>& xListener
)
934 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
936 throw DisposedException();
939 m_aListenerContainer
.addInterface( cppu::UnoType
<XEventListener
>::get(), xListener
);
942 void SAL_CALL
ModuleUIConfigurationManager::removeEventListener( const Reference
< XEventListener
>& xListener
)
944 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
945 m_aListenerContainer
.removeInterface( cppu::UnoType
<XEventListener
>::get(), xListener
);
949 void SAL_CALL
ModuleUIConfigurationManager::addConfigurationListener( const Reference
< css::ui::XUIConfigurationListener
>& xListener
)
954 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
956 throw DisposedException();
959 m_aListenerContainer
.addInterface( cppu::UnoType
<ui::XUIConfigurationListener
>::get(), xListener
);
962 void SAL_CALL
ModuleUIConfigurationManager::removeConfigurationListener( const Reference
< css::ui::XUIConfigurationListener
>& xListener
)
964 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
965 m_aListenerContainer
.removeInterface( cppu::UnoType
<ui::XUIConfigurationListener
>::get(), xListener
);
968 // XUIConfigurationManager
969 void SAL_CALL
ModuleUIConfigurationManager::reset()
971 SolarMutexClearableGuard aGuard
;
973 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
975 throw DisposedException();
979 // Remove all elements from our user-defined storage!
982 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
984 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
986 if ( rElementType
.xStorage
.is() )
988 bool bCommitSubStorage( false );
989 Sequence
< OUString
> aUIElementStreamNames
= rElementType
.xStorage
->getElementNames();
990 for ( sal_Int32 j
= 0; j
< aUIElementStreamNames
.getLength(); j
++ )
992 rElementType
.xStorage
->removeElement( aUIElementStreamNames
[j
] );
993 bCommitSubStorage
= true;
996 if ( bCommitSubStorage
)
998 Reference
< XTransactedObject
> xTransactedObject( rElementType
.xStorage
, UNO_QUERY
);
999 if ( xTransactedObject
.is() )
1000 xTransactedObject
->commit();
1001 m_pStorageHandler
[i
]->commitUserChanges();
1006 // remove settings from user defined layer and notify listener about removed settings data!
1007 ConfigEventNotifyContainer aRemoveEventNotifyContainer
;
1008 ConfigEventNotifyContainer aReplaceEventNotifyContainer
;
1009 for ( sal_Int16 j
= 1; j
< css::ui::UIElementType::COUNT
; j
++ )
1013 UIElementType
& rUserElementType
= m_aUIElements
[LAYER_USERDEFINED
][j
];
1014 UIElementType
& rDefaultElementType
= m_aUIElements
[LAYER_DEFAULT
][j
];
1016 impl_resetElementTypeData( rUserElementType
, rDefaultElementType
, aRemoveEventNotifyContainer
, aReplaceEventNotifyContainer
);
1017 rUserElementType
.bModified
= false;
1019 catch (const Exception
&)
1021 css::uno::Any anyEx
= cppu::getCaughtException();
1022 throw css::lang::WrappedTargetRuntimeException(
1023 "ModuleUIConfigurationManager::reset exception",
1024 css::uno::Reference
<css::uno::XInterface
>(*this), anyEx
);
1028 m_bModified
= false;
1030 // Unlock mutex before notify our listeners
1033 // Notify our listeners
1034 for ( auto const & k
: aRemoveEventNotifyContainer
)
1035 implts_notifyContainerListener( k
, NotifyOp_Remove
);
1036 for ( auto const & k
: aReplaceEventNotifyContainer
)
1037 implts_notifyContainerListener( k
, NotifyOp_Replace
);
1039 catch ( const css::lang::IllegalArgumentException
& )
1042 catch ( const css::container::NoSuchElementException
& )
1045 catch ( const css::embed::InvalidStorageException
& )
1048 catch ( const css::embed::StorageWrappedTargetException
& )
1054 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType
)
1056 if (( ElementType
< 0 ) || ( ElementType
>= css::ui::UIElementType::COUNT
))
1057 throw IllegalArgumentException();
1061 throw DisposedException();
1063 std::vector
< Sequence
< PropertyValue
> > aElementInfoSeq
;
1064 UIElementInfoHashMap aUIElementInfoCollection
;
1066 if ( ElementType
== css::ui::UIElementType::UNKNOWN
)
1068 for ( sal_Int16 i
= 0; i
< css::ui::UIElementType::COUNT
; i
++ )
1069 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection
, i
);
1072 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection
, ElementType
);
1074 Sequence
< PropertyValue
> aUIElementInfo( 2 );
1075 aUIElementInfo
[0].Name
= "ResourceURL";
1076 aUIElementInfo
[1].Name
= m_aPropUIName
;
1078 aElementInfoSeq
.resize( aUIElementInfoCollection
.size() );
1081 for (auto const& elem
: aUIElementInfoCollection
)
1083 aUIElementInfo
[0].Value
<<= elem
.second
.aResourceURL
;
1084 aUIElementInfo
[1].Value
<<= elem
.second
.aUIName
;
1085 aElementInfoSeq
[n
++] = aUIElementInfo
;
1088 return comphelper::containerToSequence(aElementInfoSeq
);
1091 Reference
< XIndexContainer
> SAL_CALL
ModuleUIConfigurationManager::createSettings()
1096 throw DisposedException();
1098 // Creates an empty item container which can be filled from outside
1099 return Reference
< XIndexContainer
>( static_cast< OWeakObject
* >( new RootItemContainer() ), UNO_QUERY
);
1102 sal_Bool SAL_CALL
ModuleUIConfigurationManager::hasSettings( const OUString
& ResourceURL
)
1104 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1106 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1107 ( nElementType
>= css::ui::UIElementType::COUNT
))
1108 throw IllegalArgumentException();
1113 throw DisposedException();
1115 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
, false );
1116 if ( pDataSettings
)
1122 Reference
< XIndexAccess
> SAL_CALL
ModuleUIConfigurationManager::getSettings( const OUString
& ResourceURL
, sal_Bool bWriteable
)
1124 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1126 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1127 ( nElementType
>= css::ui::UIElementType::COUNT
))
1128 throw IllegalArgumentException();
1133 throw DisposedException();
1135 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1136 if ( pDataSettings
)
1138 // Create a copy of our data if someone wants to change the data.
1140 return Reference
< XIndexAccess
>( static_cast< OWeakObject
* >( new RootItemContainer( pDataSettings
->xSettings
) ), UNO_QUERY
);
1142 return pDataSettings
->xSettings
;
1145 throw NoSuchElementException();
1148 void SAL_CALL
ModuleUIConfigurationManager::replaceSettings( const OUString
& ResourceURL
, const Reference
< css::container::XIndexAccess
>& aNewData
)
1150 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1152 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1153 ( nElementType
>= css::ui::UIElementType::COUNT
))
1154 throw IllegalArgumentException();
1155 else if ( m_bReadOnly
)
1156 throw IllegalAccessException();
1159 SolarMutexClearableGuard aGuard
;
1162 throw DisposedException();
1164 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1165 if ( !pDataSettings
)
1166 throw NoSuchElementException();
1167 if ( !pDataSettings
->bDefaultNode
)
1169 // we have a settings entry in our user-defined layer - replace
1170 Reference
< XIndexAccess
> xOldSettings
= pDataSettings
->xSettings
;
1172 // Create a copy of the data if the container is not const
1173 Reference
< XIndexReplace
> xReplace( aNewData
, UNO_QUERY
);
1174 if ( xReplace
.is() )
1175 pDataSettings
->xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( aNewData
) ), UNO_QUERY
);
1177 pDataSettings
->xSettings
= aNewData
;
1178 pDataSettings
->bDefault
= false;
1179 pDataSettings
->bModified
= true;
1182 // Modify type container
1183 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1184 rElementType
.bModified
= true;
1186 Reference
< XUIConfigurationManager
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
1187 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
1189 // Create event to notify listener about replaced element settings
1190 ui::ConfigurationEvent aEvent
;
1191 aEvent
.ResourceURL
= ResourceURL
;
1192 aEvent
.Accessor
<<= xThis
;
1193 aEvent
.Source
= xIfac
;
1194 aEvent
.ReplacedElement
<<= xOldSettings
;
1195 aEvent
.Element
<<= pDataSettings
->xSettings
;
1199 implts_notifyContainerListener( aEvent
, NotifyOp_Replace
);
1203 // we have no settings in our user-defined layer - insert
1204 UIElementData aUIElementData
;
1206 aUIElementData
.bDefault
= false;
1207 aUIElementData
.bDefaultNode
= false;
1208 aUIElementData
.bModified
= true;
1210 // Create a copy of the data if the container is not const
1211 Reference
< XIndexReplace
> xReplace( aNewData
, UNO_QUERY
);
1212 if ( xReplace
.is() )
1213 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( aNewData
) ), UNO_QUERY
);
1215 aUIElementData
.xSettings
= aNewData
;
1216 aUIElementData
.aName
= RetrieveNameFromResourceURL( ResourceURL
) + m_aXMLPostfix
;
1217 aUIElementData
.aResourceURL
= ResourceURL
;
1220 // Modify type container
1221 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1222 rElementType
.bModified
= true;
1224 UIElementDataHashMap
& rElements
= rElementType
.aElementsHashMap
;
1226 // Check our user element settings hash map as it can already contain settings that have been set to default!
1227 // If no node can be found, we have to insert it.
1228 UIElementDataHashMap::iterator pIter
= rElements
.find( ResourceURL
);
1229 if ( pIter
!= rElements
.end() )
1230 pIter
->second
= aUIElementData
;
1232 rElements
.emplace( ResourceURL
, aUIElementData
);
1234 Reference
< XUIConfigurationManager
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
1235 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
1237 // Create event to notify listener about replaced element settings
1238 ui::ConfigurationEvent aEvent
;
1240 aEvent
.ResourceURL
= ResourceURL
;
1241 aEvent
.Accessor
<<= xThis
;
1242 aEvent
.Source
= xIfac
;
1243 aEvent
.ReplacedElement
<<= pDataSettings
->xSettings
;
1244 aEvent
.Element
<<= aUIElementData
.xSettings
;
1248 implts_notifyContainerListener( aEvent
, NotifyOp_Replace
);
1253 void SAL_CALL
ModuleUIConfigurationManager::removeSettings( const OUString
& ResourceURL
)
1255 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1257 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1258 ( nElementType
>= css::ui::UIElementType::COUNT
))
1259 throw IllegalArgumentException( "The ResourceURL is not valid or "
1260 "describes an unknown type. "
1261 "ResourceURL: " + ResourceURL
, nullptr, 0 );
1262 else if ( m_bReadOnly
)
1263 throw IllegalAccessException( "The configuration manager is read-only. "
1264 "ResourceURL: " + ResourceURL
, nullptr );
1267 SolarMutexClearableGuard aGuard
;
1270 throw DisposedException( "The configuration manager has been disposed, "
1271 "and can't uphold its method specification anymore. "
1272 "ResourceURL: " + ResourceURL
, nullptr );
1274 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1275 if ( !pDataSettings
)
1276 throw NoSuchElementException( "The settings data cannot be found. "
1277 "ResourceURL: " + ResourceURL
, nullptr );
1278 // If element settings are default, we don't need to change anything!
1279 if ( pDataSettings
->bDefault
)
1283 Reference
< XIndexAccess
> xRemovedSettings
= pDataSettings
->xSettings
;
1284 pDataSettings
->bDefault
= true;
1286 // check if this is a default layer node
1287 if ( !pDataSettings
->bDefaultNode
)
1288 pDataSettings
->bModified
= true; // we have to remove this node from the user layer!
1289 pDataSettings
->xSettings
.clear();
1290 m_bModified
= true; // user layer must be written
1292 // Modify type container
1293 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1294 rElementType
.bModified
= true;
1296 Reference
< XUIConfigurationManager
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
1297 Reference
< XInterface
> xIfac( xThis
, UNO_QUERY
);
1299 // Check if we have settings in the default layer which replaces the user-defined one!
1300 UIElementData
* pDefaultDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
);
1301 if ( pDefaultDataSettings
)
1303 // Create event to notify listener about replaced element settings
1304 ui::ConfigurationEvent aEvent
;
1306 aEvent
.ResourceURL
= ResourceURL
;
1307 aEvent
.Accessor
<<= xThis
;
1308 aEvent
.Source
= xIfac
;
1309 aEvent
.Element
<<= xRemovedSettings
;
1310 aEvent
.ReplacedElement
<<= pDefaultDataSettings
->xSettings
;
1314 implts_notifyContainerListener( aEvent
, NotifyOp_Replace
);
1318 // Create event to notify listener about removed element settings
1319 ui::ConfigurationEvent aEvent
;
1321 aEvent
.ResourceURL
= ResourceURL
;
1322 aEvent
.Accessor
<<= xThis
;
1323 aEvent
.Source
= xIfac
;
1324 aEvent
.Element
<<= xRemovedSettings
;
1328 implts_notifyContainerListener( aEvent
, NotifyOp_Remove
);
1334 void SAL_CALL
ModuleUIConfigurationManager::insertSettings( const OUString
& NewResourceURL
, const Reference
< XIndexAccess
>& aNewData
)
1336 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( NewResourceURL
);
1338 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1339 ( nElementType
>= css::ui::UIElementType::COUNT
))
1340 throw IllegalArgumentException();
1341 else if ( m_bReadOnly
)
1342 throw IllegalAccessException();
1345 SolarMutexClearableGuard aGuard
;
1348 throw DisposedException();
1350 UIElementData
* pDataSettings
= impl_findUIElementData( NewResourceURL
, nElementType
);
1351 if ( !(!pDataSettings
) )
1352 throw ElementExistException();
1353 UIElementData aUIElementData
;
1355 aUIElementData
.bDefault
= false;
1356 aUIElementData
.bDefaultNode
= false;
1357 aUIElementData
.bModified
= true;
1359 // Create a copy of the data if the container is not const
1360 Reference
< XIndexReplace
> xReplace( aNewData
, UNO_QUERY
);
1361 if ( xReplace
.is() )
1362 aUIElementData
.xSettings
.set( static_cast< OWeakObject
* >( new ConstItemContainer( aNewData
) ), UNO_QUERY
);
1364 aUIElementData
.xSettings
= aNewData
;
1365 aUIElementData
.aName
= RetrieveNameFromResourceURL( NewResourceURL
) + m_aXMLPostfix
;
1366 aUIElementData
.aResourceURL
= NewResourceURL
;
1369 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][nElementType
];
1370 rElementType
.bModified
= true;
1372 UIElementDataHashMap
& rElements
= rElementType
.aElementsHashMap
;
1373 rElements
.emplace( NewResourceURL
, aUIElementData
);
1375 Reference
< XIndexAccess
> xInsertSettings( aUIElementData
.xSettings
);
1376 Reference
< XUIConfigurationManager
> xThis( static_cast< OWeakObject
* >( this ), UNO_QUERY
);
1378 // Create event to notify listener about removed element settings
1379 ui::ConfigurationEvent aEvent
;
1381 aEvent
.ResourceURL
= NewResourceURL
;
1382 aEvent
.Accessor
<<= xThis
;
1383 aEvent
.Source
= xThis
;
1384 aEvent
.Element
<<= xInsertSettings
;
1388 implts_notifyContainerListener( aEvent
, NotifyOp_Insert
);
1392 Reference
< XInterface
> SAL_CALL
ModuleUIConfigurationManager::getImageManager()
1397 throw DisposedException();
1399 if ( !m_xModuleImageManager
.is() )
1401 m_xModuleImageManager
.set( static_cast< cppu::OWeakObject
*>( new ModuleImageManager( m_xContext
)),
1403 Reference
< XInitialization
> xInit( m_xModuleImageManager
, UNO_QUERY
);
1405 uno::Sequence
<uno::Any
> aPropSeq(comphelper::InitAnyPropertySequence(
1407 {"UserConfigStorage", uno::Any(m_xUserConfigStorage
)},
1408 {"ModuleIdentifier", uno::Any(m_aModuleIdentifier
)},
1409 {"UserRootCommit", uno::Any(m_xUserRootCommit
)},
1411 xInit
->initialize( aPropSeq
);
1414 return Reference
< XInterface
>( m_xModuleImageManager
, UNO_QUERY
);
1417 Reference
< ui::XAcceleratorConfiguration
> SAL_CALL
ModuleUIConfigurationManager::getShortCutManager()
1422 throw DisposedException();
1424 if ( !m_xModuleAcceleratorManager
.is() ) try
1426 m_xModuleAcceleratorManager
= ui::ModuleAcceleratorConfiguration::
1427 createWithModuleIdentifier(m_xContext
, m_aModuleIdentifier
);
1429 catch ( const css::uno::DeploymentException
& )
1431 SAL_WARN("fwk.uiconfiguration", "ModuleAcceleratorConfiguration"
1432 " not available. This should happen only on mobile platforms.");
1435 return m_xModuleAcceleratorManager
;
1438 Reference
< XInterface
> SAL_CALL
ModuleUIConfigurationManager::getEventsManager()
1440 return Reference
< XInterface
>();
1443 // XModuleUIConfigurationManager
1444 sal_Bool SAL_CALL
ModuleUIConfigurationManager::isDefaultSettings( const OUString
& ResourceURL
)
1446 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1448 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1449 ( nElementType
>= css::ui::UIElementType::COUNT
))
1450 throw IllegalArgumentException();
1455 throw DisposedException();
1457 UIElementData
* pDataSettings
= impl_findUIElementData( ResourceURL
, nElementType
, false );
1458 if ( pDataSettings
&& pDataSettings
->bDefaultNode
)
1464 Reference
< XIndexAccess
> SAL_CALL
ModuleUIConfigurationManager::getDefaultSettings( const OUString
& ResourceURL
)
1466 sal_Int16 nElementType
= RetrieveTypeFromResourceURL( ResourceURL
);
1468 if (( nElementType
== css::ui::UIElementType::UNKNOWN
) ||
1469 ( nElementType
>= css::ui::UIElementType::COUNT
))
1470 throw IllegalArgumentException();
1475 throw DisposedException();
1477 // preload list of element types on demand
1478 impl_preloadUIElementTypeList( LAYER_DEFAULT
, nElementType
);
1480 // Look into our default vector/unordered_map combination
1481 UIElementDataHashMap
& rDefaultHashMap
= m_aUIElements
[LAYER_DEFAULT
][nElementType
].aElementsHashMap
;
1482 UIElementDataHashMap::iterator pIter
= rDefaultHashMap
.find( ResourceURL
);
1483 if ( pIter
!= rDefaultHashMap
.end() )
1485 if ( !pIter
->second
.xSettings
.is() )
1486 impl_requestUIElementData( nElementType
, LAYER_DEFAULT
, pIter
->second
);
1487 return pIter
->second
.xSettings
;
1490 // Nothing has been found!
1491 throw NoSuchElementException();
1494 // XUIConfigurationPersistence
1495 void SAL_CALL
ModuleUIConfigurationManager::reload()
1497 SolarMutexClearableGuard aGuard
;
1500 throw DisposedException();
1502 if ( m_xUserConfigStorage
.is() && m_bModified
&& !m_bReadOnly
)
1504 // Try to access our module sub folder
1505 ConfigEventNotifyContainer aRemoveNotifyContainer
;
1506 ConfigEventNotifyContainer aReplaceNotifyContainer
;
1507 for ( sal_Int16 i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
1511 UIElementType
& rUserElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1513 if ( rUserElementType
.bModified
)
1515 UIElementType
& rDefaultElementType
= m_aUIElements
[LAYER_DEFAULT
][i
];
1516 impl_reloadElementTypeData( rUserElementType
, rDefaultElementType
, aRemoveNotifyContainer
, aReplaceNotifyContainer
);
1519 catch ( const Exception
& )
1521 throw IOException();
1525 m_bModified
= false;
1527 // Unlock mutex before notify our listeners
1530 // Notify our listeners
1531 for (const ui::ConfigurationEvent
& j
: aRemoveNotifyContainer
)
1532 implts_notifyContainerListener( j
, NotifyOp_Remove
);
1533 for (const ui::ConfigurationEvent
& k
: aReplaceNotifyContainer
)
1534 implts_notifyContainerListener( k
, NotifyOp_Replace
);
1538 void SAL_CALL
ModuleUIConfigurationManager::store()
1543 throw DisposedException();
1545 if ( m_xUserConfigStorage
.is() && m_bModified
&& !m_bReadOnly
)
1547 // Try to access our module sub folder
1548 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
1552 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1554 if ( rElementType
.bModified
&& rElementType
.xStorage
.is() )
1556 impl_storeElementTypeData( rElementType
.xStorage
, rElementType
);
1557 m_pStorageHandler
[i
]->commitUserChanges();
1560 catch ( const Exception
& )
1562 throw IOException();
1566 m_bModified
= false;
1570 void SAL_CALL
ModuleUIConfigurationManager::storeToStorage( const Reference
< XStorage
>& Storage
)
1575 throw DisposedException();
1577 if ( m_xUserConfigStorage
.is() && m_bModified
&& !m_bReadOnly
)
1579 // Try to access our module sub folder
1580 for ( int i
= 1; i
< css::ui::UIElementType::COUNT
; i
++ )
1584 Reference
< XStorage
> xElementTypeStorage( Storage
->openStorageElement(
1585 UIELEMENTTYPENAMES
[i
], ElementModes::READWRITE
));
1586 UIElementType
& rElementType
= m_aUIElements
[LAYER_USERDEFINED
][i
];
1588 if ( rElementType
.bModified
&& xElementTypeStorage
.is() )
1589 impl_storeElementTypeData( xElementTypeStorage
, rElementType
, false ); // store data to storage, but don't reset modify flag!
1591 catch ( const Exception
& )
1593 throw IOException();
1597 Reference
< XTransactedObject
> xTransactedObject( Storage
, UNO_QUERY
);
1598 if ( xTransactedObject
.is() )
1599 xTransactedObject
->commit();
1603 sal_Bool SAL_CALL
ModuleUIConfigurationManager::isModified()
1610 sal_Bool SAL_CALL
ModuleUIConfigurationManager::isReadOnly()
1617 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ui::ConfigurationEvent
& aEvent
, NotifyOp eOp
)
1619 ::cppu::OInterfaceContainerHelper
* pContainer
= m_aListenerContainer
.getContainer( cppu::UnoType
<css::ui::XUIConfigurationListener
>::get());
1620 if ( pContainer
!= nullptr )
1622 ::cppu::OInterfaceIteratorHelper
pIterator( *pContainer
);
1623 while ( pIterator
.hasMoreElements() )
1629 case NotifyOp_Replace
:
1630 static_cast< css::ui::XUIConfigurationListener
*>(pIterator
.next())->elementReplaced( aEvent
);
1632 case NotifyOp_Insert
:
1633 static_cast< css::ui::XUIConfigurationListener
*>(pIterator
.next())->elementInserted( aEvent
);
1635 case NotifyOp_Remove
:
1636 static_cast< css::ui::XUIConfigurationListener
*>(pIterator
.next())->elementRemoved( aEvent
);
1640 catch( const css::uno::RuntimeException
& )
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: */