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