xref: /AOO41X/main/framework/source/fwe/classes/addonsoptions.cxx (revision 711fced44833292f9bb8ce33bc20bc17437f6f7d)
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 
27 //_________________________________________________________________________________________________________________
28 //  includes
29 //_________________________________________________________________________________________________________________
30 #include <framework/addonsoptions.hxx>
31 #include <unotools/configmgr.hxx>
32 #include <unotools/configitem.hxx>
33 #include <unotools/ucbstreamhelper.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/stream.hxx>
36 #include <tools/color.hxx>
37 #include <com/sun/star/uno/Any.hxx>
38 #include <com/sun/star/uno/Sequence.hxx>
39 #include "com/sun/star/util/XMacroExpander.hpp"
40 #include "com/sun/star/uno/XComponentContext.hpp"
41 #include "com/sun/star/beans/XPropertySet.hpp"
42 #include <rtl/ustrbuf.hxx>
43 #include <rtl/uri.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <vcl/graph.hxx>
46 #include <svtools/filter.hxx>
47 
48 #include <hash_map>
49 #include <algorithm>
50 #include <vector>
51 
52 //_________________________________________________________________________________________________________________
53 //  namespaces
54 //_________________________________________________________________________________________________________________
55 
56 using namespace ::std                   ;
57 using namespace ::utl                   ;
58 using namespace ::osl                   ;
59 using namespace ::com::sun::star::uno   ;
60 using namespace ::com::sun::star::beans ;
61 using namespace ::com::sun::star::lang  ;
62 
63 //_________________________________________________________________________________________________________________
64 //  const
65 //_________________________________________________________________________________________________________________
66 
67 #define ROOTNODE_ADDONMENU                              ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Addons" ))
68 #define PATHDELIMITER                                   ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"             ))
69 #define TOOLBARITEMS                                    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ToolBarItems"      ))
70 #define SEPARATOR_URL_STR                               "private:separator"
71 #define SEPARATOR_URL_LEN                               17
72 #define SEPARATOR_URL                                   ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SEPARATOR_URL_STR ))
73 
74 #define PROPERTYNAME_URL                                ADDONSMENUITEM_PROPERTYNAME_URL
75 #define PROPERTYNAME_TITLE                              ADDONSMENUITEM_PROPERTYNAME_TITLE
76 #define PROPERTYNAME_TARGET                             ADDONSMENUITEM_PROPERTYNAME_TARGET
77 #define PROPERTYNAME_IMAGEIDENTIFIER                    ADDONSMENUITEM_PROPERTYNAME_IMAGEIDENTIFIER
78 #define PROPERTYNAME_CONTEXT                            ADDONSMENUITEM_PROPERTYNAME_CONTEXT
79 #define PROPERTYNAME_SUBMENU                            ADDONSMENUITEM_PROPERTYNAME_SUBMENU
80 #define PROPERTYNAME_CONTROLTYPE                        ADDONSMENUITEM_PROPERTYNAME_CONTROLTYPE
81 #define PROPERTYNAME_WIDTH                              ADDONSMENUITEM_PROPERTYNAME_WIDTH
82 
83 #define PROPERTYNAME_IMAGESMALL                         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmall" ))
84 #define PROPERTYNAME_IMAGEBIG                           ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBig" ))
85 #define PROPERTYNAME_IMAGESMALLHC                       ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallHC" ))
86 #define PROPERTYNAME_IMAGEBIGHC                         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigHC" ))
87 #define PROPERTYNAME_IMAGESMALL_URL                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallURL" ))
88 #define PROPERTYNAME_IMAGEBIG_URL                       ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigURL" ))
89 #define PROPERTYNAME_IMAGESMALLHC_URL                   ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallHCURL" ))
90 #define PROPERTYNAME_IMAGEBIGHC_URL                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigHCURL" ))
91 
92 #define IMAGES_NODENAME                                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UserDefinedImages" ))
93 #define PRIVATE_IMAGE_URL                               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:image/" ))
94 
95 #define PROPERTYNAME_MERGEMENU_MERGEPOINT               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergePoint" ))
96 #define PROPERTYNAME_MERGEMENU_MERGECOMMAND             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommand" ))
97 #define PROPERTYNAME_MERGEMENU_MERGECOMMANDPARAMETER    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommandParameter" ))
98 #define PROPERTYNAME_MERGEMENU_MERGEFALLBACK            ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeFallback" ))
99 #define PROPERTYNAME_MERGEMENU_MERGECONTEXT             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeContext" ))
100 #define PROPERTYNAME_MERGEMENU_MENUITEMS                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MenuItems" ))
101 #define MERGEMENU_MERGEPOINT_SEPARATOR                  '\\'
102 
103 #define PROPERTYNAME_MERGETOOLBAR_TOOLBAR               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeToolBar" ))
104 #define PROPERTYNAME_MERGETOOLBAR_MERGEPOINT            ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergePoint" ))
105 #define PROPERTYNAME_MERGETOOLBAR_MERGECOMMAND          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommand" ))
106 #define PROPERTYNAME_MERGETOOLBAR_MERGECOMMANDPARAMETER ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommandParameter" ))
107 #define PROPERTYNAME_MERGETOOLBAR_MERGEFALLBACK         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeFallback" ))
108 #define PROPERTYNAME_MERGETOOLBAR_MERGECONTEXT          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeContext" ))
109 #define PROPERTYNAME_MERGETOOLBAR_TOOLBARITEMS          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ToolBarItems" ))
110 
111 // The following order is mandatory. Please add properties at the end!
112 #define INDEX_URL             0
113 #define INDEX_TITLE           1
114 #define INDEX_IMAGEIDENTIFIER 2
115 #define INDEX_TARGET          3
116 #define INDEX_CONTEXT         4
117 #define INDEX_SUBMENU         5
118 #define INDEX_CONTROLTYPE     6
119 #define INDEX_WIDTH           7
120 #define PROPERTYCOUNT_INDEX   8
121 
122 // The following order is mandatory. Please add properties at the end!
123 #define PROPERTYCOUNT_MENUITEM                          6
124 #define OFFSET_MENUITEM_URL                             0
125 #define OFFSET_MENUITEM_TITLE                           1
126 #define OFFSET_MENUITEM_IMAGEIDENTIFIER                 2
127 #define OFFSET_MENUITEM_TARGET                          3
128 #define OFFSET_MENUITEM_CONTEXT                         4
129 #define OFFSET_MENUITEM_SUBMENU                         5
130 
131 // The following order is mandatory. Please add properties at the end!
132 #define PROPERTYCOUNT_POPUPMENU                         4
133 #define OFFSET_POPUPMENU_TITLE                          0
134 #define OFFSET_POPUPMENU_CONTEXT                        1
135 #define OFFSET_POPUPMENU_SUBMENU                        2
136 #define OFFSET_POPUPMENU_URL                            3   // Used for property set
137 
138 // The following order is mandatory. Please add properties at the end!
139 #define PROPERTYCOUNT_TOOLBARITEM                       7
140 #define OFFSET_TOOLBARITEM_URL                          0
141 #define OFFSET_TOOLBARITEM_TITLE                        1
142 #define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER              2
143 #define OFFSET_TOOLBARITEM_TARGET                       3
144 #define OFFSET_TOOLBARITEM_CONTEXT                      4
145 #define OFFSET_TOOLBARITEM_CONTROLTYPE                  5
146 #define OFFSET_TOOLBARITEM_WIDTH                        6
147 
148 // The following order is mandatory. Please add properties at the end!
149 #define PROPERTYCOUNT_IMAGES                            8
150 #define PROPERTYCOUNT_EMBEDDED_IMAGES                   4
151 #define OFFSET_IMAGES_SMALL                             0
152 #define OFFSET_IMAGES_BIG                               1
153 #define OFFSET_IMAGES_SMALLHC                           2
154 #define OFFSET_IMAGES_BIGHC                             3
155 #define OFFSET_IMAGES_SMALL_URL                         4
156 #define OFFSET_IMAGES_BIG_URL                           5
157 #define OFFSET_IMAGES_SMALLHC_URL                       6
158 #define OFFSET_IMAGES_BIGHC_URL                         7
159 
160 #define PROPERTYCOUNT_MERGE_MENUBAR                     6
161 #define OFFSET_MERGEMENU_MERGEPOINT                     0
162 #define OFFSET_MERGEMENU_MERGECOMMAND                   1
163 #define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER          2
164 #define OFFSET_MERGEMENU_MERGEFALLBACK                  3
165 #define OFFSET_MERGEMENU_MERGECONTEXT                   4
166 #define OFFSET_MERGEMENU_MENUITEMS                      5
167 
168 #define PROPERTYCOUNT_MERGE_TOOLBAR                     7
169 #define OFFSET_MERGETOOLBAR_TOOLBAR                     0
170 #define OFFSET_MERGETOOLBAR_MERGEPOINT                  1
171 #define OFFSET_MERGETOOLBAR_MERGECOMMAND                2
172 #define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER       3
173 #define OFFSET_MERGETOOLBAR_MERGEFALLBACK               4
174 #define OFFSET_MERGETOOLBAR_MERGECONTEXT                5
175 #define OFFSET_MERGETOOLBAR_TOOLBARITEMS                6
176 
177 #define EXPAND_PROTOCOL                                 "vnd.sun.star.expand:"
178 
179 const Size  aImageSizeSmall( 16, 16 );
180 const Size  aImageSizeBig( 26, 26 );
181 
182 //_________________________________________________________________________________________________________________
183 //  private declarations!
184 //_________________________________________________________________________________________________________________
185 
186 /*-****************************************************************************************************************
187     @descr  struct to hold information about one menu entry.
188 ****************************************************************************************************************-*/
189 
190 namespace framework
191 {
192 
193 class AddonsOptions_Impl : public ConfigItem
194 {
195     //-------------------------------------------------------------------------------------------------------------
196     //  public methods
197     //-------------------------------------------------------------------------------------------------------------
198 
199     public:
200         //---------------------------------------------------------------------------------------------------------
201         //  constructor / destructor
202         //---------------------------------------------------------------------------------------------------------
203 
204          AddonsOptions_Impl();
205         ~AddonsOptions_Impl();
206 
207         //---------------------------------------------------------------------------------------------------------
208         //  overloaded methods of baseclass
209         //---------------------------------------------------------------------------------------------------------
210 
211         /*-****************************************************************************************************//**
212             @short      called for notify of configmanager
213             @descr      These method is called from the ConfigManager before application ends or from the
214                         PropertyChangeListener if the sub tree broadcasts changes. You must update your
215                         internal values.
216 
217             @seealso    baseclass ConfigItem
218 
219             @param      "lPropertyNames" is the list of properties which should be updated.
220             @return     -
221 
222             @onerror    -
223         *//*-*****************************************************************************************************/
224 
225         virtual void Notify( const Sequence< ::rtl::OUString >& lPropertyNames );
226 
227         /*-****************************************************************************************************//**
228             @short      write changes to configuration
229             @descr      These method writes the changed values into the sub tree
230                         and should always called in our destructor to guarantee consistency of config data.
231 
232             @seealso    baseclass ConfigItem
233 
234             @param      -
235             @return     -
236 
237             @onerror    -
238         *//*-*****************************************************************************************************/
239 
240         virtual void Commit();
241 
242         //---------------------------------------------------------------------------------------------------------
243         //  public interface
244         //---------------------------------------------------------------------------------------------------------
245 
246         /*-****************************************************************************************************//**
247             @short      base implementation of public interface for "SvtDynamicMenuOptions"!
248             @descr      These class is used as static member of "SvtDynamicMenuOptions" ...
249                         => The code exist only for one time and isn't duplicated for every instance!
250 
251             @seealso    -
252 
253             @param      -
254             @return     -
255 
256             @onerror    -
257         *//*-*****************************************************************************************************/
258 
259         sal_Bool                                        HasAddonsMenu        () const ;
260         sal_Bool                                        HasAddonsHelpMenu    () const ;
261         sal_Int32                                       GetAddonsToolBarCount() const ;
262         const Sequence< Sequence< PropertyValue > >&    GetAddonsMenu        () const ;
263         const Sequence< Sequence< PropertyValue > >&    GetAddonsMenuBarPart () const ;
264         const Sequence< Sequence< PropertyValue > >&    GetAddonsToolBarPart ( sal_uInt32 nIndex ) const ;
265         const ::rtl::OUString                           GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
266         const Sequence< Sequence< PropertyValue > >&    GetAddonsHelpMenu    () const ;
267         Image                                           GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const;
268         const MergeMenuInstructionContainer&            GetMergeMenuInstructions() const;
269         bool                                            GetMergeToolbarInstructions( const ::rtl::OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const;
270 
271         void                                            ReadConfigurationData();
272 
273     //-------------------------------------------------------------------------------------------------------------
274     //  private methods
275     //-------------------------------------------------------------------------------------------------------------
276 
277     private:
278 
279         struct ImageEntry
280         {
281             Image   aImageSmall;
282             Image   aImageBig;
283             Image   aImageSmallHC;
284             Image   aImageBigHC;
285 
286             Image   aImageSmallNoScale;
287             Image   aImageBigNoScale;
288             Image   aImageSmallHCNoScale;
289             Image   aImageBigHCNoScale;
290         };
291 
292         typedef std::hash_map< ::rtl::OUString, ImageEntry, rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ImageManager;
293         typedef std::hash_map< ::rtl::OUString, sal_uInt32, rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > StringToIndexMap;
294         typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars;
295         typedef ::std::hash_map< ::rtl::OUString, MergeToolbarInstructionContainer, rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > ToolbarMergingInstructions;
296 
297         enum ImageSize
298         {
299             IMGSIZE_SMALL,
300             IMGSIZE_BIG
301         };
302 
303         /*-****************************************************************************************************//**
304             @short      return list of key names of our configuration management which represent oue module tree
305             @descr      These methods return the current list of key names! We need it to get needed values from our
306                         configuration management!
307 
308             @seealso    -
309 
310             @param      "nCount"     ,   returns count of menu entries for "new"
311             @return     A list of configuration key names is returned.
312 
313             @onerror    -
314         *//*-*****************************************************************************************************/
315 
316         sal_Bool             ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq );
317         sal_Bool             ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq );
318         sal_Bool             ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< rtl::OUString >& rAddonOfficeToolBarResNames );
319         sal_Bool             ReadToolBarItemSet( const rtl::OUString rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq );
320         sal_Bool             ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq );
321         sal_Bool             ReadImages( ImageManager& aImageManager );
322         sal_Bool             ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer );
323         sal_Bool             ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap );
324 
325         sal_Bool             ReadMergeMenuData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu );
326         sal_Bool             ReadMergeToolbarData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems );
327         sal_Bool             ReadMenuItem( const ::rtl::OUString& aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, sal_Bool bIgnoreSubMenu = sal_False );
328         sal_Bool             ReadPopupMenu( const ::rtl::OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu );
329         sal_Bool             AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu );
330         sal_Bool             ReadToolBarItem( const ::rtl::OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem );
331         sal_Bool             ReadImagesItem( const ::rtl::OUString& aImagesItemNodeName, Sequence< PropertyValue >& aImagesItem );
332         ImageEntry*          ReadImageData( const ::rtl::OUString& aImagesNodeName );
333         void                 ReadAndAssociateImages( const ::rtl::OUString& aURL, const ::rtl::OUString& aImageId );
334         void                 ReadImageFromURL( ImageSize nImageSize, const ::rtl::OUString& aURL, Image& aImage, Image& aNoScaleImage );
335         sal_Bool             HasAssociatedImages( const ::rtl::OUString& aURL );
336         void                 SubstituteVariables( ::rtl::OUString& aURL );
337 
338         sal_Bool             ReadSubMenuEntries( const Sequence< ::rtl::OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
339         void                 InsertToolBarSeparator( Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq );
340         ::rtl::OUString          GeneratePrefixURL();
341 
342         Sequence< ::rtl::OUString > GetPropertyNamesMergeMenuInstruction( const ::rtl::OUString& aPropertyRootName ) const;
343         Sequence< ::rtl::OUString > GetPropertyNamesMenuItem( const ::rtl::OUString& aPropertyRootNode ) const;
344         Sequence< ::rtl::OUString > GetPropertyNamesPopupMenu( const ::rtl::OUString& aPropertyRootNode ) const;
345         Sequence< ::rtl::OUString > GetPropertyNamesToolBarItem( const ::rtl::OUString& aPropertyRootNode ) const;
346         Sequence< ::rtl::OUString > GetPropertyNamesImages( const ::rtl::OUString& aPropertyRootNode ) const;
347         sal_Bool             CreateImageFromSequence( Image& rImage, sal_Bool bBig, Sequence< sal_Int8 >& rBitmapDataSeq ) const;
348 
349     //-------------------------------------------------------------------------------------------------------------
350     //  private member
351     //-------------------------------------------------------------------------------------------------------------
352 
353     private:
354         ImageEntry* ReadOptionalImageData( const ::rtl::OUString& aMenuNodeName );
355 
356         sal_Int32                                         m_nRootAddonPopupMenuId;
357         ::rtl::OUString                                          m_aPropNames[PROPERTYCOUNT_INDEX];
358         ::rtl::OUString                                          m_aPropImagesNames[PROPERTYCOUNT_IMAGES];
359         ::rtl::OUString                                          m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR];
360         ::rtl::OUString                                          m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR];
361         ::rtl::OUString                                          m_aEmpty;
362         ::rtl::OUString                                          m_aPathDelimiter;
363         ::rtl::OUString                                          m_aSeparator;
364         ::rtl::OUString                                          m_aRootAddonPopupMenuURLPrexfix;
365         ::rtl::OUString                                          m_aPrivateImageURL;
366         Sequence< Sequence< PropertyValue > >             m_aCachedMenuProperties;
367         Sequence< Sequence< PropertyValue > >             m_aCachedMenuBarPartProperties;
368         AddonToolBars                                     m_aCachedToolBarPartProperties;
369         std::vector< rtl::OUString >                      m_aCachedToolBarPartResourceNames;
370         Sequence< Sequence< PropertyValue > >             m_aCachedHelpMenuProperties;
371         Reference< com::sun::star::util::XMacroExpander > m_xMacroExpander;
372         ImageManager                                      m_aImageManager;
373         Sequence< Sequence< PropertyValue > >             m_aEmptyAddonToolBar;
374         MergeMenuInstructionContainer                     m_aCachedMergeMenuInsContainer;
375         ToolbarMergingInstructions                        m_aCachedToolbarMergingInstructions;
376 };
377 
378 //_________________________________________________________________________________________________________________
379 //  definitions
380 //_________________________________________________________________________________________________________________
381 
382 //*****************************************************************************************************************
383 //  constructor
384 //*****************************************************************************************************************
385 AddonsOptions_Impl::AddonsOptions_Impl()
386     // Init baseclasses first
387     : ConfigItem( ROOTNODE_ADDONMENU ),
388     m_nRootAddonPopupMenuId( 0 ),
389     m_aPathDelimiter( PATHDELIMITER ),
390     m_aSeparator( SEPARATOR_URL ),
391     m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX ),
392     m_aPrivateImageURL( PRIVATE_IMAGE_URL )
393 {
394     // initialize array with fixed property names
395     m_aPropNames[ INDEX_URL             ] = PROPERTYNAME_URL;
396     m_aPropNames[ INDEX_TITLE           ] = PROPERTYNAME_TITLE;
397     m_aPropNames[ INDEX_TARGET          ] = PROPERTYNAME_TARGET;
398     m_aPropNames[ INDEX_IMAGEIDENTIFIER ] = PROPERTYNAME_IMAGEIDENTIFIER;
399     m_aPropNames[ INDEX_CONTEXT         ] = PROPERTYNAME_CONTEXT;
400     m_aPropNames[ INDEX_SUBMENU         ] = PROPERTYNAME_SUBMENU; // Submenu set!
401     m_aPropNames[ INDEX_CONTROLTYPE     ] = PROPERTYNAME_CONTROLTYPE;
402     m_aPropNames[ INDEX_WIDTH           ] = PROPERTYNAME_WIDTH;
403 
404     // initialize array with fixed images property names
405     m_aPropImagesNames[ OFFSET_IMAGES_SMALL         ] = PROPERTYNAME_IMAGESMALL;
406     m_aPropImagesNames[ OFFSET_IMAGES_BIG           ] = PROPERTYNAME_IMAGEBIG;
407     m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC       ] = PROPERTYNAME_IMAGESMALLHC;
408     m_aPropImagesNames[ OFFSET_IMAGES_BIGHC         ] = PROPERTYNAME_IMAGEBIGHC;
409     m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL     ] = PROPERTYNAME_IMAGESMALL_URL;
410     m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL       ] = PROPERTYNAME_IMAGEBIG_URL;
411     m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL   ] = PROPERTYNAME_IMAGESMALLHC_URL;
412     m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL     ] = PROPERTYNAME_IMAGEBIGHC_URL;
413 
414     // initialize array with fixed merge menu property names
415     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT    ] = PROPERTYNAME_MERGEMENU_MERGEPOINT;
416     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND  ] = PROPERTYNAME_MERGEMENU_MERGECOMMAND;
417     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = PROPERTYNAME_MERGEMENU_MERGECOMMANDPARAMETER;
418     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = PROPERTYNAME_MERGEMENU_MERGEFALLBACK;
419     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT  ] = PROPERTYNAME_MERGEMENU_MERGECONTEXT;
420     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS     ] = PROPERTYNAME_MERGEMENU_MENUITEMS;
421 
422     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR               ] = PROPERTYNAME_MERGETOOLBAR_TOOLBAR;
423     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT            ] = PROPERTYNAME_MERGETOOLBAR_MERGEPOINT;
424     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND          ] = PROPERTYNAME_MERGETOOLBAR_MERGECOMMAND;
425     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = PROPERTYNAME_MERGETOOLBAR_MERGECOMMANDPARAMETER;
426     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK         ] = PROPERTYNAME_MERGETOOLBAR_MERGEFALLBACK;
427     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT          ] = PROPERTYNAME_MERGETOOLBAR_MERGECONTEXT;
428     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS          ] = PROPERTYNAME_MERGETOOLBAR_TOOLBARITEMS;
429 
430     Reference< XComponentContext > xContext;
431     Reference< com::sun::star::beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY );
432     xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
433     if ( xContext.is() )
434     {
435         m_xMacroExpander =  Reference< com::sun::star::util::XMacroExpander >( xContext->getValueByName(
436                                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))),
437                                 UNO_QUERY );
438     }
439 
440     ReadConfigurationData();
441 
442     // Enable notification mechanism of ouer baseclass.
443     // We need it to get information about changes outside these class on ouer used configuration keys!
444     Sequence< rtl::OUString > aNotifySeq( 1 );
445     aNotifySeq[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AddonUI" ));
446     EnableNotification( aNotifySeq );
447 }
448 
449 //*****************************************************************************************************************
450 //  destructor
451 //*****************************************************************************************************************
452 AddonsOptions_Impl::~AddonsOptions_Impl()
453 {
454     // We must save our current values .. if user forget it!
455     if( IsModified() == sal_True )
456     {
457         Commit();
458     }
459 }
460 
461 void AddonsOptions_Impl::ReadConfigurationData()
462 {
463     // reset members to be read again from configuration
464     m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >();
465     m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >();
466     m_aCachedToolBarPartProperties = AddonToolBars();
467     m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
468     m_aCachedToolBarPartResourceNames.clear();
469     m_aImageManager = ImageManager();
470 
471     ReadAddonMenuSet( m_aCachedMenuProperties );
472     ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
473     ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
474     ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
475     ReadImages( m_aImageManager );
476 
477     m_aCachedMergeMenuInsContainer.clear();
478     m_aCachedToolbarMergingInstructions.clear();
479 
480     ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
481     ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
482 }
483 
484 //*****************************************************************************************************************
485 //  public method
486 //*****************************************************************************************************************
487 void AddonsOptions_Impl::Notify( const Sequence< ::rtl::OUString >& /*lPropertyNames*/ )
488 {
489     Application::PostUserEvent( STATIC_LINK( 0, AddonsOptions, Notify ) );
490 }
491 
492 //*****************************************************************************************************************
493 //  public method
494 //*****************************************************************************************************************
495 void AddonsOptions_Impl::Commit()
496 {
497     DBG_ERROR( "AddonsOptions_Impl::Commit()\nNot implemented yet!\n" );
498 }
499 
500 //*****************************************************************************************************************
501 //  public method
502 //*****************************************************************************************************************
503 sal_Bool AddonsOptions_Impl::HasAddonsMenu() const
504 {
505     return ( m_aCachedMenuProperties.getLength() > 0 );
506 }
507 
508 //*****************************************************************************************************************
509 //  public method
510 //*****************************************************************************************************************
511 sal_Bool AddonsOptions_Impl::HasAddonsHelpMenu  () const
512 {
513     return ( m_aCachedHelpMenuProperties.getLength() > 0 );
514 }
515 
516 //*****************************************************************************************************************
517 //  public method
518 //*****************************************************************************************************************
519 sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
520 {
521     return m_aCachedToolBarPartProperties.size();
522 }
523 
524 //*****************************************************************************************************************
525 //  public method
526 //*****************************************************************************************************************
527 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsMenu() const
528 {
529     return m_aCachedMenuProperties;
530 }
531 
532 //*****************************************************************************************************************
533 //  public method
534 //*****************************************************************************************************************
535 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsMenuBarPart() const
536 {
537     return m_aCachedMenuBarPartProperties;
538 }
539 
540 //*****************************************************************************************************************
541 //  public method
542 //*****************************************************************************************************************
543 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
544 {
545     if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() )
546         return m_aCachedToolBarPartProperties[nIndex];
547     else
548         return m_aEmptyAddonToolBar;
549 }
550 
551 //*****************************************************************************************************************
552 //  public method
553 //*****************************************************************************************************************
554 const ::rtl::OUString AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
555 {
556     if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
557         return m_aCachedToolBarPartResourceNames[nIndex];
558     else
559         return rtl::OUString();
560 }
561 
562 //*****************************************************************************************************************
563 //  public method
564 //*****************************************************************************************************************
565 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsHelpMenu  () const
566 {
567     return m_aCachedHelpMenuProperties;
568 }
569 
570 //*****************************************************************************************************************
571 //  public method
572 //*****************************************************************************************************************
573 const MergeMenuInstructionContainer& AddonsOptions_Impl::GetMergeMenuInstructions() const
574 {
575     return m_aCachedMergeMenuInsContainer;
576 }
577 
578 //*****************************************************************************************************************
579 //  public method
580 //*****************************************************************************************************************
581 bool AddonsOptions_Impl::GetMergeToolbarInstructions(
582     const ::rtl::OUString& rToolbarName,
583     MergeToolbarInstructionContainer& rToolbarInstructions ) const
584 {
585     ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName );
586     if ( pIter != m_aCachedToolbarMergingInstructions.end() )
587     {
588         rToolbarInstructions = pIter->second;
589         return true;
590     }
591     else
592         return false;
593 }
594 
595 //*****************************************************************************************************************
596 //  public method
597 //*****************************************************************************************************************
598 Image AddonsOptions_Impl::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const
599 {
600     Image aImage;
601 
602     ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
603     if ( pIter != m_aImageManager.end() )
604     {
605         if ( !bHiContrast  )
606         {
607             if ( bNoScale )
608                 aImage = ( bBig ? pIter->second.aImageBigNoScale : pIter->second.aImageSmallNoScale );
609             if ( !aImage )
610                 aImage = ( bBig ? pIter->second.aImageBig : pIter->second.aImageSmall );
611         }
612         else
613         {
614             if ( bNoScale )
615                 aImage = ( bBig ? pIter->second.aImageBigHCNoScale : pIter->second.aImageSmallHCNoScale );
616             if ( !aImage )
617                 aImage = ( bBig ? pIter->second.aImageBigHC : pIter->second.aImageSmallHC );
618         }
619     }
620 
621     return aImage;
622 }
623 
624 //*****************************************************************************************************************
625 //  private method
626 //*****************************************************************************************************************
627 sal_Bool AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
628 {
629     // Read the AddonMenu set and fill property sequences
630     ::rtl::OUString             aAddonMenuNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/AddonMenu" ));
631     Sequence< ::rtl::OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
632     ::rtl::OUString             aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter );
633 
634     sal_uInt32              nCount = aAddonMenuNodeSeq.getLength();
635     sal_uInt32              nIndex = 0;
636     Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
637 
638     // Init the property value sequence
639     aMenuItem[ OFFSET_MENUITEM_URL              ].Name = m_aPropNames[ INDEX_URL            ];
640     aMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = m_aPropNames[ INDEX_TITLE          ];
641     aMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = m_aPropNames[ INDEX_TARGET         ];
642     aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
643     aMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = m_aPropNames[ INDEX_CONTEXT        ];
644     aMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = m_aPropNames[ INDEX_SUBMENU        ];  // Submenu set!
645 
646     for ( sal_uInt32 n = 0; n < nCount; n++ )
647     {
648         ::rtl::OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] );
649 
650         // Read the MenuItem
651         if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) )
652         {
653             // Successfully read a menu item, append to our list
654             sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1;
655             rAddonMenuSeq.realloc( nMenuItemCount );
656             rAddonMenuSeq[nIndex++] = aMenuItem;
657         }
658     }
659 
660     return ( rAddonMenuSeq.getLength() > 0 );
661 }
662 
663 //*****************************************************************************************************************
664 //  private method
665 //*****************************************************************************************************************
666 sal_Bool AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
667 {
668     // Read the AddonMenu set and fill property sequences
669     ::rtl::OUString             aAddonHelpMenuNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeHelp" ));
670     Sequence< ::rtl::OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
671     ::rtl::OUString             aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter );
672 
673     sal_uInt32              nCount = aAddonHelpMenuNodeSeq.getLength();
674     sal_uInt32              nIndex = 0;
675     Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
676 
677     // Init the property value sequence
678     aMenuItem[ OFFSET_MENUITEM_URL              ].Name = m_aPropNames[ INDEX_URL            ];
679     aMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = m_aPropNames[ INDEX_TITLE          ];
680     aMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = m_aPropNames[ INDEX_TARGET         ];
681     aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
682     aMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = m_aPropNames[ INDEX_CONTEXT        ];
683     aMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = m_aPropNames[ INDEX_SUBMENU        ];  // Submenu set!
684 
685     for ( sal_uInt32 n = 0; n < nCount; n++ )
686     {
687         ::rtl::OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );
688 
689         // Read the MenuItem
690         if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, sal_True ) )
691         {
692             // Successfully read a menu item, append to our list
693             sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
694             rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
695             rAddonOfficeHelpMenuSeq[nIndex++] = aMenuItem;
696         }
697     }
698 
699     return ( rAddonOfficeHelpMenuSeq.getLength() > 0 );
700 }
701 
702 //*****************************************************************************************************************
703 //  private method
704 //*****************************************************************************************************************
705 sal_Bool AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
706 {
707     // Read the OfficeMenuBar set and fill property sequences
708     ::rtl::OUString             aAddonMenuBarNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeMenuBar" ));
709     Sequence< ::rtl::OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
710     ::rtl::OUString             aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter );
711 
712     sal_uInt32              nCount = aAddonMenuBarNodeSeq.getLength();
713     sal_uInt32              nIndex = 0;
714     Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU );
715 
716     // Init the property value sequence
717     aPopupMenu[ OFFSET_POPUPMENU_TITLE      ].Name = m_aPropNames[ INDEX_TITLE  ];
718     aPopupMenu[ OFFSET_POPUPMENU_CONTEXT    ].Name = m_aPropNames[ INDEX_CONTEXT];
719     aPopupMenu[ OFFSET_POPUPMENU_SUBMENU    ].Name = m_aPropNames[ INDEX_SUBMENU];
720     aPopupMenu[ OFFSET_POPUPMENU_URL        ].Name = m_aPropNames[ INDEX_URL    ];
721 
722     StringToIndexMap aTitleToIndexMap;
723 
724     for ( sal_uInt32 n = 0; n < nCount; n++ )
725     {
726         ::rtl::OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );
727 
728         // Read the MenuItem
729         if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
730         {
731             // Successfully read a popup menu, append to our list
732             ::rtl::OUString aPopupTitle;
733             if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle )
734             {
735                 StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle );
736                 if ( pIter != aTitleToIndexMap.end() )
737                 {
738                     // title already there => concat both popup menus
739                     Sequence< PropertyValue >& rOldPopupMenu = rAddonOfficeMenuBarSeq[pIter->second];
740                     AppendPopupMenu( rOldPopupMenu, aPopupMenu );
741                 }
742                 else
743                 {
744                     // not found
745                     sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1;
746                     rAddonOfficeMenuBarSeq.realloc( nMenuItemCount );
747                     rAddonOfficeMenuBarSeq[nIndex] = aPopupMenu;
748                     aTitleToIndexMap.insert( StringToIndexMap::value_type( aPopupTitle, nIndex ));
749                     ++nIndex;
750                 }
751             }
752         }
753     }
754 
755     return ( rAddonOfficeMenuBarSeq.getLength() > 0 );
756 }
757 
758 //*****************************************************************************************************************
759 //  private method
760 //*****************************************************************************************************************
761 sal_Bool AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< rtl::OUString >& rAddonOfficeToolBarResNames )
762 {
763     // Read the OfficeToolBar set and fill property sequences
764     ::rtl::OUString             aAddonToolBarNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeToolBar" ));
765     Sequence< ::rtl::OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
766     ::rtl::OUString             aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );
767 
768     sal_uInt32           nCount = aAddonToolBarNodeSeq.getLength();
769 
770     for ( sal_uInt32 n = 0; n < nCount; n++ )
771     {
772         ::rtl::OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
773         rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
774         rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
775         ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
776     }
777 
778     return ( !rAddonOfficeToolBars.empty() );
779 }
780 
781 
782 //*****************************************************************************************************************
783 //  private method
784 //*****************************************************************************************************************
785 sal_Bool AddonsOptions_Impl::ReadToolBarItemSet( const rtl::OUString rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
786 {
787     sal_Bool                    bInsertSeparator        = sal_False;
788     sal_uInt32                  nToolBarItemCount       = rAddonOfficeToolBarSeq.getLength();
789     ::rtl::OUString                 aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
790     Sequence< ::rtl::OUString >     aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName );
791     Sequence< PropertyValue >   aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
792 
793     // Init the property value sequence
794     aToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Name = m_aPropNames[ INDEX_URL            ];
795     aToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Name = m_aPropNames[ INDEX_TITLE          ];
796     aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
797     aToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Name = m_aPropNames[ INDEX_TARGET         ];
798     aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Name = m_aPropNames[ INDEX_CONTEXT        ];
799     aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Name = m_aPropNames[ INDEX_CONTROLTYPE    ];
800     aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Name = m_aPropNames[ INDEX_WIDTH          ];
801 
802     sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength();
803     for ( sal_uInt32 n = 0; n < nCount; n++ )
804     {
805         ::rtl::OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );
806 
807         // Read the ToolBarItem
808         if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
809         {
810             if ( bInsertSeparator )
811             {
812                 bInsertSeparator = sal_False;
813                 InsertToolBarSeparator( rAddonOfficeToolBarSeq );
814             }
815 
816             // Successfully read a toolbar item, append to our list
817             sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
818             rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
819             rAddonOfficeToolBarSeq[nAddonCount] = aToolBarItem;
820         }
821     }
822 
823     return ( (sal_uInt32)rAddonOfficeToolBarSeq.getLength() > nToolBarItemCount );
824 }
825 
826 //*****************************************************************************************************************
827 //  private method
828 //*****************************************************************************************************************
829 void AddonsOptions_Impl::InsertToolBarSeparator( Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
830 {
831     Sequence< PropertyValue >   aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
832 
833     aToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Name = m_aPropNames[ INDEX_URL            ];
834     aToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Name = m_aPropNames[ INDEX_TITLE          ];
835     aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
836     aToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Name = m_aPropNames[ INDEX_TARGET         ];
837     aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Name = m_aPropNames[ INDEX_CONTEXT        ];
838 
839     aToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Value <<= SEPARATOR_URL;
840     aToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Value <<= m_aEmpty;
841     aToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Value <<= m_aEmpty;
842     aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Value <<= m_aEmpty;
843     aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Value <<= m_aEmpty;
844 
845     sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength();
846     rAddonOfficeToolBarSeq.realloc( nToolBarItemCount+1 );
847     rAddonOfficeToolBarSeq[nToolBarItemCount] = aToolBarItem;
848 }
849 
850 //*****************************************************************************************************************
851 //  private method
852 //*****************************************************************************************************************
853 sal_Bool AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
854 {
855     // Read the user-defined Images set and fill image manager
856     ::rtl::OUString                aAddonImagesNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/Images" ));
857     Sequence< ::rtl::OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
858     ::rtl::OUString                aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );
859 
860     sal_uInt32              nCount = aAddonImagesNodeSeq.getLength();
861 
862     // Init the property value sequence
863     Sequence< ::rtl::OUString > aAddonImageItemNodePropNames( 1 );
864     ::rtl::OUString                aURL;
865 
866     for ( sal_uInt32 n = 0; n < nCount; n++ )
867     {
868         ::rtl::OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );
869 
870         // Create sequence for data access
871         ::rtl::OUStringBuffer aBuffer( aImagesItemNode );
872         aBuffer.append( m_aPathDelimiter );
873         aBuffer.append( m_aPropNames[ OFFSET_MENUITEM_URL ] );
874         aAddonImageItemNodePropNames[0] = aBuffer.makeStringAndClear();
875 
876         Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );
877 
878         // An user-defined image entry must have an URL. As "ImageIdentifier" has a higher priority
879         // we also check if we already have an images association.
880         if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
881             aURL.getLength() > 0 &&
882             !HasAssociatedImages( aURL ))
883         {
884             ::rtl::OUStringBuffer aBuf( aImagesItemNode );
885             aBuf.append( m_aPathDelimiter );
886             aBuf.append( IMAGES_NODENAME );
887             aBuf.append( m_aPathDelimiter );
888             ::rtl::OUString aImagesUserDefinedItemNode = aBuf.makeStringAndClear();
889 
890             // Read a user-defined images data
891             ImageEntry* pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
892             if ( pImageEntry )
893             {
894                 // Successfully read a user-defined images item, put it into our image manager
895                 aImageManager.insert( ImageManager::value_type( aURL, *pImageEntry ));
896                 delete pImageEntry; // We have the ownership of the pointer
897             }
898         }
899     }
900 
901     return sal_True;
902 }
903 
904 //*****************************************************************************************************************
905 //  private method
906 //*****************************************************************************************************************
907 
908 ::rtl::OUString AddonsOptions_Impl::GeneratePrefixURL()
909 {
910     // Create an unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu.
911     // They use a different image manager, so they must be identified by the sfx2/framework code.
912     ::rtl::OUString aPopupMenuURL;
913     ::rtl::OUStringBuffer aBuf( m_aRootAddonPopupMenuURLPrexfix.getLength() + 3 );
914     aBuf.append( m_aRootAddonPopupMenuURLPrexfix );
915     aBuf.append( ::rtl::OUString::valueOf( ++m_nRootAddonPopupMenuId ));
916     aPopupMenuURL = aBuf.makeStringAndClear();
917     return aPopupMenuURL;
918 }
919 
920 //*****************************************************************************************************************
921 //  private method
922 //*****************************************************************************************************************
923 
924 sal_Bool AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer )
925 {
926     const ::rtl::OUString aMenuMergeRootName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeMenuBarMerging/" ));
927 
928     Sequence< ::rtl::OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );
929     ::rtl::OUString                aAddonMergeNode( aMenuMergeRootName );
930 
931     sal_uInt32              nCount = aAddonMergeNodesSeq.getLength();
932 
933     // Init the property value sequence
934     Sequence< ::rtl::OUString > aNodePropNames( 5 );
935     ::rtl::OUString                aURL;
936 
937     for ( sal_uInt32 i = 0; i < nCount; i++ )
938     {
939         ::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
940 
941         Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
942         sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();
943 
944         for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
945         {
946             ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
947             aMergeAddonInstructionBase.append( m_aPathDelimiter );
948             aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
949             aMergeAddonInstructionBase.append( m_aPathDelimiter );
950 
951             // Create sequence for data access
952             ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
953             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] );
954             aNodePropNames[0] = aBuffer.makeStringAndClear();
955 
956             aBuffer = aMergeAddonInstructionBase;
957             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] );
958             aNodePropNames[1] = aBuffer.makeStringAndClear();
959 
960             aBuffer = aMergeAddonInstructionBase;
961             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] );
962             aNodePropNames[2] = aBuffer.makeStringAndClear();
963 
964             aBuffer = aMergeAddonInstructionBase;
965             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] );
966             aNodePropNames[3] = aBuffer.makeStringAndClear();
967 
968             aBuffer = aMergeAddonInstructionBase;
969             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] );
970             aNodePropNames[4] = aBuffer.makeStringAndClear();
971 
972             Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
973 
974             MergeMenuInstruction aMergeMenuInstruction;
975             aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint;
976             aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand;
977             aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter;
978             aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback;
979             aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext;
980 
981             ::rtl::OUString aMergeMenuBase = aMergeAddonInstructionBase.makeStringAndClear();
982             ReadMergeMenuData( aMergeMenuBase, aMergeMenuInstruction.aMergeMenu );
983 
984             aContainer.push_back( aMergeMenuInstruction );
985         }
986     }
987 
988     return sal_True;
989 }
990 
991 //*****************************************************************************************************************
992 //  private method
993 //*****************************************************************************************************************
994 sal_Bool AddonsOptions_Impl::ReadMergeMenuData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
995 {
996     ::rtl::OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );
997 
998     Sequence< ::rtl::OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
999     aMergeMenuBaseNode += m_aPathDelimiter;
1000 
1001     // extend the node names to have full path strings
1002     for ( sal_uInt32 i = 0; i < (sal_uInt32)aSubMenuNodeNames.getLength(); i++ )
1003         aSubMenuNodeNames[i] = ::rtl::OUString( aMergeMenuBaseNode + aSubMenuNodeNames[i] );
1004 
1005     return ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
1006 }
1007 
1008 //*****************************************************************************************************************
1009 //  private method
1010 //*****************************************************************************************************************
1011 sal_Bool AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions )
1012 {
1013     const ::rtl::OUString aToolbarMergeRootName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeToolbarMerging/" ));
1014 
1015     Sequence< ::rtl::OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
1016     ::rtl::OUString                aAddonMergeNode( aToolbarMergeRootName );
1017 
1018     sal_uInt32              nCount = aAddonMergeNodesSeq.getLength();
1019 
1020     // Init the property value sequence
1021     Sequence< ::rtl::OUString > aNodePropNames( 6 );
1022     ::rtl::OUString                aURL;
1023 
1024     for ( sal_uInt32 i = 0; i < nCount; i++ )
1025     {
1026         ::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
1027 
1028         Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
1029         sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();
1030 
1031         for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
1032         {
1033             ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
1034             aMergeAddonInstructionBase.append( m_aPathDelimiter );
1035             aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
1036             aMergeAddonInstructionBase.append( m_aPathDelimiter );
1037 
1038             // Create sequence for data access
1039             ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
1040             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] );
1041             aNodePropNames[0] = aBuffer.makeStringAndClear();
1042 
1043             aBuffer = aMergeAddonInstructionBase;
1044             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] );
1045             aNodePropNames[1] = aBuffer.makeStringAndClear();
1046 
1047             aBuffer = aMergeAddonInstructionBase;
1048             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] );
1049             aNodePropNames[2] = aBuffer.makeStringAndClear();
1050 
1051             aBuffer = aMergeAddonInstructionBase;
1052             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] );
1053             aNodePropNames[3] = aBuffer.makeStringAndClear();
1054 
1055             aBuffer = aMergeAddonInstructionBase;
1056             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] );
1057             aNodePropNames[4] = aBuffer.makeStringAndClear();
1058 
1059             aBuffer = aMergeAddonInstructionBase;
1060             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] );
1061             aNodePropNames[5] = aBuffer.makeStringAndClear();
1062 
1063             Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
1064 
1065             MergeToolbarInstruction aMergeToolbarInstruction;
1066             aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar;
1067             aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint;
1068             aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand;
1069             aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter;
1070             aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback;
1071             aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext;
1072 
1073             ReadMergeToolbarData( aMergeAddonInstructionBase.makeStringAndClear(),
1074                                   aMergeToolbarInstruction.aMergeToolbarItems );
1075 
1076             MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ];
1077             rVector.push_back( aMergeToolbarInstruction );
1078         }
1079     }
1080 
1081     return sal_True;
1082 }
1083 
1084 //*****************************************************************************************************************
1085 //  private method
1086 //*****************************************************************************************************************
1087 sal_Bool AddonsOptions_Impl::ReadMergeToolbarData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
1088 {
1089     ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
1090     aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] );
1091 
1092     ::rtl::OUString aMergeToolbarBaseNode = aBuffer.makeStringAndClear();
1093 
1094     return ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
1095 }
1096 
1097 //*****************************************************************************************************************
1098 //  private method
1099 //*****************************************************************************************************************
1100 sal_Bool AddonsOptions_Impl::ReadMenuItem( const ::rtl::OUString& aMenuNodeName, Sequence< PropertyValue >& aMenuItem, sal_Bool bIgnoreSubMenu )
1101 {
1102     sal_Bool            bResult = sal_False;
1103     ::rtl::OUString         aStrValue;
1104     ::rtl::OUString         aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );
1105     Sequence< Any >     aMenuItemNodePropValues;
1106 
1107     aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
1108     if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && aStrValue.getLength() > 0 )
1109     {
1110         aMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;
1111 
1112         ::rtl::OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1113         Sequence< ::rtl::OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1114         if ( aRootSubMenuNodeNames.getLength() > 0 && !bIgnoreSubMenu )
1115         {
1116             // Set a unique prefixed Add-On popup menu URL so it can be identified later
1117             ::rtl::OUString aPopupMenuURL     = GeneratePrefixURL();
1118             ::rtl::OUString aPopupMenuImageId;
1119 
1120             aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId;
1121             ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId );
1122 
1123             // A popup menu must have a title and can have a URL and ImageIdentifier
1124             // Set the other property values to empty
1125             aMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aPopupMenuURL;
1126             aMenuItem[ OFFSET_MENUITEM_TARGET           ].Value <<= m_aEmpty;
1127             aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= aPopupMenuImageId;
1128             aMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1129 
1130             // Continue to read the sub menu nodes
1131             Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1132             ::rtl::OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1133             for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ )
1134                 aRootSubMenuNodeNames[n] = ::rtl::OUString( aSubMenuRootNodeName + aRootSubMenuNodeNames[n] );
1135             ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1136             aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
1137             bResult = sal_True;
1138         }
1139         else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && aStrValue.getLength() > 0 )
1140         {
1141             // A simple menu item => read the other properties;
1142             ::rtl::OUString aMenuImageId;
1143 
1144             aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId;
1145             ReadAndAssociateImages( aStrValue, aMenuImageId );
1146 
1147             aMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aStrValue;
1148             aMenuItem[ OFFSET_MENUITEM_TARGET           ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET         ];
1149             aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= aMenuImageId;
1150             aMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT        ];
1151             aMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1152 
1153             bResult = sal_True;
1154         }
1155     }
1156     else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) &&
1157               aStrValue.equalsAsciiL( SEPARATOR_URL_STR, SEPARATOR_URL_LEN ))
1158     {
1159         // Separator
1160         aMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aStrValue;
1161         aMenuItem[ OFFSET_MENUITEM_TARGET           ].Value <<= m_aEmpty;
1162         aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= m_aEmpty;
1163         aMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value <<= m_aEmpty;
1164         aMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1165         bResult = sal_True;
1166     }
1167 
1168     return bResult;
1169 }
1170 
1171 //*****************************************************************************************************************
1172 //  private method
1173 //*****************************************************************************************************************
1174 sal_Bool AddonsOptions_Impl::ReadPopupMenu( const ::rtl::OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu )
1175 {
1176     sal_Bool            bResult = sal_False;
1177     ::rtl::OUString         aStrValue;
1178     ::rtl::OUString         aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter );
1179     Sequence< Any >     aPopupMenuNodePropValues;
1180 
1181     aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) );
1182     if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) &&
1183          aStrValue.getLength() > 0 )
1184     {
1185         aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue;
1186 
1187         ::rtl::OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1188         Sequence< ::rtl::OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1189         if ( aRootSubMenuNodeNames.getLength() > 0 )
1190         {
1191             // A top-level popup menu needs a title
1192             // Set a unique prefixed Add-On popup menu URL so it can be identified later
1193             ::rtl::OUString aPopupMenuURL = GeneratePrefixURL();
1194 
1195             aPopupMenu[ OFFSET_POPUPMENU_URL        ].Value <<= aPopupMenuURL;
1196             aPopupMenu[ OFFSET_POPUPMENU_CONTEXT    ].Value <<= aPopupMenuNodePropValues[ OFFSET_POPUPMENU_CONTEXT ];
1197 
1198             // Continue to read the sub menu nodes
1199             Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1200             ::rtl::OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1201             for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ )
1202                 aRootSubMenuNodeNames[n] = ::rtl::OUString( aSubMenuRootNodeName + aRootSubMenuNodeNames[n] );
1203             ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1204             aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq;
1205             bResult = sal_True;
1206         }
1207     }
1208 
1209     return bResult;
1210 }
1211 
1212 //*****************************************************************************************************************
1213 //  private method
1214 //*****************************************************************************************************************
1215 sal_Bool AddonsOptions_Impl::AppendPopupMenu( Sequence< PropertyValue >& rTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu )
1216 {
1217     Sequence< Sequence< PropertyValue > > aTargetSubMenuSeq;
1218     Sequence< Sequence< PropertyValue > > aSourceSubMenuSeq;
1219 
1220     if (( rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aTargetSubMenuSeq ) &&
1221         ( rSourcePopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aSourceSubMenuSeq ))
1222     {
1223         sal_uInt32 nIndex = aTargetSubMenuSeq.getLength();
1224         aTargetSubMenuSeq.realloc( nIndex + aSourceSubMenuSeq.getLength() );
1225         for ( sal_uInt32 i = 0; i < sal_uInt32( aSourceSubMenuSeq.getLength() ); i++ )
1226             aTargetSubMenuSeq[nIndex++] = aSourceSubMenuSeq[i];
1227         rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq;
1228     }
1229 
1230     return sal_True;
1231 }
1232 
1233 //*****************************************************************************************************************
1234 //  private method
1235 //*****************************************************************************************************************
1236 sal_Bool AddonsOptions_Impl::ReadToolBarItem( const ::rtl::OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem )
1237 {
1238     sal_Bool            bResult = sal_False;
1239     ::rtl::OUString         aTitle;
1240     ::rtl::OUString         aURL;
1241     ::rtl::OUString         aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter );
1242     Sequence< Any >     aToolBarItemNodePropValues;
1243 
1244     aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) );
1245 
1246     // A toolbar item must have a command URL
1247     if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
1248     {
1249         if ( aURL.equals( SEPARATOR_URL ))
1250         {
1251             // A speparator toolbar item only needs a URL
1252             aToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Value <<= aURL;
1253             aToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Value <<= m_aEmpty;
1254             aToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Value <<= m_aEmpty;
1255             aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Value <<= m_aEmpty;
1256             aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Value <<= m_aEmpty;
1257             aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Value <<= m_aEmpty;
1258             aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Value <<= sal_Int32( 0 );
1259 
1260             bResult = sal_True;
1261         }
1262         else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE ] >>= aTitle ) && aTitle.getLength() > 0 )
1263         {
1264             // A normal toolbar item must also have title => read the other properties;
1265             ::rtl::OUString aImageId;
1266 
1267             // Try to map a user-defined image URL to our internal private image URL
1268             aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1269             ReadAndAssociateImages( aURL, aImageId );
1270 
1271             aToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Value <<= aURL;
1272             aToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Value <<= aTitle;
1273             aToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TARGET      ];
1274             aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Value <<= aImageId;
1275             aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTEXT     ];
1276             aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTROLTYPE ];
1277 
1278             // Configuration uses hyper for long. Therefore transform into sal_Int32
1279             sal_Int64 nValue( 0 );
1280             aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_WIDTH ] >>= nValue;
1281             aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Value <<= sal_Int32( nValue );
1282 
1283             bResult = sal_True;
1284         }
1285     }
1286 
1287     return bResult;
1288 }
1289 
1290 //*****************************************************************************************************************
1291 //  private method
1292 //*****************************************************************************************************************
1293 sal_Bool AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< ::rtl::OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenuSeq )
1294 {
1295     Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
1296 
1297     // Init the property value sequence
1298     aMenuItem[ OFFSET_MENUITEM_URL              ].Name = PROPERTYNAME_URL;
1299     aMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = PROPERTYNAME_TITLE;
1300     aMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = PROPERTYNAME_TARGET;
1301     aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = PROPERTYNAME_IMAGEIDENTIFIER;
1302     aMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = PROPERTYNAME_CONTEXT;
1303     aMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = PROPERTYNAME_SUBMENU;  // Submenu set!
1304 
1305     sal_uInt32 nIndex = 0;
1306     sal_uInt32 nCount = aSubMenuNodeNames.getLength();
1307     for ( sal_uInt32 n = 0; n < nCount; n++ )
1308     {
1309         if ( ReadMenuItem( aSubMenuNodeNames[n], aMenuItem ))
1310         {
1311             sal_uInt32 nSubMenuCount = rSubMenuSeq.getLength() + 1;
1312             rSubMenuSeq.realloc( nSubMenuCount );
1313             rSubMenuSeq[nIndex++] = aMenuItem;
1314         }
1315     }
1316 
1317     return sal_True;
1318 }
1319 
1320 //*****************************************************************************************************************
1321 //  private method
1322 //*****************************************************************************************************************
1323 sal_Bool AddonsOptions_Impl::HasAssociatedImages( const ::rtl::OUString& aURL )
1324 {
1325     ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
1326     return ( pIter != m_aImageManager.end() );
1327 }
1328 
1329 //*****************************************************************************************************************
1330 //  private method
1331 //*****************************************************************************************************************
1332 void AddonsOptions_Impl::SubstituteVariables( ::rtl::OUString& aURL )
1333 {
1334     if (( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) &&
1335         m_xMacroExpander.is() )
1336     {
1337         // cut protocol
1338         ::rtl::OUString macro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) );
1339         // decode uric class chars
1340         macro = ::rtl::Uri::decode(
1341             macro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
1342         // expand macro string
1343         aURL = m_xMacroExpander->expandMacros( macro );
1344     }
1345 }
1346 
1347 //*****************************************************************************************************************
1348 //  private method
1349 //*****************************************************************************************************************
1350 void AddonsOptions_Impl::ReadImageFromURL( ImageSize nImageSize, const ::rtl::OUString& aImageURL, Image& aImage, Image& aImageNoScale )
1351 {
1352     SvStream* pStream = UcbStreamHelper::CreateStream( aImageURL, STREAM_STD_READ );
1353     if ( pStream && ( pStream->GetErrorCode() == 0 ))
1354     {
1355         // Use graphic class to also support more graphic formats (bmp,png,...)
1356         Graphic aGraphic;
1357 
1358         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
1359         pGF->ImportGraphic( aGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW );
1360 
1361         BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
1362 
1363         const Size aSize = ( nImageSize == IMGSIZE_SMALL ) ? aImageSizeSmall : aImageSizeBig; // Sizes used for menu/toolbox images
1364 
1365         Size aBmpSize = aBitmapEx.GetSizePixel();
1366         if ( aBmpSize.Width() > 0 && aBmpSize.Height() > 0 )
1367         {
1368             // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1369             if( !aBitmapEx.IsTransparent() )
1370                 aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1371 
1372             // A non-scaled bitmap can have a flexible width, but must have a defined height!
1373             Size aNoScaleSize( aBmpSize.Width(), aSize.Height() );
1374             if ( aBmpSize != aNoScaleSize )
1375             {
1376                 BitmapEx aNoScaleBmp( aBitmapEx );
1377                 aNoScaleBmp.Scale( aNoScaleSize, BMP_SCALE_INTERPOLATE );
1378             }
1379             else
1380                 aImageNoScale = Image( aBitmapEx );
1381 
1382             if ( aBmpSize != aSize )
1383                 aBitmapEx.Scale( aSize, BMP_SCALE_INTERPOLATE );
1384 
1385             aImage = Image( aBitmapEx );
1386         }
1387     }
1388 
1389     delete pStream;
1390 }
1391 
1392 //*****************************************************************************************************************
1393 //  private method
1394 //*****************************************************************************************************************
1395 void AddonsOptions_Impl::ReadAndAssociateImages( const ::rtl::OUString& aURL, const ::rtl::OUString& aImageId )
1396 {
1397     const int   MAX_NUM_IMAGES = 4;
1398     const char* aExtArray[MAX_NUM_IMAGES] = { "_16", "_26", "_16h", "_26h" };
1399     const char* pBmpExt = ".bmp";
1400 
1401     if ( aImageId.getLength() == 0 )
1402         return;
1403 
1404     bool        bImageFound = true;
1405     ImageEntry  aImageEntry;
1406     ::rtl::OUString    aImageURL( aImageId );
1407 
1408     SubstituteVariables( aImageURL );
1409 
1410     // Loop to create the four possible image names and try to read the bitmap files
1411     for ( int i = 0; i < MAX_NUM_IMAGES; i++ )
1412     {
1413         ::rtl::OUStringBuffer aFileURL( aImageURL );
1414         aFileURL.appendAscii( aExtArray[i] );
1415         aFileURL.appendAscii( pBmpExt );
1416 
1417         Image aImage;
1418         Image aImageNoScale;
1419         ReadImageFromURL( ((i==0)||(i==2)) ? IMGSIZE_SMALL : IMGSIZE_BIG, aFileURL.makeStringAndClear(), aImage, aImageNoScale );
1420         if ( !!aImage )
1421         {
1422             bImageFound = true;
1423             switch ( i )
1424             {
1425                 case 0:
1426                     aImageEntry.aImageSmall          = aImage;
1427                     aImageEntry.aImageSmallNoScale   = aImageNoScale;
1428                     break;
1429                 case 1:
1430                     aImageEntry.aImageBig            = aImage;
1431                     aImageEntry.aImageBigNoScale     = aImageNoScale;
1432                     break;
1433                 case 2:
1434                     aImageEntry.aImageSmallHC        = aImage;
1435                     aImageEntry.aImageSmallHCNoScale = aImageNoScale;
1436                     break;
1437                 case 3:
1438                     aImageEntry.aImageBigHC          = aImage;
1439                     aImageEntry.aImageBigHCNoScale   = aImageNoScale;
1440                     break;
1441             }
1442         }
1443     }
1444 
1445     if ( bImageFound )
1446         m_aImageManager.insert( ImageManager::value_type( aURL, aImageEntry ));
1447 }
1448 
1449 //*****************************************************************************************************************
1450 //  private method
1451 //*****************************************************************************************************************
1452 AddonsOptions_Impl::ImageEntry* AddonsOptions_Impl::ReadImageData( const ::rtl::OUString& aImagesNodeName )
1453 {
1454     Sequence< ::rtl::OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName );
1455     Sequence< Any >      aPropertyData;
1456     Sequence< sal_Int8 > aImageDataSeq;
1457     ::rtl::OUString             aImageURL;
1458 
1459     ImageEntry* pEntry = NULL;
1460 
1461     // It is possible to use both forms (embedded image data and URLs to external bitmap files) at the
1462     // same time. Embedded image data has a higher priority.
1463     aPropertyData = GetProperties( aImageDataNodeNames );
1464     for ( int i = 0; i < PROPERTYCOUNT_IMAGES; i++ )
1465     {
1466         if ( i < PROPERTYCOUNT_EMBEDDED_IMAGES )
1467         {
1468             // Extract image data from the embedded hex binary sequence
1469             Image aImage;
1470             if (( aPropertyData[i] >>= aImageDataSeq ) &&
1471                 aImageDataSeq.getLength() > 0 &&
1472                 ( CreateImageFromSequence( aImage,
1473                                         (( i == OFFSET_IMAGES_BIG ) ||
1474                                         ( i == OFFSET_IMAGES_BIGHC )),
1475                                         aImageDataSeq )) )
1476             {
1477                 if ( !pEntry )
1478                     pEntry = new ImageEntry;
1479 
1480                 if ( i == OFFSET_IMAGES_SMALL )
1481                     pEntry->aImageSmall = aImage;
1482                 else if ( i == OFFSET_IMAGES_BIG )
1483                     pEntry->aImageBig = aImage;
1484                 else if ( i == OFFSET_IMAGES_SMALLHC )
1485                     pEntry->aImageSmallHC = aImage;
1486                 else
1487                     pEntry->aImageBigHC = aImage;
1488             }
1489         }
1490         else
1491         {
1492             // Retrieve image data from a external bitmap file. Make sure that embedded image data
1493             // has a higher priority.
1494             aPropertyData[i] >>= aImageURL;
1495 
1496             if ( aImageURL.getLength() > 0 )
1497             {
1498                 Image aImage;
1499                 Image aImageNoScale;
1500 
1501                 SubstituteVariables( aImageURL );
1502                 ReadImageFromURL( ((i==OFFSET_IMAGES_SMALL_URL)||(i==OFFSET_IMAGES_SMALLHC_URL)) ? IMGSIZE_SMALL : IMGSIZE_BIG,
1503                                   aImageURL, aImage, aImageNoScale );
1504                 if ( !!aImage )
1505                 {
1506                     if ( !pEntry )
1507                         pEntry = new ImageEntry;
1508 
1509                     if ( i == OFFSET_IMAGES_SMALL_URL && !pEntry->aImageSmall )
1510                     {
1511                         pEntry->aImageSmall = aImage;
1512                         pEntry->aImageSmallNoScale = aImageNoScale;
1513                     }
1514                     else if ( i == OFFSET_IMAGES_BIG_URL && !pEntry->aImageBig )
1515                     {
1516                         pEntry->aImageBig = aImage;
1517                         pEntry->aImageBigNoScale = aImageNoScale;
1518                     }
1519                     else if ( i == OFFSET_IMAGES_SMALLHC_URL && !pEntry->aImageSmallHC )
1520                     {
1521                         pEntry->aImageSmallHC = aImage;
1522                         pEntry->aImageSmallHCNoScale = aImageNoScale;
1523                     }
1524                     else if ( !pEntry->aImageBigHC )
1525                     {
1526                         pEntry->aImageBigHC = aImage;
1527                         pEntry->aImageBigHCNoScale = aImageNoScale;
1528                     }
1529                 }
1530             }
1531         }
1532     }
1533 
1534     return pEntry;
1535 }
1536 
1537 //*****************************************************************************************************************
1538 //  private method
1539 //*****************************************************************************************************************
1540 sal_Bool AddonsOptions_Impl::CreateImageFromSequence( Image& rImage, sal_Bool bBig, Sequence< sal_Int8 >& rBitmapDataSeq ) const
1541 {
1542     sal_Bool    bResult = sal_False;
1543     Size        aSize = bBig ? aImageSizeBig : aImageSizeSmall; // Sizes used for menu/toolbox images
1544 
1545     if ( rBitmapDataSeq.getLength() > 0 )
1546     {
1547         SvMemoryStream  aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), STREAM_STD_READ );
1548         BitmapEx        aBitmapEx;
1549 
1550         aMemStream >> aBitmapEx;
1551 
1552         // Scale bitmap to fit the correct size for the menu/toolbar. Use best quality
1553         if ( aBitmapEx.GetSizePixel() != aSize )
1554             aBitmapEx.Scale( aSize, BMP_SCALE_INTERPOLATE );
1555 
1556         if( !aBitmapEx.IsTransparent() )
1557         {
1558             // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1559             aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1560         }
1561 
1562         rImage = Image( aBitmapEx );
1563         bResult = sal_True;
1564     }
1565 
1566     return bResult;
1567 }
1568 
1569 //*****************************************************************************************************************
1570 //  private methods
1571 //*****************************************************************************************************************
1572 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesMergeMenuInstruction( const ::rtl::OUString& aPropertyRootNode ) const
1573 {
1574     Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_MERGE_MENUBAR );
1575 
1576     // Create property names dependent from the root node name
1577     lResult[ OFFSET_MERGEMENU_MERGEPOINT            ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT    ] );
1578     lResult[ OFFSET_MERGEMENU_MERGECOMMAND          ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND  ] );
1579     lResult[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] );
1580     lResult[ OFFSET_MERGEMENU_MERGEFALLBACK         ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] );
1581     lResult[ OFFSET_MERGEMENU_MERGECONTEXT          ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT  ] );
1582     lResult[ OFFSET_MERGEMENU_MENUITEMS             ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS     ] );
1583 
1584     return lResult;
1585 }
1586 
1587 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( const ::rtl::OUString& aPropertyRootNode ) const
1588 {
1589     Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_MENUITEM );
1590 
1591     // Create property names dependent from the root node name
1592     lResult[OFFSET_MENUITEM_URL]             = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL          ] );
1593     lResult[OFFSET_MENUITEM_TITLE]           = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE            ] );
1594     lResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ] );
1595     lResult[OFFSET_MENUITEM_TARGET]          = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TARGET           ] );
1596     lResult[OFFSET_MENUITEM_CONTEXT]         = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT      ] );
1597     lResult[OFFSET_MENUITEM_SUBMENU]         = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU      ] );
1598 
1599     return lResult;
1600 }
1601 
1602 //*****************************************************************************************************************
1603 //  private method
1604 //*****************************************************************************************************************
1605 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( const ::rtl::OUString& aPropertyRootNode ) const
1606 {
1607     // The URL is automatically set and not read from the configuration.
1608     Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 );
1609 
1610     // Create property names dependent from the root node name
1611     lResult[OFFSET_POPUPMENU_TITLE]   = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE  ] );
1612     lResult[OFFSET_POPUPMENU_CONTEXT] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT    ] );
1613     lResult[OFFSET_POPUPMENU_SUBMENU] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU    ] );
1614 
1615     return lResult;
1616 }
1617 
1618 //*****************************************************************************************************************
1619 //  private method
1620 //*****************************************************************************************************************
1621 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( const ::rtl::OUString& aPropertyRootNode ) const
1622 {
1623     Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_TOOLBARITEM );
1624 
1625     // Create property names dependent from the root node name
1626     lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL             ] );
1627     lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE       ] );
1628     lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER] );
1629     lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TARGET          ] );
1630     lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT         ] );
1631     lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE     ] );
1632     lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH       ] );
1633 
1634     return lResult;
1635 }
1636 
1637 //*****************************************************************************************************************
1638 //  private method
1639 //*****************************************************************************************************************
1640 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesImages( const ::rtl::OUString& aPropertyRootNode ) const
1641 {
1642     Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_IMAGES );
1643 
1644     // Create property names dependent from the root node name
1645     lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL       ] );
1646     lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG     ] );
1647     lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ] );
1648     lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC       ] );
1649     lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL  ] );
1650     lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ] );
1651     lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL] );
1652     lResult[7] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL   ] );
1653 
1654     return lResult;
1655 }
1656 
1657 //*****************************************************************************************************************
1658 //  initialize static member
1659 //  DON'T DO IT IN YOUR HEADER!
1660 //  see definition for further informations
1661 //*****************************************************************************************************************
1662 AddonsOptions_Impl*     AddonsOptions::m_pDataContainer = NULL  ;
1663 sal_Int32               AddonsOptions::m_nRefCount      = 0     ;
1664 
1665 //*****************************************************************************************************************
1666 //  constructor
1667 //*****************************************************************************************************************
1668 AddonsOptions::AddonsOptions()
1669 {
1670     // Global access, must be guarded (multithreading!).
1671     MutexGuard aGuard( GetOwnStaticMutex() );
1672     // Increase ouer refcount ...
1673     ++m_nRefCount;
1674     // ... and initialize ouer data container only if it not already exist!
1675     if( m_pDataContainer == NULL )
1676     {
1677         m_pDataContainer = new AddonsOptions_Impl;
1678     }
1679 }
1680 
1681 //*****************************************************************************************************************
1682 //  destructor
1683 //*****************************************************************************************************************
1684 AddonsOptions::~AddonsOptions()
1685 {
1686     // Global access, must be guarded (multithreading!)
1687     MutexGuard aGuard( GetOwnStaticMutex() );
1688     // Decrease ouer refcount.
1689     --m_nRefCount;
1690     // If last instance was deleted ...
1691     // we must destroy ouer static data container!
1692     if( m_nRefCount <= 0 )
1693     {
1694         delete m_pDataContainer;
1695         m_pDataContainer = NULL;
1696     }
1697 }
1698 
1699 //*****************************************************************************************************************
1700 //  public method
1701 //*****************************************************************************************************************
1702 sal_Bool AddonsOptions::HasAddonsMenu() const
1703 {
1704     MutexGuard aGuard( GetOwnStaticMutex() );
1705     return m_pDataContainer->HasAddonsMenu();
1706 }
1707 
1708 //*****************************************************************************************************************
1709 //  public method
1710 //*****************************************************************************************************************
1711 
1712 sal_Bool AddonsOptions::HasAddonsHelpMenu() const
1713 {
1714     MutexGuard aGuard( GetOwnStaticMutex() );
1715     return m_pDataContainer->HasAddonsHelpMenu();
1716 }
1717 
1718 //*****************************************************************************************************************
1719 //  public method
1720 //*****************************************************************************************************************
1721 
1722 sal_Int32 AddonsOptions::GetAddonsToolBarCount() const
1723 {
1724     MutexGuard aGuard( GetOwnStaticMutex() );
1725     return m_pDataContainer->GetAddonsToolBarCount();
1726 }
1727 
1728 //*****************************************************************************************************************
1729 //  public method
1730 //*****************************************************************************************************************
1731 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const
1732 {
1733     MutexGuard aGuard( GetOwnStaticMutex() );
1734     return m_pDataContainer->GetAddonsMenu();
1735 }
1736 
1737 //*****************************************************************************************************************
1738 //  public method
1739 //*****************************************************************************************************************
1740 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const
1741 {
1742     MutexGuard aGuard( GetOwnStaticMutex() );
1743     return m_pDataContainer->GetAddonsMenuBarPart();
1744 }
1745 
1746 //*****************************************************************************************************************
1747 //  public method
1748 //*****************************************************************************************************************
1749 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
1750 {
1751     MutexGuard aGuard( GetOwnStaticMutex() );
1752     return m_pDataContainer->GetAddonsToolBarPart( nIndex );
1753 }
1754 
1755 //*****************************************************************************************************************
1756 //  public method
1757 //*****************************************************************************************************************
1758 const ::rtl::OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
1759 {
1760     MutexGuard aGuard( GetOwnStaticMutex() );
1761     return m_pDataContainer->GetAddonsToolbarResourceName( nIndex );
1762 }
1763 
1764 //*****************************************************************************************************************
1765 //  public method
1766 //*****************************************************************************************************************
1767 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const
1768 {
1769     MutexGuard aGuard( GetOwnStaticMutex() );
1770     return m_pDataContainer->GetAddonsHelpMenu();
1771 }
1772 
1773 //*****************************************************************************************************************
1774 //  public method
1775 //*****************************************************************************************************************
1776 const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const
1777 {
1778     MutexGuard aGuard( GetOwnStaticMutex() );
1779     return m_pDataContainer->GetMergeMenuInstructions();
1780 }
1781 
1782 //*****************************************************************************************************************
1783 //  public method
1784 //*****************************************************************************************************************
1785 bool AddonsOptions::GetMergeToolbarInstructions(
1786     const ::rtl::OUString& rToolbarName,
1787     MergeToolbarInstructionContainer& rToolbarInstructions ) const
1788 {
1789     MutexGuard aGuard( GetOwnStaticMutex() );
1790     return m_pDataContainer->GetMergeToolbarInstructions(
1791         rToolbarName, rToolbarInstructions );
1792 }
1793 
1794 //*****************************************************************************************************************
1795 //  public method
1796 //*****************************************************************************************************************
1797 Image AddonsOptions::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const
1798 {
1799     MutexGuard aGuard( GetOwnStaticMutex() );
1800     return m_pDataContainer->GetImageFromURL( aURL, bBig, bHiContrast, bNoScale );
1801 }
1802 
1803 //*****************************************************************************************************************
1804 //  public method
1805 //*****************************************************************************************************************
1806 Image AddonsOptions::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast ) const
1807 {
1808     return GetImageFromURL( aURL, bBig, bHiContrast, sal_False );
1809 }
1810 
1811 //*****************************************************************************************************************
1812 //  private method
1813 //*****************************************************************************************************************
1814 Mutex& AddonsOptions::GetOwnStaticMutex()
1815 {
1816     // Initialize static mutex only for one time!
1817     static Mutex* pMutex = NULL;
1818     // If these method first called (Mutex not already exist!) ...
1819     if( pMutex == NULL )
1820     {
1821         // ... we must create a new one. Protect follow code with the global mutex -
1822         // It must be - we create a static variable!
1823         MutexGuard aGuard( Mutex::getGlobalMutex() );
1824         // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
1825         if( pMutex == NULL )
1826         {
1827             // Create the new mutex and set it for return on static variable.
1828             static Mutex aMutex;
1829             pMutex = &aMutex;
1830         }
1831     }
1832     // Return new created or already existing mutex object.
1833     return *pMutex;
1834 }
1835 
1836 //*****************************************************************************************************************
1837 //  private method
1838 //*****************************************************************************************************************
1839 IMPL_STATIC_LINK_NOINSTANCE( AddonsOptions, Notify, void*, EMPTYARG )
1840 {
1841     MutexGuard aGuard( GetOwnStaticMutex() );
1842     m_pDataContainer->ReadConfigurationData();
1843     return 0;
1844 }
1845 
1846 }
1847 
1848