/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: */ |