update credits
[LibreOffice.git] / framework / source / accelerators / acceleratorconfiguration.cxx
blob01a43399b8dc6a80027b86870c9c74c10a3622db
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <accelerators/acceleratorconfiguration.hxx>
22 #include <pattern/configuration.hxx>
23 #include <accelerators/presethandler.hxx>
25 #include <xml/saxnamespacefilter.hxx>
26 #include <xml/acceleratorconfigurationreader.hxx>
27 #include <xml/acceleratorconfigurationwriter.hxx>
29 #include <threadhelp/readguard.hxx>
30 #include <threadhelp/writeguard.hxx>
32 #include <acceleratorconst.h>
33 #include <services.h>
35 #include <com/sun/star/xml/sax/Parser.hpp>
36 #include <com/sun/star/xml/sax/InputSource.hpp>
37 #include <com/sun/star/xml/sax/Writer.hpp>
38 #include <com/sun/star/io/XActiveDataSource.hpp>
39 #include <com/sun/star/embed/ElementModes.hpp>
40 #include <com/sun/star/io/XSeekable.hpp>
41 #include <com/sun/star/io/XTruncate.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <vcl/svapp.hxx>
45 #include <com/sun/star/container/XNamed.hpp>
46 #include <com/sun/star/container/XNameContainer.hpp>
47 #include <com/sun/star/awt/KeyEvent.hpp>
48 #include <com/sun/star/awt/KeyModifier.hpp>
49 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
50 #include <com/sun/star/util/XChangesNotifier.hpp>
51 #include <comphelper/componentcontext.hxx>
52 #include <comphelper/configurationhelper.hxx>
53 #include <unotools/configpaths.hxx>
54 #include <rtl/logfile.hxx>
55 #include <svtools/acceleratorexecute.hxx>
56 #include <stdio.h>
59 namespace framework
61 const char CFG_ENTRY_SECONDARY[] = "SecondaryKeys";
62 const char CFG_PROP_COMMAND[] = "Command";
64 #ifdef fpc
65 #error "Who exports this define? I use it as namespace alias ..."
66 #else
67 namespace fpc = ::framework::pattern::configuration;
68 #endif
70 OUString lcl_getKeyString(salhelper::SingletonRef<framework::KeyMapping>& _rKeyMapping, const css::awt::KeyEvent& aKeyEvent)
72 const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of a identifier...
73 OUStringBuffer sKeyBuffer((_rKeyMapping->mapCodeToIdentifier(aKeyEvent.KeyCode)).copy(nBeginIndex));
75 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
76 sKeyBuffer.appendAscii("_SHIFT");
77 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 )
78 sKeyBuffer.appendAscii("_MOD1");
79 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 )
80 sKeyBuffer.appendAscii("_MOD2");
81 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 )
82 sKeyBuffer.appendAscii("_MOD3");
84 return sKeyBuffer.makeStringAndClear();
87 //-----------------------------------------------
88 // XInterface, XTypeProvider
89 DEFINE_XINTERFACE_6(XMLBasedAcceleratorConfiguration ,
90 OWeakObject ,
91 DIRECT_INTERFACE(css::lang::XTypeProvider ),
92 DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration ),
93 DIRECT_INTERFACE(css::form::XReset ),
94 DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
95 DIRECT_INTERFACE(css::ui::XUIConfigurationStorage ),
96 DIRECT_INTERFACE(css::ui::XUIConfiguration ))
98 DEFINE_XTYPEPROVIDER_6(XMLBasedAcceleratorConfiguration ,
99 css::lang::XTypeProvider ,
100 css::ui::XAcceleratorConfiguration ,
101 css::form::XReset ,
102 css::ui::XUIConfigurationPersistence,
103 css::ui::XUIConfigurationStorage ,
104 css::ui::XUIConfiguration )
106 //-----------------------------------------------
107 XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
108 : ThreadHelpBase (&Application::GetSolarMutex())
109 , m_xSMGR (xSMGR )
110 , m_aPresetHandler(xSMGR )
111 , m_pWriteCache (0 )
115 //-----------------------------------------------
116 XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
118 LOG_ASSERT(!m_pWriteCache, "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()\nChanges not flushed. Ignore it ...")
121 //-----------------------------------------------
122 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getAllKeyEvents()
123 throw(css::uno::RuntimeException)
125 // SAFE -> ----------------------------------
126 ReadGuard aReadLock(m_aLock);
128 AcceleratorCache& rCache = impl_getCFG();
129 AcceleratorCache::TKeyList lKeys = rCache.getAllKeys();
130 return lKeys.getAsConstList();
132 // <- SAFE ----------------------------------
135 //-----------------------------------------------
136 OUString SAL_CALL XMLBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
137 throw(css::container::NoSuchElementException,
138 css::uno::RuntimeException )
140 // SAFE -> ----------------------------------
141 ReadGuard aReadLock(m_aLock);
143 AcceleratorCache& rCache = impl_getCFG();
144 if (!rCache.hasKey(aKeyEvent))
145 throw css::container::NoSuchElementException(
146 OUString(),
147 static_cast< ::cppu::OWeakObject* >(this));
148 return rCache.getCommandByKey(aKeyEvent);
150 // <- SAFE ----------------------------------
153 //-----------------------------------------------
154 void SAL_CALL XMLBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
155 const OUString& sCommand )
156 throw(css::lang::IllegalArgumentException,
157 css::uno::RuntimeException )
159 if (
160 (aKeyEvent.KeyCode == 0) &&
161 (aKeyEvent.KeyChar == 0) &&
162 (aKeyEvent.KeyFunc == 0) &&
163 (aKeyEvent.Modifiers == 0)
165 throw css::lang::IllegalArgumentException(
166 OUString("Such key event seams not to be supported by any operating system."),
167 static_cast< ::cppu::OWeakObject* >(this),
170 if (sCommand.isEmpty())
171 throw css::lang::IllegalArgumentException(
172 OUString("Empty command strings are not allowed here."),
173 static_cast< ::cppu::OWeakObject* >(this),
176 // SAFE -> ----------------------------------
177 WriteGuard aWriteLock(m_aLock);
179 AcceleratorCache& rCache = impl_getCFG(sal_True); // sal_True => force getting of a writeable cache!
180 rCache.setKeyCommandPair(aKeyEvent, sCommand);
182 aWriteLock.unlock();
183 // <- SAFE ----------------------------------
186 //-----------------------------------------------
187 void SAL_CALL XMLBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
188 throw(css::container::NoSuchElementException,
189 css::uno::RuntimeException )
191 // SAFE -> ----------------------------------
192 WriteGuard aWriteLock(m_aLock);
194 AcceleratorCache& rCache = impl_getCFG(sal_True); // true => force using of a writeable cache
195 if (!rCache.hasKey(aKeyEvent))
196 throw css::container::NoSuchElementException(
197 OUString(),
198 static_cast< ::cppu::OWeakObject* >(this));
199 rCache.removeKey(aKeyEvent);
201 // <- SAFE ----------------------------------
204 //-----------------------------------------------
205 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
206 throw(css::lang::IllegalArgumentException ,
207 css::container::NoSuchElementException,
208 css::uno::RuntimeException )
210 if (sCommand.isEmpty())
211 throw css::lang::IllegalArgumentException(
212 OUString("Empty command strings are not allowed here."),
213 static_cast< ::cppu::OWeakObject* >(this),
216 // SAFE -> ----------------------------------
217 ReadGuard aReadLock(m_aLock);
219 AcceleratorCache& rCache = impl_getCFG();
220 if (!rCache.hasCommand(sCommand))
221 throw css::container::NoSuchElementException(
222 OUString(),
223 static_cast< ::cppu::OWeakObject* >(this));
225 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(sCommand);
226 return lKeys.getAsConstList();
228 // <- SAFE ----------------------------------
231 //-----------------------------------------------
232 css::uno::Sequence< css::uno::Any > SAL_CALL XMLBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
233 throw(css::lang::IllegalArgumentException ,
234 css::uno::RuntimeException )
236 // SAFE -> ----------------------------------
237 ReadGuard aReadLock(m_aLock);
239 sal_Int32 i = 0;
240 sal_Int32 c = lCommandList.getLength();
241 css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
242 AcceleratorCache& rCache = impl_getCFG();
244 for (i=0; i<c; ++i)
246 const OUString& rCommand = lCommandList[i];
247 if (rCommand.isEmpty())
248 throw css::lang::IllegalArgumentException(
249 OUString("Empty command strings are not allowed here."),
250 static_cast< ::cppu::OWeakObject* >(this),
251 (sal_Int16)i);
253 if (!rCache.hasCommand(rCommand))
254 continue;
256 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
257 if ( lKeys.empty() )
258 continue;
260 css::uno::Any& rAny = lPreferredOnes[i];
261 rAny <<= *(lKeys.begin());
264 aReadLock.unlock();
265 // <- SAFE ----------------------------------
267 return lPreferredOnes;
270 //-----------------------------------------------
271 void SAL_CALL XMLBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const OUString& sCommand)
272 throw(css::lang::IllegalArgumentException ,
273 css::container::NoSuchElementException,
274 css::uno::RuntimeException )
276 if (sCommand.isEmpty())
277 throw css::lang::IllegalArgumentException(
278 OUString("Empty command strings are not allowed here."),
279 static_cast< ::cppu::OWeakObject* >(this),
282 // SAFE -> ----------------------------------
283 WriteGuard aWriteLock(m_aLock);
285 AcceleratorCache& rCache = impl_getCFG(sal_True); // sal_True => force getting of a writeable cache!
286 if (!rCache.hasCommand(sCommand))
287 throw css::container::NoSuchElementException(
288 OUString("Command does not exists inside this container."),
289 static_cast< ::cppu::OWeakObject* >(this));
290 rCache.removeCommand(sCommand);
292 aWriteLock.unlock();
293 // <- SAFE ----------------------------------
296 //-----------------------------------------------
297 void SAL_CALL XMLBasedAcceleratorConfiguration::reload()
298 throw(css::uno::Exception ,
299 css::uno::RuntimeException)
301 css::uno::Reference< css::io::XStream > xStreamNoLang;
303 // SAFE -> ----------------------------------
304 ReadGuard aReadLock(m_aLock);
305 css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
308 xStreamNoLang = m_aPresetHandler.openPreset(PresetHandler::PRESET_DEFAULT(), sal_True);
310 catch(const css::io::IOException&) {} // does not have to exist
311 aReadLock.unlock();
312 // <- SAFE ----------------------------------
314 css::uno::Reference< css::io::XInputStream > xIn;
315 if (xStream.is())
316 xIn = xStream->getInputStream();
317 if (!xIn.is())
318 throw css::io::IOException(
319 OUString("Could not open accelerator configuration for reading."),
320 static_cast< ::cppu::OWeakObject* >(this));
322 // impl_ts_load() does not clear the cache
323 // SAFE -> ----------------------------------
324 WriteGuard aWriteLock(m_aLock);
325 m_aReadCache = AcceleratorCache();
326 aWriteLock.unlock();
327 // <- SAFE ----------------------------------
329 impl_ts_load(xIn);
331 // Load also the general language independent default accelerators
332 // (ignoring the already defined accelerators)
333 if (xStreamNoLang.is())
335 xIn = xStreamNoLang->getInputStream();
336 if (xIn.is())
337 impl_ts_load(xIn);
341 //-----------------------------------------------
342 void SAL_CALL XMLBasedAcceleratorConfiguration::store()
343 throw(css::uno::Exception ,
344 css::uno::RuntimeException)
346 // SAFE -> ----------------------------------
347 ReadGuard aReadLock(m_aLock);
348 css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
349 aReadLock.unlock();
350 // <- SAFE ----------------------------------
352 css::uno::Reference< css::io::XOutputStream > xOut;
353 if (xStream.is())
354 xOut = xStream->getOutputStream();
356 if (!xOut.is())
357 throw css::io::IOException(
358 OUString("Could not open accelerator configuration for saving."),
359 static_cast< ::cppu::OWeakObject* >(this));
361 impl_ts_save(xOut);
363 xOut.clear();
364 xStream.clear();
366 m_aPresetHandler.commitUserChanges();
369 //-----------------------------------------------
370 void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
371 throw(css::uno::Exception ,
372 css::uno::RuntimeException)
374 css::uno::Reference< css::io::XStream > xStream = StorageHolder::openSubStreamWithFallback(
375 xStorage,
376 PresetHandler::TARGET_CURRENT(),
377 css::embed::ElementModes::READWRITE,
378 sal_False); // False => no fallback from read/write to readonly!
379 css::uno::Reference< css::io::XOutputStream > xOut;
380 if (xStream.is())
381 xOut = xStream->getOutputStream();
383 if (!xOut.is())
384 throw css::io::IOException(
385 OUString("Could not open accelerator configuration for saving."),
386 static_cast< ::cppu::OWeakObject* >(this));
388 impl_ts_save(xOut);
390 // TODO inform listener about success, so it can flush the root and sub storage of this stream!
393 //-----------------------------------------------
394 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isModified()
395 throw(css::uno::RuntimeException)
397 // SAFE -> ----------------------------------
398 ReadGuard aReadLock(m_aLock);
399 return (m_pWriteCache != 0);
400 // <- SAFE ----------------------------------
403 //-----------------------------------------------
404 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isReadOnly()
405 throw(css::uno::RuntimeException)
407 // SAFE -> ----------------------------------
408 ReadGuard aReadLock(m_aLock);
409 css::uno::Reference< css::io::XStream > xStream = m_aPresetHandler.openTarget(PresetHandler::TARGET_CURRENT(), sal_True); // sal_True => open or create!
410 aReadLock.unlock();
411 // <- SAFE ----------------------------------
413 css::uno::Reference< css::io::XOutputStream > xOut;
414 if (xStream.is())
415 xOut = xStream->getOutputStream();
416 return !(xOut.is());
419 //-----------------------------------------------
420 void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
421 throw(css::uno::RuntimeException)
423 LOG_WARNING("XMLBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
426 //-----------------------------------------------
427 ::sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::hasStorage()
428 throw(css::uno::RuntimeException)
430 LOG_WARNING("XMLBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
431 return sal_False;
434 //-----------------------------------------------
435 void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
436 throw(css::uno::RuntimeException)
438 LOG_WARNING("XMLBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
441 //-----------------------------------------------
442 void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
443 throw(css::uno::RuntimeException)
445 LOG_WARNING("XMLBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
448 //-----------------------------------------------
449 void SAL_CALL XMLBasedAcceleratorConfiguration::reset()
450 throw(css::uno::RuntimeException)
452 // SAFE -> ----------------------------------
453 WriteGuard aWriteLock(m_aLock);
454 m_aPresetHandler.copyPresetToTarget(PresetHandler::PRESET_DEFAULT(), PresetHandler::TARGET_CURRENT());
455 aWriteLock.unlock();
456 // <- SAFE ----------------------------------
458 reload();
461 //-----------------------------------------------
462 void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
463 throw(css::uno::RuntimeException)
465 LOG_WARNING("XMLBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
468 //-----------------------------------------------
469 void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
470 throw(css::uno::RuntimeException)
472 LOG_WARNING("XMLBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
475 //-----------------------------------------------
476 // IStorageListener
477 void XMLBasedAcceleratorConfiguration::changesOccurred(const OUString& /*sPath*/)
479 reload();
482 //-----------------------------------------------
483 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
485 // SAFE -> ----------------------------------
486 WriteGuard aWriteLock(m_aLock);
488 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
489 if (m_pWriteCache)
491 // be aware of reentrance problems - use temp variable for calling delete ... :-)
492 AcceleratorCache* pTemp = m_pWriteCache;
493 m_pWriteCache = 0;
494 delete pTemp;
497 aWriteLock.unlock();
498 // <- SAFE ----------------------------------
500 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
501 if (xSeek.is())
502 xSeek->seek(0);
504 // add accelerators to the cache (the cache is not cleared)
505 // SAFE -> ----------------------------------
506 aWriteLock.lock();
508 // create the parser queue
509 // Note: Use special filter object between parser and reader
510 // to get filtered xml with right namespaces ...
511 // Use further a temp cache for reading!
512 AcceleratorConfigurationReader* pReader = new AcceleratorConfigurationReader(m_aReadCache);
513 css::uno::Reference< css::xml::sax::XDocumentHandler > xReader (static_cast< ::cppu::OWeakObject* >(pReader), css::uno::UNO_QUERY_THROW);
514 SaxNamespaceFilter* pFilter = new SaxNamespaceFilter(xReader);
515 css::uno::Reference< css::xml::sax::XDocumentHandler > xFilter (static_cast< ::cppu::OWeakObject* >(pFilter), css::uno::UNO_QUERY_THROW);
517 // connect parser, filter and stream
518 css::uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create(comphelper::getComponentContext(xSMGR));
519 xParser->setDocumentHandler(xFilter);
521 css::xml::sax::InputSource aSource;
522 aSource.aInputStream = xStream;
524 // TODO think about error handling
525 xParser->parseStream(aSource);
527 aWriteLock.unlock();
528 // <- SAFE ----------------------------------
531 //-----------------------------------------------
532 void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
534 // SAFE -> ----------------------------------
535 ReadGuard aReadLock(m_aLock);
537 AcceleratorCache aCache;
538 sal_Bool bChanged = (m_pWriteCache != 0);
539 if (bChanged)
540 aCache.takeOver(*m_pWriteCache);
541 else
542 aCache.takeOver(m_aReadCache);
543 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
545 aReadLock.unlock();
546 // <- SAFE ----------------------------------
548 css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
549 xClearable->truncate();
551 // TODO can be removed if seek(0) is done by truncate() automaticly!
552 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
553 if (xSeek.is())
554 xSeek->seek(0);
556 // combine writer/cache/stream etcpp.
557 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(comphelper::getComponentContext(xSMGR));
558 xWriter->setOutputStream(xStream);
560 // write into the stream
561 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
562 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
563 aWriter.flush();
565 // take over all changes into the original container
566 // SAFE -> ----------------------------------
567 WriteGuard aWriteLock(m_aLock);
569 // take over all changes into the readonly cache ...
570 // and forget the copy-on-write copied cache
571 if (bChanged)
573 m_aReadCache.takeOver(*m_pWriteCache);
574 // live with reentrance .-)
575 AcceleratorCache* pTemp = m_pWriteCache;
576 m_pWriteCache = 0;
577 delete pTemp;
580 aWriteLock.unlock();
581 // <- SAFE ----------------------------------
584 //-----------------------------------------------
585 AcceleratorCache& XMLBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bWriteAccessRequested)
587 // SAFE -> ----------------------------------
588 WriteGuard aWriteLock(m_aLock);
590 //create copy of our readonly-cache, if write access is forced ... but
591 //not still possible!
592 if (
593 (bWriteAccessRequested) &&
594 (!m_pWriteCache )
597 m_pWriteCache = new AcceleratorCache(m_aReadCache);
600 // in case, we have a writeable cache, we use it for reading too!
601 // Otherwhise the API user cant find its own changes ...
602 if (m_pWriteCache)
603 return *m_pWriteCache;
604 else
605 return m_aReadCache;
606 // <- SAFE ----------------------------------
609 //-----------------------------------------------
610 OUString XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
612 // SAFE -> ----------------------------------
613 ReadGuard aReadLock(m_aLock);
614 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
615 aReadLock.unlock();
616 // <- SAFE ----------------------------------
618 css::uno::Reference< css::uno::XInterface > xCFG = fpc::ConfigurationHelper::openConfig( comphelper::getComponentContext(xSMGR),
619 "/org.openoffice.Setup", "L10N", fpc::ConfigurationHelper::E_READONLY);
620 css::uno::Reference< css::beans::XPropertySet > xProp (xCFG, css::uno::UNO_QUERY_THROW);
621 OUString sISOLocale;
622 xProp->getPropertyValue("ooLocale") >>= sISOLocale;
624 if (sISOLocale.isEmpty())
625 return OUString("en-US");
626 return sISOLocale;
629 /*******************************************************************************
631 * XCU based accelerator configuration
633 *******************************************************************************/
635 //-----------------------------------------------
636 // XInterface, XTypeProvider
637 DEFINE_XINTERFACE_8(XCUBasedAcceleratorConfiguration ,
638 OWeakObject ,
639 DIRECT_INTERFACE(css::lang::XTypeProvider ),
640 DIRECT_INTERFACE(css::ui::XAcceleratorConfiguration ),
641 DIRECT_INTERFACE(css::util::XChangesListener ),
642 DIRECT_INTERFACE(css::form::XReset ),
643 DIRECT_INTERFACE(css::lang::XComponent ),
644 DIRECT_INTERFACE(css::ui::XUIConfigurationPersistence),
645 DIRECT_INTERFACE(css::ui::XUIConfigurationStorage ),
646 DIRECT_INTERFACE(css::ui::XUIConfiguration ))
648 DEFINE_XTYPEPROVIDER_8(XCUBasedAcceleratorConfiguration ,
649 css::lang::XTypeProvider ,
650 css::ui::XAcceleratorConfiguration ,
651 css::util::XChangesListener ,
652 css::form::XReset ,
653 css::lang::XComponent ,
654 css::ui::XUIConfigurationPersistence,
655 css::ui::XUIConfigurationStorage ,
656 css::ui::XUIConfiguration )
658 //-----------------------------------------------
659 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR)
660 : ThreadHelpBase (&Application::GetSolarMutex())
661 , m_xSMGR (xSMGR )
662 , m_pPrimaryWriteCache(0 )
663 , m_pSecondaryWriteCache(0 )
665 const OUString CFG_ENTRY_ACCELERATORS("org.openoffice.Office.Accelerators");
666 m_xCfg = css::uno::Reference< css::container::XNameAccess > (
667 ::comphelper::ConfigurationHelper::openConfig( comphelper::getComponentContext(m_xSMGR), CFG_ENTRY_ACCELERATORS, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
668 css::uno::UNO_QUERY );
671 //-----------------------------------------------
672 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
676 //-----------------------------------------------
677 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
678 throw(css::uno::RuntimeException)
680 // SAFE -> ----------------------------------
681 ReadGuard aReadLock(m_aLock);
683 AcceleratorCache::TKeyList lKeys = impl_getCFG(sal_True).getAllKeys(); //get keys from PrimaryKeys set
685 AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(sal_False).getAllKeys(); //get keys from SecondaryKeys set
686 lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
687 AcceleratorCache::TKeyList::const_iterator pIt;
688 AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
689 for ( pIt = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
690 lKeys.push_back(*pIt);
692 return lKeys.getAsConstList();
694 // <- SAFE ----------------------------------
697 //-----------------------------------------------
698 OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
699 throw(css::container::NoSuchElementException,
700 css::uno::RuntimeException )
702 // SAFE -> ----------------------------------
703 ReadGuard aReadLock(m_aLock);
705 AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True );
706 AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
708 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
709 throw css::container::NoSuchElementException(
710 OUString(),
711 static_cast< ::cppu::OWeakObject* >(this));
713 if (rPrimaryCache.hasKey(aKeyEvent))
714 return rPrimaryCache.getCommandByKey(aKeyEvent);
715 else
716 return rSecondaryCache.getCommandByKey(aKeyEvent);
718 // <- SAFE ----------------------------------
721 //-----------------------------------------------
722 void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
723 const OUString& sCommand )
724 throw(css::lang::IllegalArgumentException,
725 css::uno::RuntimeException )
727 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::setKeyEvent" );
729 if (
730 (aKeyEvent.KeyCode == 0) &&
731 (aKeyEvent.KeyChar == 0) &&
732 (aKeyEvent.KeyFunc == 0) &&
733 (aKeyEvent.Modifiers == 0)
735 throw css::lang::IllegalArgumentException(
736 OUString("Such key event seams not to be supported by any operating system."),
737 static_cast< ::cppu::OWeakObject* >(this),
740 if (sCommand.isEmpty())
741 throw css::lang::IllegalArgumentException(
742 OUString("Empty command strings are not allowed here."),
743 static_cast< ::cppu::OWeakObject* >(this),
746 // SAFE -> ----------------------------------
747 WriteGuard aWriteLock(m_aLock);
749 AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True, sal_True ); // sal_True => force getting of a writeable cache!
750 AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True); // sal_True => force getting of a writeable cache!
752 if ( rPrimaryCache.hasKey(aKeyEvent) )
754 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
755 if ( sCommand != sOriginalCommand )
757 if (rSecondaryCache.hasCommand(sOriginalCommand))
759 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
760 rSecondaryCache.removeKey(lSecondaryKeys[0]);
761 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
764 if (rPrimaryCache.hasCommand(sCommand))
766 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
767 rPrimaryCache.removeKey(lPrimaryKeys[0]);
768 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
771 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
775 else if ( rSecondaryCache.hasKey(aKeyEvent) )
777 OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
778 if (sCommand != sOriginalCommand)
780 if (rPrimaryCache.hasCommand(sCommand))
782 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
783 rPrimaryCache.removeKey(lPrimaryKeys[0]);
784 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
787 rSecondaryCache.removeKey(aKeyEvent);
788 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
792 else
794 if (rPrimaryCache.hasCommand(sCommand))
796 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
797 rPrimaryCache.removeKey(lPrimaryKeys[0]);
798 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
801 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
804 aWriteLock.unlock();
805 // <- SAFE ----------------------------------
808 //-----------------------------------------------
809 void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
810 throw(css::container::NoSuchElementException,
811 css::uno::RuntimeException )
813 // SAFE -> ----------------------------------
814 WriteGuard aWriteLock(m_aLock);
816 AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True, sal_True );
817 AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
819 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
820 throw css::container::NoSuchElementException(
821 OUString(),
822 static_cast< ::cppu::OWeakObject* >(this));
824 if (rPrimaryCache.hasKey(aKeyEvent))
826 OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
827 if (!sDelCommand.isEmpty())
829 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
830 if (rSecondaryCache.hasCommand(sOriginalCommand))
832 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
833 rSecondaryCache.removeKey(lSecondaryKeys[0]);
834 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
837 rPrimaryCache.removeKey(aKeyEvent);
841 else
843 OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
844 if (!sDelCommand.isEmpty())
845 rSecondaryCache.removeKey(aKeyEvent);
848 // <- SAFE ----------------------------------
851 //-----------------------------------------------
852 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
853 throw(css::lang::IllegalArgumentException ,
854 css::container::NoSuchElementException,
855 css::uno::RuntimeException )
857 if (sCommand.isEmpty())
858 throw css::lang::IllegalArgumentException(
859 OUString("Empty command strings are not allowed here."),
860 static_cast< ::cppu::OWeakObject* >(this),
863 // SAFE -> ----------------------------------
864 ReadGuard aReadLock(m_aLock);
866 AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True );
867 AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False);
869 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
870 throw css::container::NoSuchElementException(
871 OUString(),
872 static_cast< ::cppu::OWeakObject* >(this));
874 AcceleratorCache::TKeyList lKeys = rPrimaryCache.getKeysByCommand(sCommand);
876 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
877 AcceleratorCache::TKeyList::const_iterator pIt;
878 for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
879 lKeys.push_back(*pIt);
881 return lKeys.getAsConstList();
883 // <- SAFE ----------------------------------
886 //-----------------------------------------------
887 AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
889 AcceleratorCache::TKeyList::const_iterator pIt;
890 for ( pIt = lKeys.begin ();
891 pIt != lKeys.end ();
892 ++pIt )
894 const css::awt::KeyEvent& rAWTKey = *pIt;
895 const KeyCode aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
896 const String sName = aVCLKey.GetName();
898 if (sName.Len () > 0)
899 return pIt;
902 return lKeys.end ();
905 //-----------------------------------------------
906 css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
907 throw(css::lang::IllegalArgumentException ,
908 css::uno::RuntimeException )
910 // SAFE -> ----------------------------------
911 ReadGuard aReadLock(m_aLock);
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);
918 for (i=0; i<c; ++i)
920 const OUString& rCommand = lCommandList[i];
921 if (rCommand.isEmpty())
922 throw css::lang::IllegalArgumentException(
923 OUString("Empty command strings are not allowed here."),
924 static_cast< ::cppu::OWeakObject* >(this),
925 (sal_Int16)i);
927 if (!rCache.hasCommand(rCommand))
928 continue;
930 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
931 if ( lKeys.empty() )
932 continue;
934 AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
935 if (pPreferredKey != lKeys.end ())
937 css::uno::Any& rAny = lPreferredOnes[i];
938 rAny <<= *(pPreferredKey);
942 aReadLock.unlock();
943 // <- SAFE ----------------------------------
945 return lPreferredOnes;
948 //-----------------------------------------------
949 void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const OUString& sCommand)
950 throw(css::lang::IllegalArgumentException ,
951 css::container::NoSuchElementException,
952 css::uno::RuntimeException )
954 if (sCommand.isEmpty())
955 throw css::lang::IllegalArgumentException(
956 OUString("Empty command strings are not allowed here."),
957 static_cast< ::cppu::OWeakObject* >(this),
960 // SAFE -> ----------------------------------
961 WriteGuard aWriteLock(m_aLock);
963 AcceleratorCache& rPrimaryCache = impl_getCFG(sal_True, sal_True );
964 AcceleratorCache& rSecondaryCache = impl_getCFG(sal_False, sal_True);
966 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
967 throw css::container::NoSuchElementException(
968 OUString("Command does not exists inside this container."),
969 static_cast< ::cppu::OWeakObject* >(this));
971 if (rPrimaryCache.hasCommand(sCommand))
972 rPrimaryCache.removeCommand(sCommand);
973 if (rSecondaryCache.hasCommand(sCommand))
974 rSecondaryCache.removeCommand(sCommand);
976 aWriteLock.unlock();
977 // <- SAFE ----------------------------------
980 //-----------------------------------------------
981 void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
982 throw(css::uno::Exception ,
983 css::uno::RuntimeException)
985 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::reload()" );
987 // SAFE -> ----------------------------------
988 WriteGuard aWriteLock(m_aLock);
990 sal_Bool bPreferred;
991 css::uno::Reference< css::container::XNameAccess > xAccess;
993 bPreferred = sal_True;
994 m_aPrimaryReadCache = AcceleratorCache();
995 if (m_pPrimaryWriteCache)
997 // be aware of reentrance problems - use temp variable for calling delete ... :-)
998 AcceleratorCache* pTemp = m_pPrimaryWriteCache;
999 m_pPrimaryWriteCache = 0;
1000 delete pTemp;
1002 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1003 impl_ts_load(bPreferred, xAccess); // load the preferred keys
1005 bPreferred = sal_False;
1006 m_aSecondaryReadCache = AcceleratorCache();
1007 if (m_pSecondaryWriteCache)
1009 // be aware of reentrance problems - use temp variable for calling delete ... :-)
1010 AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1011 m_pSecondaryWriteCache = 0;
1012 delete pTemp;
1014 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1015 impl_ts_load(bPreferred, xAccess); // load the secondary keys
1017 aWriteLock.unlock();
1018 // <- SAFE ----------------------------------
1021 //-----------------------------------------------
1022 void SAL_CALL XCUBasedAcceleratorConfiguration::store()
1023 throw(css::uno::Exception ,
1024 css::uno::RuntimeException)
1026 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::store()" );
1028 // SAFE -> ----------------------------------
1029 ReadGuard aReadLock(m_aLock);
1031 sal_Bool bPreferred;
1032 css::uno::Reference< css::container::XNameAccess > xAccess;
1034 bPreferred = sal_True;
1035 // on-demand creation of the primary write cache
1036 impl_getCFG(bPreferred, sal_True);
1037 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1038 impl_ts_save(bPreferred, xAccess);
1040 bPreferred = sal_False;
1041 // on-demand creation of the secondary write cache
1042 impl_getCFG(bPreferred, sal_True);
1043 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1044 impl_ts_save(bPreferred, xAccess);
1046 aReadLock.unlock();
1047 // <- SAFE ----------------------------------
1050 //-----------------------------------------------
1051 void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
1052 throw(css::uno::Exception ,
1053 css::uno::RuntimeException)
1055 // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
1056 if (!xStorage.is())
1057 return;
1059 long nOpenModes = css::embed::ElementModes::READWRITE;
1060 css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement(OUString("accelerator"), nOpenModes);
1061 if (!xAcceleratorTypeStorage.is())
1062 return;
1064 css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement(OUString("current"), nOpenModes);
1065 css::uno::Reference< css::io::XOutputStream > xOut;
1066 if (xStream.is())
1067 xOut = xStream->getOutputStream();
1068 if (!xOut.is())
1069 throw css::io::IOException(
1070 OUString("Could not open accelerator configuration for saving."),
1071 static_cast< ::cppu::OWeakObject* >(this));
1073 // the original m_aCache has been split into primay cache and secondary cache...
1074 // we should merge them before storing to storage
1075 // SAFE -> ----------------------------------
1076 WriteGuard aWriteLock(m_aLock);
1078 AcceleratorCache aCache;
1079 if (m_pPrimaryWriteCache != 0)
1080 aCache.takeOver(*m_pPrimaryWriteCache);
1081 else
1082 aCache.takeOver(m_aPrimaryReadCache);
1084 AcceleratorCache::TKeyList lKeys;
1085 AcceleratorCache::TKeyList::const_iterator pIt;
1086 if (m_pSecondaryWriteCache!=0)
1088 lKeys = m_pSecondaryWriteCache->getAllKeys();
1089 for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1090 aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
1092 else
1094 lKeys = m_aSecondaryReadCache.getAllKeys();
1095 for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
1096 aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
1099 aWriteLock.unlock();
1100 // <- SAFE ----------------------------------
1102 css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
1103 xClearable->truncate();
1104 css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
1105 if (xSeek.is())
1106 xSeek->seek(0);
1108 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(comphelper::getComponentContext(m_xSMGR));
1109 xWriter->setOutputStream(xOut);
1111 // write into the stream
1112 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
1113 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
1114 aWriter.flush();
1117 //-----------------------------------------------
1118 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
1119 throw(css::uno::RuntimeException)
1121 return sal_False;
1124 //-----------------------------------------------
1125 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
1126 throw(css::uno::RuntimeException)
1128 return sal_False;
1131 //-----------------------------------------------
1132 void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
1133 throw(css::uno::RuntimeException)
1135 LOG_WARNING("XCUBasedAcceleratorConfiguration::setStorage()", "TODO implement this HACK .-)")
1138 //-----------------------------------------------
1139 ::sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
1140 throw(css::uno::RuntimeException)
1142 LOG_WARNING("XCUBasedAcceleratorConfiguration::hasStorage()", "TODO implement this HACK .-)")
1143 return sal_False;
1146 //-----------------------------------------------
1147 void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1148 throw(css::uno::RuntimeException)
1150 LOG_WARNING("XCUBasedAcceleratorConfiguration::addConfigurationListener()", "TODO implement me")
1153 //-----------------------------------------------
1154 void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
1155 throw(css::uno::RuntimeException)
1157 LOG_WARNING("XCUBasedAcceleratorConfiguration::removeConfigurationListener()", "TODO implement me")
1160 //-----------------------------------------------
1161 void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
1162 throw(css::uno::RuntimeException)
1164 css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
1165 OUString sConfig = xNamed->getName();
1166 if ( sConfig == "Global" )
1168 m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1169 ::comphelper::ConfigurationHelper::openConfig( comphelper::getComponentContext(m_xSMGR), CFG_ENTRY_GLOBAL, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1170 css::uno::UNO_QUERY );
1171 XCUBasedAcceleratorConfiguration::reload();
1173 else if ( sConfig == "Modules" )
1175 m_xCfg = css::uno::Reference< css::container::XNameAccess > (
1176 ::comphelper::ConfigurationHelper::openConfig( comphelper::getComponentContext(m_xSMGR), CFG_ENTRY_MODULES, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
1177 css::uno::UNO_QUERY );
1178 XCUBasedAcceleratorConfiguration::reload();
1182 //-----------------------------------------------
1183 void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1184 throw(css::uno::RuntimeException)
1186 LOG_WARNING("XCUBasedAcceleratorConfiguration::addResetListener()", "TODO implement me")
1189 //-----------------------------------------------
1190 void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
1191 throw(css::uno::RuntimeException)
1193 LOG_WARNING("XCUBasedAcceleratorConfiguration::removeResetListener()", "TODO implement me")
1196 //-----------------------------------------------
1197 void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
1198 throw(css::uno::RuntimeException)
1200 RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1202 css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
1203 aEvent.Base >>= xHAccess;
1204 if (! xHAccess.is ())
1205 return;
1207 css::util::ChangesEvent aReceivedEvents( aEvent );
1208 const sal_Int32 c = aReceivedEvents.Changes.getLength();
1209 sal_Int32 i = 0;
1210 for (i=0; i<c; ++i)
1212 const css::util::ElementChange& aChange = aReceivedEvents.Changes[i];
1214 // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1215 // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1216 // So we try to split the path into 3 parts (module isnt important here, because we already know it ... because
1217 // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1219 OUString sOrgPath ;
1220 OUString sPath ;
1221 OUString sKey;
1223 aChange.Accessor >>= sOrgPath;
1224 sPath = sOrgPath;
1225 OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1226 OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1228 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1230 OUString sModule;
1231 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1232 if ( !sKey.isEmpty() && !sPath.isEmpty() )
1233 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1235 else if ( sGlobalModules == CFG_ENTRY_MODULES )
1237 OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1238 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1240 if ( !sKey.isEmpty() && !sPath.isEmpty() )
1242 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1248 //-----------------------------------------------
1249 void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
1250 throw(css::uno::RuntimeException)
1254 //-----------------------------------------------
1255 void SAL_CALL XCUBasedAcceleratorConfiguration::dispose()
1256 throw(css::uno::RuntimeException)
1258 // nop
1261 //-----------------------------------------------
1262 void SAL_CALL XCUBasedAcceleratorConfiguration::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /*xListener*/ )
1263 throw(css::uno::RuntimeException)
1265 // nop
1268 //-----------------------------------------------
1269 void SAL_CALL XCUBasedAcceleratorConfiguration::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /*xListener*/ )
1270 throw(css::uno::RuntimeException)
1272 // nop
1275 //-----------------------------------------------
1276 void XCUBasedAcceleratorConfiguration::impl_ts_load( sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
1278 AcceleratorCache aReadCache = AcceleratorCache();
1279 css::uno::Reference< css::container::XNameAccess > xAccess;
1280 if ( m_sGlobalOrModules == "Global" )
1281 xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
1282 else if ( m_sGlobalOrModules == "Modules" )
1284 css::uno::Reference< css::container::XNameAccess > xModules;
1285 xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
1286 xModules->getByName(m_sModuleCFG) >>= xAccess;
1289 const OUString sIsoLang = impl_ts_getLocale();
1290 const OUString sDefaultLocale("en-US");
1292 css::uno::Reference< css::container::XNameAccess > xKey;
1293 css::uno::Reference< css::container::XNameAccess > xCommand;
1294 if (xAccess.is())
1296 css::uno::Sequence< OUString > lKeys = xAccess->getElementNames();
1297 sal_Int32 nKeys = lKeys.getLength();
1298 for ( sal_Int32 i=0; i<nKeys; ++i )
1300 OUString sKey = lKeys[i];
1301 xAccess->getByName(sKey) >>= xKey;
1302 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1304 css::uno::Sequence< OUString > lLocales = xCommand->getElementNames();
1305 sal_Int32 nLocales = lLocales.getLength();
1306 ::std::vector< OUString > aLocales;
1307 for ( sal_Int32 j=0; j<nLocales; ++j )
1308 aLocales.push_back(lLocales[j]);
1310 ::std::vector< OUString >::const_iterator pFound;
1311 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1313 if ( *pFound == sIsoLang )
1314 break;
1317 if ( pFound == aLocales.end() )
1319 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1321 if ( *pFound == sDefaultLocale )
1322 break;
1325 if ( pFound == aLocales.end() )
1326 continue;
1329 OUString sLocale = *pFound;
1330 OUString sCommand;
1331 xCommand->getByName(sLocale) >>= sCommand;
1332 if (sCommand.isEmpty())
1333 continue;
1335 css::awt::KeyEvent aKeyEvent;
1337 sal_Int32 nIndex = 0;
1338 OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
1339 OUString sPrefix("KEY_");
1340 aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sPrefix + sKeyCommand);
1342 css::uno::Sequence< OUString > sToken(4);
1343 const sal_Int32 nToken = 4;
1344 sal_Bool bValid = sal_True;
1345 sal_Int32 k;
1346 for (k=0; k<nToken; ++k)
1348 if (nIndex < 0)
1349 break;
1351 sToken[k] = sKey.getToken(0, '_', nIndex);
1352 if (sToken[k].isEmpty())
1354 bValid = sal_False;
1355 break;
1358 if ( sToken[k] == "SHIFT" )
1359 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1360 else if ( sToken[k] == "MOD1" )
1361 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1362 else if ( sToken[k] == "MOD2" )
1363 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1364 else if ( sToken[k] == "MOD3" )
1365 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1366 else
1368 bValid = sal_False;
1369 break;
1373 if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1374 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1378 if (bPreferred)
1379 m_aPrimaryReadCache.takeOver(aReadCache);
1380 else
1381 m_aSecondaryReadCache.takeOver(aReadCache);
1384 //-----------------------------------------------
1385 void XCUBasedAcceleratorConfiguration::impl_ts_save(sal_Bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
1387 if (bPreferred)
1389 AcceleratorCache::TKeyList::const_iterator pIt;
1390 AcceleratorCache::TKeyList lPrimaryReadKeys = m_aPrimaryReadCache.getAllKeys();
1391 AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1393 for ( pIt = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
1395 if (!m_pPrimaryWriteCache->hasKey(*pIt))
1396 removeKeyFromConfiguration(*pIt, sal_True);
1399 for ( pIt = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
1401 OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
1402 if (!m_aPrimaryReadCache.hasKey(*pIt))
1404 insertKeyToConfiguration(*pIt, sCommand, sal_True);
1406 else
1408 OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
1409 if (sReadCommand != sCommand)
1410 insertKeyToConfiguration(*pIt, sCommand, sal_True);
1414 // take over all changes into the original container
1415 // SAFE -> ----------------------------------
1416 WriteGuard aWriteLock(m_aLock);
1418 if (m_pPrimaryWriteCache)
1420 m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
1421 AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1422 m_pPrimaryWriteCache = 0;
1423 delete pTemp;
1426 aWriteLock.unlock();
1427 // <- SAFE ----------------------------------
1430 else
1432 AcceleratorCache::TKeyList::const_iterator pIt;
1433 AcceleratorCache::TKeyList lSecondaryReadKeys = m_aSecondaryReadCache.getAllKeys();
1434 AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1436 for ( pIt = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
1438 if (!m_pSecondaryWriteCache->hasKey(*pIt))
1439 removeKeyFromConfiguration(*pIt, sal_False);
1443 for ( pIt = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
1445 OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
1446 if (!m_aSecondaryReadCache.hasKey(*pIt))
1448 insertKeyToConfiguration(*pIt, sCommand, sal_False);
1450 else
1452 OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
1453 if (sReadCommand != sCommand)
1454 insertKeyToConfiguration(*pIt, sCommand, sal_False);
1458 // take over all changes into the original container
1459 // SAFE -> ----------------------------------
1460 WriteGuard aWriteLock(m_aLock);
1462 if (m_pSecondaryWriteCache)
1464 m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
1465 AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1466 m_pSecondaryWriteCache = 0;
1467 delete pTemp;
1470 aWriteLock.unlock();
1471 // <- SAFE ----------------------------------
1474 ::comphelper::ConfigurationHelper::flush(m_xCfg);
1477 //-----------------------------------------------
1478 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const OUString& sCommand, const sal_Bool bPreferred )
1480 css::uno::Reference< css::container::XNameAccess > xAccess;
1481 css::uno::Reference< css::container::XNameContainer > xContainer;
1482 css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1483 css::uno::Reference< css::uno::XInterface > xInst;
1485 if ( bPreferred )
1486 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1487 else
1488 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1490 if ( m_sGlobalOrModules == CFG_ENTRY_GLOBAL )
1491 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1492 else if ( m_sGlobalOrModules == CFG_ENTRY_MODULES )
1494 css::uno::Reference< css::container::XNameContainer > xModules;
1495 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1496 if ( !xModules->hasByName(m_sModuleCFG) )
1498 xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xModules, css::uno::UNO_QUERY);
1499 xInst = xFac->createInstance();
1500 xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
1502 xModules->getByName(m_sModuleCFG) >>= xContainer;
1505 const OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1506 css::uno::Reference< css::container::XNameAccess > xKey;
1507 css::uno::Reference< css::container::XNameContainer > xCommand;
1508 if ( !xContainer->hasByName(sKey) )
1510 xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xContainer, css::uno::UNO_QUERY);
1511 xInst = xFac->createInstance();
1512 xContainer->insertByName(sKey, css::uno::makeAny(xInst));
1514 xContainer->getByName(sKey) >>= xKey;
1516 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1517 OUString sLocale = impl_ts_getLocale();
1518 if ( !xCommand->hasByName(sLocale) )
1519 xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
1520 else
1521 xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
1524 //-----------------------------------------------
1525 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const sal_Bool bPreferred )
1527 css::uno::Reference< css::container::XNameAccess > xAccess;
1528 css::uno::Reference< css::container::XNameContainer > xContainer;
1530 if ( bPreferred )
1531 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1532 else
1533 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1535 if ( m_sGlobalOrModules == CFG_ENTRY_GLOBAL )
1536 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1537 else if ( m_sGlobalOrModules == CFG_ENTRY_MODULES )
1539 css::uno::Reference< css::container::XNameAccess > xModules;
1540 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1541 if ( !xModules->hasByName(m_sModuleCFG) )
1542 return;
1543 xModules->getByName(m_sModuleCFG) >>= xContainer;
1546 const OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1547 xContainer->removeByName(sKey);
1550 //-----------------------------------------------
1551 void XCUBasedAcceleratorConfiguration::reloadChanged( const OUString& sPrimarySecondary, const OUString& sGlobalModules, const OUString& sModule, const OUString& sKey )
1553 css::uno::Reference< css::container::XNameAccess > xAccess;
1554 css::uno::Reference< css::container::XNameContainer > xContainer;
1556 m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1557 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1558 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1559 else
1561 css::uno::Reference< css::container::XNameAccess > xModules;
1562 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1563 if ( !xModules->hasByName(sModule) )
1564 return;
1565 xModules->getByName(sModule) >>= xContainer;
1568 css::awt::KeyEvent aKeyEvent;
1569 OUString sKeyIdentifier;
1571 sal_Int32 nIndex = 0;
1572 sKeyIdentifier = sKey.getToken(0, '_', nIndex);
1573 aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(OUString("KEY_")+sKeyIdentifier);
1575 css::uno::Sequence< OUString > sToken(3);
1576 const sal_Int32 nToken = 3;
1577 for (sal_Int32 i=0; i<nToken; ++i)
1579 if ( nIndex < 0 )
1580 break;
1582 sToken[i] = sKey.getToken(0, '_', nIndex);
1583 if ( sToken[i] == "SHIFT" )
1584 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1585 else if ( sToken[i] == "MOD1" )
1586 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1587 else if ( sToken[i] == "MOD2" )
1588 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1589 else if ( sToken[i] == "MOD3" )
1590 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1593 css::uno::Reference< css::container::XNameAccess > xKey;
1594 css::uno::Reference< css::container::XNameAccess > xCommand;
1595 OUString sCommand;
1597 if (xContainer->hasByName(sKey))
1599 OUString sLocale = impl_ts_getLocale();
1600 xContainer->getByName(sKey) >>= xKey;
1601 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1602 xCommand->getByName(sLocale) >>= sCommand;
1605 if ( sPrimarySecondary == CFG_ENTRY_PRIMARY )
1607 if (sCommand.isEmpty())
1608 m_aPrimaryReadCache.removeKey(aKeyEvent);
1609 else
1610 m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1612 else if ( sPrimarySecondary == CFG_ENTRY_SECONDARY )
1614 if (sCommand.isEmpty())
1615 m_aSecondaryReadCache.removeKey(aKeyEvent);
1616 else
1617 m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1621 //-----------------------------------------------
1622 AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(sal_Bool bPreferred, sal_Bool bWriteAccessRequested)
1624 // SAFE -> ----------------------------------
1625 WriteGuard aWriteLock(m_aLock);
1627 if (bPreferred)
1629 //create copy of our readonly-cache, if write access is forced ... but
1630 //not still possible!
1631 if (
1632 (bWriteAccessRequested) &&
1633 (!m_pPrimaryWriteCache )
1636 m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
1639 // in case, we have a writeable cache, we use it for reading too!
1640 // Otherwhise the API user cant find its own changes ...
1641 if (m_pPrimaryWriteCache)
1642 return *m_pPrimaryWriteCache;
1643 else
1644 return m_aPrimaryReadCache;
1647 else
1649 //create copy of our readonly-cache, if write access is forced ... but
1650 //not still possible!
1651 if (
1652 (bWriteAccessRequested) &&
1653 (!m_pSecondaryWriteCache )
1656 m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
1659 // in case, we have a writeable cache, we use it for reading too!
1660 // Otherwhise the API user cant find its own changes ...
1661 if (m_pSecondaryWriteCache)
1662 return *m_pSecondaryWriteCache;
1663 else
1664 return m_aSecondaryReadCache;
1667 // <- SAFE ----------------------------------
1670 //-----------------------------------------------
1671 OUString XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1673 // SAFE -> ----------------------------------
1674 ReadGuard aReadLock(m_aLock);
1675 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
1676 aReadLock.unlock();
1677 // <- SAFE ----------------------------------
1679 css::uno::Reference< css::uno::XInterface > xCFG = fpc::ConfigurationHelper::openConfig( comphelper::getComponentContext(xSMGR),
1680 "/org.openoffice.Setup", "L10N", fpc::ConfigurationHelper::E_READONLY);
1681 css::uno::Reference< css::beans::XPropertySet > xProp (xCFG, css::uno::UNO_QUERY_THROW);
1682 OUString sISOLocale;
1683 xProp->getPropertyValue("ooLocale") >>= sISOLocale;
1685 if (sISOLocale.isEmpty())
1686 return OUString("en-US");
1687 return sISOLocale;
1690 } // namespace framework
1692 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */