Line data Source code
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 <unotools/cmdoptions.hxx>
21 : #include <unotools/configmgr.hxx>
22 : #include <unotools/configitem.hxx>
23 : #include <tools/debug.hxx>
24 : #include <com/sun/star/uno/Any.hxx>
25 : #include <com/sun/star/uno/Sequence.hxx>
26 : #include <cppuhelper/weakref.hxx>
27 : #include <rtl/ustrbuf.hxx>
28 : #include <rtl/instance.hxx>
29 :
30 : #include "itemholder1.hxx"
31 :
32 : #include <algorithm>
33 : #include <boost/unordered_map.hpp>
34 :
35 : using namespace ::std;
36 : using namespace ::utl;
37 : using namespace ::osl;
38 : using namespace ::com::sun::star::uno;
39 : using namespace ::com::sun::star::beans;
40 :
41 : #define ROOTNODE_CMDOPTIONS OUString("Office.Commands/Execute")
42 : #define PATHDELIMITER OUString("/")
43 :
44 : #define SETNODE_DISABLED OUString("Disabled")
45 :
46 : #define PROPERTYNAME_CMD OUString("Command")
47 :
48 : /*-****************************************************************************************************************
49 : @descr support simple command option structures and operations on it
50 : ****************************************************************************************************************-*/
51 508 : class SvtCmdOptions
52 : {
53 : public:
54 :
55 : // the only way to free memory!
56 0 : void Clear()
57 : {
58 0 : m_aCommandHashMap.clear();
59 0 : }
60 :
61 10302 : bool HasEntries() const
62 : {
63 10302 : return ( m_aCommandHashMap.size() > 0 );
64 : }
65 :
66 317984 : bool Lookup( const OUString& aCmd ) const
67 : {
68 317984 : CommandHashMap::const_iterator pEntry = m_aCommandHashMap.find( aCmd );
69 317984 : return ( pEntry != m_aCommandHashMap.end() );
70 : }
71 :
72 0 : void AddCommand( const OUString& aCmd )
73 : {
74 0 : m_aCommandHashMap.insert( CommandHashMap::value_type( aCmd, 0 ) );
75 0 : }
76 :
77 : private:
78 : typedef boost::unordered_map<OUString, sal_Int32, OUStringHash>
79 : CommandHashMap;
80 :
81 : CommandHashMap m_aCommandHashMap;
82 : };
83 :
84 : typedef ::std::vector< ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XFrame > > SvtFrameVector;
85 :
86 : class SvtCommandOptions_Impl : public ConfigItem
87 : {
88 : public:
89 :
90 : SvtCommandOptions_Impl();
91 : virtual ~SvtCommandOptions_Impl();
92 :
93 : /*-****************************************************************************************************
94 : @short called for notify of configmanager
95 : @descr These method is called from the ConfigManager before application ends or from the
96 : PropertyChangeListener if the sub tree broadcasts changes. You must update your
97 : internal values.
98 :
99 : @seealso baseclass ConfigItem
100 :
101 : @param "lPropertyNames" is the list of properties which should be updated.
102 : *//*-*****************************************************************************************************/
103 :
104 : virtual void Notify( const Sequence< OUString >& lPropertyNames ) SAL_OVERRIDE;
105 :
106 : /*-****************************************************************************************************
107 : @short write changes to configuration
108 : @descr These method writes the changed values into the sub tree
109 : and should always called in our destructor to guarantee consistency of config data.
110 :
111 : @seealso baseclass ConfigItem
112 : *//*-*****************************************************************************************************/
113 :
114 : virtual void Commit() SAL_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 HasEntries ( SvtCommandOptions::CmdOption eOption ) const;
123 : bool Lookup ( SvtCommandOptions::CmdOption eCmdOption, const OUString& ) const;
124 : void EstablisFrameCallback(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame);
125 :
126 : private:
127 :
128 : /*-****************************************************************************************************
129 : @short return list of key names of our configuration management which represent oue module tree
130 : @descr These methods return the current list of key names! We need it to get needed values from our
131 : configuration management and support dynamical menu item lists!
132 : @param "nDisabledCount" , returns count of menu entries for "new"
133 : @return A list of configuration key names is returned.
134 : *//*-*****************************************************************************************************/
135 :
136 : Sequence< OUString > impl_GetPropertyNames();
137 :
138 : private:
139 : SvtCmdOptions m_aDisabledCommands;
140 : SvtFrameVector m_lFrames;
141 : };
142 :
143 : // constructor
144 :
145 309 : SvtCommandOptions_Impl::SvtCommandOptions_Impl()
146 : // Init baseclasses first
147 309 : : ConfigItem( ROOTNODE_CMDOPTIONS )
148 : // Init member then...
149 : {
150 : // Get names and values of all accessible menu entries and fill internal structures.
151 : // See impl_GetPropertyNames() for further information.
152 309 : Sequence< OUString > lNames = impl_GetPropertyNames ();
153 618 : Sequence< Any > lValues = GetProperties ( lNames );
154 :
155 : // Safe impossible cases.
156 : // We need values from ALL configuration keys.
157 : // Follow assignment use order of values in relation to our list of key names!
158 : DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtCommandOptions_Impl::SvtCommandOptions_Impl()\nI miss some values of configuration keys!\n" );
159 :
160 : // Copy values from list in right order to our internal member.
161 : // Attention: List for names and values have an internal construction pattern!
162 309 : sal_Int32 nItem = 0;
163 618 : OUString sCmd;
164 :
165 : // Get names/values for disabled commands.
166 309 : for( nItem=0; nItem < lNames.getLength(); ++nItem )
167 : {
168 : // Currently only one value
169 0 : lValues[nItem] >>= sCmd;
170 0 : m_aDisabledCommands.AddCommand( sCmd );
171 : }
172 :
173 : /*TODO: Not used in the moment! see Notify() ...
174 : // Enable notification mechanism of our baseclass.
175 : // We need it to get information about changes outside these class on our used configuration keys! */
176 618 : Sequence< OUString > aNotifySeq( 1 );
177 309 : aNotifySeq[0] = "Disabled";
178 618 : EnableNotification( aNotifySeq, true );
179 309 : }
180 :
181 : // destructor
182 :
183 597 : SvtCommandOptions_Impl::~SvtCommandOptions_Impl()
184 : {
185 : // We must save our current values .. if user forget it!
186 199 : if( IsModified() )
187 : {
188 0 : Commit();
189 : }
190 398 : }
191 :
192 : // public method
193 :
194 0 : void SvtCommandOptions_Impl::Notify( const Sequence< OUString >& )
195 : {
196 0 : MutexGuard aGuard( SvtCommandOptions::GetOwnStaticMutex() );
197 :
198 0 : Sequence< OUString > lNames = impl_GetPropertyNames ();
199 0 : Sequence< Any > lValues = GetProperties ( lNames );
200 :
201 : // Safe impossible cases.
202 : // We need values from ALL configuration keys.
203 : // Follow assignment use order of values in relation to our list of key names!
204 : DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtCommandOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
205 :
206 : // Copy values from list in right order to our internal member.
207 : // Attention: List for names and values have an internal construction pattern!
208 0 : sal_Int32 nItem = 0;
209 0 : OUString sCmd;
210 :
211 0 : m_aDisabledCommands.Clear();
212 :
213 : // Get names/values for disabled commands.
214 0 : for( nItem=0; nItem < lNames.getLength(); ++nItem )
215 : {
216 : // Currently only one value
217 0 : lValues[nItem] >>= sCmd;
218 0 : m_aDisabledCommands.AddCommand( sCmd );
219 : }
220 :
221 : // dont forget to update all existing frames and her might cached dispatch objects!
222 : // But look for already killed frames. We hold weak references instead of hard ones ...
223 0 : for (SvtFrameVector::const_iterator pIt = m_lFrames.begin();
224 0 : pIt != m_lFrames.end();
225 : ++pIt )
226 : {
227 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame(pIt->get(), ::com::sun::star::uno::UNO_QUERY);
228 0 : if (xFrame.is())
229 0 : xFrame->contextChanged();
230 0 : }
231 0 : }
232 :
233 : // public method
234 :
235 0 : void SvtCommandOptions_Impl::Commit()
236 : {
237 : OSL_FAIL( "SvtCommandOptions_Impl::Commit()\nNot implemented yet!\n" );
238 0 : }
239 :
240 : // public method
241 :
242 10302 : bool SvtCommandOptions_Impl::HasEntries( SvtCommandOptions::CmdOption eOption ) const
243 : {
244 10302 : if ( eOption == SvtCommandOptions::CMDOPTION_DISABLED )
245 10302 : return m_aDisabledCommands.HasEntries();
246 : else
247 0 : return false;
248 : }
249 :
250 : // public method
251 :
252 317984 : bool SvtCommandOptions_Impl::Lookup( SvtCommandOptions::CmdOption eCmdOption, const OUString& aCommand ) const
253 : {
254 317984 : switch( eCmdOption )
255 : {
256 : case SvtCommandOptions::CMDOPTION_DISABLED:
257 : {
258 317984 : return m_aDisabledCommands.Lookup( aCommand );
259 : }
260 : default:
261 : DBG_ASSERT( false, "SvtCommandOptions_Impl::Lookup()\nUnknown option type given!\n" );
262 : }
263 :
264 0 : return false;
265 : }
266 :
267 : // public method
268 :
269 5574 : void SvtCommandOptions_Impl::EstablisFrameCallback(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
270 : {
271 : // check if frame already exists inside list
272 : // ignore double registrations
273 : // every frame must be notified one times only!
274 5574 : ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XFrame > xWeak(xFrame);
275 5574 : SvtFrameVector::const_iterator pIt = ::std::find(m_lFrames.begin(), m_lFrames.end(), xWeak);
276 5574 : if (pIt == m_lFrames.end())
277 5574 : m_lFrames.push_back(xWeak);
278 5574 : }
279 :
280 : // private method
281 :
282 309 : Sequence< OUString > SvtCommandOptions_Impl::impl_GetPropertyNames()
283 : {
284 : // First get ALL names of current existing list items in configuration!
285 309 : Sequence< OUString > lDisabledItems = GetNodeNames( SETNODE_DISABLED, utl::CONFIG_NAME_LOCAL_PATH );
286 :
287 618 : OUString aSetNode( SETNODE_DISABLED );
288 309 : aSetNode += PATHDELIMITER;
289 :
290 618 : OUString aCommandKey( PATHDELIMITER );
291 309 : aCommandKey += PROPERTYNAME_CMD;
292 :
293 : // Expand all keys
294 309 : for (sal_Int32 i=0; i<lDisabledItems.getLength(); ++i )
295 : {
296 0 : OUStringBuffer aBuffer( 32 );
297 0 : aBuffer.append( aSetNode );
298 0 : aBuffer.append( lDisabledItems[i] );
299 0 : aBuffer.append( aCommandKey );
300 0 : lDisabledItems[i] = aBuffer.makeStringAndClear();
301 0 : }
302 :
303 : // Return result.
304 618 : return lDisabledItems;
305 : }
306 :
307 : // initialize static member
308 : // DON'T DO IT IN YOUR HEADER!
309 : // see definition for further information
310 :
311 : SvtCommandOptions_Impl* SvtCommandOptions::m_pDataContainer = NULL;
312 : sal_Int32 SvtCommandOptions::m_nRefCount = 0;
313 :
314 : // constructor
315 :
316 47476 : SvtCommandOptions::SvtCommandOptions()
317 : {
318 : // Global access, must be guarded (multithreading!).
319 47476 : MutexGuard aGuard( GetOwnStaticMutex() );
320 : // Increase our refcount ...
321 47476 : ++m_nRefCount;
322 : // ... and initialize our data container only if it not already exist!
323 47476 : if( m_pDataContainer == NULL )
324 : {
325 309 : m_pDataContainer = new SvtCommandOptions_Impl;
326 309 : ItemHolder1::holdConfigItem(E_CMDOPTIONS);
327 47476 : }
328 47476 : }
329 :
330 : // destructor
331 :
332 94945 : SvtCommandOptions::~SvtCommandOptions()
333 : {
334 : // Global access, must be guarded (multithreading!)
335 47320 : MutexGuard aGuard( GetOwnStaticMutex() );
336 : // Decrease our refcount.
337 47320 : --m_nRefCount;
338 : // If last instance was deleted ...
339 : // we must destroy our static data container!
340 47320 : if( m_nRefCount <= 0 )
341 : {
342 199 : delete m_pDataContainer;
343 199 : m_pDataContainer = NULL;
344 47320 : }
345 47625 : }
346 :
347 : // public method
348 :
349 10302 : bool SvtCommandOptions::HasEntries( CmdOption eOption ) const
350 : {
351 10302 : MutexGuard aGuard( GetOwnStaticMutex() );
352 10302 : return m_pDataContainer->HasEntries( eOption );
353 : }
354 :
355 : // public method
356 :
357 317984 : bool SvtCommandOptions::Lookup( CmdOption eCmdOption, const OUString& aCommandURL ) const
358 : {
359 317984 : MutexGuard aGuard( GetOwnStaticMutex() );
360 317984 : return m_pDataContainer->Lookup( eCmdOption, aCommandURL );
361 : }
362 :
363 : // public method
364 :
365 5574 : void SvtCommandOptions::EstablisFrameCallback(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame)
366 : {
367 5574 : MutexGuard aGuard( GetOwnStaticMutex() );
368 5574 : m_pDataContainer->EstablisFrameCallback(xFrame);
369 5574 : }
370 :
371 : namespace
372 : {
373 : class theCommandOptionsMutex : public rtl::Static<osl::Mutex, theCommandOptionsMutex>{};
374 : }
375 :
376 : // private method
377 :
378 428656 : Mutex& SvtCommandOptions::GetOwnStaticMutex()
379 : {
380 428656 : return theCommandOptionsMutex::get();
381 : }
382 :
383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|