xref: /trunk/main/framework/source/accelerators/acceleratorconfiguration.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 #include <accelerators/acceleratorconfiguration.hxx>
27 
28 //_______________________________________________
29 // own includes
30 #include <pattern/configuration.hxx>
31 #include <accelerators/presethandler.hxx>
32 
33 #include <xml/saxnamespacefilter.hxx>
34 #include <xml/acceleratorconfigurationreader.hxx>
35 #include <xml/acceleratorconfigurationwriter.hxx>
36 
37 #include <threadhelp/readguard.hxx>
38 #include <threadhelp/writeguard.hxx>
39 
40 #include <acceleratorconst.h>
41 #include <services.h>
42 
43 //_______________________________________________
44 // interface includes
45 #include <com/sun/star/xml/sax/XParser.hpp>
46 #include <com/sun/star/xml/sax/InputSource.hpp>
47 #include <com/sun/star/io/XActiveDataSource.hpp>
48 #include <com/sun/star/embed/ElementModes.hpp>
49 #include <com/sun/star/io/XSeekable.hpp>
50 #include <com/sun/star/io/XTruncate.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 
53 //_______________________________________________
54 // other includes
55 #include <vcl/svapp.hxx>
56 
57 #ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
58 #include <com/sun/star/container/XNamed.hpp>
59 #endif
60 
61 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
62 #include <com/sun/star/container/XNameContainer.hpp>
63 #endif
64 
65 #ifndef __COM_SUN_STAR_AWT_KEYEVENT_HPP_
66 #include <com/sun/star/awt/KeyEvent.hpp>
67 #endif
68 
69 #ifndef __COM_SUN_STAR_AWT_KEYMODIFIER_HPP_
70 #include <com/sun/star/awt/KeyModifier.hpp>
71 #endif
72 
73 #ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
74 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
75 #endif
76 
77 #ifndef _COM_SUN_STAR_UTIL_XCHANGESNOTIFIER_HPP_
78 #include <com/sun/star/util/XChangesNotifier.hpp>
79 #endif
80 
81 #ifndef _COMPHELPER_CONFIGURATIONHELPER_HXX_
82 #include <comphelper/configurationhelper.hxx>
83 #endif
84 
85 #ifndef UNOTOOLS_CONFIGPATHES_HXX_INCLUDED
86 #include <unotools/configpathes.hxx>
87 #endif
88 
89 #ifndef _RTL_LOGFILE_HXX_
90 #include <rtl/logfile.hxx>
91 #endif
92 
93 #include <svtools/acceleratorexecute.hxx>
94 
95 #include <stdio.h>
96 
97 //_______________________________________________
98 // const
99 
100 namespace framework
101 {
102 
103 #ifdef fpc
104     #error "Who exports this define? I use it as namespace alias ..."
105 #else
106     namespace fpc = ::framework::pattern::configuration;
107 #endif
108 
lcl_getKeyString(salhelper::SingletonRef<framework::KeyMapping> & _rKeyMapping,const css::awt::KeyEvent & aKeyEvent)109     ::rtl::OUString lcl_getKeyString(salhelper::SingletonRef<framework::KeyMapping>& _rKeyMapping, const css::awt::KeyEvent& aKeyEvent)
110     {
111         const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of a identifier...
112         ::rtl::OUStringBuffer sKeyBuffer((_rKeyMapping->mapCodeToIdentifier(aKeyEvent.KeyCode)).copy(nBeginIndex));
113 
114         if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
115             sKeyBuffer.appendAscii("_SHIFT");
116         if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1  )
117             sKeyBuffer.appendAscii("_MOD1");
118         if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2  )
119             sKeyBuffer.appendAscii("_MOD2");
120         if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3  )
121             sKeyBuffer.appendAscii("_MOD3");
122 
123         return sKeyBuffer.makeStringAndClear();
124     }
125 
126 //-----------------------------------------------
127 //  XInterface, XTypeProvider
DEFINE_XINTERFACE_6(XMLBasedAcceleratorConfiguration,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::ui::XAcceleratorConfiguration),DIRECT_INTERFACE (css::form::XReset),DIRECT_INTERFACE (css::ui::XUIConfigurationPersistence),DIRECT_INTERFACE (css::ui::XUIConfigurationStorage),DIRECT_INTERFACE (css::ui::XUIConfiguration))128 DEFINE_XINTERFACE_6(XMLBasedAcceleratorConfiguration                       ,
129                     OWeakObject                                            ,
130                     DIRECT_INTERFACE(css::lang::XTypeProvider             ),
131                     DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration  ),
132                     DIRECT_INTERFACE(css::form::XReset                    ),
133                     DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
134                     DIRECT_INTERFACE(css::ui::XUIConfigurationStorage    ),
135                     DIRECT_INTERFACE(css::ui::XUIConfiguration           ))
136 
137 DEFINE_XTYPEPROVIDER_6(XMLBasedAcceleratorConfiguration     ,
138                        css::lang::XTypeProvider             ,
139                        css::ui::XAcceleratorConfiguration  ,
140                        css::form::XReset                    ,
141                        css::ui::XUIConfigurationPersistence,
142                        css::ui::XUIConfigurationStorage    ,
143                        css::ui::XUIConfiguration           )
144 
145 //-----------------------------------------------
146 XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
147     : ThreadHelpBase  (&Application::GetSolarMutex())
148     , m_xSMGR         (xSMGR                        )
149     , m_aPresetHandler(xSMGR                        )
150     , m_pWriteCache   (0                            )
151 {
152 }
153 
154 //-----------------------------------------------
~XMLBasedAcceleratorConfiguration()155 XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
156 {
157     LOG_ASSERT(!m_pWriteCache, "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()\nChanges not flushed. Ignore it ...")
158 }
159 
160 //-----------------------------------------------
getAllKeyEvents()161 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getAllKeyEvents()
162 {
163     // SAFE -> ----------------------------------
164     ReadGuard aReadLock(m_aLock);
165 
166     AcceleratorCache&          rCache = impl_getCFG();
167     AcceleratorCache::TKeyList lKeys  = rCache.getAllKeys();
168     return lKeys.getAsConstList();
169 
170     // <- SAFE ----------------------------------
171 }
172 
173 //-----------------------------------------------
getCommandByKeyEvent(const css::awt::KeyEvent & aKeyEvent)174 ::rtl::OUString SAL_CALL XMLBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
175 {
176     // SAFE -> ----------------------------------
177     ReadGuard aReadLock(m_aLock);
178 
179     AcceleratorCache& rCache = impl_getCFG();
180     if (!rCache.hasKey(aKeyEvent))
181         throw css::container::NoSuchElementException(
182                 ::rtl::OUString(),
183                 static_cast< ::cppu::OWeakObject* >(this));
184     return rCache.getCommandByKey(aKeyEvent);
185 
186     // <- SAFE ----------------------------------
187 }
188 
189 //-----------------------------------------------
setKeyEvent(const css::awt::KeyEvent & aKeyEvent,const::rtl::OUString & sCommand)190 void SAL_CALL XMLBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
191                                                     const ::rtl::OUString&    sCommand )
192 {
193     if (
194         (aKeyEvent.KeyCode   == 0) &&
195         (aKeyEvent.KeyChar   == 0) &&
196         (aKeyEvent.KeyFunc   == 0) &&
197         (aKeyEvent.Modifiers == 0)
198         )
199         throw css::lang::IllegalArgumentException(
200         ::rtl::OUString::createFromAscii("Such key event seems not to be supported by any operating system."),
201         static_cast< ::cppu::OWeakObject* >(this),
202         0);
203 
204     if (!sCommand.getLength())
205         throw css::lang::IllegalArgumentException(
206         ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
207         static_cast< ::cppu::OWeakObject* >(this),
208         1);
209 
210     // SAFE -> ----------------------------------
211     WriteGuard aWriteLock(m_aLock);
212 
213     AcceleratorCache& rCache = impl_getCFG(sal_True); // sal_True => force getting of a writeable cache!
214     rCache.setKeyCommandPair(aKeyEvent, sCommand);
215 
216     aWriteLock.unlock();
217     // <- SAFE ----------------------------------
218 }
219 
220 //-----------------------------------------------
removeKeyEvent(const css::awt::KeyEvent & aKeyEvent)221 void SAL_CALL XMLBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
222 {
223     // SAFE -> ----------------------------------
224     WriteGuard aWriteLock(m_aLock);
225 
226     AcceleratorCache& rCache = impl_getCFG(sal_True); // true => force using of a writeable cache
227     if (!rCache.hasKey(aKeyEvent))
228         throw css::container::NoSuchElementException(
229         ::rtl::OUString(),
230         static_cast< ::cppu::OWeakObject* >(this));
231     rCache.removeKey(aKeyEvent);
232 
233     // <- SAFE ----------------------------------
234 }
235 
236 //-----------------------------------------------
getKeyEventsByCommand(const::rtl::OUString & sCommand)237 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
238 {
239     if (!sCommand.getLength())
240         throw css::lang::IllegalArgumentException(
241                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
242                 static_cast< ::cppu::OWeakObject* >(this),
243                 1);
244 
245     // SAFE -> ----------------------------------
246     ReadGuard aReadLock(m_aLock);
247 
248     AcceleratorCache& rCache = impl_getCFG();
249     if (!rCache.hasCommand(sCommand))
250         throw css::container::NoSuchElementException(
251                 ::rtl::OUString(),
252                 static_cast< ::cppu::OWeakObject* >(this));
253 
254     AcceleratorCache::TKeyList lKeys  = rCache.getKeysByCommand(sCommand);
255     return lKeys.getAsConstList();
256 
257     // <- SAFE ----------------------------------
258 }
259 
260 //-----------------------------------------------
getPreferredKeyEventsForCommandList(const css::uno::Sequence<::rtl::OUString> & lCommandList)261 css::uno::Sequence< css::uno::Any > SAL_CALL XMLBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
262 {
263     // SAFE -> ----------------------------------
264     ReadGuard aReadLock(m_aLock);
265 
266     sal_Int32                           i              = 0;
267     sal_Int32                           c              = lCommandList.getLength();
268     css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
269     AcceleratorCache&                   rCache         = impl_getCFG();
270 
271     for (i=0; i<c; ++i)
272     {
273         const ::rtl::OUString& rCommand = lCommandList[i];
274         if (!rCommand.getLength())
275             throw css::lang::IllegalArgumentException(
276                     ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
277                     static_cast< ::cppu::OWeakObject* >(this),
278                     (sal_Int16)i);
279 
280         if (!rCache.hasCommand(rCommand))
281             continue;
282 
283         AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
284         if ( lKeys.empty() )
285             continue;
286 
287         css::uno::Any& rAny = lPreferredOnes[i];
288         rAny <<= *(lKeys.begin());
289     }
290 
291     aReadLock.unlock();
292     // <- SAFE ----------------------------------
293 
294     return lPreferredOnes;
295 }
296 
297 //-----------------------------------------------
removeCommandFromAllKeyEvents(const::rtl::OUString & sCommand)298 void SAL_CALL XMLBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
299 {
300     if (!sCommand.getLength())
301         throw css::lang::IllegalArgumentException(
302                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
303                 static_cast< ::cppu::OWeakObject* >(this),
304                 0);
305 
306     // SAFE -> ----------------------------------
307     WriteGuard aWriteLock(m_aLock);
308 
309     AcceleratorCache& rCache = impl_getCFG(sal_True); // sal_True => force getting of a writeable cache!
310     if (!rCache.hasCommand(sCommand))
311         throw css::container::NoSuchElementException(
312                 ::rtl::OUString::createFromAscii("Command does not exists inside this container."),
313                 static_cast< ::cppu::OWeakObject* >(this));
314     rCache.removeCommand(sCommand);
315 
316     aWriteLock.unlock();
317     // <- SAFE ----------------------------------
318 }
319 
320 //-----------------------------------------------
reload()321 void SAL_CALL XMLBasedAcceleratorConfiguration::reload()
322 {
323     css::uno::Reference< css::io::XStream > xStreamNoLang;
324 
325     // SAFE -> ----------------------------------
326     ReadGuard aReadLock(m_aLock);
327     css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
328     try
329     {
330         xStreamNoLang = m_aPresetHandler.openPreset(PresetHandler::PRESET_DEFAULT(), sal_True);
331     }
332     catch(const css::io::IOException&) {} // does not have to exist
333     aReadLock.unlock();
334     // <- SAFE ----------------------------------
335 
336     css::uno::Reference< css::io::XInputStream > xIn;
337     if (xStream.is())
338         xIn = xStream->getInputStream();
339     if (!xIn.is())
340         throw css::io::IOException(
341         ::rtl::OUString::createFromAscii("Could not open accelerator configuration for reading."),
342         static_cast< ::cppu::OWeakObject* >(this));
343 
344     // impl_ts_load() does not clear the cache
345     // SAFE -> ----------------------------------
346     WriteGuard aWriteLock(m_aLock);
347     m_aReadCache = AcceleratorCache();
348     aWriteLock.unlock();
349     // <- SAFE ----------------------------------
350 
351     impl_ts_load(xIn);
352 
353     // Load also the general language independent default accelerators
354     // (ignoring the already defined accelerators)
355     if (xStreamNoLang.is())
356     {
357         xIn = xStreamNoLang->getInputStream();
358         if (xIn.is())
359             impl_ts_load(xIn);
360     }
361 }
362 
363 //-----------------------------------------------
store()364 void SAL_CALL XMLBasedAcceleratorConfiguration::store()
365 {
366     // SAFE -> ----------------------------------
367     ReadGuard aReadLock(m_aLock);
368     css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
369     aReadLock.unlock();
370     // <- SAFE ----------------------------------
371 
372     css::uno::Reference< css::io::XOutputStream > xOut;
373     if (xStream.is())
374         xOut = xStream->getOutputStream();
375 
376     if (!xOut.is())
377         throw css::io::IOException(
378         ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
379         static_cast< ::cppu::OWeakObject* >(this));
380 
381     impl_ts_save(xOut);
382 
383     xOut.clear();
384     xStream.clear();
385 
386     m_aPresetHandler.commitUserChanges();
387 }
388 
389 //-----------------------------------------------
storeToStorage(const css::uno::Reference<css::embed::XStorage> & xStorage)390 void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
391 {
392     css::uno::Reference< css::io::XStream > xStream = StorageHolder::openSubStreamWithFallback(
393                                                             xStorage,
394                                                             PresetHandler::TARGET_CURRENT(),
395                                                             css::embed::ElementModes::READWRITE,
396                                                             sal_False); // False => no fallback from read/write to readonly!
397     css::uno::Reference< css::io::XOutputStream > xOut;
398     if (xStream.is())
399         xOut = xStream->getOutputStream();
400 
401     if (!xOut.is())
402         throw css::io::IOException(
403                 ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
404                 static_cast< ::cppu::OWeakObject* >(this));
405 
406     impl_ts_save(xOut);
407 
408     // TODO inform listener about success, so it can flush the root and sub storage of this stream!
409 }
410 
411 //-----------------------------------------------
isModified()412 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isModified()
413 {
414     // SAFE -> ----------------------------------
415     ReadGuard aReadLock(m_aLock);
416     return (m_pWriteCache != 0);
417     // <- SAFE ----------------------------------
418 }
419 
420 //-----------------------------------------------
isReadOnly()421 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isReadOnly()
422 {
423     // SAFE -> ----------------------------------
424     ReadGuard aReadLock(m_aLock);
425     css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
426     aReadLock.unlock();
427     // <- SAFE ----------------------------------
428 
429     css::uno::Reference< css::io::XOutputStream > xOut;
430     if (xStream.is())
431         xOut = xStream->getOutputStream();
432     return !(xOut.is());
433 }
434 
435 //-----------------------------------------------
setStorage(const css::uno::Reference<css::embed::XStorage> &)436 void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
437 {
438     LOG_WARNING("XMLBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
439 }
440 
441 //-----------------------------------------------
hasStorage()442 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::hasStorage()
443 {
444     LOG_WARNING("XMLBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
445     return sal_False;
446 }
447 
448 //-----------------------------------------------
addConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)449 void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
450 {
451     LOG_WARNING("XMLBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
452 }
453 
454 //-----------------------------------------------
removeConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)455 void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
456 {
457     LOG_WARNING("XMLBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
458 }
459 
460 //-----------------------------------------------
reset()461 void SAL_CALL XMLBasedAcceleratorConfiguration::reset()
462 {
463     // SAFE -> ----------------------------------
464     WriteGuard aWriteLock(m_aLock);
465     m_aPresetHandler.copyPresetToTarget(PresetHandler::PRESET_DEFAULT(), PresetHandler::TARGET_CURRENT());
466     aWriteLock.unlock();
467     // <- SAFE ----------------------------------
468 
469     reload();
470 }
471 
472 //-----------------------------------------------
addResetListener(const css::uno::Reference<css::form::XResetListener> &)473 void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
474 {
475     LOG_WARNING("XMLBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
476 }
477 
478 //-----------------------------------------------
removeResetListener(const css::uno::Reference<css::form::XResetListener> &)479 void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
480 {
481     LOG_WARNING("XMLBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
482 }
483 
484 //-----------------------------------------------
485 // IStorageListener
changesOccured(const::rtl::OUString &)486 void XMLBasedAcceleratorConfiguration::changesOccured(const ::rtl::OUString& /*sPath*/)
487 {
488     reload();
489 }
490 
491 //-----------------------------------------------
impl_ts_load(const css::uno::Reference<css::io::XInputStream> & xStream)492 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
493 {
494     // SAFE -> ----------------------------------
495     WriteGuard aWriteLock(m_aLock);
496 
497     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
498     if (m_pWriteCache)
499     {
500         // be aware of reentrance problems - use temp variable for calling delete ... :-)
501         AcceleratorCache* pTemp = m_pWriteCache;
502         m_pWriteCache = 0;
503         delete pTemp;
504     }
505 
506     aWriteLock.unlock();
507     // <- SAFE ----------------------------------
508 
509     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
510     if (xSeek.is())
511         xSeek->seek(0);
512 
513     // add accelerators to the cache (the cache is not cleared)
514     // SAFE -> ----------------------------------
515     aWriteLock.lock();
516 
517     // create the parser queue
518     // Note: Use special filter object between parser and reader
519     // to get filtered xml with right namespaces ...
520     // Use further a temp cache for reading!
521     AcceleratorConfigurationReader*                        pReader = new AcceleratorConfigurationReader(m_aReadCache);
522     css::uno::Reference< css::xml::sax::XDocumentHandler > xReader (static_cast< ::cppu::OWeakObject* >(pReader), css::uno::UNO_QUERY_THROW);
523     SaxNamespaceFilter*                                    pFilter = new SaxNamespaceFilter(xReader);
524     css::uno::Reference< css::xml::sax::XDocumentHandler > xFilter (static_cast< ::cppu::OWeakObject* >(pFilter), css::uno::UNO_QUERY_THROW);
525 
526     // connect parser, filter and stream
527     css::uno::Reference< css::xml::sax::XParser > xParser(xSMGR->createInstance(SERVICENAME_SAXPARSER), css::uno::UNO_QUERY_THROW);
528     xParser->setDocumentHandler(xFilter);
529 
530     css::xml::sax::InputSource aSource;
531     aSource.aInputStream = xStream;
532 
533     // TODO think about error handling
534     xParser->parseStream(aSource);
535 
536     aWriteLock.unlock();
537     // <- SAFE ----------------------------------
538 }
539 
540 //-----------------------------------------------
impl_ts_save(const css::uno::Reference<css::io::XOutputStream> & xStream)541 void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
542 {
543     // SAFE -> ----------------------------------
544     ReadGuard aReadLock(m_aLock);
545 
546     AcceleratorCache aCache;
547     sal_Bool bChanged = (m_pWriteCache != 0);
548     if (bChanged)
549         aCache.takeOver(*m_pWriteCache);
550     else
551         aCache.takeOver(m_aReadCache);
552     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
553 
554     aReadLock.unlock();
555     // <- SAFE ----------------------------------
556 
557     css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
558     xClearable->truncate();
559 
560     // TODO can be removed if seek(0) is done by truncate() automatically!
561     css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
562     if (xSeek.is())
563         xSeek->seek(0);
564 
565     // combine writer/cache/stream etcpp.
566     css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter    (xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
567     css::uno::Reference< css::io::XActiveDataSource>       xDataSource(xWriter                                     , css::uno::UNO_QUERY_THROW);
568     xDataSource->setOutputStream(xStream);
569 
570     // write into the stream
571     AcceleratorConfigurationWriter aWriter(aCache, xWriter);
572     aWriter.flush();
573 
574     // take over all changes into the original container
575     // SAFE -> ----------------------------------
576     WriteGuard aWriteLock(m_aLock);
577 
578     // take over all changes into the readonly cache ...
579     // and forget the copy-on-write copied cache
580     if (bChanged)
581     {
582         m_aReadCache.takeOver(*m_pWriteCache);
583         // live with reentrance .-)
584         AcceleratorCache* pTemp = m_pWriteCache;
585         m_pWriteCache = 0;
586         delete pTemp;
587     }
588 
589     aWriteLock.unlock();
590     // <- SAFE ----------------------------------
591 }
592 
593 //-----------------------------------------------
impl_getCFG(sal_Bool bWriteAccessRequested)594 AcceleratorCache& XMLBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bWriteAccessRequested)
595 {
596     // SAFE -> ----------------------------------
597     WriteGuard aWriteLock(m_aLock);
598 
599     //create copy of our readonly-cache, if write access is forced ... but
600     //not still possible!
601     if (
602         (bWriteAccessRequested) &&
603         (!m_pWriteCache       )
604        )
605     {
606         m_pWriteCache = new AcceleratorCache(m_aReadCache);
607     }
608 
609     // in case, we have a writeable cache, we use it for reading too!
610     // Otherwise the API user can't find its own changes ...
611     if (m_pWriteCache)
612         return *m_pWriteCache;
613     else
614         return m_aReadCache;
615     // <- SAFE ----------------------------------
616 }
617 
618 //-----------------------------------------------
impl_ts_getLocale() const619 ::comphelper::Locale XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
620 {
621     static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
622     static ::rtl::OUString LOCALE_PATH    = ::rtl::OUString::createFromAscii("L10N"                 );
623     static ::rtl::OUString LOCALE_KEY     = ::rtl::OUString::createFromAscii("ooLocale"             );
624 
625     // SAFE -> ----------------------------------
626     ReadGuard aReadLock(m_aLock);
627     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
628     aReadLock.unlock();
629     // <- SAFE ----------------------------------
630 
631     css::uno::Reference< css::uno::XInterface >     xCFG      = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
632     css::uno::Reference< css::beans::XPropertySet > xProp     (xCFG, css::uno::UNO_QUERY_THROW);
633     ::rtl::OUString                                 sISOLocale;
634     xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
635 
636     if (!sISOLocale.getLength())
637         return ::comphelper::Locale::EN_US();
638     return ::comphelper::Locale(sISOLocale);
639 }
640 
641 /*******************************************************************************
642 *
643 * XCU based accelerator configuration
644 *
645 *******************************************************************************/
646 
647 //-----------------------------------------------
648 //  XInterface, XTypeProvider
DEFINE_XINTERFACE_8(XCUBasedAcceleratorConfiguration,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::ui::XAcceleratorConfiguration),DIRECT_INTERFACE (css::util::XChangesListener),DIRECT_INTERFACE (css::form::XReset),DIRECT_INTERFACE (css::lang::XComponent),DIRECT_INTERFACE (css::ui::XUIConfigurationPersistence),DIRECT_INTERFACE (css::ui::XUIConfigurationStorage),DIRECT_INTERFACE (css::ui::XUIConfiguration))649 DEFINE_XINTERFACE_8(XCUBasedAcceleratorConfiguration                       ,
650                     OWeakObject                                            ,
651                     DIRECT_INTERFACE(css::lang::XTypeProvider             ),
652                     DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration  ),
653                     DIRECT_INTERFACE(css::util::XChangesListener          ),
654                     DIRECT_INTERFACE(css::form::XReset                    ),
655                     DIRECT_INTERFACE(css::lang::XComponent                ),
656                     DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
657                     DIRECT_INTERFACE(css::ui::XUIConfigurationStorage    ),
658                     DIRECT_INTERFACE(css::ui::XUIConfiguration           ))
659 
660                     DEFINE_XTYPEPROVIDER_8(XCUBasedAcceleratorConfiguration ,
661                     css::lang::XTypeProvider             ,
662                     css::ui::XAcceleratorConfiguration  ,
663                     css::util::XChangesListener          ,
664                     css::form::XReset                    ,
665                     css::lang::XComponent                ,
666                     css::ui::XUIConfigurationPersistence,
667                     css::ui::XUIConfigurationStorage    ,
668                     css::ui::XUIConfiguration           )
669 
670 //-----------------------------------------------
671 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
672                                 : ThreadHelpBase  (&Application::GetSolarMutex())
673                                 , m_xSMGR         (xSMGR                        )
674                                 , m_pPrimaryWriteCache(0                        )
675                                 , m_pSecondaryWriteCache(0                      )
676 {
677     static const ::rtl::OUString CFG_ENTRY_ACCELERATORS(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Accelerators"));
678     m_xCfg = css::uno::Reference< css::container::XNameAccess > (
679              ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_ACCELERATORS, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
680              css::uno::UNO_QUERY );
681 }
682 
683 //-----------------------------------------------
~XCUBasedAcceleratorConfiguration()684 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
685 {
686 }
687 
688 //-----------------------------------------------
getAllKeyEvents()689 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
690 {
691     // SAFE -> ----------------------------------
692     ReadGuard aReadLock(m_aLock);
693 
694     AcceleratorCache::TKeyList lKeys  = impl_getCFG(sal_True).getAllKeys(); //get keys from PrimaryKeys set
695 
696     AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(sal_False).getAllKeys(); //get keys from SecondaryKeys set
697     lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
698     AcceleratorCache::TKeyList::const_iterator pIt;
699     AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
700     for ( pIt  = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
701         lKeys.push_back(*pIt);
702 
703     return lKeys.getAsConstList();
704 
705     // <- SAFE ----------------------------------
706 }
707 
708 //-----------------------------------------------
getCommandByKeyEvent(const css::awt::KeyEvent & aKeyEvent)709 ::rtl::OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
710 {
711     // SAFE -> ----------------------------------
712     ReadGuard aReadLock(m_aLock);
713 
714     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True );
715     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
716 
717     if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
718         throw css::container::NoSuchElementException(
719         ::rtl::OUString(),
720         static_cast< ::cppu::OWeakObject* >(this));
721 
722     if (rPrimaryCache.hasKey(aKeyEvent))
723         return rPrimaryCache.getCommandByKey(aKeyEvent);
724     else
725         return rSecondaryCache.getCommandByKey(aKeyEvent);
726 
727     // <- SAFE ----------------------------------
728 }
729 
730 //-----------------------------------------------
setKeyEvent(const css::awt::KeyEvent & aKeyEvent,const::rtl::OUString & sCommand)731 void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
732                                                     const ::rtl::OUString&    sCommand )
733 {
734     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::setKeyEvent" );
735 
736     if (
737         (aKeyEvent.KeyCode   == 0) &&
738         (aKeyEvent.KeyChar   == 0) &&
739         (aKeyEvent.KeyFunc   == 0) &&
740         (aKeyEvent.Modifiers == 0)
741         )
742         throw css::lang::IllegalArgumentException(
743                 ::rtl::OUString::createFromAscii("Such key event seems not to be supported by any operating system."),
744                 static_cast< ::cppu::OWeakObject* >(this),
745                 0);
746 
747     if (!sCommand.getLength())
748                 throw css::lang::IllegalArgumentException(
749                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
750                 static_cast< ::cppu::OWeakObject* >(this),
751                 1);
752 
753     // SAFE -> ----------------------------------
754     WriteGuard aWriteLock(m_aLock);
755 
756     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True ); // sal_True => force getting of a writeable cache!
757     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True); // sal_True => force getting of a writeable cache!
758 
759     if ( rPrimaryCache.hasKey(aKeyEvent) )
760     {
761         ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
762         if ( sCommand != sOriginalCommand )
763         {
764             if (rSecondaryCache.hasCommand(sOriginalCommand))
765             {
766                 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
767                 rSecondaryCache.removeKey(lSecondaryKeys[0]);
768                 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
769             }
770 
771             if (rPrimaryCache.hasCommand(sCommand))
772             {
773                 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
774                 rPrimaryCache.removeKey(lPrimaryKeys[0]);
775                 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
776             }
777 
778             rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
779         }
780     }
781 
782     else if ( rSecondaryCache.hasKey(aKeyEvent) )
783     {
784         ::rtl::OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
785         if (sCommand != sOriginalCommand)
786         {
787             if (rPrimaryCache.hasCommand(sCommand))
788             {
789                 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
790                 rPrimaryCache.removeKey(lPrimaryKeys[0]);
791                 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
792             }
793 
794             rSecondaryCache.removeKey(aKeyEvent);
795             rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
796         }
797     }
798 
799     else
800     {
801         if (rPrimaryCache.hasCommand(sCommand))
802         {
803             AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
804             rPrimaryCache.removeKey(lPrimaryKeys[0]);
805             rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
806         }
807 
808         rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
809     }
810 
811     aWriteLock.unlock();
812     // <- SAFE ----------------------------------
813 }
814 
815 //-----------------------------------------------
removeKeyEvent(const css::awt::KeyEvent & aKeyEvent)816 void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
817 {
818     // SAFE -> ----------------------------------
819     WriteGuard aWriteLock(m_aLock);
820 
821     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True );
822     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
823 
824     if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
825         throw css::container::NoSuchElementException(
826         ::rtl::OUString(),
827         static_cast< ::cppu::OWeakObject* >(this));
828 
829     if (rPrimaryCache.hasKey(aKeyEvent))
830     {
831         ::rtl::OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
832         if (sDelCommand.getLength() > 0)
833         {
834             ::rtl::OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
835             if (rSecondaryCache.hasCommand(sOriginalCommand))
836             {
837                 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
838                 rSecondaryCache.removeKey(lSecondaryKeys[0]);
839                 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
840             }
841 
842             rPrimaryCache.removeKey(aKeyEvent);
843         }
844 
845     }
846     else
847     {
848         ::rtl::OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
849         if (sDelCommand.getLength() > 0)
850             rSecondaryCache.removeKey(aKeyEvent);
851     }
852 
853     // <- SAFE ----------------------------------
854 }
855 
856 //-----------------------------------------------
getKeyEventsByCommand(const::rtl::OUString & sCommand)857 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const ::rtl::OUString& sCommand)
858 {
859     if (!sCommand.getLength())
860         throw css::lang::IllegalArgumentException(
861                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
862                 static_cast< ::cppu::OWeakObject* >(this),
863                 1);
864 
865     // SAFE -> ----------------------------------
866     ReadGuard aReadLock(m_aLock);
867 
868     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True );
869     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
870 
871     if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
872         throw css::container::NoSuchElementException(
873                 ::rtl::OUString(),
874                 static_cast< ::cppu::OWeakObject* >(this));
875 
876     AcceleratorCache::TKeyList lKeys  = rPrimaryCache.getKeysByCommand(sCommand);
877 
878     AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
879     AcceleratorCache::TKeyList::const_iterator pIt;
880     for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
881         lKeys.push_back(*pIt);
882 
883     return lKeys.getAsConstList();
884 
885     // <- SAFE ----------------------------------
886 }
887 
888 //-----------------------------------------------
lcl_getPreferredKey(const AcceleratorCache::TKeyList & lKeys)889 AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
890 {
891     AcceleratorCache::TKeyList::const_iterator pIt;
892     for (  pIt  = lKeys.begin ();
893            pIt != lKeys.end   ();
894          ++pIt                  )
895     {
896         const css::awt::KeyEvent& rAWTKey = *pIt;
897         const KeyCode             aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
898         const String              sName   = aVCLKey.GetName();
899 
900         if (sName.Len () > 0)
901             return pIt;
902     }
903 
904     return lKeys.end ();
905 }
906 
907 //-----------------------------------------------
getPreferredKeyEventsForCommandList(const css::uno::Sequence<::rtl::OUString> & lCommandList)908 css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< ::rtl::OUString >& lCommandList)
909 {
910     // SAFE -> ----------------------------------
911     ReadGuard aReadLock(m_aLock);
912 
913     sal_Int32                           i              = 0;
914     sal_Int32                           c              = lCommandList.getLength();
915     css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
916     AcceleratorCache&                   rCache         = impl_getCFG(sal_True);
917 
918     for (i=0; i<c; ++i)
919     {
920         const ::rtl::OUString& rCommand = lCommandList[i];
921         if (!rCommand.getLength())
922             throw css::lang::IllegalArgumentException(
923                     ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
924                     static_cast< ::cppu::OWeakObject* >(this),
925                     (sal_Int16)i);
926 
927         if (!rCache.hasCommand(rCommand))
928             continue;
929 
930         AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
931         if ( lKeys.empty() )
932             continue;
933 
934         AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
935         if (pPreferredKey != lKeys.end ())
936         {
937             css::uno::Any& rAny = lPreferredOnes[i];
938             rAny <<= *(pPreferredKey);
939         }
940     }
941 
942     aReadLock.unlock();
943     // <- SAFE ----------------------------------
944 
945     return lPreferredOnes;
946 }
947 
948 //-----------------------------------------------
removeCommandFromAllKeyEvents(const::rtl::OUString & sCommand)949 void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const ::rtl::OUString& sCommand)
950 {
951     if (!sCommand.getLength())
952         throw css::lang::IllegalArgumentException(
953                 ::rtl::OUString::createFromAscii("Empty command strings are not allowed here."),
954                 static_cast< ::cppu::OWeakObject* >(this),
955                 0);
956 
957     // SAFE -> ----------------------------------
958     WriteGuard aWriteLock(m_aLock);
959 
960     AcceleratorCache& rPrimaryCache   = impl_getCFG(sal_True, sal_True );
961     AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
962 
963     if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
964         throw css::container::NoSuchElementException(
965                 ::rtl::OUString::createFromAscii("Command does not exists inside this container."),
966                 static_cast< ::cppu::OWeakObject* >(this));
967 
968     if (rPrimaryCache.hasCommand(sCommand))
969         rPrimaryCache.removeCommand(sCommand);
970     if (rSecondaryCache.hasCommand(sCommand))
971         rSecondaryCache.removeCommand(sCommand);
972 
973     aWriteLock.unlock();
974     // <- SAFE ----------------------------------
975 }
976 
977 //-----------------------------------------------
reload()978 void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
979 {
980     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::reload()" );
981 
982     // SAFE -> ----------------------------------
983     WriteGuard aWriteLock(m_aLock);
984 
985     sal_Bool bPreferred;
986     css::uno::Reference< css::container::XNameAccess > xAccess;
987 
988     bPreferred = sal_True;
989     m_aPrimaryReadCache = AcceleratorCache();
990     if (m_pPrimaryWriteCache)
991     {
992         // be aware of reentrance problems - use temp variable for calling delete ... :-)
993         AcceleratorCache* pTemp = m_pPrimaryWriteCache;
994         m_pPrimaryWriteCache = 0;
995         delete pTemp;
996     }
997     m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
998     impl_ts_load(bPreferred, xAccess); // load the preferred keys
999 
1000     bPreferred = sal_False;
1001     m_aSecondaryReadCache = AcceleratorCache();
1002     if (m_pSecondaryWriteCache)
1003     {
1004         // be aware of reentrance problems - use temp variable for calling delete ... :-)
1005         AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1006         m_pSecondaryWriteCache = 0;
1007         delete pTemp;
1008     }
1009     m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1010     impl_ts_load(bPreferred, xAccess); // load the secondary keys
1011 
1012     aWriteLock.unlock();
1013     // <- SAFE ----------------------------------
1014 }
1015 
1016 //-----------------------------------------------
store()1017 void SAL_CALL XCUBasedAcceleratorConfiguration::store()
1018 {
1019     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::store()" );
1020 
1021     // SAFE -> ----------------------------------
1022     ReadGuard aReadLock(m_aLock);
1023 
1024     sal_Bool bPreferred;
1025     css::uno::Reference< css::container::XNameAccess > xAccess;
1026 
1027     bPreferred = sal_True;
1028     // on-demand creation of the primary write cache
1029     impl_getCFG(bPreferred, sal_True);
1030     m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1031     impl_ts_save(bPreferred, xAccess);
1032 
1033     bPreferred = sal_False;
1034     // on-demand creation of the secondary write cache
1035     impl_getCFG(bPreferred, sal_True);
1036     m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1037     impl_ts_save(bPreferred, xAccess);
1038 
1039     aReadLock.unlock();
1040     // <- SAFE ----------------------------------
1041 }
1042 
1043 //-----------------------------------------------
storeToStorage(const css::uno::Reference<css::embed::XStorage> & xStorage)1044 void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
1045 {
1046     // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
1047     if (!xStorage.is())
1048         return;
1049 
1050     long nOpenModes = css::embed::ElementModes::READWRITE;
1051     css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement(::rtl::OUString::createFromAscii("accelerator"), nOpenModes);
1052     if (!xAcceleratorTypeStorage.is())
1053         return;
1054 
1055     css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement(::rtl::OUString::createFromAscii("current"), nOpenModes);
1056     css::uno::Reference< css::io::XOutputStream > xOut;
1057     if (xStream.is())
1058         xOut = xStream->getOutputStream();
1059     if (!xOut.is())
1060         throw css::io::IOException(
1061         ::rtl::OUString::createFromAscii("Could not open accelerator configuration for saving."),
1062         static_cast< ::cppu::OWeakObject* >(this));
1063 
1064     // the original m_aCache has been split into primay cache and secondary cache...
1065     // we should merge them before storing to storage
1066     // SAFE -> ----------------------------------
1067     WriteGuard aWriteLock(m_aLock);
1068 
1069     AcceleratorCache aCache;
1070     if (m_pPrimaryWriteCache != 0)
1071         aCache.takeOver(*m_pPrimaryWriteCache);
1072     else
1073         aCache.takeOver(m_aPrimaryReadCache);
1074 
1075     AcceleratorCache::TKeyList lKeys;
1076     AcceleratorCache::TKeyList::const_iterator pIt;
1077     if (m_pSecondaryWriteCache!=0)
1078     {
1079         lKeys = m_pSecondaryWriteCache->getAllKeys();
1080         for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1081             aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
1082     }
1083     else
1084     {
1085         lKeys = m_aSecondaryReadCache.getAllKeys();
1086         for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1087             aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
1088     }
1089 
1090     aWriteLock.unlock();
1091     // <- SAFE ----------------------------------
1092 
1093     css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
1094     xClearable->truncate();
1095     css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
1096     if (xSeek.is())
1097         xSeek->seek(0);
1098 
1099     css::uno::Reference< css::xml::sax::XDocumentHandler > xWriter    (m_xSMGR->createInstance(SERVICENAME_SAXWRITER), css::uno::UNO_QUERY_THROW);
1100     css::uno::Reference< css::io::XActiveDataSource>       xDataSource(xWriter                                     , css::uno::UNO_QUERY_THROW);
1101     xDataSource->setOutputStream(xOut);
1102 
1103     // write into the stream
1104     AcceleratorConfigurationWriter aWriter(aCache, xWriter);
1105     aWriter.flush();
1106 }
1107 
1108 //-----------------------------------------------
isModified()1109 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
1110 {
1111     return sal_False;
1112 }
1113 
1114 //-----------------------------------------------
isReadOnly()1115 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
1116 {
1117     return sal_False;
1118 }
1119 
1120 //-----------------------------------------------
setStorage(const css::uno::Reference<css::embed::XStorage> &)1121 void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
1122 {
1123     LOG_WARNING("XCUBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
1124 }
1125 
1126 //-----------------------------------------------
hasStorage()1127 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
1128 {
1129     LOG_WARNING("XCUBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
1130         return sal_False;
1131 }
1132 
1133 //-----------------------------------------------
addConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)1134 void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1135 {
1136     LOG_WARNING("XCUBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
1137 }
1138 
1139 //-----------------------------------------------
removeConfigurationListener(const css::uno::Reference<css::ui::XUIConfigurationListener> &)1140 void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1141 {
1142     LOG_WARNING("XCUBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
1143 }
1144 
1145 //-----------------------------------------------
reset()1146 void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
1147 {
1148     css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
1149     ::rtl::OUString sConfig = xNamed->getName();
1150     if ( sConfig.equalsAscii("Global") )
1151     {
1152         m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1153             ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_GLOBAL, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1154             css::uno::UNO_QUERY );
1155         XCUBasedAcceleratorConfiguration::reload();
1156     }
1157     else if ( sConfig.equalsAscii("Modules") )
1158     {
1159         m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1160             ::comphelper::ConfigurationHelper::openConfig( m_xSMGR, CFG_ENTRY_MODULES, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1161             css::uno::UNO_QUERY );
1162         XCUBasedAcceleratorConfiguration::reload();
1163     }
1164 }
1165 
1166 //-----------------------------------------------
addResetListener(const css::uno::Reference<css::form::XResetListener> &)1167 void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1168 {
1169     LOG_WARNING("XCUBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
1170 }
1171 
1172 //-----------------------------------------------
removeResetListener(const css::uno::Reference<css::form::XResetListener> &)1173 void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1174 {
1175     LOG_WARNING("XCUBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
1176 }
1177 
1178 //-----------------------------------------------
changesOccurred(const css::util::ChangesEvent & aEvent)1179 void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
1180 {
1181     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1182 
1183     css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
1184     aEvent.Base >>= xHAccess;
1185     if (! xHAccess.is ())
1186         return;
1187 
1188     css::util::ChangesEvent aReceivedEvents( aEvent );
1189     const sal_Int32 c = aReceivedEvents.Changes.getLength();
1190           sal_Int32 i = 0;
1191     for (i=0; i<c; ++i)
1192     {
1193         const css::util::ElementChange& aChange  =   aReceivedEvents.Changes[i];
1194 
1195         // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1196         // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1197         // So we try to split the path into 3 parts (module isn't important here, because we already know it ... because
1198         // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1199 
1200         ::rtl::OUString sOrgPath ;
1201         ::rtl::OUString sPath    ;
1202         ::rtl::OUString sKey;
1203 
1204         aChange.Accessor >>= sOrgPath;
1205         sPath              = sOrgPath;
1206         ::rtl::OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1207         ::rtl::OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1208 
1209         if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
1210         {
1211             ::rtl::OUString sModule;
1212             sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1213             if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
1214                 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1215         }
1216         else if ( sGlobalModules.equals(CFG_ENTRY_MODULES) )
1217         {
1218             ::rtl::OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1219             sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1220 
1221             if (( sKey.getLength() > 0 ) && ( sPath.getLength() > 0 ))
1222             {
1223                 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1224             }
1225         }
1226     }
1227 }
1228 
1229 //-----------------------------------------------
disposing(const css::lang::EventObject &)1230 void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
1231 {
1232 }
1233 
1234 //-----------------------------------------------
dispose()1235 void SAL_CALL XCUBasedAcceleratorConfiguration::dispose()
1236 {
1237     // nop
1238 }
1239 
1240 //-----------------------------------------------
addEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> &)1241 void SAL_CALL XCUBasedAcceleratorConfiguration::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /* xListener */ )
1242 {
1243     // nop
1244 }
1245 
1246 //-----------------------------------------------
removeEventListener(const::com::sun::star::uno::Reference<::com::sun::star::lang::XEventListener> &)1247 void SAL_CALL XCUBasedAcceleratorConfiguration::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /* aListener */ )
1248 {
1249     // nop
1250 }
1251 
1252 //-----------------------------------------------
impl_ts_load(sal_Bool bPreferred,const css::uno::Reference<css::container::XNameAccess> & xCfg)1253 void XCUBasedAcceleratorConfiguration::impl_ts_load( sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
1254 {
1255     AcceleratorCache aReadCache = AcceleratorCache();
1256     css::uno::Reference< css::container::XNameAccess > xAccess;
1257     if (m_sGlobalOrModules.equalsAscii("Global"))
1258         xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
1259     else if (m_sGlobalOrModules.equalsAscii("Modules"))
1260     {
1261         css::uno::Reference< css::container::XNameAccess > xModules;
1262         xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
1263         xModules->getByName(m_sModuleCFG) >>= xAccess;
1264     }
1265 
1266     const ::rtl::OUString sIsoLang       = impl_ts_getLocale().toISO();
1267     const ::rtl::OUString sDefaultLocale = ::rtl::OUString::createFromAscii("en-US");
1268 
1269     css::uno::Reference< css::container::XNameAccess > xKey;
1270     css::uno::Reference< css::container::XNameAccess > xCommand;
1271     if (xAccess.is())
1272     {
1273         css::uno::Sequence< ::rtl::OUString > lKeys = xAccess->getElementNames();
1274         sal_Int32 nKeys = lKeys.getLength();
1275         for ( sal_Int32 i=0; i<nKeys; ++i )
1276         {
1277             ::rtl::OUString sKey = lKeys[i];
1278             xAccess->getByName(sKey) >>= xKey;
1279             xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1280 
1281             css::uno::Sequence< ::rtl::OUString > lLocales = xCommand->getElementNames();
1282             sal_Int32 nLocales = lLocales.getLength();
1283             ::std::vector< ::rtl::OUString > aLocales;
1284             for ( sal_Int32 j=0; j<nLocales; ++j )
1285                 aLocales.push_back(lLocales[j]);
1286 
1287             ::std::vector< ::rtl::OUString >::const_iterator pFound;
1288             for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1289             {
1290                 if ( *pFound == sIsoLang )
1291                     break;
1292             }
1293 
1294             if ( pFound == aLocales.end() )
1295             {
1296                 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1297                 {
1298                     if ( *pFound == sDefaultLocale )
1299                         break;
1300                 }
1301 
1302                 if ( pFound == aLocales.end() )
1303                     continue;
1304             }
1305 
1306             ::rtl::OUString sLocale = *pFound;
1307             ::rtl::OUString sCommand;
1308             xCommand->getByName(sLocale) >>= sCommand;
1309             if (sCommand.getLength()<1)
1310                 continue;
1311 
1312             css::awt::KeyEvent aKeyEvent;
1313 
1314             sal_Int32 nIndex = 0;
1315             ::rtl::OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
1316             ::rtl::OUString sPrefix = ::rtl::OUString::createFromAscii("KEY_");
1317             aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sPrefix + sKeyCommand);
1318 
1319             css::uno::Sequence< ::rtl::OUString > sToken(4);
1320             const sal_Int32 nToken = 4;
1321             sal_Bool bValid = sal_True;
1322             sal_Int32 k;
1323             for (k=0; k<nToken; ++k)
1324             {
1325                 if (nIndex < 0)
1326                     break;
1327 
1328                 sToken[k] = sKey.getToken(0, '_', nIndex);
1329                 ::rtl::OUString sTest = sToken[k];
1330                 if (sToken[k].getLength() < 1)
1331                 {
1332                     bValid = sal_False;
1333                     break;
1334                 }
1335 
1336                 if (sToken[k].equalsAscii("SHIFT"))
1337                     aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1338                 else if (sToken[k].equalsAscii("MOD1"))
1339                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1340                 else if (sToken[k].equalsAscii("MOD2"))
1341                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1342                 else if (sToken[k].equalsAscii("MOD3"))
1343                     aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1344                 else
1345                 {
1346                     bValid = sal_False;
1347                     break;
1348                 }
1349             }
1350 
1351             if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1352                 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1353         }
1354     }
1355 
1356     if (bPreferred)
1357         m_aPrimaryReadCache.takeOver(aReadCache);
1358     else
1359         m_aSecondaryReadCache.takeOver(aReadCache);
1360 }
1361 
1362 //-----------------------------------------------
impl_ts_save(sal_Bool bPreferred,const css::uno::Reference<css::container::XNameAccess> &)1363 void XCUBasedAcceleratorConfiguration::impl_ts_save(sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
1364 {
1365     if (bPreferred)
1366     {
1367         AcceleratorCache::TKeyList::const_iterator pIt;
1368         AcceleratorCache::TKeyList lPrimaryReadKeys  = m_aPrimaryReadCache.getAllKeys();
1369         AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1370 
1371         for ( pIt  = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
1372         {
1373             if (!m_pPrimaryWriteCache->hasKey(*pIt))
1374                 removeKeyFromConfiguration(*pIt, sal_True);
1375         }
1376 
1377         for ( pIt  = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
1378         {
1379             ::rtl::OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
1380             if (!m_aPrimaryReadCache.hasKey(*pIt))
1381             {
1382                 insertKeyToConfiguration(*pIt, sCommand, sal_True);
1383             }
1384             else
1385             {
1386                 ::rtl::OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
1387                 if (sReadCommand != sCommand)
1388                     insertKeyToConfiguration(*pIt, sCommand, sal_True);
1389             }
1390         }
1391 
1392         // take over all changes into the original container
1393         // SAFE -> ----------------------------------
1394         WriteGuard aWriteLock(m_aLock);
1395 
1396         if (m_pPrimaryWriteCache)
1397         {
1398             m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
1399             AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1400             m_pPrimaryWriteCache = 0;
1401             delete pTemp;
1402         }
1403 
1404         aWriteLock.unlock();
1405         // <- SAFE ----------------------------------
1406     }
1407 
1408     else
1409     {
1410         AcceleratorCache::TKeyList::const_iterator pIt;
1411         AcceleratorCache::TKeyList lSecondaryReadKeys  = m_aSecondaryReadCache.getAllKeys();
1412         AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1413 
1414         for ( pIt  = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
1415         {
1416             if (!m_pSecondaryWriteCache->hasKey(*pIt))
1417                 removeKeyFromConfiguration(*pIt, sal_False);
1418         }
1419 
1420 
1421         for ( pIt  = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
1422         {
1423             ::rtl::OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
1424             if (!m_aSecondaryReadCache.hasKey(*pIt))
1425             {
1426                 insertKeyToConfiguration(*pIt, sCommand, sal_False);
1427             }
1428             else
1429             {
1430                 ::rtl::OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
1431                 if (sReadCommand != sCommand)
1432                     insertKeyToConfiguration(*pIt, sCommand, sal_False);
1433             }
1434         }
1435 
1436         // take over all changes into the original container
1437         // SAFE -> ----------------------------------
1438         WriteGuard aWriteLock(m_aLock);
1439 
1440         if (m_pSecondaryWriteCache)
1441         {
1442             m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
1443             AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1444             m_pSecondaryWriteCache = 0;
1445             delete pTemp;
1446         }
1447 
1448         aWriteLock.unlock();
1449         // <- SAFE ----------------------------------
1450     }
1451 
1452     ::comphelper::ConfigurationHelper::flush(m_xCfg);
1453 }
1454 
1455 //-----------------------------------------------
insertKeyToConfiguration(const css::awt::KeyEvent & aKeyEvent,const::rtl::OUString & sCommand,const sal_Bool bPreferred)1456 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const ::rtl::OUString& sCommand, const sal_Bool bPreferred )
1457 {
1458     css::uno::Reference< css::container::XNameAccess > xAccess;
1459     css::uno::Reference< css::container::XNameContainer > xContainer;
1460     css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1461     css::uno::Reference< css::uno::XInterface > xInst;
1462 
1463     if ( bPreferred )
1464         m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1465     else
1466         m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1467 
1468     if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
1469         xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1470     else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
1471     {
1472         css::uno::Reference< css::container::XNameContainer > xModules;
1473         xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1474         if ( !xModules->hasByName(m_sModuleCFG) )
1475         {
1476             xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xModules, css::uno::UNO_QUERY);
1477             xInst = xFac->createInstance();
1478             xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
1479         }
1480         xModules->getByName(m_sModuleCFG) >>= xContainer;
1481     }
1482 
1483     const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1484     css::uno::Reference< css::container::XNameAccess > xKey;
1485     css::uno::Reference< css::container::XNameContainer > xCommand;
1486     if ( !xContainer->hasByName(sKey) )
1487     {
1488         xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xContainer, css::uno::UNO_QUERY);
1489         xInst = xFac->createInstance();
1490         xContainer->insertByName(sKey, css::uno::makeAny(xInst));
1491     }
1492     xContainer->getByName(sKey) >>= xKey;
1493 
1494     xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1495     ::rtl::OUString sLocale = impl_ts_getLocale().toISO();
1496     if ( !xCommand->hasByName(sLocale) )
1497         xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
1498     else
1499         xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
1500 }
1501 
1502 //-----------------------------------------------
removeKeyFromConfiguration(const css::awt::KeyEvent & aKeyEvent,const sal_Bool bPreferred)1503 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const sal_Bool bPreferred )
1504 {
1505     css::uno::Reference< css::container::XNameAccess > xAccess;
1506     css::uno::Reference< css::container::XNameContainer > xContainer;
1507 
1508     if ( bPreferred )
1509         m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1510     else
1511         m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1512 
1513     if ( m_sGlobalOrModules.equals(CFG_ENTRY_GLOBAL) )
1514         xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1515     else if ( m_sGlobalOrModules.equals(CFG_ENTRY_MODULES) )
1516     {
1517         css::uno::Reference< css::container::XNameAccess > xModules;
1518         xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1519         if ( !xModules->hasByName(m_sModuleCFG) )
1520             return;
1521         xModules->getByName(m_sModuleCFG) >>= xContainer;
1522     }
1523 
1524     const ::rtl::OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1525     xContainer->removeByName(sKey);
1526 }
1527 
1528 //-----------------------------------------------
reloadChanged(const::rtl::OUString & sPrimarySecondary,const::rtl::OUString & sGlobalModules,const::rtl::OUString & sModule,const::rtl::OUString & sKey)1529 void XCUBasedAcceleratorConfiguration::reloadChanged( const ::rtl::OUString& sPrimarySecondary, const ::rtl::OUString& sGlobalModules, const ::rtl::OUString& sModule, const ::rtl::OUString& sKey )
1530 {
1531     css::uno::Reference< css::container::XNameAccess > xAccess;
1532     css::uno::Reference< css::container::XNameContainer > xContainer;
1533 
1534     m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1535     if ( sGlobalModules.equals(CFG_ENTRY_GLOBAL) )
1536         xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1537     else
1538     {
1539         css::uno::Reference< css::container::XNameAccess > xModules;
1540         xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1541         if ( !xModules->hasByName(sModule) )
1542             return;
1543         xModules->getByName(sModule) >>= xContainer;
1544     }
1545 
1546     css::awt::KeyEvent aKeyEvent;
1547     ::rtl::OUString sKeyIdentifier;
1548 
1549     sal_Int32 nIndex = 0;
1550     sKeyIdentifier = sKey.getToken(0, '_', nIndex);
1551     aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(::rtl::OUString::createFromAscii("KEY_")+sKeyIdentifier);
1552 
1553     css::uno::Sequence< ::rtl::OUString > sToken(3);
1554     const sal_Int32 nToken = 3;
1555     for (sal_Int32 i=0; i<nToken; ++i)
1556     {
1557         if ( nIndex < 0 )
1558             break;
1559 
1560         sToken[i] = sKey.getToken(0, '_', nIndex);
1561         if (sToken[i].equalsAscii("SHIFT"))
1562             aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1563         else if (sToken[i].equalsAscii("MOD1"))
1564             aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1565         else if (sToken[i].equalsAscii("MOD2"))
1566             aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1567                 else if (sToken[i].equalsAscii("MOD3"))
1568                         aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1569     }
1570 
1571     css::uno::Reference< css::container::XNameAccess > xKey;
1572     css::uno::Reference< css::container::XNameAccess > xCommand;
1573     ::rtl::OUString sCommand;
1574 
1575     if (xContainer->hasByName(sKey))
1576     {
1577         ::rtl::OUString sLocale = impl_ts_getLocale().toISO();
1578         xContainer->getByName(sKey)    >>= xKey;
1579         xKey->getByName(CFG_PROP_COMMAND)  >>= xCommand;
1580         xCommand->getByName(sLocale)       >>= sCommand;
1581     }
1582 
1583     if (sPrimarySecondary.equals(CFG_ENTRY_PRIMARY))
1584     {
1585         if (sCommand.getLength() ==0)
1586             m_aPrimaryReadCache.removeKey(aKeyEvent);
1587         else
1588             m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1589     }
1590     else if (sPrimarySecondary.equals(CFG_ENTRY_SECONDARY))
1591     {
1592         if (sCommand.getLength() ==0)
1593             m_aSecondaryReadCache.removeKey(aKeyEvent);
1594         else
1595             m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1596     }
1597 }
1598 
1599 //-----------------------------------------------
impl_getCFG(sal_Bool bPreferred,sal_Bool bWriteAccessRequested)1600 AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bPreferred, sal_Bool bWriteAccessRequested)
1601 {
1602     // SAFE -> ----------------------------------
1603     WriteGuard aWriteLock(m_aLock);
1604 
1605     if (bPreferred)
1606     {
1607         //create copy of our readonly-cache, if write access is forced ... but
1608         //not still possible!
1609         if (
1610             (bWriteAccessRequested) &&
1611             (!m_pPrimaryWriteCache       )
1612             )
1613         {
1614             m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
1615         }
1616 
1617         // in case, we have a writeable cache, we use it for reading too!
1618         // Otherwise the API user can't find its own changes ...
1619         if (m_pPrimaryWriteCache)
1620             return *m_pPrimaryWriteCache;
1621         else
1622             return m_aPrimaryReadCache;
1623     }
1624 
1625     else
1626     {
1627         //create copy of our readonly-cache, if write access is forced ... but
1628         //not still possible!
1629         if (
1630             (bWriteAccessRequested) &&
1631             (!m_pSecondaryWriteCache       )
1632             )
1633         {
1634             m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
1635         }
1636 
1637         // in case, we have a writeable cache, we use it for reading too!
1638         // Otherwise the API user can't find its own changes ...
1639         if (m_pSecondaryWriteCache)
1640             return *m_pSecondaryWriteCache;
1641         else
1642             return m_aSecondaryReadCache;
1643     }
1644 
1645     // <- SAFE ----------------------------------
1646 }
1647 
1648 //-----------------------------------------------
impl_ts_getLocale() const1649 ::comphelper::Locale XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1650 {
1651     static ::rtl::OUString LOCALE_PACKAGE = ::rtl::OUString::createFromAscii("/org.openoffice.Setup");
1652     static ::rtl::OUString LOCALE_PATH    = ::rtl::OUString::createFromAscii("L10N"                 );
1653     static ::rtl::OUString LOCALE_KEY     = ::rtl::OUString::createFromAscii("ooLocale"             );
1654 
1655     // SAFE -> ----------------------------------
1656     ReadGuard aReadLock(m_aLock);
1657     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1658     aReadLock.unlock();
1659     // <- SAFE ----------------------------------
1660 
1661     css::uno::Reference< css::uno::XInterface >     xCFG      = fpc::ConfigurationHelper::openConfig(xSMGR, LOCALE_PACKAGE, LOCALE_PATH, fpc::ConfigurationHelper::E_READONLY);
1662     css::uno::Reference< css::beans::XPropertySet > xProp     (xCFG, css::uno::UNO_QUERY_THROW);
1663     ::rtl::OUString                                 sISOLocale;
1664     xProp->getPropertyValue(LOCALE_KEY) >>= sISOLocale;
1665 
1666     if (!sISOLocale.getLength())
1667         return ::comphelper::Locale::EN_US();
1668     return ::comphelper::Locale(sISOLocale);
1669 }
1670 
1671 } // namespace framework
1672