Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/framework/source/fwe/classes/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 88 kB image not shown  

Quelle  addonsoptions.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <com/sun/star/beans/PropertyValue.hpp>
#include <framework/addonsoptions.hxx>
#include <o3tl/safeint.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/configitem.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <tools/stream.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <comphelper/getexpandeduri.hxx>
#include <comphelper/processfactory.hxx>
#include <vcl/dibtools.hxx>
#include <vcl/graph.hxx>
#include <vcl/graphicfilter.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/svapp.hxx>

#include <algorithm>
#include <string_view>
#include <unordered_map>
#include <vector>

//  namespaces

using namespace ::utl;
using namespace ::osl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star;

constexpr OUStringLiteral ROOTNODE_ADDONMENU = u"Office.Addons";
constexpr OUStringLiteral PATHDELIMITER = u"/";
constexpr OUString SEPARATOR_URL = u"private:separator"_ustr;

#define PROPERTYNAME_URL                                ADDONSMENUITEM_STRING_URL
#define PROPERTYNAME_TITLE                              ADDONSMENUITEM_STRING_TITLE
#define PROPERTYNAME_TARGET                             ADDONSMENUITEM_STRING_TARGET
#define PROPERTYNAME_IMAGEIDENTIFIER                    ADDONSMENUITEM_STRING_IMAGEIDENTIFIER
#define PROPERTYNAME_CONTEXT                            ADDONSMENUITEM_STRING_CONTEXT
#define PROPERTYNAME_SUBMENU                            ADDONSMENUITEM_STRING_SUBMENU

constexpr OUStringLiteral IMAGES_NODENAME = u"UserDefinedImages";

// The following order is mandatory. Please add properties at the end!
#define INDEX_URL               0
#define INDEX_TITLE             1
#define INDEX_IMAGEIDENTIFIER   2
#define INDEX_TARGET            3
#define INDEX_CONTEXT           4
#define INDEX_SUBMENU           5
#define INDEX_CONTROLTYPE       6
#define INDEX_WIDTH             7
#define INDEX_ALIGN             8
#define INDEX_AUTOSIZE          9
#define INDEX_OWNERDRAW         10
#define INDEX_MANDATORY         11
#define INDEX_STYLE             12
#define PROPERTYCOUNT_INDEX     13

// The following order is mandatory. Please add properties at the end!
#define PROPERTYCOUNT_MENUITEM                          6
#define OFFSET_MENUITEM_URL                             0
#define OFFSET_MENUITEM_TITLE                           1
#define OFFSET_MENUITEM_IMAGEIDENTIFIER                 2
#define OFFSET_MENUITEM_TARGET                          3
#define OFFSET_MENUITEM_CONTEXT                         4
#define OFFSET_MENUITEM_SUBMENU                         5

// The following order is mandatory. Please add properties at the end!
#define PROPERTYCOUNT_POPUPMENU                         4
#define OFFSET_POPUPMENU_TITLE                          0
#define OFFSET_POPUPMENU_CONTEXT                        1
#define OFFSET_POPUPMENU_SUBMENU                        2
#define OFFSET_POPUPMENU_URL                            3   // Used for property set

// The following order is mandatory. Please add properties at the end!
#define PROPERTYCOUNT_TOOLBARITEM                       7
#define OFFSET_TOOLBARITEM_URL                          0
#define OFFSET_TOOLBARITEM_TITLE                        1
#define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER              2
#define OFFSET_TOOLBARITEM_TARGET                       3
#define OFFSET_TOOLBARITEM_CONTEXT                      4
#define OFFSET_TOOLBARITEM_CONTROLTYPE                  5
#define OFFSET_TOOLBARITEM_WIDTH                        6

// The following order is mandatory. Please add properties at the end!
#define PROPERTYCOUNT_NOTEBOOKBARITEM                   8
#define OFFSET_NOTEBOOKBARITEM_URL                      0
#define OFFSET_NOTEBOOKBARITEM_TITLE                    1
#define OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER          2
#define OFFSET_NOTEBOOKBARITEM_TARGET                   3
#define OFFSET_NOTEBOOKBARITEM_CONTEXT                  4
#define OFFSET_NOTEBOOKBARITEM_CONTROLTYPE              5
#define OFFSET_NOTEBOOKBARITEM_WIDTH                    6
#define OFFSET_NOTEBOOKBARITEM_STYLE                    7

// The following order is mandatory. Please add properties at the end!
#define PROPERTYCOUNT_STATUSBARITEM                     8
#define OFFSET_STATUSBARITEM_URL                        0
#define OFFSET_STATUSBARITEM_TITLE                      1
#define OFFSET_STATUSBARITEM_CONTEXT                    2
#define OFFSET_STATUSBARITEM_ALIGN                      3
#define OFFSET_STATUSBARITEM_AUTOSIZE                   4
#define OFFSET_STATUSBARITEM_OWNERDRAW                  5
#define OFFSET_STATUSBARITEM_MANDATORY                  6
#define OFFSET_STATUSBARITEM_WIDTH                      7

// The following order is mandatory. Please add properties at the end!
#define PROPERTYCOUNT_IMAGES                            8
#define PROPERTYCOUNT_EMBEDDED_IMAGES                   2
#define OFFSET_IMAGES_SMALL                             0
#define OFFSET_IMAGES_BIG                               1
#define OFFSET_IMAGES_SMALLHC                           2
#define OFFSET_IMAGES_BIGHC                             3
#define OFFSET_IMAGES_SMALL_URL                         4
#define OFFSET_IMAGES_BIG_URL                           5
#define OFFSET_IMAGES_SMALLHC_URL                       6
#define OFFSET_IMAGES_BIGHC_URL                         7

#define PROPERTYCOUNT_MERGE_MENUBAR                     6
#define OFFSET_MERGEMENU_MERGEPOINT                     0
#define OFFSET_MERGEMENU_MERGECOMMAND                   1
#define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER          2
#define OFFSET_MERGEMENU_MERGEFALLBACK                  3
#define OFFSET_MERGEMENU_MERGECONTEXT                   4
#define OFFSET_MERGEMENU_MENUITEMS                      5

#define PROPERTYCOUNT_MERGE_TOOLBAR                     7
#define OFFSET_MERGETOOLBAR_TOOLBAR                     0
#define OFFSET_MERGETOOLBAR_MERGEPOINT                  1
#define OFFSET_MERGETOOLBAR_MERGECOMMAND                2
#define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER       3
#define OFFSET_MERGETOOLBAR_MERGEFALLBACK               4
#define OFFSET_MERGETOOLBAR_MERGECONTEXT                5
#define OFFSET_MERGETOOLBAR_TOOLBARITEMS                6

#define PROPERTYCOUNT_MERGE_NOTEBOOKBAR                 7
#define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR             0
#define OFFSET_MERGENOTEBOOKBAR_MERGEPOINT              1
#define OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND            2
#define OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER   3
#define OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK           4
#define OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT            5
#define OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS        6

#define PROPERTYCOUNT_MERGE_STATUSBAR                   6
#define OFFSET_MERGESTATUSBAR_MERGEPOINT                0
#define OFFSET_MERGESTATUSBAR_MERGECOMMAND              1
#define OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER     2
#define OFFSET_MERGESTATUSBAR_MERGEFALLBACK             3
#define OFFSET_MERGESTATUSBAR_MERGECONTEXT              4
#define OFFSET_MERGESTATUSBAR_STATUSBARITEMS            5

//  private declarations!

/*-****************************************************************************************************************
    @descr  struct to hold information about one menu entry.
****************************************************************************************************************-*/


namespace framework
{

class AddonsOptions_Impl : public ConfigItem
{

    //  public methods

    public:

        //  constructor / destructor

         AddonsOptions_Impl();
        virtual ~AddonsOptions_Impl() override;

        //  overridden methods of baseclass

        /*-****************************************************************************************************
            @short      called for notify of configmanager
            @descr      This method is called from the ConfigManager before application ends or from the
                        PropertyChangeListener if the sub tree broadcasts changes. You must update your
                        internal values.

            @seealso    baseclass ConfigItem

            @param      "lPropertyNames" is the list of properties which should be updated.
        */


        virtual void Notify( const Sequence< OUString >& lPropertyNames ) override;

        //  public interface

        /*-****************************************************************************************************
            @short      base implementation of public interface for "SvtDynamicMenuOptions"!
            @descr      These class is used as static member of "SvtDynamicMenuOptions" ...
                        => The code exist only for one time and isn't duplicated for every instance!
        */


        bool                                            HasAddonsMenu        () const;
        sal_Int32                                       GetAddonsToolBarCount() const;
        sal_Int32                                       GetAddonsNotebookBarCount() const;
        const Sequence< Sequence< PropertyValue > >&    GetAddonsMenu        () const { return m_aCachedMenuProperties;}
        const Sequence< Sequence< PropertyValue > >&    GetAddonsMenuBarPart () const { return m_aCachedMenuBarPartProperties;}
        const Sequence< Sequence< PropertyValue > >&    GetAddonsToolBarPart ( sal_uInt32 nIndex ) const;
        const Sequence< Sequence< PropertyValue > >&    GetAddonsNotebookBarPart ( sal_uInt32 nIndex const;
        const OUString &                                GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
        const OUString &                                GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const;
        const Sequence< Sequence< PropertyValue > >&    GetAddonsHelpMenu    () const { return m_aCachedHelpMenuProperties;}
        BitmapEx                                        GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale );
        const MergeMenuInstructionContainer&            GetMergeMenuInstructions() const { return m_aCachedMergeMenuInsContainer;}
        bool                                            GetMergeToolbarInstructions( const OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const;
        bool                                            GetMergeNotebookBarInstructions( const OUString& rNotebookBarName, MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const;
        const MergeStatusbarInstructionContainer&       GetMergeStatusbarInstructions() const return m_aCachedStatusbarMergingInstructions;}
        void                                            ReadConfigurationData();

    private:
        enum ImageSize
        {
            IMGSIZE_SMALL = 0,
            IMGSIZE_BIG
        };

        struct OneImageEntry
        {
            BitmapEx aScaled;   ///< cached scaled image
            BitmapEx aImage;    ///< original un-scaled image
            OUString aURL;      ///< URL in case it is not loaded yet
        };

        struct ImageEntry
        {
            // if the image is set, it was embedded in some way,
            // otherwise we use the associated URL to load on demand

            // accessed in this order
            OneImageEntry aSizeEntry[2];
            ImageEntry() {}
            void addImage(ImageSize eSize, const BitmapEx &rImage);
            void addImage(ImageSize eSize, const OUString &rURL);
        };

        typedef std::unordered_map< OUString, ImageEntry > ImageManager;
        typedef std::unordered_map< OUString, sal_uInt32 > StringToIndexMap;
        typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars;
        typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonNotebookBars;
        typedef std::unordered_map< OUString, MergeToolbarInstructionContainer > ToolbarMergingInstructions;
        typedef std::unordered_map< OUString, MergeNotebookBarInstructionContainer > NotebookBarMergingInstructions;

        /*-****************************************************************************************************
            @short      return list of key names of our configuration management which represent our module tree
            @descr      These methods return the current list of key names! We need it to get needed values from our
                        configuration management!
            @param      "nCount"     ,   returns count of menu entries for "new"
            @return     A list of configuration key names is returned.
        */


        void                 ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq );
        void                 ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq );
        void                 ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames );
        bool                 ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq );
        void                 ReadOfficeNotebookBarSet( AddonNotebookBars& rAddonOfficeNotebookBars, std::vector< OUString >& rAddonOfficeNotebookBarResNames );
        bool                 ReadNotebookBarItemSet( const OUString& rNotebookBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeNotebookBarSeq );

        void                 ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq );
        void                 ReadImages( ImageManager& aImageManager );
        void                 ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer );
        void                 ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap );
        void                 ReadNotebookBarMergeInstructions( NotebookBarMergingInstructions& rNotebookBarMergeMap );
        void                 ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& rContainer );

        void                 ReadMergeMenuData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu );
        void                 ReadMergeToolbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems );
        void                 ReadMergeNotebookBarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeNotebookBarItems );
        void                 ReadMergeStatusbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeStatusbar );
        bool                 ReadMenuItem( std::u16string_view aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu = false );
        bool                 ReadPopupMenu( std::u16string_view aPopupMenuNodeName, Sequence< PropertyValue >&&nbsp;aPopupMenu );
        static void          AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu );
        bool                 ReadToolBarItem( std::u16string_view aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem );
        bool                 ReadNotebookBarItem( std::u16string_view aNotebookBarItemNodeName, Sequence< PropertyValue >& aNotebookBarItem );

        bool                 ReadStatusBarItem( std::u16string_view aStatusbarItemNodeName, Sequence< PropertyValue >& aStatusbarItem );
        std::unique_ptr<ImageEntry> ReadImageData( std::u16string_view aImagesNodeName );
        void                 ReadAndAssociateImages( const OUString& aURL, const OUString& aImageId );
        static BitmapEx      ReadImageFromURL( const OUString& aURL );
        bool                 HasAssociatedImages( const OUString& aURL );
        static void          SubstituteVariables( OUString& aURL );

        void                 ReadSubMenuEntries( const Sequence< OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
        OUString             GeneratePrefixURL();

        Sequence< OUString > GetPropertyNamesMenuItem( std::u16string_view aPropertyRootNode )
            const;
        Sequence< OUString > GetPropertyNamesPopupMenu( std::u16string_view aPropertyRootNode )
            const;
        Sequence< OUString > GetPropertyNamesToolBarItem( std::u16string_view aPropertyRootNode )
            const;
        Sequence< OUString > GetPropertyNamesNotebookBarItem( std::u16string_view aPropertyRootNode ) const;

        Sequence< OUString > GetPropertyNamesStatusbarItem( std::u16string_view aPropertyRootNode ) const;
        Sequence< OUString > GetPropertyNamesImages( std::u16string_view aPropertyRootNode ) const;
        static bool CreateImageFromSequence( BitmapEx& rImage, Sequence< sal_Int8 >& rBitmapDataSeq );

        DECL_LINK(NotifyEvent, void*, void);

        virtual void ImplCommit() override;

    //  private member

    private:
        sal_Int32                                         m_nRootAddonPopupMenuId;
        OUString                                   m_aPropNames[PROPERTYCOUNT_INDEX];
        OUString                                   m_aPropImagesNames[PROPERTYCOUNT_IMAGES];
        OUString                                   m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR];
        OUString                                   m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR];
        OUString                                   m_aPropMergeNotebookBarNames[PROPERTYCOUNT_MERGE_NOTEBOOKBAR];
        OUString                                   m_aPropMergeStatusbarNames[PROPERTYCOUNT_MERGE_STATUSBAR];
        OUString                                   m_aPathDelimiter;
        OUString                                   m_aRootAddonPopupMenuURLPrexfix;
        Sequence< Sequence< PropertyValue > >             m_aCachedMenuProperties;
        Sequence< Sequence< PropertyValue > >             m_aCachedMenuBarPartProperties;
        AddonToolBars                                     m_aCachedToolBarPartProperties;
        AddonNotebookBars                                 m_aCachedNotebookBarPartProperties;
        std::vector< OUString >                      m_aCachedToolBarPartResourceNames;
        std::vector< OUString >                      m_aCachedNotebookBarPartResourceNames;
        Sequence< Sequence< PropertyValue > >             m_aCachedHelpMenuProperties;
        ImageManager                                      m_aImageManager;
        Sequence< Sequence< PropertyValue > >             m_aEmptyAddonToolBar;
        Sequence< Sequence< PropertyValue > >             m_aEmptyAddonNotebookBar;
        MergeMenuInstructionContainer                     m_aCachedMergeMenuInsContainer;
        ToolbarMergingInstructions                        m_aCachedToolbarMergingInstructions;
        NotebookBarMergingInstructions                    m_aCachedNotebookBarMergingInstructions;
        MergeStatusbarInstructionContainer                m_aCachedStatusbarMergingInstructions;
};

void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize, const BitmapEx& rImage)
{
    aSizeEntry[static_cast<int>(eSize)].aImage = rImage;
}

void AddonsOptions_Impl::ImageEntry::addImage(ImageSize eSize, const OUString &rURL)
{
    aSizeEntry[static_cast<int>(eSize)].aURL = rURL;
}

//  constructor

AddonsOptions_Impl::AddonsOptions_Impl()
    // Init baseclasses first
    : ConfigItem( ROOTNODE_ADDONMENU ),
    m_nRootAddonPopupMenuId( 0 ),
    m_aPathDelimiter( PATHDELIMITER ),
    m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX_STR )
{
    // initialize array with fixed property names
    m_aPropNames[ INDEX_URL             ] = PROPERTYNAME_URL;
    m_aPropNames[ INDEX_TITLE           ] = PROPERTYNAME_TITLE;
    m_aPropNames[ INDEX_TARGET          ] = PROPERTYNAME_TARGET;
    m_aPropNames[ INDEX_IMAGEIDENTIFIER ] = PROPERTYNAME_IMAGEIDENTIFIER;
    m_aPropNames[ INDEX_CONTEXT         ] = PROPERTYNAME_CONTEXT;
    m_aPropNames[ INDEX_SUBMENU         ] = PROPERTYNAME_SUBMENU; // Submenu set!
    m_aPropNames[ INDEX_CONTROLTYPE     ] = "ControlType";
    m_aPropNames[ INDEX_WIDTH           ] = "Width";
    m_aPropNames[ INDEX_ALIGN           ] = "Alignment";
    m_aPropNames[ INDEX_AUTOSIZE        ] = "AutoSize";
    m_aPropNames[ INDEX_OWNERDRAW       ] = "OwnerDraw";
    m_aPropNames[ INDEX_MANDATORY       ] = "Mandatory";
    m_aPropNames[ INDEX_STYLE           ] = "Style";

    // initialize array with fixed images property names
    m_aPropImagesNames[ OFFSET_IMAGES_SMALL         ] = "ImageSmall";
    m_aPropImagesNames[ OFFSET_IMAGES_BIG           ] = "ImageBig";
    m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC       ] = "ImageSmallHC";
    m_aPropImagesNames[ OFFSET_IMAGES_BIGHC         ] = "ImageBigHC";
    m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL     ] = "ImageSmallURL";
    m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL       ] = "ImageBigURL";
    m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL   ] = "ImageSmallHCURL";
    m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL     ] = "ImageBigHCURL";

    // initialize array with fixed merge menu property names
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT    ] = "MergePoint";
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND  ] = "MergeCommand";
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = "MergeFallback";
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT  ] = "MergeContext";
    m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS     ] = "MenuItems";

    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR               ] = "MergeToolBar";
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT            ] = "MergePoint";
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND          ] = "MergeCommand";
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK         ] = "MergeFallback";
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT          ] = "MergeContext";
    m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS          ] = "ToolBarItems";

    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR           ] = "MergeNotebookBar";
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEPOINT            ] = "MergePoint";
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND          ] = "MergeCommand";
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK         ] = "MergeFallback";
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT          ] = "MergeContext";
    m_aPropMergeNotebookBarNames[ OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS      ] = "NotebookBarItems";

    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT            ] = "MergePoint";
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND          ] = "MergeCommand";
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ] = "MergeCommandParameter";
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK         ] = "MergeFallback";
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT          ] = "MergeContext";
    m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS        ] = "StatusBarItems";

    ReadConfigurationData();

    // Enable notification mechanism of our baseclass.
    // We need it to get information about changes outside these class on our used configuration keys!
    Sequence<OUString> aNotifySeq { u"AddonUI"_ustr };
    EnableNotification( aNotifySeq );
}

//  destructor

AddonsOptions_Impl::~AddonsOptions_Impl()
{
    assert(!IsModified()); // should have been committed
}

void AddonsOptions_Impl::ReadConfigurationData()
{
    // reset members to be read again from configuration
    m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >();
    m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >();
    m_aCachedToolBarPartProperties = AddonToolBars();
    m_aCachedNotebookBarPartProperties = AddonNotebookBars();
    m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
    m_aCachedToolBarPartResourceNames.clear();
    m_aCachedNotebookBarPartResourceNames.clear();
    m_aImageManager = ImageManager();

    ReadAddonMenuSet( m_aCachedMenuProperties );
    ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
    ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
    ReadOfficeNotebookBarSet( m_aCachedNotebookBarPartProperties, m_aCachedNotebookBarPartResourceNames );

    ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
    ReadImages( m_aImageManager );

    m_aCachedMergeMenuInsContainer.clear();
    m_aCachedToolbarMergingInstructions.clear();
    m_aCachedNotebookBarMergingInstructions.clear();
    m_aCachedStatusbarMergingInstructions.clear();

    ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
    ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
    ReadNotebookBarMergeInstructions( m_aCachedNotebookBarMergingInstructions );
    ReadStatusbarMergeInstructions( m_aCachedStatusbarMergingInstructions );
}

//  public method

void AddonsOptions_Impl::Notify( const Sequence< OUString >& /*lPropertyNames*/ )
{
    Application::PostUserEvent(LINK(this, AddonsOptions_Impl, NotifyEvent));
}

//  public method

void AddonsOptions_Impl::ImplCommit()
{
    SAL_WARN("fwk""AddonsOptions_Impl::ImplCommit(): Not implemented yet!");
}

//  public method

bool AddonsOptions_Impl::HasAddonsMenu() const
{
    return m_aCachedMenuProperties.hasElements();
}

//  public method

sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
{
    return m_aCachedToolBarPartProperties.size();
}

//  public method

sal_Int32 AddonsOptions_Impl::GetAddonsNotebookBarCount() const
{
    return m_aCachedNotebookBarPartProperties.size();
}

//  public method

const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
{
    if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() )
        return m_aCachedToolBarPartProperties[nIndex];
    else
        return m_aEmptyAddonToolBar;
}

//  public method

const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsNotebookBarPart( sal_uInt32 nIndex ) const
{
    if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedNotebookBarPartProperties.size() )
        return m_aCachedNotebookBarPartProperties[nIndex];
    else
        return m_aEmptyAddonNotebookBar;
}

//  public method

const OUString & AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
{
    if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
        return m_aCachedToolBarPartResourceNames[nIndex];
    else
        return EMPTY_OUSTRING;
}

//  public method

const OUString & AddonsOptions_Impl::GetAddonsNotebookBarResourceName( sal_uInt32 nIndex ) const
{
    if ( nIndex < m_aCachedNotebookBarPartResourceNames.size() )
        return m_aCachedNotebookBarPartResourceNames[nIndex];
    else
        return EMPTY_OUSTRING;
}

//  public method

bool AddonsOptions_Impl::GetMergeToolbarInstructions(
    const OUString& rToolbarName,
    MergeToolbarInstructionContainer& rToolbarInstructions ) const
{
    ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName );
    if ( pIter != m_aCachedToolbarMergingInstructions.end() )
    {
        rToolbarInstructions = pIter->second;
        return true;
    }
    else
        return false;
}

//  public method

bool AddonsOptions_Impl::GetMergeNotebookBarInstructions(
    const OUString& rNotebookBarName,
    MergeNotebookBarInstructionContainer& rNotebookBarInstructions ) const
{
    NotebookBarMergingInstructions::const_iterator pIter = m_aCachedNotebookBarMergingInstructions.find( rNotebookBarName );
    if ( pIter != m_aCachedNotebookBarMergingInstructions.end() )
    {
        rNotebookBarInstructions = pIter->second;
        return true;
    }
    else
        return false;
}

//  public method

static BitmapEx ScaleImage( const BitmapEx &rImage, bool bBig )
{
    Size aSize = ToolBox::GetDefaultImageSize(bBig ? ToolBoxButtonSize::Large : ToolBoxButtonSize::Small);
    BitmapEx aScaleBmp(rImage);
    SAL_INFO("fwk""Addons: expensive scale image from "
             << aScaleBmp.GetSizePixel() << " to " << aSize);
    aScaleBmp.Scale(aSize, BmpScaleFlag::BestQuality);
    return aScaleBmp;
}

BitmapEx AddonsOptions_Impl::GetImageFromURL( const OUString& aURL, bool bBig, bool bNoScale )
{
    BitmapEx aImage;

    SAL_INFO("fwk""Expensive: Addons GetImageFromURL " << aURL <<
             " big " << (bBig?"big":"little") <<
             " scale " << (bNoScale ? "noscale" : "scale"));

    ImageManager::iterator pIter = m_aImageManager.find(aURL);
    if ( pIter != m_aImageManager.end() )
    {
        ImageSize eSize = bBig ? IMGSIZE_BIG : IMGSIZE_SMALL;
        int nIdx = static_cast<int>(eSize);
        int nOtherIdx = nIdx ? 0 : 1;

        OneImageEntry& rSizeEntry = pIter->second.aSizeEntry[nIdx];
        OneImageEntry& rOtherEntry = pIter->second.aSizeEntry[nOtherIdx];
        // actually read the image ...
        if (rSizeEntry.aImage.IsEmpty())
            rSizeEntry.aImage = ReadImageFromURL(rSizeEntry.aURL);

        if (rSizeEntry.aImage.IsEmpty())
        { // try the other size and scale it
            aImage = ScaleImage(ReadImageFromURL(rOtherEntry.aURL), bBig);
            rSizeEntry.aImage = aImage;
            if (rSizeEntry.aImage.IsEmpty())
                SAL_WARN("fwk""failed to load addons image " << aURL);
        }

        // FIXME: bNoScale is not terribly meaningful or useful

        if (aImage.IsEmpty() && bNoScale)
            aImage = rSizeEntry.aImage;

        if (aImage.IsEmpty() && !rSizeEntry.aScaled.IsEmpty())
            aImage = rSizeEntry.aScaled;

        else // scale to the correct size for the theme / toolbox
        {
            aImage = rSizeEntry.aImage;
            if (aImage.IsEmpty()) // use and scale the other if one size is missing
                aImage = rOtherEntry.aImage;

            aImage = ScaleImage(aImage, bBig);
            rSizeEntry.aScaled = aImage; // cache for next time
        }
    }

    return aImage;
}

void AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
{
    // Read the AddonMenu set and fill property sequences
    OUString             aAddonMenuNodeName( u"AddonUI/AddonMenu"_ustr );
    Sequence< OUString > aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
    OUString             aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter );

    sal_uInt32              nCount = aAddonMenuNodeSeq.getLength();
    sal_uInt32              nIndex = 0;
    Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
    auto pMenuItem = aMenuItem.getArray();
    // Init the property value sequence
    pMenuItem[ OFFSET_MENUITEM_URL              ].Name = m_aPropNames[ INDEX_URL            ];
    pMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = m_aPropNames[ INDEX_TITLE          ];
    pMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = m_aPropNames[ INDEX_TARGET         ];
    pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
    pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = m_aPropNames[ INDEX_CONTEXT        ];
    pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = m_aPropNames[ INDEX_SUBMENU        ];  // Submenu set!

    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] );

        // Read the MenuItem
        if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) )
        {
            // Successfully read a menu item, append to our list
            sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1;
            rAddonMenuSeq.realloc( nMenuItemCount );
            rAddonMenuSeq.getArray()[nIndex++] = aMenuItem;
        }
    }
}

void AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
{
    // Read the AddonMenu set and fill property sequences
    OUString             aAddonHelpMenuNodeName( u"AddonUI/OfficeHelp"_ustr );
    Sequence< OUString > aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
    OUString             aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter );

    sal_uInt32              nCount = aAddonHelpMenuNodeSeq.getLength();
    sal_uInt32              nIndex = 0;
    Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
    auto pMenuItem = aMenuItem.getArray();
    // Init the property value sequence
    pMenuItem[ OFFSET_MENUITEM_URL              ].Name = m_aPropNames[ INDEX_URL            ];
    pMenuItem[ OFFSET_MENUITEM_TITLE            ].Name = m_aPropNames[ INDEX_TITLE          ];
    pMenuItem[ OFFSET_MENUITEM_TARGET           ].Name = m_aPropNames[ INDEX_TARGET         ];
    pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
    pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Name = m_aPropNames[ INDEX_CONTEXT        ];
    pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Name = m_aPropNames[ INDEX_SUBMENU        ];  // Submenu set!

    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );

        // Read the MenuItem
        if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, true ) )
        {
            // Successfully read a menu item, append to our list
            sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
            rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
            rAddonOfficeHelpMenuSeq.getArray()[nIndex++] = aMenuItem;
        }
    }
}

void AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
{
    // Read the OfficeMenuBar set and fill property sequences
    OUString             aAddonMenuBarNodeName( u"AddonUI/OfficeMenuBar"_ustr );
    Sequence< OUString > aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
    OUString             aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter );

    sal_uInt32              nCount = aAddonMenuBarNodeSeq.getLength();
    sal_uInt32              nIndex = 0;
    Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU );
    auto pPopupMenu = aPopupMenu.getArray();
    // Init the property value sequence
    pPopupMenu[ OFFSET_POPUPMENU_TITLE      ].Name = m_aPropNames[ INDEX_TITLE  ];
    pPopupMenu[ OFFSET_POPUPMENU_CONTEXT    ].Name = m_aPropNames[ INDEX_CONTEXT];
    pPopupMenu[ OFFSET_POPUPMENU_SUBMENU    ].Name = m_aPropNames[ INDEX_SUBMENU];
    pPopupMenu[ OFFSET_POPUPMENU_URL        ].Name = m_aPropNames[ INDEX_URL    ];

    StringToIndexMap aTitleToIndexMap;
    auto pAddonOfficeMenuBarSeq = rAddonOfficeMenuBarSeq.getArray();
    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );

        // Read the MenuItem
        if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
        {
            // Successfully read a popup menu, append to our list
            OUString aPopupTitle;
            if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle )
            {
                StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle );
                if ( pIter != aTitleToIndexMap.end() )
                {
                    // title already there => concat both popup menus
                    Sequence< PropertyValue >& rOldPopupMenu = pAddonOfficeMenuBarSeq[pIter->second];
                    AppendPopupMenu( rOldPopupMenu, aPopupMenu );
                }
                else
                {
                    // not found
                    sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1;
                    rAddonOfficeMenuBarSeq.realloc( nMenuItemCount );
                    pAddonOfficeMenuBarSeq = rAddonOfficeMenuBarSeq.getArray();
                    pAddonOfficeMenuBarSeq[nIndex] = aPopupMenu;
                    aTitleToIndexMap.emplace( aPopupTitle, nIndex );
                    ++nIndex;
                }
            }
        }
    }
}

void AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< OUString >& rAddonOfficeToolBarResNames )
{
    // Read the OfficeToolBar set and fill property sequences
    OUString             aAddonToolBarNodeName( u"AddonUI/OfficeToolBar"_ustr );
    Sequence< OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
    OUString             aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );

    sal_uInt32           nCount = aAddonToolBarNodeSeq.getLength();

    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
        rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
        rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
        ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
    }
}

bool AddonsOptions_Impl::ReadToolBarItemSet( const OUString& rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
{
    sal_uInt32               nToolBarItemCount       = rAddonOfficeToolBarSeq.getLength();
    OUString                 aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
    Sequence< OUString >     aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName );
    Sequence< PropertyValue >   aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
    auto pToolBarItem = aToolBarItem.getArray();
    // Init the property value sequence
    pToolBarItem[ OFFSET_TOOLBARITEM_URL                ].Name = m_aPropNames[ INDEX_URL            ];
    pToolBarItem[ OFFSET_TOOLBARITEM_TITLE              ].Name = m_aPropNames[ INDEX_TITLE          ];
    pToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER    ].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
    pToolBarItem[ OFFSET_TOOLBARITEM_TARGET             ].Name = m_aPropNames[ INDEX_TARGET         ];
    pToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT            ].Name = m_aPropNames[ INDEX_CONTEXT        ];
    pToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE        ].Name = m_aPropNames[ INDEX_CONTROLTYPE    ];
    pToolBarItem[ OFFSET_TOOLBARITEM_WIDTH              ].Name = m_aPropNames[ INDEX_WIDTH          ];

    sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength();
    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );

        // Read the ToolBarItem
        if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
        {
            // Successfully read a toolbar item, append to our list
            sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
            rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
            rAddonOfficeToolBarSeq.getArray()[nAddonCount] = aToolBarItem;
        }
    }

    return ( o3tl::make_unsigned(rAddonOfficeToolBarSeq.getLength()) > nToolBarItemCount );
}

void AddonsOptions_Impl::ReadOfficeNotebookBarSet(
    AddonNotebookBars& rAddonOfficeNotebookBars,
    std::vector<OUString>& rAddonOfficeNotebookBarResNames)
{
    // Read the OfficeToolBar set and fill property sequences
    OUString aAddonNotebookBarNodeName(u"AddonUI/OfficeNotebookBar"_ustr);
    Sequence<OUString> aAddonNotebookBarNodeSeq = GetNodeNames(aAddonNotebookBarNodeName);
    OUString aAddonNotebookBarNode(aAddonNotebookBarNodeName + m_aPathDelimiter);

    sal_uInt32 nCount = aAddonNotebookBarNodeSeq.getLength();

    for (sal_uInt32 n = 0; n < nCount; n++)
    {
        OUString aNotebookBarItemNode(aAddonNotebookBarNode + aAddonNotebookBarNodeSeq[n]);
        rAddonOfficeNotebookBarResNames.push_back(aAddonNotebookBarNodeSeq[n]);
        rAddonOfficeNotebookBars.push_back(m_aEmptyAddonNotebookBar);
        ReadNotebookBarItemSet(aNotebookBarItemNode, rAddonOfficeNotebookBars[n]);
    }
}

bool AddonsOptions_Impl::ReadNotebookBarItemSet(
    const OUString& rNotebookBarItemSetNodeName,
    Sequence<Sequence<PropertyValue>>& rAddonOfficeNotebookBarSeq)
{
    sal_uInt32 nNotebookBarItemCount = rAddonOfficeNotebookBarSeq.getLength();
    OUString aAddonNotebookBarItemSetNode(rNotebookBarItemSetNodeName + m_aPathDelimiter);
    Sequence<OUString> aAddonNotebookBarItemSetNodeSeq = GetNodeNames(rNotebookBarItemSetNodeName);
    Sequence<PropertyValue> aNotebookBarItem(PROPERTYCOUNT_NOTEBOOKBARITEM);
    auto pNotebookBarItem = aNotebookBarItem.getArray();
    // Init the property value sequence
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_URL].Name = m_aPropNames[INDEX_URL];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TITLE].Name = m_aPropNames[INDEX_TITLE];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_IMAGEIDENTIFIER].Name
        = m_aPropNames[INDEX_IMAGEIDENTIFIER];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_TARGET].Name = m_aPropNames[INDEX_TARGET];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTEXT].Name = m_aPropNames[INDEX_CONTEXT];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_CONTROLTYPE].Name = m_aPropNames[INDEX_CONTROLTYPE];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_WIDTH].Name = m_aPropNames[INDEX_WIDTH];
    pNotebookBarItem[OFFSET_NOTEBOOKBARITEM_STYLE].Name = m_aPropNames[INDEX_STYLE];

    sal_uInt32 nCount = aAddonNotebookBarItemSetNodeSeq.getLength();
    for (sal_uInt32 n = 0; n < nCount; n++)
    {
        OUString aNotebookBarItemNode(aAddonNotebookBarItemSetNode
                                      + aAddonNotebookBarItemSetNodeSeq[n]);
        // Read the NotebookBarItem
        if (ReadNotebookBarItem(aNotebookBarItemNode, aNotebookBarItem))
        {
            // Successfully read a toolbar item, append to our list
            sal_uInt32 nAddonCount = rAddonOfficeNotebookBarSeq.getLength();
            rAddonOfficeNotebookBarSeq.realloc(nAddonCount + 1);
            rAddonOfficeNotebookBarSeq.getArray()[nAddonCount] = aNotebookBarItem;
        }
    }

    return (o3tl::make_unsigned(rAddonOfficeNotebookBarSeq.getLength())
            > nNotebookBarItemCount);
}

void AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
{
    // Read the user-defined Images set and fill image manager
    OUString                aAddonImagesNodeName( u"AddonUI/Images"_ustr );
    Sequence< OUString > aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
    OUString                aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );

    sal_uInt32              nCount = aAddonImagesNodeSeq.getLength();

    // Init the property value sequence
    OUString                aURL;

    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );

        // Create sequence for data access
        Sequence< OUString > aAddonImageItemNodePropNames = { aImagesItemNode +
            m_aPathDelimiter +
            m_aPropNames[ OFFSET_MENUITEM_URL ] };

        Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );

        // An user-defined image entry must have a URL. As "ImageIdentifier" has a higher priority
        // we also check if we already have an images association.
        if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
            !aURL.isEmpty() &&
            !HasAssociatedImages( aURL ))
        {
            OUString aImagesUserDefinedItemNode = aImagesItemNode +
                m_aPathDelimiter +
                IMAGES_NODENAME +
                m_aPathDelimiter;

            // Read a user-defined images data
            std::unique_ptr<ImageEntry> pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
            if ( pImageEntry )
            {
                // Successfully read a user-defined images item, put it into our image manager
                aImageManager.emplace( aURL, std::move(*pImageEntry) );
            }
        }
    }
}

OUString AddonsOptions_Impl::GeneratePrefixURL()
{
    // Create a unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu.
    return m_aRootAddonPopupMenuURLPrexfix + OUString::number( ++m_nRootAddonPopupMenuId );
}

void AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer&&nbsp;aContainer )
{
    static constexpr OUString aMenuMergeRootName( u"AddonUI/OfficeMenuBarMerging/"_ustr );

    Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );

    sal_uInt32           nCount = aAddonMergeNodesSeq.getLength();

    // Init the property value sequence
    Sequence< OUString > aNodePropNames( 5 );
    auto pNodePropNames = aNodePropNames.getArray();

    for ( sal_uInt32 i = 0; i < nCount; i++ )
    {
        OUString aMergeAddonInstructions( aMenuMergeRootName + aAddonMergeNodesSeq[i] );

        Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
        sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();

        for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
        {
            OUString aMergeAddonInstructionBase =  aMergeAddonInstructions +
                m_aPathDelimiter +
                aAddonInstMergeNodesSeq[j] +
                m_aPathDelimiter;

            // Create sequence for data access
            pNodePropNames[0] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ];

            pNodePropNames[1] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ];

            pNodePropNames[2] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ];

            pNodePropNames[3] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ];

            pNodePropNames[4] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ];

            Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );

            MergeMenuInstruction aMergeMenuInstruction;
            aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint;
            aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand;
            aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter;
            aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback;
            aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext;

            ReadMergeMenuData( aMergeAddonInstructionBase, aMergeMenuInstruction.aMergeMenu );

            aContainer.push_back( aMergeMenuInstruction );
        }
    }
}

void AddonsOptions_Impl::ReadMergeMenuData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
{
    OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );

    Sequence< OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
    aMergeMenuBaseNode += m_aPathDelimiter;

    // extend the node names to have full path strings
    for ( OUString& rName : asNonConstRange(aSubMenuNodeNames) )
        rName = aMergeMenuBaseNode + rName;

    ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
}

void AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions&&nbsp;rCachedToolbarMergingInstructions )
{
    static constexpr OUString aToolbarMergeRootName( u"AddonUI/OfficeToolbarMerging/"_ustr );

    Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
    sal_uInt32           nCount = aAddonMergeNodesSeq.getLength();

    // Init the property value sequence
    Sequence< OUString > aNodePropNames( 6 );
    auto pNodePropNames = aNodePropNames.getArray();

    for ( sal_uInt32 i = 0; i < nCount; i++ )
    {
        OUString aMergeAddonInstructions( aToolbarMergeRootName + aAddonMergeNodesSeq[i] );

        Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
        sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();

        for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
        {
            OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
                m_aPathDelimiter +
                aAddonInstMergeNodesSeq[j] +
                m_aPathDelimiter;

            // Create sequence for data access
            pNodePropNames[0] = aMergeAddonInstructionBase +
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ];

            pNodePropNames[1] = aMergeAddonInstructionBase +
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ];

            pNodePropNames[2] = aMergeAddonInstructionBase +
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ];

            pNodePropNames[3] = aMergeAddonInstructionBase +
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ];

            pNodePropNames[4] = aMergeAddonInstructionBase +
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ];

            pNodePropNames[5] = aMergeAddonInstructionBase +
                m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ];

            Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );

            MergeToolbarInstruction aMergeToolbarInstruction;
            aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar;
            aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint;
            aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand;
            aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter;
            aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback;
            aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext;

            ReadMergeToolbarData( aMergeAddonInstructionBase,
                                  aMergeToolbarInstruction.aMergeToolbarItems );

            MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ];
            rVector.push_back( aMergeToolbarInstruction );
        }
    }
}

void AddonsOptions_Impl::ReadMergeToolbarData( std::u16string_view aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
{
    OUString aMergeToolbarBaseNode = aMergeAddonInstructionBase +
        m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ];

    ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
}

void AddonsOptions_Impl::ReadNotebookBarMergeInstructions(
    NotebookBarMergingInstructions& rCachedNotebookBarMergingInstructions)
{
    static constexpr OUString aNotebookBarMergeRootName(u"AddonUI/OfficeNotebookBarMerging/"_ustr);

    Sequence<OUString> aAddonMergeNodesSeq = GetNodeNames(aNotebookBarMergeRootName);
    sal_uInt32 nCount = aAddonMergeNodesSeq.getLength();

    // Init the property value sequence
    Sequence<OUString> aNodePropNames(6);
    auto pNodePropNames = aNodePropNames.getArray();

    for (sal_uInt32 i = 0; i < nCount; i++)
    {
        OUString aMergeAddonInstructions(aNotebookBarMergeRootName + aAddonMergeNodesSeq[i]);

        Sequence<OUString> aAddonInstMergeNodesSeq = GetNodeNames(aMergeAddonInstructions);
        sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();

        for (sal_uInt32 j = 0; j < nCountAddons; j++)
        {
            OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
                m_aPathDelimiter +
                aAddonInstMergeNodesSeq[j] +
                m_aPathDelimiter;

            // Create sequence for data access
            pNodePropNames[0] = aMergeAddonInstructionBase +
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBAR];

            pNodePropNames[1] = aMergeAddonInstructionBase +
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEPOINT];

            pNodePropNames[2] = aMergeAddonInstructionBase +
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMAND];

            pNodePropNames[3] = aMergeAddonInstructionBase +
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECOMMANDPARAMETER];

            pNodePropNames[4] = aMergeAddonInstructionBase +
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGEFALLBACK];

            pNodePropNames[5] = aMergeAddonInstructionBase +
                m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_MERGECONTEXT];

            Sequence<Any> aNodePropValues = GetProperties(aNodePropNames);

            MergeNotebookBarInstruction aMergeNotebookBarInstruction;
            aNodePropValues[0] >>= aMergeNotebookBarInstruction.aMergeNotebookBar;
            aNodePropValues[1] >>= aMergeNotebookBarInstruction.aMergePoint;
            aNodePropValues[2] >>= aMergeNotebookBarInstruction.aMergeCommand;
            aNodePropValues[3] >>= aMergeNotebookBarInstruction.aMergeCommandParameter;
            aNodePropValues[4] >>= aMergeNotebookBarInstruction.aMergeFallback;
            aNodePropValues[5] >>= aMergeNotebookBarInstruction.aMergeContext;

            ReadMergeNotebookBarData(aMergeAddonInstructionBase,
                                     aMergeNotebookBarInstruction.aMergeNotebookBarItems);

            MergeNotebookBarInstructionContainer& rVector
                = rCachedNotebookBarMergingInstructions[aMergeNotebookBarInstruction
                                                            .aMergeNotebookBar];
            rVector.push_back(aMergeNotebookBarInstruction);
        }
    }
}

void AddonsOptions_Impl::ReadMergeNotebookBarData(
    std::u16string_view aMergeAddonInstructionBase,
    Sequence<Sequence<PropertyValue>>& rMergeNotebookBarItems)
{
    OUString aMergeNotebookBarBaseNode = aMergeAddonInstructionBase +
        m_aPropMergeNotebookBarNames[OFFSET_MERGENOTEBOOKBAR_NOTEBOOKBARITEMS];

    ReadNotebookBarItemSet(aMergeNotebookBarBaseNode, rMergeNotebookBarItems);
}

void AddonsOptions_Impl::ReadStatusbarMergeInstructions( MergeStatusbarInstructionContainer& aContainer )
{
    static constexpr OUString aStatusbarMergeRootName( u"AddonUI/OfficeStatusbarMerging/"_ustr );

    Sequence< OUString > aAddonMergeNodesSeq = GetNodeNames( aStatusbarMergeRootName );
    sal_uInt32  nCount = aAddonMergeNodesSeq.getLength();

    Sequence< OUString > aNodePropNames( 5 );
    auto pNodePropNames = aNodePropNames.getArray();

    for ( sal_uInt32 i = 0; i < nCount; i++ )
    {
        OUString aMergeAddonInstructions( aStatusbarMergeRootName + aAddonMergeNodesSeq[i] );

        Sequence< OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
        sal_uInt32 nCountAddons = aAddonInstMergeNodesSeq.getLength();

        for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
        {
            OUString aMergeAddonInstructionBase = aMergeAddonInstructions +
                m_aPathDelimiter +
                aAddonInstMergeNodesSeq[j] +
                m_aPathDelimiter;

            // Create sequence for data access
            pNodePropNames[0] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEPOINT ];

            pNodePropNames[1] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMAND ];

            pNodePropNames[2] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECOMMANDPARAMETER ];

            pNodePropNames[3] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGEFALLBACK ];

            pNodePropNames[4] = aMergeAddonInstructionBase +
                m_aPropMergeMenuNames[ OFFSET_MERGESTATUSBAR_MERGECONTEXT ];

            Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );

            MergeStatusbarInstruction aMergeStatusbarInstruction;
            aNodePropValues[0] >>= aMergeStatusbarInstruction.aMergePoint;
            aNodePropValues[1] >>= aMergeStatusbarInstruction.aMergeCommand;
            aNodePropValues[2] >>= aMergeStatusbarInstruction.aMergeCommandParameter;
            // aNodePropValues[3] >>= aMergeStatusbarInstruction.aMergeFallback;
            aNodePropValues[4] >>= aMergeStatusbarInstruction.aMergeContext;

            ReadMergeStatusbarData( aMergeAddonInstructionBase,
                                    aMergeStatusbarInstruction.aMergeStatusbarItems );

            aContainer.push_back( aMergeStatusbarInstruction );
        }
    }
}

void AddonsOptions_Impl::ReadMergeStatusbarData(
    std::u16string_view aMergeAddonInstructionBase,
    Sequence< Sequence< PropertyValue > >& rMergeStatusbarItems )
{
    OUString aMergeStatusbarBaseNode = aMergeAddonInstructionBase +
        m_aPropMergeStatusbarNames[ OFFSET_MERGESTATUSBAR_STATUSBARITEMS ];

    OUString aAddonStatusbarItemSetNode( aMergeStatusbarBaseNode + m_aPathDelimiter );
    Sequence< OUString > aAddonStatusbarItemSetNodeSeq = GetNodeNames( aMergeStatusbarBaseNode );

    Sequence< PropertyValue > aStatusbarItem( PROPERTYCOUNT_STATUSBARITEM );
    auto pStatusbarItem = aStatusbarItem.getArray();
    pStatusbarItem[ OFFSET_STATUSBARITEM_URL       ].Name = m_aPropNames[ INDEX_URL       ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_TITLE     ].Name = m_aPropNames[ INDEX_TITLE     ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT   ].Name = m_aPropNames[ INDEX_CONTEXT   ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN     ].Name = m_aPropNames[ INDEX_ALIGN     ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE  ].Name = m_aPropNames[ INDEX_AUTOSIZE  ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW ].Name = m_aPropNames[ INDEX_OWNERDRAW ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY ].Name = m_aPropNames[ INDEX_MANDATORY ];
    pStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH     ].Name = m_aPropNames[ INDEX_WIDTH     ];

    sal_uInt32 nCount = aAddonStatusbarItemSetNodeSeq.getLength();
    for ( sal_uInt32 n = 0; n < nCount; n++ )
    {
        OUString aStatusbarItemNode( aAddonStatusbarItemSetNode + aAddonStatusbarItemSetNodeSeq[n] );

        if ( ReadStatusBarItem( aStatusbarItemNode, aStatusbarItem ) )
        {
            sal_uInt32 nAddonCount = rMergeStatusbarItems.getLength();
            rMergeStatusbarItems.realloc( nAddonCount+1 );
            rMergeStatusbarItems.getArray()[nAddonCount] = aStatusbarItem;
        }
    }
}

bool AddonsOptions_Impl::ReadStatusBarItem(
    std::u16string_view aStatusarItemNodeName,
    Sequence< PropertyValue >& aStatusbarItem )
{
    bool bResult( false );
    OUString aURL;
    OUString aAddonStatusbarItemTreeNode( aStatusarItemNodeName + m_aPathDelimiter );

    Sequence< Any > aStatusbarItemNodePropValues = GetProperties( GetPropertyNamesStatusbarItem( aAddonStatusbarItemTreeNode ) );

    // Command URL is required
    if (( aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
    {
        auto pStatusbarItem = aStatusbarItem.getArray();
        pStatusbarItem[ OFFSET_STATUSBARITEM_URL        ].Value <<= aURL;
        pStatusbarItem[ OFFSET_STATUSBARITEM_TITLE      ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_TITLE     ];
        pStatusbarItem[ OFFSET_STATUSBARITEM_CONTEXT    ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_CONTEXT   ];
        pStatusbarItem[ OFFSET_STATUSBARITEM_ALIGN      ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_ALIGN     ];
        pStatusbarItem[ OFFSET_STATUSBARITEM_AUTOSIZE   ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_AUTOSIZE  ];
        pStatusbarItem[ OFFSET_STATUSBARITEM_OWNERDRAW  ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_OWNERDRAW ];
        pStatusbarItem[ OFFSET_STATUSBARITEM_MANDATORY  ].Value = aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_MANDATORY ];

        // Configuration uses hyper for long. Therefore transform into sal_Int32
        sal_Int64 nValue( 0 );
        aStatusbarItemNodePropValues[ OFFSET_STATUSBARITEM_WIDTH ] >>= nValue;
        pStatusbarItem[ OFFSET_STATUSBARITEM_WIDTH ].Value <<= sal_Int32( nValue );

        bResult = true;
    }

    return bResult;
}

bool AddonsOptions_Impl::ReadMenuItem( std::u16string_view aMenuNodeName, Sequence< PropertyValue >& aMenuItem, bool bIgnoreSubMenu )
{
    bool             bResult = false;
    OUString         aStrValue;
    OUString         aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );

    Sequence< Any >  aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
    if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && !aStrValue.isEmpty() )
    {
        auto pMenuItem = aMenuItem.getArray();
        pMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;

        OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
        Sequence< OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
        if ( aRootSubMenuNodeNames.hasElements() && !bIgnoreSubMenu )
        {
            // Set a unique prefixed Add-On popup menu URL so it can be identified later
            OUString aPopupMenuURL     = GeneratePrefixURL();
            OUString aPopupMenuImageId;

            aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId;
            ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId );

            // A popup menu must have a title and can have a URL and ImageIdentifier
            // Set the other property values to empty
            pMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aPopupMenuURL;
            pMenuItem[ OFFSET_MENUITEM_TARGET           ].Value <<= OUString();
            pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= aPopupMenuImageId;
            pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];

            // Continue to read the sub menu nodes
            Sequence< Sequence< PropertyValue > > aSubMenuSeq;
            OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
            for ( OUString& rName : asNonConstRange(aRootSubMenuNodeNames) )
                rName = aSubMenuRootNodeName + rName;
            ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
            pMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
            bResult = true;
        }
        else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && !aStrValue.isEmpty() )
        {
            // A simple menu item => read the other properties;
            OUString aMenuImageId;

            aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId;
            ReadAndAssociateImages( aStrValue, aMenuImageId );

            pMenuItem[ OFFSET_MENUITEM_URL              ].Value <<= aStrValue;
            pMenuItem[ OFFSET_MENUITEM_TARGET           ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET         ];
            pMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER  ].Value <<= aMenuImageId;
            pMenuItem[ OFFSET_MENUITEM_CONTEXT          ].Value = aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT        ];
            pMenuItem[ OFFSET_MENUITEM_SUBMENU          ].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!

            bResult = true;
        }
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.49 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.