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