Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/unotools/source/config/cmdoptions.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 <sal/config.h>
21
22
#include <sal/log.hxx>
23
#include <unotools/cmdoptions.hxx>
24
#include <unotools/configitem.hxx>
25
#include <tools/debug.hxx>
26
#include <com/sun/star/uno/Any.hxx>
27
#include <com/sun/star/uno/Sequence.hxx>
28
#include <com/sun/star/frame/XFrame.hpp>
29
#include <cppuhelper/weakref.hxx>
30
31
#include "itemholder1.hxx"
32
33
#include <algorithm>
34
#include <unordered_map>
35
36
using namespace ::utl;
37
using namespace ::osl;
38
using namespace ::com::sun::star::uno;
39
using namespace ::com::sun::star::beans;
40
41
constexpr OUStringLiteral ROOTNODE_CMDOPTIONS        = u"Office.Commands/Execute";
42
0
#define PATHDELIMITER                                   "/"
43
44
0
#define SETNODE_DISABLED                                "Disabled"
45
46
0
#define PROPERTYNAME_CMD                                "Command"
47
48
namespace {
49
50
/*-****************************************************************************************************************
51
    @descr  support simple command option structures and operations on it
52
****************************************************************************************************************-*/
53
class SvtCmdOptions
54
{
55
    public:
56
57
        // the only way to free memory!
58
        void Clear()
59
0
        {
60
0
            m_aCommandHashMap.clear();
61
0
        }
62
63
        bool HasEntries() const
64
0
        {
65
0
            return ( !m_aCommandHashMap.empty() );
66
0
        }
67
68
        bool Lookup( const OUString& aCmd ) const
69
0
        {
70
0
            CommandHashMap::const_iterator pEntry = m_aCommandHashMap.find( aCmd );
71
0
            return ( pEntry != m_aCommandHashMap.end() );
72
0
        }
73
74
        void AddCommand( const OUString& aCmd )
75
0
        {
76
0
            m_aCommandHashMap.emplace( aCmd, 0 );
77
0
        }
78
79
    private:
80
        typedef std::unordered_map<OUString, sal_Int32>
81
            CommandHashMap;
82
83
        CommandHashMap m_aCommandHashMap;
84
};
85
86
std::mutex& GetOwnStaticMutex()
87
17.5k
{
88
17.5k
    static std::mutex theCommandOptionsMutex;
89
17.5k
    return theCommandOptionsMutex;
90
17.5k
}
91
92
}
93
94
typedef ::std::vector< css::uno::WeakReference< css::frame::XFrame > > SvtFrameVector;
95
96
class SvtCommandOptions_Impl : public ConfigItem
97
{
98
    public:
99
100
         SvtCommandOptions_Impl();
101
        virtual ~SvtCommandOptions_Impl() override;
102
103
        /*-****************************************************************************************************
104
            @short      called for notify of configmanager
105
            @descr      This method is called from the ConfigManager before the application ends or from the
106
                         PropertyChangeListener if the sub tree broadcasts changes. You must update your
107
                        internal values.
108
109
            @seealso    baseclass ConfigItem
110
111
            @param      "lPropertyNames" is the list of properties which should be updated.
112
        *//*-*****************************************************************************************************/
113
114
        virtual void Notify( const Sequence< OUString >& lPropertyNames ) override;
115
116
        /*-****************************************************************************************************
117
            @short      base implementation of public interface for "SvtDynamicMenuOptions"!
118
            @descr      These class is used as static member of "SvtDynamicMenuOptions" ...
119
                        => The code exist only for one time and isn't duplicated for every instance!
120
        *//*-*****************************************************************************************************/
121
122
        bool                HasEntriesDisabled() const;
123
        bool                LookupDisabled( const OUString& ) const;
124
        void EstablishFrameCallback(const css::uno::Reference< css::frame::XFrame >& xFrame);
125
126
    private:
127
128
        virtual void ImplCommit() override;
129
130
        /*-****************************************************************************************************
131
            @short      return list of key names of our configuration management which represent our module tree
132
            @descr      This method returns the current list of key names! We need it to get needed values from our
133
                        configuration management and support dynamical menu item lists!
134
            @param      "nDisabledCount", returns count of menu entries for "new"
135
            @return     A list of configuration key names is returned.
136
        *//*-*****************************************************************************************************/
137
138
        Sequence< OUString > impl_GetPropertyNames();
139
140
    private:
141
        SvtCmdOptions  m_aDisabledCommands;
142
        SvtFrameVector m_lFrames;
143
};
144
145
//  constructor
146
147
SvtCommandOptions_Impl::SvtCommandOptions_Impl()
148
    // Init baseclasses first
149
2
    :   ConfigItem( ROOTNODE_CMDOPTIONS )
150
    // Init member then...
151
2
{
152
    // Get names and values of all accessible menu entries and fill internal structures.
153
    // See impl_GetPropertyNames() for further information.
154
2
    Sequence< OUString >    lNames              = impl_GetPropertyNames ();
155
2
    Sequence< Any >         lValues             = GetProperties         ( lNames         );
156
157
    // Safe impossible cases.
158
    // We need values from ALL configuration keys.
159
    // Follow assignment use order of values in relation to our list of key names!
160
2
    DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtCommandOptions_Impl::SvtCommandOptions_Impl()\nI miss some values of configuration keys!\n" );
161
162
    // Copy values from list in right order to our internal member.
163
    // Attention: List for names and values have an internal construction pattern!
164
2
    sal_Int32   nItem     = 0;
165
2
    OUString    sCmd;
166
167
    // Get names/values for disabled commands.
168
2
    for( nItem=0; nItem < lNames.getLength(); ++nItem )
169
0
    {
170
        // Currently only one value
171
0
        lValues[nItem] >>= sCmd;
172
0
        m_aDisabledCommands.AddCommand( sCmd );
173
0
    }
174
175
/*TODO: Not used in the moment! see Notify() ...
176
    // Enable notification mechanism of our baseclass.
177
    // We need it to get information about changes outside these class on our used configuration keys! */
178
2
    Sequence<OUString> aNotifySeq { u"Disabled"_ustr };
179
2
    EnableNotification( aNotifySeq, true );
180
2
}
181
182
//  destructor
183
184
SvtCommandOptions_Impl::~SvtCommandOptions_Impl()
185
0
{
186
0
    assert(!IsModified()); // should have been committed
187
0
}
188
189
//  public method
190
191
void SvtCommandOptions_Impl::Notify( const Sequence< OUString >& )
192
0
{
193
0
    std::unique_lock aGuard( GetOwnStaticMutex() );
194
195
0
    Sequence< OUString >    lNames   = impl_GetPropertyNames ();
196
0
    Sequence< Any >         lValues  = GetProperties         ( lNames         );
197
198
    // Safe impossible cases.
199
    // We need values from ALL configuration keys.
200
    // Follow assignment use order of values in relation to our list of key names!
201
0
    DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtCommandOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
202
203
    // Copy values from list in right order to our internal member.
204
    // Attention: List for names and values have an internal construction pattern!
205
0
    sal_Int32   nItem     = 0;
206
0
    OUString    sCmd;
207
208
0
    m_aDisabledCommands.Clear();
209
210
    // Get names/values for disabled commands.
211
0
    for( nItem=0; nItem < lNames.getLength(); ++nItem )
212
0
    {
213
        // Currently only one value
214
0
        lValues[nItem] >>= sCmd;
215
0
        m_aDisabledCommands.AddCommand( sCmd );
216
0
    }
217
218
    // don't forget to update all existing frames and her might cached dispatch objects!
219
    // But look for already killed frames. We hold weak references instead of hard ones ...
220
0
    for (SvtFrameVector::iterator pIt  = m_lFrames.begin(); pIt != m_lFrames.end(); )
221
0
    {
222
0
        css::uno::Reference< css::frame::XFrame > xFrame(pIt->get(), css::uno::UNO_QUERY);
223
0
        if (xFrame.is())
224
0
        {
225
0
            aGuard.unlock(); // because we can call back into ourself
226
0
            xFrame->contextChanged();
227
0
            aGuard.lock();
228
0
            ++pIt;
229
0
        }
230
0
        else
231
0
            pIt = m_lFrames.erase(pIt);
232
0
    }
233
0
}
234
235
//  public method
236
237
void SvtCommandOptions_Impl::ImplCommit()
238
0
{
239
0
    SAL_WARN("unotools.config","SvtCommandOptions_Impl::ImplCommit(): Not implemented yet!");
240
0
}
241
242
//  public method
243
244
bool SvtCommandOptions_Impl::HasEntriesDisabled() const
245
0
{
246
0
    return m_aDisabledCommands.HasEntries();
247
0
}
248
249
//  public method
250
251
bool SvtCommandOptions_Impl::LookupDisabled( const OUString& aCommand ) const
252
0
{
253
0
    return m_aDisabledCommands.Lookup( aCommand );
254
0
}
255
256
//  public method
257
258
void SvtCommandOptions_Impl::EstablishFrameCallback(const css::uno::Reference< css::frame::XFrame >& xFrame)
259
7.14k
{
260
    // check if frame already exists inside list
261
    // ignore double registrations
262
    // every frame must be notified one times only!
263
7.14k
    css::uno::WeakReference< css::frame::XFrame > xWeak(xFrame);
264
7.14k
    SvtFrameVector::const_iterator pIt = ::std::find(m_lFrames.begin(), m_lFrames.end(), xWeak);
265
7.14k
    if (pIt == m_lFrames.end())
266
7.14k
        m_lFrames.push_back(xWeak);
267
7.14k
}
268
269
//  private method
270
271
Sequence< OUString > SvtCommandOptions_Impl::impl_GetPropertyNames()
272
2
{
273
    // First get ALL names of current existing list items in configuration!
274
2
    Sequence< OUString > lDisabledItems      = GetNodeNames( u"" SETNODE_DISABLED ""_ustr, utl::ConfigNameFormat::LocalPath );
275
276
    // Expand all keys
277
2
    for (OUString& rItem : asNonConstRange(lDisabledItems))
278
0
        rItem =  SETNODE_DISABLED PATHDELIMITER + rItem + PATHDELIMITER PROPERTYNAME_CMD;
279
280
    // Return result.
281
2
    return lDisabledItems;
282
2
}
283
284
namespace {
285
286
std::weak_ptr<SvtCommandOptions_Impl> g_pCommandOptions;
287
288
}
289
290
SvtCommandOptions::SvtCommandOptions()
291
7.14k
{
292
    // Global access, must be guarded (multithreading!).
293
7.14k
    std::unique_lock aGuard( GetOwnStaticMutex() );
294
295
7.14k
    m_pImpl = g_pCommandOptions.lock();
296
7.14k
    if( !m_pImpl )
297
2
    {
298
2
        m_pImpl = std::make_shared<SvtCommandOptions_Impl>();
299
2
        g_pCommandOptions = m_pImpl;
300
2
        aGuard.unlock(); // because holdConfigItem will call this constructor
301
2
        ItemHolder1::holdConfigItem(EItem::CmdOptions);
302
2
    }
303
7.14k
}
304
305
SvtCommandOptions::~SvtCommandOptions()
306
3.28k
{
307
    // Global access, must be guarded (multithreading!)
308
3.28k
    std::unique_lock aGuard( GetOwnStaticMutex() );
309
310
3.28k
    m_pImpl.reset();
311
3.28k
}
312
313
//  public method
314
315
bool SvtCommandOptions::HasEntriesDisabled() const
316
0
{
317
0
    std::unique_lock aGuard( GetOwnStaticMutex() );
318
0
    return m_pImpl->HasEntriesDisabled();
319
0
}
320
321
//  public method
322
323
bool SvtCommandOptions::LookupDisabled( const OUString& aCommandURL ) const
324
0
{
325
0
    std::unique_lock aGuard( GetOwnStaticMutex() );
326
0
    return m_pImpl->LookupDisabled( aCommandURL );
327
0
}
328
329
//  public method
330
331
void SvtCommandOptions::EstablishFrameCallback(const css::uno::Reference< css::frame::XFrame >& xFrame)
332
7.14k
{
333
7.14k
    std::unique_lock aGuard( GetOwnStaticMutex() );
334
7.14k
    m_pImpl->EstablishFrameCallback(xFrame);
335
7.14k
}
336
337
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */