Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <uiconfiguration/imagemanager.hxx>
21 : #include <uielement/rootitemcontainer.hxx>
22 : #include <uielement/constitemcontainer.hxx>
23 : #include <uielement/uielementtypenames.hxx>
24 : #include <framework/menuconfiguration.hxx>
25 : #include <framework/statusbarconfiguration.hxx>
26 : #include <framework/toolboxconfiguration.hxx>
27 :
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 : #include <com/sun/star/container/XIndexContainer.hpp>
30 : #include <com/sun/star/embed/ElementModes.hpp>
31 : #include <com/sun/star/embed/XTransactedObject.hpp>
32 : #include <com/sun/star/lang/XInitialization.hpp>
33 : #include <com/sun/star/lang/DisposedException.hpp>
34 : #include <com/sun/star/io/XStream.hpp>
35 : #include <com/sun/star/ui/UIElementType.hpp>
36 : #include <com/sun/star/ui/ConfigurationEvent.hpp>
37 : #include <com/sun/star/ui/DocumentAcceleratorConfiguration.hpp>
38 : #include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
39 : #include <com/sun/star/ui/XUIConfigurationManager2.hpp>
40 : #include <com/sun/star/lang/XComponent.hpp>
41 : #include <com/sun/star/lang/XServiceInfo.hpp>
42 :
43 : #include <cppuhelper/implbase2.hxx>
44 : #include <cppuhelper/supportsservice.hxx>
45 : #include <vcl/svapp.hxx>
46 : #include <rtl/ref.hxx>
47 : #include <rtl/ustrbuf.hxx>
48 :
49 : #include <unordered_map>
50 :
51 : using namespace com::sun::star::uno;
52 : using namespace com::sun::star::io;
53 : using namespace com::sun::star::embed;
54 : using namespace com::sun::star::lang;
55 : using namespace com::sun::star::container;
56 : using namespace com::sun::star::beans;
57 : using namespace com::sun::star::ui;
58 : using namespace framework;
59 :
60 : namespace {
61 :
62 : class UIConfigurationManager : public ::cppu::WeakImplHelper2<
63 : css::lang::XServiceInfo ,
64 : css::ui::XUIConfigurationManager2 >
65 : {
66 : public:
67 2 : virtual OUString SAL_CALL getImplementationName()
68 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
69 : {
70 2 : return OUString("com.sun.star.comp.framework.UIConfigurationManager");
71 : }
72 :
73 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
74 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
75 : {
76 0 : return cppu::supportsService(this, ServiceName);
77 : }
78 :
79 1 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
80 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
81 : {
82 1 : css::uno::Sequence< OUString > aSeq(1);
83 1 : aSeq[0] = "com.sun.star.ui.UIConfigurationManager";
84 1 : return aSeq;
85 : }
86 :
87 : UIConfigurationManager( const css::uno::Reference< css::uno::XComponentContext > & rxContext );
88 : virtual ~UIConfigurationManager();
89 :
90 : // XComponent
91 : virtual void SAL_CALL dispose() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
92 : virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
93 : virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
94 :
95 : // XUIConfiguration
96 : virtual void SAL_CALL addConfigurationListener( const css::uno::Reference< css::ui::XUIConfigurationListener >& Listener ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
97 : virtual void SAL_CALL removeConfigurationListener( const css::uno::Reference< css::ui::XUIConfigurationListener >& Listener ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
98 :
99 : // XUIConfigurationManager
100 : virtual void SAL_CALL reset() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
101 : virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getUIElementsInfo( sal_Int16 ElementType ) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
102 : virtual css::uno::Reference< css::container::XIndexContainer > SAL_CALL createSettings( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
103 : virtual sal_Bool SAL_CALL hasSettings( const OUString& ResourceURL ) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
104 : virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getSettings( const OUString& ResourceURL, sal_Bool bWriteable ) throw (css::container::NoSuchElementException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
105 : virtual void SAL_CALL replaceSettings( const OUString& ResourceURL, const css::uno::Reference< css::container::XIndexAccess >& aNewData ) throw (css::container::NoSuchElementException, css::lang::IllegalArgumentException, css::lang::IllegalAccessException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
106 : virtual void SAL_CALL removeSettings( const OUString& ResourceURL ) throw (css::container::NoSuchElementException, css::lang::IllegalArgumentException, css::lang::IllegalAccessException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
107 : virtual void SAL_CALL insertSettings( const OUString& NewResourceURL, const css::uno::Reference< css::container::XIndexAccess >& aNewData ) throw (css::container::ElementExistException, css::lang::IllegalArgumentException, css::lang::IllegalAccessException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
108 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getImageManager() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
109 : virtual css::uno::Reference< css::ui::XAcceleratorConfiguration > SAL_CALL getShortCutManager() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
110 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getEventsManager() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
111 :
112 : // XUIConfigurationPersistence
113 : virtual void SAL_CALL reload() throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
114 : virtual void SAL_CALL store() throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
115 : virtual void SAL_CALL storeToStorage( const css::uno::Reference< css::embed::XStorage >& Storage ) throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
116 : virtual sal_Bool SAL_CALL isModified() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
117 : virtual sal_Bool SAL_CALL isReadOnly() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
118 :
119 : // XUIConfigurationStorage
120 : virtual void SAL_CALL setStorage( const css::uno::Reference< css::embed::XStorage >& Storage ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
121 : virtual sal_Bool SAL_CALL hasStorage() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
122 :
123 : private:
124 : // private data types
125 : enum NotifyOp
126 : {
127 : NotifyOp_Remove,
128 : NotifyOp_Insert,
129 : NotifyOp_Replace
130 : };
131 :
132 0 : struct UIElementInfo
133 : {
134 0 : UIElementInfo( const OUString& rResourceURL, const OUString& rUIName ) :
135 0 : aResourceURL( rResourceURL), aUIName( rUIName ) {}
136 : OUString aResourceURL;
137 : OUString aUIName;
138 : };
139 :
140 0 : struct UIElementData
141 : {
142 0 : UIElementData() : bModified( false ), bDefault( true ) {};
143 :
144 : OUString aResourceURL;
145 : OUString aName;
146 : bool bModified; // has been changed since last storing
147 : bool bDefault; // default settings
148 : css::uno::Reference< css::container::XIndexAccess > xSettings;
149 : };
150 :
151 : struct UIElementType;
152 : friend struct UIElementType;
153 : typedef std::unordered_map< OUString, UIElementData, OUStringHash, std::equal_to< OUString > > UIElementDataHashMap;
154 :
155 28256 : struct UIElementType
156 : {
157 28368 : UIElementType() : bModified( false ),
158 : bLoaded( false ),
159 : bDefaultLayer( false ),
160 28368 : nElementType( css::ui::UIElementType::UNKNOWN ) {}
161 :
162 : bool bModified;
163 : bool bLoaded;
164 : bool bDefaultLayer;
165 : sal_Int16 nElementType;
166 : UIElementDataHashMap aElementsHashMap;
167 : css::uno::Reference< css::embed::XStorage > xStorage;
168 : };
169 :
170 : typedef std::vector< UIElementType > UIElementTypesVector;
171 : typedef std::vector< css::ui::ConfigurationEvent > ConfigEventNotifyContainer;
172 : typedef std::unordered_map< OUString, UIElementInfo, OUStringHash, std::equal_to< OUString > > UIElementInfoHashMap;
173 :
174 : void impl_Initialize();
175 : void implts_notifyContainerListener( const css::ui::ConfigurationEvent& aEvent, NotifyOp eOp );
176 : void impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType );
177 : void impl_preloadUIElementTypeList( sal_Int16 nElementType );
178 : UIElementData* impl_findUIElementData( const OUString& aResourceURL, sal_Int16 nElementType, bool bLoad = true );
179 : void impl_requestUIElementData( sal_Int16 nElementType, UIElementData& aUIElementData );
180 : void impl_storeElementTypeData( css::uno::Reference< css::embed::XStorage >& xStorage, UIElementType& rElementType, bool bResetModifyState = true );
181 : void impl_resetElementTypeData( UIElementType& rDocElementType, ConfigEventNotifyContainer& rRemoveNotifyContainer );
182 : void impl_reloadElementTypeData( UIElementType& rDocElementType, ConfigEventNotifyContainer& rRemoveNotifyContainer, ConfigEventNotifyContainer& rReplaceNotifyContainer );
183 :
184 : UIElementTypesVector m_aUIElements;
185 : css::uno::Reference< css::embed::XStorage > m_xDocConfigStorage;
186 : bool m_bReadOnly;
187 : bool m_bModified;
188 : bool m_bConfigRead;
189 : bool m_bDisposed;
190 : OUString m_aXMLPostfix;
191 : OUString m_aPropUIName;
192 : OUString m_aPropResourceURL;
193 : OUString m_aModuleIdentifier;
194 : css::uno::Reference< css::uno::XComponentContext > m_xContext;
195 : osl::Mutex m_mutex;
196 : cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer; /// container for ALL Listener
197 : css::uno::Reference< css::lang::XComponent > m_xImageManager;
198 : css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xAccConfig;
199 : };
200 :
201 : // important: The order and position of the elements must match the constant
202 : // definition of "::com::sun::star::ui::UIElementType"
203 : static const char* UIELEMENTTYPENAMES[] =
204 : {
205 : "", // Dummy value for unknown!
206 : UIELEMENTTYPE_MENUBAR_NAME,
207 : UIELEMENTTYPE_POPUPMENU_NAME,
208 : UIELEMENTTYPE_TOOLBAR_NAME,
209 : UIELEMENTTYPE_STATUSBAR_NAME,
210 : UIELEMENTTYPE_FLOATINGWINDOW_NAME,
211 : UIELEMENTTYPE_PROGRESSBAR_NAME,
212 : UIELEMENTTYPE_TOOLPANEL_NAME
213 : };
214 :
215 : static const char RESOURCEURL_PREFIX[] = "private:resource/";
216 : static const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17;
217 :
218 13108 : static sal_Int16 RetrieveTypeFromResourceURL( const OUString& aResourceURL )
219 : {
220 :
221 26216 : if (( aResourceURL.startsWith( RESOURCEURL_PREFIX ) ) &&
222 13108 : ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
223 : {
224 13108 : OUString aTmpStr = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE );
225 13108 : sal_Int32 nIndex = aTmpStr.indexOf( '/' );
226 13108 : if (( nIndex > 0 ) && ( aTmpStr.getLength() > nIndex ))
227 : {
228 13108 : OUString aTypeStr( aTmpStr.copy( 0, nIndex ));
229 49236 : for ( int i = 0; i < UIElementType::COUNT; i++ )
230 : {
231 49236 : if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] ))
232 13108 : return sal_Int16( i );
233 0 : }
234 0 : }
235 : }
236 :
237 0 : return UIElementType::UNKNOWN;
238 : }
239 :
240 0 : static OUString RetrieveNameFromResourceURL( const OUString& aResourceURL )
241 : {
242 0 : if (( aResourceURL.startsWith( RESOURCEURL_PREFIX ) ) &&
243 0 : ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
244 : {
245 0 : sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' );
246 0 : if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength()))
247 0 : return aResourceURL.copy( nIndex+1 );
248 : }
249 :
250 0 : return OUString();
251 : }
252 :
253 3272 : void UIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType )
254 : {
255 : // preload list of element types on demand
256 3272 : impl_preloadUIElementTypeList( nElementType );
257 :
258 3272 : UIElementDataHashMap& rUserElements = m_aUIElements[nElementType].aElementsHashMap;
259 3272 : UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin();
260 :
261 6544 : while ( pUserIter != rUserElements.end() )
262 : {
263 0 : UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType );
264 0 : if ( pDataSettings && !pDataSettings->bDefault )
265 : {
266 : // Retrieve user interface name from XPropertySet interface
267 0 : OUString aUIName;
268 0 : Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
269 0 : if ( xPropSet.is() )
270 : {
271 0 : Any a = xPropSet->getPropertyValue( m_aPropUIName );
272 0 : a >>= aUIName;
273 : }
274 :
275 0 : UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName );
276 0 : aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo ));
277 : }
278 0 : ++pUserIter;
279 : }
280 3272 : }
281 :
282 16380 : void UIConfigurationManager::impl_preloadUIElementTypeList( sal_Int16 nElementType )
283 : {
284 16380 : UIElementType& rElementTypeData = m_aUIElements[nElementType];
285 :
286 16380 : if ( !rElementTypeData.bLoaded )
287 : {
288 9613 : Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
289 9613 : if ( xElementTypeStorage.is() )
290 : {
291 9523 : OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE );
292 9523 : aBuf.appendAscii( RESOURCEURL_PREFIX );
293 9523 : aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] );
294 9523 : aBuf.appendAscii( "/" );
295 19046 : OUString aResURLPrefix( aBuf.makeStringAndClear() );
296 :
297 9523 : UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap;
298 19046 : Sequence< OUString > aUIElementNames = xElementTypeStorage->getElementNames();
299 9523 : for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ )
300 : {
301 0 : UIElementData aUIElementData;
302 :
303 : // Resource name must be without ".xml"
304 0 : sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' );
305 0 : if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() ))
306 : {
307 0 : OUString aExtension( aUIElementNames[n].copy( nIndex+1 ));
308 0 : OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex ));
309 :
310 0 : if (!aUIElementName.isEmpty() &&
311 0 : ( aExtension.equalsIgnoreAsciiCase("xml")))
312 : {
313 0 : aUIElementData.aResourceURL = aResURLPrefix + aUIElementName;
314 0 : aUIElementData.aName = aUIElementNames[n];
315 0 : aUIElementData.bModified = false;
316 0 : aUIElementData.bDefault = false;
317 :
318 : // Create unordered_map entries for all user interface elements inside the storage. We don't load the
319 : // settings to speed up the process.
320 0 : rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData ));
321 0 : }
322 : }
323 9523 : }
324 9613 : }
325 : }
326 :
327 16380 : rElementTypeData.bLoaded = true;
328 16380 : }
329 :
330 0 : void UIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, UIElementData& aUIElementData )
331 : {
332 0 : UIElementType& rElementTypeData = m_aUIElements[nElementType];
333 :
334 0 : Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
335 0 : if ( xElementTypeStorage.is() && !aUIElementData.aName.isEmpty() )
336 : {
337 : try
338 : {
339 0 : Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ );
340 0 : Reference< XInputStream > xInputStream = xStream->getInputStream();
341 :
342 0 : if ( xInputStream.is() )
343 : {
344 0 : switch ( nElementType )
345 : {
346 : case ::com::sun::star::ui::UIElementType::UNKNOWN:
347 0 : break;
348 :
349 : case ::com::sun::star::ui::UIElementType::MENUBAR:
350 : {
351 : try
352 : {
353 0 : MenuConfiguration aMenuCfg( m_xContext );
354 0 : Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream ));
355 0 : RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer );
356 0 : if ( pRootItemContainer )
357 0 : aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, true ) ), UNO_QUERY );
358 : else
359 0 : aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, true ) ), UNO_QUERY );
360 0 : return;
361 : }
362 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
363 : {
364 : }
365 : }
366 0 : break;
367 :
368 : case ::com::sun::star::ui::UIElementType::POPUPMENU:
369 : {
370 0 : break;
371 : }
372 :
373 : case ::com::sun::star::ui::UIElementType::TOOLBAR:
374 : {
375 : try
376 : {
377 0 : Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
378 0 : ToolBoxConfiguration::LoadToolBox( m_xContext, xInputStream, xIndexContainer );
379 0 : RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
380 0 : aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, true ) ), UNO_QUERY );
381 0 : return;
382 : }
383 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
384 : {
385 : }
386 :
387 0 : break;
388 : }
389 :
390 : case ::com::sun::star::ui::UIElementType::STATUSBAR:
391 : {
392 : try
393 : {
394 0 : Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
395 0 : StatusBarConfiguration::LoadStatusBar( m_xContext, xInputStream, xIndexContainer );
396 0 : RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
397 0 : aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, true ) ), UNO_QUERY );
398 0 : return;
399 : }
400 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
401 : {
402 : }
403 :
404 0 : break;
405 : }
406 :
407 : case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW:
408 : {
409 0 : break;
410 : }
411 : }
412 0 : }
413 : }
414 0 : catch ( const ::com::sun::star::embed::InvalidStorageException& )
415 : {
416 : }
417 0 : catch ( const ::com::sun::star::lang::IllegalArgumentException& )
418 : {
419 : }
420 0 : catch ( const ::com::sun::star::io::IOException& )
421 : {
422 : }
423 0 : catch ( const ::com::sun::star::embed::StorageWrappedTargetException& )
424 : {
425 : }
426 : }
427 :
428 : // At least we provide an empty settings container!
429 0 : aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer()), UNO_QUERY );
430 : }
431 :
432 13108 : UIConfigurationManager::UIElementData* UIConfigurationManager::impl_findUIElementData( const OUString& aResourceURL, sal_Int16 nElementType, bool bLoad )
433 : {
434 : // preload list of element types on demand
435 13108 : impl_preloadUIElementTypeList( nElementType );
436 :
437 : // try to look into our document vector/unordered_map combination
438 13108 : UIElementDataHashMap& rUserHashMap = m_aUIElements[nElementType].aElementsHashMap;
439 13108 : UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL );
440 13108 : if ( pIter != rUserHashMap.end() )
441 : {
442 : // Default data settings data means removed!
443 0 : if ( pIter->second.bDefault )
444 0 : return &(pIter->second);
445 : else
446 : {
447 0 : if ( !pIter->second.xSettings.is() && bLoad )
448 0 : impl_requestUIElementData( nElementType, pIter->second );
449 0 : return &(pIter->second);
450 : }
451 : }
452 :
453 : // Nothing has been found!
454 13108 : return NULL;
455 : }
456 :
457 0 : void UIConfigurationManager::impl_storeElementTypeData( Reference< XStorage >& xStorage, UIElementType& rElementType, bool bResetModifyState )
458 : {
459 0 : UIElementDataHashMap& rHashMap = rElementType.aElementsHashMap;
460 0 : UIElementDataHashMap::iterator pIter = rHashMap.begin();
461 :
462 0 : while ( pIter != rHashMap.end() )
463 : {
464 0 : UIElementData& rElement = pIter->second;
465 0 : if ( rElement.bModified )
466 : {
467 0 : if ( rElement.bDefault )
468 : {
469 0 : xStorage->removeElement( rElement.aName );
470 0 : rElement.bModified = false; // mark as not modified
471 : }
472 : else
473 : {
474 0 : Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY );
475 0 : Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
476 :
477 0 : if ( xOutputStream.is() )
478 : {
479 0 : switch( rElementType.nElementType )
480 : {
481 : case ::com::sun::star::ui::UIElementType::MENUBAR:
482 : {
483 : try
484 : {
485 0 : MenuConfiguration aMenuCfg( m_xContext );
486 0 : aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream );
487 : }
488 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
489 : {
490 : }
491 : }
492 0 : break;
493 :
494 : case ::com::sun::star::ui::UIElementType::TOOLBAR:
495 : {
496 : try
497 : {
498 0 : ToolBoxConfiguration::StoreToolBox( m_xContext, xOutputStream, rElement.xSettings );
499 : }
500 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
501 : {
502 : }
503 : }
504 0 : break;
505 :
506 : case ::com::sun::star::ui::UIElementType::STATUSBAR:
507 : {
508 : try
509 : {
510 0 : StatusBarConfiguration::StoreStatusBar( m_xContext, xOutputStream, rElement.xSettings );
511 : }
512 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
513 : {
514 : }
515 : }
516 0 : break;
517 :
518 : default:
519 0 : break;
520 : }
521 : }
522 :
523 : // mark as not modified if we store to our own storage
524 0 : if ( bResetModifyState )
525 0 : rElement.bModified = false;
526 : }
527 : }
528 :
529 0 : ++pIter;
530 : }
531 :
532 : // commit element type storage
533 0 : Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY );
534 0 : if ( xTransactedObject.is() )
535 0 : xTransactedObject->commit();
536 :
537 : // mark UIElementType as not modified if we store to our own storage
538 0 : if ( bResetModifyState )
539 0 : rElementType.bModified = false;
540 0 : }
541 :
542 0 : void UIConfigurationManager::impl_resetElementTypeData(
543 : UIElementType& rDocElementType,
544 : ConfigEventNotifyContainer& rRemoveNotifyContainer )
545 : {
546 0 : UIElementDataHashMap& rHashMap = rDocElementType.aElementsHashMap;
547 0 : UIElementDataHashMap::iterator pIter = rHashMap.begin();
548 :
549 0 : Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
550 0 : Reference< XInterface > xIfac( xThis, UNO_QUERY );
551 :
552 : // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
553 : // our listeners!
554 0 : while ( pIter != rHashMap.end() )
555 : {
556 0 : UIElementData& rElement = pIter->second;
557 0 : if ( !rElement.bDefault )
558 : {
559 : // Remove user-defined settings from document
560 0 : ConfigurationEvent aEvent;
561 0 : aEvent.ResourceURL = rElement.aResourceURL;
562 0 : aEvent.Accessor <<= xThis;
563 0 : aEvent.Source = xIfac;
564 0 : aEvent.Element <<= rElement.xSettings;
565 :
566 0 : rRemoveNotifyContainer.push_back( aEvent );
567 :
568 : // Mark element as default.
569 0 : rElement.bModified = false;
570 0 : rElement.bDefault = true;
571 : }
572 : else
573 0 : rElement.bModified = false;
574 :
575 0 : ++pIter;
576 : }
577 :
578 : // Remove all settings from our user interface elements
579 0 : rHashMap.clear();
580 0 : }
581 :
582 0 : void UIConfigurationManager::impl_reloadElementTypeData(
583 : UIElementType& rDocElementType,
584 : ConfigEventNotifyContainer& rRemoveNotifyContainer,
585 : ConfigEventNotifyContainer& rReplaceNotifyContainer )
586 : {
587 0 : UIElementDataHashMap& rHashMap = rDocElementType.aElementsHashMap;
588 0 : UIElementDataHashMap::iterator pIter = rHashMap.begin();
589 0 : Reference< XStorage > xElementStorage( rDocElementType.xStorage );
590 :
591 0 : Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
592 0 : Reference< XInterface > xIfac( xThis, UNO_QUERY );
593 0 : sal_Int16 nType = rDocElementType.nElementType;
594 :
595 0 : while ( pIter != rHashMap.end() )
596 : {
597 0 : UIElementData& rElement = pIter->second;
598 0 : if ( rElement.bModified )
599 : {
600 0 : if ( xElementStorage->hasByName( rElement.aName ))
601 : {
602 : // Replace settings with data from user layer
603 0 : Reference< XIndexAccess > xOldSettings( rElement.xSettings );
604 :
605 0 : impl_requestUIElementData( nType, rElement );
606 :
607 0 : ConfigurationEvent aReplaceEvent;
608 :
609 0 : aReplaceEvent.ResourceURL = rElement.aResourceURL;
610 0 : aReplaceEvent.Accessor <<= xThis;
611 0 : aReplaceEvent.Source = xIfac;
612 0 : aReplaceEvent.ReplacedElement <<= xOldSettings;
613 0 : aReplaceEvent.Element <<= rElement.xSettings;
614 0 : rReplaceNotifyContainer.push_back( aReplaceEvent );
615 :
616 0 : rElement.bModified = false;
617 : }
618 : else
619 : {
620 : // Element settings are not in any storage => remove
621 0 : ConfigurationEvent aRemoveEvent;
622 :
623 0 : aRemoveEvent.ResourceURL = rElement.aResourceURL;
624 0 : aRemoveEvent.Accessor <<= xThis;
625 0 : aRemoveEvent.Source = xIfac;
626 0 : aRemoveEvent.Element <<= rElement.xSettings;
627 :
628 0 : rRemoveNotifyContainer.push_back( aRemoveEvent );
629 :
630 : // Mark element as default and not modified. That means "not active" in the document anymore
631 0 : rElement.bModified = false;
632 0 : rElement.bDefault = true;
633 : }
634 : }
635 0 : ++pIter;
636 : }
637 :
638 0 : rDocElementType.bModified = false;
639 0 : }
640 :
641 4146 : void UIConfigurationManager::impl_Initialize()
642 : {
643 : // Initialize the top-level structures with the storage data
644 4146 : if ( m_xDocConfigStorage.is() )
645 : {
646 4116 : long nModes = m_bReadOnly ? ElementModes::READ : ElementModes::READWRITE;
647 :
648 : // Try to access our module sub folder
649 32928 : for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT;
650 : i++ )
651 : {
652 28812 : Reference< XStorage > xElementTypeStorage;
653 : try
654 : {
655 28812 : xElementTypeStorage = m_xDocConfigStorage->openStorageElement( OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), nModes );
656 : }
657 0 : catch ( const com::sun::star::container::NoSuchElementException& )
658 : {
659 : }
660 0 : catch ( const ::com::sun::star::embed::InvalidStorageException& )
661 : {
662 : }
663 0 : catch ( const ::com::sun::star::lang::IllegalArgumentException& )
664 : {
665 : }
666 0 : catch ( const ::com::sun::star::io::IOException& )
667 : {
668 : }
669 0 : catch ( const ::com::sun::star::embed::StorageWrappedTargetException& )
670 : {
671 : }
672 :
673 28812 : m_aUIElements[i].nElementType = i;
674 28812 : m_aUIElements[i].bModified = false;
675 28812 : m_aUIElements[i].xStorage = xElementTypeStorage;
676 28812 : m_aUIElements[i].bDefaultLayer = false;
677 28812 : }
678 : }
679 : else
680 : {
681 : // We have no storage, just initialize ui element types with empty storage!
682 240 : for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
683 210 : m_aUIElements[i].xStorage = m_xDocConfigStorage;
684 : }
685 4146 : }
686 :
687 3546 : UIConfigurationManager::UIConfigurationManager( const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > & rxContext ) :
688 : m_xDocConfigStorage( 0 )
689 : , m_bReadOnly( true )
690 : , m_bModified( false )
691 : , m_bConfigRead( false )
692 : , m_bDisposed( false )
693 : , m_aXMLPostfix( ".xml" )
694 : , m_aPropUIName( "UIName" )
695 : , m_aPropResourceURL( "ResourceURL" )
696 : , m_xContext( rxContext )
697 3546 : , m_aListenerContainer( m_mutex )
698 : {
699 : // Make sure we have a default initialized entry for every layer and user interface element type!
700 : // The following code depends on this!
701 3546 : m_aUIElements.resize( ::com::sun::star::ui::UIElementType::COUNT );
702 3546 : }
703 :
704 7064 : UIConfigurationManager::~UIConfigurationManager()
705 : {
706 7064 : }
707 :
708 : // XComponent
709 2 : void SAL_CALL UIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException, std::exception)
710 : {
711 2 : Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
712 :
713 4 : css::lang::EventObject aEvent( xThis );
714 2 : m_aListenerContainer.disposeAndClear( aEvent );
715 :
716 : {
717 2 : SolarMutexGuard g;
718 : try
719 : {
720 2 : if ( m_xImageManager.is() )
721 0 : m_xImageManager->dispose();
722 : }
723 0 : catch ( const Exception& )
724 : {
725 : }
726 :
727 2 : m_xImageManager.clear();
728 2 : m_aUIElements.clear();
729 2 : m_xDocConfigStorage.clear();
730 2 : m_bConfigRead = false;
731 2 : m_bModified = false;
732 2 : m_bDisposed = true;
733 2 : }
734 2 : }
735 :
736 2 : void SAL_CALL UIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException, std::exception)
737 : {
738 : {
739 2 : SolarMutexGuard g;
740 :
741 : /* SAFE AREA ----------------------------------------------------------------------------------------------- */
742 2 : if ( m_bDisposed )
743 0 : throw DisposedException();
744 : }
745 :
746 2 : m_aListenerContainer.addInterface( cppu::UnoType<XEventListener>::get(), xListener );
747 2 : }
748 :
749 1 : void SAL_CALL UIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException, std::exception)
750 : {
751 : /* SAFE AREA ----------------------------------------------------------------------------------------------- */
752 1 : m_aListenerContainer.removeInterface( cppu::UnoType<XEventListener>::get(), xListener );
753 1 : }
754 :
755 : // XUIConfigurationManager
756 3274 : void SAL_CALL UIConfigurationManager::addConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException, std::exception)
757 : {
758 : {
759 3274 : SolarMutexGuard g;
760 :
761 : /* SAFE AREA ----------------------------------------------------------------------------------------------- */
762 3274 : if ( m_bDisposed )
763 0 : throw DisposedException();
764 : }
765 :
766 3274 : m_aListenerContainer.addInterface( cppu::UnoType<XUIConfigurationListener>::get(), xListener );
767 3274 : }
768 :
769 3261 : void SAL_CALL UIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException, std::exception)
770 : {
771 : /* SAFE AREA ----------------------------------------------------------------------------------------------- */
772 3261 : m_aListenerContainer.removeInterface( cppu::UnoType<XUIConfigurationListener>::get(), xListener );
773 3261 : }
774 :
775 0 : void SAL_CALL UIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException, std::exception)
776 : {
777 0 : SolarMutexClearableGuard aGuard;
778 :
779 : /* SAFE AREA ----------------------------------------------------------------------------------------------- */
780 0 : if ( m_bDisposed )
781 0 : throw DisposedException();
782 :
783 0 : if ( isReadOnly() )
784 0 : return;
785 :
786 0 : if ( m_xDocConfigStorage.is() )
787 : {
788 : try
789 : {
790 : // Remove all elements from our user-defined storage!
791 0 : bool bCommit( false );
792 0 : for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
793 : {
794 0 : UIElementType& rElementType = m_aUIElements[i];
795 0 : Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY );
796 :
797 0 : if ( xSubStorage.is() )
798 : {
799 0 : bool bCommitSubStorage( false );
800 0 : Sequence< OUString > aUIElementStreamNames = xSubStorage->getElementNames();
801 0 : for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ )
802 : {
803 0 : xSubStorage->removeElement( aUIElementStreamNames[j] );
804 0 : bCommitSubStorage = true;
805 0 : bCommit = true;
806 : }
807 :
808 0 : if ( bCommitSubStorage )
809 : {
810 0 : Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY );
811 0 : if ( xTransactedObject.is() )
812 0 : xTransactedObject->commit();
813 0 : }
814 : }
815 0 : }
816 :
817 : // Commit changes
818 0 : if ( bCommit )
819 : {
820 0 : Reference< XTransactedObject > xTransactedObject( m_xDocConfigStorage, UNO_QUERY );
821 0 : if ( xTransactedObject.is() )
822 0 : xTransactedObject->commit();
823 : }
824 :
825 : // remove settings from user defined layer and notify listener about removed settings data!
826 : // Try to access our module sub folder
827 0 : ConfigEventNotifyContainer aRemoveEventNotifyContainer;
828 0 : for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ )
829 : {
830 0 : UIElementType& rDocElementType = m_aUIElements[j];
831 :
832 0 : impl_resetElementTypeData( rDocElementType, aRemoveEventNotifyContainer );
833 0 : rDocElementType.bModified = false;
834 : }
835 :
836 0 : m_bModified = false;
837 :
838 : // Unlock mutex before notify our listeners
839 0 : aGuard.clear();
840 :
841 : // Notify our listeners
842 0 : for ( size_t k = 0; k < aRemoveEventNotifyContainer.size(); k++ )
843 0 : implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove );
844 : }
845 0 : catch ( const ::com::sun::star::lang::IllegalArgumentException& )
846 : {
847 : }
848 0 : catch ( const ::com::sun::star::container::NoSuchElementException& )
849 : {
850 : }
851 0 : catch ( const ::com::sun::star::embed::InvalidStorageException& )
852 : {
853 : }
854 0 : catch ( const ::com::sun::star::embed::StorageWrappedTargetException& )
855 : {
856 : }
857 0 : }
858 : }
859 :
860 3272 : Sequence< Sequence< PropertyValue > > SAL_CALL UIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType )
861 : throw ( IllegalArgumentException, RuntimeException, std::exception )
862 : {
863 3272 : if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
864 0 : throw IllegalArgumentException();
865 :
866 3272 : SolarMutexGuard g;
867 3272 : if ( m_bDisposed )
868 0 : throw DisposedException();
869 :
870 3272 : Sequence< Sequence< PropertyValue > > aElementInfoSeq;
871 6544 : UIElementInfoHashMap aUIElementInfoCollection;
872 :
873 3272 : if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN )
874 : {
875 0 : for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
876 0 : impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) );
877 : }
878 : else
879 3272 : impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType );
880 :
881 6544 : Sequence< PropertyValue > aUIElementInfo( 2 );
882 3272 : aUIElementInfo[0].Name = m_aPropResourceURL;
883 3272 : aUIElementInfo[1].Name = m_aPropUIName;
884 :
885 3272 : aElementInfoSeq.realloc( aUIElementInfoCollection.size() );
886 3272 : UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin();
887 :
888 3272 : sal_Int32 n = 0;
889 6544 : while ( pIter != aUIElementInfoCollection.end() )
890 : {
891 0 : aUIElementInfo[0].Value <<= pIter->second.aResourceURL;
892 0 : aUIElementInfo[1].Value <<= pIter->second.aUIName;
893 0 : aElementInfoSeq[n++] = aUIElementInfo;
894 0 : ++pIter;
895 : }
896 :
897 6544 : return aElementInfoSeq;
898 : }
899 :
900 0 : Reference< XIndexContainer > SAL_CALL UIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException, std::exception)
901 : {
902 0 : SolarMutexGuard g;
903 :
904 0 : if ( m_bDisposed )
905 0 : throw DisposedException();
906 :
907 : // Creates an empty item container which can be filled from outside
908 0 : return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer()), UNO_QUERY );
909 : }
910 :
911 13108 : sal_Bool SAL_CALL UIConfigurationManager::hasSettings( const OUString& ResourceURL )
912 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
913 : {
914 13108 : sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
915 :
916 13108 : if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
917 : ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
918 0 : throw IllegalArgumentException();
919 : else
920 : {
921 13108 : UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
922 13108 : if ( pDataSettings && !pDataSettings->bDefault )
923 0 : return sal_True;
924 : }
925 :
926 13108 : return sal_False;
927 : }
928 :
929 0 : Reference< XIndexAccess > SAL_CALL UIConfigurationManager::getSettings( const OUString& ResourceURL, sal_Bool bWriteable )
930 : throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
931 : {
932 0 : sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
933 :
934 0 : if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
935 : ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
936 0 : throw IllegalArgumentException();
937 : else
938 : {
939 0 : SolarMutexGuard g;
940 :
941 0 : if ( m_bDisposed )
942 0 : throw DisposedException();
943 :
944 0 : UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
945 0 : if ( pDataSettings && !pDataSettings->bDefault )
946 : {
947 : // Create a copy of our data if someone wants to change the data.
948 0 : if ( bWriteable )
949 0 : return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY );
950 : else
951 0 : return pDataSettings->xSettings;
952 0 : }
953 : }
954 :
955 0 : throw NoSuchElementException();
956 : }
957 :
958 0 : void SAL_CALL UIConfigurationManager::replaceSettings( const OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData )
959 : throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException, std::exception)
960 : {
961 0 : sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
962 :
963 0 : if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
964 : ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
965 0 : throw IllegalArgumentException();
966 0 : else if ( m_bReadOnly )
967 0 : throw IllegalAccessException();
968 : else
969 : {
970 0 : SolarMutexClearableGuard aGuard;
971 :
972 0 : if ( m_bDisposed )
973 0 : throw DisposedException();
974 :
975 0 : UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
976 0 : if ( pDataSettings && !pDataSettings->bDefault )
977 : {
978 : // we have a settings entry in our user-defined layer - replace
979 0 : Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings;
980 :
981 : // Create a copy of the data if the container is not const
982 0 : Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
983 0 : if ( xReplace.is() )
984 0 : pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
985 : else
986 0 : pDataSettings->xSettings = aNewData;
987 :
988 0 : pDataSettings->bDefault = false;
989 0 : pDataSettings->bModified = true;
990 0 : m_bModified = true;
991 :
992 : // Modify type container
993 0 : UIElementType& rElementType = m_aUIElements[nElementType];
994 0 : rElementType.bModified = true;
995 :
996 0 : Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
997 0 : Reference< XInterface > xIfac( xThis, UNO_QUERY );
998 :
999 : // Create event to notify listener about replaced element settings
1000 0 : ConfigurationEvent aEvent;
1001 :
1002 0 : aEvent.ResourceURL = ResourceURL;
1003 0 : aEvent.Accessor <<= xThis;
1004 0 : aEvent.Source = xIfac;
1005 0 : aEvent.ReplacedElement <<= xOldSettings;
1006 0 : aEvent.Element <<= pDataSettings->xSettings;
1007 :
1008 0 : aGuard.clear();
1009 :
1010 0 : implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1011 : }
1012 : else
1013 0 : throw NoSuchElementException();
1014 : }
1015 0 : }
1016 :
1017 0 : void SAL_CALL UIConfigurationManager::removeSettings( const OUString& ResourceURL )
1018 : throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException, std::exception)
1019 : {
1020 0 : sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1021 :
1022 0 : if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1023 : ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1024 0 : throw IllegalArgumentException();
1025 0 : else if ( m_bReadOnly )
1026 0 : throw IllegalAccessException();
1027 : else
1028 : {
1029 0 : SolarMutexClearableGuard aGuard;
1030 :
1031 0 : if ( m_bDisposed )
1032 0 : throw DisposedException();
1033 :
1034 0 : UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1035 0 : if ( pDataSettings )
1036 : {
1037 : // If element settings are default, we don't need to change anything!
1038 0 : if ( pDataSettings->bDefault )
1039 0 : return;
1040 : else
1041 : {
1042 0 : Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings;
1043 0 : pDataSettings->bDefault = true;
1044 :
1045 : // check if this is a default layer node
1046 0 : pDataSettings->bModified = true; // we have to remove this node from the user layer!
1047 0 : pDataSettings->xSettings.clear();
1048 0 : m_bModified = true; // user layer must be written
1049 :
1050 : // Modify type container
1051 0 : UIElementType& rElementType = m_aUIElements[nElementType];
1052 0 : rElementType.bModified = true;
1053 :
1054 0 : Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1055 0 : Reference< XInterface > xIfac( xThis, UNO_QUERY );
1056 :
1057 : // Create event to notify listener about removed element settings
1058 0 : ConfigurationEvent aEvent;
1059 :
1060 0 : aEvent.ResourceURL = ResourceURL;
1061 0 : aEvent.Accessor <<= xThis;
1062 0 : aEvent.Source = xIfac;
1063 0 : aEvent.Element <<= xRemovedSettings;
1064 :
1065 0 : aGuard.clear();
1066 :
1067 0 : implts_notifyContainerListener( aEvent, NotifyOp_Remove );
1068 : }
1069 : }
1070 : else
1071 0 : throw NoSuchElementException();
1072 : }
1073 : }
1074 :
1075 0 : void SAL_CALL UIConfigurationManager::insertSettings( const OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData )
1076 : throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException, std::exception )
1077 : {
1078 0 : sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL );
1079 :
1080 0 : if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1081 : ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1082 0 : throw IllegalArgumentException();
1083 0 : else if ( m_bReadOnly )
1084 0 : throw IllegalAccessException();
1085 : else
1086 : {
1087 0 : SolarMutexClearableGuard aGuard;
1088 :
1089 0 : if ( m_bDisposed )
1090 0 : throw DisposedException();
1091 :
1092 0 : bool bInsertData( false );
1093 0 : UIElementData aUIElementData;
1094 0 : UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType );
1095 :
1096 0 : if ( pDataSettings && !pDataSettings->bDefault )
1097 0 : throw ElementExistException();
1098 :
1099 0 : if ( !pDataSettings )
1100 : {
1101 0 : pDataSettings = &aUIElementData;
1102 0 : bInsertData = true;
1103 : }
1104 :
1105 : {
1106 0 : pDataSettings->bDefault = false;
1107 0 : pDataSettings->bModified = true;
1108 :
1109 : // Create a copy of the data if the container is not const
1110 0 : Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1111 0 : if ( xReplace.is() )
1112 0 : pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1113 : else
1114 0 : pDataSettings->xSettings = aNewData;
1115 :
1116 0 : m_bModified = true;
1117 :
1118 0 : UIElementType& rElementType = m_aUIElements[nElementType];
1119 0 : rElementType.bModified = true;
1120 :
1121 0 : if ( bInsertData )
1122 : {
1123 0 : pDataSettings->aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix;
1124 0 : pDataSettings->aResourceURL = NewResourceURL;
1125 :
1126 0 : UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1127 0 : rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, *pDataSettings ));
1128 : }
1129 :
1130 0 : Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings );
1131 0 : Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1132 0 : Reference< XInterface > xIfac( xThis, UNO_QUERY );
1133 :
1134 : // Create event to notify listener about removed element settings
1135 0 : ConfigurationEvent aEvent;
1136 :
1137 0 : aEvent.ResourceURL = NewResourceURL;
1138 0 : aEvent.Accessor <<= xThis;
1139 0 : aEvent.Source = xIfac;
1140 0 : aEvent.Element <<= xInsertSettings;
1141 :
1142 0 : aGuard.clear();
1143 :
1144 0 : implts_notifyContainerListener( aEvent, NotifyOp_Insert );
1145 0 : }
1146 : }
1147 0 : }
1148 :
1149 69252 : Reference< XInterface > SAL_CALL UIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException, std::exception)
1150 : {
1151 69252 : if ( m_bDisposed )
1152 0 : throw DisposedException();
1153 :
1154 69252 : if ( !m_xImageManager.is() )
1155 : {
1156 6360 : m_xImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ImageManager( m_xContext )),
1157 3180 : UNO_QUERY );
1158 3180 : Reference< XInitialization > xInit( m_xImageManager, UNO_QUERY );
1159 :
1160 6360 : Sequence< Any > aPropSeq( 2 );
1161 6360 : PropertyValue aPropValue;
1162 3180 : aPropValue.Name = "UserConfigStorage";
1163 3180 : aPropValue.Value = makeAny( m_xDocConfigStorage );
1164 3180 : aPropSeq[0] = makeAny( aPropValue );
1165 3180 : aPropValue.Name = "ModuleIdentifier";
1166 3180 : aPropValue.Value = makeAny( m_aModuleIdentifier );
1167 3180 : aPropSeq[1] = makeAny( aPropValue );
1168 :
1169 6360 : xInit->initialize( aPropSeq );
1170 : }
1171 :
1172 69252 : return Reference< XInterface >( m_xImageManager, UNO_QUERY );
1173 : }
1174 :
1175 1736 : Reference< XAcceleratorConfiguration > SAL_CALL UIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException, std::exception)
1176 : {
1177 : // SAFE ->
1178 1736 : SolarMutexGuard g;
1179 :
1180 1736 : if (!m_xAccConfig.is()) try
1181 : {
1182 1176 : m_xAccConfig = DocumentAcceleratorConfiguration::
1183 588 : createWithDocumentRoot(m_xContext, m_xDocConfigStorage);
1184 : }
1185 0 : catch ( const css::uno::DeploymentException& )
1186 : {
1187 : SAL_WARN("fwk.uiconfiguration", "DocumentAcceleratorConfiguration"
1188 : " not available. This should happen only on mobile platforms.");
1189 : }
1190 :
1191 1736 : return m_xAccConfig;
1192 : }
1193 :
1194 0 : Reference< XInterface > SAL_CALL UIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException, std::exception)
1195 : {
1196 0 : return Reference< XInterface >();
1197 : }
1198 :
1199 : // XUIConfigurationStorage
1200 4146 : void SAL_CALL UIConfigurationManager::setStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1201 : {
1202 4146 : SolarMutexGuard g;
1203 :
1204 4146 : if ( m_bDisposed )
1205 0 : throw DisposedException();
1206 :
1207 4146 : if ( m_xDocConfigStorage.is() )
1208 : {
1209 : try
1210 : {
1211 : // Dispose old storage to be sure that it will be closed
1212 601 : Reference< XComponent > xComponent( m_xDocConfigStorage, UNO_QUERY );
1213 601 : if ( xComponent.is() )
1214 879 : xComponent->dispose();
1215 : }
1216 278 : catch ( const Exception& )
1217 : {
1218 : }
1219 : }
1220 :
1221 : // We store the new storage. Be careful it could be an empty reference!
1222 4146 : m_xDocConfigStorage = Storage;
1223 4146 : m_bReadOnly = true;
1224 :
1225 8292 : Reference< XUIConfigurationStorage > xAccUpdate(m_xAccConfig, UNO_QUERY);
1226 4146 : if ( xAccUpdate.is() )
1227 4 : xAccUpdate->setStorage( m_xDocConfigStorage );
1228 :
1229 4146 : if ( m_xImageManager.is() )
1230 : {
1231 21 : ImageManager* pImageManager = static_cast<ImageManager*>(m_xImageManager.get());
1232 21 : if ( pImageManager )
1233 21 : pImageManager->setStorage( m_xDocConfigStorage );
1234 : }
1235 :
1236 4146 : if ( m_xDocConfigStorage.is() )
1237 : {
1238 4116 : Reference< XPropertySet > xPropSet( m_xDocConfigStorage, UNO_QUERY );
1239 4116 : if ( xPropSet.is() )
1240 : {
1241 : try
1242 : {
1243 4116 : long nOpenMode = 0;
1244 4116 : Any a = xPropSet->getPropertyValue("OpenMode");
1245 4116 : if ( a >>= nOpenMode )
1246 4116 : m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
1247 : }
1248 0 : catch ( const com::sun::star::beans::UnknownPropertyException& )
1249 : {
1250 : }
1251 0 : catch ( const com::sun::star::lang::WrappedTargetException& )
1252 : {
1253 : }
1254 4116 : }
1255 : }
1256 :
1257 8292 : impl_Initialize();
1258 4146 : }
1259 :
1260 0 : sal_Bool SAL_CALL UIConfigurationManager::hasStorage() throw (::com::sun::star::uno::RuntimeException, std::exception)
1261 : {
1262 0 : SolarMutexGuard g;
1263 :
1264 0 : if ( m_bDisposed )
1265 0 : throw DisposedException();
1266 :
1267 0 : return ( m_xDocConfigStorage.is() );
1268 : }
1269 :
1270 : // XUIConfigurationPersistence
1271 0 : void SAL_CALL UIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
1272 : {
1273 0 : SolarMutexClearableGuard aGuard;
1274 :
1275 0 : if ( m_bDisposed )
1276 0 : throw DisposedException();
1277 :
1278 0 : if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly )
1279 : {
1280 : // Try to access our module sub folder
1281 0 : ConfigEventNotifyContainer aRemoveNotifyContainer;
1282 0 : ConfigEventNotifyContainer aReplaceNotifyContainer;
1283 0 : for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1284 : {
1285 : try
1286 : {
1287 0 : UIElementType& rDocElementType = m_aUIElements[i];
1288 0 : if ( rDocElementType.bModified )
1289 0 : impl_reloadElementTypeData( rDocElementType, aRemoveNotifyContainer, aReplaceNotifyContainer );
1290 : }
1291 0 : catch ( const Exception& )
1292 : {
1293 0 : throw IOException();
1294 : }
1295 : }
1296 :
1297 0 : m_bModified = false;
1298 :
1299 : // Unlock mutex before notify our listeners
1300 0 : aGuard.clear();
1301 :
1302 : // Notify our listeners
1303 0 : for ( size_t j = 0; j < aRemoveNotifyContainer.size(); j++ )
1304 0 : implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove );
1305 0 : for ( size_t k = 0; k < aReplaceNotifyContainer.size(); k++ )
1306 0 : implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace );
1307 0 : }
1308 0 : }
1309 :
1310 0 : void SAL_CALL UIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
1311 : {
1312 0 : SolarMutexGuard g;
1313 :
1314 0 : if ( m_bDisposed )
1315 0 : throw DisposedException();
1316 :
1317 0 : if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly )
1318 : {
1319 : // Try to access our module sub folder
1320 0 : for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1321 : {
1322 : try
1323 : {
1324 0 : UIElementType& rElementType = m_aUIElements[i];
1325 0 : Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY );
1326 :
1327 0 : if ( rElementType.bModified && xStorage.is() )
1328 0 : impl_storeElementTypeData( xStorage, rElementType );
1329 : }
1330 0 : catch ( const Exception& )
1331 : {
1332 0 : throw IOException();
1333 : }
1334 : }
1335 :
1336 0 : m_bModified = false;
1337 0 : Reference< XTransactedObject > xTransactedObject( m_xDocConfigStorage, UNO_QUERY );
1338 0 : if ( xTransactedObject.is() )
1339 0 : xTransactedObject->commit();
1340 0 : }
1341 0 : }
1342 :
1343 0 : void SAL_CALL UIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
1344 : {
1345 0 : SolarMutexGuard g;
1346 :
1347 0 : if ( m_bDisposed )
1348 0 : throw DisposedException();
1349 :
1350 0 : if ( m_xDocConfigStorage.is() && m_bModified && !m_bReadOnly )
1351 : {
1352 : // Try to access our module sub folder
1353 0 : for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1354 : {
1355 : try
1356 : {
1357 0 : Reference< XStorage > xElementTypeStorage( Storage->openStorageElement(
1358 0 : OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE ));
1359 0 : UIElementType& rElementType = m_aUIElements[i];
1360 :
1361 0 : if ( rElementType.bModified && xElementTypeStorage.is() )
1362 0 : impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag!
1363 : }
1364 0 : catch ( const Exception& )
1365 : {
1366 0 : throw IOException();
1367 : }
1368 : }
1369 :
1370 0 : Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY );
1371 0 : if ( xTransactedObject.is() )
1372 0 : xTransactedObject->commit();
1373 0 : }
1374 0 : }
1375 :
1376 0 : sal_Bool SAL_CALL UIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException, std::exception)
1377 : {
1378 0 : SolarMutexGuard g;
1379 :
1380 0 : return m_bModified;
1381 : }
1382 :
1383 0 : sal_Bool SAL_CALL UIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException, std::exception)
1384 : {
1385 0 : SolarMutexGuard g;
1386 :
1387 0 : return m_bReadOnly;
1388 : }
1389 :
1390 0 : void UIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
1391 : {
1392 0 : ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( cppu::UnoType<com::sun::star::ui::XUIConfigurationListener>::get());
1393 0 : if ( pContainer != NULL )
1394 : {
1395 0 : ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1396 0 : while ( pIterator.hasMoreElements() )
1397 : {
1398 : try
1399 : {
1400 0 : switch ( eOp )
1401 : {
1402 : case NotifyOp_Replace:
1403 0 : static_cast< ::com::sun::star::ui::XUIConfigurationListener*>(pIterator.next())->elementReplaced( aEvent );
1404 0 : break;
1405 : case NotifyOp_Insert:
1406 0 : static_cast< ::com::sun::star::ui::XUIConfigurationListener*>(pIterator.next())->elementInserted( aEvent );
1407 0 : break;
1408 : case NotifyOp_Remove:
1409 0 : static_cast< ::com::sun::star::ui::XUIConfigurationListener*>(pIterator.next())->elementRemoved( aEvent );
1410 0 : break;
1411 : }
1412 : }
1413 0 : catch( const css::uno::RuntimeException& )
1414 : {
1415 0 : pIterator.remove();
1416 : }
1417 0 : }
1418 : }
1419 0 : }
1420 :
1421 : }
1422 :
1423 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1424 3546 : com_sun_star_comp_framework_UIConfigurationManager_get_implementation(
1425 : css::uno::XComponentContext *context,
1426 : css::uno::Sequence<css::uno::Any> const &)
1427 : {
1428 3546 : return cppu::acquire(new UIConfigurationManager(context));
1429 : }
1430 :
1431 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|