Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/framework/source/fwe/classes/addonsoptions.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
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>
38
39
#include <algorithm>
40
#include <string_view>
41
#include <unordered_map>
42
#include <vector>
43
44
//  namespaces
45
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;
52
53
constexpr OUStringLiteral ROOTNODE_ADDONMENU = u"Office.Addons";
54
constexpr OUStringLiteral PATHDELIMITER = u"/";
55
constexpr OUString SEPARATOR_URL = u"private:separator"_ustr;
56
57
0
#define PROPERTYNAME_URL                                ADDONSMENUITEM_STRING_URL
58
0
#define PROPERTYNAME_TITLE                              ADDONSMENUITEM_STRING_TITLE
59
0
#define PROPERTYNAME_TARGET                             ADDONSMENUITEM_STRING_TARGET
60
0
#define PROPERTYNAME_IMAGEIDENTIFIER                    ADDONSMENUITEM_STRING_IMAGEIDENTIFIER
61
0
#define PROPERTYNAME_CONTEXT                            ADDONSMENUITEM_STRING_CONTEXT
62
0
#define PROPERTYNAME_SUBMENU                            ADDONSMENUITEM_STRING_SUBMENU
63
64
constexpr OUStringLiteral IMAGES_NODENAME = u"UserDefinedImages";
65
66
// The following order is mandatory. Please add properties at the end!
67
0
#define INDEX_URL               0
68
0
#define INDEX_TITLE             1
69
0
#define INDEX_IMAGEIDENTIFIER   2
70
0
#define INDEX_TARGET            3
71
0
#define INDEX_CONTEXT           4
72
0
#define INDEX_SUBMENU           5
73
0
#define INDEX_CONTROLTYPE       6
74
0
#define INDEX_WIDTH             7
75
0
#define INDEX_ALIGN             8
76
0
#define INDEX_AUTOSIZE          9
77
0
#define INDEX_OWNERDRAW         10
78
0
#define INDEX_MANDATORY         11
79
0
#define INDEX_STYLE             12
80
#define PROPERTYCOUNT_INDEX     13
81
82
// The following order is mandatory. Please add properties at the end!
83
0
#define PROPERTYCOUNT_MENUITEM                          6
84
0
#define OFFSET_MENUITEM_URL                             0
85
0
#define OFFSET_MENUITEM_TITLE                           1
86
0
#define OFFSET_MENUITEM_IMAGEIDENTIFIER                 2
87
0
#define OFFSET_MENUITEM_TARGET                          3
88
0
#define OFFSET_MENUITEM_CONTEXT                         4
89
0
#define OFFSET_MENUITEM_SUBMENU                         5
90
91
// The following order is mandatory. Please add properties at the end!
92
0
#define PROPERTYCOUNT_POPUPMENU                         4
93
0
#define OFFSET_POPUPMENU_TITLE                          0
94
0
#define OFFSET_POPUPMENU_CONTEXT                        1
95
0
#define OFFSET_POPUPMENU_SUBMENU                        2
96
0
#define OFFSET_POPUPMENU_URL                            3   // Used for property set
97
98
// The following order is mandatory. Please add properties at the end!
99
0
#define PROPERTYCOUNT_TOOLBARITEM                       7
100
0
#define OFFSET_TOOLBARITEM_URL                          0
101
0
#define OFFSET_TOOLBARITEM_TITLE                        1
102
0
#define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER              2
103
0
#define OFFSET_TOOLBARITEM_TARGET                       3
104
0
#define OFFSET_TOOLBARITEM_CONTEXT                      4
105
0
#define OFFSET_TOOLBARITEM_CONTROLTYPE                  5
106
0
#define OFFSET_TOOLBARITEM_WIDTH                        6
107
108
// The following order is mandatory. Please add properties at the end!
109
0
#define PROPERTYCOUNT_NOTEBOOKBARITEM                   8
110
0
#define OFFSET_NOTEBOOKBARITEM_URL                      0
111
0
#define OFFSET_NOTEBOOKBARITEM_TITLE                    1
112
0
#define OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER          2
113
0
#define OFFSET_NOTEBOOKBARITEM_TARGET                   3
114
0
#define OFFSET_NOTEBOOKBARITEM_CONTEXT                  4
115
0
#define OFFSET_NOTEBOOKBARITEM_CONTROLTYPE              5
116
0
#define OFFSET_NOTEBOOKBARITEM_WIDTH                    6
117
0
#define OFFSET_NOTEBOOKBARITEM_STYLE                    7
118
119
// The following order is mandatory. Please add properties at the end!
120
0
#define PROPERTYCOUNT_STATUSBARITEM                     8
121
0
#define OFFSET_STATUSBARITEM_URL                        0
122
0
#define OFFSET_STATUSBARITEM_TITLE                      1
123
0
#define OFFSET_STATUSBARITEM_CONTEXT                    2
124
0
#define OFFSET_STATUSBARITEM_ALIGN                      3
125
0
#define OFFSET_STATUSBARITEM_AUTOSIZE                   4
126
0
#define OFFSET_STATUSBARITEM_OWNERDRAW                  5
127
0
#define OFFSET_STATUSBARITEM_MANDATORY                  6
128
0
#define OFFSET_STATUSBARITEM_WIDTH                      7
129
130
// The following order is mandatory. Please add properties at the end!
131
0
#define PROPERTYCOUNT_IMAGES                            8
132
0
#define PROPERTYCOUNT_EMBEDDED_IMAGES                   2
133
0
#define OFFSET_IMAGES_SMALL                             0
134
0
#define OFFSET_IMAGES_BIG                               1
135
0
#define OFFSET_IMAGES_SMALLHC                           2
136
0
#define OFFSET_IMAGES_BIGHC                             3
137
0
#define OFFSET_IMAGES_SMALL_URL                         4
138
0
#define OFFSET_IMAGES_BIG_URL                           5
139
0
#define OFFSET_IMAGES_SMALLHC_URL                       6
140
0
#define OFFSET_IMAGES_BIGHC_URL                         7
141
142
#define PROPERTYCOUNT_MERGE_MENUBAR                     6
143
0
#define OFFSET_MERGEMENU_MERGEPOINT                     0
144
0
#define OFFSET_MERGEMENU_MERGECOMMAND                   1
145
0
#define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER          2
146
0
#define OFFSET_MERGEMENU_MERGEFALLBACK                  3
147
0
#define OFFSET_MERGEMENU_MERGECONTEXT                   4
148
0
#define OFFSET_MERGEMENU_MENUITEMS                      5
149
150
#define PROPERTYCOUNT_MERGE_TOOLBAR                     7
151
0
#define OFFSET_MERGETOOLBAR_TOOLBAR                     0
152
0
#define OFFSET_MERGETOOLBAR_MERGEPOINT                  1
153
0
#define OFFSET_MERGETOOLBAR_MERGECOMMAND                2
154
0
#define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER       3
155
0
#define OFFSET_MERGETOOLBAR_MERGEFALLBACK               4
156
0
#define OFFSET_MERGETOOLBAR_MERGECONTEXT                5
157
0
#define OFFSET_MERGETOOLBAR_TOOLBARITEMS                6
158
159
#define PROPERTYCOUNT_MERGE_NOTEBOOKBAR                 7
160
0
#define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR             0
161
0
#define OFFSET_MERGENOTEBOOKBAR_MERGEPOINT              1
162
0
#define OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND            2
163
0
#define OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER   3
164
0
#define OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK           4
165
0
#define OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT            5
166
0
#define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS        6
167
168
#define PROPERTYCOUNT_MERGE_STATUSBAR                   6
169
0
#define OFFSET_MERGESTATUSBAR_MERGEPOINT                0
170
0
#define OFFSET_MERGESTATUSBAR_MERGECOMMAND              1
171
0
#define OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER     2
172
0
#define OFFSET_MERGESTATUSBAR_MERGEFALLBACK             3
173
0
#define OFFSET_MERGESTATUSBAR_MERGECONTEXT              4
174
0
#define OFFSET_MERGESTATUSBAR_STATUSBARITEMS            5
175
176
//  private declarations!
177
178
/*-****************************************************************************************************************
179
    @descr  struct to hold information about one menu entry.
180
****************************************************************************************************************-*/
181
182
namespace framework
183
{
184
185
class AddonsOptions_Impl : public ConfigItem
186
{
187
188
    //  public methods
189
190
    public:
191
192
        //  constructor / destructor
193
194
         AddonsOptions_Impl();
195
        virtual ~AddonsOptions_Impl() override;
196
197
        //  overridden methods of baseclass
198
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.
204
205
            @seealso    baseclass ConfigItem
206
207
            @param      "lPropertyNames" is the list of properties which should be updated.
208
        *//*-*****************************************************************************************************/
209
210
        virtual void Notify( const Sequence< OUString >& lPropertyNames ) override;
211
212
        //  public interface
213
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
        *//*-*****************************************************************************************************/
219
220
        bool                                            HasAddonsMenu        () const;
221
        sal_Int32                                       GetAddonsToolBarCount() const;
222
        sal_Int32                                       GetAddonsNotebookBarCount() const;
223
0
        const Sequence< Sequence< PropertyValue > >&    GetAddonsMenu        () const { return m_aCachedMenuProperties;}
224
0
        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
        const OUString &                                GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
228
        const OUString &                                GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const;
229
0
        const Sequence< Sequence< PropertyValue > >&    GetAddonsHelpMenu    () const { return m_aCachedHelpMenuProperties;}
230
        Bitmap                                          GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale );
231
0
        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
0
        const MergeStatusbarInstructionContainer&       GetMergeStatusbarInstructions() const { return m_aCachedStatusbarMergingInstructions;}
235
        void                                            ReadConfigurationData();
236
237
    private:
238
        enum ImageSize
239
        {
240
            IMGSIZE_SMALL = 0,
241
            IMGSIZE_BIG
242
        };
243
244
        struct OneImageEntry
245
        {
246
            Bitmap aScaled;   ///< cached scaled image
247
            Bitmap aImage;    ///< original un-scaled image
248
            OUString aURL;      ///< URL in case it is not loaded yet
249
        };
250
251
        struct ImageEntry
252
        {
253
            // if the image is set, it was embedded in some way,
254
            // otherwise we use the associated URL to load on demand
255
256
            // accessed in this order
257
            OneImageEntry aSizeEntry[2];
258
0
            ImageEntry() {}
259
            void addImage(ImageSize eSize, const Bitmap &rImage);
260
            void addImage(ImageSize eSize, const OUString &rURL);
261
        };
262
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;
269
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
        *//*-*****************************************************************************************************/
277
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 );
284
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 );
291
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
        static 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 );
301
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
        static Bitmap        ReadImageFromURL( const OUString& aURL );
306
        bool                 HasAssociatedImages( const OUString& aURL );
307
        static void          SubstituteVariables( OUString& aURL );
308
309
        void                 ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
310
        OUString             GeneratePrefixURL();
311
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;
319
320
        Sequence< OUString > GetPropertyNamesStatusbarItem( std::u16string_view aPropertyRootNode ) const;
321
        Sequence< OUString > GetPropertyNamesImages( std::u16string_view aPropertyRootNode ) const;
322
        static bool CreateImageFromSequence( Bitmap& rImage, Sequence< sal_Int8 >& rBitmapDataSeq );
323
324
        DECL_LINK(NotifyEvent, void*, void);
325
326
        virtual void ImplCommit() override;
327
328
    //  private member
329
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;
354
};
355
356
void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize, const Bitmap& rImage)
357
0
{
358
0
    aSizeEntry[static_cast<int>(eSize)].aImage = rImage;
359
0
}
360
361
void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize, const OUString &rURL)
362
0
{
363
0
    aSizeEntry[static_cast<int>(eSize)].aURL = rURL;
364
0
}
365
366
//  constructor
367
368
AddonsOptions_Impl::AddonsOptions_Impl()
369
    // Init baseclasses first
370
0
    : ConfigItem( ROOTNODE_ADDONMENU ),
371
0
    m_nRootAddonPopupMenuId( 0 ),
372
0
    m_aPathDelimiter( PATHDELIMITER ),
373
0
    m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX_STR )
374
0
{
375
    // initialize array with fixed property names
376
0
    m_aPropNames[ INDEX_URL             ] = PROPERTYNAME_URL;
377
0
    m_aPropNames[ INDEX_TITLE           ] = PROPERTYNAME_TITLE;
378
0
    m_aPropNames[ INDEX_TARGET          ] = PROPERTYNAME_TARGET;
379
0
    m_aPropNames[ INDEX_IMAGEIDENTIFIER ] = PROPERTYNAME_IMAGEIDENTIFIER;
380
0
    m_aPropNames[ INDEX_CONTEXT         ] = PROPERTYNAME_CONTEXT;
381
0
    m_aPropNames[ INDEX_SUBMENU         ] = PROPERTYNAME_SUBMENU; // Submenu set!
382
0
    m_aPropNames[ INDEX_CONTROLTYPE     ] = "ControlType";
383
0
    m_aPropNames[ INDEX_WIDTH           ] = "Width";
384
0
    m_aPropNames[ INDEX_ALIGN           ] = "Alignment";
385
0
    m_aPropNames[ INDEX_AUTOSIZE        ] = "AutoSize";
386
0
    m_aPropNames[ INDEX_OWNERDRAW       ] = "OwnerDraw";
387
0
    m_aPropNames[ INDEX_MANDATORY       ] = "Mandatory";
388
0
    m_aPropNames[ INDEX_STYLE           ] = "Style";
389
390
    // initialize array with fixed images property names
391
0
    m_aPropImagesNames[ OFFSET_IMAGES_SMALL         ] = "ImageSmall";
392
0
    m_aPropImagesNames[ OFFSET_IMAGES_BIG           ] = "ImageBig";
393
0
    m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC       ] = "ImageSmallHC";
394
0
    m_aPropImagesNames[ OFFSET_IMAGES_BIGHC         ] = "ImageBigHC";
395
0
    m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL     ] = "ImageSmallURL";
396
0
    m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL       ] = "ImageBigURL";
397
0
    m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL   ] = "ImageSmallHCURL";
398
0
    m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL     ] = "ImageBigHCURL";
399
400
    // initialize array with fixed merge menu property names
401
0
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT    ] = "MergePoint";
402
0
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND  ] = "MergeCommand";
403
0
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
404
0
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = "MergeFallback";
405
0
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT  ] = "MergeContext";
406
0
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS     ] = "MenuItems";
407
408
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR               ] = "MergeToolBar";
409
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT            ] = "MergePoint";
410
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND          ] = "MergeCommand";
411
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
412
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK         ] = "MergeFallback";
413
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT          ] = "MergeContext";
414
0
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS          ] = "ToolBarItems";
415
416
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR           ] = "MergeNotebookBar";
417
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEPOINT            ] = "MergePoint";
418
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND          ] = "MergeCommand";
419
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
420
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK         ] = "MergeFallback";
421
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT          ] = "MergeContext";
422
0
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS      ] = "NotebookBarItems";
423
424
0
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT            ] = "MergePoint";
425
0
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND          ] = "MergeCommand";
426
0
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
427
0
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK         ] = "MergeFallback";
428
0
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT          ] = "MergeContext";
429
0
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS        ] = "StatusBarItems";
430
431
0
    ReadConfigurationData();
432
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
0
    Sequence<OUString> aNotifySeq { u"AddonUI"_ustr };
436
0
    EnableNotification( aNotifySeq );
437
0
}
438
439
//  destructor
440
441
AddonsOptions_Impl::~AddonsOptions_Impl()
442
0
{
443
0
    assert(!IsModified()); // should have been committed
444
0
}
445
446
void AddonsOptions_Impl::ReadConfigurationData()
447
0
{
448
    // reset members to be read again from configuration
449
0
    m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >();
450
0
    m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >();
451
0
    m_aCachedToolBarPartProperties = AddonToolBars();
452
0
    m_aCachedNotebookBarPartProperties = AddonNotebookBars();
453
0
    m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
454
0
    m_aCachedToolBarPartResourceNames.clear();
455
0
    m_aCachedNotebookBarPartResourceNames.clear();
456
0
    m_aImageManager = ImageManager();
457
458
0
    ReadAddonMenuSet( m_aCachedMenuProperties );
459
0
    ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
460
0
    ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
461
0
    ReadOfficeNotebookBarSet( m_aCachedNotebookBarPartProperties, m_aCachedNotebookBarPartResourceNames );
462
463
0
    ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
464
0
    ReadImages( m_aImageManager );
465
466
0
    m_aCachedMergeMenuInsContainer.clear();
467
0
    m_aCachedToolbarMergingInstructions.clear();
468
0
    m_aCachedNotebookBarMergingInstructions.clear();
469
0
    m_aCachedStatusbarMergingInstructions.clear();
470
471
0
    ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
472
0
    ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
473
0
    ReadNotebookBarMergeInstructions( m_aCachedNotebookBarMergingInstructions );
474
0
    ReadStatusbarMergeInstructions( m_aCachedStatusbarMergingInstructions );
475
0
}
476
477
//  public method
478
479
void AddonsOptions_Impl::Notify( const Sequence< OUString >& /*lPropertyNames*/ )
480
0
{
481
0
    Application::PostUserEvent(LINK(this, AddonsOptions_Impl, NotifyEvent));
482
0
}
483
484
//  public method
485
486
void AddonsOptions_Impl::ImplCommit()
487
0
{
488
0
    SAL_WARN("fwk", "AddonsOptions_Impl::ImplCommit(): Not implemented yet!");
489
0
}
490
491
//  public method
492
493
bool AddonsOptions_Impl::HasAddonsMenu() const
494
0
{
495
0
    return m_aCachedMenuProperties.hasElements();
496
0
}
497
498
//  public method
499
500
sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
501
0
{
502
0
    return m_aCachedToolBarPartProperties.size();
503
0
}
504
505
//  public method
506
507
sal_Int32 AddonsOptions_Impl::GetAddonsNotebookBarCount() const
508
0
{
509
0
    return m_aCachedNotebookBarPartProperties.size();
510
0
}
511
512
//  public method
513
514
const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
515
0
{
516
0
    if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() )
517
0
        return m_aCachedToolBarPartProperties[nIndex];
518
0
    else
519
0
        return m_aEmptyAddonToolBar;
520
0
}
521
522
//  public method
523
524
const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
525
0
{
526
0
    if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedNotebookBarPartProperties.size() )
527
0
        return m_aCachedNotebookBarPartProperties[nIndex];
528
0
    else
529
0
        return m_aEmptyAddonNotebookBar;
530
0
}
531
532
//  public method
533
534
const OUString & AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
535
0
{
536
0
    if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
537
0
        return m_aCachedToolBarPartResourceNames[nIndex];
538
0
    else
539
0
        return EMPTY_OUSTRING;
540
0
}
541
542
//  public method
543
544
const OUString & AddonsOptions_Impl::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
545
0
{
546
0
    if ( nIndex < m_aCachedNotebookBarPartResourceNames.size() )
547
0
        return m_aCachedNotebookBarPartResourceNames[nIndex];
548
0
    else
549
0
        return EMPTY_OUSTRING;
550
0
}
551
552
//  public method
553
554
bool AddonsOptions_Impl::GetMergeToolbarInstructions(
555
    const OUString& rToolbarName,
556
    MergeToolbarInstructionContainer& rToolbarInstructions ) const
557
0
{
558
0
    ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName );
559
0
    if ( pIter != m_aCachedToolbarMergingInstructions.end() )
560
0
    {
561
0
        rToolbarInstructions = pIter->second;
562
0
        return true;
563
0
    }
564
0
    else
565
0
        return false;
566
0
}
567
568
//  public method
569
570
bool AddonsOptions_Impl::GetMergeNotebookBarInstructions(
571
    const OUString& rNotebookBarName,
572
    MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
573
0
{
574
0
    NotebookBarMergingInstructions::const_iterator pIter = m_aCachedNotebookBarMergingInstructions.find( rNotebookBarName );
575
0
    if ( pIter != m_aCachedNotebookBarMergingInstructions.end() )
576
0
    {
577
0
        rNotebookBarInstructions = pIter->second;
578
0
        return true;
579
0
    }
580
0
    else
581
0
        return false;
582
0
}
583
584
//  public method
585
586
static Bitmap ScaleImage( const Bitmap &rImage, bool bBig )
587
0
{
588
0
    Size aSize = ToolBox::GetDefaultImageSize(bBig ? ToolBoxButtonSize::Large : ToolBoxButtonSize::Small);
589
0
    Bitmap aScaleBmp(rImage);
590
0
    SAL_INFO("fwk", "Addons: expensive scale image from "
591
0
             << aScaleBmp.GetSizePixel() << " to " << aSize);
592
0
    aScaleBmp.Scale(aSize, BmpScaleFlag::BestQuality);
593
0
    return aScaleBmp;
594
0
}
595
596
Bitmap AddonsOptions_Impl::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale )
597
0
{
598
0
    Bitmap aImage;
599
600
0
    SAL_INFO("fwk", "Expensive: Addons GetImageFromURL " << aURL <<
601
0
             " big " << (bBig?"big":"little") <<
602
0
             " scale " << (bNoScale ? "noscale" : "scale"));
603
604
0
    ImageManager::iterator pIter = m_aImageManager.find(aURL);
605
0
    if ( pIter != m_aImageManager.end() )
606
0
    {
607
0
        ImageSize eSize = bBig ? IMGSIZE_BIG : IMGSIZE_SMALL;
608
0
        int nIdx = static_cast<int>(eSize);
609
0
        int nOtherIdx = nIdx ? 0 : 1;
610
611
0
        OneImageEntry& rSizeEntry = pIter->second.aSizeEntry[nIdx];
612
0
        OneImageEntry& rOtherEntry = pIter->second.aSizeEntry[nOtherIdx];
613
        // actually read the image ...
614
0
        if (rSizeEntry.aImage.IsEmpty())
615
0
            rSizeEntry.aImage = ReadImageFromURL(rSizeEntry.aURL);
616
617
0
        if (rSizeEntry.aImage.IsEmpty())
618
0
        { // try the other size and scale it
619
0
            aImage = ScaleImage(ReadImageFromURL(rOtherEntry.aURL), bBig);
620
0
            rSizeEntry.aImage = aImage;
621
0
            if (rSizeEntry.aImage.IsEmpty())
622
0
                SAL_WARN("fwk", "failed to load addons image " << aURL);
623
0
        }
624
625
        // FIXME: bNoScale is not terribly meaningful or useful
626
627
0
        if (aImage.IsEmpty() && bNoScale)
628
0
            aImage = rSizeEntry.aImage;
629
630
0
        if (aImage.IsEmpty() && !rSizeEntry.aScaled.IsEmpty())
631
0
            aImage = rSizeEntry.aScaled;
632
633
0
        else // scale to the correct size for the theme / toolbox
634
0
        {
635
0
            aImage = rSizeEntry.aImage;
636
0
            if (aImage.IsEmpty()) // use and scale the other if one size is missing
637
0
                aImage = rOtherEntry.aImage;
638
639
0
            aImage = ScaleImage(aImage, bBig);
640
0
            rSizeEntry.aScaled = aImage; // cache for next time
641
0
        }
642
0
    }
643
644
0
    return aImage;
645
0
}
646
647
void AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
648
0
{
649
    // Read the AddonMenu set and fill property sequences
650
0
    OUString             aAddonMenuNodeName( u"AddonUI/AddonMenu"_ustr );
651
0
    Sequence< OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
652
0
    OUString             aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter );
653
654
0
    sal_uInt32              nCount = aAddonMenuNodeSeq.getLength();
655
0
    sal_uInt32              nIndex = 0;
656
0
    Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
657
0
    auto pMenuItem = aMenuItem.getArray();
658
    // Init the property value sequence
659
0
    pMenuItem[ OFFSET_MENUITEM_URL              ].Name = m_aPropNames[ INDEX_URL            ];
660
0
    pMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = m_aPropNames[ INDEX_TITLE          ];
661
0
    pMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = m_aPropNames[ INDEX_TARGET         ];
662
0
    pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
663
0
    pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = m_aPropNames[ INDEX_CONTEXT        ];
664
0
    pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = m_aPropNames[ INDEX_SUBMENU        ];  // Submenu set!
665
666
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
667
0
    {
668
0
        OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] );
669
670
        // Read the MenuItem
671
0
        if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) )
672
0
        {
673
            // Successfully read a menu item, append to our list
674
0
            sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1;
675
0
            rAddonMenuSeq.realloc( nMenuItemCount );
676
0
            rAddonMenuSeq.getArray()[nIndex++] = aMenuItem;
677
0
        }
678
0
    }
679
0
}
680
681
void AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
682
0
{
683
    // Read the AddonMenu set and fill property sequences
684
0
    OUString             aAddonHelpMenuNodeName( u"AddonUI/OfficeHelp"_ustr );
685
0
    Sequence< OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
686
0
    OUString             aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter );
687
688
0
    sal_uInt32              nCount = aAddonHelpMenuNodeSeq.getLength();
689
0
    sal_uInt32              nIndex = 0;
690
0
    Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
691
0
    auto pMenuItem = aMenuItem.getArray();
692
    // Init the property value sequence
693
0
    pMenuItem[ OFFSET_MENUITEM_URL              ].Name = m_aPropNames[ INDEX_URL            ];
694
0
    pMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = m_aPropNames[ INDEX_TITLE          ];
695
0
    pMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = m_aPropNames[ INDEX_TARGET         ];
696
0
    pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
697
0
    pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = m_aPropNames[ INDEX_CONTEXT        ];
698
0
    pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = m_aPropNames[ INDEX_SUBMENU        ];  // Submenu set!
699
700
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
701
0
    {
702
0
        OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );
703
704
        // Read the MenuItem
705
0
        if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, true ) )
706
0
        {
707
            // Successfully read a menu item, append to our list
708
0
            sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
709
0
            rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
710
0
            rAddonOfficeHelpMenuSeq.getArray()[nIndex++] = aMenuItem;
711
0
        }
712
0
    }
713
0
}
714
715
void AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
716
0
{
717
    // Read the OfficeMenuBar set and fill property sequences
718
0
    OUString             aAddonMenuBarNodeName( u"AddonUI/OfficeMenuBar"_ustr );
719
0
    Sequence< OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
720
0
    OUString             aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter );
721
722
0
    sal_uInt32              nCount = aAddonMenuBarNodeSeq.getLength();
723
0
    sal_uInt32              nIndex = 0;
724
0
    Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU );
725
0
    auto pPopupMenu = aPopupMenu.getArray();
726
    // Init the property value sequence
727
0
    pPopupMenu[ OFFSET_POPUPMENU_TITLE      ].Name = m_aPropNames[ INDEX_TITLE  ];
728
0
    pPopupMenu[ OFFSET_POPUPMENU_CONTEXT    ].Name = m_aPropNames[ INDEX_CONTEXT];
729
0
    pPopupMenu[ OFFSET_POPUPMENU_SUBMENU    ].Name = m_aPropNames[ INDEX_SUBMENU];
730
0
    pPopupMenu[ OFFSET_POPUPMENU_URL        ].Name = m_aPropNames[ INDEX_URL    ];
731
732
0
    StringToIndexMap aTitleToIndexMap;
733
0
    auto pAddonOfficeMenuBarSeq = rAddonOfficeMenuBarSeq.getArray();
734
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
735
0
    {
736
0
        OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );
737
738
        // Read the MenuItem
739
0
        if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
740
0
        {
741
            // Successfully read a popup menu, append to our list
742
0
            OUString aPopupTitle;
743
0
            if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle )
744
0
            {
745
0
                StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle );
746
0
                if ( pIter != aTitleToIndexMap.end() )
747
0
                {
748
                    // title already there => concat both popup menus
749
0
                    Sequence< PropertyValue >& rOldPopupMenu = pAddonOfficeMenuBarSeq[pIter->second];
750
0
                    AppendPopupMenu( rOldPopupMenu, aPopupMenu );
751
0
                }
752
0
                else
753
0
                {
754
                    // not found
755
0
                    sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1;
756
0
                    rAddonOfficeMenuBarSeq.realloc( nMenuItemCount );
757
0
                    pAddonOfficeMenuBarSeq = rAddonOfficeMenuBarSeq.getArray();
758
0
                    pAddonOfficeMenuBarSeq[nIndex] = aPopupMenu;
759
0
                    aTitleToIndexMap.emplace( aPopupTitle, nIndex );
760
0
                    ++nIndex;
761
0
                }
762
0
            }
763
0
        }
764
0
    }
765
0
}
766
767
void AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames )
768
0
{
769
    // Read the OfficeToolBar set and fill property sequences
770
0
    OUString             aAddonToolBarNodeName( u"AddonUI/OfficeToolBar"_ustr );
771
0
    Sequence< OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
772
0
    OUString             aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );
773
774
0
    sal_uInt32           nCount = aAddonToolBarNodeSeq.getLength();
775
776
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
777
0
    {
778
0
        OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
779
0
        rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
780
0
        rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
781
0
        ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
782
0
    }
783
0
}
784
785
bool AddonsOptions_Impl::ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
786
0
{
787
0
    sal_uInt32               nToolBarItemCount       = rAddonOfficeToolBarSeq.getLength();
788
0
    OUString                 aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
789
0
    Sequence< OUString >     aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName );
790
0
    Sequence< PropertyValue >   aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
791
0
    auto pToolBarItem = aToolBarItem.getArray();
792
    // Init the property value sequence
793
0
    pToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Name = m_aPropNames[ INDEX_URL            ];
794
0
    pToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Name = m_aPropNames[ INDEX_TITLE          ];
795
0
    pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
796
0
    pToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Name = m_aPropNames[ INDEX_TARGET         ];
797
0
    pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Name = m_aPropNames[ INDEX_CONTEXT        ];
798
0
    pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Name = m_aPropNames[ INDEX_CONTROLTYPE    ];
799
0
    pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Name = m_aPropNames[ INDEX_WIDTH          ];
800
801
0
    sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength();
802
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
803
0
    {
804
0
        OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );
805
806
        // Read the ToolBarItem
807
0
        if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
808
0
        {
809
            // Successfully read a toolbar item, append to our list
810
0
            sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
811
0
            rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
812
0
            rAddonOfficeToolBarSeq.getArray()[nAddonCount] = aToolBarItem;
813
0
        }
814
0
    }
815
816
0
    return ( o3tl::make_unsigned(rAddonOfficeToolBarSeq.getLength()) > nToolBarItemCount );
817
0
}
818
819
void AddonsOptions_Impl::ReadOfficeNotebookBarSet(
820
    AddonNotebookBars& rAddonOfficeNotebookBars,
821
    std::vector<OUString>& rAddonOfficeNotebookBarResNames)
822
0
{
823
    // Read the OfficeToolBar set and fill property sequences
824
0
    OUString aAddonNotebookBarNodeName(u"AddonUI/OfficeNotebookBar"_ustr);
825
0
    Sequence<OUString> aAddonNotebookBarNodeSeq = GetNodeNames(aAddonNotebookBarNodeName);
826
0
    OUString aAddonNotebookBarNode(aAddonNotebookBarNodeName + m_aPathDelimiter);
827
828
0
    sal_uInt32 nCount = aAddonNotebookBarNodeSeq.getLength();
829
830
0
    for (sal_uInt32 n = 0; n < nCount; n++)
831
0
    {
832
0
        OUString aNotebookBarItemNode(aAddonNotebookBarNode + aAddonNotebookBarNodeSeq[n]);
833
0
        rAddonOfficeNotebookBarResNames.push_back(aAddonNotebookBarNodeSeq[n]);
834
0
        rAddonOfficeNotebookBars.push_back(m_aEmptyAddonNotebookBar);
835
0
        ReadNotebookBarItemSet(aNotebookBarItemNode, rAddonOfficeNotebookBars[n]);
836
0
    }
837
0
}
838
839
bool AddonsOptions_Impl::ReadNotebookBarItemSet(
840
    const OUString& rNotebookBarItemSetNodeName,
841
    Sequence<Sequence<PropertyValue>>& rAddonOfficeNotebookBarSeq)
842
0
{
843
0
    sal_uInt32 nNotebookBarItemCount = rAddonOfficeNotebookBarSeq.getLength();
844
0
    OUString aAddonNotebookBarItemSetNode(rNotebookBarItemSetNodeName + m_aPathDelimiter);
845
0
    Sequence<OUString> aAddonNotebookBarItemSetNodeSeq = GetNodeNames(rNotebookBarItemSetNodeName);
846
0
    Sequence<PropertyValue> aNotebookBarItem(PROPERTYCOUNT_NOTEBOOKBARITEM);
847
0
    auto pNotebookBarItem = aNotebookBarItem.getArray();
848
    // Init the property value sequence
849
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_URL].Name = m_aPropNames[INDEX_URL];
850
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TITLE].Name = m_aPropNames[INDEX_TITLE];
851
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER].Name
852
0
        = m_aPropNames[INDEX_IMAGEIDENTIFIER];
853
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TARGET].Name = m_aPropNames[INDEX_TARGET];
854
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTEXT].Name = m_aPropNames[INDEX_CONTEXT];
855
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTROLTYPE].Name = m_aPropNames[INDEX_CONTROLTYPE];
856
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_WIDTH].Name = m_aPropNames[INDEX_WIDTH];
857
0
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_STYLE].Name = m_aPropNames[INDEX_STYLE];
858
859
0
    sal_uInt32 nCount = aAddonNotebookBarItemSetNodeSeq.getLength();
860
0
    for (sal_uInt32 n = 0; n < nCount; n++)
861
0
    {
862
0
        OUString aNotebookBarItemNode(aAddonNotebookBarItemSetNode
863
0
                                      + aAddonNotebookBarItemSetNodeSeq[n]);
864
        // Read the NotebookBarItem
865
0
        if (ReadNotebookBarItem(aNotebookBarItemNode, aNotebookBarItem))
866
0
        {
867
            // Successfully read a toolbar item, append to our list
868
0
            sal_uInt32 nAddonCount = rAddonOfficeNotebookBarSeq.getLength();
869
0
            rAddonOfficeNotebookBarSeq.realloc(nAddonCount + 1);
870
0
            rAddonOfficeNotebookBarSeq.getArray()[nAddonCount] = aNotebookBarItem;
871
0
        }
872
0
    }
873
874
0
    return (o3tl::make_unsigned(rAddonOfficeNotebookBarSeq.getLength())
875
0
            > nNotebookBarItemCount);
876
0
}
877
878
void AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
879
0
{
880
    // Read the user-defined Images set and fill image manager
881
0
    OUString                aAddonImagesNodeName( u"AddonUI/Images"_ustr );
882
0
    Sequence< OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
883
0
    OUString                aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );
884
885
0
    sal_uInt32              nCount = aAddonImagesNodeSeq.getLength();
886
887
    // Init the property value sequence
888
0
    OUString                aURL;
889
890
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
891
0
    {
892
0
        OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );
893
894
        // Create sequence for data access
895
0
        Sequence< OUString > aAddonImageItemNodePropNames = { aImagesItemNode +
896
0
            m_aPathDelimiter +
897
0
            m_aPropNames[ OFFSET_MENUITEM_URL ] };
898
899
0
        Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );
900
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
0
        if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
904
0
            !aURL.isEmpty() &&
905
0
            !HasAssociatedImages( aURL ))
906
0
        {
907
0
            OUString aImagesUserDefinedItemNode = aImagesItemNode +
908
0
                m_aPathDelimiter +
909
0
                IMAGES_NODENAME +
910
0
                m_aPathDelimiter;
911
912
            // Read a user-defined images data
913
0
            std::unique_ptr<ImageEntry> pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
914
0
            if ( pImageEntry )
915
0
            {
916
                // Successfully read a user-defined images item, put it into our image manager
917
0
                aImageManager.emplace( aURL, std::move(*pImageEntry) );
918
0
            }
919
0
        }
920
0
    }
921
0
}
922
923
OUString AddonsOptions_Impl::GeneratePrefixURL()
924
0
{
925
    // Create a unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu.
926
0
    return m_aRootAddonPopupMenuURLPrexfix + OUString::number( ++m_nRootAddonPopupMenuId );
927
0
}
928
929
void AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer )
930
0
{
931
0
    static constexpr OUString aMenuMergeRootName( u"AddonUI/OfficeMenuBarMerging/"_ustr );
932
933
0
    Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );
934
935
0
    sal_uInt32           nCount = aAddonMergeNodesSeq.getLength();
936
937
    // Init the property value sequence
938
0
    Sequence< OUString > aNodePropNames( 5 );
939
0
    auto pNodePropNames = aNodePropNames.getArray();
940
941
0
    for ( sal_uInt32 i = 0; i < nCount; i++ )
942
0
    {
943
0
        OUString aMergeAddonInstructions( aMenuMergeRootName + aAddonMergeNodesSeq[i] );
944
945
0
        Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
946
0
        sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();
947
948
0
        for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
949
0
        {
950
0
            OUString aMergeAddonInstructionBase =  aMergeAddonInstructions +
951
0
                m_aPathDelimiter +
952
0
                aAddonInstMergeNodesSeq[j] +
953
0
                m_aPathDelimiter;
954
955
            // Create sequence for data access
956
0
            pNodePropNames[0] = aMergeAddonInstructionBase +
957
0
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ];
958
959
0
            pNodePropNames[1] = aMergeAddonInstructionBase +
960
0
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ];
961
962
0
            pNodePropNames[2] = aMergeAddonInstructionBase +
963
0
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ];
964
965
0
            pNodePropNames[3] = aMergeAddonInstructionBase +
966
0
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ];
967
968
0
            pNodePropNames[4] = aMergeAddonInstructionBase +
969
0
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ];
970
971
0
            Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
972
973
0
            MergeMenuInstruction aMergeMenuInstruction;
974
0
            aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint;
975
0
            aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand;
976
0
            aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter;
977
0
            aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback;
978
0
            aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext;
979
980
0
            ReadMergeMenuData( aMergeAddonInstructionBase, aMergeMenuInstruction.aMergeMenu );
981
982
0
            aContainer.push_back(std::move(aMergeMenuInstruction));
983
0
        }
984
0
    }
985
0
}
986
987
void AddonsOptions_Impl::ReadMergeMenuData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
988
0
{
989
0
    OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );
990
991
0
    Sequence< OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
992
0
    aMergeMenuBaseNode += m_aPathDelimiter;
993
994
    // extend the node names to have full path strings
995
0
    for ( OUString& rName : asNonConstRange(aSubMenuNodeNames) )
996
0
        rName = aMergeMenuBaseNode + rName;
997
998
0
    ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
999
0
}
1000
1001
void AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions )
1002
0
{
1003
0
    static constexpr OUString aToolbarMergeRootName( u"AddonUI/OfficeToolbarMerging/"_ustr );
1004
1005
0
    Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
1006
0
    sal_uInt32           nCount = aAddonMergeNodesSeq.getLength();
1007
1008
    // Init the property value sequence
1009
0
    Sequence< OUString > aNodePropNames( 6 );
1010
0
    auto pNodePropNames = aNodePropNames.getArray();
1011
1012
0
    for ( sal_uInt32 i = 0; i < nCount; i++ )
1013
0
    {
1014
0
        OUString aMergeAddonInstructions( aToolbarMergeRootName + aAddonMergeNodesSeq[i] );
1015
1016
0
        Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
1017
0
        sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();
1018
1019
0
        for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
1020
0
        {
1021
0
            OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
1022
0
                m_aPathDelimiter +
1023
0
                aAddonInstMergeNodesSeq[j] +
1024
0
                m_aPathDelimiter;
1025
1026
            // Create sequence for data access
1027
0
            pNodePropNames[0] = aMergeAddonInstructionBase +
1028
0
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ];
1029
1030
0
            pNodePropNames[1] = aMergeAddonInstructionBase +
1031
0
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ];
1032
1033
0
            pNodePropNames[2] = aMergeAddonInstructionBase +
1034
0
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ];
1035
1036
0
            pNodePropNames[3] = aMergeAddonInstructionBase +
1037
0
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ];
1038
1039
0
            pNodePropNames[4] = aMergeAddonInstructionBase +
1040
0
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ];
1041
1042
0
            pNodePropNames[5] = aMergeAddonInstructionBase +
1043
0
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ];
1044
1045
0
            Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
1046
1047
0
            MergeToolbarInstruction aMergeToolbarInstruction;
1048
0
            aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar;
1049
0
            aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint;
1050
0
            aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand;
1051
0
            aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter;
1052
0
            aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback;
1053
0
            aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext;
1054
1055
0
            ReadMergeToolbarData( aMergeAddonInstructionBase,
1056
0
                                  aMergeToolbarInstruction.aMergeToolbarItems );
1057
1058
0
            MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ];
1059
0
            rVector.push_back(std::move(aMergeToolbarInstruction));
1060
0
        }
1061
0
    }
1062
0
}
1063
1064
void AddonsOptions_Impl::ReadMergeToolbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
1065
0
{
1066
0
    OUString aMergeToolbarBaseNode = aMergeAddonInstructionBase +
1067
0
        m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ];
1068
1069
0
    ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
1070
0
}
1071
1072
void AddonsOptions_Impl::ReadNotebookBarMergeInstructions(
1073
    NotebookBarMergingInstructions& rCachedNotebookBarMergingInstructions)
1074
0
{
1075
0
    static constexpr OUString aNotebookBarMergeRootName(u"AddonUI/OfficeNotebookBarMerging/"_ustr);
1076
1077
0
    Sequence<OUString> aAddonMergeNodesSeq = GetNodeNames(aNotebookBarMergeRootName);
1078
0
    sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();
1079
1080
    // Init the property value sequence
1081
0
    Sequence<OUString> aNodePropNames(6);
1082
0
    auto pNodePropNames = aNodePropNames.getArray();
1083
1084
0
    for (sal_uInt32 i = 0; i < nCount; i++)
1085
0
    {
1086
0
        OUString aMergeAddonInstructions(aNotebookBarMergeRootName + aAddonMergeNodesSeq[i]);
1087
1088
0
        Sequence<OUString> aAddonInstMergeNodesSeq = GetNodeNames(aMergeAddonInstructions);
1089
0
        sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
1090
1091
0
        for (sal_uInt32 j = 0; j < nCountAddons; j++)
1092
0
        {
1093
0
            OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
1094
0
                m_aPathDelimiter +
1095
0
                aAddonInstMergeNodesSeq[j] +
1096
0
                m_aPathDelimiter;
1097
1098
            // Create sequence for data access
1099
0
            pNodePropNames[0] = aMergeAddonInstructionBase +
1100
0
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR];
1101
1102
0
            pNodePropNames[1] = aMergeAddonInstructionBase +
1103
0
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEPOINT];
1104
1105
0
            pNodePropNames[2] = aMergeAddonInstructionBase +
1106
0
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND];
1107
1108
0
            pNodePropNames[3] = aMergeAddonInstructionBase +
1109
0
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER];
1110
1111
0
            pNodePropNames[4] = aMergeAddonInstructionBase +
1112
0
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK];
1113
1114
0
            pNodePropNames[5] = aMergeAddonInstructionBase +
1115
0
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT];
1116
1117
0
            Sequence<Any> aNodePropValues = GetProperties(aNodePropNames);
1118
1119
0
            MergeNotebookBarInstruction aMergeNotebookBarInstruction;
1120
0
            aNodePropValues[0] >>= aMergeNotebookBarInstruction.aMergeNotebookBar;
1121
0
            aNodePropValues[1] >>= aMergeNotebookBarInstruction.aMergePoint;
1122
0
            aNodePropValues[2] >>= aMergeNotebookBarInstruction.aMergeCommand;
1123
0
            aNodePropValues[3] >>= aMergeNotebookBarInstruction.aMergeCommandParameter;
1124
0
            aNodePropValues[4] >>= aMergeNotebookBarInstruction.aMergeFallback;
1125
0
            aNodePropValues[5] >>= aMergeNotebookBarInstruction.aMergeContext;
1126
1127
0
            ReadMergeNotebookBarData(aMergeAddonInstructionBase,
1128
0
                                     aMergeNotebookBarInstruction.aMergeNotebookBarItems);
1129
1130
0
            MergeNotebookBarInstructionContainer& rVector
1131
0
                = rCachedNotebookBarMergingInstructions[aMergeNotebookBarInstruction
1132
0
                                                            .aMergeNotebookBar];
1133
0
            rVector.push_back(std::move(aMergeNotebookBarInstruction));
1134
0
        }
1135
0
    }
1136
0
}
1137
1138
void AddonsOptions_Impl::ReadMergeNotebookBarData(
1139
    std::u16string_view aMergeAddonInstructionBase,
1140
    Sequence<Sequence<PropertyValue>>& rMergeNotebookBarItems)
1141
0
{
1142
0
    OUString aMergeNotebookBarBaseNode = aMergeAddonInstructionBase +
1143
0
        m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS];
1144
1145
0
    ReadNotebookBarItemSet(aMergeNotebookBarBaseNode, rMergeNotebookBarItems);
1146
0
}
1147
1148
void AddonsOptions_Impl::ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& aContainer )
1149
0
{
1150
0
    static constexpr OUString aStatusbarMergeRootName( u"AddonUI/OfficeStatusbarMerging/"_ustr );
1151
1152
0
    Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aStatusbarMergeRootName );
1153
0
    sal_uInt32  nCount = aAddonMergeNodesSeq.getLength();
1154
1155
0
    Sequence< OUString > aNodePropNames( 5 );
1156
0
    auto pNodePropNames = aNodePropNames.getArray();
1157
1158
0
    for ( sal_uInt32 i = 0; i < nCount; i++ )
1159
0
    {
1160
0
        OUString aMergeAddonInstructions( aStatusbarMergeRootName + aAddonMergeNodesSeq[i] );
1161
1162
0
        Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
1163
0
        sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();
1164
1165
0
        for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
1166
0
        {
1167
0
            OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
1168
0
                m_aPathDelimiter +
1169
0
                aAddonInstMergeNodesSeq[j] +
1170
0
                m_aPathDelimiter;
1171
1172
            // Create sequence for data access
1173
0
            pNodePropNames[0] = aMergeAddonInstructionBase +
1174
0
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ];
1175
1176
0
            pNodePropNames[1] = aMergeAddonInstructionBase +
1177
0
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ];
1178
1179
0
            pNodePropNames[2] = aMergeAddonInstructionBase +
1180
0
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ];
1181
1182
0
            pNodePropNames[3] = aMergeAddonInstructionBase +
1183
0
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ];
1184
1185
0
            pNodePropNames[4] = aMergeAddonInstructionBase +
1186
0
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ];
1187
1188
0
            Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
1189
1190
0
            MergeStatusbarInstruction aMergeStatusbarInstruction;
1191
0
            aNodePropValues[0] >>= aMergeStatusbarInstruction.aMergePoint;
1192
0
            aNodePropValues[1] >>= aMergeStatusbarInstruction.aMergeCommand;
1193
0
            aNodePropValues[2] >>= aMergeStatusbarInstruction.aMergeCommandParameter;
1194
            // aNodePropValues[3] >>= aMergeStatusbarInstruction.aMergeFallback;
1195
0
            aNodePropValues[4] >>= aMergeStatusbarInstruction.aMergeContext;
1196
1197
0
            ReadMergeStatusbarData( aMergeAddonInstructionBase,
1198
0
                                    aMergeStatusbarInstruction.aMergeStatusbarItems );
1199
1200
0
            aContainer.push_back(std::move(aMergeStatusbarInstruction));
1201
0
        }
1202
0
    }
1203
0
}
1204
1205
void AddonsOptions_Impl::ReadMergeStatusbarData(
1206
    std::u16string_view aMergeAddonInstructionBase,
1207
    Sequence< Sequence< PropertyValue > >& rMergeStatusbarItems )
1208
0
{
1209
0
    OUString aMergeStatusbarBaseNode = aMergeAddonInstructionBase +
1210
0
        m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ];
1211
1212
0
    OUString aAddonStatusbarItemSetNode( aMergeStatusbarBaseNode + m_aPathDelimiter );
1213
0
    Sequence< OUString > aAddonStatusbarItemSetNodeSeq = GetNodeNames( aMergeStatusbarBaseNode );
1214
1215
0
    Sequence< PropertyValue > aStatusbarItem( PROPERTYCOUNT_STATUSBARITEM );
1216
0
    auto pStatusbarItem = aStatusbarItem.getArray();
1217
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_URL       ].Name = m_aPropNames[ INDEX_URL       ];
1218
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_TITLE     ].Name = m_aPropNames[ INDEX_TITLE     ];
1219
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT   ].Name = m_aPropNames[ INDEX_CONTEXT   ];
1220
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN     ].Name = m_aPropNames[ INDEX_ALIGN     ];
1221
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE  ].Name = m_aPropNames[ INDEX_AUTOSIZE  ];
1222
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Name = m_aPropNames[ INDEX_OWNERDRAW ];
1223
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY ].Name = m_aPropNames[ INDEX_MANDATORY ];
1224
0
    pStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH     ].Name = m_aPropNames[ INDEX_WIDTH     ];
1225
1226
0
    sal_uInt32 nCount = aAddonStatusbarItemSetNodeSeq.getLength();
1227
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
1228
0
    {
1229
0
        OUString aStatusbarItemNode( aAddonStatusbarItemSetNode + aAddonStatusbarItemSetNodeSeq[n] );
1230
1231
0
        if ( ReadStatusBarItem( aStatusbarItemNode, aStatusbarItem ) )
1232
0
        {
1233
0
            sal_uInt32 nAddonCount = rMergeStatusbarItems.getLength();
1234
0
            rMergeStatusbarItems.realloc( nAddonCount+1 );
1235
0
            rMergeStatusbarItems.getArray()[nAddonCount] = aStatusbarItem;
1236
0
        }
1237
0
    }
1238
0
}
1239
1240
bool AddonsOptions_Impl::ReadStatusBarItem(
1241
    std::u16string_view aStatusarItemNodeName,
1242
    Sequence< PropertyValue >& aStatusbarItem )
1243
0
{
1244
0
    bool bResult( false );
1245
0
    OUString aURL;
1246
0
    OUString aAddonStatusbarItemTreeNode( aStatusarItemNodeName + m_aPathDelimiter );
1247
1248
0
    Sequence< Any > aStatusbarItemNodePropValues = GetProperties( GetPropertyNamesStatusbarItem( aAddonStatusbarItemTreeNode ) );
1249
1250
    // Command URL is required
1251
0
    if (( aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
1252
0
    {
1253
0
        auto pStatusbarItem = aStatusbarItem.getArray();
1254
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_URL        ].Value <<= aURL;
1255
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_TITLE      ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_TITLE     ];
1256
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT    ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_CONTEXT   ];
1257
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN      ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_ALIGN     ];
1258
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE   ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_AUTOSIZE  ];
1259
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW  ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_OWNERDRAW ];
1260
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY  ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_MANDATORY ];
1261
1262
        // Configuration uses hyper for long. Therefore transform into sal_Int32
1263
0
        sal_Int64 nValue( 0 );
1264
0
        aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_WIDTH ] >>= nValue;
1265
0
        pStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Value <<= sal_Int32( nValue );
1266
1267
0
        bResult = true;
1268
0
    }
1269
1270
0
    return bResult;
1271
0
}
1272
1273
bool AddonsOptions_Impl::ReadMenuItem( std::u16string_view aMenuNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu )
1274
0
{
1275
0
    bool             bResult = false;
1276
0
    OUString         aStrValue;
1277
0
    OUString         aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );
1278
1279
0
    Sequence< Any >  aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
1280
0
    if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && !aStrValue.isEmpty() )
1281
0
    {
1282
0
        auto pMenuItem = aMenuItem.getArray();
1283
0
        pMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;
1284
1285
0
        OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1286
0
        Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1287
0
        if ( aRootSubMenuNodeNames.hasElements() && !bIgnoreSubMenu )
1288
0
        {
1289
            // Set a unique prefixed Add-On popup menu URL so it can be identified later
1290
0
            OUString aPopupMenuURL     = GeneratePrefixURL();
1291
0
            OUString aPopupMenuImageId;
1292
1293
0
            aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId;
1294
0
            ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId );
1295
1296
            // A popup menu must have a title and can have a URL and ImageIdentifier
1297
            // Set the other property values to empty
1298
0
            pMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aPopupMenuURL;
1299
0
            pMenuItem[ OFFSET_MENUITEM_TARGET           ].Value <<= OUString();
1300
0
            pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= aPopupMenuImageId;
1301
0
            pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1302
1303
            // Continue to read the sub menu nodes
1304
0
            Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1305
0
            OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1306
0
            for ( OUString& rName : asNonConstRange(aRootSubMenuNodeNames) )
1307
0
                rName = aSubMenuRootNodeName + rName;
1308
0
            ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1309
0
            pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
1310
0
            bResult = true;
1311
0
        }
1312
0
        else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && !aStrValue.isEmpty() )
1313
0
        {
1314
            // A simple menu item => read the other properties;
1315
0
            OUString aMenuImageId;
1316
1317
0
            aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId;
1318
0
            ReadAndAssociateImages( aStrValue, aMenuImageId );
1319
1320
0
            pMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aStrValue;
1321
0
            pMenuItem[ OFFSET_MENUITEM_TARGET           ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET         ];
1322
0
            pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= aMenuImageId;
1323
0
            pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT        ];
1324
0
            pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1325
1326
0
            bResult = true;
1327
0
        }
1328
0
    }
1329
0
    else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) &&
1330
0
              aStrValue == SEPARATOR_URL )
1331
0
    {
1332
0
        auto pMenuItem = aMenuItem.getArray();
1333
1334
        // Separator
1335
0
        pMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aStrValue;
1336
0
        pMenuItem[ OFFSET_MENUITEM_TARGET           ].Value <<= OUString();
1337
0
        pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= OUString();
1338
0
        pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value <<= OUString();
1339
0
        pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1340
0
        bResult = true;
1341
0
    }
1342
1343
0
    return bResult;
1344
0
}
1345
1346
bool AddonsOptions_Impl::ReadPopupMenu( std::u16string_view aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu )
1347
0
{
1348
0
    bool             bResult = false;
1349
0
    OUString         aStrValue;
1350
0
    OUString         aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter );
1351
1352
0
    Sequence< Any >  aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) );
1353
0
    if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) &&
1354
0
         !aStrValue.isEmpty() )
1355
0
    {
1356
0
        auto pPopupMenu = aPopupMenu.getArray();
1357
0
        pPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue;
1358
1359
0
        OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1360
0
        Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1361
0
        if ( aRootSubMenuNodeNames.hasElements() )
1362
0
        {
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
0
            OUString aPopupMenuURL = GeneratePrefixURL();
1366
1367
0
            pPopupMenu[ OFFSET_POPUPMENU_URL        ].Value <<= aPopupMenuURL;
1368
0
            pPopupMenu[ OFFSET_POPUPMENU_CONTEXT    ].Value = aPopupMenuNodePropValues[ OFFSET_POPUPMENU_CONTEXT ];
1369
1370
            // Continue to read the sub menu nodes
1371
0
            Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1372
0
            OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1373
0
            for ( OUString& rName : asNonConstRange(aRootSubMenuNodeNames) )
1374
0
                rName = aSubMenuRootNodeName + rName;
1375
0
            ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1376
0
            pPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq;
1377
0
            bResult = true;
1378
0
        }
1379
0
    }
1380
1381
0
    return bResult;
1382
0
}
1383
1384
// static
1385
void AddonsOptions_Impl::AppendPopupMenu( Sequence< PropertyValue >& rTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu )
1386
0
{
1387
0
    Sequence< Sequence< PropertyValue > > aTargetSubMenuSeq;
1388
0
    Sequence< Sequence< PropertyValue > > aSourceSubMenuSeq;
1389
1390
0
    if (( rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aTargetSubMenuSeq ) &&
1391
0
        ( rSourcePopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aSourceSubMenuSeq ))
1392
0
    {
1393
0
        sal_uInt32 nIndex = aTargetSubMenuSeq.getLength();
1394
0
        aTargetSubMenuSeq.realloc( nIndex + aSourceSubMenuSeq.getLength() );
1395
0
        auto pTargetSubMenuSeq = aTargetSubMenuSeq.getArray();
1396
0
        for (Sequence<PropertyValue> const& rSeq : aSourceSubMenuSeq)
1397
0
            pTargetSubMenuSeq[nIndex++] = rSeq;
1398
0
        rTargetPopupMenu.getArray()[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq;
1399
0
    }
1400
0
}
1401
1402
bool AddonsOptions_Impl::ReadToolBarItem( std::u16string_view aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem )
1403
0
{
1404
0
    bool             bResult = false;
1405
0
    OUString         aURL;
1406
0
    OUString         aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter );
1407
1408
0
    Sequence< Any >  aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) );
1409
1410
    // A toolbar item must have a command URL
1411
0
    if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
1412
0
    {
1413
0
        OUString         aTitle;
1414
0
        if ( aURL == SEPARATOR_URL )
1415
0
        {
1416
0
            auto pToolBarItem = aToolBarItem.getArray();
1417
1418
            // A separator toolbar item only needs a URL
1419
0
            pToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Value <<= aURL;
1420
0
            pToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Value <<= OUString();
1421
0
            pToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Value <<= OUString();
1422
0
            pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Value <<= OUString();
1423
0
            pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Value <<= OUString();
1424
0
            pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Value <<= OUString();
1425
0
            pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Value <<= sal_Int32( 0 );
1426
1427
0
            bResult = true;
1428
0
        }
1429
0
        else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
1430
0
        {
1431
0
            auto pToolBarItem = aToolBarItem.getArray();
1432
1433
            // A normal toolbar item must also have title => read the other properties;
1434
0
            OUString aImageId;
1435
1436
            // Try to map a user-defined image URL to our internal private image URL
1437
0
            aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1438
0
            ReadAndAssociateImages( aURL, aImageId );
1439
1440
0
            pToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Value <<= aURL;
1441
0
            pToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Value <<= aTitle;
1442
0
            pToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Value = aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TARGET      ];
1443
0
            pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Value <<= aImageId;
1444
0
            pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Value = aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTEXT     ];
1445
0
            pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Value = aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTROLTYPE ];
1446
1447
            // Configuration uses hyper for long. Therefore transform into sal_Int32
1448
0
            sal_Int64 nValue( 0 );
1449
0
            aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_WIDTH ] >>= nValue;
1450
0
            pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Value <<= sal_Int32( nValue );
1451
1452
0
            bResult = true;
1453
0
        }
1454
0
    }
1455
1456
0
    return bResult;
1457
0
}
1458
1459
bool AddonsOptions_Impl::ReadNotebookBarItem( std::u16string_view aNotebookBarItemNodeName, Sequence< PropertyValue >& aNotebookBarItem )
1460
0
{
1461
0
    bool             bResult = false;
1462
0
    OUString         aURL;
1463
0
    OUString         aAddonNotebookBarItemTreeNode( aNotebookBarItemNodeName + m_aPathDelimiter );
1464
1465
0
    Sequence< Any >  aNotebookBarItemNodePropValues = GetProperties( GetPropertyNamesNotebookBarItem( aAddonNotebookBarItemTreeNode ) );
1466
1467
    // A toolbar item must have a command URL
1468
0
    if (( aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_URL ] >>= aURL ) && !aURL.isEmpty() )
1469
0
    {
1470
0
        OUString         aTitle;
1471
0
        if ( aURL == SEPARATOR_URL )
1472
0
        {
1473
0
            auto pNotebookBarItem = aNotebookBarItem.getArray();
1474
1475
            // A separator toolbar item only needs a URL
1476
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_URL                ].Value <<= aURL;
1477
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TITLE              ].Value <<= OUString();
1478
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TARGET             ].Value <<= OUString();
1479
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER    ].Value <<= OUString();
1480
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTEXT            ].Value <<= OUString();
1481
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE        ].Value <<= OUString();
1482
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_WIDTH              ].Value <<= sal_Int32( 0 );
1483
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_STYLE              ].Value <<= OUString();
1484
1485
0
            bResult = true;
1486
0
        }
1487
0
        else if (( aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_TITLE ] >>= aTitle ) && !aTitle.isEmpty() )
1488
0
        {
1489
0
            auto pNotebookBarItem = aNotebookBarItem.getArray();
1490
1491
            // A normal toolbar item must also have title => read the other properties;
1492
0
            OUString aImageId;
1493
1494
            // Try to map a user-defined image URL to our internal private image URL
1495
0
            aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1496
0
            ReadAndAssociateImages( aURL, aImageId );
1497
1498
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_URL                ].Value <<= aURL;
1499
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TITLE              ].Value <<= aTitle;
1500
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_TARGET             ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_TARGET      ];
1501
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER    ].Value <<= aImageId;
1502
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTEXT            ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_CONTEXT     ];
1503
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE        ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_CONTROLTYPE ];
1504
1505
            // Configuration uses hyper for long. Therefore transform into sal_Int32
1506
0
            sal_Int64 nValue( 0 );
1507
0
            aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_WIDTH ] >>= nValue;
1508
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_WIDTH              ].Value <<= sal_Int32( nValue );
1509
0
            pNotebookBarItem[ OFFSET_NOTEBOOKBARITEM_STYLE              ].Value = aNotebookBarItemNodePropValues[ OFFSET_NOTEBOOKBARITEM_STYLE ];
1510
1511
0
            bResult = true;
1512
0
        }
1513
0
    }
1514
1515
0
    return bResult;
1516
0
}
1517
1518
void AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenuSeq )
1519
0
{
1520
0
    Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
1521
0
    auto pMenuItem = aMenuItem.getArray();
1522
1523
    // Init the property value sequence
1524
0
    pMenuItem[ OFFSET_MENUITEM_URL              ].Name = PROPERTYNAME_URL;
1525
0
    pMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = PROPERTYNAME_TITLE;
1526
0
    pMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = PROPERTYNAME_TARGET;
1527
0
    pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = PROPERTYNAME_IMAGEIDENTIFIER;
1528
0
    pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = PROPERTYNAME_CONTEXT;
1529
0
    pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = PROPERTYNAME_SUBMENU;  // Submenu set!
1530
1531
0
    sal_uInt32 nIndex = 0;
1532
0
    sal_uInt32 nCount = aSubMenuNodeNames.getLength();
1533
0
    for ( sal_uInt32 n = 0; n < nCount; n++ )
1534
0
    {
1535
0
        if ( ReadMenuItem( aSubMenuNodeNames[n], aMenuItem ))
1536
0
        {
1537
0
            sal_uInt32 nSubMenuCount = rSubMenuSeq.getLength() + 1;
1538
0
            rSubMenuSeq.realloc( nSubMenuCount );
1539
0
            rSubMenuSeq.getArray()[nIndex++] = aMenuItem;
1540
0
        }
1541
0
    }
1542
0
}
1543
1544
bool AddonsOptions_Impl::HasAssociatedImages( const OUString& aURL )
1545
0
{
1546
    // FIXME: potentially this is not so useful in a world of delayed image loading
1547
0
    ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
1548
0
    return ( pIter != m_aImageManager.end() );
1549
0
}
1550
1551
// static
1552
void AddonsOptions_Impl::SubstituteVariables( OUString& aURL )
1553
0
{
1554
0
    aURL = comphelper::getExpandedUri(
1555
0
        comphelper::getProcessComponentContext(), aURL);
1556
0
}
1557
1558
// static
1559
Bitmap AddonsOptions_Impl::ReadImageFromURL(const OUString& aImageURL)
1560
0
{
1561
0
    std::unique_ptr<SvStream> pStream = UcbStreamHelper::CreateStream( aImageURL, StreamMode::STD_READ );
1562
0
    if ( pStream && ( pStream->GetErrorCode() == ERRCODE_NONE ))
1563
0
    {
1564
        // Use graphic class to also support more graphic formats (bmp,png,...)
1565
0
        Graphic aGraphic;
1566
1567
0
        GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
1568
0
        rGF.ImportGraphic( aGraphic, u"", *pStream );
1569
1570
0
        Bitmap aBitmap = aGraphic.GetBitmap();
1571
1572
0
        Size aBmpSize = aBitmap.GetSizePixel();
1573
0
        if ( !aBmpSize.IsEmpty() )
1574
0
        {
1575
            // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1576
0
            if( !aBitmap.HasAlpha() )
1577
0
                aBitmap = Bitmap( aBitmap.CreateColorBitmap(), COL_LIGHTMAGENTA );
1578
1579
0
            return aBitmap;
1580
0
        }
1581
0
    }
1582
1583
0
    return Bitmap();
1584
0
}
1585
1586
void AddonsOptions_Impl::ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId )
1587
0
{
1588
0
    if ( aImageId.isEmpty() )
1589
0
        return;
1590
1591
0
    ImageEntry  aImageEntry;
1592
0
    OUString    aImageURL( aImageId );
1593
1594
0
    SubstituteVariables( aImageURL );
1595
1596
    // Loop to create the two possible image names and try to read the bitmap files
1597
0
    static const char* const aExtArray[] = { "_16", "_26" };
1598
0
    for ( size_t i = 0; i < std::size(aExtArray); i++ )
1599
0
    {
1600
0
        OUStringBuffer aFileURL( aImageURL );
1601
0
        aFileURL.appendAscii( aExtArray[i] );
1602
0
        aFileURL.append( ".bmp" );
1603
1604
0
        aImageEntry.addImage( !i ? IMGSIZE_SMALL : IMGSIZE_BIG, aFileURL.makeStringAndClear() );
1605
0
    }
1606
1607
0
    m_aImageManager.emplace( aURL, aImageEntry );
1608
0
}
1609
1610
std::unique_ptr<AddonsOptions_Impl::ImageEntry> AddonsOptions_Impl::ReadImageData( std::u16string_view aImagesNodeName )
1611
0
{
1612
0
    Sequence< OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName );
1613
0
    Sequence< Any >      aPropertyData;
1614
0
    Sequence< sal_Int8 > aImageDataSeq;
1615
0
    OUString             aImageURL;
1616
1617
0
    std::unique_ptr<ImageEntry> pEntry;
1618
1619
    // It is possible to use both forms (embedded image data and URLs to external bitmap files) at the
1620
    // same time. Embedded image data has a higher priority.
1621
0
    aPropertyData = GetProperties( aImageDataNodeNames );
1622
0
    for ( int i = 0; i < PROPERTYCOUNT_IMAGES; i++ )
1623
0
    {
1624
0
        if ( i < PROPERTYCOUNT_EMBEDDED_IMAGES )
1625
0
        {
1626
            // Extract image data from the embedded hex binary sequence
1627
0
            Bitmap aImage;
1628
0
            if (( aPropertyData[i] >>= aImageDataSeq ) &&
1629
0
                aImageDataSeq.hasElements() &&
1630
0
                ( CreateImageFromSequence( aImage, aImageDataSeq ) ) )
1631
0
            {
1632
0
                if ( !pEntry )
1633
0
                    pEntry.reset(new ImageEntry);
1634
0
                pEntry->addImage(i == OFFSET_IMAGES_SMALL ? IMGSIZE_SMALL : IMGSIZE_BIG, aImage);
1635
0
            }
1636
0
        }
1637
0
        else if ( i == OFFSET_IMAGES_SMALL_URL || i == OFFSET_IMAGES_BIG_URL )
1638
0
        {
1639
0
            if(!pEntry)
1640
0
                pEntry.reset(new ImageEntry());
1641
1642
            // Retrieve image data from an external bitmap file. Make sure that embedded image data
1643
            // has a higher priority.
1644
0
            if (aPropertyData[i] >>= aImageURL)
1645
0
            {
1646
0
                SubstituteVariables(aImageURL);
1647
0
                pEntry->addImage(i == OFFSET_IMAGES_SMALL_URL ? IMGSIZE_SMALL : IMGSIZE_BIG, aImageURL);
1648
0
            }
1649
0
        }
1650
0
    }
1651
1652
0
    return pEntry;
1653
0
}
1654
1655
// static
1656
bool AddonsOptions_Impl::CreateImageFromSequence( Bitmap& rImage, Sequence< sal_Int8 >& rBitmapDataSeq )
1657
0
{
1658
0
    bool bResult = false;
1659
1660
0
    if ( rBitmapDataSeq.hasElements() )
1661
0
    {
1662
0
        SvMemoryStream  aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), StreamMode::STD_READ );
1663
1664
0
        ReadDIBBitmapEx(rImage, aMemStream);
1665
1666
0
        if( !rImage.HasAlpha() )
1667
0
        {
1668
            // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1669
0
            rImage = Bitmap( rImage, COL_LIGHTMAGENTA );
1670
0
        }
1671
1672
0
        bResult = true;
1673
0
    }
1674
1675
0
    return bResult;
1676
0
}
1677
1678
Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( std::u16string_view aPropertyRootNode ) const
1679
0
{
1680
0
    Sequence< OUString > lResult( PROPERTYCOUNT_MENUITEM );
1681
0
    auto plResult = lResult.getArray();
1682
1683
    // Create property names dependent from the root node name
1684
0
    plResult[OFFSET_MENUITEM_URL]             = aPropertyRootNode + m_aPropNames[ INDEX_URL          ];
1685
0
    plResult[OFFSET_MENUITEM_TITLE]           = aPropertyRootNode + m_aPropNames[ INDEX_TITLE            ];
1686
0
    plResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ];
1687
0
    plResult[OFFSET_MENUITEM_TARGET]          = aPropertyRootNode + m_aPropNames[ INDEX_TARGET           ];
1688
0
    plResult[OFFSET_MENUITEM_CONTEXT]         = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT      ];
1689
0
    plResult[OFFSET_MENUITEM_SUBMENU]         = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU      ];
1690
1691
0
    return lResult;
1692
0
}
1693
1694
Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( std::u16string_view aPropertyRootNode ) const
1695
0
{
1696
    // The URL is automatically set and not read from the configuration.
1697
0
    Sequence< OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 );
1698
0
    auto plResult = lResult.getArray();
1699
1700
    // Create property names dependent from the root node name
1701
0
    plResult[OFFSET_POPUPMENU_TITLE]   = aPropertyRootNode + m_aPropNames[ INDEX_TITLE  ];
1702
0
    plResult[OFFSET_POPUPMENU_CONTEXT] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT    ];
1703
0
    plResult[OFFSET_POPUPMENU_SUBMENU] = aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU    ];
1704
1705
0
    return lResult;
1706
0
}
1707
1708
Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( std::u16string_view aPropertyRootNode ) const
1709
0
{
1710
0
    Sequence< OUString > lResult( PROPERTYCOUNT_TOOLBARITEM );
1711
0
    auto plResult = lResult.getArray();
1712
1713
    // Create property names dependent from the root node name
1714
0
    plResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL             ];
1715
0
    plResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE       ];
1716
0
    plResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
1717
0
    plResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET          ];
1718
0
    plResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT         ];
1719
0
    plResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE     ];
1720
0
    plResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH       ];
1721
1722
0
    return lResult;
1723
0
}
1724
1725
Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesNotebookBarItem( std::u16string_view aPropertyRootNode ) const
1726
0
{
1727
0
    Sequence< OUString > lResult( PROPERTYCOUNT_NOTEBOOKBARITEM );
1728
0
    auto plResult = lResult.getArray();
1729
1730
    // Create property names dependent from the root node name
1731
0
    plResult[0] = aPropertyRootNode + m_aPropNames[ INDEX_URL             ];
1732
0
    plResult[1] = aPropertyRootNode + m_aPropNames[ INDEX_TITLE       ];
1733
0
    plResult[2] = aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER];
1734
0
    plResult[3] = aPropertyRootNode + m_aPropNames[ INDEX_TARGET          ];
1735
0
    plResult[4] = aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT         ];
1736
0
    plResult[5] = aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE     ];
1737
0
    plResult[6] = aPropertyRootNode + m_aPropNames[ INDEX_WIDTH       ];
1738
0
    plResult[7] = aPropertyRootNode + m_aPropNames[ INDEX_STYLE       ];
1739
1740
0
    return lResult;
1741
0
}
1742
1743
Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesStatusbarItem(
1744
    std::u16string_view aPropertyRootNode ) const
1745
0
{
1746
0
    Sequence< OUString > lResult( PROPERTYCOUNT_STATUSBARITEM );
1747
0
    auto plResult = lResult.getArray();
1748
1749
0
    plResult[0] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL       ] );
1750
0
    plResult[1] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE     ] );
1751
0
    plResult[2] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT   ] );
1752
0
    plResult[3] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_ALIGN     ] );
1753
0
    plResult[4] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_AUTOSIZE  ] );
1754
0
    plResult[5] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_OWNERDRAW ] );
1755
0
    plResult[6] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_MANDATORY ] );
1756
0
    plResult[7] = OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH     ] );
1757
1758
0
    return lResult;
1759
0
}
1760
1761
Sequence< OUString > AddonsOptions_Impl::GetPropertyNamesImages( std::u16string_view aPropertyRootNode ) const
1762
0
{
1763
0
    Sequence< OUString > lResult( PROPERTYCOUNT_IMAGES );
1764
0
    auto plResult = lResult.getArray();
1765
1766
    // Create property names dependent from the root node name
1767
0
    plResult[0] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL       ];
1768
0
    plResult[1] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG     ];
1769
0
    plResult[2] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC ];
1770
0
    plResult[3] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC       ];
1771
0
    plResult[4] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL  ];
1772
0
    plResult[5] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL ];
1773
0
    plResult[6] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL];
1774
0
    plResult[7] = aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL   ];
1775
1776
0
    return lResult;
1777
0
}
1778
1779
namespace{
1780
    //global
1781
    std::weak_ptr<AddonsOptions_Impl> g_pAddonsOptions;
1782
}
1783
1784
AddonsOptions::AddonsOptions()
1785
0
{
1786
    // Global access, must be guarded (multithreading!).
1787
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1788
1789
0
    m_pImpl = g_pAddonsOptions.lock();
1790
0
    if( !m_pImpl )
1791
0
    {
1792
0
        m_pImpl = std::make_shared<AddonsOptions_Impl>();
1793
0
        g_pAddonsOptions = m_pImpl;
1794
0
    }
1795
0
}
1796
1797
AddonsOptions::~AddonsOptions()
1798
0
{
1799
    // Global access, must be guarded (multithreading!)
1800
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1801
1802
0
    m_pImpl.reset();
1803
0
}
1804
1805
//  public method
1806
1807
bool AddonsOptions::HasAddonsMenu() const
1808
0
{
1809
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1810
0
    return m_pImpl->HasAddonsMenu();
1811
0
}
1812
1813
//  public method
1814
1815
sal_Int32 AddonsOptions::GetAddonsToolBarCount() const
1816
0
{
1817
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1818
0
    return m_pImpl->GetAddonsToolBarCount();
1819
0
}
1820
1821
//  public method
1822
1823
sal_Int32 AddonsOptions::GetAddonsNotebookBarCount() const
1824
0
{
1825
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1826
0
    return m_pImpl->GetAddonsNotebookBarCount();
1827
0
}
1828
1829
//  public method
1830
1831
const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const
1832
0
{
1833
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1834
0
    return m_pImpl->GetAddonsMenu();
1835
0
}
1836
1837
//  public method
1838
1839
const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const
1840
0
{
1841
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1842
0
    return m_pImpl->GetAddonsMenuBarPart();
1843
0
}
1844
1845
//  public method
1846
1847
const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
1848
0
{
1849
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1850
0
    return m_pImpl->GetAddonsToolBarPart( nIndex );
1851
0
}
1852
1853
//  public method
1854
1855
const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
1856
0
{
1857
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1858
0
    return m_pImpl->GetAddonsNotebookBarPart( nIndex );
1859
0
}
1860
1861
//  public method
1862
1863
OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
1864
0
{
1865
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1866
0
    return m_pImpl->GetAddonsToolbarResourceName( nIndex );
1867
0
}
1868
1869
//  public method
1870
1871
OUString AddonsOptions::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
1872
0
{
1873
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1874
0
    return m_pImpl->GetAddonsNotebookBarResourceName( nIndex );
1875
0
}
1876
1877
//  public method
1878
1879
const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const
1880
0
{
1881
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1882
0
    return m_pImpl->GetAddonsHelpMenu();
1883
0
}
1884
1885
//  public method
1886
1887
const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const
1888
0
{
1889
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1890
0
    return m_pImpl->GetMergeMenuInstructions();
1891
0
}
1892
1893
//  public method
1894
1895
bool AddonsOptions::GetMergeToolbarInstructions(
1896
    const OUString& rToolbarName,
1897
    MergeToolbarInstructionContainer& rToolbarInstructions ) const
1898
0
{
1899
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1900
0
    return m_pImpl->GetMergeToolbarInstructions(
1901
0
        rToolbarName, rToolbarInstructions );
1902
0
}
1903
1904
//  public method
1905
1906
bool AddonsOptions::GetMergeNotebookBarInstructions(
1907
    const OUString& rNotebookBarName,
1908
    MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
1909
0
{
1910
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1911
0
    return m_pImpl->GetMergeNotebookBarInstructions(
1912
0
        rNotebookBarName, rNotebookBarInstructions );
1913
0
}
1914
1915
//public method
1916
1917
const MergeStatusbarInstructionContainer& AddonsOptions::GetMergeStatusbarInstructions() const
1918
0
{
1919
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1920
0
    return m_pImpl->GetMergeStatusbarInstructions();
1921
0
}
1922
1923
//  public method
1924
1925
Bitmap AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale ) const
1926
0
{
1927
0
    MutexGuard aGuard( GetOwnStaticMutex() );
1928
0
    return m_pImpl->GetImageFromURL( aURL, bBig, bNoScale );
1929
0
}
1930
1931
//  public method
1932
1933
Bitmap AddonsOptions::GetImageFromURL( const OUString& aURL, bool bBig ) const
1934
0
{
1935
0
    return GetImageFromURL( aURL, bBig, false );
1936
0
}
1937
1938
Mutex& AddonsOptions::GetOwnStaticMutex()
1939
0
{
1940
    // Create static mutex variable.
1941
0
    static Mutex ourMutex;
1942
1943
0
    return ourMutex;
1944
0
}
1945
1946
IMPL_LINK_NOARG(AddonsOptions_Impl, NotifyEvent, void*, void)
1947
0
{
1948
0
    MutexGuard aGuard(AddonsOptions::GetOwnStaticMutex());
1949
0
    ReadConfigurationData();
1950
0
}
1951
1952
}
1953
1954
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */