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