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()
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 )
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 )
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 )
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 )
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 )
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()
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 {
994 if (( ElementType < 0 ) || ( ElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
995 throw IllegalArgumentException();
996
997 ResetableGuard aGuard( m_aLock );
998 if ( m_bDisposed )
999 throw DisposedException();
1000
1001 Sequence< Sequence< PropertyValue > > aElementInfoSeq;
1002 UIElementInfoHashMap aUIElementInfoCollection;
1003
1004 if ( ElementType == ::com::sun::star::ui::UIElementType::UNKNOWN )
1005 {
1006 for ( sal_Int16 i = 0; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1007 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, sal_Int16( i ) );
1008 }
1009 else
1010 impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType );
1011
1012 Sequence< PropertyValue > aUIElementInfo( 2 );
1013 aUIElementInfo[0].Name = m_aPropResourceURL;
1014 aUIElementInfo[1].Name = m_aPropUIName;
1015
1016 aElementInfoSeq.realloc( aUIElementInfoCollection.size() );
1017 UIElementInfoHashMap::const_iterator pIter = aUIElementInfoCollection.begin();
1018
1019 sal_Int32 n = 0;
1020 while ( pIter != aUIElementInfoCollection.end() )
1021 {
1022 aUIElementInfo[0].Value <<= pIter->second.aResourceURL;
1023 aUIElementInfo[1].Value <<= pIter->second.aUIName;
1024 aElementInfoSeq[n++] = aUIElementInfo;
1025 ++pIter;
1026 }
1027
1028 return aElementInfoSeq;
1029 }
1030
createSettings()1031 Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings()
1032 {
1033 ResetableGuard aGuard( m_aLock );
1034
1035 if ( m_bDisposed )
1036 throw DisposedException();
1037
1038 // Creates an empty item container which can be filled from outside
1039 return Reference< XIndexContainer >( static_cast< OWeakObject * >( new RootItemContainer() ), UNO_QUERY );
1040 }
1041
hasSettings(const::rtl::OUString & ResourceURL)1042 sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const ::rtl::OUString& ResourceURL )
1043 {
1044 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1045
1046 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1047 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1048 throw IllegalArgumentException();
1049 else
1050 {
1051 ResetableGuard aGuard( m_aLock );
1052
1053 if ( m_bDisposed )
1054 throw DisposedException();
1055
1056 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1057 if ( pDataSettings )
1058 return sal_True;
1059 }
1060
1061 return sal_False;
1062 }
1063
getSettings(const::rtl::OUString & ResourceURL,sal_Bool bWriteable)1064 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const ::rtl::OUString& ResourceURL, sal_Bool bWriteable )
1065 {
1066 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1067
1068 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1069 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1070 throw IllegalArgumentException();
1071 else
1072 {
1073 ResetableGuard aGuard( m_aLock );
1074
1075 if ( m_bDisposed )
1076 throw DisposedException();
1077
1078 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1079 if ( pDataSettings )
1080 {
1081 // Create a copy of our data if someone wants to change the data.
1082 if ( bWriteable )
1083 return Reference< XIndexAccess >( static_cast< OWeakObject * >( new RootItemContainer( pDataSettings->xSettings ) ), UNO_QUERY );
1084 else
1085 return pDataSettings->xSettings;
1086 }
1087 }
1088
1089 throw NoSuchElementException();
1090 }
1091
replaceSettings(const::rtl::OUString & ResourceURL,const Reference<::com::sun::star::container::XIndexAccess> & aNewData)1092 void SAL_CALL ModuleUIConfigurationManager::replaceSettings( const ::rtl::OUString& ResourceURL, const Reference< ::com::sun::star::container::XIndexAccess >& aNewData )
1093 {
1094 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1095
1096 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1097 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1098 throw IllegalArgumentException();
1099 else if ( m_bReadOnly )
1100 throw IllegalAccessException();
1101 else
1102 {
1103 ResetableGuard aGuard( m_aLock );
1104
1105 if ( m_bDisposed )
1106 throw DisposedException();
1107
1108 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1109 if ( pDataSettings )
1110 {
1111 if ( !pDataSettings->bDefaultNode )
1112 {
1113 // we have a settings entry in our user-defined layer - replace
1114 Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings;
1115
1116 // Create a copy of the data if the container is not const
1117 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1118 if ( xReplace.is() )
1119 pDataSettings->xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1120 else
1121 pDataSettings->xSettings = aNewData;
1122 pDataSettings->bDefault = false;
1123 pDataSettings->bModified = true;
1124 m_bModified = true;
1125
1126 // Modify type container
1127 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1128 rElementType.bModified = true;
1129
1130 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1131
1132 // Create event to notify listener about replaced element settings
1133 ConfigurationEvent aEvent;
1134 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1135
1136 aEvent.ResourceURL = ResourceURL;
1137 aEvent.Accessor <<= xThis;
1138 aEvent.Source = xIfac;
1139 aEvent.ReplacedElement <<= xOldSettings;
1140 aEvent.Element <<= pDataSettings->xSettings;
1141
1142 aGuard.unlock();
1143
1144 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1145 }
1146 else
1147 {
1148 // we have no settings in our user-defined layer - insert
1149 UIElementData aUIElementData;
1150
1151 aUIElementData.bDefault = false;
1152 aUIElementData.bDefaultNode = false;
1153 aUIElementData.bModified = true;
1154
1155 // Create a copy of the data if the container is not const
1156 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1157 if ( xReplace.is() )
1158 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1159 else
1160 aUIElementData.xSettings = aNewData;
1161 aUIElementData.aName = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix;
1162 aUIElementData.aResourceURL = ResourceURL;
1163 m_bModified = true;
1164
1165 // Modify type container
1166 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1167 rElementType.bModified = true;
1168
1169 UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1170
1171 // Check our user element settings hash map as it can already contain settings that have been set to default!
1172 // If no node can be found, we have to insert it.
1173 UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL );
1174 if ( pIter != rElements.end() )
1175 pIter->second = aUIElementData;
1176 else
1177 rElements.insert( UIElementDataHashMap::value_type( ResourceURL, aUIElementData ));
1178
1179 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1180 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1181
1182 // Create event to notify listener about replaced element settings
1183 ConfigurationEvent aEvent;
1184
1185 aEvent.ResourceURL = ResourceURL;
1186 aEvent.Accessor <<= xThis;
1187 aEvent.Source = xIfac;
1188 aEvent.ReplacedElement <<= pDataSettings->xSettings;
1189 aEvent.Element <<= aUIElementData.xSettings;
1190
1191 aGuard.unlock();
1192
1193 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1194 }
1195 }
1196 else
1197 throw NoSuchElementException();
1198 }
1199 }
1200
removeSettings(const::rtl::OUString & ResourceURL)1201 void SAL_CALL ModuleUIConfigurationManager::removeSettings( const ::rtl::OUString& ResourceURL )
1202 {
1203 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1204
1205 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1206 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1207 throw IllegalArgumentException();
1208 else if ( m_bReadOnly )
1209 throw IllegalAccessException();
1210 else
1211 {
1212 ResetableGuard aGuard( m_aLock );
1213
1214 if ( m_bDisposed )
1215 throw DisposedException();
1216
1217 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1218 if ( pDataSettings )
1219 {
1220 // If element settings are default, we don't need to change anything!
1221 if ( pDataSettings->bDefault )
1222 return;
1223 else
1224 {
1225 Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings;
1226 pDataSettings->bDefault = true;
1227
1228 // check if this is a default layer node
1229 if ( !pDataSettings->bDefaultNode )
1230 pDataSettings->bModified = true; // we have to remove this node from the user layer!
1231 pDataSettings->xSettings.clear();
1232 m_bModified = true; // user layer must be written
1233
1234 // Modify type container
1235 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1236 rElementType.bModified = true;
1237
1238 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1239 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1240
1241 // Check if we have settings in the default layer which replaces the user-defined one!
1242 UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1243 if ( pDefaultDataSettings )
1244 {
1245 // Create event to notify listener about replaced element settings
1246 ConfigurationEvent aEvent;
1247
1248 aEvent.ResourceURL = ResourceURL;
1249 aEvent.Accessor <<= xThis;
1250 aEvent.Source = xIfac;
1251 aEvent.Element <<= xRemovedSettings;
1252 aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings;
1253
1254 aGuard.unlock();
1255
1256 implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1257 }
1258 else
1259 {
1260 // Create event to notify listener about removed element settings
1261 ConfigurationEvent aEvent;
1262
1263 aEvent.ResourceURL = ResourceURL;
1264 aEvent.Accessor <<= xThis;
1265 aEvent.Source = xIfac;
1266 aEvent.Element <<= xRemovedSettings;
1267
1268 aGuard.unlock();
1269
1270 implts_notifyContainerListener( aEvent, NotifyOp_Remove );
1271 }
1272 }
1273 }
1274 else
1275 throw NoSuchElementException();
1276 }
1277 }
1278
insertSettings(const::rtl::OUString & NewResourceURL,const Reference<XIndexAccess> & aNewData)1279 void SAL_CALL ModuleUIConfigurationManager::insertSettings( const ::rtl::OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData )
1280 {
1281 sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL );
1282
1283 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1284 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1285 throw IllegalArgumentException();
1286 else if ( m_bReadOnly )
1287 throw IllegalAccessException();
1288 else
1289 {
1290 ResetableGuard aGuard( m_aLock );
1291
1292 if ( m_bDisposed )
1293 throw DisposedException();
1294
1295 UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType );
1296 if ( !pDataSettings )
1297 {
1298 UIElementData aUIElementData;
1299
1300 aUIElementData.bDefault = false;
1301 aUIElementData.bDefaultNode = false;
1302 aUIElementData.bModified = true;
1303
1304 // Create a copy of the data if the container is not const
1305 Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1306 if ( xReplace.is() )
1307 aUIElementData.xSettings = Reference< XIndexAccess >( static_cast< OWeakObject * >( new ConstItemContainer( aNewData ) ), UNO_QUERY );
1308 else
1309 aUIElementData.xSettings = aNewData;
1310 aUIElementData.aName = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix;
1311 aUIElementData.aResourceURL = NewResourceURL;
1312 m_bModified = true;
1313
1314 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1315 rElementType.bModified = true;
1316
1317 UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1318 rElements.insert( UIElementDataHashMap::value_type( NewResourceURL, aUIElementData ));
1319
1320 Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings );
1321 Reference< XUIConfigurationManager > xThis( static_cast< OWeakObject* >( this ), UNO_QUERY );
1322 Reference< XInterface > xIfac( xThis, UNO_QUERY );
1323
1324 // Create event to notify listener about removed element settings
1325 ConfigurationEvent aEvent;
1326
1327 aEvent.ResourceURL = NewResourceURL;
1328 aEvent.Accessor <<= xThis;
1329 aEvent.Source = xIfac;
1330 aEvent.Element <<= xInsertSettings;
1331
1332 aGuard.unlock();
1333
1334 implts_notifyContainerListener( aEvent, NotifyOp_Insert );
1335 }
1336 else
1337 throw ElementExistException();
1338 }
1339 }
1340
getImageManager()1341 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager()
1342 {
1343 ResetableGuard aGuard( m_aLock );
1344
1345 if ( m_bDisposed )
1346 throw DisposedException();
1347
1348 if ( !m_xModuleImageManager.is() )
1349 {
1350 m_xModuleImageManager = Reference< XComponent >( static_cast< cppu::OWeakObject *>( new ModuleImageManager( m_xServiceManager )),
1351 UNO_QUERY );
1352 Reference< XInitialization > xInit( m_xModuleImageManager, UNO_QUERY );
1353
1354 Sequence< Any > aPropSeq( 3 );
1355 PropertyValue aPropValue;
1356 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" ));
1357 aPropValue.Value = makeAny( m_xUserConfigStorage );
1358 aPropSeq[0] = makeAny( aPropValue );
1359 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleIdentifier" ));
1360 aPropValue.Value = makeAny( m_aModuleIdentifier );
1361 aPropSeq[1] = makeAny( aPropValue );
1362 aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserRootCommit" ));
1363 aPropValue.Value = makeAny( m_xUserRootCommit );
1364 aPropSeq[2] = makeAny( aPropValue );
1365
1366 xInit->initialize( aPropSeq );
1367 }
1368
1369 return Reference< XInterface >( m_xModuleImageManager, UNO_QUERY );
1370 }
1371
getShortCutManager()1372 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getShortCutManager()
1373 {
1374 ResetableGuard aGuard( m_aLock );
1375
1376 if ( m_bDisposed )
1377 throw DisposedException();
1378
1379 Reference< XMultiServiceFactory > xSMGR = m_xServiceManager;
1380 ::rtl::OUString aModule = m_aModuleIdentifier;
1381
1382 if ( !m_xModuleAcceleratorManager.is() )
1383 {
1384 Reference< XInterface > xManager = xSMGR->createInstance(SERVICENAME_MODULEACCELERATORCONFIGURATION);
1385 Reference< XInitialization > xInit (xManager, UNO_QUERY_THROW);
1386
1387 PropertyValue aProp;
1388 aProp.Name = ::rtl::OUString::createFromAscii("ModuleIdentifier");
1389 aProp.Value <<= aModule;
1390
1391 Sequence< Any > lArgs(1);
1392 lArgs[0] <<= aProp;
1393
1394 xInit->initialize(lArgs);
1395 m_xModuleAcceleratorManager = Reference< XInterface >( xManager, UNO_QUERY );
1396 }
1397
1398 return m_xModuleAcceleratorManager;
1399 }
1400
getEventsManager()1401 Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager()
1402 {
1403 return Reference< XInterface >();
1404 }
1405
1406 // XModuleUIConfigurationManager
isDefaultSettings(const::rtl::OUString & ResourceURL)1407 sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const ::rtl::OUString& ResourceURL )
1408 {
1409 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1410
1411 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1412 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1413 throw IllegalArgumentException();
1414 else
1415 {
1416 ResetableGuard aGuard( m_aLock );
1417
1418 if ( m_bDisposed )
1419 throw DisposedException();
1420
1421 UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1422 if ( pDataSettings && pDataSettings->bDefaultNode )
1423 return sal_True;
1424 }
1425
1426 return sal_False;
1427 }
1428
getDefaultSettings(const::rtl::OUString & ResourceURL)1429 Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const ::rtl::OUString& ResourceURL )
1430 {
1431 sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1432
1433 if (( nElementType == ::com::sun::star::ui::UIElementType::UNKNOWN ) ||
1434 ( nElementType >= ::com::sun::star::ui::UIElementType::COUNT ))
1435 throw IllegalArgumentException();
1436 else
1437 {
1438 ResetableGuard aGuard( m_aLock );
1439
1440 if ( m_bDisposed )
1441 throw DisposedException();
1442
1443 // preload list of element types on demand
1444 impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
1445
1446 // Look into our default vector/hash_map combination
1447 UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
1448 UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL );
1449 if ( pIter != rDefaultHashMap.end() )
1450 {
1451 if ( !pIter->second.xSettings.is() )
1452 impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
1453 return pIter->second.xSettings;
1454 }
1455 }
1456
1457 // Nothing has been found!
1458 throw NoSuchElementException();
1459 }
1460
1461 // XUIConfigurationPersistence
reload()1462 void SAL_CALL ModuleUIConfigurationManager::reload()
1463 {
1464 ResetableGuard aGuard( m_aLock );
1465
1466 if ( m_bDisposed )
1467 throw DisposedException();
1468
1469 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1470 {
1471 // Try to access our module sub folder
1472 ConfigEventNotifyContainer aRemoveNotifyContainer;
1473 ConfigEventNotifyContainer aReplaceNotifyContainer;
1474 for ( sal_Int16 i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1475 {
1476 try
1477 {
1478 UIElementType& rUserElementType = m_aUIElements[LAYER_USERDEFINED][i];
1479 UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i];
1480
1481 if ( rUserElementType.bModified )
1482 impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer );
1483 }
1484 catch ( Exception& )
1485 {
1486 throw IOException();
1487 }
1488 }
1489
1490 m_bModified = sal_False;
1491
1492 // Unlock mutex before notify our listeners
1493 aGuard.unlock();
1494
1495 // Notify our listeners
1496 for ( sal_uInt32 j = 0; j < aRemoveNotifyContainer.size(); j++ )
1497 implts_notifyContainerListener( aRemoveNotifyContainer[j], NotifyOp_Remove );
1498 for ( sal_uInt32 k = 0; k < aReplaceNotifyContainer.size(); k++ )
1499 implts_notifyContainerListener( aReplaceNotifyContainer[k], NotifyOp_Replace );
1500 }
1501 }
1502
store()1503 void SAL_CALL ModuleUIConfigurationManager::store()
1504 {
1505 ResetableGuard aGuard( m_aLock );
1506
1507 if ( m_bDisposed )
1508 throw DisposedException();
1509
1510 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1511 {
1512 // Try to access our module sub folder
1513 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1514 {
1515 try
1516 {
1517 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1518 Reference< XStorage > xStorage( rElementType.xStorage, UNO_QUERY );
1519
1520 if ( rElementType.bModified && xStorage.is() )
1521 {
1522 impl_storeElementTypeData( xStorage, rElementType );
1523 m_pStorageHandler[i]->commitUserChanges();
1524 }
1525 }
1526 catch ( Exception& )
1527 {
1528 throw IOException();
1529 }
1530 }
1531
1532 m_bModified = false;
1533 }
1534 }
1535
storeToStorage(const Reference<XStorage> & Storage)1536 void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage )
1537 {
1538 ResetableGuard aGuard( m_aLock );
1539
1540 if ( m_bDisposed )
1541 throw DisposedException();
1542
1543 if ( m_xUserConfigStorage.is() && m_bModified && !m_bReadOnly )
1544 {
1545 // Try to access our module sub folder
1546 for ( int i = 1; i < ::com::sun::star::ui::UIElementType::COUNT; i++ )
1547 {
1548 try
1549 {
1550 Reference< XStorage > xElementTypeStorage( Storage->openStorageElement(
1551 OUString::createFromAscii( UIELEMENTTYPENAMES[i] ), ElementModes::READWRITE ));
1552 UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1553
1554 if ( rElementType.bModified && xElementTypeStorage.is() )
1555 impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag!
1556 }
1557 catch ( Exception& )
1558 {
1559 throw IOException();
1560 }
1561 }
1562
1563 Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY );
1564 if ( xTransactedObject.is() )
1565 xTransactedObject->commit();
1566 }
1567 }
1568
isModified()1569 sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified()
1570 {
1571 ResetableGuard aGuard( m_aLock );
1572
1573 return m_bModified;
1574 }
1575
isReadOnly()1576 sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly()
1577 {
1578 ResetableGuard aGuard( m_aLock );
1579
1580 return m_bReadOnly;
1581 }
1582
implts_notifyContainerListener(const ConfigurationEvent & aEvent,NotifyOp eOp)1583 void ModuleUIConfigurationManager::implts_notifyContainerListener( const ConfigurationEvent& aEvent, NotifyOp eOp )
1584 {
1585 ::cppu::OInterfaceContainerHelper* pContainer = m_aListenerContainer.getContainer( ::getCppuType( ( const css::uno::Reference< ::com::sun::star::ui::XUIConfigurationListener >*) NULL ) );
1586 if ( pContainer != NULL )
1587 {
1588 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1589 while ( pIterator.hasMoreElements() )
1590 {
1591 try
1592 {
1593 switch ( eOp )
1594 {
1595 case NotifyOp_Replace:
1596 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementReplaced( aEvent );
1597 break;
1598 case NotifyOp_Insert:
1599 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementInserted( aEvent );
1600 break;
1601 case NotifyOp_Remove:
1602 ((::com::sun::star::ui::XUIConfigurationListener*)pIterator.next())->elementRemoved( aEvent );
1603 break;
1604 }
1605 }
1606 catch( css::uno::RuntimeException& )
1607 {
1608 pIterator.remove();
1609 }
1610 }
1611 }
1612 }
1613
1614 } // namespace framework
1615