1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 #include <uiconfiguration/moduleuiconfigurationmanager.hxx>
27 #include <threadhelp/resetableguard.hxx>
28 #include <services.h>
29 #include <uielement/constitemcontainer.hxx>
30 #include <uielement/rootitemcontainer.hxx>
31 #include <uielement/uielementtypenames.hxx>
32 #include <framework/menuconfiguration.hxx>
33 #include <framework/toolboxconfiguration.hxx>
34
35 #ifndef __FRAMEWORK_XML_STATUSBARCONFIGURATION_HXX_
36 #include <framework/statusbarconfiguration.hxx>
37 #endif
38
39 //_________________________________________________________________________________________________________________
40 // interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/ui/UIElementType.hpp>
43 #include <com/sun/star/ui/ConfigurationEvent.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/embed/ElementModes.hpp>
47 #include <com/sun/star/container/XNameAccess.hpp>
48 #include <com/sun/star/io/XStream.hpp>
49
50 //_________________________________________________________________________________________________________________
51 // other includes
52 //_________________________________________________________________________________________________________________
53
54 #include <vcl/svapp.hxx>
55 #include <rtl/ustrbuf.hxx>
56 #include <comphelper/sequenceashashmap.hxx>
57
58 //_________________________________________________________________________________________________________________
59 // namespaces
60 //_________________________________________________________________________________________________________________
61
62 using rtl::OUString;
63 using namespace com::sun::star::uno;
64 using namespace com::sun::star::io;
65 using namespace com::sun::star::embed;
66 using namespace com::sun::star::lang;
67 using namespace com::sun::star::container;
68 using namespace com::sun::star::beans;
69 using namespace ::com::sun::star::ui;
70
71 namespace framework
72 {
73
74 //*****************************************************************************************************************
75 // XInterface, XTypeProvider, XServiceInfo
76 //*****************************************************************************************************************
77 DEFINE_XINTERFACE_8 ( ModuleUIConfigurationManager ,
78 OWeakObject ,
79 DIRECT_INTERFACE( css::lang::XTypeProvider ),
80 DIRECT_INTERFACE( css::lang::XServiceInfo ),
81 DIRECT_INTERFACE( css::lang::XComponent ),
82 DIRECT_INTERFACE( css::lang::XInitialization ),
83 DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfiguration ),
84 DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationManager ),
85 DIRECT_INTERFACE( ::com::sun::star::ui::XModuleUIConfigurationManager ),
86 DIRECT_INTERFACE( ::com::sun::star::ui::XUIConfigurationPersistence )
87 )
88
89 DEFINE_XTYPEPROVIDER_8 ( ModuleUIConfigurationManager ,
90 css::lang::XTypeProvider ,
91 css::lang::XServiceInfo ,
92 css::lang::XComponent ,
93 css::lang::XInitialization ,
94 ::com::sun::star::ui::XUIConfiguration ,
95 ::com::sun::star::ui::XUIConfigurationManager ,
96 ::com::sun::star::ui::XModuleUIConfigurationManager ,
97 ::com::sun::star::ui::XUIConfigurationPersistence
98 )
99
100 DEFINE_XSERVICEINFO_MULTISERVICE ( ModuleUIConfigurationManager ,
101 ::cppu::OWeakObject ,
102 SERVICENAME_MODULEUICONFIGURATIONMANAGER ,
103 IMPLEMENTATIONNAME_MODULEUICONFIGURATIONMANAGER
104 )
105
106 DEFINE_INIT_SERVICE ( ModuleUIConfigurationManager, {} )
107
108
109 // important: The order and position of the elements must match the constant
110 // definition of "::com::sun::star::ui::UIElementType"
111 static const char* UIELEMENTTYPENAMES[] =
112 {
113 "", // Dummy value for unknown!
114 UIELEMENTTYPE_MENUBAR_NAME,
115 UIELEMENTTYPE_POPUPMENU_NAME,
116 UIELEMENTTYPE_TOOLBAR_NAME,
117 UIELEMENTTYPE_STATUSBAR_NAME,
118 UIELEMENTTYPE_FLOATINGWINDOW_NAME,
119 UIELEMENTTYPE_PROGRESSBAR_NAME,
120 UIELEMENTTYPE_TOOLPANEL_NAME
121 };
122
123 static const char RESOURCEURL_PREFIX[] = "private:resource/";
124 static const sal_Int32 RESOURCEURL_PREFIX_SIZE = 17;
125 static const char RESOURCEURL_CUSTOM_ELEMENT[] = "custom_";
126
RetrieveTypeFromResourceURL(const rtl::OUString & aResourceURL)127 static sal_Int16 RetrieveTypeFromResourceURL( const rtl::OUString& aResourceURL )
128 {
129
130 if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
131 ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
132 {
133 OUString aTmpStr = aResourceURL.copy( RESOURCEURL_PREFIX_SIZE );
134 sal_Int32 nIndex = aTmpStr.indexOf( '/' );
135 if (( nIndex > 0 ) && ( aTmpStr.getLength() > nIndex ))
136 {
137 OUString aTypeStr( aTmpStr.copy( 0, nIndex ));
138 for ( int i = 0; i < UIElementType::COUNT; i++ )
139 {
140 if ( aTypeStr.equalsAscii( UIELEMENTTYPENAMES[i] ))
141 return sal_Int16( i );
142 }
143 }
144 }
145
146 return UIElementType::UNKNOWN;
147 }
148
RetrieveNameFromResourceURL(const rtl::OUString & aResourceURL)149 static OUString RetrieveNameFromResourceURL( const rtl::OUString& aResourceURL )
150 {
151 if (( aResourceURL.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_PREFIX ))) == 0 ) &&
152 ( aResourceURL.getLength() > RESOURCEURL_PREFIX_SIZE ))
153 {
154 sal_Int32 nIndex = aResourceURL.lastIndexOf( '/' );
155 if (( nIndex > 0 ) && (( nIndex+1 ) < aResourceURL.getLength()))
156 return aResourceURL.copy( nIndex+1 );
157 }
158
159 return OUString();
160 }
161
impl_fillSequenceWithElementTypeInfo(UIElementInfoHashMap & aUIElementInfoCollection,sal_Int16 nElementType)162 void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType )
163 {
164 // preload list of element types on demand
165 impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType );
166 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
167
168 UIElementDataHashMap& rUserElements = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap;
169 UIElementDataHashMap::const_iterator pUserIter = rUserElements.begin();
170
171 OUString aCustomUrlPrefix( RTL_CONSTASCII_USTRINGPARAM( RESOURCEURL_CUSTOM_ELEMENT ));
172 while ( pUserIter != rUserElements.end() )
173 {
174 sal_Int32 nIndex = pUserIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE );
175 if ( nIndex > RESOURCEURL_PREFIX_SIZE )
176 {
177 // Performance: Retrieve user interface name only for custom user interface elements.
178 // It's only used by them!
179 UIElementData* pDataSettings = impl_findUIElementData( pUserIter->second.aResourceURL, nElementType );
180 if ( pDataSettings )
181 {
182 // Retrieve user interface name from XPropertySet interface
183 rtl::OUString aUIName;
184 Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
185 if ( xPropSet.is() )
186 {
187 Any a = xPropSet->getPropertyValue( m_aPropUIName );
188 a >>= aUIName;
189 }
190
191 UIElementInfo aInfo( pUserIter->second.aResourceURL, aUIName );
192 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo ));
193 }
194 }
195 else
196 {
197 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
198 UIElementInfo aInfo( pUserIter->second.aResourceURL, OUString() );
199 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pUserIter->second.aResourceURL, aInfo ));
200 }
201 ++pUserIter;
202 }
203
204 UIElementDataHashMap& rDefaultElements = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
205 UIElementDataHashMap::const_iterator pDefIter = rDefaultElements.begin();
206
207 while ( pDefIter != rDefaultElements.end() )
208 {
209 UIElementInfoHashMap::const_iterator pIterInfo = aUIElementInfoCollection.find( pDefIter->second.aResourceURL );
210 if ( pIterInfo == aUIElementInfoCollection.end() )
211 {
212 sal_Int32 nIndex = pDefIter->second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX_SIZE );
213 if ( nIndex > RESOURCEURL_PREFIX_SIZE )
214 {
215 // Performance: Retrieve user interface name only for custom user interface elements.
216 // It's only used by them!
217 UIElementData* pDataSettings = impl_findUIElementData( pDefIter->second.aResourceURL, nElementType );
218 if ( pDataSettings )
219 {
220 // Retrieve user interface name from XPropertySet interface
221 rtl::OUString aUIName;
222 Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
223 if ( xPropSet.is() )
224 {
225 Any a = xPropSet->getPropertyValue( m_aPropUIName );
226 a >>= aUIName;
227 }
228
229 UIElementInfo aInfo( pDefIter->second.aResourceURL, aUIName );
230 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo ));
231 }
232 }
233 else
234 {
235 // The user interface name for standard user interface elements is stored in the WindowState.xcu file
236 UIElementInfo aInfo( pDefIter->second.aResourceURL, OUString() );
237 aUIElementInfoCollection.insert( UIElementInfoHashMap::value_type( pDefIter->second.aResourceURL, aInfo ));
238 }
239 }
240
241 ++pDefIter;
242 }
243 }
244
impl_preloadUIElementTypeList(Layer eLayer,sal_Int16 nElementType)245 void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType )
246 {
247 UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType];
248
249 if ( !rElementTypeData.bLoaded )
250 {
251 Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
252 if ( xElementTypeStorage.is() )
253 {
254 rtl::OUStringBuffer aBuf( RESOURCEURL_PREFIX_SIZE );
255 aBuf.appendAscii( RESOURCEURL_PREFIX );
256 aBuf.appendAscii( UIELEMENTTYPENAMES[ nElementType ] );
257 aBuf.appendAscii( "/" );
258 OUString aResURLPrefix( aBuf.makeStringAndClear() );
259
260 UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap;
261 Reference< XNameAccess > xNameAccess( xElementTypeStorage, UNO_QUERY );
262 Sequence< OUString > aUIElementNames = xNameAccess->getElementNames();
263 for ( sal_Int32 n = 0; n < aUIElementNames.getLength(); n++ )
264 {
265 UIElementData aUIElementData;
266
267 // Resource name must be without ".xml"
268 sal_Int32 nIndex = aUIElementNames[n].lastIndexOf( '.' );
269 if (( nIndex > 0 ) && ( nIndex < aUIElementNames[n].getLength() ))
270 {
271 OUString aExtension( aUIElementNames[n].copy( nIndex+1 ));
272 OUString aUIElementName( aUIElementNames[n].copy( 0, nIndex ));
273
274 if (( aUIElementName.getLength() > 0 ) &&
275 ( aExtension.equalsIgnoreAsciiCaseAsciiL( "xml", 3 )))
276 {
277 aUIElementData.aResourceURL = aResURLPrefix + aUIElementName;
278 aUIElementData.aName = aUIElementNames[n];
279
280 if ( eLayer == LAYER_USERDEFINED )
281 {
282 aUIElementData.bModified = false;
283 aUIElementData.bDefault = false;
284 aUIElementData.bDefaultNode = false;
285 }
286
287 // Create hash_map entries for all user interface elements inside the storage. We don't load the
288 // settings to speed up the process.
289 rHashMap.insert( UIElementDataHashMap::value_type( aUIElementData.aResourceURL, aUIElementData ));
290 }
291 }
292 rElementTypeData.bLoaded = true;
293 }
294 }
295 }
296
297 //rElementTypeData.bLoaded = true;
298 }
299
impl_requestUIElementData(sal_Int16 nElementType,Layer eLayer,UIElementData & aUIElementData)300 void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData )
301 {
302 UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType];
303
304 Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
305 if ( xElementTypeStorage.is() && aUIElementData.aName.getLength() )
306 {
307 try
308 {
309 Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ );
310 Reference< XInputStream > xInputStream = xStream->getInputStream();
311
312 if ( xInputStream.is() )
313 {
314 switch ( nElementType )
315 {
316 case ::com::sun::star::ui::UIElementType::UNKNOWN:
317 break;
318
319 case ::com::sun::star::ui::UIElementType::MENUBAR:
320 {
321 try
322 {
323 MenuConfiguration aMenuCfg( m_xServiceManager );
324 Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream ));
325 RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xContainer );
326 if ( pRootItemContainer )
327 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
328 else
329 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( xContainer, sal_True ) ), UNO_QUERY );
330 return;
331 }
332 catch ( ::com::sun::star::lang::WrappedTargetException& )
333 {
334 }
335 }
336 break;
337
338 case ::com::sun::star::ui::UIElementType::POPUPMENU:
339 {
340 break;
341 }
342
343 case ::com::sun::star::ui::UIElementType::TOOLBAR:
344 {
345 try
346 {
347 Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
348 ToolBoxConfiguration::LoadToolBox( m_xServiceManager, xInputStream, xIndexContainer );
349 RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
350 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
351 return;
352 }
353 catch ( ::com::sun::star::lang::WrappedTargetException& )
354 {
355 }
356
357 break;
358 }
359
360 case ::com::sun::star::ui::UIElementType::STATUSBAR:
361 {
362 try
363 {
364 Reference< XIndexContainer > xIndexContainer( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
365 StatusBarConfiguration::LoadStatusBar( m_xServiceManager, xInputStream, xIndexContainer );
366 RootItemContainer* pRootItemContainer = RootItemContainer::GetImplementation( xIndexContainer );
367 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( pRootItemContainer, sal_True ) ), UNO_QUERY );
368 return;
369 }
370 catch ( ::com::sun::star::lang::WrappedTargetException& )
371 {
372 }
373
374 break;
375 }
376
377 case ::com::sun::star::ui::UIElementType::FLOATINGWINDOW:
378 {
379 break;
380 }
381 }
382 }
383 }
384 catch ( ::com::sun::star::embed::InvalidStorageException& )
385 {
386 }
387 catch ( ::com::sun::star::lang::IllegalArgumentException& )
388 {
389 }
390 catch ( ::com::sun::star::io::IOException& )
391 {
392 }
393 catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
394 {
395 }
396 }
397
398 // At least we provide an empty settings container!
399 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer() ), UNO_QUERY );
400 }
401
impl_findUIElementData(const rtl::OUString & aResourceURL,sal_Int16 nElementType,bool bLoad)402 ModuleUIConfigurationManager::UIElementData* ModuleUIConfigurationManager::impl_findUIElementData( const rtl::OUString& aResourceURL, sal_Int16 nElementType, bool bLoad )
403 {
404 // preload list of element types on demand
405 impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType );
406 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
407
408 // first try to look into our user-defined vector/hash_map combination
409 UIElementDataHashMap& rUserHashMap = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap;
410 UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL );
411 if ( pIter != rUserHashMap.end() )
412 {
413 // Default data settings data must be retrieved from the default layer!
414 if ( !pIter->second.bDefault )
415 {
416 if ( !pIter->second.xSettings.is() && bLoad )
417 impl_requestUIElementData( nElementType, LAYER_USERDEFINED, pIter->second );
418 return &(pIter->second);
419 }
420 }
421
422 // Not successful, we have to look into our default vector/hash_map combination
423 UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
424 pIter = rDefaultHashMap.find( aResourceURL );
425 if ( pIter != rDefaultHashMap.end() )
426 {
427 if ( !pIter->second.xSettings.is() && bLoad )
428 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
429 return &(pIter->second);
430 }
431
432 // Nothing has been found!
433 return NULL;
434 }
435
impl_storeElementTypeData(Reference<XStorage> xStorage,UIElementType & rElementType,bool bResetModifyState)436 void ModuleUIConfigurationManager::impl_storeElementTypeData( Reference< XStorage > xStorage, UIElementType& rElementType, bool bResetModifyState )
437 {
438 UIElementDataHashMap& rHashMap = rElementType.aElementsHashMap;
439 UIElementDataHashMap::iterator pIter = rHashMap.begin();
440
441 while ( pIter != rHashMap.end() )
442 {
443 UIElementData& rElement = pIter->second;
444 if ( rElement.bModified )
445 {
446 if ( rElement.bDefault )
447 {
448 xStorage->removeElement( rElement.aName );
449 rElement.bModified = sal_False; // mark as not modified
450 }
451 else
452 {
453 Reference< XStream > xStream( xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE ), UNO_QUERY );
454 Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
455
456 if ( xOutputStream.is() )
457 {
458 switch( rElementType.nElementType )
459 {
460 case ::com::sun::star::ui::UIElementType::MENUBAR:
461 {
462 try
463 {
464 MenuConfiguration aMenuCfg( m_xServiceManager );
465 aMenuCfg.StoreMenuBarConfigurationToXML( rElement.xSettings, xOutputStream );
466 }
467 catch ( ::com::sun::star::lang::WrappedTargetException& )
468 {
469 }
470 }
471 break;
472
473 case ::com::sun::star::ui::UIElementType::TOOLBAR:
474 {
475 try
476 {
477 ToolBoxConfiguration::StoreToolBox( m_xServiceManager, xOutputStream, rElement.xSettings );
478 }
479 catch ( ::com::sun::star::lang::WrappedTargetException& )
480 {
481 }
482 }
483 break;
484
485 case ::com::sun::star::ui::UIElementType::STATUSBAR:
486 {
487 try
488 {
489 StatusBarConfiguration::StoreStatusBar( m_xServiceManager, xOutputStream, rElement.xSettings );
490 }
491 catch ( ::com::sun::star::lang::WrappedTargetException& )
492 {
493 }
494 }
495 break;
496
497 default:
498 break;
499 }
500 }
501
502 // mark as not modified if we store to our own storage
503 if ( bResetModifyState )
504 rElement.bModified = sal_False;
505 }
506 }
507
508 ++pIter;
509 }
510
511 // commit element type storage
512 Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY );
513 if ( xTransactedObject.is() )
514 xTransactedObject->commit();
515
516 // mark UIElementType as not modified if we store to our own storage
517 if ( bResetModifyState )
518 rElementType.bModified = sal_False;
519 }
520
521 // This is only allowed to be called on the LAYER_USER_DEFINED!
impl_resetElementTypeData(UIElementType & rUserElementType,UIElementType & rDefaultElementType,ConfigEventNotifyContainer & rRemoveNotifyContainer,ConfigEventNotifyContainer & rReplaceNotifyContainer)522 void ModuleUIConfigurationManager::impl_resetElementTypeData(
523 UIElementType& rUserElementType,
524 UIElementType& rDefaultElementType,
525 ConfigEventNotifyContainer& rRemoveNotifyContainer,
526 ConfigEventNotifyContainer& rReplaceNotifyContainer )
527 {
528 UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap;
529 UIElementDataHashMap::iterator pIter = rHashMap.begin();
530
531 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
532 Reference< XInterface > xIfac( xThis, UNO_QUERY );
533 Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY );
534 sal_Int16 nType = rUserElementType.nElementType;
535
536 // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
537 // our listeners!
538 while ( pIter != rHashMap.end() )
539 {
540 UIElementData& rElement = pIter->second;
541 if ( !rElement.bDefault )
542 {
543 if ( xDefaultNameAccess->hasByName( rElement.aName ))
544 {
545 // Replace settings with data from default layer
546 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
547 impl_requestUIElementData( nType, LAYER_DEFAULT, rElement );
548
549 ConfigurationEvent aReplaceEvent;
550 aReplaceEvent.ResourceURL = rElement.aResourceURL;
551 aReplaceEvent.Accessor <<= xThis;
552 aReplaceEvent.Source = xIfac;
553 aReplaceEvent.ReplacedElement <<= xOldSettings;
554 aReplaceEvent.Element <<= rElement.xSettings;
555
556 rReplaceNotifyContainer.push_back( aReplaceEvent );
557
558 // Mark element as default and not modified. That means "not active"
559 // in the user layer anymore.
560 rElement.bModified = false;
561 rElement.bDefault = true;
562 }
563 else
564 {
565 // Remove user-defined settings from user layer
566 ConfigurationEvent aEvent;
567 aEvent.ResourceURL = rElement.aResourceURL;
568 aEvent.Accessor <<= xThis;
569 aEvent.Source = xIfac;
570 aEvent.Element <<= rElement.xSettings;
571
572 rRemoveNotifyContainer.push_back( aEvent );
573
574 // Mark element as default and not modified. That means "not active"
575 // in the user layer anymore.
576 rElement.bModified = false;
577 rElement.bDefault = true;
578 }
579 }
580
581 ++pIter;
582 }
583
584 // Remove all settings from our user interface elements
585 rHashMap.clear();
586 }
587
impl_reloadElementTypeData(UIElementType & rUserElementType,UIElementType & rDefaultElementType,ConfigEventNotifyContainer & rRemoveNotifyContainer,ConfigEventNotifyContainer & rReplaceNotifyContainer)588 void ModuleUIConfigurationManager::impl_reloadElementTypeData(
589 UIElementType& rUserElementType,
590 UIElementType& rDefaultElementType,
591 ConfigEventNotifyContainer& rRemoveNotifyContainer,
592 ConfigEventNotifyContainer& rReplaceNotifyContainer )
593 {
594 UIElementDataHashMap& rHashMap = rUserElementType.aElementsHashMap;
595 UIElementDataHashMap::iterator pIter = rHashMap.begin();
596 Reference< XStorage > xUserStorage( rUserElementType.xStorage );
597 Reference< XStorage > xDefaultStorage( rDefaultElementType.xStorage );
598 Reference< XNameAccess > xUserNameAccess( rUserElementType.xStorage, UNO_QUERY );
599 Reference< XNameAccess > xDefaultNameAccess( rDefaultElementType.xStorage, UNO_QUERY );
600
601 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
602 Reference< XInterface > xIfac( xThis, UNO_QUERY );
603 sal_Int16 nType = rUserElementType.nElementType;
604
605 while ( pIter != rHashMap.end() )
606 {
607 UIElementData& rElement = pIter->second;
608 if ( rElement.bModified )
609 {
610 if ( xUserNameAccess->hasByName( rElement.aName ))
611 {
612 // Replace settings with data from user layer
613 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
614
615 impl_requestUIElementData( nType, LAYER_USERDEFINED, rElement );
616
617 ConfigurationEvent aReplaceEvent;
618
619 aReplaceEvent.ResourceURL = rElement.aResourceURL;
620 aReplaceEvent.Accessor <<= xThis;
621 aReplaceEvent.Source = xIfac;
622 aReplaceEvent.ReplacedElement <<= xOldSettings;
623 aReplaceEvent.Element <<= rElement.xSettings;
624 rReplaceNotifyContainer.push_back( aReplaceEvent );
625
626 rElement.bModified = false;
627 }
628 else if ( xDefaultNameAccess->hasByName( rElement.aName ))
629 {
630 // Replace settings with data from default layer
631 Reference< XIndexAccess > xOldSettings( rElement.xSettings );
632
633 impl_requestUIElementData( nType, LAYER_DEFAULT, rElement );
634
635 ConfigurationEvent aReplaceEvent;
636
637 aReplaceEvent.ResourceURL = rElement.aResourceURL;
638 aReplaceEvent.Accessor <<= xThis;
639 aReplaceEvent.Source = xIfac;
640 aReplaceEvent.ReplacedElement <<= xOldSettings;
641 aReplaceEvent.Element <<= rElement.xSettings;
642 rReplaceNotifyContainer.push_back( aReplaceEvent );
643
644 // Mark element as default and not modified. That means "not active"
645 // in the user layer anymore.
646 rElement.bModified = false;
647 rElement.bDefault = true;
648 }
649 else
650 {
651 // Element settings are not in any storage => remove
652 ConfigurationEvent aRemoveEvent;
653
654 aRemoveEvent.ResourceURL = rElement.aResourceURL;
655 aRemoveEvent.Accessor <<= xThis;
656 aRemoveEvent.Source = xIfac;
657 aRemoveEvent.Element <<= rElement.xSettings;
658
659 rRemoveNotifyContainer.push_back( aRemoveEvent );
660
661 // Mark element as default and not modified. That means "not active"
662 // in the user layer anymore.
663 rElement.bModified = false;
664 rElement.bDefault = true;
665 }
666 }
667 ++pIter;
668 }
669
670 rUserElementType.bModified = sal_False;
671 }
672
impl_Initialize()673 void ModuleUIConfigurationManager::impl_Initialize()
674 {
675 // Initialize the top-level structures with the storage data
676 if ( m_xUserConfigStorage.is() )
677 {
678 // Try to access our module sub folder
679 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT;
680 i++ )
681 {
682 Reference< XStorage > xElementTypeStorage;
683 try
684 {
685 if ( m_pStorageHandler[i] )
686 xElementTypeStorage = m_pStorageHandler[i]->getWorkingStorageUser();
687 }
688 catch ( com::sun::star::container::NoSuchElementException& )
689 {
690 }
691 catch ( ::com::sun::star::embed::InvalidStorageException& )
692 {
693 }
694 catch ( ::com::sun::star::lang::IllegalArgumentException& )
695 {
696 }
697 catch ( ::com::sun::star::io::IOException& )
698 {
699 }
700 catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
701 {
702 }
703
704 m_aUIElements[LAYER_USERDEFINED][i].nElementType = i;
705 m_aUIElements[LAYER_USERDEFINED][i].bModified = false;
706 m_aUIElements[LAYER_USERDEFINED][i].xStorage = xElementTypeStorage;
707 m_aUIElements[LAYER_USERDEFINED][i].bDefaultLayer = false;
708 }
709 }
710
711 if ( m_xDefaultConfigStorage.is() )
712 {
713 Reference< XNameAccess > xNameAccess( m_xDefaultConfigStorage, UNO_QUERY_THROW );
714
715 // Try to access our module sub folder
716 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT;
717 i++ )
718 {
719 Reference< XStorage > xElementTypeStorage;
720 try
721 {
722 const OUString sName( OUString::createFromAscii( UIELEMENTTYPENAMES[i] ) );
723 if( xNameAccess->hasByName( sName ) )
724 xNameAccess->getByName( sName ) >>= xElementTypeStorage;
725 }
726 catch ( com::sun::star::container::NoSuchElementException& )
727 {
728 }
729
730 m_aUIElements[LAYER_DEFAULT][i].nElementType = i;
731 m_aUIElements[LAYER_DEFAULT][i].bModified = false;
732 m_aUIElements[LAYER_DEFAULT][i].xStorage = xElementTypeStorage;
733 m_aUIElements[LAYER_DEFAULT][i].bDefaultLayer = true;
734 }
735 }
736 }
737
ModuleUIConfigurationManager(com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> xServiceManager)738 ModuleUIConfigurationManager::ModuleUIConfigurationManager( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xServiceManager ) :
739 ThreadHelpBase( &Application::GetSolarMutex() )
740 , m_xDefaultConfigStorage( 0 )
741 , m_xUserConfigStorage( 0 )
742 , m_bReadOnly( true )
743 , m_bInitialized( false )
744 , m_bModified( false )
745 , m_bConfigRead( false )
746 , m_bDisposed( false )
747 , m_aXMLPostfix( RTL_CONSTASCII_USTRINGPARAM( ".xml" ))
748 , m_aPropUIName( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))
749 , m_aPropResourceURL( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" ))
750 , m_xServiceManager( xServiceManager )
751 , m_aListenerContainer( m_aLock.getShareableOslMutex() )
752 {
753 for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
754 m_pStorageHandler[i] = 0;
755
756 // Make sure we have a default initialized entry for every layer and user interface element type!
757 // The following code depends on this!
758 m_aUIElements[LAYER_DEFAULT].resize( ::com::sun::star::ui::UIElementType::COUNT );
759 m_aUIElements[LAYER_USERDEFINED].resize( ::com::sun::star::ui::UIElementType::COUNT );
760 }
761
~ModuleUIConfigurationManager()762 ModuleUIConfigurationManager::~ModuleUIConfigurationManager()
763 {
764 for ( int i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
765 delete m_pStorageHandler[i];
766 }
767
768 // XComponent
dispose()769 void SAL_CALL ModuleUIConfigurationManager::dispose() throw (::com::sun::star::uno::RuntimeException)
770 {
771 Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
772
773 css::lang::EventObject aEvent( xThis );
774 m_aListenerContainer.disposeAndClear( aEvent );
775
776 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
777 ResetableGuard aGuard( m_aLock );
778 Reference< XComponent > xModuleImageManager( m_xModuleImageManager );
779 m_xModuleImageManager.clear();
780 Reference< XComponent > xCompMAM( m_xModuleAcceleratorManager, UNO_QUERY );
781 if ( xCompMAM.is() )
782 xCompMAM->dispose();
783 m_xModuleAcceleratorManager.clear();
784 m_aUIElements[LAYER_USERDEFINED].clear();
785 m_aUIElements[LAYER_DEFAULT].clear();
786 m_xDefaultConfigStorage.clear();
787 m_xUserConfigStorage.clear();
788 m_xUserRootCommit.clear();
789 m_bConfigRead = false;
790 m_bModified = false;
791 m_bDisposed = true;
792 aGuard.unlock();
793 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
794
795 try
796 {
797 if ( xModuleImageManager.is() )
798 xModuleImageManager->dispose();
799 }
800 catch ( Exception& )
801 {
802 }
803 }
804
addEventListener(const Reference<XEventListener> & xListener)805 void SAL_CALL ModuleUIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
806 {
807 {
808 ResetableGuard aGuard( m_aLock );
809
810 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
811 if ( m_bDisposed )
812 throw DisposedException();
813 }
814
815 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
816 }
817
removeEventListener(const Reference<XEventListener> & xListener)818 void SAL_CALL ModuleUIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
819 {
820 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
821 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XEventListener >* ) NULL ), xListener );
822 }
823
824 // XInitialization
initialize(const Sequence<Any> & aArguments)825 void SAL_CALL ModuleUIConfigurationManager::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException )
826 {
827 ResetableGuard aLock( m_aLock );
828
829 if ( !m_bInitialized )
830 {
831 ::comphelper::SequenceAsHashMap lArgs(aArguments);
832 m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleIdentifier"), ::rtl::OUString());
833 m_aModuleShortName = lArgs.getUnpackedValueOrDefault(::rtl::OUString::createFromAscii("ModuleShortName"), ::rtl::OUString());
834
835 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
836 {
837 rtl::OUString aResourceType;
838 if ( i == ::com::sun::star::ui::UIElementType::MENUBAR )
839 aResourceType = PresetHandler::RESOURCETYPE_MENUBAR();
840 else if ( i == ::com::sun::star::ui::UIElementType::TOOLBAR )
841 aResourceType = PresetHandler::RESOURCETYPE_TOOLBAR();
842 else if ( i == ::com::sun::star::ui::UIElementType::STATUSBAR )
843 aResourceType = PresetHandler::RESOURCETYPE_STATUSBAR();
844
845 if ( aResourceType.getLength() > 0 )
846 {
847 m_pStorageHandler[i] = new PresetHandler( m_xServiceManager );
848 m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES,
849 aResourceType, // this path won't be used later ... see next lines!
850 m_aModuleShortName,
851 css::uno::Reference< css::embed::XStorage >()); // no document root used here!
852 }
853 }
854
855 // initialize root storages for all resource types
856 m_xUserRootCommit = css::uno::Reference< css::embed::XTransactedObject >(
857 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty
858 m_xDefaultConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageShare(
859 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageShare());
860 m_xUserConfigStorage = m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getParentStorageUser(
861 m_pStorageHandler[::com::sun::star::ui::UIElementType::MENUBAR]->getWorkingStorageUser());
862
863 if ( m_xUserConfigStorage.is() )
864 {
865 Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY );
866 if ( xPropSet.is() )
867 {
868 long nOpenMode = 0;
869 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" )));
870 if ( a >>= nOpenMode )
871 m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
872 }
873 }
874
875 impl_Initialize();
876
877 m_bInitialized = true;
878 }
879 }
880
881 // XUIConfiguration
addConfigurationListener(const Reference<::com::sun::star::ui::XUIConfigurationListener> & xListener)882 void SAL_CALL ModuleUIConfigurationManager::addConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
883 {
884 {
885 ResetableGuard aGuard( m_aLock );
886
887 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
888 if ( m_bDisposed )
889 throw DisposedException();
890 }
891
892 m_aListenerContainer.addInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener );
893 }
894
removeConfigurationListener(const Reference<::com::sun::star::ui::XUIConfigurationListener> & xListener)895 void SAL_CALL ModuleUIConfigurationManager::removeConfigurationListener( const Reference< ::com::sun::star::ui::XUIConfigurationListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
896 {
897 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
898 m_aListenerContainer.removeInterface( ::getCppuType( ( const Reference< XUIConfigurationListener >* ) NULL ), xListener );
899 }
900
901
902 // XUIConfigurationManager
reset()903 void SAL_CALL ModuleUIConfigurationManager::reset() throw (::com::sun::star::uno::RuntimeException)
904 {
905 ResetableGuard aGuard( m_aLock );
906
907 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
908 if ( m_bDisposed )
909 throw DisposedException();
910
911 bool bResetStorage( false );
912
913 if ( !isReadOnly() )
914 {
915 // Remove all elements from our user-defined storage!
916 try
917 {
918 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
919 {
920 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i];
921 Reference< XStorage > xSubStorage( rElementType.xStorage, UNO_QUERY );
922
923 if ( xSubStorage.is() )
924 {
925 bool bCommitSubStorage( false );
926 Reference< XNameAccess > xSubStorageNameAccess( xSubStorage, UNO_QUERY );
927 Sequence< OUString > aUIElementStreamNames = xSubStorageNameAccess->getElementNames();
928 for ( sal_Int32 j = 0; j < aUIElementStreamNames.getLength(); j++ )
929 {
930 xSubStorage->removeElement( aUIElementStreamNames[j] );
931 bCommitSubStorage = true;
932 }
933
934 if ( bCommitSubStorage )
935 {
936 Reference< XTransactedObject > xTransactedObject( xSubStorage, UNO_QUERY );
937 if ( xTransactedObject.is() )
938 xTransactedObject->commit();
939 m_pStorageHandler[i]->commitUserChanges();
940 }
941 }
942 }
943
944 bResetStorage = true;
945
946 // remove settings from user defined layer and notify listener about removed settings data!
947 ConfigEventNotifyContainer aRemoveEventNotifyContainer;
948 ConfigEventNotifyContainer aReplaceEventNotifyContainer;
949 for ( sal_Int16 j = 1; j < ::com::sun::star::ui::UIElementType::COUNT; j++ )
950 {
951 try
952 {
953 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][j];
954 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][j];
955
956 impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer );
957 rUserElementType.bModified = sal_False;
958 }
959 catch ( Exception& )
960 {
961 throw IOException();
962 }
963 }
964
965 m_bModified = sal_False;
966
967 // Unlock mutex before notify our listeners
968 aGuard.unlock();
969
970 // Notify our listeners
971 sal_uInt32 k = 0;
972 for ( k = 0; k < aRemoveEventNotifyContainer.size(); k++ )
973 implts_notifyContainerListener( aRemoveEventNotifyContainer[k], NotifyOp_Remove );
974 for ( k = 0; k < aReplaceEventNotifyContainer.size(); k++ )
975 implts_notifyContainerListener( aReplaceEventNotifyContainer[k], NotifyOp_Replace );
976 }
977 catch ( ::com::sun::star::lang::IllegalArgumentException& )
978 {
979 }
980 catch ( ::com::sun::star::container::NoSuchElementException& )
981 {
982 }
983 catch ( ::com::sun::star::embed::InvalidStorageException& )
984 {
985 }
986 catch ( ::com::sun::star::embed::StorageWrappedTargetException& )
987 {
988 }
989 }
990 }
991
getUIElementsInfo(sal_Int16 ElementType)992 Sequence< Sequence< PropertyValue > > SAL_CALL ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType )
993 throw ( IllegalArgumentException, RuntimeException )
994 {
995 if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
996 throw IllegalArgumentException();
997
998 ResetableGuard aGuard( m_aLock );
999 if ( m_bDisposed )
1000 throw DisposedException();
1001
1002 Sequence< Sequence< PropertyValue > > aElementInfoSeq;
1003 UIElementInfoHashMap aUIElementInfoCollection;
1004
1005 if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN )
1006 {
1007 for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1008 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) );
1009 }
1010 else
1011 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType );
1012
1013 Sequence< PropertyValue > aUIElementInfo( 2 );
1014 aUIElementInfo[0].Name = m_aPropResourceURL;
1015 aUIElementInfo[1].Name = m_aPropUIName;
1016
1017 aElementInfoSeq.realloc( aUIElementInfoCollection.size() );
1018 UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin();
1019
1020 sal_Int32 n = 0;
1021 while ( pIter != aUIElementInfoCollection.end() )
1022 {
1023 aUIElementInfo[0].Value <<= pIter->second.aResourceURL;
1024 aUIElementInfo[1].Value <<= pIter->second.aUIName;
1025 aElementInfoSeq[n++] = aUIElementInfo;
1026 ++pIter;
1027 }
1028
1029 return aElementInfoSeq;
1030 }
1031
createSettings()1032 Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings() throw (::com::sun::star::uno::RuntimeException)
1033 {
1034 ResetableGuard aGuard( m_aLock );
1035
1036 if ( m_bDisposed )
1037 throw DisposedException();
1038
1039 // Creates an empty item container which can be filled from outside
1040 return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
1041 }
1042
hasSettings(const::rtl::OUString & ResourceURL)1043 sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL )
1044 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1045 {
1046 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1047
1048 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1049 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1050 throw IllegalArgumentException();
1051 else
1052 {
1053 ResetableGuard aGuard( m_aLock );
1054
1055 if ( m_bDisposed )
1056 throw DisposedException();
1057
1058 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1059 if ( pDataSettings )
1060 return sal_True;
1061 }
1062
1063 return sal_False;
1064 }
1065
getSettings(const::rtl::OUString & ResourceURL,sal_Bool bWriteable)1066 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable )
1067 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1068 {
1069 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1070
1071 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1072 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1073 throw IllegalArgumentException();
1074 else
1075 {
1076 ResetableGuard aGuard( m_aLock );
1077
1078 if ( m_bDisposed )
1079 throw DisposedException();
1080
1081 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1082 if ( pDataSettings )
1083 {
1084 // Create a copy of our data if someone wants to change the data.
1085 if ( bWriteable )
1086 return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY );
1087 else
1088 return pDataSettings->xSettings;
1089 }
1090 }
1091
1092 throw NoSuchElementException();
1093 }
1094
replaceSettings(const::rtl::OUString & ResourceURL,const Reference<::com::sun::star::container::XIndexAccess> & aNewData)1095 void SAL_CALL ModuleUIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData )
1096 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException)
1097 {
1098 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1099
1100 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1101 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1102 throw IllegalArgumentException();
1103 else if ( m_bReadOnly )
1104 throw IllegalAccessException();
1105 else
1106 {
1107 ResetableGuard aGuard( m_aLock );
1108
1109 if ( m_bDisposed )
1110 throw DisposedException();
1111
1112 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1113 if ( pDataSettings )
1114 {
1115 if ( !pDataSettings->bDefaultNode )
1116 {
1117 // we have a settings entry in our user-defined layer - replace
1118 Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings;
1119
1120 // Create a copy of the data if the container is not const
1121 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1122 if ( xReplace.is() )
1123 pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1124 else
1125 pDataSettings->xSettings = aNewData;
1126 pDataSettings->bDefault = false;
1127 pDataSettings->bModified = true;
1128 m_bModified = true;
1129
1130 // Modify type container
1131 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1132 rElementType.bModified = true;
1133
1134 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1135
1136 // Create event to notify listener about replaced element settings
1137 ConfigurationEvent aEvent;
1138 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1139
1140 aEvent.ResourceURL = ResourceURL;
1141 aEvent.Accessor <<= xThis;
1142 aEvent.Source = xIfac;
1143 aEvent.ReplacedElement <<= xOldSettings;
1144 aEvent.Element <<= pDataSettings->xSettings;
1145
1146 aGuard.unlock();
1147
1148 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1149 }
1150 else
1151 {
1152 // we have no settings in our user-defined layer - insert
1153 UIElementData aUIElementData;
1154
1155 aUIElementData.bDefault = false;
1156 aUIElementData.bDefaultNode = false;
1157 aUIElementData.bModified = true;
1158
1159 // Create a copy of the data if the container is not const
1160 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1161 if ( xReplace.is() )
1162 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1163 else
1164 aUIElementData.xSettings = aNewData;
1165 aUIElementData.aName = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix;
1166 aUIElementData.aResourceURL = ResourceURL;
1167 m_bModified = true;
1168
1169 // Modify type container
1170 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1171 rElementType.bModified = true;
1172
1173 UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1174
1175 // Check our user element settings hash map as it can already contain settings that have been set to default!
1176 // If no node can be found, we have to insert it.
1177 UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL );
1178 if ( pIter != rElements.end() )
1179 pIter->second = aUIElementData;
1180 else
1181 rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData ));
1182
1183 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1184 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1185
1186 // Create event to notify listener about replaced element settings
1187 ConfigurationEvent aEvent;
1188
1189 aEvent.ResourceURL = ResourceURL;
1190 aEvent.Accessor <<= xThis;
1191 aEvent.Source = xIfac;
1192 aEvent.ReplacedElement <<= pDataSettings->xSettings;
1193 aEvent.Element <<= aUIElementData.xSettings;
1194
1195 aGuard.unlock();
1196
1197 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1198 }
1199 }
1200 else
1201 throw NoSuchElementException();
1202 }
1203 }
1204
removeSettings(const::rtl::OUString & ResourceURL)1205 void SAL_CALL ModuleUIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL )
1206 throw ( NoSuchElementException, IllegalArgumentException, IllegalAccessException, RuntimeException)
1207 {
1208 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1209
1210 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1211 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1212 throw IllegalArgumentException();
1213 else if ( m_bReadOnly )
1214 throw IllegalAccessException();
1215 else
1216 {
1217 ResetableGuard aGuard( m_aLock );
1218
1219 if ( m_bDisposed )
1220 throw DisposedException();
1221
1222 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1223 if ( pDataSettings )
1224 {
1225 // If element settings are default, we don't need to change anything!
1226 if ( pDataSettings->bDefault )
1227 return;
1228 else
1229 {
1230 Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings;
1231 pDataSettings->bDefault = true;
1232
1233 // check if this is a default layer node
1234 if ( !pDataSettings->bDefaultNode )
1235 pDataSettings->bModified = true; // we have to remove this node from the user layer!
1236 pDataSettings->xSettings.clear();
1237 m_bModified = true; // user layer must be written
1238
1239 // Modify type container
1240 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1241 rElementType.bModified = true;
1242
1243 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1244 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1245
1246 // Check if we have settings in the default layer which replaces the user-defined one!
1247 UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1248 if ( pDefaultDataSettings )
1249 {
1250 // Create event to notify listener about replaced element settings
1251 ConfigurationEvent aEvent;
1252
1253 aEvent.ResourceURL = ResourceURL;
1254 aEvent.Accessor <<= xThis;
1255 aEvent.Source = xIfac;
1256 aEvent.Element <<= xRemovedSettings;
1257 aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings;
1258
1259 aGuard.unlock();
1260
1261 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1262 }
1263 else
1264 {
1265 // Create event to notify listener about removed element settings
1266 ConfigurationEvent aEvent;
1267
1268 aEvent.ResourceURL = ResourceURL;
1269 aEvent.Accessor <<= xThis;
1270 aEvent.Source = xIfac;
1271 aEvent.Element <<= xRemovedSettings;
1272
1273 aGuard.unlock();
1274
1275 implts_notifyContainerListener( aEvent, NotifyOp_Remove );
1276 }
1277 }
1278 }
1279 else
1280 throw NoSuchElementException();
1281 }
1282 }
1283
insertSettings(const::rtl::OUString & NewResourceURL,const Reference<XIndexAccess> & aNewData)1284 void SAL_CALL ModuleUIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData )
1285 throw ( ElementExistException, IllegalArgumentException, IllegalAccessException, RuntimeException )
1286 {
1287 sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL );
1288
1289 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1290 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1291 throw IllegalArgumentException();
1292 else if ( m_bReadOnly )
1293 throw IllegalAccessException();
1294 else
1295 {
1296 ResetableGuard aGuard( m_aLock );
1297
1298 if ( m_bDisposed )
1299 throw DisposedException();
1300
1301 UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType );
1302 if ( !pDataSettings )
1303 {
1304 UIElementData aUIElementData;
1305
1306 aUIElementData.bDefault = false;
1307 aUIElementData.bDefaultNode = false;
1308 aUIElementData.bModified = true;
1309
1310 // Create a copy of the data if the container is not const
1311 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1312 if ( xReplace.is() )
1313 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1314 else
1315 aUIElementData.xSettings = aNewData;
1316 aUIElementData.aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix;
1317 aUIElementData.aResourceURL = NewResourceURL;
1318 m_bModified = true;
1319
1320 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1321 rElementType.bModified = true;
1322
1323 UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1324 rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData ));
1325
1326 Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings );
1327 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1328 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1329
1330 // Create event to notify listener about removed element settings
1331 ConfigurationEvent aEvent;
1332
1333 aEvent.ResourceURL = NewResourceURL;
1334 aEvent.Accessor <<= xThis;
1335 aEvent.Source = xIfac;
1336 aEvent.Element <<= xInsertSettings;
1337
1338 aGuard.unlock();
1339
1340 implts_notifyContainerListener( aEvent, NotifyOp_Insert );
1341 }
1342 else
1343 throw ElementExistException();
1344 }
1345 }
1346
getImageManager()1347 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager() throw (::com::sun::star::uno::RuntimeException)
1348 {
1349 ResetableGuard aGuard( m_aLock );
1350
1351 if ( m_bDisposed )
1352 throw DisposedException();
1353
1354 if ( !m_xModuleImageManager.is() )
1355 {
1356 m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )),
1357 UNO_QUERY );
1358 Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY );
1359
1360 Sequence< Any > aPropSeq( 3 );
1361 PropertyValue aPropValue;
1362 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" ));
1363 aPropValue.Value = makeAny( m_xUserConfigStorage );
1364 aPropSeq[0] = makeAny( aPropValue );
1365 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" ));
1366 aPropValue.Value = makeAny( m_aModuleIdentifier );
1367 aPropSeq[1] = makeAny( aPropValue );
1368 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" ));
1369 aPropValue.Value = makeAny( m_xUserRootCommit );
1370 aPropSeq[2] = makeAny( aPropValue );
1371
1372 xInit->initialize( aPropSeq );
1373 }
1374
1375 return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY );
1376 }
1377
getShortCutManager()1378 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getShortCutManager() throw (::com::sun::star::uno::RuntimeException)
1379 {
1380 ResetableGuard aGuard( m_aLock );
1381
1382 if ( m_bDisposed )
1383 throw DisposedException();
1384
1385 Reference< XMultiServiceFactory > xSMGR = m_xServiceManager;
1386 ::rtl::OUString aModule = m_aModuleIdentifier;
1387
1388 if ( !m_xModuleAcceleratorManager.is() )
1389 {
1390 Reference< XInterface > xManager = xSMGR->createInstance(SERVICENAME_MODULEACCELERATORCONFIGURATION);
1391 Reference< XInitialization > xInit (xManager, UNO_QUERY_THROW);
1392
1393 PropertyValue aProp;
1394 aProp.Name = ::rtl::OUString::createFromAscii("ModuleIdentifier");
1395 aProp.Value <<= aModule;
1396
1397 Sequence< Any > lArgs(1);
1398 lArgs[0] <<= aProp;
1399
1400 xInit->initialize(lArgs);
1401 m_xModuleAcceleratorManager = Reference< XInterface >( xManager, UNO_QUERY );
1402 }
1403
1404 return m_xModuleAcceleratorManager;
1405 }
1406
getEventsManager()1407 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager() throw (::com::sun::star::uno::RuntimeException)
1408 {
1409 return Reference< XInterface >();
1410 }
1411
1412 // XModuleUIConfigurationManager
isDefaultSettings(const::rtl::OUString & ResourceURL)1413 sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const ::rtl::OUString& ResourceURL )
1414 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1415 {
1416 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1417
1418 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1419 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1420 throw IllegalArgumentException();
1421 else
1422 {
1423 ResetableGuard aGuard( m_aLock );
1424
1425 if ( m_bDisposed )
1426 throw DisposedException();
1427
1428 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1429 if ( pDataSettings && pDataSettings->bDefaultNode )
1430 return sal_True;
1431 }
1432
1433 return sal_False;
1434 }
1435
getDefaultSettings(const::rtl::OUString & ResourceURL)1436 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const ::rtl::OUString& ResourceURL )
1437 throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
1438 {
1439 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1440
1441 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1442 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1443 throw IllegalArgumentException();
1444 else
1445 {
1446 ResetableGuard aGuard( m_aLock );
1447
1448 if ( m_bDisposed )
1449 throw DisposedException();
1450
1451 // preload list of element types on demand
1452 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
1453
1454 // Look into our default vector/hash_map combination
1455 UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
1456 UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL );
1457 if ( pIter != rDefaultHashMap.end() )
1458 {
1459 if ( !pIter->second.xSettings.is() )
1460 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
1461 return pIter->second.xSettings;
1462 }
1463 }
1464
1465 // Nothing has been found!
1466 throw NoSuchElementException();
1467 }
1468
1469 // XUIConfigurationPersistence
reload()1470 void SAL_CALL ModuleUIConfigurationManager::reload() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1471 {
1472 ResetableGuard aGuard( m_aLock );
1473
1474 if ( m_bDisposed )
1475 throw DisposedException();
1476
1477 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1478 {
1479 // Try to access our module sub folder
1480 ConfigEventNotifyContainer aRemoveNotifyContainer;
1481 ConfigEventNotifyContainer aReplaceNotifyContainer;
1482 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1483 {
1484 try
1485 {
1486 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][i];
1487 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i];
1488
1489 if ( rUserElementType.bModified )
1490 impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer );
1491 }
1492 catch ( Exception& )
1493 {
1494 throw IOException();
1495 }
1496 }
1497
1498 m_bModified = sal_False;
1499
1500 // Unlock mutex before notify our listeners
1501 aGuard.unlock();
1502
1503 // Notify our listeners
1504 for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ )
1505 implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove );
1506 for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ )
1507 implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace );
1508 }
1509 }
1510
store()1511 void SAL_CALL ModuleUIConfigurationManager::store() throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1512 {
1513 ResetableGuard aGuard( m_aLock );
1514
1515 if ( m_bDisposed )
1516 throw DisposedException();
1517
1518 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1519 {
1520 // Try to access our module sub folder
1521 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1522 {
1523 try
1524 {
1525 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1526 Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY );
1527
1528 if ( rElementType.bModified && xStorage.is() )
1529 {
1530 impl_storeElementTypeData( xStorage, rElementType );
1531 m_pStorageHandler[i]->commitUserChanges();
1532 }
1533 }
1534 catch ( Exception& )
1535 {
1536 throw IOException();
1537 }
1538 }
1539
1540 m_bModified = false;
1541 }
1542 }
1543
storeToStorage(const Reference<XStorage> & Storage)1544 void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1545 {
1546 ResetableGuard aGuard( m_aLock );
1547
1548 if ( m_bDisposed )
1549 throw DisposedException();
1550
1551 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1552 {
1553 // Try to access our module sub folder
1554 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1555 {
1556 try
1557 {
1558 Reference< XStorage > xElementTypeStorage( Storage->openStorageElement(
1559 OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE ));
1560 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1561
1562 if ( rElementType.bModified && xElementTypeStorage.is() )
1563 impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag!
1564 }
1565 catch ( Exception& )
1566 {
1567 throw IOException();
1568 }
1569 }
1570
1571 Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY );
1572 if ( xTransactedObject.is() )
1573 xTransactedObject->commit();
1574 }
1575 }
1576
isModified()1577 sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified() throw (::com::sun::star::uno::RuntimeException)
1578 {
1579 ResetableGuard aGuard( m_aLock );
1580
1581 return m_bModified;
1582 }
1583
isReadOnly()1584 sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly() throw (::com::sun::star::uno::RuntimeException)
1585 {
1586 ResetableGuard aGuard( m_aLock );
1587
1588 return m_bReadOnly;
1589 }
1590
implts_notifyContainerListener(const ConfigurationEvent & aEvent,NotifyOp eOp)1591 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
1592 {
1593 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) );
1594 if ( pContainer != NULL )
1595 {
1596 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1597 while ( pIterator.hasMoreElements() )
1598 {
1599 try
1600 {
1601 switch ( eOp )
1602 {
1603 case NotifyOp_Replace:
1604 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent );
1605 break;
1606 case NotifyOp_Insert:
1607 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent );
1608 break;
1609 case NotifyOp_Remove:
1610 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent );
1611 break;
1612 }
1613 }
1614 catch( css::uno::RuntimeException& )
1615 {
1616 pIterator.remove();
1617 }
1618 }
1619 }
1620 }
1621
1622 } // namespace framework
1623