fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / fwe / classes / addonsoptions.cxx
blobf99a4f155dec9a8cb80dc92c43aebb2699d199cf
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 <framework/addonsoptions.hxx>
21 #include <unotools/configmgr.hxx>
22 #include <unotools/configitem.hxx>
23 #include <unotools/ucbstreamhelper.hxx>
24 #include <tools/stream.hxx>
25 #include <com/sun/star/uno/Any.hxx>
26 #include <com/sun/star/uno/Sequence.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <comphelper/getexpandeduri.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <vcl/dibtools.hxx>
31 #include <vcl/graph.hxx>
32 #include <vcl/graphicfilter.hxx>
33 #include <vcl/toolbox.hxx>
35 #include <algorithm>
36 #include <unordered_map>
37 #include <vector>
39 // namespaces
41 using namespace ::std;
42 using namespace ::utl;
43 using namespace ::osl;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star;
49 #define ROOTNODE_ADDONMENU OUString("Office.Addons" )
50 #define PATHDELIMITER OUString("/" )
51 #define SEPARATOR_URL "private:separator"
53 #define PROPERTYNAME_URL ADDONSMENUITEM_STRING_URL
54 #define PROPERTYNAME_TITLE ADDONSMENUITEM_STRING_TITLE
55 #define PROPERTYNAME_TARGET ADDONSMENUITEM_STRING_TARGET
56 #define PROPERTYNAME_IMAGEIDENTIFIER ADDONSMENUITEM_STRING_IMAGEIDENTIFIER
57 #define PROPERTYNAME_CONTEXT ADDONSMENUITEM_STRING_CONTEXT
58 #define PROPERTYNAME_SUBMENU ADDONSMENUITEM_STRING_SUBMENU
60 #define IMAGES_NODENAME OUString("UserDefinedImages" )
62 // The following order is mandatory. Please add properties at the end!
63 #define INDEX_URL 0
64 #define INDEX_TITLE 1
65 #define INDEX_IMAGEIDENTIFIER 2
66 #define INDEX_TARGET 3
67 #define INDEX_CONTEXT 4
68 #define INDEX_SUBMENU 5
69 #define INDEX_CONTROLTYPE 6
70 #define INDEX_WIDTH 7
71 #define INDEX_ALIGN 8
72 #define INDEX_AUTOSIZE 9
73 #define INDEX_OWNERDRAW 10
74 #define PROPERTYCOUNT_INDEX 11
76 // The following order is mandatory. Please add properties at the end!
77 #define PROPERTYCOUNT_MENUITEM 6
78 #define OFFSET_MENUITEM_URL 0
79 #define OFFSET_MENUITEM_TITLE 1
80 #define OFFSET_MENUITEM_IMAGEIDENTIFIER 2
81 #define OFFSET_MENUITEM_TARGET 3
82 #define OFFSET_MENUITEM_CONTEXT 4
83 #define OFFSET_MENUITEM_SUBMENU 5
85 // The following order is mandatory. Please add properties at the end!
86 #define PROPERTYCOUNT_POPUPMENU 4
87 #define OFFSET_POPUPMENU_TITLE 0
88 #define OFFSET_POPUPMENU_CONTEXT 1
89 #define OFFSET_POPUPMENU_SUBMENU 2
90 #define OFFSET_POPUPMENU_URL 3 // Used for property set
92 // The following order is mandatory. Please add properties at the end!
93 #define PROPERTYCOUNT_TOOLBARITEM 7
94 #define OFFSET_TOOLBARITEM_URL 0
95 #define OFFSET_TOOLBARITEM_TITLE 1
96 #define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER 2
97 #define OFFSET_TOOLBARITEM_TARGET 3
98 #define OFFSET_TOOLBARITEM_CONTEXT 4
99 #define OFFSET_TOOLBARITEM_CONTROLTYPE 5
100 #define OFFSET_TOOLBARITEM_WIDTH 6
102 // The following order is mandatory. Please add properties at the end!
103 #define PROPERTYCOUNT_STATUSBARITEM 7
104 #define OFFSET_STATUSBARITEM_URL 0
105 #define OFFSET_STATUSBARITEM_TITLE 1
106 #define OFFSET_STATUSBARITEM_CONTEXT 2
107 #define OFFSET_STATUSBARITEM_ALIGN 3
108 #define OFFSET_STATUSBARITEM_AUTOSIZE 4
109 #define OFFSET_STATUSBARITEM_OWNERDRAW 5
110 #define OFFSET_STATUSBARITEM_WIDTH 6
112 // The following order is mandatory. Please add properties at the end!
113 #define PROPERTYCOUNT_IMAGES 8
114 #define PROPERTYCOUNT_EMBEDDED_IMAGES 4
115 #define OFFSET_IMAGES_SMALL 0
116 #define OFFSET_IMAGES_BIG 1
117 #define OFFSET_IMAGES_SMALLHC 2
118 #define OFFSET_IMAGES_BIGHC 3
119 #define OFFSET_IMAGES_SMALL_URL 4
120 #define OFFSET_IMAGES_BIG_URL 5
121 #define OFFSET_IMAGES_SMALLHC_URL 6
122 #define OFFSET_IMAGES_BIGHC_URL 7
124 #define PROPERTYCOUNT_MERGE_MENUBAR 6
125 #define OFFSET_MERGEMENU_MERGEPOINT 0
126 #define OFFSET_MERGEMENU_MERGECOMMAND 1
127 #define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER 2
128 #define OFFSET_MERGEMENU_MERGEFALLBACK 3
129 #define OFFSET_MERGEMENU_MERGECONTEXT 4
130 #define OFFSET_MERGEMENU_MENUITEMS 5
132 #define PROPERTYCOUNT_MERGE_TOOLBAR 7
133 #define OFFSET_MERGETOOLBAR_TOOLBAR 0
134 #define OFFSET_MERGETOOLBAR_MERGEPOINT 1
135 #define OFFSET_MERGETOOLBAR_MERGECOMMAND 2
136 #define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER 3
137 #define OFFSET_MERGETOOLBAR_MERGEFALLBACK 4
138 #define OFFSET_MERGETOOLBAR_MERGECONTEXT 5
139 #define OFFSET_MERGETOOLBAR_TOOLBARITEMS 6
141 #define PROPERTYCOUNT_MERGE_STATUSBAR 6
142 #define OFFSET_MERGESTATUSBAR_MERGEPOINT 0
143 #define OFFSET_MERGESTATUSBAR_MERGECOMMAND 1
144 #define OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER 2
145 #define OFFSET_MERGESTATUSBAR_MERGEFALLBACK 3
146 #define OFFSET_MERGESTATUSBAR_MERGECONTEXT 4
147 #define OFFSET_MERGESTATUSBAR_STATUSBARITEMS 5
149 // private declarations!
151 /*-****************************************************************************************************************
152 @descr struct to hold information about one menu entry.
153 ****************************************************************************************************************-*/
155 namespace framework
158 class AddonsOptions_Impl : public ConfigItem
161 // public methods
163 public:
165 // constructor / destructor
167 AddonsOptions_Impl();
168 virtual ~AddonsOptions_Impl();
170 // overridden methods of baseclass
172 /*-****************************************************************************************************
173 @short called for notify of configmanager
174 @descr These method is called from the ConfigManager before application ends or from the
175 PropertyChangeListener if the sub tree broadcasts changes. You must update your
176 internal values.
178 @seealso baseclass ConfigItem
180 @param "lPropertyNames" is the list of properties which should be updated.
181 *//*-*****************************************************************************************************/
183 virtual void Notify( const Sequence< OUString >& lPropertyNames ) SAL_OVERRIDE;
185 // public interface
187 /*-****************************************************************************************************
188 @short base implementation of public interface for "SvtDynamicMenuOptions"!
189 @descr These class is used as static member of "SvtDynamicMenuOptions" ...
190 => The code exist only for one time and isn't duplicated for every instance!
191 *//*-*****************************************************************************************************/
193 bool HasAddonsMenu () const;
194 sal_Int32 GetAddonsToolBarCount() const;
195 const Sequence< Sequence< PropertyValue > >& GetAddonsMenu () const { return m_aCachedMenuProperties;}
196 const Sequence< Sequence< PropertyValue > >& GetAddonsMenuBarPart () const { return m_aCachedMenuBarPartProperties;}
197 const Sequence< Sequence< PropertyValue > >& GetAddonsToolBarPart ( sal_uInt32 nIndex ) const;
198 const OUString GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
199 const Sequence< Sequence< PropertyValue > >& GetAddonsHelpMenu () const { return m_aCachedHelpMenuProperties;}
200 Image GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale );
201 const MergeMenuInstructionContainer& GetMergeMenuInstructions() const { return m_aCachedMergeMenuInsContainer;}
202 bool GetMergeToolbarInstructions( const OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const;
203 const MergeStatusbarInstructionContainer& GetMergeStatusbarInstructions() const { return m_aCachedStatusbarMergingInstructions;}
204 void ReadConfigurationData();
207 private:
208 enum ImageSize
210 IMGSIZE_SMALL = 0,
211 IMGSIZE_BIG
214 struct OneImageEntry
216 Image aScaled; ///< cached scaled image
217 Image aImage; ///< original un-scaled image
218 OUString aURL; ///< URL in case it is not loaded yet
221 struct ImageEntry
223 // if the image is set, it was embedded in some way,
224 // otherwise we use the associated URL to load on demand
226 // accessed in this order
227 OneImageEntry aSizeEntry[2];
228 ImageEntry() {}
229 void addImage(ImageSize eSize, const Image &rImage, const OUString &rURL);
232 typedef std::unordered_map< OUString, ImageEntry, OUStringHash, std::equal_to< OUString > > ImageManager;
233 typedef std::unordered_map< OUString, sal_uInt32, OUStringHash, std::equal_to< OUString > > StringToIndexMap;
234 typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars;
235 typedef std::unordered_map< OUString, MergeToolbarInstructionContainer, OUStringHash, std::equal_to< OUString > > ToolbarMergingInstructions;
237 /*-****************************************************************************************************
238 @short return list of key names of our configuration management which represent oue module tree
239 @descr These methods return the current list of key names! We need it to get needed values from our
240 configuration management!
241 @param "nCount" , returns count of menu entries for "new"
242 @return A list of configuration key names is returned.
243 *//*-*****************************************************************************************************/
245 bool ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq );
246 bool ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq );
247 bool ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames );
248 bool ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq );
249 bool ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq );
250 void ReadImages( ImageManager& aImageManager );
251 bool ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer );
252 bool ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap );
253 bool ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& rContainer );
255 bool ReadMergeMenuData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu );
256 bool ReadMergeToolbarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems );
257 bool ReadMergeStatusbarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeStatusbar );
258 bool ReadMenuItem( const OUString& aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu = false );
259 bool ReadPopupMenu( const OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu );
260 bool AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu );
261 bool ReadToolBarItem( const OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem );
262 bool ReadStatusBarItem( const OUString& aStatusbarItemNodeName, Sequence< PropertyValue >& aStatusbarItem );
263 ImageEntry* ReadImageData( const OUString& aImagesNodeName );
264 void ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId );
265 Image ReadImageFromURL( const OUString& aURL );
266 bool HasAssociatedImages( const OUString& aURL );
267 void SubstituteVariables( OUString& aURL );
269 bool ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
270 OUString GeneratePrefixURL();
272 Sequence< OUString > GetPropertyNamesMenuItem( const OUString& aPropertyRootNode ) const;
273 Sequence< OUString > GetPropertyNamesPopupMenu( const OUString& aPropertyRootNode ) const;
274 Sequence< OUString > GetPropertyNamesToolBarItem( const OUString& aPropertyRootNode ) const;
275 Sequence< OUString > GetPropertyNamesStatusbarItem( const ::rtl::OUString& aPropertyRootNode ) const;
276 Sequence< OUString > GetPropertyNamesImages( const OUString& aPropertyRootNode ) const;
277 bool CreateImageFromSequence( Image& rImage, Sequence< sal_Int8 >& rBitmapDataSeq ) const;
279 virtual void ImplCommit() SAL_OVERRIDE;
281 // private member
283 private:
284 sal_Int32 m_nRootAddonPopupMenuId;
285 OUString m_aPropNames[PROPERTYCOUNT_INDEX];
286 OUString m_aPropImagesNames[PROPERTYCOUNT_IMAGES];
287 OUString m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR];
288 OUString m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR];
289 OUString m_aPropMergeStatusbarNames[PROPERTYCOUNT_MERGE_STATUSBAR];
290 OUString m_aEmpty;
291 OUString m_aPathDelimiter;
292 OUString m_aRootAddonPopupMenuURLPrexfix;
293 Sequence< Sequence< PropertyValue > > m_aCachedMenuProperties;
294 Sequence< Sequence< PropertyValue > > m_aCachedMenuBarPartProperties;
295 AddonToolBars m_aCachedToolBarPartProperties;
296 std::vector< OUString > m_aCachedToolBarPartResourceNames;
297 Sequence< Sequence< PropertyValue > > m_aCachedHelpMenuProperties;
298 ImageManager m_aImageManager;
299 Sequence< Sequence< PropertyValue > > m_aEmptyAddonToolBar;
300 MergeMenuInstructionContainer m_aCachedMergeMenuInsContainer;
301 ToolbarMergingInstructions m_aCachedToolbarMergingInstructions;
302 MergeStatusbarInstructionContainer m_aCachedStatusbarMergingInstructions;
305 void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize,
306 const Image &rImage,
307 const OUString &rURL)
309 aSizeEntry[(int)eSize].aImage = rImage;
310 aSizeEntry[(int)eSize].aURL = rURL;
313 // constructor
315 AddonsOptions_Impl::AddonsOptions_Impl()
316 // Init baseclasses first
317 : ConfigItem( ROOTNODE_ADDONMENU ),
318 m_nRootAddonPopupMenuId( 0 ),
319 m_aPathDelimiter( PATHDELIMITER ),
320 m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX_STR )
322 // initialize array with fixed property names
323 m_aPropNames[ INDEX_URL ] = PROPERTYNAME_URL;
324 m_aPropNames[ INDEX_TITLE ] = PROPERTYNAME_TITLE;
325 m_aPropNames[ INDEX_TARGET ] = PROPERTYNAME_TARGET;
326 m_aPropNames[ INDEX_IMAGEIDENTIFIER ] = PROPERTYNAME_IMAGEIDENTIFIER;
327 m_aPropNames[ INDEX_CONTEXT ] = PROPERTYNAME_CONTEXT;
328 m_aPropNames[ INDEX_SUBMENU ] = PROPERTYNAME_SUBMENU; // Submenu set!
329 m_aPropNames[ INDEX_CONTROLTYPE ] = "ControlType";
330 m_aPropNames[ INDEX_WIDTH ] = "Width";
331 m_aPropNames[ INDEX_ALIGN ] = "Alignment";
332 m_aPropNames[ INDEX_AUTOSIZE ] = "AutoSize";
333 m_aPropNames[ INDEX_OWNERDRAW ] = "OwnerDraw";
335 // initialize array with fixed images property names
336 m_aPropImagesNames[ OFFSET_IMAGES_SMALL ] = "ImageSmall";
337 m_aPropImagesNames[ OFFSET_IMAGES_BIG ] = "ImageBig";
338 m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ] = "ImageSmallHC";
339 m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ] = "ImageBigHC";
340 m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ] = "ImageSmallURL";
341 m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ] = "ImageBigURL";
342 m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL ] = "ImageSmallHCURL";
343 m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ] = "ImageBigHCURL";
345 // initialize array with fixed merge menu property names
346 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] = "MergePoint";
347 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] = "MergeCommand";
348 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
349 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = "MergeFallback";
350 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] = "MergeContext";
351 m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] = "MenuItems";
353 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] = "MergeToolBar";
354 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] = "MergePoint";
355 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] = "MergeCommand";
356 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
357 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] = "MergeFallback";
358 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] = "MergeContext";
359 m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] = "ToolBarItems";
361 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ] = "MergePoint";
362 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ] = "MergeCommand";
363 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
364 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ] = "MergeFallback";
365 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ] = "MergeContext";
366 m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ] = "StatusBarItems";
368 ReadConfigurationData();
370 // Enable notification mechanism of our baseclass.
371 // We need it to get information about changes outside these class on our used configuration keys!
372 Sequence< OUString > aNotifySeq( 1 );
373 aNotifySeq[0] = "AddonUI";
374 EnableNotification( aNotifySeq );
377 // destructor
379 AddonsOptions_Impl::~AddonsOptions_Impl()
381 assert(!IsModified()); // should have been committed
384 void AddonsOptions_Impl::ReadConfigurationData()
386 // reset members to be read again from configuration
387 m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >();
388 m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >();
389 m_aCachedToolBarPartProperties = AddonToolBars();
390 m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
391 m_aCachedToolBarPartResourceNames.clear();
392 m_aImageManager = ImageManager();
394 ReadAddonMenuSet( m_aCachedMenuProperties );
395 ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
396 ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
398 ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
399 ReadImages( m_aImageManager );
401 m_aCachedMergeMenuInsContainer.clear();
402 m_aCachedToolbarMergingInstructions.clear();
403 m_aCachedStatusbarMergingInstructions.clear();
405 ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
406 ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
407 ReadStatusbarMergeInstructions( m_aCachedStatusbarMergingInstructions );
410 // public method
412 void AddonsOptions_Impl::Notify( const Sequence< OUString >& /*lPropertyNames*/ )
414 Application::PostUserEvent( LINK( 0, AddonsOptions, Notify ) );
417 // public method
419 void AddonsOptions_Impl::ImplCommit()
421 SAL_WARN("framework", "AddonsOptions_Impl::ImplCommit(): Not implemented yet!");
424 // public method
426 bool AddonsOptions_Impl::HasAddonsMenu() const
428 return ( m_aCachedMenuProperties.getLength() > 0 );
431 // public method
433 sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
435 return m_aCachedToolBarPartProperties.size();
438 // public method
440 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
442 if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() )
443 return m_aCachedToolBarPartProperties[nIndex];
444 else
445 return m_aEmptyAddonToolBar;
448 // public method
450 const OUString AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
452 if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
453 return m_aCachedToolBarPartResourceNames[nIndex];
454 else
455 return OUString();
458 // public method
460 bool AddonsOptions_Impl::GetMergeToolbarInstructions(
461 const OUString& rToolbarName,
462 MergeToolbarInstructionContainer& rToolbarInstructions ) const
464 ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName );
465 if ( pIter != m_aCachedToolbarMergingInstructions.end() )
467 rToolbarInstructions = pIter->second;
468 return true;
470 else
471 return false;
475 // public method
477 static Image ScaleImage( const Image &rImage, bool bBig )
479 Size aSize = ToolBox::GetDefaultImageSize(bBig);
480 BitmapEx aScaleBmp(rImage.GetBitmapEx());
481 SAL_INFO("fwk", "Addons: expensive scale image from "
482 << aScaleBmp.GetSizePixel() << " to " << aSize);
483 aScaleBmp.Scale(aSize, BmpScaleFlag::BestQuality);
484 return Image(aScaleBmp);
487 Image AddonsOptions_Impl::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale )
489 Image aImage;
491 SAL_INFO("fwk", "Expensive: Addons GetImageFromURL " << aURL <<
492 " big " << (bBig?"big":"litte") <<
493 " scale " << (bNoScale ? "noscale" : "scale"));
495 ImageManager::iterator pIter = m_aImageManager.find(aURL);
496 if ( pIter != m_aImageManager.end() )
498 ImageSize eSize = bBig ? IMGSIZE_BIG : IMGSIZE_SMALL;
499 int nIdx = (int)eSize;
500 int nOtherIdx = nIdx ? 0 : 1;
502 OneImageEntry& rSizeEntry = pIter->second.aSizeEntry[nIdx];
503 OneImageEntry& rOtherEntry = pIter->second.aSizeEntry[nOtherIdx];
504 // actually read the image ...
505 if (!rSizeEntry.aImage)
506 rSizeEntry.aImage = ReadImageFromURL(rSizeEntry.aURL);
508 if (!rSizeEntry.aImage)
509 { // try the other size and scale it
510 aImage = ScaleImage(ReadImageFromURL(rOtherEntry.aURL), bBig);
511 rSizeEntry.aImage = aImage;
512 if (!rSizeEntry.aImage)
513 SAL_WARN("fwk", "failed to load addons image " << aURL);
516 // FIXME: bNoScale is not terribly meaningful or useful
518 if (!aImage && bNoScale)
519 aImage = rSizeEntry.aImage;
521 if (!aImage && !!rSizeEntry.aScaled)
522 aImage = rSizeEntry.aScaled;
524 else // scale to the correct size for the theme / toolbox
526 aImage = rSizeEntry.aImage;
527 if (!aImage) // use and scale the other if one size is missing
528 aImage = rOtherEntry.aImage;
530 aImage = ScaleImage(aImage, bBig);
531 rSizeEntry.aScaled = aImage; // cache for next time
535 return aImage;
538 bool AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
540 // Read the AddonMenu set and fill property sequences
541 OUString aAddonMenuNodeName( "AddonUI/AddonMenu" );
542 Sequence< OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
543 OUString aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter );
545 sal_uInt32 nCount = aAddonMenuNodeSeq.getLength();
546 sal_uInt32 nIndex = 0;
547 Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
549 // Init the property value sequence
550 aMenuItem[ OFFSET_MENUITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
551 aMenuItem[ OFFSET_MENUITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
552 aMenuItem[ OFFSET_MENUITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ];
553 aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
554 aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
555 aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU ]; // Submenu set!
557 for ( sal_uInt32 n = 0; n < nCount; n++ )
559 OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] );
561 // Read the MenuItem
562 if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) )
564 // Successfully read a menu item, append to our list
565 sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1;
566 rAddonMenuSeq.realloc( nMenuItemCount );
567 rAddonMenuSeq[nIndex++] = aMenuItem;
571 return ( rAddonMenuSeq.getLength() > 0 );
574 bool AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
576 // Read the AddonMenu set and fill property sequences
577 OUString aAddonHelpMenuNodeName( "AddonUI/OfficeHelp" );
578 Sequence< OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
579 OUString aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter );
581 sal_uInt32 nCount = aAddonHelpMenuNodeSeq.getLength();
582 sal_uInt32 nIndex = 0;
583 Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
585 // Init the property value sequence
586 aMenuItem[ OFFSET_MENUITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
587 aMenuItem[ OFFSET_MENUITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
588 aMenuItem[ OFFSET_MENUITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ];
589 aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
590 aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
591 aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU ]; // Submenu set!
593 for ( sal_uInt32 n = 0; n < nCount; n++ )
595 OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );
597 // Read the MenuItem
598 if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, true ) )
600 // Successfully read a menu item, append to our list
601 sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
602 rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
603 rAddonOfficeHelpMenuSeq[nIndex++] = aMenuItem;
607 return ( rAddonOfficeHelpMenuSeq.getLength() > 0 );
610 bool AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
612 // Read the OfficeMenuBar set and fill property sequences
613 OUString aAddonMenuBarNodeName( "AddonUI/OfficeMenuBar" );
614 Sequence< OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
615 OUString aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter );
617 sal_uInt32 nCount = aAddonMenuBarNodeSeq.getLength();
618 sal_uInt32 nIndex = 0;
619 Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU );
621 // Init the property value sequence
622 aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
623 aPopupMenu[ OFFSET_POPUPMENU_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT];
624 aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Name = m_aPropNames[ INDEX_SUBMENU];
625 aPopupMenu[ OFFSET_POPUPMENU_URL ].Name = m_aPropNames[ INDEX_URL ];
627 StringToIndexMap aTitleToIndexMap;
629 for ( sal_uInt32 n = 0; n < nCount; n++ )
631 OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );
633 // Read the MenuItem
634 if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
636 // Successfully read a popup menu, append to our list
637 OUString aPopupTitle;
638 if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle )
640 StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle );
641 if ( pIter != aTitleToIndexMap.end() )
643 // title already there => concat both popup menus
644 Sequence< PropertyValue >& rOldPopupMenu = rAddonOfficeMenuBarSeq[pIter->second];
645 AppendPopupMenu( rOldPopupMenu, aPopupMenu );
647 else
649 // not found
650 sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1;
651 rAddonOfficeMenuBarSeq.realloc( nMenuItemCount );
652 rAddonOfficeMenuBarSeq[nIndex] = aPopupMenu;
653 aTitleToIndexMap.insert( StringToIndexMap::value_type( aPopupTitle, nIndex ));
654 ++nIndex;
660 return ( rAddonOfficeMenuBarSeq.getLength() > 0 );
663 bool AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames )
665 // Read the OfficeToolBar set and fill property sequences
666 OUString aAddonToolBarNodeName( "AddonUI/OfficeToolBar" );
667 Sequence< OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
668 OUString aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );
670 sal_uInt32 nCount = aAddonToolBarNodeSeq.getLength();
672 for ( sal_uInt32 n = 0; n < nCount; n++ )
674 OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
675 rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
676 rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
677 ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
680 return ( !rAddonOfficeToolBars.empty() );
683 bool AddonsOptions_Impl::ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
685 sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength();
686 OUString aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
687 Sequence< OUString > aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName );
688 Sequence< PropertyValue > aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
690 // Init the property value sequence
691 aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
692 aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
693 aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
694 aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Name = m_aPropNames[ INDEX_TARGET ];
695 aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
696 aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Name = m_aPropNames[ INDEX_CONTROLTYPE ];
697 aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Name = m_aPropNames[ INDEX_WIDTH ];
699 sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength();
700 for ( sal_uInt32 n = 0; n < nCount; n++ )
702 OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );
704 // Read the ToolBarItem
705 if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
707 // Successfully read a toolbar item, append to our list
708 sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
709 rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
710 rAddonOfficeToolBarSeq[nAddonCount] = aToolBarItem;
714 return ( (sal_uInt32)rAddonOfficeToolBarSeq.getLength() > nToolBarItemCount );
717 void AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
719 // Read the user-defined Images set and fill image manager
720 OUString aAddonImagesNodeName( "AddonUI/Images" );
721 Sequence< OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
722 OUString aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );
724 sal_uInt32 nCount = aAddonImagesNodeSeq.getLength();
726 // Init the property value sequence
727 Sequence< OUString > aAddonImageItemNodePropNames( 1 );
728 OUString aURL;
730 for ( sal_uInt32 n = 0; n < nCount; n++ )
732 OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );
734 // Create sequence for data access
735 OUStringBuffer aBuffer( aImagesItemNode );
736 aBuffer.append( m_aPathDelimiter );
737 aBuffer.append( m_aPropNames[ OFFSET_MENUITEM_URL ] );
738 aAddonImageItemNodePropNames[0] = aBuffer.makeStringAndClear();
740 Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );
742 // An user-defined image entry must have an URL. As "ImageIdentifier" has a higher priority
743 // we also check if we already have an images association.
744 if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
745 !aURL.isEmpty() &&
746 !HasAssociatedImages( aURL ))
748 OUStringBuffer aBuf( aImagesItemNode );
749 aBuf.append( m_aPathDelimiter );
750 aBuf.append( IMAGES_NODENAME );
751 aBuf.append( m_aPathDelimiter );
752 OUString aImagesUserDefinedItemNode = aBuf.makeStringAndClear();
754 // Read a user-defined images data
755 ImageEntry* pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
756 if ( pImageEntry )
758 // Successfully read a user-defined images item, put it into our image manager
759 aImageManager.insert( ImageManager::value_type( aURL, *pImageEntry ));
760 delete pImageEntry; // We have the ownership of the pointer
766 OUString AddonsOptions_Impl::GeneratePrefixURL()
768 // Create an unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu.
769 // They use a different image manager, so they must be identified by the sfx2/framework code.
770 OUString aPopupMenuURL;
771 OUStringBuffer aBuf( m_aRootAddonPopupMenuURLPrexfix.getLength() + 3 );
772 aBuf.append( m_aRootAddonPopupMenuURLPrexfix );
773 aBuf.append( OUString::number( ++m_nRootAddonPopupMenuId ));
774 aPopupMenuURL = aBuf.makeStringAndClear();
775 return aPopupMenuURL;
778 bool AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer )
780 const OUString aMenuMergeRootName( "AddonUI/OfficeMenuBarMerging/" );
782 Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );
783 OUString aAddonMergeNode( aMenuMergeRootName );
785 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
787 // Init the property value sequence
788 Sequence< OUString > aNodePropNames( 5 );
790 for ( sal_uInt32 i = 0; i < nCount; i++ )
792 OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
794 Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
795 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
797 for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
799 OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
800 aMergeAddonInstructionBase.append( m_aPathDelimiter );
801 aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
802 aMergeAddonInstructionBase.append( m_aPathDelimiter );
804 // Create sequence for data access
805 OUStringBuffer aBuffer( aMergeAddonInstructionBase );
806 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] );
807 aNodePropNames[0] = aBuffer.makeStringAndClear();
809 aBuffer = aMergeAddonInstructionBase;
810 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] );
811 aNodePropNames[1] = aBuffer.makeStringAndClear();
813 aBuffer = aMergeAddonInstructionBase;
814 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] );
815 aNodePropNames[2] = aBuffer.makeStringAndClear();
817 aBuffer = aMergeAddonInstructionBase;
818 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] );
819 aNodePropNames[3] = aBuffer.makeStringAndClear();
821 aBuffer = aMergeAddonInstructionBase;
822 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] );
823 aNodePropNames[4] = aBuffer.makeStringAndClear();
825 Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
827 MergeMenuInstruction aMergeMenuInstruction;
828 aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint;
829 aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand;
830 aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter;
831 aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback;
832 aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext;
834 OUString aMergeMenuBase = aMergeAddonInstructionBase.makeStringAndClear();
835 ReadMergeMenuData( aMergeMenuBase, aMergeMenuInstruction.aMergeMenu );
837 aContainer.push_back( aMergeMenuInstruction );
841 return true;
844 bool AddonsOptions_Impl::ReadMergeMenuData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
846 OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );
848 Sequence< OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
849 aMergeMenuBaseNode += m_aPathDelimiter;
851 // extend the node names to have full path strings
852 for ( sal_uInt32 i = 0; i < (sal_uInt32)aSubMenuNodeNames.getLength(); i++ )
853 aSubMenuNodeNames[i] = aMergeMenuBaseNode + aSubMenuNodeNames[i];
855 return ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
858 bool AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions )
860 const OUString aToolbarMergeRootName( "AddonUI/OfficeToolbarMerging/" );
862 Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
863 OUString aAddonMergeNode( aToolbarMergeRootName );
865 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
867 // Init the property value sequence
868 Sequence< OUString > aNodePropNames( 6 );
870 for ( sal_uInt32 i = 0; i < nCount; i++ )
872 OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
874 Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
875 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
877 for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
879 OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
880 aMergeAddonInstructionBase.append( m_aPathDelimiter );
881 aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
882 aMergeAddonInstructionBase.append( m_aPathDelimiter );
884 // Create sequence for data access
885 OUStringBuffer aBuffer( aMergeAddonInstructionBase );
886 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] );
887 aNodePropNames[0] = aBuffer.makeStringAndClear();
889 aBuffer = aMergeAddonInstructionBase;
890 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] );
891 aNodePropNames[1] = aBuffer.makeStringAndClear();
893 aBuffer = aMergeAddonInstructionBase;
894 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] );
895 aNodePropNames[2] = aBuffer.makeStringAndClear();
897 aBuffer = aMergeAddonInstructionBase;
898 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] );
899 aNodePropNames[3] = aBuffer.makeStringAndClear();
901 aBuffer = aMergeAddonInstructionBase;
902 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] );
903 aNodePropNames[4] = aBuffer.makeStringAndClear();
905 aBuffer = aMergeAddonInstructionBase;
906 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] );
907 aNodePropNames[5] = aBuffer.makeStringAndClear();
909 Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
911 MergeToolbarInstruction aMergeToolbarInstruction;
912 aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar;
913 aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint;
914 aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand;
915 aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter;
916 aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback;
917 aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext;
919 ReadMergeToolbarData( aMergeAddonInstructionBase.makeStringAndClear(),
920 aMergeToolbarInstruction.aMergeToolbarItems );
922 MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ];
923 rVector.push_back( aMergeToolbarInstruction );
927 return true;
930 bool AddonsOptions_Impl::ReadMergeToolbarData( const OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
932 OUStringBuffer aBuffer( aMergeAddonInstructionBase );
933 aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] );
935 OUString aMergeToolbarBaseNode = aBuffer.makeStringAndClear();
937 return ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
940 bool AddonsOptions_Impl::ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& aContainer )
942 const ::rtl::OUString aStatusbarMergeRootName( "AddonUI/OfficeStatusbarMerging/" );
944 Sequence< ::rtl::OUString > aAddonMergeNodesSeq = GetNodeNames( aStatusbarMergeRootName );
945 ::rtl::OUString aAddonMergeNode( aStatusbarMergeRootName );
946 sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
948 Sequence< ::rtl::OUString > aNodePropNames( 5 );
950 for ( sal_uInt32 i = 0; i < nCount; i++ )
952 ::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
954 Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
955 sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
957 for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
959 ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
960 aMergeAddonInstructionBase.append( m_aPathDelimiter );
961 aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
962 aMergeAddonInstructionBase.append( m_aPathDelimiter );
964 // Create sequence for data access
965 ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
966 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ] );
967 aNodePropNames[0] = aBuffer.makeStringAndClear();
969 aBuffer = aMergeAddonInstructionBase;
970 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ] );
971 aNodePropNames[1] = aBuffer.makeStringAndClear();
973 aBuffer = aMergeAddonInstructionBase;
974 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] );
975 aNodePropNames[2] = aBuffer.makeStringAndClear();
977 aBuffer = aMergeAddonInstructionBase;
978 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ] );
979 aNodePropNames[3] = aBuffer.makeStringAndClear();
981 aBuffer = aMergeAddonInstructionBase;
982 aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ] );
983 aNodePropNames[4] = aBuffer.makeStringAndClear();
985 Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
987 MergeStatusbarInstruction aMergeStatusbarInstruction;
988 aNodePropValues[0] >>= aMergeStatusbarInstruction.aMergePoint;
989 aNodePropValues[1] >>= aMergeStatusbarInstruction.aMergeCommand;
990 aNodePropValues[2] >>= aMergeStatusbarInstruction.aMergeCommandParameter;
991 aNodePropValues[3] >>= aMergeStatusbarInstruction.aMergeFallback;
992 aNodePropValues[4] >>= aMergeStatusbarInstruction.aMergeContext;
994 ReadMergeStatusbarData( aMergeAddonInstructionBase.makeStringAndClear(),
995 aMergeStatusbarInstruction.aMergeStatusbarItems );
997 aContainer.push_back( aMergeStatusbarInstruction );
1001 return true;
1004 bool AddonsOptions_Impl::ReadMergeStatusbarData(
1005 const ::rtl::OUString& aMergeAddonInstructionBase,
1006 Sequence< Sequence< PropertyValue > >& rMergeStatusbarItems )
1008 sal_uInt32 nStatusbarItemCount = rMergeStatusbarItems.getLength();
1010 ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
1011 aBuffer.append( m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ] );
1012 ::rtl::OUString aMergeStatusbarBaseNode = aBuffer.makeStringAndClear();
1014 ::rtl::OUString aAddonStatusbarItemSetNode( aMergeStatusbarBaseNode + m_aPathDelimiter );
1015 Sequence< ::rtl::OUString > aAddonStatusbarItemSetNodeSeq = GetNodeNames( aMergeStatusbarBaseNode );
1017 Sequence< PropertyValue > aStatusbarItem( PROPERTYCOUNT_STATUSBARITEM );
1018 aStatusbarItem[ OFFSET_STATUSBARITEM_URL ].Name = m_aPropNames[ INDEX_URL ];
1019 aStatusbarItem[ OFFSET_STATUSBARITEM_TITLE ].Name = m_aPropNames[ INDEX_TITLE ];
1020 aStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT ].Name = m_aPropNames[ INDEX_CONTEXT ];
1021 aStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN ].Name = m_aPropNames[ INDEX_ALIGN ];
1022 aStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE ].Name = m_aPropNames[ INDEX_AUTOSIZE ];
1023 aStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Name = m_aPropNames[ INDEX_OWNERDRAW ];
1024 aStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Name = m_aPropNames[ INDEX_WIDTH ];
1026 sal_uInt32 nCount = aAddonStatusbarItemSetNodeSeq.getLength();
1027 for ( sal_uInt32 n = 0; n < nCount; n++ )
1029 ::rtl::OUString aStatusbarItemNode( aAddonStatusbarItemSetNode + aAddonStatusbarItemSetNodeSeq[n] );
1031 if ( ReadStatusBarItem( aStatusbarItemNode, aStatusbarItem ) )
1033 sal_uInt32 nAddonCount = rMergeStatusbarItems.getLength();
1034 rMergeStatusbarItems.realloc( nAddonCount+1 );
1035 rMergeStatusbarItems[nAddonCount] = aStatusbarItem;
1039 return ( (sal_uInt32)rMergeStatusbarItems.getLength() > nStatusbarItemCount );
1042 bool AddonsOptions_Impl::ReadStatusBarItem(
1043 const ::rtl::OUString& aStatusarItemNodeName,
1044 Sequence< PropertyValue >& aStatusbarItem )
1046 bool bResult( false );
1047 ::rtl::OUString aURL;
1048 ::rtl::OUString aAddonStatusbarItemTreeNode( aStatusarItemNodeName + m_aPathDelimiter );
1049 Sequence< Any > aStatusbarItemNodePropValues;
1051 aStatusbarItemNodePropValues = GetProperties( GetPropertyNamesStatusbarItem( aAddonStatusbarItemTreeNode ) );
1053 // Command URL is required
1054 if (( aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
1056 aStatusbarItem[ OFFSET_STATUSBARITEM_URL ].Value <<= aURL;
1057 aStatusbarItem[ OFFSET_STATUSBARITEM_TITLE ].Value <<= aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_TITLE ];
1058 aStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT ].Value <<= aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_CONTEXT ];
1059 aStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN ].Value <<= aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_ALIGN ];
1060 aStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE ].Value <<= aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_AUTOSIZE ];;
1061 aStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Value <<= aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_OWNERDRAW ];
1063 // Configuration uses hyper for long. Therefore transform into sal_Int32
1064 sal_Int64 nValue( 0 );
1065 aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_WIDTH ] >>= nValue;
1066 aStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
1068 bResult = true;
1071 return bResult;
1074 bool AddonsOptions_Impl::ReadMenuItem( const OUString& aMenuNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu )
1076 bool bResult = false;
1077 OUString aStrValue;
1078 OUString aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );
1079 Sequence< Any > aMenuItemNodePropValues;
1081 aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
1082 if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && !aStrValue.isEmpty() )
1084 aMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;
1086 OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1087 Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1088 if ( aRootSubMenuNodeNames.getLength() > 0 && !bIgnoreSubMenu )
1090 // Set a unique prefixed Add-On popup menu URL so it can be identified later
1091 OUString aPopupMenuURL = GeneratePrefixURL();
1092 OUString aPopupMenuImageId;
1094 aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId;
1095 ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId );
1097 // A popup menu must have a title and can have a URL and ImageIdentifier
1098 // Set the other property values to empty
1099 aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aPopupMenuURL;
1100 aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= m_aEmpty;
1101 aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= aPopupMenuImageId;
1102 aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1104 // Continue to read the sub menu nodes
1105 Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1106 OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1107 for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ )
1108 aRootSubMenuNodeNames[n] = aSubMenuRootNodeName + aRootSubMenuNodeNames[n];
1109 ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1110 aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
1111 bResult = true;
1113 else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && !aStrValue.isEmpty() )
1115 // A simple menu item => read the other properties;
1116 OUString aMenuImageId;
1118 aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId;
1119 ReadAndAssociateImages( aStrValue, aMenuImageId );
1121 aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue;
1122 aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET ];
1123 aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= aMenuImageId;
1124 aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1125 aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1127 bResult = true;
1130 else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) &&
1131 aStrValue == SEPARATOR_URL )
1133 // Separator
1134 aMenuItem[ OFFSET_MENUITEM_URL ].Value <<= aStrValue;
1135 aMenuItem[ OFFSET_MENUITEM_TARGET ].Value <<= m_aEmpty;
1136 aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Value <<= m_aEmpty;
1137 aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Value <<= m_aEmpty;
1138 aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1139 bResult = true;
1142 return bResult;
1145 bool AddonsOptions_Impl::ReadPopupMenu( const OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu )
1147 bool bResult = false;
1148 OUString aStrValue;
1149 OUString aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter );
1150 Sequence< Any > aPopupMenuNodePropValues;
1152 aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) );
1153 if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) &&
1154 !aStrValue.isEmpty() )
1156 aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue;
1158 OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1159 Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1160 if ( aRootSubMenuNodeNames.getLength() > 0 )
1162 // A top-level popup menu needs a title
1163 // Set a unique prefixed Add-On popup menu URL so it can be identified later
1164 OUString aPopupMenuURL = GeneratePrefixURL();
1166 aPopupMenu[ OFFSET_POPUPMENU_URL ].Value <<= aPopupMenuURL;
1167 aPopupMenu[ OFFSET_POPUPMENU_CONTEXT ].Value <<= aPopupMenuNodePropValues[ OFFSET_POPUPMENU_CONTEXT ];
1169 // Continue to read the sub menu nodes
1170 Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1171 OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1172 for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ )
1173 aRootSubMenuNodeNames[n] = aSubMenuRootNodeName + aRootSubMenuNodeNames[n];
1174 ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1175 aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq;
1176 bResult = true;
1180 return bResult;
1183 bool AddonsOptions_Impl::AppendPopupMenu( Sequence< PropertyValue >& rTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu )
1185 Sequence< Sequence< PropertyValue > > aTargetSubMenuSeq;
1186 Sequence< Sequence< PropertyValue > > aSourceSubMenuSeq;
1188 if (( rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aTargetSubMenuSeq ) &&
1189 ( rSourcePopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aSourceSubMenuSeq ))
1191 sal_uInt32 nIndex = aTargetSubMenuSeq.getLength();
1192 aTargetSubMenuSeq.realloc( nIndex + aSourceSubMenuSeq.getLength() );
1193 for ( sal_uInt32 i = 0; i < sal_uInt32( aSourceSubMenuSeq.getLength() ); i++ )
1194 aTargetSubMenuSeq[nIndex++] = aSourceSubMenuSeq[i];
1195 rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq;
1198 return true;
1201 bool AddonsOptions_Impl::ReadToolBarItem( const OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem )
1203 bool bResult = false;
1204 OUString aTitle;
1205 OUString aURL;
1206 OUString aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter );
1207 Sequence< Any > aToolBarItemNodePropValues;
1209 aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) );
1211 // A toolbar item must have a command URL
1212 if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
1214 if ( aURL == SEPARATOR_URL )
1216 // A speparator toolbar item only needs a URL
1217 aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL;
1218 aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= m_aEmpty;
1219 aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= m_aEmpty;
1220 aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= m_aEmpty;
1221 aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= m_aEmpty;
1222 aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value <<= m_aEmpty;
1223 aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( 0 );
1225 bResult = true;
1227 else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
1229 // A normal toolbar item must also have title => read the other properties;
1230 OUString aImageId;
1232 // Try to map a user-defined image URL to our internal private image URL
1233 aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1234 ReadAndAssociateImages( aURL, aImageId );
1236 aToolBarItem[ OFFSET_TOOLBARITEM_URL ].Value <<= aURL;
1237 aToolBarItem[ OFFSET_TOOLBARITEM_TITLE ].Value <<= aTitle;
1238 aToolBarItem[ OFFSET_TOOLBARITEM_TARGET ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TARGET ];
1239 aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ].Value <<= aImageId;
1240 aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTEXT ];
1241 aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE ].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTROLTYPE ];
1243 // Configuration uses hyper for long. Therefore transform into sal_Int32
1244 sal_Int64 nValue( 0 );
1245 aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_WIDTH ] >>= nValue;
1246 aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
1248 bResult = true;
1252 return bResult;
1255 bool AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenuSeq )
1257 Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
1259 // Init the property value sequence
1260 aMenuItem[ OFFSET_MENUITEM_URL ].Name = PROPERTYNAME_URL;
1261 aMenuItem[ OFFSET_MENUITEM_TITLE ].Name = PROPERTYNAME_TITLE;
1262 aMenuItem[ OFFSET_MENUITEM_TARGET ].Name = PROPERTYNAME_TARGET;
1263 aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER ].Name = PROPERTYNAME_IMAGEIDENTIFIER;
1264 aMenuItem[ OFFSET_MENUITEM_CONTEXT ].Name = PROPERTYNAME_CONTEXT;
1265 aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Name = PROPERTYNAME_SUBMENU; // Submenu set!
1267 sal_uInt32 nIndex = 0;
1268 sal_uInt32 nCount = aSubMenuNodeNames.getLength();
1269 for ( sal_uInt32 n = 0; n < nCount; n++ )
1271 if ( ReadMenuItem( aSubMenuNodeNames[n], aMenuItem ))
1273 sal_uInt32 nSubMenuCount = rSubMenuSeq.getLength() + 1;
1274 rSubMenuSeq.realloc( nSubMenuCount );
1275 rSubMenuSeq[nIndex++] = aMenuItem;
1279 return true;
1282 bool AddonsOptions_Impl::HasAssociatedImages( const OUString& aURL )
1284 // FIXME: potentially this is not so useful in a world of delayed image loading
1285 ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
1286 return ( pIter != m_aImageManager.end() );
1289 void AddonsOptions_Impl::SubstituteVariables( OUString& aURL )
1291 aURL = comphelper::getExpandedUri(
1292 comphelper::getProcessComponentContext(), aURL);
1295 Image AddonsOptions_Impl::ReadImageFromURL(const OUString& aImageURL)
1297 Image aImage;
1299 SvStream* pStream = UcbStreamHelper::CreateStream( aImageURL, STREAM_STD_READ );
1300 if ( pStream && ( pStream->GetErrorCode() == 0 ))
1302 // Use graphic class to also support more graphic formats (bmp,png,...)
1303 Graphic aGraphic;
1305 GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
1306 rGF.ImportGraphic( aGraphic, OUString(), *pStream, GRFILTER_FORMAT_DONTKNOW );
1308 BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
1310 Size aBmpSize = aBitmapEx.GetSizePixel();
1311 if ( aBmpSize.Width() > 0 && aBmpSize.Height() > 0 )
1313 // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1314 if( !aBitmapEx.IsTransparent() )
1315 aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1317 aImage = Image(aBitmapEx);
1321 delete pStream;
1323 return aImage;
1326 void AddonsOptions_Impl::ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId )
1328 if ( aImageId.isEmpty() )
1329 return;
1331 ImageEntry aImageEntry;
1332 OUString aImageURL( aImageId );
1334 SubstituteVariables( aImageURL );
1336 // Loop to create the two possible image names and try to read the bitmap files
1337 static const char* aExtArray[] = { "_16", "_26" };
1338 for ( size_t i = 0; i < SAL_N_ELEMENTS(aExtArray); i++ )
1340 OUStringBuffer aFileURL( aImageURL );
1341 aFileURL.appendAscii( aExtArray[i] );
1342 aFileURL.appendAscii( ".bmp" );
1344 aImageEntry.addImage( !i ? IMGSIZE_SMALL : IMGSIZE_BIG,
1345 Image(), aFileURL.makeStringAndClear() );
1348 m_aImageManager.insert( ImageManager::value_type( aURL, aImageEntry ));
1351 AddonsOptions_Impl::ImageEntry* AddonsOptions_Impl::ReadImageData( const OUString& aImagesNodeName )
1353 Sequence< OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName );
1354 Sequence< Any > aPropertyData;
1355 Sequence< sal_Int8 > aImageDataSeq;
1356 OUString aImageURL;
1358 ImageEntry* pEntry = NULL;
1360 // It is possible to use both forms (embedded image data and URLs to external bitmap files) at the
1361 // same time. Embedded image data has a higher priority.
1362 aPropertyData = GetProperties( aImageDataNodeNames );
1363 for ( int i = 0; i < PROPERTYCOUNT_IMAGES; i++ )
1365 if ( i < PROPERTYCOUNT_EMBEDDED_IMAGES )
1367 // Extract image data from the embedded hex binary sequence
1368 Image aImage;
1369 if (( aPropertyData[i] >>= aImageDataSeq ) &&
1370 aImageDataSeq.getLength() > 0 &&
1371 ( CreateImageFromSequence( aImage, aImageDataSeq ) ) )
1373 if ( !pEntry )
1374 pEntry = new ImageEntry;
1375 pEntry->addImage(i == OFFSET_IMAGES_SMALL ? IMGSIZE_SMALL : IMGSIZE_BIG, aImage, "");
1378 else
1380 if(!pEntry)
1381 pEntry = new ImageEntry();
1383 // Retrieve image data from a external bitmap file. Make sure that embedded image data
1384 // has a higher priority.
1385 aPropertyData[i] >>= aImageURL;
1387 SubstituteVariables( aImageURL );
1389 pEntry->addImage(IMGSIZE_BIG, Image(), aImageURL);
1393 return pEntry;
1396 bool AddonsOptions_Impl::CreateImageFromSequence( Image& rImage, Sequence< sal_Int8 >& rBitmapDataSeq ) const
1398 bool bResult = false;
1400 if ( rBitmapDataSeq.getLength() > 0 )
1402 SvMemoryStream aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), STREAM_STD_READ );
1403 BitmapEx aBitmapEx;
1405 ReadDIBBitmapEx(aBitmapEx, aMemStream);
1407 if( !aBitmapEx.IsTransparent() )
1409 // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1410 aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1413 rImage = Image( aBitmapEx );
1414 bResult = true;
1417 return bResult;
1420 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( const OUString& aPropertyRootNode ) const
1422 Sequence< OUString > lResult( PROPERTYCOUNT_MENUITEM );
1424 // Create property names dependent from the root node name
1425 lResult[OFFSET_MENUITEM_URL] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
1426 lResult[OFFSET_MENUITEM_TITLE] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1427 lResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ];
1428 lResult[OFFSET_MENUITEM_TARGET] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
1429 lResult[OFFSET_MENUITEM_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1430 lResult[OFFSET_MENUITEM_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ];
1432 return lResult;
1435 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( const OUString& aPropertyRootNode ) const
1437 // The URL is automatically set and not read from the configuration.
1438 Sequence< OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 );
1440 // Create property names dependent from the root node name
1441 lResult[OFFSET_POPUPMENU_TITLE] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1442 lResult[OFFSET_POPUPMENU_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1443 lResult[OFFSET_POPUPMENU_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU ];
1445 return lResult;
1448 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( const OUString& aPropertyRootNode ) const
1450 Sequence< OUString > lResult( PROPERTYCOUNT_TOOLBARITEM );
1452 // Create property names dependent from the root node name
1453 lResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL ];
1454 lResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE ];
1455 lResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
1456 lResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET ];
1457 lResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ];
1458 lResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE ];
1459 lResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ];
1461 return lResult;
1464 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesStatusbarItem(
1465 const ::rtl::OUString& aPropertyRootNode ) const
1467 Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_STATUSBARITEM );
1469 lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL ] );
1470 lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE ] );
1471 lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT ] );
1472 lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_ALIGN ] );
1473 lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_AUTOSIZE ] );
1474 lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_OWNERDRAW ] );
1475 lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH ] );
1477 return lResult;
1480 Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesImages( const OUString& aPropertyRootNode ) const
1482 Sequence< OUString > lResult( PROPERTYCOUNT_IMAGES );
1484 // Create property names dependent from the root node name
1485 lResult[0] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL ];
1486 lResult[1] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG ];
1487 lResult[2] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ];
1488 lResult[3] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC ];
1489 lResult[4] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL ];
1490 lResult[5] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ];
1491 lResult[6] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL];
1492 lResult[7] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL ];
1494 return lResult;
1497 // initialize static member
1498 // DON'T DO IT IN YOUR HEADER!
1499 // see definition for further information
1501 AddonsOptions_Impl* AddonsOptions::m_pDataContainer = NULL;
1502 sal_Int32 AddonsOptions::m_nRefCount = 0;
1504 // constructor
1506 AddonsOptions::AddonsOptions()
1508 // Global access, must be guarded (multithreading!).
1509 MutexGuard aGuard( GetOwnStaticMutex() );
1510 // Increase our refcount ...
1511 ++m_nRefCount;
1512 // ... and initialize our data container only if it not already exist!
1513 if( m_pDataContainer == NULL )
1515 m_pDataContainer = new AddonsOptions_Impl;
1519 // destructor
1521 AddonsOptions::~AddonsOptions()
1523 // Global access, must be guarded (multithreading!)
1524 MutexGuard aGuard( GetOwnStaticMutex() );
1525 // Decrease our refcount.
1526 --m_nRefCount;
1527 // If last instance was deleted ...
1528 // we must destroy our static data container!
1529 if( m_nRefCount <= 0 )
1531 delete m_pDataContainer;
1532 m_pDataContainer = NULL;
1536 // public method
1538 bool AddonsOptions::HasAddonsMenu() const
1540 MutexGuard aGuard( GetOwnStaticMutex() );
1541 return m_pDataContainer->HasAddonsMenu();
1544 // public method
1546 sal_Int32 AddonsOptions::GetAddonsToolBarCount() const
1548 MutexGuard aGuard( GetOwnStaticMutex() );
1549 return m_pDataContainer->GetAddonsToolBarCount();
1552 // public method
1554 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const
1556 MutexGuard aGuard( GetOwnStaticMutex() );
1557 return m_pDataContainer->GetAddonsMenu();
1560 // public method
1562 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const
1564 MutexGuard aGuard( GetOwnStaticMutex() );
1565 return m_pDataContainer->GetAddonsMenuBarPart();
1568 // public method
1570 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
1572 MutexGuard aGuard( GetOwnStaticMutex() );
1573 return m_pDataContainer->GetAddonsToolBarPart( nIndex );
1576 // public method
1578 const OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
1580 MutexGuard aGuard( GetOwnStaticMutex() );
1581 return m_pDataContainer->GetAddonsToolbarResourceName( nIndex );
1584 // public method
1586 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const
1588 MutexGuard aGuard( GetOwnStaticMutex() );
1589 return m_pDataContainer->GetAddonsHelpMenu();
1592 // public method
1594 const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const
1596 MutexGuard aGuard( GetOwnStaticMutex() );
1597 return m_pDataContainer->GetMergeMenuInstructions();
1600 // public method
1602 bool AddonsOptions::GetMergeToolbarInstructions(
1603 const OUString& rToolbarName,
1604 MergeToolbarInstructionContainer& rToolbarInstructions ) const
1606 MutexGuard aGuard( GetOwnStaticMutex() );
1607 return m_pDataContainer->GetMergeToolbarInstructions(
1608 rToolbarName, rToolbarInstructions );
1611 const MergeStatusbarInstructionContainer& AddonsOptions::GetMergeStatusbarInstructions() const
1613 MutexGuard aGuard( GetOwnStaticMutex() );
1614 return m_pDataContainer->GetMergeStatusbarInstructions();
1617 // public method
1619 Image AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale ) const
1621 MutexGuard aGuard( GetOwnStaticMutex() );
1622 return m_pDataContainer->GetImageFromURL( aURL, bBig, bNoScale );
1625 // public method
1627 Image AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig ) const
1629 return GetImageFromURL( aURL, bBig, false );
1632 Mutex& AddonsOptions::GetOwnStaticMutex()
1634 // Initialize static mutex only for one time!
1635 static Mutex* pMutex = NULL;
1636 // If these method first called (Mutex not already exist!) ...
1637 if( pMutex == NULL )
1639 // ... we must create a new one. Protect follow code with the global mutex -
1640 // It must be - we create a static variable!
1641 MutexGuard aGuard( Mutex::getGlobalMutex() );
1642 // We must check our pointer again - because it can be that another instance of our class will be fastr then these!
1643 if( pMutex == NULL )
1645 // Create the new mutex and set it for return on static variable.
1646 static Mutex aMutex;
1647 pMutex = &aMutex;
1650 // Return new created or already existing mutex object.
1651 return *pMutex;
1654 IMPL_STATIC_LINK_NOARG( AddonsOptions, Notify )
1656 MutexGuard aGuard( GetOwnStaticMutex() );
1657 m_pDataContainer->ReadConfigurationData();
1658 return 0;
1663 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */