Avoid potential negative array index access to cached text.
[LibreOffice.git] / framework / source / fwe / classes / addonsoptions.cxx
blob7801fa5e81750b85406ecc9d18fd11b289a8364b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/beans/PropertyValue.hpp>
21 #include <framework/addonsoptions.hxx>
22 #include <o3tl/safeint.hxx>
23 #include <unotools/configmgr.hxx>
24 #include <unotools/configitem.hxx>
25 #include <unotools/ucbstreamhelper.hxx>
26 #include <tools/stream.hxx>
27 #include <com/sun/star/uno/Any.hxx>
28 #include <com/sun/star/uno/Sequence.hxx>
29 #include <rtl/ustrbuf.hxx>
30 #include <sal/log.hxx>
31 #include <comphelper/getexpandeduri.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <vcl/dibtools.hxx>
34 #include <vcl/graph.hxx>
35 #include <vcl/graphicfilter.hxx>
36 #include <vcl/toolbox.hxx>
37 #include <vcl/svapp.hxx>
39 #include <algorithm>
40 #include <string_view>
41 #include <unordered_map>
42 #include <vector>
44 // namespaces
46 using namespace ::utl;
47 using namespace ::osl;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::beans;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star;
53 constexpr OUStringLiteral ROOTNODE_ADDONMENU = u"Office.Addons";
54 constexpr OUStringLiteral PATHDELIMITER = u"/";
55 constexpr OUString SEPARATOR_URL = u"private:separator"_ustr;
57 #define PROPERTYNAME_URL ADDONSMENUITEM_STRING_URL
58 #define PROPERTYNAME_TITLE ADDONSMENUITEM_STRING_TITLE
59 #define PROPERTYNAME_TARGET ADDONSMENUITEM_STRING_TARGET
60 #define PROPERTYNAME_IMAGEIDENTIFIER ADDONSMENUITEM_STRING_IMAGEIDENTIFIER
61 #define PROPERTYNAME_CONTEXT ADDONSMENUITEM_STRING_CONTEXT
62 #define PROPERTYNAME_SUBMENU ADDONSMENUITEM_STRING_SUBMENU
64 constexpr OUStringLiteral IMAGES_NODENAME = u"UserDefinedImages";
66 // The following order is mandatory. Please add properties at the end!
67 #define INDEX_URL 0
68 #define INDEX_TITLE 1
69 #define INDEX_IMAGEIDENTIFIER 2
70 #define INDEX_TARGET 3
71 #define INDEX_CONTEXT 4
72 #define INDEX_SUBMENU 5
73 #define INDEX_CONTROLTYPE 6
74 #define INDEX_WIDTH 7
75 #define INDEX_ALIGN 8
76 #define INDEX_AUTOSIZE 9
77 #define INDEX_OWNERDRAW 10
78 #define INDEX_MANDATORY 11
79 #define INDEX_STYLE 12
80 #define PROPERTYCOUNT_INDEX 13
82 // The following order is mandatory. Please add properties at the end!
83 #define PROPERTYCOUNT_MENUITEM 6
84 #define OFFSET_MENUITEM_URL 0
85 #define OFFSET_MENUITEM_TITLE 1
86 #define OFFSET_MENUITEM_IMAGEIDENTIFIER 2
87 #define OFFSET_MENUITEM_TARGET 3
88 #define OFFSET_MENUITEM_CONTEXT 4
89 #define OFFSET_MENUITEM_SUBMENU 5
91 // The following order is mandatory. Please add properties at the end!
92 #define PROPERTYCOUNT_POPUPMENU 4
93 #define OFFSET_POPUPMENU_TITLE 0
94 #define OFFSET_POPUPMENU_CONTEXT 1
95 #define OFFSET_POPUPMENU_SUBMENU 2
96 #define OFFSET_POPUPMENU_URL 3 // Used for property set
98 // The following order is mandatory. Please add properties at the end!
99 #define PROPERTYCOUNT_TOOLBARITEM 7
100 #define OFFSET_TOOLBARITEM_URL 0
101 #define OFFSET_TOOLBARITEM_TITLE 1
102 #define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER 2
103 #define OFFSET_TOOLBARITEM_TARGET 3
104 #define OFFSET_TOOLBARITEM_CONTEXT 4
105 #define OFFSET_TOOLBARITEM_CONTROLTYPE 5
106 #define OFFSET_TOOLBARITEM_WIDTH 6
108 // The following order is mandatory. Please add properties at the end!
109 #define PROPERTYCOUNT_NOTEBOOKBARITEM 8
110 #define OFFSET_NOTEBOOKBARITEM_URL 0
111 #define OFFSET_NOTEBOOKBARITEM_TITLE 1
112 #define OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER 2
113 #define OFFSET_NOTEBOOKBARITEM_TARGET 3
114 #define OFFSET_NOTEBOOKBARITEM_CONTEXT 4
115 #define OFFSET_NOTEBOOKBARITEM_CONTROLTYPE 5
116 #define OFFSET_NOTEBOOKBARITEM_WIDTH 6
117 #define OFFSET_NOTEBOOKBARITEM_STYLE 7
119 // The following order is mandatory. Please add properties at the end!
120 #define PROPERTYCOUNT_STATUSBARITEM 8
121 #define OFFSET_STATUSBARITEM_URL 0
122 #define OFFSET_STATUSBARITEM_TITLE 1
123 #define OFFSET_STATUSBARITEM_CONTEXT 2
124 #define OFFSET_STATUSBARITEM_ALIGN 3
125 #define OFFSET_STATUSBARITEM_AUTOSIZE 4
126 #define OFFSET_STATUSBARITEM_OWNERDRAW 5
127 #define OFFSET_STATUSBARITEM_MANDATORY 6
128 #define OFFSET_STATUSBARITEM_WIDTH 7
130 // The following order is mandatory. Please add properties at the end!
131 #define PROPERTYCOUNT_IMAGES 8
132 #define PROPERTYCOUNT_EMBEDDED_IMAGES 2
133 #define OFFSET_IMAGES_SMALL 0
134 #define OFFSET_IMAGES_BIG 1
135 #define OFFSET_IMAGES_SMALLHC 2
136 #define OFFSET_IMAGES_BIGHC 3
137 #define OFFSET_IMAGES_SMALL_URL 4
138 #define OFFSET_IMAGES_BIG_URL 5
139 #define OFFSET_IMAGES_SMALLHC_URL 6
140 #define OFFSET_IMAGES_BIGHC_URL 7
142 #define PROPERTYCOUNT_MERGE_MENUBAR 6
143 #define OFFSET_MERGEMENU_MERGEPOINT 0
144 #define OFFSET_MERGEMENU_MERGECOMMAND 1
145 #define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER 2
146 #define OFFSET_MERGEMENU_MERGEFALLBACK 3
147 #define OFFSET_MERGEMENU_MERGECONTEXT 4
148 #define OFFSET_MERGEMENU_MENUITEMS 5
150 #define PROPERTYCOUNT_MERGE_TOOLBAR 7
151 #define OFFSET_MERGETOOLBAR_TOOLBAR 0
152 #define OFFSET_MERGETOOLBAR_MERGEPOINT 1
153 #define OFFSET_MERGETOOLBAR_MERGECOMMAND 2
154 #define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER 3
155 #define OFFSET_MERGETOOLBAR_MERGEFALLBACK 4
156 #define OFFSET_MERGETOOLBAR_MERGECONTEXT 5
157 #define OFFSET_MERGETOOLBAR_TOOLBARITEMS 6
159 #define PROPERTYCOUNT_MERGE_NOTEBOOKBAR 7
160 #define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR 0
161 #define OFFSET_MERGENOTEBOOKBAR_MERGEPOINT 1
162 #define OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND 2
163 #define OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER 3
164 #define OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK 4
165 #define OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT 5
166 #define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS 6
168 #define PROPERTYCOUNT_MERGE_STATUSBAR 6
169 #define OFFSET_MERGESTATUSBAR_MERGEPOINT 0
170 #define OFFSET_MERGESTATUSBAR_MERGECOMMAND 1
171 #define OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER 2
172 #define OFFSET_MERGESTATUSBAR_MERGEFALLBACK 3
173 #define OFFSET_MERGESTATUSBAR_MERGECONTEXT 4
174 #define OFFSET_MERGESTATUSBAR_STATUSBARITEMS 5
176 // private declarations!
178 /*-****************************************************************************************************************
179 @descr struct to hold information about one menu entry.
180 ****************************************************************************************************************-*/
182 namespace framework
185 class AddonsOptions_Impl : public ConfigItem
188 // public methods
190 public:
192 // constructor / destructor
194 AddonsOptions_Impl();
195 virtual ~AddonsOptions_Impl() override;
197 // overridden methods of baseclass
199 /*-****************************************************************************************************
200 @short called for notify of configmanager
201 @descr This method is called from the ConfigManager before application ends or from the
202 PropertyChangeListener if the sub tree broadcasts changes. You must update your
203 internal values.
205 @seealso baseclass ConfigItem
207 @param "lPropertyNames" is the list of properties which should be updated.
208 *//*-*****************************************************************************************************/
210 virtual void Notify( const Sequence< OUString >& lPropertyNames ) override;
212 // public interface
214 /*-****************************************************************************************************
215 @short base implementation of public interface for "SvtDynamicMenuOptions"!
216 @descr These class is used as static member of "SvtDynamicMenuOptions" ...
217 => The code exist only for one time and isn't duplicated for every instance!
218 *//*-*****************************************************************************************************/
220 bool HasAddonsMenu () const;
221 sal_Int32 GetAddonsToolBarCount() const;
222 sal_Int32 GetAddonsNotebookBarCount() const;
223 const Sequence< Sequence< PropertyValue > >& GetAddonsMenu () const { return m_aCachedMenuProperties;}
224 const Sequence< Sequence< PropertyValue > >& GetAddonsMenuBarPart () const { return m_aCachedMenuBarPartProperties;}
225 const Sequence< Sequence< PropertyValue > >& GetAddonsToolBarPart ( sal_uInt32 nIndex ) const;
226 const Sequence< Sequence< PropertyValue > >& GetAddonsNotebookBarPart ( sal_uInt32 nIndex ) const;
227 OUString GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
228 OUString GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const;
229 const Sequence< Sequence< PropertyValue > >& GetAddonsHelpMenu () const { return m_aCachedHelpMenuProperties;}
230 BitmapEx GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale );
231 const MergeMenuInstructionContainer& GetMergeMenuInstructions() const { return m_aCachedMergeMenuInsContainer;}
232 bool GetMergeToolbarInstructions( const OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const;
233 bool GetMergeNotebookBarInstructions( const OUString& rNotebookBarName, MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const;
234 const MergeStatusbarInstructionContainer& GetMergeStatusbarInstructions() const { return m_aCachedStatusbarMergingInstructions;}
235 void ReadConfigurationData();
237 private:
238 enum ImageSize
240 IMGSIZE_SMALL = 0,
241 IMGSIZE_BIG
244 struct OneImageEntry
246 BitmapEx aScaled; ///< cached scaled image
247 BitmapEx aImage; ///< original un-scaled image
248 OUString aURL; ///< URL in case it is not loaded yet
251 struct ImageEntry
253 // if the image is set, it was embedded in some way,
254 // otherwise we use the associated URL to load on demand
256 // accessed in this order
257 OneImageEntry aSizeEntry[2];
258 ImageEntry() {}
259 void addImage(ImageSize eSize, const BitmapEx &rImage);
260 void addImage(ImageSize eSize, const OUString &rURL);
263 typedef std::unordered_map< OUString, ImageEntry > ImageManager;
264 typedef std::unordered_map< OUString, sal_uInt32 > StringToIndexMap;
265 typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars;
266 typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonNotebookBars;
267 typedef std::unordered_map< OUString, MergeToolbarInstructionContainer > ToolbarMergingInstructions;
268 typedef std::unordered_map< OUString, MergeNotebookBarInstructionContainer > NotebookBarMergingInstructions;
270 /*-****************************************************************************************************
271 @short return list of key names of our configuration management which represent our module tree
272 @descr These methods return the current list of key names! We need it to get needed values from our
273 configuration management!
274 @param "nCount" , returns count of menu entries for "new"
275 @return A list of configuration key names is returned.
276 *//*-*****************************************************************************************************/
278 void ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq );
279 void ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq );
280 void ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames );
281 bool ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq );
282 void ReadOfficeNotebookBarSet( AddonNotebookBars& rAddonOfficeNotebookBars, std::vector< OUString >& rAddonOfficeNotebookBarResNames );
283 bool ReadNotebookBarItemSet( const OUString& rNotebookBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeNotebookBarSeq );
285 void ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq );
286 void ReadImages( ImageManager& aImageManager );
287 void ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer );
288 void ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap );
289 void ReadNotebookBarMergeInstructions( NotebookBarMergingInstructions& rNotebookBarMergeMap );
290 void ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& rContainer );
292 void ReadMergeMenuData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu );
293 void ReadMergeToolbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems );
294 void ReadMergeNotebookBarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeNotebookBarItems );
295 void ReadMergeStatusbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeStatusbar );
296 bool ReadMenuItem( std::u16string_view aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu = false );
297 bool ReadPopupMenu( std::u16string_view aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu );
298 void AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu );
299 bool ReadToolBarItem( std::u16string_view aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem );
300 bool ReadNotebookBarItem( std::u16string_view aNotebookBarItemNodeName, Sequence< PropertyValue >& aNotebookBarItem );
302 bool ReadStatusBarItem( std::u16string_view aStatusbarItemNodeName, Sequence< PropertyValue >& aStatusbarItem );
303 std::unique_ptr<ImageEntry> ReadImageData( std::u16string_view aImagesNodeName );
304 void ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId );
305 BitmapEx ReadImageFromURL( const OUString& aURL );
306 bool HasAssociatedImages( const OUString& aURL );
307 void SubstituteVariables( OUString& aURL );
309 void ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
310 OUString GeneratePrefixURL();
312 Sequence< OUString > GetPropertyNamesMenuItem( std::u16string_view aPropertyRootNode )
313 const;
314 Sequence< OUString > GetPropertyNamesPopupMenu( std::u16string_view aPropertyRootNode )
315 const;
316 Sequence< OUString > GetPropertyNamesToolBarItem( std::u16string_view aPropertyRootNode )
317 const;
318 Sequence< OUString > GetPropertyNamesNotebookBarItem( std::u16string_view aPropertyRootNode ) const;
320 Sequence< OUString > GetPropertyNamesStatusbarItem( std::u16string_view aPropertyRootNode ) const;
321 Sequence< OUString > GetPropertyNamesImages( std::u16string_view aPropertyRootNode ) const;
322 bool CreateImageFromSequence( BitmapEx& rImage, Sequence< sal_Int8 >& rBitmapDataSeq ) const;
324 DECL_LINK(NotifyEvent, void*, void);
326 virtual void ImplCommit() override;
328 // private member
330 private:
331 sal_Int32 m_nRootAddonPopupMenuId;
332 OUString m_aPropNames[PROPERTYCOUNT_INDEX];
333 OUString m_aPropImagesNames[PROPERTYCOUNT_IMAGES];
334 OUString m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR];
335 OUString m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR];
336 OUString m_aPropMergeNotebookBarNames[PROPERTYCOUNT_MERGE_NOTEBOOKBAR];
337 OUString m_aPropMergeStatusbarNames[PROPERTYCOUNT_MERGE_STATUSBAR];
338 OUString m_aPathDelimiter;
339 OUString m_aRootAddonPopupMenuURLPrexfix;
340 Sequence< Sequence< PropertyValue > > m_aCachedMenuProperties;
341 Sequence< Sequence< PropertyValue > > m_aCachedMenuBarPartProperties;
342 AddonToolBars m_aCachedToolBarPartProperties;
343 AddonNotebookBars m_aCachedNotebookBarPartProperties;
344 std::vector< OUString > m_aCachedToolBarPartResourceNames;
345 std::vector< OUString > m_aCachedNotebookBarPartResourceNames;
346 Sequence< Sequence< PropertyValue > > m_aCachedHelpMenuProperties;
347 ImageManager m_aImageManager;
348 Sequence< Sequence< PropertyValue > > m_aEmptyAddonToolBar;
349 Sequence< Sequence< PropertyValue > > m_aEmptyAddonNotebookBar;
350 MergeMenuInstructionContainer m_aCachedMergeMenuInsContainer;
351 ToolbarMergingInstructions m_aCachedToolbarMergingInstructions;
352 NotebookBarMergingInstructions m_aCachedNotebookBarMergingInstructions;
353 MergeStatusbarInstructionContainer m_aCachedStatusbarMergingInstructions;
356 void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize, const BitmapEx& rImage)
358 aSizeEntry[static_cast<int>(eSize)].aImage = rImage;
361 void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize, const OUString &rURL)
363 aSizeEntry[static_cast<int>(eSize)].aURL = rURL;
366 // constructor
368 AddonsOptions_Impl::AddonsOptions_Impl()
369 // Init baseclasses first
370 : ConfigItem( ROOTNODE_ADDONMENU ),
371 m_nRootAddonPopupMenuId( 0 ),
372 m_aPathDelimiter( PATHDELIMITER ),
373 m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX_STR )
375 // initialize array with fixed property names
376 m_aPropNames[ INDEX_URL ] = PROPERTYNAME_URL;
377 m_aPropNames[ INDEX_TITLE ] = PROPERTYNAME_TITLE;
378 m_aPropNames[ INDEX_TARGET ] = PROPERTYNAME_TARGET;
379 m_aPropNames[ INDEX_IMAGEIDENTIFIER ] = PROPERTYNAME_IMAGEIDENTIFIER;
380 m_aPropNames[ INDEX_CONTEXT ] = PROPERTYNAME_CONTEXT;
381 m_aPropNames[ INDEX_SUBMENU ] = PROPERTYNAME_SUBMENU; // Submenu set!
382 m_aPropNames[ INDEX_CONTROLTYPE ] = "ControlType";
383 m_aPropNames[ INDEX_WIDTH ] = "Width";
384 m_aPropNames[ INDEX_ALIGN ] = "Alignment";
385 m_aPropNames[ INDEX_AUTOSIZE ] = "AutoSize";
386 m_aPropNames[ INDEX_OWNERDRAW ] = "OwnerDraw";
387 m_aPropNames[ INDEX_MANDATORY ] = "Mandatory";
388 m_aPropNames[ INDEX_STYLE ] = "Style";
390 // initialize array with fixed images property names
391 m_aPropImagesNames[ OFFSET_IMAGES_SMALL ] = "ImageSmall";
392 m_aPropImagesNames[ OFFSET_IMAGES_BIG ] = "ImageBig";
393 m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ] = "ImageSmallHC";
394 m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ] = "ImageBigHC";
395 m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ] = "ImageSmallURL";
396 m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ] = "ImageBigURL";
397 m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL ] = "ImageSmallHCURL";
398 m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ] = "ImageBigHCURL";
400 // initialize array with fixed merge menu property names
401 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] = "MergePoint";
402 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] = "MergeCommand";
403 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
404 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = "MergeFallback";
405 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] = "MergeContext";
406 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] = "MenuItems";
408 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] = "MergeToolBar";
409 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] = "MergePoint";
410 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] = "MergeCommand";
411 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
412 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] = "MergeFallback";
413 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] = "MergeContext";
414 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] = "ToolBarItems";
416 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR ] = "MergeNotebookBar";
417 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEPOINT ] = "MergePoint";
418 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND ] = "MergeCommand";
419 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
420 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK ] = "MergeFallback";
421 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT ] = "MergeContext";
422 m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS ] = "NotebookBarItems";
424 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ] = "MergePoint";
425 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ] = "MergeCommand";
426 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
427 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ] = "MergeFallback";
428 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ] = "MergeContext";
429 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ] = "StatusBarItems";
431 ReadConfigurationData();
433 // Enable notification mechanism of our baseclass.
434 // We need it to get information about changes outside these class on our used configuration keys!
435 Sequence<OUString> aNotifySeq { "AddonUI" };
436 EnableNotification( aNotifySeq );
439 // destructor
441 AddonsOptions_Impl::~AddonsOptions_Impl()
443 assert(!IsModified()); // should have been committed
446 void AddonsOptions_Impl::ReadConfigurationData()
448 // reset members to be read again from configuration
449 m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >();
450 m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >();
451 m_aCachedToolBarPartProperties = AddonToolBars();
452 m_aCachedNotebookBarPartProperties = AddonNotebookBars();
453 m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
454 m_aCachedToolBarPartResourceNames.clear();
455 m_aCachedNotebookBarPartResourceNames.clear();
456 m_aImageManager = ImageManager();
458 ReadAddonMenuSet( m_aCachedMenuProperties );
459 ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
460 ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
461 ReadOfficeNotebookBarSet( m_aCachedNotebookBarPartProperties, m_aCachedNotebookBarPartResourceNames );
463 ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
464 ReadImages( m_aImageManager );
466 m_aCachedMergeMenuInsContainer.clear();
467 m_aCachedToolbarMergingInstructions.clear();
468 m_aCachedNotebookBarMergingInstructions.clear();
469 m_aCachedStatusbarMergingInstructions.clear();
471 ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
472 ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
473 ReadNotebookBarMergeInstructions( m_aCachedNotebookBarMergingInstructions );
474 ReadStatusbarMergeInstructions( m_aCachedStatusbarMergingInstructions );
477 // public method
479 void AddonsOptions_Impl::Notify( const Sequence< OUString >& /*lPropertyNames*/ )
481 Application::PostUserEvent(LINK(this, AddonsOptions_Impl, NotifyEvent));
484 // public method
486 void AddonsOptions_Impl::ImplCommit()
488 SAL_WARN("fwk", "AddonsOptions_Impl::ImplCommit(): Not implemented yet!");
491 // public method
493 bool AddonsOptions_Impl::HasAddonsMenu() const
495 return m_aCachedMenuProperties.hasElements();
498 // public method
500 sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
502 return m_aCachedToolBarPartProperties.size();
505 // public method
507 sal_Int32 AddonsOptions_Impl::GetAddonsNotebookBarCount() const
509 return m_aCachedNotebookBarPartProperties.size();
512 // public method
514 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
516 if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() )
517 return m_aCachedToolBarPartProperties[nIndex];
518 else
519 return m_aEmptyAddonToolBar;
522 // public method
524 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
526 if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedNotebookBarPartProperties.size() )
527 return m_aCachedNotebookBarPartProperties[nIndex];
528 else
529 return m_aEmptyAddonNotebookBar;
532 // public method
534 OUString AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
536 if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
537 return m_aCachedToolBarPartResourceNames[nIndex];
538 else
539 return OUString();
542 // public method
544 OUString AddonsOptions_Impl::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
546 if ( nIndex < m_aCachedNotebookBarPartResourceNames.size() )
547 return m_aCachedNotebookBarPartResourceNames[nIndex];
548 else
549 return OUString();
552 // public method
554 bool AddonsOptions_Impl::GetMergeToolbarInstructions(
555 const OUString& rToolbarName,
556 MergeToolbarInstructionContainer& rToolbarInstructions ) const
558 ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName );
559 if ( pIter != m_aCachedToolbarMergingInstructions.end() )
561 rToolbarInstructions = pIter->second;
562 return true;
564 else
565 return false;
568 // public method
570 bool AddonsOptions_Impl::GetMergeNotebookBarInstructions(
571 const OUString& rNotebookBarName,
572 MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
574 NotebookBarMergingInstructions::const_iterator pIter = m_aCachedNotebookBarMergingInstructions.find( rNotebookBarName );
575 if ( pIter != m_aCachedNotebookBarMergingInstructions.end() )
577 rNotebookBarInstructions = pIter->second;
578 return true;
580 else
581 return false;
584 // public method
586 static BitmapEx ScaleImage( const BitmapEx &rImage, bool bBig )
588 Size aSize = ToolBox::GetDefaultImageSize(bBig ? ToolBoxButtonSize::Large : ToolBoxButtonSize::Small);
589 BitmapEx aScaleBmp(rImage);
590 SAL_INFO("fwk", "Addons: expensive scale image from "
591 << aScaleBmp.GetSizePixel() << " to " << aSize);
592 aScaleBmp.Scale(aSize, BmpScaleFlag::BestQuality);
593 return aScaleBmp;
596 BitmapEx AddonsOptions_Impl::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale )
598 BitmapEx aImage;
600 SAL_INFO("fwk", "Expensive: Addons GetImageFromURL " << aURL <<
601 " big " << (bBig?"big":"little") <<
602 " scale " << (bNoScale ? "noscale" : "scale"));
604 ImageManager::iterator pIter = m_aImageManager.find(aURL);
605 if ( pIter != m_aImageManager.end() )
607 ImageSize eSize = bBig ? IMGSIZE_BIG : IMGSIZE_SMALL;
608 int nIdx = static_cast<int>(eSize);
609 int nOtherIdx = nIdx ? 0 : 1;
611 OneImageEntry& rSizeEntry = pIter->second.aSizeEntry[nIdx];
612 OneImageEntry& rOtherEntry = pIter->second.aSizeEntry[nOtherIdx];
613 // actually read the image ...
614 if (rSizeEntry.aImage.IsEmpty())
615 rSizeEntry.aImage = ReadImageFromURL(rSizeEntry.aURL);
617 if (rSizeEntry.aImage.IsEmpty())
618 { // try the other size and scale it
619 aImage = ScaleImage(ReadImageFromURL(rOtherEntry.aURL), bBig);
620 rSizeEntry.aImage = aImage;
621 if (rSizeEntry.aImage.IsEmpty())
622 SAL_WARN("fwk", "failed to load addons image " << aURL);
625 // FIXME: bNoScale is not terribly meaningful or useful
627 if (aImage.IsEmpty() && bNoScale)
628 aImage = rSizeEntry.aImage;
630 if (aImage.IsEmpty() && !rSizeEntry.aScaled.IsEmpty())
631 aImage = rSizeEntry.aScaled;
633 else // scale to the correct size for the theme / toolbox
635 aImage = rSizeEntry.aImage;
636 if (aImage.IsEmpty()) // use and scale the other if one size is missing
637 aImage = rOtherEntry.aImage;
639 aImage = ScaleImage(aImage, bBig);
640 rSizeEntry.aScaled = aImage; // cache for next time
644 return aImage;
647 void AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
649 // Read the AddonMenu set and fill property sequences
650 OUString aAddonMenuNodeName( "AddonUI/AddonMenu" );
651 Sequence< OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
652 OUString aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter );
654 sal_uInt32 nCount = aAddonMenuNodeSeq.getLength();
655 sal_uInt32 nIndex = 0;
656 Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
657 auto pMenuItem = aMenuItem.getArray();
658 // Init the property value sequence
659 pMenuItem[ OFFSET_MENUITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
660 pMenuItem[ OFFSET_MENUITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
661 pMenuItem[ OFFSET_MENUITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ];
662 pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
663 pMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
664 pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU ]; // Submenu set!
666 for ( sal_uInt32 n = 0; n < nCount; n++ )
668 OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] );
670 // Read the MenuItem
671 if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) )
673 // Successfully read a menu item, append to our list
674 sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1;
675 rAddonMenuSeq.realloc( nMenuItemCount );
676 rAddonMenuSeq.getArray()[nIndex++] = aMenuItem;
681 void AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
683 // Read the AddonMenu set and fill property sequences
684 OUString aAddonHelpMenuNodeName( "AddonUI/OfficeHelp" );
685 Sequence< OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
686 OUString aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter );
688 sal_uInt32 nCount = aAddonHelpMenuNodeSeq.getLength();
689 sal_uInt32 nIndex = 0;
690 Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
691 auto pMenuItem = aMenuItem.getArray();
692 // Init the property value sequence
693 pMenuItem[ OFFSET_MENUITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
694 pMenuItem[ OFFSET_MENUITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
695 pMenuItem[ OFFSET_MENUITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ];
696 pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
697 pMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
698 pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU ]; // Submenu set!
700 for ( sal_uInt32 n = 0; n < nCount; n++ )
702 OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );
704 // Read the MenuItem
705 if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, true ) )
707 // Successfully read a menu item, append to our list
708 sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
709 rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
710 rAddonOfficeHelpMenuSeq.getArray()[nIndex++] = aMenuItem;
715 void AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
717 // Read the OfficeMenuBar set and fill property sequences
718 OUString aAddonMenuBarNodeName( "AddonUI/OfficeMenuBar" );
719 Sequence< OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
720 OUString aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter );
722 sal_uInt32 nCount = aAddonMenuBarNodeSeq.getLength();
723 sal_uInt32 nIndex = 0;
724 Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU );
725 auto pPopupMenu = aPopupMenu.getArray();
726 // Init the property value sequence
727 pPopupMenu[ OFFSET_POPUPMENU_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
728 pPopupMenu[ OFFSET_POPUPMENU_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT];
729 pPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU];
730 pPopupMenu[ OFFSET_POPUPMENU_URL ].Name = m_aPropNames[ INDEX_URL ];
732 StringToIndexMap aTitleToIndexMap;
733 auto pAddonOfficeMenuBarSeq = rAddonOfficeMenuBarSeq.getArray();
734 for ( sal_uInt32 n = 0; n < nCount; n++ )
736 OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );
738 // Read the MenuItem
739 if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
741 // Successfully read a popup menu, append to our list
742 OUString aPopupTitle;
743 if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle )
745 StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle );
746 if ( pIter != aTitleToIndexMap.end() )
748 // title already there => concat both popup menus
749 Sequence< PropertyValue >& rOldPopupMenu = pAddonOfficeMenuBarSeq[pIter->second];
750 AppendPopupMenu( rOldPopupMenu, aPopupMenu );
752 else
754 // not found
755 sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1;
756 rAddonOfficeMenuBarSeq.realloc( nMenuItemCount );
757 pAddonOfficeMenuBarSeq = rAddonOfficeMenuBarSeq.getArray();
758 pAddonOfficeMenuBarSeq[nIndex] = aPopupMenu;
759 aTitleToIndexMap.emplace( aPopupTitle, nIndex );
760 ++nIndex;
767 void AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames )
769 // Read the OfficeToolBar set and fill property sequences
770 OUString aAddonToolBarNodeName( "AddonUI/OfficeToolBar" );
771 Sequence< OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
772 OUString aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );
774 sal_uInt32 nCount = aAddonToolBarNodeSeq.getLength();
776 for ( sal_uInt32 n = 0; n < nCount; n++ )
778 OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
779 rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
780 rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
781 ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
785 bool AddonsOptions_Impl::ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
787 sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength();
788 OUString aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
789 Sequence< OUString > aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName );
790 Sequence< PropertyValue > aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
791 auto pToolBarItem = aToolBarItem.getArray();
792 // Init the property value sequence
793 pToolBarItem[ OFFSET_TOOLBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
794 pToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
795 pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
796 pToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ];
797 pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
798 pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Name = m_aPropNames[ INDEX_CONTROLTYPE ];
799 pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Name = m_aPropNames[ INDEX_WIDTH ];
801 sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength();
802 for ( sal_uInt32 n = 0; n < nCount; n++ )
804 OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );
806 // Read the ToolBarItem
807 if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
809 // Successfully read a toolbar item, append to our list
810 sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
811 rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
812 rAddonOfficeToolBarSeq.getArray()[nAddonCount] = aToolBarItem;
816 return ( o3tl::make_unsigned(rAddonOfficeToolBarSeq.getLength()) > nToolBarItemCount );
819 void AddonsOptions_Impl::ReadOfficeNotebookBarSet(
820 AddonNotebookBars& rAddonOfficeNotebookBars,
821 std::vector<OUString>& rAddonOfficeNotebookBarResNames)
823 // Read the OfficeToolBar set and fill property sequences
824 OUString aAddonNotebookBarNodeName("AddonUI/OfficeNotebookBar");
825 Sequence<OUString> aAddonNotebookBarNodeSeq = GetNodeNames(aAddonNotebookBarNodeName);
826 OUString aAddonNotebookBarNode(aAddonNotebookBarNodeName + m_aPathDelimiter);
828 sal_uInt32 nCount = aAddonNotebookBarNodeSeq.getLength();
830 for (sal_uInt32 n = 0; n < nCount; n++)
832 OUString aNotebookBarItemNode(aAddonNotebookBarNode + aAddonNotebookBarNodeSeq[n]);
833 rAddonOfficeNotebookBarResNames.push_back(aAddonNotebookBarNodeSeq[n]);
834 rAddonOfficeNotebookBars.push_back(m_aEmptyAddonNotebookBar);
835 ReadNotebookBarItemSet(aNotebookBarItemNode, rAddonOfficeNotebookBars[n]);
839 bool AddonsOptions_Impl::ReadNotebookBarItemSet(
840 const OUString& rNotebookBarItemSetNodeName,
841 Sequence<Sequence<PropertyValue>>& rAddonOfficeNotebookBarSeq)
843 sal_uInt32 nNotebookBarItemCount = rAddonOfficeNotebookBarSeq.getLength();
844 OUString aAddonNotebookBarItemSetNode(rNotebookBarItemSetNodeName + m_aPathDelimiter);
845 Sequence<OUString> aAddonNotebookBarItemSetNodeSeq = GetNodeNames(rNotebookBarItemSetNodeName);
846 Sequence<PropertyValue> aNotebookBarItem(PROPERTYCOUNT_NOTEBOOKBARITEM);
847 auto pNotebookBarItem = aNotebookBarItem.getArray();
848 // Init the property value sequence
849 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_URL].Name = m_aPropNames[INDEX_URL];
850 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TITLE].Name = m_aPropNames[INDEX_TITLE];
851 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER].Name
852 = m_aPropNames[INDEX_IMAGEIDENTIFIER];
853 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TARGET].Name = m_aPropNames[INDEX_TARGET];
854 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTEXT].Name = m_aPropNames[INDEX_CONTEXT];
855 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTROLTYPE].Name = m_aPropNames[INDEX_CONTROLTYPE];
856 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_WIDTH].Name = m_aPropNames[INDEX_WIDTH];
857 pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_STYLE].Name = m_aPropNames[INDEX_STYLE];
859 sal_uInt32 nCount = aAddonNotebookBarItemSetNodeSeq.getLength();
860 for (sal_uInt32 n = 0; n < nCount; n++)
862 OUString aNotebookBarItemNode(aAddonNotebookBarItemSetNode
863 + aAddonNotebookBarItemSetNodeSeq[n]);
864 // Read the NotebookBarItem
865 if (ReadNotebookBarItem(aNotebookBarItemNode, aNotebookBarItem))
867 // Successfully read a toolbar item, append to our list
868 sal_uInt32 nAddonCount = rAddonOfficeNotebookBarSeq.getLength();
869 rAddonOfficeNotebookBarSeq.realloc(nAddonCount + 1);
870 rAddonOfficeNotebookBarSeq.getArray()[nAddonCount] = aNotebookBarItem;
874 return (o3tl::make_unsigned(rAddonOfficeNotebookBarSeq.getLength())
875 > nNotebookBarItemCount);
878 void AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
880 // Read the user-defined Images set and fill image manager
881 OUString aAddonImagesNodeName( "AddonUI/Images" );
882 Sequence< OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
883 OUString aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );
885 sal_uInt32 nCount = aAddonImagesNodeSeq.getLength();
887 // Init the property value sequence
888 OUString aURL;
890 for ( sal_uInt32 n = 0; n < nCount; n++ )
892 OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );
894 // Create sequence for data access
895 Sequence< OUString > aAddonImageItemNodePropNames = { aImagesItemNode +
896 m_aPathDelimiter +
897 m_aPropNames[ OFFSET_MENUITEM_URL ] };
899 Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );
901 // An user-defined image entry must have a URL. As "ImageIdentifier" has a higher priority
902 // we also check if we already have an images association.
903 if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
904 !aURL.isEmpty() &&
905 !HasAssociatedImages( aURL ))
907 OUString aImagesUserDefinedItemNode = aImagesItemNode +
908 m_aPathDelimiter +
909 IMAGES_NODENAME +
910 m_aPathDelimiter;
912 // Read a user-defined images data
913 std::unique_ptr<ImageEntry> pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
914 if ( pImageEntry )
916 // Successfully read a user-defined images item, put it into our image manager
917 aImageManager.emplace( aURL, std::move(*pImageEntry) );
923 OUString AddonsOptions_Impl::GeneratePrefixURL()
925 // Create a unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu.
926 return m_aRootAddonPopupMenuURLPrexfix + OUString::number( ++m_nRootAddonPopupMenuId );
929 void AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer )
931 static constexpr OUString aMenuMergeRootName( u"AddonUI/OfficeMenuBarMerging/"_ustr );
933 Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );
935 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
937 // Init the property value sequence
938 Sequence< OUString > aNodePropNames( 5 );
939 auto pNodePropNames = aNodePropNames.getArray();
941 for ( sal_uInt32 i = 0; i < nCount; i++ )
943 OUString aMergeAddonInstructions( aMenuMergeRootName + aAddonMergeNodesSeq[i] );
945 Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
946 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
948 for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
950 OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
951 m_aPathDelimiter +
952 aAddonInstMergeNodesSeq[j] +
953 m_aPathDelimiter;
955 // Create sequence for data access
956 pNodePropNames[0] = aMergeAddonInstructionBase +
957 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ];
959 pNodePropNames[1] = aMergeAddonInstructionBase +
960 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ];
962 pNodePropNames[2] = aMergeAddonInstructionBase +
963 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ];
965 pNodePropNames[3] = aMergeAddonInstructionBase +
966 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ];
968 pNodePropNames[4] = aMergeAddonInstructionBase +
969 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ];
971 Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
973 MergeMenuInstruction aMergeMenuInstruction;
974 aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint;
975 aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand;
976 aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter;
977 aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback;
978 aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext;
980 ReadMergeMenuData( aMergeAddonInstructionBase, aMergeMenuInstruction.aMergeMenu );
982 aContainer.push_back( aMergeMenuInstruction );
987 void AddonsOptions_Impl::ReadMergeMenuData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
989 OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );
991 Sequence< OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
992 aMergeMenuBaseNode += m_aPathDelimiter;
994 // extend the node names to have full path strings
995 for ( OUString& rName : asNonConstRange(aSubMenuNodeNames) )
996 rName = aMergeMenuBaseNode + rName;
998 ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
1001 void AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions )
1003 static constexpr OUString aToolbarMergeRootName( u"AddonUI/OfficeToolbarMerging/"_ustr );
1005 Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
1006 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
1008 // Init the property value sequence
1009 Sequence< OUString > aNodePropNames( 6 );
1010 auto pNodePropNames = aNodePropNames.getArray();
1012 for ( sal_uInt32 i = 0; i < nCount; i++ )
1014 OUString aMergeAddonInstructions( aToolbarMergeRootName + aAddonMergeNodesSeq[i] );
1016 Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
1017 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
1019 for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
1021 OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
1022 m_aPathDelimiter +
1023 aAddonInstMergeNodesSeq[j] +
1024 m_aPathDelimiter;
1026 // Create sequence for data access
1027 pNodePropNames[0] = aMergeAddonInstructionBase +
1028 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ];
1030 pNodePropNames[1] = aMergeAddonInstructionBase +
1031 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ];
1033 pNodePropNames[2] = aMergeAddonInstructionBase +
1034 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ];
1036 pNodePropNames[3] = aMergeAddonInstructionBase +
1037 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ];
1039 pNodePropNames[4] = aMergeAddonInstructionBase +
1040 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ];
1042 pNodePropNames[5] = aMergeAddonInstructionBase +
1043 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ];
1045 Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
1047 MergeToolbarInstruction aMergeToolbarInstruction;
1048 aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar;
1049 aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint;
1050 aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand;
1051 aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter;
1052 aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback;
1053 aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext;
1055 ReadMergeToolbarData( aMergeAddonInstructionBase,
1056 aMergeToolbarInstruction.aMergeToolbarItems );
1058 MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ];
1059 rVector.push_back( aMergeToolbarInstruction );
1064 void AddonsOptions_Impl::ReadMergeToolbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
1066 OUString aMergeToolbarBaseNode = aMergeAddonInstructionBase +
1067 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ];
1069 ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
1072 void AddonsOptions_Impl::ReadNotebookBarMergeInstructions(
1073 NotebookBarMergingInstructions& rCachedNotebookBarMergingInstructions)
1075 static constexpr OUString aNotebookBarMergeRootName(u"AddonUI/OfficeNotebookBarMerging/"_ustr);
1077 Sequence<OUString> aAddonMergeNodesSeq = GetNodeNames(aNotebookBarMergeRootName);
1078 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
1080 // Init the property value sequence
1081 Sequence<OUString> aNodePropNames(6);
1082 auto pNodePropNames = aNodePropNames.getArray();
1084 for (sal_uInt32 i = 0; i < nCount; i++)
1086 OUString aMergeAddonInstructions(aNotebookBarMergeRootName + aAddonMergeNodesSeq[i]);
1088 Sequence<OUString> aAddonInstMergeNodesSeq = GetNodeNames(aMergeAddonInstructions);
1089 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
1091 for (sal_uInt32 j = 0; j < nCountAddons; j++)
1093 OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
1094 m_aPathDelimiter +
1095 aAddonInstMergeNodesSeq[j] +
1096 m_aPathDelimiter;
1098 // Create sequence for data access
1099 pNodePropNames[0] = aMergeAddonInstructionBase +
1100 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR];
1102 pNodePropNames[1] = aMergeAddonInstructionBase +
1103 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEPOINT];
1105 pNodePropNames[2] = aMergeAddonInstructionBase +
1106 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND];
1108 pNodePropNames[3] = aMergeAddonInstructionBase +
1109 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER];
1111 pNodePropNames[4] = aMergeAddonInstructionBase +
1112 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK];
1114 pNodePropNames[5] = aMergeAddonInstructionBase +
1115 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT];
1117 Sequence<Any> aNodePropValues = GetProperties(aNodePropNames);
1119 MergeNotebookBarInstruction aMergeNotebookBarInstruction;
1120 aNodePropValues[0] >>= aMergeNotebookBarInstruction.aMergeNotebookBar;
1121 aNodePropValues[1] >>= aMergeNotebookBarInstruction.aMergePoint;
1122 aNodePropValues[2] >>= aMergeNotebookBarInstruction.aMergeCommand;
1123 aNodePropValues[3] >>= aMergeNotebookBarInstruction.aMergeCommandParameter;
1124 aNodePropValues[4] >>= aMergeNotebookBarInstruction.aMergeFallback;
1125 aNodePropValues[5] >>= aMergeNotebookBarInstruction.aMergeContext;
1127 ReadMergeNotebookBarData(aMergeAddonInstructionBase,
1128 aMergeNotebookBarInstruction.aMergeNotebookBarItems);
1130 MergeNotebookBarInstructionContainer& rVector
1131 = rCachedNotebookBarMergingInstructions[aMergeNotebookBarInstruction
1132 .aMergeNotebookBar];
1133 rVector.push_back(aMergeNotebookBarInstruction);
1138 void AddonsOptions_Impl::ReadMergeNotebookBarData(
1139 std::u16string_view aMergeAddonInstructionBase,
1140 Sequence<Sequence<PropertyValue>>& rMergeNotebookBarItems)
1142 OUString aMergeNotebookBarBaseNode = aMergeAddonInstructionBase +
1143 m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS];
1145 ReadNotebookBarItemSet(aMergeNotebookBarBaseNode, rMergeNotebookBarItems);
1148 void AddonsOptions_Impl::ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& aContainer )
1150 static constexpr OUString aStatusbarMergeRootName( u"AddonUI/OfficeStatusbarMerging/"_ustr );
1152 Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aStatusbarMergeRootName );
1153 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
1155 Sequence< OUString > aNodePropNames( 5 );
1156 auto pNodePropNames = aNodePropNames.getArray();
1158 for ( sal_uInt32 i = 0; i < nCount; i++ )
1160 OUString aMergeAddonInstructions( aStatusbarMergeRootName + aAddonMergeNodesSeq[i] );
1162 Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
1163 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
1165 for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
1167 OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
1168 m_aPathDelimiter +
1169 aAddonInstMergeNodesSeq[j] +
1170 m_aPathDelimiter;
1172 // Create sequence for data access
1173 pNodePropNames[0] = aMergeAddonInstructionBase +
1174 m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ];
1176 pNodePropNames[1] = aMergeAddonInstructionBase +
1177 m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ];
1179 pNodePropNames[2] = aMergeAddonInstructionBase +
1180 m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ];
1182 pNodePropNames[3] = aMergeAddonInstructionBase +
1183 m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ];
1185 pNodePropNames[4] = aMergeAddonInstructionBase +
1186 m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ];
1188 Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
1190 MergeStatusbarInstruction aMergeStatusbarInstruction;
1191 aNodePropValues[0] >>= aMergeStatusbarInstruction.aMergePoint;
1192 aNodePropValues[1] >>= aMergeStatusbarInstruction.aMergeCommand;
1193 aNodePropValues[2] >>= aMergeStatusbarInstruction.aMergeCommandParameter;
1194 // aNodePropValues[3] >>= aMergeStatusbarInstruction.aMergeFallback;
1195 aNodePropValues[4] >>= aMergeStatusbarInstruction.aMergeContext;
1197 ReadMergeStatusbarData( aMergeAddonInstructionBase,
1198 aMergeStatusbarInstruction.aMergeStatusbarItems );
1200 aContainer.push_back( aMergeStatusbarInstruction );
1205 void AddonsOptions_Impl::ReadMergeStatusbarData(
1206 std::u16string_view aMergeAddonInstructionBase,
1207 Sequence< Sequence< PropertyValue > >& rMergeStatusbarItems )
1209 OUString aMergeStatusbarBaseNode = aMergeAddonInstructionBase +
1210 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ];
1212 OUString aAddonStatusbarItemSetNode( aMergeStatusbarBaseNode + m_aPathDelimiter );
1213 Sequence< OUString > aAddonStatusbarItemSetNodeSeq = GetNodeNames( aMergeStatusbarBaseNode );
1215 Sequence< PropertyValue > aStatusbarItem( PROPERTYCOUNT_STATUSBARITEM );
1216 auto pStatusbarItem = aStatusbarItem.getArray();
1217 pStatusbarItem[ OFFSET_STATUSBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
1218 pStatusbarItem[ OFFSET_STATUSBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
1219 pStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
1220 pStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN ].Name = m_aPropNames[ INDEX_ALIGN ];
1221 pStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE ].Name = m_aPropNames[ INDEX_AUTOSIZE ];
1222 pStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Name = m_aPropNames[ INDEX_OWNERDRAW ];
1223 pStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY ].Name = m_aPropNames[ INDEX_MANDATORY ];
1224 pStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Name = m_aPropNames[ INDEX_WIDTH ];
1226 sal_uInt32 nCount = aAddonStatusbarItemSetNodeSeq.getLength();
1227 for ( sal_uInt32 n = 0; n < nCount; n++ )
1229 OUString aStatusbarItemNode( aAddonStatusbarItemSetNode + aAddonStatusbarItemSetNodeSeq[n] );
1231 if ( ReadStatusBarItem( aStatusbarItemNode, aStatusbarItem ) )
1233 sal_uInt32 nAddonCount = rMergeStatusbarItems.getLength();
1234 rMergeStatusbarItems.realloc( nAddonCount+1 );
1235 rMergeStatusbarItems.getArray()[nAddonCount] = aStatusbarItem;
1240 bool AddonsOptions_Impl::ReadStatusBarItem(
1241 std::u16string_view aStatusarItemNodeName,
1242 Sequence< PropertyValue >& aStatusbarItem )
1244 bool bResult( false );
1245 OUString aURL;
1246 OUString aAddonStatusbarItemTreeNode( aStatusarItemNodeName + m_aPathDelimiter );
1248 Sequence< Any > aStatusbarItemNodePropValues = GetProperties( GetPropertyNamesStatusbarItem( aAddonStatusbarItemTreeNode ) );
1250 // Command URL is required
1251 if (( aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
1253 auto pStatusbarItem = aStatusbarItem.getArray();
1254 pStatusbarItem[ OFFSET_STATUSBARITEM_URL ].Value <<= aURL;
1255 pStatusbarItem[ OFFSET_STATUSBARITEM_TITLE ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_TITLE ];
1256 pStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_CONTEXT ];
1257 pStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_ALIGN ];
1258 pStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_AUTOSIZE ];
1259 pStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_OWNERDRAW ];
1260 pStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_MANDATORY ];
1262 // Configuration uses hyper for long. Therefore transform into sal_Int32
1263 sal_Int64 nValue( 0 );
1264 aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_WIDTH ] >>= nValue;
1265 pStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
1267 bResult = true;
1270 return bResult;
1273 bool AddonsOptions_Impl::ReadMenuItem( std::u16string_view aMenuNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu )
1275 bool bResult = false;
1276 OUString aStrValue;
1277 OUString aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );
1279 Sequence< Any > aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
1280 if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && !aStrValue.isEmpty() )
1282 auto pMenuItem = aMenuItem.getArray();
1283 pMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;
1285 OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1286 Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1287 if ( aRootSubMenuNodeNames.hasElements() && !bIgnoreSubMenu )
1289 // Set a unique prefixed Add-On popup menu URL so it can be identified later
1290 OUString aPopupMenuURL = GeneratePrefixURL();
1291 OUString aPopupMenuImageId;
1293 aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId;
1294 ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId );
1296 // A popup menu must have a title and can have a URL and ImageIdentifier
1297 // Set the other property values to empty
1298 pMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aPopupMenuURL;
1299 pMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= OUString();
1300 pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= aPopupMenuImageId;
1301 pMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1303 // Continue to read the sub menu nodes
1304 Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1305 OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1306 for ( OUString& rName : asNonConstRange(aRootSubMenuNodeNames) )
1307 rName = aSubMenuRootNodeName + rName;
1308 ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1309 pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
1310 bResult = true;
1312 else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && !aStrValue.isEmpty() )
1314 // A simple menu item => read the other properties;
1315 OUString aMenuImageId;
1317 aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId;
1318 ReadAndAssociateImages( aStrValue, aMenuImageId );
1320 pMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue;
1321 pMenuItem[ OFFSET_MENUITEM_TARGET ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET ];
1322 pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= aMenuImageId;
1323 pMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1324 pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1326 bResult = true;
1329 else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) &&
1330 aStrValue == SEPARATOR_URL )
1332 auto pMenuItem = aMenuItem.getArray();
1334 // Separator
1335 pMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue;
1336 pMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= OUString();
1337 pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= OUString();
1338 pMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= OUString();
1339 pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1340 bResult = true;
1343 return bResult;
1346 bool AddonsOptions_Impl::ReadPopupMenu( std::u16string_view aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu )
1348 bool bResult = false;
1349 OUString aStrValue;
1350 OUString aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter );
1352 Sequence< Any > aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) );
1353 if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) &&
1354 !aStrValue.isEmpty() )
1356 auto pPopupMenu = aPopupMenu.getArray();
1357 pPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue;
1359 OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1360 Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1361 if ( aRootSubMenuNodeNames.hasElements() )
1363 // A top-level popup menu needs a title
1364 // Set a unique prefixed Add-On popup menu URL so it can be identified later
1365 OUString aPopupMenuURL = GeneratePrefixURL();
1367 pPopupMenu[ OFFSET_POPUPMENU_URL ].Value <<= aPopupMenuURL;
1368 pPopupMenu[ OFFSET_POPUPMENU_CONTEXT ].Value = aPopupMenuNodePropValues[ OFFSET_POPUPMENU_CONTEXT ];
1370 // Continue to read the sub menu nodes
1371 Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1372 OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1373 for ( OUString& rName : asNonConstRange(aRootSubMenuNodeNames) )
1374 rName = aSubMenuRootNodeName + rName;
1375 ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1376 pPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq;
1377 bResult = true;
1381 return bResult;
1384 void AddonsOptions_Impl::AppendPopupMenu( Sequence< PropertyValue >& rTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu )
1386 Sequence< Sequence< PropertyValue > > aTargetSubMenuSeq;
1387 Sequence< Sequence< PropertyValue > > aSourceSubMenuSeq;
1389 if (( rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aTargetSubMenuSeq ) &&
1390 ( rSourcePopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aSourceSubMenuSeq ))
1392 sal_uInt32 nIndex = aTargetSubMenuSeq.getLength();
1393 aTargetSubMenuSeq.realloc( nIndex + aSourceSubMenuSeq.getLength() );
1394 auto pTargetSubMenuSeq = aTargetSubMenuSeq.getArray();
1395 for ( Sequence<PropertyValue> const & rSeq : std::as_const(aSourceSubMenuSeq) )
1396 pTargetSubMenuSeq[nIndex++] = rSeq;
1397 rTargetPopupMenu.getArray()[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq;
1401 bool AddonsOptions_Impl::ReadToolBarItem( std::u16string_view aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem )
1403 bool bResult = false;
1404 OUString aURL;
1405 OUString aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter );
1407 Sequence< Any > aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) );
1409 // A toolbar item must have a command URL
1410 if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
1412 OUString aTitle;
1413 if ( aURL == SEPARATOR_URL )
1415 auto pToolBarItem = aToolBarItem.getArray();
1417 // A separator toolbar item only needs a URL
1418 pToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL;
1419 pToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= OUString();
1420 pToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= OUString();
1421 pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= OUString();
1422 pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= OUString();
1423 pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value <<= OUString();
1424 pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( 0 );
1426 bResult = true;
1428 else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
1430 auto pToolBarItem = aToolBarItem.getArray();
1432 // A normal toolbar item must also have title => read the other properties;
1433 OUString aImageId;
1435 // Try to map a user-defined image URL to our internal private image URL
1436 aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1437 ReadAndAssociateImages( aURL, aImageId );
1439 pToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL;
1440 pToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= aTitle;
1441 pToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value = aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TARGET ];
1442 pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= aImageId;
1443 pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value = aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTEXT ];
1444 pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value = aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTROLTYPE ];
1446 // Configuration uses hyper for long. Therefore transform into sal_Int32
1447 sal_Int64 nValue( 0 );
1448 aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_WIDTH ] >>= nValue;
1449 pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
1451 bResult = true;
1455 return bResult;
1458 bool AddonsOptions_Impl::ReadNotebookBarItem( std::u16string_view aNotebookBarItemNodeName, Sequence< PropertyValue >& aNotebookBarItem )
1460 bool bResult = false;
1461 OUString aURL;
1462 OUString aAddonNotebookBarItemTreeNode( aNotebookBarItemNodeName + m_aPathDelimiter );
1464 Sequence< Any > aNotebookBarItemNodePropValues = GetProperties( GetPropertyNamesNotebookBarItem( aAddonNotebookBarItemTreeNode ) );
1466 // A toolbar item must have a command URL
1467 if (( aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
1469 OUString aTitle;
1470 if ( aURL == SEPARATOR_URL )
1472 auto pNotebookBarItem = aNotebookBarItem.getArray();
1474 // A separator toolbar item only needs a URL
1475 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_URL ].Value <<= aURL;
1476 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TITLE ].Value <<= OUString();
1477 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TARGET ].Value <<= OUString();
1478 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ].Value <<= OUString();
1479 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTEXT ].Value <<= OUString();
1480 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ].Value <<= OUString();
1481 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_WIDTH ].Value <<= sal_Int32( 0 );
1482 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_STYLE ].Value <<= OUString();
1484 bResult = true;
1486 else if (( aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
1488 auto pNotebookBarItem = aNotebookBarItem.getArray();
1490 // A normal toolbar item must also have title => read the other properties;
1491 OUString aImageId;
1493 // Try to map a user-defined image URL to our internal private image URL
1494 aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1495 ReadAndAssociateImages( aURL, aImageId );
1497 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_URL ].Value <<= aURL;
1498 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TITLE ].Value <<= aTitle;
1499 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TARGET ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_TARGET ];
1500 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ].Value <<= aImageId;
1501 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTEXT ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_CONTEXT ];
1502 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ];
1504 // Configuration uses hyper for long. Therefore transform into sal_Int32
1505 sal_Int64 nValue( 0 );
1506 aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_WIDTH ] >>= nValue;
1507 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
1508 pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_STYLE ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_STYLE ];
1510 bResult = true;
1514 return bResult;
1517 void AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenuSeq )
1519 Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
1520 auto pMenuItem = aMenuItem.getArray();
1522 // Init the property value sequence
1523 pMenuItem[ OFFSET_MENUITEM_URL ].Name = PROPERTYNAME_URL;
1524 pMenuItem[ OFFSET_MENUITEM_TITLE ].Name = PROPERTYNAME_TITLE;
1525 pMenuItem[ OFFSET_MENUITEM_TARGET ].Name = PROPERTYNAME_TARGET;
1526 pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = PROPERTYNAME_IMAGEIDENTIFIER;
1527 pMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = PROPERTYNAME_CONTEXT;
1528 pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = PROPERTYNAME_SUBMENU; // Submenu set!
1530 sal_uInt32 nIndex = 0;
1531 sal_uInt32 nCount = aSubMenuNodeNames.getLength();
1532 for ( sal_uInt32 n = 0; n < nCount; n++ )
1534 if ( ReadMenuItem( aSubMenuNodeNames[n], aMenuItem ))
1536 sal_uInt32 nSubMenuCount = rSubMenuSeq.getLength() + 1;
1537 rSubMenuSeq.realloc( nSubMenuCount );
1538 rSubMenuSeq.getArray()[nIndex++] = aMenuItem;
1543 bool AddonsOptions_Impl::HasAssociatedImages( const OUString& aURL )
1545 // FIXME: potentially this is not so useful in a world of delayed image loading
1546 ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
1547 return ( pIter != m_aImageManager.end() );
1550 void AddonsOptions_Impl::SubstituteVariables( OUString& aURL )
1552 aURL = comphelper::getExpandedUri(
1553 comphelper::getProcessComponentContext(), aURL);
1556 BitmapEx AddonsOptions_Impl::ReadImageFromURL(const OUString& aImageURL)
1558 BitmapEx aImage;
1560 std::unique_ptr<SvStream> pStream = UcbStreamHelper::CreateStream( aImageURL, StreamMode::STD_READ );
1561 if ( pStream && ( pStream->GetErrorCode() == ERRCODE_NONE ))
1563 // Use graphic class to also support more graphic formats (bmp,png,...)
1564 Graphic aGraphic;
1566 GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
1567 rGF.ImportGraphic( aGraphic, u"", *pStream );
1569 BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
1571 Size aBmpSize = aBitmapEx.GetSizePixel();
1572 if ( !aBmpSize.IsEmpty() )
1574 // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1575 if( !aBitmapEx.IsAlpha() )
1576 aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1578 aImage = aBitmapEx;
1582 return aImage;
1585 void AddonsOptions_Impl::ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId )
1587 if ( aImageId.isEmpty() )
1588 return;
1590 ImageEntry aImageEntry;
1591 OUString aImageURL( aImageId );
1593 SubstituteVariables( aImageURL );
1595 // Loop to create the two possible image names and try to read the bitmap files
1596 static const char* aExtArray[] = { "_16", "_26" };
1597 for ( size_t i = 0; i < std::size(aExtArray); i++ )
1599 OUStringBuffer aFileURL( aImageURL );
1600 aFileURL.appendAscii( aExtArray[i] );
1601 aFileURL.append( ".bmp" );
1603 aImageEntry.addImage( !i ? IMGSIZE_SMALL : IMGSIZE_BIG, aFileURL.makeStringAndClear() );
1606 m_aImageManager.emplace( aURL, aImageEntry );
1609 std::unique_ptr<AddonsOptions_Impl::ImageEntry> AddonsOptions_Impl::ReadImageData( std::u16string_view aImagesNodeName )
1611 Sequence< OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName );
1612 Sequence< Any > aPropertyData;
1613 Sequence< sal_Int8 > aImageDataSeq;
1614 OUString aImageURL;
1616 std::unique_ptr<ImageEntry> pEntry;
1618 // It is possible to use both forms (embedded image data and URLs to external bitmap files) at the
1619 // same time. Embedded image data has a higher priority.
1620 aPropertyData = GetProperties( aImageDataNodeNames );
1621 for ( int i = 0; i < PROPERTYCOUNT_IMAGES; i++ )
1623 if ( i < PROPERTYCOUNT_EMBEDDED_IMAGES )
1625 // Extract image data from the embedded hex binary sequence
1626 BitmapEx aImage;
1627 if (( aPropertyData[i] >>= aImageDataSeq ) &&
1628 aImageDataSeq.hasElements() &&
1629 ( CreateImageFromSequence( aImage, aImageDataSeq ) ) )
1631 if ( !pEntry )
1632 pEntry.reset(new ImageEntry);
1633 pEntry->addImage(i == OFFSET_IMAGES_SMALL ? IMGSIZE_SMALL : IMGSIZE_BIG, aImage);
1636 else if ( i == OFFSET_IMAGES_SMALL_URL || i == OFFSET_IMAGES_BIG_URL )
1638 if(!pEntry)
1639 pEntry.reset(new ImageEntry());
1641 // Retrieve image data from an external bitmap file. Make sure that embedded image data
1642 // has a higher priority.
1643 if (aPropertyData[i] >>= aImageURL)
1645 SubstituteVariables(aImageURL);
1646 pEntry->addImage(i == OFFSET_IMAGES_SMALL_URL ? IMGSIZE_SMALL : IMGSIZE_BIG, aImageURL);
1651 return pEntry;
1654 bool AddonsOptions_Impl::CreateImageFromSequence( BitmapEx& rImage, Sequence< sal_Int8 >& rBitmapDataSeq ) const
1656 bool bResult = false;
1658 if ( rBitmapDataSeq.hasElements() )
1660 SvMemoryStream aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), StreamMode::STD_READ );
1662 ReadDIBBitmapEx(rImage, aMemStream);
1664 if( !rImage.IsAlpha() )
1666 // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1667 rImage = BitmapEx( rImage.GetBitmap(), COL_LIGHTMAGENTA );
1670 bResult = true;
1673 return bResult;
1676 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( std::u16string_view aPropertyRootNode ) const
1678 Sequence< OUString > lResult( PROPERTYCOUNT_MENUITEM );
1679 auto plResult = lResult.getArray();
1681 // Create property names dependent from the root node name
1682 plResult[OFFSET_MENUITEM_URL] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
1683 plResult[OFFSET_MENUITEM_TITLE] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1684 plResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ];
1685 plResult[OFFSET_MENUITEM_TARGET] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
1686 plResult[OFFSET_MENUITEM_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1687 plResult[OFFSET_MENUITEM_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ];
1689 return lResult;
1692 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( std::u16string_view aPropertyRootNode ) const
1694 // The URL is automatically set and not read from the configuration.
1695 Sequence< OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 );
1696 auto plResult = lResult.getArray();
1698 // Create property names dependent from the root node name
1699 plResult[OFFSET_POPUPMENU_TITLE] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1700 plResult[OFFSET_POPUPMENU_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1701 plResult[OFFSET_POPUPMENU_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ];
1703 return lResult;
1706 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( std::u16string_view aPropertyRootNode ) const
1708 Sequence< OUString > lResult( PROPERTYCOUNT_TOOLBARITEM );
1709 auto plResult = lResult.getArray();
1711 // Create property names dependent from the root node name
1712 plResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
1713 plResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1714 plResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
1715 plResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
1716 plResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1717 plResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE ];
1718 plResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ];
1720 return lResult;
1723 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesNotebookBarItem( std::u16string_view aPropertyRootNode ) const
1725 Sequence< OUString > lResult( PROPERTYCOUNT_NOTEBOOKBARITEM );
1726 auto plResult = lResult.getArray();
1728 // Create property names dependent from the root node name
1729 plResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
1730 plResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1731 plResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
1732 plResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
1733 plResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1734 plResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE ];
1735 plResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ];
1736 plResult[7] = aPropertyRootNode + m_aPropNames[ INDEX_STYLE ];
1738 return lResult;
1741 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesStatusbarItem(
1742 std::u16string_view aPropertyRootNode ) const
1744 Sequence< OUString > lResult( PROPERTYCOUNT_STATUSBARITEM );
1745 auto plResult = lResult.getArray();
1747 plResult[0] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL ] );
1748 plResult[1] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE ] );
1749 plResult[2] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ] );
1750 plResult[3] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_ALIGN ] );
1751 plResult[4] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_AUTOSIZE ] );
1752 plResult[5] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_OWNERDRAW ] );
1753 plResult[6] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_MANDATORY ] );
1754 plResult[7] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ] );
1756 return lResult;
1759 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesImages( std::u16string_view aPropertyRootNode ) const
1761 Sequence< OUString > lResult( PROPERTYCOUNT_IMAGES );
1762 auto plResult = lResult.getArray();
1764 // Create property names dependent from the root node name
1765 plResult[0] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL ];
1766 plResult[1] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG ];
1767 plResult[2] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ];
1768 plResult[3] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ];
1769 plResult[4] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ];
1770 plResult[5] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ];
1771 plResult[6] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL];
1772 plResult[7] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ];
1774 return lResult;
1777 namespace{
1778 //global
1779 std::weak_ptr<AddonsOptions_Impl> g_pAddonsOptions;
1782 AddonsOptions::AddonsOptions()
1784 // Global access, must be guarded (multithreading!).
1785 MutexGuard aGuard( GetOwnStaticMutex() );
1787 m_pImpl = g_pAddonsOptions.lock();
1788 if( !m_pImpl )
1790 m_pImpl = std::make_shared<AddonsOptions_Impl>();
1791 g_pAddonsOptions = m_pImpl;
1795 AddonsOptions::~AddonsOptions()
1797 // Global access, must be guarded (multithreading!)
1798 MutexGuard aGuard( GetOwnStaticMutex() );
1800 m_pImpl.reset();
1803 // public method
1805 bool AddonsOptions::HasAddonsMenu() const
1807 MutexGuard aGuard( GetOwnStaticMutex() );
1808 return m_pImpl->HasAddonsMenu();
1811 // public method
1813 sal_Int32 AddonsOptions::GetAddonsToolBarCount() const
1815 MutexGuard aGuard( GetOwnStaticMutex() );
1816 return m_pImpl->GetAddonsToolBarCount();
1819 // public method
1821 sal_Int32 AddonsOptions::GetAddonsNotebookBarCount() const
1823 MutexGuard aGuard( GetOwnStaticMutex() );
1824 return m_pImpl->GetAddonsNotebookBarCount();
1827 // public method
1829 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const
1831 MutexGuard aGuard( GetOwnStaticMutex() );
1832 return m_pImpl->GetAddonsMenu();
1835 // public method
1837 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const
1839 MutexGuard aGuard( GetOwnStaticMutex() );
1840 return m_pImpl->GetAddonsMenuBarPart();
1843 // public method
1845 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
1847 MutexGuard aGuard( GetOwnStaticMutex() );
1848 return m_pImpl->GetAddonsToolBarPart( nIndex );
1851 // public method
1853 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
1855 MutexGuard aGuard( GetOwnStaticMutex() );
1856 return m_pImpl->GetAddonsNotebookBarPart( nIndex );
1859 // public method
1861 OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
1863 MutexGuard aGuard( GetOwnStaticMutex() );
1864 return m_pImpl->GetAddonsToolbarResourceName( nIndex );
1867 // public method
1869 OUString AddonsOptions::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
1871 MutexGuard aGuard( GetOwnStaticMutex() );
1872 return m_pImpl->GetAddonsNotebookBarResourceName( nIndex );
1875 // public method
1877 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const
1879 MutexGuard aGuard( GetOwnStaticMutex() );
1880 return m_pImpl->GetAddonsHelpMenu();
1883 // public method
1885 const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const
1887 MutexGuard aGuard( GetOwnStaticMutex() );
1888 return m_pImpl->GetMergeMenuInstructions();
1891 // public method
1893 bool AddonsOptions::GetMergeToolbarInstructions(
1894 const OUString& rToolbarName,
1895 MergeToolbarInstructionContainer& rToolbarInstructions ) const
1897 MutexGuard aGuard( GetOwnStaticMutex() );
1898 return m_pImpl->GetMergeToolbarInstructions(
1899 rToolbarName, rToolbarInstructions );
1902 // public method
1904 bool AddonsOptions::GetMergeNotebookBarInstructions(
1905 const OUString& rNotebookBarName,
1906 MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
1908 MutexGuard aGuard( GetOwnStaticMutex() );
1909 return m_pImpl->GetMergeNotebookBarInstructions(
1910 rNotebookBarName, rNotebookBarInstructions );
1913 //public method
1915 const MergeStatusbarInstructionContainer& AddonsOptions::GetMergeStatusbarInstructions() const
1917 MutexGuard aGuard( GetOwnStaticMutex() );
1918 return m_pImpl->GetMergeStatusbarInstructions();
1921 // public method
1923 BitmapEx AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale ) const
1925 MutexGuard aGuard( GetOwnStaticMutex() );
1926 return m_pImpl->GetImageFromURL( aURL, bBig, bNoScale );
1929 // public method
1931 BitmapEx AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig ) const
1933 return GetImageFromURL( aURL, bBig, false );
1936 Mutex& AddonsOptions::GetOwnStaticMutex()
1938 // Create static mutex variable.
1939 static Mutex ourMutex;
1941 return ourMutex;
1944 IMPL_LINK_NOARG(AddonsOptions_Impl, NotifyEvent, void*, void)
1946 MutexGuard aGuard(AddonsOptions::GetOwnStaticMutex());
1947 ReadConfigurationData();
1952 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */