Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/framework/source/uiconfiguration/moduleuiconfigurationmanager.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 <accelerators/presethandler.hxx>
21
#include <uiconfiguration/imagemanager.hxx>
22
#include <uielement/constitemcontainer.hxx>
23
#include <uielement/rootitemcontainer.hxx>
24
#include <uielement/uielementtypenames.hxx>
25
#include <menuconfiguration.hxx>
26
#include <toolboxconfiguration.hxx>
27
28
#include <statusbarconfiguration.hxx>
29
30
#include <com/sun/star/ui/UIElementType.hpp>
31
#include <com/sun/star/ui/ConfigurationEvent.hpp>
32
#include <com/sun/star/ui/ModuleAcceleratorConfiguration.hpp>
33
#include <com/sun/star/ui/XModuleUIConfigurationManager2.hpp>
34
#include <com/sun/star/lang/DisposedException.hpp>
35
#include <com/sun/star/lang/IllegalAccessException.hpp>
36
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37
#include <com/sun/star/beans/XPropertySet.hpp>
38
#include <com/sun/star/embed/ElementModes.hpp>
39
#include <com/sun/star/embed/InvalidStorageException.hpp>
40
#include <com/sun/star/embed/StorageWrappedTargetException.hpp>
41
#include <com/sun/star/embed/XTransactedObject.hpp>
42
#include <com/sun/star/container/ElementExistException.hpp>
43
#include <com/sun/star/container/XNameAccess.hpp>
44
#include <com/sun/star/container/XIndexContainer.hpp>
45
#include <com/sun/star/io/IOException.hpp>
46
#include <com/sun/star/io/XStream.hpp>
47
#include <com/sun/star/lang/XServiceInfo.hpp>
48
#include <com/sun/star/lang/XComponent.hpp>
49
50
#include <comphelper/propertysequence.hxx>
51
#include <comphelper/sequence.hxx>
52
#include <cppuhelper/exc_hlp.hxx>
53
#include <cppuhelper/implbase.hxx>
54
#include <cppuhelper/supportsservice.hxx>
55
#include <utility>
56
#include <vcl/svapp.hxx>
57
#include <sal/log.hxx>
58
#include <comphelper/interfacecontainer4.hxx>
59
#include <comphelper/propertyvalue.hxx>
60
#include <comphelper/sequenceashashmap.hxx>
61
#include <comphelper/servicehelper.hxx>
62
#include <o3tl/string_view.hxx>
63
#include <memory>
64
#include <mutex>
65
#include <string_view>
66
67
using namespace css;
68
using namespace com::sun::star::uno;
69
using namespace com::sun::star::io;
70
using namespace com::sun::star::embed;
71
using namespace com::sun::star::lang;
72
using namespace com::sun::star::container;
73
using namespace com::sun::star::beans;
74
using namespace framework;
75
76
constexpr OUStringLiteral RESOURCETYPE_MENUBAR = u"menubar";
77
constexpr OUStringLiteral RESOURCETYPE_TOOLBAR = u"toolbar";
78
constexpr OUStringLiteral RESOURCETYPE_STATUSBAR = u"statusbar";
79
constexpr OUStringLiteral RESOURCETYPE_POPUPMENU = u"popupmenu";
80
81
namespace {
82
83
class ModuleUIConfigurationManager : public cppu::WeakImplHelper<
84
                                       css::lang::XServiceInfo,
85
                                       css::lang::XComponent,
86
                                       css::ui::XModuleUIConfigurationManager2 >
87
{
88
public:
89
    ModuleUIConfigurationManager(
90
            const css::uno::Reference< css::uno::XComponentContext >& xServiceManager,
91
            const css::uno::Sequence< css::uno::Any >& aArguments);
92
93
    virtual OUString SAL_CALL getImplementationName() override
94
0
    {
95
0
        return u"com.sun.star.comp.framework.ModuleUIConfigurationManager"_ustr;
96
0
    }
97
98
    virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
99
0
    {
100
0
        return cppu::supportsService(this, ServiceName);
101
0
    }
102
103
    virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
104
0
    {
105
0
        return {u"com.sun.star.ui.ModuleUIConfigurationManager"_ustr};
106
0
    }
107
108
    // XComponent
109
    virtual void SAL_CALL dispose() override;
110
    virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
111
    virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
112
113
    // XUIConfiguration
114
    virtual void SAL_CALL addConfigurationListener( const css::uno::Reference< css::ui::XUIConfigurationListener >& Listener ) override;
115
    virtual void SAL_CALL removeConfigurationListener( const css::uno::Reference< css::ui::XUIConfigurationListener >& Listener ) override;
116
117
    // XUIConfigurationManager
118
    virtual void SAL_CALL reset() override;
119
    virtual css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > SAL_CALL getUIElementsInfo( sal_Int16 ElementType ) override;
120
    virtual css::uno::Reference< css::container::XIndexContainer > SAL_CALL createSettings(  ) override;
121
    virtual sal_Bool SAL_CALL hasSettings( const OUString& ResourceURL ) override;
122
    virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getSettings( const OUString& ResourceURL, sal_Bool bWriteable ) override;
123
    virtual void SAL_CALL replaceSettings( const OUString& ResourceURL, const css::uno::Reference< css::container::XIndexAccess >& aNewData ) override;
124
    virtual void SAL_CALL removeSettings( const OUString& ResourceURL ) override;
125
    virtual void SAL_CALL insertSettings( const OUString& NewResourceURL, const css::uno::Reference< css::container::XIndexAccess >& aNewData ) override;
126
    virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getImageManager() override;
127
    virtual css::uno::Reference< css::ui::XAcceleratorConfiguration > SAL_CALL getShortCutManager() override;
128
    virtual css::uno::Reference< css::ui::XAcceleratorConfiguration > SAL_CALL createShortCutManager() override;
129
    virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getEventsManager() override;
130
131
    // XModuleUIConfigurationManager
132
    virtual sal_Bool SAL_CALL isDefaultSettings( const OUString& ResourceURL ) override;
133
    virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL getDefaultSettings( const OUString& ResourceURL ) override;
134
135
    // XUIConfigurationPersistence
136
    virtual void SAL_CALL reload() override;
137
    virtual void SAL_CALL store() override;
138
    virtual void SAL_CALL storeToStorage( const css::uno::Reference< css::embed::XStorage >& Storage ) override;
139
    virtual sal_Bool SAL_CALL isModified() override;
140
    virtual sal_Bool SAL_CALL isReadOnly() override;
141
142
private:
143
    // private data types
144
    enum Layer
145
    {
146
        LAYER_DEFAULT,
147
        LAYER_USERDEFINED,
148
        LAYER_COUNT
149
    };
150
151
    enum NotifyOp
152
    {
153
        NotifyOp_Remove,
154
        NotifyOp_Insert,
155
        NotifyOp_Replace
156
    };
157
158
    struct UIElementInfo
159
    {
160
        UIElementInfo( OUString _aResourceURL, OUString _aUIName ) :
161
0
            aResourceURL(std::move( _aResourceURL)), aUIName(std::move( _aUIName )) {}
162
        OUString   aResourceURL;
163
        OUString   aUIName;
164
    };
165
166
    struct UIElementData
167
    {
168
0
        UIElementData() : bModified( false ), bDefault( true ), bDefaultNode( true ) {};
169
170
        OUString aResourceURL;
171
        OUString aName;
172
        bool          bModified;        // has been changed since last storing
173
        bool          bDefault;         // default settings
174
        bool          bDefaultNode;     // this is a default layer element data
175
        css::uno::Reference< css::container::XIndexAccess > xSettings;
176
    };
177
178
    typedef std::unordered_map< OUString, UIElementData > UIElementDataHashMap;
179
180
    struct UIElementType
181
    {
182
0
        UIElementType() : bModified( false ),
183
0
                          bLoaded( false ),
184
0
                          nElementType( css::ui::UIElementType::UNKNOWN ) {}
185
186
        bool                                                              bModified;
187
        bool                                                              bLoaded;
188
        sal_Int16                                                         nElementType;
189
        UIElementDataHashMap                                              aElementsHashMap;
190
        css::uno::Reference< css::embed::XStorage > xStorage;
191
    };
192
193
    typedef std::vector< UIElementType > UIElementTypesVector;
194
    typedef std::vector< css::ui::ConfigurationEvent > ConfigEventNotifyContainer;
195
    typedef std::unordered_map< OUString, UIElementInfo > UIElementInfoHashMap;
196
197
    void            impl_Initialize();
198
    void            implts_notifyContainerListener( const css::ui::ConfigurationEvent& aEvent, NotifyOp eOp );
199
    void            impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType );
200
    void            impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType );
201
    UIElementData*  impl_findUIElementData( const OUString& aResourceURL, sal_Int16 nElementType, bool bLoad = true );
202
    void            impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData );
203
    void            impl_storeElementTypeData( const css::uno::Reference< css::embed::XStorage >& xStorage, UIElementType& rElementType, bool bResetModifyState = true );
204
    void            impl_resetElementTypeData( UIElementType& rUserElementType, UIElementType const & rDefaultElementType, ConfigEventNotifyContainer& rRemoveNotifyContainer, ConfigEventNotifyContainer& rReplaceNotifyContainer );
205
    void            impl_reloadElementTypeData( UIElementType& rUserElementType, UIElementType const & rDefaultElementType, ConfigEventNotifyContainer& rRemoveNotifyContainer, ConfigEventNotifyContainer& rReplaceNotifyContainer );
206
207
    UIElementTypesVector                                      m_aUIElements[LAYER_COUNT];
208
    std::unique_ptr<PresetHandler>                            m_pStorageHandler[css::ui::UIElementType::COUNT];
209
    css::uno::Reference< css::embed::XStorage >               m_xDefaultConfigStorage;
210
    css::uno::Reference< css::embed::XStorage >               m_xUserConfigStorage;
211
    bool                                                      m_bReadOnly;
212
    bool                                                      m_bModified;
213
    bool                                                      m_bDisposed;
214
    OUString                                                  m_aXMLPostfix;
215
    OUString                                                  m_aPropUIName;
216
    OUString                                                  m_aModuleIdentifier;
217
    css::uno::Reference< css::embed::XTransactedObject >      m_xUserRootCommit;
218
    css::uno::Reference< css::uno::XComponentContext >        m_xContext;
219
    std::mutex                                                m_mutex;
220
    comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListeners;
221
    comphelper::OInterfaceContainerHelper4<css::ui::XUIConfigurationListener> m_aConfigListeners;
222
    rtl::Reference< ImageManager >                            m_xModuleImageManager;
223
    css::uno::Reference< css::ui::XAcceleratorConfiguration > m_xModuleAcceleratorManager;
224
};
225
226
// important: The order and position of the elements must match the constant
227
// definition of "css::ui::UIElementType"
228
constexpr std::u16string_view UIELEMENTTYPENAMES[] =
229
{
230
    u"",  // Dummy value for unknown!
231
    u"" UIELEMENTTYPE_MENUBAR_NAME,
232
    u"" UIELEMENTTYPE_POPUPMENU_NAME,
233
    u"" UIELEMENTTYPE_TOOLBAR_NAME,
234
    u"" UIELEMENTTYPE_STATUSBAR_NAME,
235
    u"" UIELEMENTTYPE_FLOATINGWINDOW_NAME,
236
    u"" UIELEMENTTYPE_PROGRESSBAR_NAME,
237
    u"" UIELEMENTTYPE_TOOLPANEL_NAME
238
};
239
240
constexpr std::u16string_view RESOURCEURL_PREFIX = u"private:resource/";
241
242
sal_Int16 RetrieveTypeFromResourceURL( std::u16string_view aResourceURL )
243
0
{
244
245
0
    if (( o3tl::starts_with(aResourceURL, RESOURCEURL_PREFIX ) ) &&
246
0
        ( aResourceURL.size() > RESOURCEURL_PREFIX.size() ))
247
0
    {
248
0
        std::u16string_view aTmpStr = aResourceURL.substr( RESOURCEURL_PREFIX.size() );
249
0
        size_t nIndex = aTmpStr.find( '/' );
250
0
        if (( nIndex > 0 ) &&  ( aTmpStr.size() > nIndex ))
251
0
        {
252
0
            std::u16string_view aTypeStr( aTmpStr.substr( 0, nIndex ));
253
0
            for ( int i = 0; i < ui::UIElementType::COUNT; i++ )
254
0
            {
255
0
                if ( aTypeStr == UIELEMENTTYPENAMES[i] )
256
0
                    return sal_Int16( i );
257
0
            }
258
0
        }
259
0
    }
260
261
0
    return ui::UIElementType::UNKNOWN;
262
0
}
263
264
OUString RetrieveNameFromResourceURL( std::u16string_view aResourceURL )
265
0
{
266
0
    if (( o3tl::starts_with(aResourceURL, RESOURCEURL_PREFIX ) ) &&
267
0
        ( aResourceURL.size() > RESOURCEURL_PREFIX.size() ))
268
0
    {
269
0
        size_t nIndex = aResourceURL.rfind( '/' );
270
271
0
        if ( nIndex > 0 && nIndex != std::u16string_view::npos && (( nIndex+1 ) < aResourceURL.size()) )
272
0
            return OUString(aResourceURL.substr( nIndex+1 ));
273
0
    }
274
275
0
    return OUString();
276
0
}
277
278
void ModuleUIConfigurationManager::impl_fillSequenceWithElementTypeInfo( UIElementInfoHashMap& aUIElementInfoCollection, sal_Int16 nElementType )
279
0
{
280
    // preload list of element types on demand
281
0
    impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType );
282
0
    impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
283
284
0
    UIElementDataHashMap& rUserElements = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap;
285
286
0
    OUString aCustomUrlPrefix( u"custom_"_ustr );
287
0
    for (auto const& userElement : rUserElements)
288
0
    {
289
0
        sal_Int32 nIndex = userElement.second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX.size() );
290
0
        if ( nIndex > static_cast<sal_Int32>(RESOURCEURL_PREFIX.size()) )
291
0
        {
292
            // Performance: Retrieve user interface name only for custom user interface elements.
293
            // It's only used by them!
294
0
            UIElementData* pDataSettings = impl_findUIElementData( userElement.second.aResourceURL, nElementType );
295
0
            if ( pDataSettings )
296
0
            {
297
                // Retrieve user interface name from XPropertySet interface
298
0
                OUString aUIName;
299
0
                Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
300
0
                if ( xPropSet.is() )
301
0
                {
302
0
                    Any a = xPropSet->getPropertyValue( m_aPropUIName );
303
0
                    a >>= aUIName;
304
0
                }
305
306
0
                UIElementInfo aInfo( userElement.second.aResourceURL, aUIName );
307
0
                aUIElementInfoCollection.emplace( userElement.second.aResourceURL, aInfo );
308
0
            }
309
0
        }
310
0
        else
311
0
        {
312
            // The user interface name for standard user interface elements is stored in the WindowState.xcu file
313
0
            UIElementInfo aInfo( userElement.second.aResourceURL, OUString() );
314
0
            aUIElementInfoCollection.emplace( userElement.second.aResourceURL, aInfo );
315
0
        }
316
0
    }
317
318
0
    UIElementDataHashMap& rDefaultElements = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
319
320
0
    for (auto const& defaultElement : rDefaultElements)
321
0
    {
322
0
        UIElementInfoHashMap::const_iterator pIterInfo = aUIElementInfoCollection.find( defaultElement.second.aResourceURL );
323
0
        if ( pIterInfo == aUIElementInfoCollection.end() )
324
0
        {
325
0
            sal_Int32 nIndex = defaultElement.second.aResourceURL.indexOf( aCustomUrlPrefix, RESOURCEURL_PREFIX.size() );
326
0
            if ( nIndex > static_cast<sal_Int32>(RESOURCEURL_PREFIX.size()) )
327
0
            {
328
                // Performance: Retrieve user interface name only for custom user interface elements.
329
                // It's only used by them!
330
0
                UIElementData* pDataSettings = impl_findUIElementData( defaultElement.second.aResourceURL, nElementType );
331
0
                if ( pDataSettings )
332
0
                {
333
                    // Retrieve user interface name from XPropertySet interface
334
0
                    OUString aUIName;
335
0
                    Reference< XPropertySet > xPropSet( pDataSettings->xSettings, UNO_QUERY );
336
0
                    if ( xPropSet.is() )
337
0
                    {
338
0
                        Any a = xPropSet->getPropertyValue( m_aPropUIName );
339
0
                        a >>= aUIName;
340
0
                    }
341
0
                    UIElementInfo aInfo( defaultElement.second.aResourceURL, aUIName );
342
0
                    aUIElementInfoCollection.emplace( defaultElement.second.aResourceURL, aInfo );
343
0
                }
344
0
            }
345
0
            else
346
0
            {
347
                // The user interface name for standard user interface elements is stored in the WindowState.xcu file
348
0
                UIElementInfo aInfo( defaultElement.second.aResourceURL, OUString() );
349
0
                aUIElementInfoCollection.emplace( defaultElement.second.aResourceURL, aInfo );
350
0
            }
351
0
        }
352
0
    }
353
0
}
354
355
void ModuleUIConfigurationManager::impl_preloadUIElementTypeList( Layer eLayer, sal_Int16 nElementType )
356
0
{
357
0
    UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType];
358
359
0
    if ( rElementTypeData.bLoaded )
360
0
        return;
361
362
0
    Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
363
0
    if ( !xElementTypeStorage.is() )
364
0
        return;
365
366
0
    OUString aResURLPrefix =
367
0
        OUString::Concat(RESOURCEURL_PREFIX) +
368
0
        UIELEMENTTYPENAMES[ nElementType ] +
369
0
        "/";
370
371
0
    UIElementDataHashMap& rHashMap = rElementTypeData.aElementsHashMap;
372
0
    const Sequence< OUString > aUIElementNames = xElementTypeStorage->getElementNames();
373
0
    for ( OUString const & rElementName : aUIElementNames )
374
0
    {
375
0
        UIElementData aUIElementData;
376
377
        // Resource name must be without ".xml"
378
0
        sal_Int32 nIndex = rElementName.lastIndexOf( '.' );
379
0
        if (( nIndex > 0 ) && ( nIndex < rElementName.getLength() ))
380
0
        {
381
0
            std::u16string_view aExtension( rElementName.subView( nIndex+1 ));
382
0
            std::u16string_view aUIElementName( rElementName.subView( 0, nIndex ));
383
384
0
            if (!aUIElementName.empty() &&
385
0
                ( o3tl::equalsIgnoreAsciiCase(aExtension, u"xml")))
386
0
            {
387
0
                aUIElementData.aResourceURL = aResURLPrefix + aUIElementName;
388
0
                aUIElementData.aName        = rElementName;
389
390
0
                if ( eLayer == LAYER_USERDEFINED )
391
0
                {
392
0
                    aUIElementData.bModified    = false;
393
0
                    aUIElementData.bDefault     = false;
394
0
                    aUIElementData.bDefaultNode = false;
395
0
                }
396
397
                // Create std::unordered_map entries for all user interface elements inside the storage. We don't load the
398
                // settings to speed up the process.
399
0
                rHashMap.emplace( aUIElementData.aResourceURL, aUIElementData );
400
0
            }
401
0
        }
402
0
        rElementTypeData.bLoaded = true;
403
0
    }
404
405
0
}
406
407
void ModuleUIConfigurationManager::impl_requestUIElementData( sal_Int16 nElementType, Layer eLayer, UIElementData& aUIElementData )
408
0
{
409
0
    UIElementType& rElementTypeData = m_aUIElements[eLayer][nElementType];
410
411
0
    Reference< XStorage > xElementTypeStorage = rElementTypeData.xStorage;
412
0
    if ( xElementTypeStorage.is() && !aUIElementData.aName.isEmpty() )
413
0
    {
414
0
        try
415
0
        {
416
0
            Reference< XStream > xStream = xElementTypeStorage->openStreamElement( aUIElementData.aName, ElementModes::READ );
417
0
            Reference< XInputStream > xInputStream = xStream->getInputStream();
418
419
0
            if ( xInputStream.is() )
420
0
            {
421
0
                switch ( nElementType )
422
0
                {
423
0
                    case css::ui::UIElementType::UNKNOWN:
424
0
                    break;
425
426
0
                    case css::ui::UIElementType::MENUBAR:
427
0
                    case css::ui::UIElementType::POPUPMENU:
428
0
                    {
429
0
                        try
430
0
                        {
431
0
                            MenuConfiguration aMenuCfg( m_xContext );
432
0
                            Reference< XIndexAccess > xContainer( aMenuCfg.CreateMenuBarConfigurationFromXML( xInputStream ));
433
0
                            auto pRootItemContainer = dynamic_cast<RootItemContainer*>( xContainer.get() );
434
0
                            if ( pRootItemContainer )
435
0
                                aUIElementData.xSettings = new ConstItemContainer( pRootItemContainer, true );
436
0
                            else
437
0
                                aUIElementData.xSettings = new ConstItemContainer( xContainer, true );
438
0
                            return;
439
0
                        }
440
0
                        catch ( const css::lang::WrappedTargetException& )
441
0
                        {
442
0
                        }
443
0
                    }
444
0
                    break;
445
446
0
                    case css::ui::UIElementType::TOOLBAR:
447
0
                    {
448
0
                        try
449
0
                        {
450
0
                            Reference< XIndexContainer > xIndexContainer( new RootItemContainer() );
451
0
                            ToolBoxConfiguration::LoadToolBox( m_xContext, xInputStream, xIndexContainer );
452
0
                            auto pRootItemContainer = dynamic_cast<RootItemContainer*>( xIndexContainer.get() );
453
0
                            aUIElementData.xSettings = new ConstItemContainer( pRootItemContainer, true );
454
0
                            return;
455
0
                        }
456
0
                        catch ( const css::lang::WrappedTargetException& )
457
0
                        {
458
0
                        }
459
460
0
                        break;
461
0
                    }
462
463
0
                    case css::ui::UIElementType::STATUSBAR:
464
0
                    {
465
0
                        try
466
0
                        {
467
0
                            Reference< XIndexContainer > xIndexContainer( new RootItemContainer() );
468
0
                            StatusBarConfiguration::LoadStatusBar( m_xContext, xInputStream, xIndexContainer );
469
0
                            auto pRootItemContainer = dynamic_cast<RootItemContainer*>( xIndexContainer.get() );
470
0
                            aUIElementData.xSettings = new ConstItemContainer( pRootItemContainer, true );
471
0
                            return;
472
0
                        }
473
0
                        catch ( const css::lang::WrappedTargetException& )
474
0
                        {
475
0
                        }
476
477
0
                        break;
478
0
                    }
479
480
0
                    case css::ui::UIElementType::FLOATINGWINDOW:
481
0
                    {
482
0
                        break;
483
0
                    }
484
0
                }
485
0
            }
486
0
        }
487
0
        catch ( const css::embed::InvalidStorageException& )
488
0
        {
489
0
        }
490
0
        catch ( const css::lang::IllegalArgumentException& )
491
0
        {
492
0
        }
493
0
        catch ( const css::io::IOException& )
494
0
        {
495
0
        }
496
0
        catch ( const css::embed::StorageWrappedTargetException& )
497
0
        {
498
0
        }
499
0
    }
500
501
    // At least we provide an empty settings container!
502
0
    aUIElementData.xSettings = new ConstItemContainer();
503
0
}
504
505
ModuleUIConfigurationManager::UIElementData*  ModuleUIConfigurationManager::impl_findUIElementData( const OUString& aResourceURL, sal_Int16 nElementType, bool bLoad )
506
0
{
507
    // preload list of element types on demand
508
0
    impl_preloadUIElementTypeList( LAYER_USERDEFINED, nElementType );
509
0
    impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
510
511
    // first try to look into our user-defined vector/unordered_map combination
512
0
    UIElementDataHashMap& rUserHashMap = m_aUIElements[LAYER_USERDEFINED][nElementType].aElementsHashMap;
513
0
    UIElementDataHashMap::iterator pIter = rUserHashMap.find( aResourceURL );
514
0
    if ( pIter != rUserHashMap.end() )
515
0
    {
516
        // Default data settings data must be retrieved from the default layer!
517
0
        if ( !pIter->second.bDefault )
518
0
        {
519
0
            if ( !pIter->second.xSettings.is() && bLoad )
520
0
                impl_requestUIElementData( nElementType, LAYER_USERDEFINED, pIter->second );
521
0
            return &(pIter->second);
522
0
        }
523
0
    }
524
525
    // Not successful, we have to look into our default vector/unordered_map combination
526
0
    UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
527
0
    pIter = rDefaultHashMap.find( aResourceURL );
528
0
    if ( pIter != rDefaultHashMap.end() )
529
0
    {
530
0
        if ( !pIter->second.xSettings.is() && bLoad )
531
0
            impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
532
0
        return &(pIter->second);
533
0
    }
534
535
    // Nothing has been found!
536
0
    return nullptr;
537
0
}
538
539
void ModuleUIConfigurationManager::impl_storeElementTypeData( const Reference< XStorage >& xStorage, UIElementType& rElementType, bool bResetModifyState )
540
0
{
541
0
    UIElementDataHashMap& rHashMap          = rElementType.aElementsHashMap;
542
543
0
    for (auto & elem : rHashMap)
544
0
    {
545
0
        UIElementData& rElement = elem.second;
546
0
        if ( rElement.bModified )
547
0
        {
548
0
            if ( rElement.bDefault )
549
0
            {
550
0
                xStorage->removeElement( rElement.aName );
551
0
                rElement.bModified = false; // mark as not modified
552
0
            }
553
0
            else
554
0
            {
555
0
                Reference< XStream > xStream = xStorage->openStreamElement( rElement.aName, ElementModes::WRITE|ElementModes::TRUNCATE );
556
0
                Reference< XOutputStream > xOutputStream( xStream->getOutputStream() );
557
558
0
                if ( xOutputStream.is() )
559
0
                {
560
0
                    switch( rElementType.nElementType )
561
0
                    {
562
0
                        case css::ui::UIElementType::MENUBAR:
563
0
                        case css::ui::UIElementType::POPUPMENU:
564
0
                        {
565
0
                            try
566
0
                            {
567
0
                                MenuConfiguration aMenuCfg( m_xContext );
568
0
                                aMenuCfg.StoreMenuBarConfigurationToXML(
569
0
                                    rElement.xSettings, xOutputStream, rElementType.nElementType == css::ui::UIElementType::MENUBAR );
570
0
                            }
571
0
                            catch ( const css::lang::WrappedTargetException& )
572
0
                            {
573
0
                            }
574
0
                        }
575
0
                        break;
576
577
0
                        case css::ui::UIElementType::TOOLBAR:
578
0
                        {
579
0
                            try
580
0
                            {
581
0
                                ToolBoxConfiguration::StoreToolBox( m_xContext, xOutputStream, rElement.xSettings );
582
0
                            }
583
0
                            catch ( const css::lang::WrappedTargetException& )
584
0
                            {
585
0
                            }
586
0
                        }
587
0
                        break;
588
589
0
                        case css::ui::UIElementType::STATUSBAR:
590
0
                        {
591
0
                            try
592
0
                            {
593
0
                                StatusBarConfiguration::StoreStatusBar( m_xContext, xOutputStream, rElement.xSettings );
594
0
                            }
595
0
                            catch ( const css::lang::WrappedTargetException& )
596
0
                            {
597
0
                            }
598
0
                        }
599
0
                        break;
600
601
0
                        default:
602
0
                        break;
603
0
                    }
604
0
                }
605
606
                // mark as not modified if we store to our own storage
607
0
                if ( bResetModifyState )
608
0
                    rElement.bModified = false;
609
0
            }
610
0
        }
611
0
    }
612
613
    // commit element type storage
614
0
    Reference< XTransactedObject > xTransactedObject( xStorage, UNO_QUERY );
615
0
    if ( xTransactedObject.is() )
616
0
        xTransactedObject->commit();
617
618
    // mark UIElementType as not modified if we store to our own storage
619
0
    if ( bResetModifyState )
620
0
        rElementType.bModified = false;
621
0
}
622
623
// This is only allowed to be called on the LAYER_USER_DEFINED!
624
void ModuleUIConfigurationManager::impl_resetElementTypeData(
625
    UIElementType& rUserElementType,
626
    UIElementType const & rDefaultElementType,
627
    ConfigEventNotifyContainer& rRemoveNotifyContainer,
628
    ConfigEventNotifyContainer& rReplaceNotifyContainer )
629
0
{
630
0
    UIElementDataHashMap& rHashMap          = rUserElementType.aElementsHashMap;
631
632
0
    Reference< XUIConfigurationManager > xThis(this);
633
0
    Reference< XInterface >  xIfac( xThis, UNO_QUERY );
634
0
    sal_Int16 nType = rUserElementType.nElementType;
635
636
    // Make copies of the event structures to be thread-safe. We have to unlock our mutex before calling
637
    // our listeners!
638
0
    for (auto & elem : rHashMap)
639
0
    {
640
0
        UIElementData& rElement = elem.second;
641
0
        if ( !rElement.bDefault )
642
0
        {
643
0
            if ( rDefaultElementType.xStorage->hasByName( rElement.aName ))
644
0
            {
645
                // Replace settings with data from default layer
646
0
                Reference< XIndexAccess > xOldSettings( rElement.xSettings );
647
0
                impl_requestUIElementData( nType, LAYER_DEFAULT, rElement );
648
649
0
                ui::ConfigurationEvent aReplaceEvent;
650
0
                aReplaceEvent.ResourceURL = rElement.aResourceURL;
651
0
                aReplaceEvent.Accessor <<= xThis;
652
0
                aReplaceEvent.Source = xIfac;
653
0
                aReplaceEvent.ReplacedElement <<= xOldSettings;
654
0
                aReplaceEvent.Element <<= rElement.xSettings;
655
656
0
                rReplaceNotifyContainer.push_back( aReplaceEvent );
657
658
                // Mark element as default and not modified. That means "not active"
659
                // in the user layer anymore.
660
0
                rElement.bModified = false;
661
0
                rElement.bDefault  = true;
662
0
            }
663
0
            else
664
0
            {
665
                // Remove user-defined settings from user layer
666
0
                ui::ConfigurationEvent aEvent;
667
0
                aEvent.ResourceURL = rElement.aResourceURL;
668
0
                aEvent.Accessor <<= xThis;
669
0
                aEvent.Source = xIfac;
670
0
                aEvent.Element <<= rElement.xSettings;
671
672
0
                rRemoveNotifyContainer.push_back( aEvent );
673
674
                // Mark element as default and not modified. That means "not active"
675
                // in the user layer anymore.
676
0
                rElement.bModified = false;
677
0
                rElement.bDefault  = true;
678
0
            }
679
0
        }
680
0
    }
681
682
    // Remove all settings from our user interface elements
683
0
    rHashMap.clear();
684
0
}
685
686
void ModuleUIConfigurationManager::impl_reloadElementTypeData(
687
    UIElementType&              rUserElementType,
688
    UIElementType const &       rDefaultElementType,
689
    ConfigEventNotifyContainer& rRemoveNotifyContainer,
690
    ConfigEventNotifyContainer& rReplaceNotifyContainer )
691
0
{
692
0
    UIElementDataHashMap& rHashMap          = rUserElementType.aElementsHashMap;
693
694
0
    Reference< XUIConfigurationManager > xThis(this);
695
0
    Reference< XInterface > xIfac( xThis, UNO_QUERY );
696
0
    sal_Int16 nType = rUserElementType.nElementType;
697
698
0
    for (auto & elem : rHashMap)
699
0
    {
700
0
        UIElementData& rElement = elem.second;
701
0
        if ( rElement.bModified )
702
0
        {
703
0
            if ( rUserElementType.xStorage->hasByName( rElement.aName ))
704
0
            {
705
                // Replace settings with data from user layer
706
0
                Reference< XIndexAccess > xOldSettings( rElement.xSettings );
707
708
0
                impl_requestUIElementData( nType, LAYER_USERDEFINED, rElement );
709
710
0
                ui::ConfigurationEvent aReplaceEvent;
711
712
0
                aReplaceEvent.ResourceURL = rElement.aResourceURL;
713
0
                aReplaceEvent.Accessor <<= xThis;
714
0
                aReplaceEvent.Source = xIfac;
715
0
                aReplaceEvent.ReplacedElement <<= xOldSettings;
716
0
                aReplaceEvent.Element <<= rElement.xSettings;
717
0
                rReplaceNotifyContainer.push_back( aReplaceEvent );
718
719
0
                rElement.bModified = false;
720
0
            }
721
0
            else if ( rDefaultElementType.xStorage->hasByName( rElement.aName ))
722
0
            {
723
                // Replace settings with data from default layer
724
0
                Reference< XIndexAccess > xOldSettings( rElement.xSettings );
725
726
0
                impl_requestUIElementData( nType, LAYER_DEFAULT, rElement );
727
728
0
                ui::ConfigurationEvent aReplaceEvent;
729
730
0
                aReplaceEvent.ResourceURL = rElement.aResourceURL;
731
0
                aReplaceEvent.Accessor <<= xThis;
732
0
                aReplaceEvent.Source = xIfac;
733
0
                aReplaceEvent.ReplacedElement <<= xOldSettings;
734
0
                aReplaceEvent.Element <<= rElement.xSettings;
735
0
                rReplaceNotifyContainer.push_back( aReplaceEvent );
736
737
                // Mark element as default and not modified. That means "not active"
738
                // in the user layer anymore.
739
0
                rElement.bModified = false;
740
0
                rElement.bDefault  = true;
741
0
            }
742
0
            else
743
0
            {
744
                // Element settings are not in any storage => remove
745
0
                ui::ConfigurationEvent aRemoveEvent;
746
747
0
                aRemoveEvent.ResourceURL = rElement.aResourceURL;
748
0
                aRemoveEvent.Accessor <<= xThis;
749
0
                aRemoveEvent.Source = xIfac;
750
0
                aRemoveEvent.Element <<= rElement.xSettings;
751
752
0
                rRemoveNotifyContainer.push_back( aRemoveEvent );
753
754
                // Mark element as default and not modified. That means "not active"
755
                // in the user layer anymore.
756
0
                rElement.bModified = false;
757
0
                rElement.bDefault  = true;
758
0
            }
759
0
        }
760
0
    }
761
762
0
    rUserElementType.bModified = false;
763
0
}
764
765
void ModuleUIConfigurationManager::impl_Initialize()
766
0
{
767
    // Initialize the top-level structures with the storage data
768
0
    if ( m_xUserConfigStorage.is() )
769
0
    {
770
        // Try to access our module sub folder
771
0
        for ( sal_Int16 i = 1; i < css::ui::UIElementType::COUNT;
772
0
              i++ )
773
0
        {
774
0
            Reference< XStorage > xElementTypeStorage;
775
0
            try
776
0
            {
777
0
                if ( m_pStorageHandler[i] )
778
0
                    xElementTypeStorage = m_pStorageHandler[i]->getWorkingStorageUser();
779
0
            }
780
0
            catch ( const css::container::NoSuchElementException& )
781
0
            {
782
0
            }
783
0
            catch ( const css::embed::InvalidStorageException& )
784
0
            {
785
0
            }
786
0
            catch ( const css::lang::IllegalArgumentException& )
787
0
            {
788
0
            }
789
0
            catch ( const css::io::IOException& )
790
0
            {
791
0
            }
792
0
            catch ( const css::embed::StorageWrappedTargetException& )
793
0
            {
794
0
            }
795
796
0
            m_aUIElements[LAYER_USERDEFINED][i].nElementType = i;
797
0
            m_aUIElements[LAYER_USERDEFINED][i].bModified = false;
798
0
            m_aUIElements[LAYER_USERDEFINED][i].xStorage = std::move(xElementTypeStorage);
799
0
        }
800
0
    }
801
802
0
    if ( !m_xDefaultConfigStorage.is() )
803
0
        return;
804
805
0
    Reference< XNameAccess > xNameAccess( m_xDefaultConfigStorage, UNO_QUERY_THROW );
806
807
    // Try to access our module sub folder
808
0
    for ( sal_Int16 i = 1; i < css::ui::UIElementType::COUNT;
809
0
          i++ )
810
0
    {
811
0
        Reference< XStorage > xElementTypeStorage;
812
0
        try
813
0
        {
814
0
            const OUString sName( UIELEMENTTYPENAMES[i] );
815
0
            if( xNameAccess->hasByName( sName ) )
816
0
                xNameAccess->getByName( sName ) >>= xElementTypeStorage;
817
0
        }
818
0
        catch ( const css::container::NoSuchElementException& )
819
0
        {
820
0
        }
821
822
0
        m_aUIElements[LAYER_DEFAULT][i].nElementType = i;
823
0
        m_aUIElements[LAYER_DEFAULT][i].bModified = false;
824
0
        m_aUIElements[LAYER_DEFAULT][i].xStorage = std::move(xElementTypeStorage);
825
0
    }
826
0
}
827
828
ModuleUIConfigurationManager::ModuleUIConfigurationManager(
829
        const Reference< XComponentContext >& xContext,
830
        const css::uno::Sequence< css::uno::Any >& aArguments)
831
0
    : m_bReadOnly( true )
832
0
    , m_bModified( false )
833
0
    , m_bDisposed( false )
834
0
    , m_aXMLPostfix( u".xml"_ustr )
835
0
    , m_aPropUIName( u"UIName"_ustr )
836
0
    , m_xContext( xContext )
837
0
{
838
    // Make sure we have a default initialized entry for every layer and user interface element type!
839
    // The following code depends on this!
840
0
    m_aUIElements[LAYER_DEFAULT].resize( css::ui::UIElementType::COUNT );
841
0
    m_aUIElements[LAYER_USERDEFINED].resize( css::ui::UIElementType::COUNT );
842
843
0
    SolarMutexGuard g;
844
845
0
    OUString aModuleShortName;
846
0
    if( aArguments.getLength() == 2 && (aArguments[0] >>= aModuleShortName) && (aArguments[1] >>= m_aModuleIdentifier))
847
0
    {
848
0
    }
849
0
    else
850
0
    {
851
0
        ::comphelper::SequenceAsHashMap lArgs(aArguments);
852
0
        aModuleShortName  = lArgs.getUnpackedValueOrDefault(u"ModuleShortName"_ustr, OUString());
853
0
        m_aModuleIdentifier = lArgs.getUnpackedValueOrDefault(u"ModuleIdentifier"_ustr, OUString());
854
0
    }
855
856
0
    for ( int i = 1; i < css::ui::UIElementType::COUNT; i++ )
857
0
    {
858
0
        OUString aResourceType;
859
0
        if ( i == css::ui::UIElementType::MENUBAR )
860
0
            aResourceType = RESOURCETYPE_MENUBAR;
861
0
        else if ( i == css::ui::UIElementType::TOOLBAR )
862
0
            aResourceType = RESOURCETYPE_TOOLBAR;
863
0
        else if ( i == css::ui::UIElementType::STATUSBAR )
864
0
            aResourceType = RESOURCETYPE_STATUSBAR;
865
0
        else if ( i == css::ui::UIElementType::POPUPMENU )
866
0
            aResourceType = RESOURCETYPE_POPUPMENU;
867
868
0
        if ( !aResourceType.isEmpty() )
869
0
        {
870
0
            m_pStorageHandler[i].reset( new PresetHandler( m_xContext ) );
871
0
            m_pStorageHandler[i]->connectToResource( PresetHandler::E_MODULES,
872
0
                                                     aResourceType, // this path won't be used later... see next lines!
873
0
                                                     aModuleShortName,
874
0
                                                     css::uno::Reference< css::embed::XStorage >()); // no document root used here!
875
0
        }
876
0
    }
877
878
    // initialize root storages for all resource types
879
0
    m_xUserRootCommit.set( m_pStorageHandler[css::ui::UIElementType::MENUBAR]->getOrCreateRootStorageUser(), css::uno::UNO_QUERY); // can be empty
880
0
    m_xDefaultConfigStorage = m_pStorageHandler[css::ui::UIElementType::MENUBAR]->getParentStorageShare();
881
0
    m_xUserConfigStorage    = m_pStorageHandler[css::ui::UIElementType::MENUBAR]->getParentStorageUser();
882
883
0
    if ( m_xUserConfigStorage.is() )
884
0
    {
885
0
        Reference< XPropertySet > xPropSet( m_xUserConfigStorage, UNO_QUERY );
886
0
        if ( xPropSet.is() )
887
0
        {
888
0
            tools::Long nOpenMode = 0;
889
0
            Any a = xPropSet->getPropertyValue(u"OpenMode"_ustr);
890
0
            if ( a >>= nOpenMode )
891
0
                m_bReadOnly = !( nOpenMode & ElementModes::WRITE );
892
0
        }
893
0
    }
894
895
0
    impl_Initialize();
896
0
}
897
898
// XComponent
899
void SAL_CALL ModuleUIConfigurationManager::dispose()
900
0
{
901
0
    Reference< XComponent > xThis(this);
902
903
0
    css::lang::EventObject aEvent( xThis );
904
0
    {
905
0
        std::unique_lock aGuard(m_mutex);
906
0
        m_aEventListeners.disposeAndClear( aGuard, aEvent );
907
0
    }
908
0
    {
909
0
        std::unique_lock aGuard(m_mutex);
910
0
        m_aConfigListeners.disposeAndClear( aGuard, aEvent );
911
0
    }
912
913
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
914
0
    SolarMutexClearableGuard aGuard;
915
0
    rtl::Reference< ImageManager > xModuleImageManager = std::move( m_xModuleImageManager );
916
0
    m_xModuleAcceleratorManager.clear();
917
0
    m_aUIElements[LAYER_USERDEFINED].clear();
918
0
    m_aUIElements[LAYER_DEFAULT].clear();
919
0
    m_xDefaultConfigStorage.clear();
920
0
    m_xUserConfigStorage.clear();
921
0
    m_xUserRootCommit.clear();
922
0
    m_bModified = false;
923
0
    m_bDisposed = true;
924
0
    aGuard.clear();
925
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
926
927
0
    try
928
0
    {
929
0
        if ( xModuleImageManager.is() )
930
0
            xModuleImageManager->dispose();
931
0
    }
932
0
    catch ( const Exception& )
933
0
    {
934
0
    }
935
0
}
936
937
void SAL_CALL ModuleUIConfigurationManager::addEventListener( const Reference< XEventListener >& xListener )
938
0
{
939
0
    {
940
0
        SolarMutexGuard g;
941
942
        /* SAFE AREA ----------------------------------------------------------------------------------------------- */
943
0
        if ( m_bDisposed )
944
0
            throw DisposedException();
945
0
    }
946
947
0
    std::unique_lock aGuard(m_mutex);
948
0
    m_aEventListeners.addInterface( aGuard, xListener );
949
0
}
950
951
void SAL_CALL ModuleUIConfigurationManager::removeEventListener( const Reference< XEventListener >& xListener )
952
0
{
953
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
954
0
    std::unique_lock aGuard(m_mutex);
955
0
    m_aEventListeners.removeInterface( aGuard, xListener );
956
0
}
957
958
// XUIConfiguration
959
void SAL_CALL ModuleUIConfigurationManager::addConfigurationListener( const Reference< css::ui::XUIConfigurationListener >& xListener )
960
0
{
961
0
    {
962
0
        SolarMutexGuard g;
963
964
        /* SAFE AREA ----------------------------------------------------------------------------------------------- */
965
0
        if ( m_bDisposed )
966
0
            throw DisposedException();
967
0
    }
968
969
0
    std::unique_lock aGuard(m_mutex);
970
0
    m_aConfigListeners.addInterface( aGuard, xListener );
971
0
}
972
973
void SAL_CALL ModuleUIConfigurationManager::removeConfigurationListener( const Reference< css::ui::XUIConfigurationListener >& xListener )
974
0
{
975
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
976
0
    std::unique_lock aGuard(m_mutex);
977
0
    m_aConfigListeners.removeInterface( aGuard, xListener );
978
0
}
979
980
// XUIConfigurationManager
981
void SAL_CALL ModuleUIConfigurationManager::reset()
982
0
{
983
0
    SolarMutexClearableGuard aGuard;
984
985
    /* SAFE AREA ----------------------------------------------------------------------------------------------- */
986
0
    if ( m_bDisposed )
987
0
        throw DisposedException();
988
989
0
    if ( isReadOnly() )
990
0
        return;
991
992
    // Remove all elements from our user-defined storage!
993
0
    try
994
0
    {
995
0
        for ( int i = 1; i < css::ui::UIElementType::COUNT; i++ )
996
0
        {
997
0
            UIElementType&        rElementType = m_aUIElements[LAYER_USERDEFINED][i];
998
999
0
            if ( rElementType.xStorage.is() )
1000
0
            {
1001
0
                bool bCommitSubStorage( false );
1002
0
                const Sequence< OUString > aUIElementStreamNames = rElementType.xStorage->getElementNames();
1003
0
                for ( OUString const & rName : aUIElementStreamNames )
1004
0
                {
1005
0
                    rElementType.xStorage->removeElement( rName );
1006
0
                    bCommitSubStorage = true;
1007
0
                }
1008
1009
0
                if ( bCommitSubStorage )
1010
0
                {
1011
0
                    Reference< XTransactedObject > xTransactedObject( rElementType.xStorage, UNO_QUERY );
1012
0
                    if ( xTransactedObject.is() )
1013
0
                        xTransactedObject->commit();
1014
0
                    m_pStorageHandler[i]->commitUserChanges();
1015
0
                }
1016
0
            }
1017
0
        }
1018
1019
        // remove settings from user defined layer and notify listener about removed settings data!
1020
0
        ConfigEventNotifyContainer aRemoveEventNotifyContainer;
1021
0
        ConfigEventNotifyContainer aReplaceEventNotifyContainer;
1022
0
        for ( sal_Int16 j = 1; j < css::ui::UIElementType::COUNT; j++ )
1023
0
        {
1024
0
            try
1025
0
            {
1026
0
                UIElementType& rUserElementType     = m_aUIElements[LAYER_USERDEFINED][j];
1027
0
                UIElementType& rDefaultElementType  = m_aUIElements[LAYER_DEFAULT][j];
1028
1029
0
                impl_resetElementTypeData( rUserElementType, rDefaultElementType, aRemoveEventNotifyContainer, aReplaceEventNotifyContainer );
1030
0
                rUserElementType.bModified = false;
1031
0
            }
1032
0
            catch (const Exception&)
1033
0
            {
1034
0
                css::uno::Any anyEx = cppu::getCaughtException();
1035
0
                throw css::lang::WrappedTargetRuntimeException(
1036
0
                        u"ModuleUIConfigurationManager::reset exception"_ustr,
1037
0
                        css::uno::Reference<css::uno::XInterface>(*this), anyEx);
1038
0
            }
1039
0
        }
1040
1041
0
        m_bModified = false;
1042
1043
        // Unlock mutex before notify our listeners
1044
0
        aGuard.clear();
1045
1046
        // Notify our listeners
1047
0
        for ( auto const & k: aRemoveEventNotifyContainer )
1048
0
            implts_notifyContainerListener( k, NotifyOp_Remove );
1049
0
        for ( auto const & k: aReplaceEventNotifyContainer )
1050
0
            implts_notifyContainerListener( k, NotifyOp_Replace );
1051
0
    }
1052
0
    catch ( const css::lang::IllegalArgumentException& )
1053
0
    {
1054
0
    }
1055
0
    catch ( const css::container::NoSuchElementException& )
1056
0
    {
1057
0
    }
1058
0
    catch ( const css::embed::InvalidStorageException& )
1059
0
    {
1060
0
    }
1061
0
    catch ( const css::embed::StorageWrappedTargetException& )
1062
0
    {
1063
0
    }
1064
0
}
1065
1066
Sequence< Sequence< PropertyValue > > SAL_CALL ModuleUIConfigurationManager::getUIElementsInfo( sal_Int16 ElementType )
1067
0
{
1068
0
    if (( ElementType < 0 ) || ( ElementType >= css::ui::UIElementType::COUNT ))
1069
0
        throw IllegalArgumentException();
1070
1071
0
    SolarMutexGuard g;
1072
0
    if ( m_bDisposed )
1073
0
        throw DisposedException();
1074
1075
0
    std::vector< Sequence< PropertyValue > > aElementInfoSeq;
1076
0
    UIElementInfoHashMap aUIElementInfoCollection;
1077
1078
0
    if ( ElementType == css::ui::UIElementType::UNKNOWN )
1079
0
    {
1080
0
        for ( sal_Int16 i = 0; i < css::ui::UIElementType::COUNT; i++ )
1081
0
            impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, i );
1082
0
    }
1083
0
    else
1084
0
        impl_fillSequenceWithElementTypeInfo( aUIElementInfoCollection, ElementType );
1085
1086
0
    aElementInfoSeq.resize( aUIElementInfoCollection.size() );
1087
1088
0
    sal_Int32 n = 0;
1089
0
    for (auto const& elem : aUIElementInfoCollection)
1090
0
    {
1091
0
        aElementInfoSeq[n++] = Sequence<PropertyValue> {
1092
0
            comphelper::makePropertyValue(u"ResourceURL"_ustr, elem.second.aResourceURL),
1093
0
            comphelper::makePropertyValue(m_aPropUIName, elem.second.aUIName)
1094
0
        };
1095
0
    }
1096
1097
0
    return comphelper::containerToSequence(aElementInfoSeq);
1098
0
}
1099
1100
Reference< XIndexContainer > SAL_CALL ModuleUIConfigurationManager::createSettings()
1101
0
{
1102
0
    SolarMutexGuard g;
1103
1104
0
    if ( m_bDisposed )
1105
0
        throw DisposedException();
1106
1107
    // Creates an empty item container which can be filled from outside
1108
0
    return Reference< XIndexContainer >( new RootItemContainer() );
1109
0
}
1110
1111
sal_Bool SAL_CALL ModuleUIConfigurationManager::hasSettings( const OUString& ResourceURL )
1112
0
{
1113
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1114
1115
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1116
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1117
0
        throw IllegalArgumentException();
1118
1119
0
    SolarMutexGuard g;
1120
1121
0
    if ( m_bDisposed )
1122
0
        throw DisposedException();
1123
1124
0
    UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1125
0
    if ( pDataSettings )
1126
0
        return true;
1127
1128
0
    return false;
1129
0
}
1130
1131
Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getSettings( const OUString& ResourceURL, sal_Bool bWriteable )
1132
0
{
1133
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1134
1135
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1136
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1137
0
        throw IllegalArgumentException();
1138
1139
0
    SolarMutexGuard g;
1140
1141
0
    if ( m_bDisposed )
1142
0
        throw DisposedException();
1143
1144
0
    UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1145
0
    if ( pDataSettings )
1146
0
    {
1147
        // Create a copy of our data if someone wants to change the data.
1148
0
        if ( bWriteable )
1149
0
            return Reference< XIndexAccess >( new RootItemContainer( pDataSettings->xSettings ) );
1150
0
        else
1151
0
            return pDataSettings->xSettings;
1152
0
    }
1153
1154
0
    throw NoSuchElementException();
1155
0
}
1156
1157
void SAL_CALL ModuleUIConfigurationManager::replaceSettings( const OUString& ResourceURL, const Reference< css::container::XIndexAccess >& aNewData )
1158
0
{
1159
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1160
1161
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1162
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1163
0
        throw IllegalArgumentException();
1164
0
    else if ( m_bReadOnly )
1165
0
        throw IllegalAccessException();
1166
0
    else
1167
0
    {
1168
0
        SolarMutexClearableGuard aGuard;
1169
1170
0
        if ( m_bDisposed )
1171
0
            throw DisposedException();
1172
1173
0
        UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1174
0
        if ( !pDataSettings )
1175
0
            throw NoSuchElementException();
1176
0
        if ( !pDataSettings->bDefaultNode )
1177
0
        {
1178
            // we have a settings entry in our user-defined layer - replace
1179
0
            Reference< XIndexAccess > xOldSettings = pDataSettings->xSettings;
1180
1181
            // Create a copy of the data if the container is not const
1182
0
            Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1183
0
            if ( xReplace.is() )
1184
0
                pDataSettings->xSettings = new ConstItemContainer( aNewData );
1185
0
            else
1186
0
                pDataSettings->xSettings = aNewData;
1187
0
            pDataSettings->bDefault  = false;
1188
0
            pDataSettings->bModified = true;
1189
0
            m_bModified = true;
1190
1191
            // Modify type container
1192
0
            UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1193
0
            rElementType.bModified = true;
1194
1195
0
            Reference< XUIConfigurationManager > xThis(this);
1196
1197
            // Create event to notify listener about replaced element settings
1198
0
            ui::ConfigurationEvent aEvent;
1199
0
            aEvent.ResourceURL = ResourceURL;
1200
0
            aEvent.Accessor <<= xThis;
1201
0
            aEvent.Source.set(xThis, UNO_QUERY);
1202
0
            aEvent.ReplacedElement <<= xOldSettings;
1203
0
            aEvent.Element <<= pDataSettings->xSettings;
1204
1205
0
            aGuard.clear();
1206
1207
0
            implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1208
0
        }
1209
0
        else
1210
0
        {
1211
            // we have no settings in our user-defined layer - insert
1212
0
            UIElementData aUIElementData;
1213
1214
0
            aUIElementData.bDefault     = false;
1215
0
            aUIElementData.bDefaultNode = false;
1216
0
            aUIElementData.bModified    = true;
1217
1218
            // Create a copy of the data if the container is not const
1219
0
            Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1220
0
            if ( xReplace.is() )
1221
0
                aUIElementData.xSettings = new ConstItemContainer( aNewData );
1222
0
            else
1223
0
                aUIElementData.xSettings = aNewData;
1224
0
            aUIElementData.aName        = RetrieveNameFromResourceURL( ResourceURL ) + m_aXMLPostfix;
1225
0
            aUIElementData.aResourceURL = ResourceURL;
1226
0
            m_bModified = true;
1227
1228
            // Modify type container
1229
0
            UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1230
0
            rElementType.bModified = true;
1231
1232
0
            UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1233
1234
            // Check our user element settings hash map as it can already contain settings that have been set to default!
1235
            // If no node can be found, we have to insert it.
1236
0
            UIElementDataHashMap::iterator pIter = rElements.find( ResourceURL );
1237
0
            if ( pIter != rElements.end() )
1238
0
                pIter->second = aUIElementData;
1239
0
            else
1240
0
                rElements.emplace( ResourceURL, aUIElementData );
1241
1242
0
            Reference< XUIConfigurationManager > xThis(this);
1243
1244
            // Create event to notify listener about replaced element settings
1245
0
            ui::ConfigurationEvent aEvent;
1246
1247
0
            aEvent.ResourceURL = ResourceURL;
1248
0
            aEvent.Accessor <<= xThis;
1249
0
            aEvent.Source.set(xThis, UNO_QUERY);
1250
0
            aEvent.ReplacedElement <<= pDataSettings->xSettings;
1251
0
            aEvent.Element <<= aUIElementData.xSettings;
1252
1253
0
            aGuard.clear();
1254
1255
0
            implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1256
0
        }
1257
0
    }
1258
0
}
1259
1260
void SAL_CALL ModuleUIConfigurationManager::removeSettings( const OUString& ResourceURL )
1261
0
{
1262
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1263
1264
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1265
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1266
0
        throw IllegalArgumentException( "The ResourceURL is not valid or "
1267
0
                                        "describes an unknown type. "
1268
0
                                        "ResourceURL: " + ResourceURL, nullptr, 0 );
1269
0
    else if ( m_bReadOnly )
1270
0
        throw IllegalAccessException( "The configuration manager is read-only. "
1271
0
                                      "ResourceURL: " + ResourceURL, nullptr );
1272
0
    else
1273
0
    {
1274
0
        SolarMutexClearableGuard aGuard;
1275
1276
0
        if ( m_bDisposed )
1277
0
            throw DisposedException( "The configuration manager has been disposed, "
1278
0
                                     "and can't uphold its method specification anymore. "
1279
0
                                     "ResourceURL: " + ResourceURL, nullptr );
1280
1281
0
        UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1282
0
        if ( !pDataSettings )
1283
0
            throw NoSuchElementException( "The settings data cannot be found. "
1284
0
                                          "ResourceURL: " + ResourceURL, nullptr );
1285
        // If element settings are default, we don't need to change anything!
1286
0
        if ( pDataSettings->bDefault )
1287
0
            return;
1288
0
        else
1289
0
        {
1290
0
            Reference< XIndexAccess > xRemovedSettings = pDataSettings->xSettings;
1291
0
            pDataSettings->bDefault = true;
1292
1293
            // check if this is a default layer node
1294
0
            if ( !pDataSettings->bDefaultNode )
1295
0
                pDataSettings->bModified = true; // we have to remove this node from the user layer!
1296
0
            pDataSettings->xSettings.clear();
1297
0
            m_bModified = true; // user layer must be written
1298
1299
            // Modify type container
1300
0
            UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1301
0
            rElementType.bModified = true;
1302
1303
0
            Reference< XUIConfigurationManager > xThis(this);
1304
0
            Reference< XInterface > xIfac( xThis, UNO_QUERY );
1305
1306
            // Check if we have settings in the default layer which replaces the user-defined one!
1307
0
            UIElementData* pDefaultDataSettings = impl_findUIElementData( ResourceURL, nElementType );
1308
0
            if ( pDefaultDataSettings )
1309
0
            {
1310
                // Create event to notify listener about replaced element settings
1311
0
                ui::ConfigurationEvent aEvent;
1312
1313
0
                aEvent.ResourceURL = ResourceURL;
1314
0
                aEvent.Accessor <<= xThis;
1315
0
                aEvent.Source = std::move(xIfac);
1316
0
                aEvent.Element <<= xRemovedSettings;
1317
0
                aEvent.ReplacedElement <<= pDefaultDataSettings->xSettings;
1318
1319
0
                aGuard.clear();
1320
1321
0
                implts_notifyContainerListener( aEvent, NotifyOp_Replace );
1322
0
            }
1323
0
            else
1324
0
            {
1325
                // Create event to notify listener about removed element settings
1326
0
                ui::ConfigurationEvent aEvent;
1327
1328
0
                aEvent.ResourceURL = ResourceURL;
1329
0
                aEvent.Accessor <<= xThis;
1330
0
                aEvent.Source = std::move(xIfac);
1331
0
                aEvent.Element <<= xRemovedSettings;
1332
1333
0
                aGuard.clear();
1334
1335
0
                implts_notifyContainerListener( aEvent, NotifyOp_Remove );
1336
0
            }
1337
0
        }
1338
0
    }
1339
0
}
1340
1341
void SAL_CALL ModuleUIConfigurationManager::insertSettings( const OUString& NewResourceURL, const Reference< XIndexAccess >& aNewData )
1342
0
{
1343
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( NewResourceURL );
1344
1345
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1346
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1347
0
        throw IllegalArgumentException();
1348
0
    else if ( m_bReadOnly )
1349
0
        throw IllegalAccessException();
1350
0
    else
1351
0
    {
1352
0
        SolarMutexClearableGuard aGuard;
1353
1354
0
        if ( m_bDisposed )
1355
0
            throw DisposedException();
1356
1357
0
        UIElementData* pDataSettings = impl_findUIElementData( NewResourceURL, nElementType );
1358
0
        if ( !(!pDataSettings) )
1359
0
            throw ElementExistException();
1360
0
        UIElementData aUIElementData;
1361
1362
0
        aUIElementData.bDefault     = false;
1363
0
        aUIElementData.bDefaultNode = false;
1364
0
        aUIElementData.bModified    = true;
1365
1366
        // Create a copy of the data if the container is not const
1367
0
        Reference< XIndexReplace > xReplace( aNewData, UNO_QUERY );
1368
0
        if ( xReplace.is() )
1369
0
            aUIElementData.xSettings = new ConstItemContainer( aNewData );
1370
0
        else
1371
0
            aUIElementData.xSettings = aNewData;
1372
0
        aUIElementData.aName        = RetrieveNameFromResourceURL( NewResourceURL ) + m_aXMLPostfix;
1373
0
        aUIElementData.aResourceURL = NewResourceURL;
1374
0
        m_bModified = true;
1375
1376
0
        UIElementType& rElementType = m_aUIElements[LAYER_USERDEFINED][nElementType];
1377
0
        rElementType.bModified = true;
1378
1379
0
        UIElementDataHashMap& rElements = rElementType.aElementsHashMap;
1380
0
        rElements.emplace( NewResourceURL, aUIElementData );
1381
1382
0
        Reference< XIndexAccess > xInsertSettings( aUIElementData.xSettings );
1383
0
        Reference< XUIConfigurationManager > xThis(this);
1384
1385
        // Create event to notify listener about removed element settings
1386
0
        ui::ConfigurationEvent aEvent;
1387
1388
0
        aEvent.ResourceURL = NewResourceURL;
1389
0
        aEvent.Accessor <<= xThis;
1390
0
        aEvent.Source = xThis;
1391
0
        aEvent.Element <<= xInsertSettings;
1392
1393
0
        aGuard.clear();
1394
1395
0
        implts_notifyContainerListener( aEvent, NotifyOp_Insert );
1396
0
    }
1397
0
}
1398
1399
Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getImageManager()
1400
0
{
1401
0
    SolarMutexGuard g;
1402
1403
0
    if ( m_bDisposed )
1404
0
        throw DisposedException();
1405
1406
0
    if ( !m_xModuleImageManager.is() )
1407
0
    {
1408
0
        m_xModuleImageManager = new ImageManager( m_xContext, /*bForModule*/true );
1409
1410
0
        uno::Sequence<uno::Any> aPropSeq(comphelper::InitAnyPropertySequence(
1411
0
        {
1412
0
            {"UserConfigStorage", uno::Any(m_xUserConfigStorage)},
1413
0
            {"ModuleIdentifier", uno::Any(m_aModuleIdentifier)},
1414
0
            {"UserRootCommit", uno::Any(m_xUserRootCommit)},
1415
0
        }));
1416
0
        m_xModuleImageManager->initialize( aPropSeq );
1417
0
    }
1418
1419
0
    return Reference< XInterface >( static_cast<cppu::OWeakObject*>(m_xModuleImageManager.get()), UNO_QUERY );
1420
0
}
1421
1422
Reference< ui::XAcceleratorConfiguration > SAL_CALL ModuleUIConfigurationManager::createShortCutManager()
1423
0
{
1424
0
    return ui::ModuleAcceleratorConfiguration::createWithModuleIdentifier(m_xContext, m_aModuleIdentifier);
1425
0
}
1426
1427
Reference< ui::XAcceleratorConfiguration > SAL_CALL ModuleUIConfigurationManager::getShortCutManager()
1428
0
{
1429
0
    SolarMutexGuard g;
1430
1431
0
    if ( m_bDisposed )
1432
0
        throw DisposedException();
1433
1434
0
    if ( !m_xModuleAcceleratorManager.is() ) try
1435
0
    {
1436
0
        m_xModuleAcceleratorManager = ui::ModuleAcceleratorConfiguration::
1437
0
            createWithModuleIdentifier(m_xContext, m_aModuleIdentifier);
1438
0
    }
1439
0
    catch ( const css::uno::DeploymentException& )
1440
0
    {
1441
0
        SAL_WARN("fwk.uiconfiguration", "ModuleAcceleratorConfiguration"
1442
0
                " not available. This should happen only on mobile platforms.");
1443
0
    }
1444
1445
0
    return m_xModuleAcceleratorManager;
1446
0
}
1447
1448
Reference< XInterface > SAL_CALL ModuleUIConfigurationManager::getEventsManager()
1449
0
{
1450
0
    return Reference< XInterface >();
1451
0
}
1452
1453
// XModuleUIConfigurationManager
1454
sal_Bool SAL_CALL ModuleUIConfigurationManager::isDefaultSettings( const OUString& ResourceURL )
1455
0
{
1456
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1457
1458
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1459
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1460
0
        throw IllegalArgumentException();
1461
1462
0
    SolarMutexGuard g;
1463
1464
0
    if ( m_bDisposed )
1465
0
        throw DisposedException();
1466
1467
0
    UIElementData* pDataSettings = impl_findUIElementData( ResourceURL, nElementType, false );
1468
0
    if ( pDataSettings && pDataSettings->bDefaultNode )
1469
0
        return true;
1470
1471
0
    return false;
1472
0
}
1473
1474
Reference< XIndexAccess > SAL_CALL ModuleUIConfigurationManager::getDefaultSettings( const OUString& ResourceURL )
1475
0
{
1476
0
    sal_Int16 nElementType = RetrieveTypeFromResourceURL( ResourceURL );
1477
1478
0
    if (( nElementType == css::ui::UIElementType::UNKNOWN ) ||
1479
0
        ( nElementType >= css::ui::UIElementType::COUNT   ))
1480
0
        throw IllegalArgumentException();
1481
1482
0
    SolarMutexGuard g;
1483
1484
0
    if ( m_bDisposed )
1485
0
        throw DisposedException();
1486
1487
    // preload list of element types on demand
1488
0
    impl_preloadUIElementTypeList( LAYER_DEFAULT, nElementType );
1489
1490
    // Look into our default vector/unordered_map combination
1491
0
    UIElementDataHashMap& rDefaultHashMap = m_aUIElements[LAYER_DEFAULT][nElementType].aElementsHashMap;
1492
0
    UIElementDataHashMap::iterator pIter = rDefaultHashMap.find( ResourceURL );
1493
0
    if ( pIter != rDefaultHashMap.end() )
1494
0
    {
1495
0
        if ( !pIter->second.xSettings.is() )
1496
0
            impl_requestUIElementData( nElementType, LAYER_DEFAULT, pIter->second );
1497
0
        return pIter->second.xSettings;
1498
0
    }
1499
1500
    // Nothing has been found!
1501
0
    throw NoSuchElementException();
1502
0
}
1503
1504
// XUIConfigurationPersistence
1505
void SAL_CALL ModuleUIConfigurationManager::reload()
1506
0
{
1507
0
    SolarMutexClearableGuard aGuard;
1508
1509
0
    if ( m_bDisposed )
1510
0
        throw DisposedException();
1511
1512
0
    if ( !m_xUserConfigStorage.is() || !m_bModified || m_bReadOnly )
1513
0
        return;
1514
1515
    // Try to access our module sub folder
1516
0
    ConfigEventNotifyContainer aRemoveNotifyContainer;
1517
0
    ConfigEventNotifyContainer aReplaceNotifyContainer;
1518
0
    for ( sal_Int16 i = 1; i < css::ui::UIElementType::COUNT; i++ )
1519
0
    {
1520
0
        try
1521
0
        {
1522
0
            UIElementType& rUserElementType    = m_aUIElements[LAYER_USERDEFINED][i];
1523
1524
0
            if ( rUserElementType.bModified )
1525
0
            {
1526
0
                UIElementType& rDefaultElementType = m_aUIElements[LAYER_DEFAULT][i];
1527
0
                impl_reloadElementTypeData( rUserElementType, rDefaultElementType, aRemoveNotifyContainer, aReplaceNotifyContainer );
1528
0
            }
1529
0
        }
1530
0
        catch ( const Exception& )
1531
0
        {
1532
0
            throw IOException();
1533
0
        }
1534
0
    }
1535
1536
0
    m_bModified = false;
1537
1538
    // Unlock mutex before notify our listeners
1539
0
    aGuard.clear();
1540
1541
    // Notify our listeners
1542
0
    for (const ui::ConfigurationEvent & j : aRemoveNotifyContainer)
1543
0
        implts_notifyContainerListener( j, NotifyOp_Remove );
1544
0
    for (const ui::ConfigurationEvent & k : aReplaceNotifyContainer)
1545
0
        implts_notifyContainerListener( k, NotifyOp_Replace );
1546
0
}
1547
1548
void SAL_CALL ModuleUIConfigurationManager::store()
1549
0
{
1550
0
    SolarMutexGuard g;
1551
1552
0
    if ( m_bDisposed )
1553
0
        throw DisposedException();
1554
1555
0
    if ( !m_xUserConfigStorage.is() || !m_bModified || m_bReadOnly )
1556
0
        return;
1557
1558
    // Try to access our module sub folder
1559
0
    for ( int i = 1; i < css::ui::UIElementType::COUNT; i++ )
1560
0
    {
1561
0
        try
1562
0
        {
1563
0
            UIElementType&        rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1564
1565
0
            if ( rElementType.bModified && rElementType.xStorage.is() )
1566
0
            {
1567
0
                impl_storeElementTypeData( rElementType.xStorage, rElementType );
1568
0
                m_pStorageHandler[i]->commitUserChanges();
1569
0
            }
1570
0
        }
1571
0
        catch ( const Exception& )
1572
0
        {
1573
0
            throw IOException();
1574
0
        }
1575
0
    }
1576
1577
0
    m_bModified = false;
1578
0
}
1579
1580
void SAL_CALL ModuleUIConfigurationManager::storeToStorage( const Reference< XStorage >& Storage )
1581
0
{
1582
0
    SolarMutexGuard g;
1583
1584
0
    if ( m_bDisposed )
1585
0
        throw DisposedException();
1586
1587
0
    if ( !m_xUserConfigStorage.is() || !m_bModified || m_bReadOnly )
1588
0
        return;
1589
1590
    // Try to access our module sub folder
1591
0
    for ( int i = 1; i < css::ui::UIElementType::COUNT; i++ )
1592
0
    {
1593
0
        try
1594
0
        {
1595
0
            Reference< XStorage > xElementTypeStorage( Storage->openStorageElement(
1596
0
                                                          OUString(UIELEMENTTYPENAMES[i]), ElementModes::READWRITE ));
1597
0
            UIElementType&        rElementType = m_aUIElements[LAYER_USERDEFINED][i];
1598
1599
0
            if ( rElementType.bModified && xElementTypeStorage.is() )
1600
0
                impl_storeElementTypeData( xElementTypeStorage, rElementType, false ); // store data to storage, but don't reset modify flag!
1601
0
        }
1602
0
        catch ( const Exception& )
1603
0
        {
1604
0
            throw IOException();
1605
0
        }
1606
0
    }
1607
1608
0
    Reference< XTransactedObject > xTransactedObject( Storage, UNO_QUERY );
1609
0
    if ( xTransactedObject.is() )
1610
0
        xTransactedObject->commit();
1611
0
}
1612
1613
sal_Bool SAL_CALL ModuleUIConfigurationManager::isModified()
1614
0
{
1615
0
    SolarMutexGuard g;
1616
1617
0
    return m_bModified;
1618
0
}
1619
1620
sal_Bool SAL_CALL ModuleUIConfigurationManager::isReadOnly()
1621
0
{
1622
0
    SolarMutexGuard g;
1623
1624
0
    return m_bReadOnly;
1625
0
}
1626
1627
void ModuleUIConfigurationManager::implts_notifyContainerListener( const ui::ConfigurationEvent& aEvent, NotifyOp eOp )
1628
0
{
1629
0
    std::unique_lock aGuard(m_mutex);
1630
0
    using ListenerMethodType = void (SAL_CALL css::ui::XUIConfigurationListener::*)(const ui::ConfigurationEvent&);
1631
0
    ListenerMethodType aListenerMethod {};
1632
0
    switch ( eOp )
1633
0
    {
1634
0
        case NotifyOp_Replace:
1635
0
            aListenerMethod = &css::ui::XUIConfigurationListener::elementReplaced;
1636
0
            break;
1637
0
        case NotifyOp_Insert:
1638
0
            aListenerMethod = &css::ui::XUIConfigurationListener::elementInserted;
1639
0
            break;
1640
0
        case NotifyOp_Remove:
1641
0
            aListenerMethod = &css::ui::XUIConfigurationListener::elementRemoved;
1642
0
            break;
1643
0
    }
1644
0
    m_aConfigListeners.notifyEach(aGuard, aListenerMethod, aEvent);
1645
0
}
1646
1647
}
1648
1649
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1650
com_sun_star_comp_framework_ModuleUIConfigurationManager_get_implementation(
1651
    css::uno::XComponentContext *context,
1652
    css::uno::Sequence<css::uno::Any> const &arguments)
1653
0
{
1654
0
    return cppu::acquire(new ModuleUIConfigurationManager(context, arguments));
1655
0
}
1656
1657
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */