build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / framework / source / accelerators / acceleratorconfiguration.cxx
blob3e27f5c8c85f0722bf931334ffa304d53fec377d
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>
21 #include <accelerators/keymapping.hxx>
22 #include <accelerators/presethandler.hxx>
24 #include <xml/saxnamespacefilter.hxx>
25 #include <xml/acceleratorconfigurationreader.hxx>
26 #include <xml/acceleratorconfigurationwriter.hxx>
28 #include <acceleratorconst.h>
29 #include <services.h>
31 #include <com/sun/star/xml/sax/Parser.hpp>
32 #include <com/sun/star/xml/sax/InputSource.hpp>
33 #include <com/sun/star/xml/sax/Writer.hpp>
34 #include <com/sun/star/io/XActiveDataSource.hpp>
35 #include <com/sun/star/embed/ElementModes.hpp>
36 #include <com/sun/star/io/XSeekable.hpp>
37 #include <com/sun/star/io/XTruncate.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <vcl/svapp.hxx>
41 #include <com/sun/star/container/XNamed.hpp>
42 #include <com/sun/star/container/XNameContainer.hpp>
43 #include <com/sun/star/awt/KeyEvent.hpp>
44 #include <com/sun/star/awt/KeyModifier.hpp>
45 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
46 #include <comphelper/configurationhelper.hxx>
47 #include <comphelper/sequence.hxx>
48 #include <officecfg/Setup.hxx>
49 #include <unotools/configpaths.hxx>
50 #include <svtools/acceleratorexecute.hxx>
52 #define PRESET_DEFAULT "default"
53 #define TARGET_CURRENT "current"
55 namespace framework
57 const char CFG_ENTRY_SECONDARY[] = "SecondaryKeys";
58 const char CFG_PROP_COMMAND[] = "Command";
60 OUString lcl_getKeyString(const css::awt::KeyEvent& aKeyEvent)
62 const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of a identifier...
63 OUStringBuffer sKeyBuffer((KeyMapping::get().mapCodeToIdentifier(aKeyEvent.KeyCode)).copy(nBeginIndex));
65 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
66 sKeyBuffer.append("_SHIFT");
67 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 )
68 sKeyBuffer.append("_MOD1");
69 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 )
70 sKeyBuffer.append("_MOD2");
71 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 )
72 sKeyBuffer.append("_MOD3");
74 return sKeyBuffer.makeStringAndClear();
77 XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext >& xContext)
78 : m_xContext (xContext )
79 , m_aPresetHandler(xContext )
80 , m_pWriteCache (nullptr )
84 XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
86 SAL_WARN_IF(m_pWriteCache, "fwk", "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration(): Changes not flushed. Ignore it ...");
89 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getAllKeyEvents()
90 throw(css::uno::RuntimeException, std::exception)
92 SolarMutexGuard g;
93 AcceleratorCache& rCache = impl_getCFG();
94 AcceleratorCache::TKeyList lKeys = rCache.getAllKeys();
95 return comphelper::containerToSequence(lKeys);
98 OUString SAL_CALL XMLBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
99 throw(css::container::NoSuchElementException,
100 css::uno::RuntimeException, std::exception )
102 SolarMutexGuard g;
103 AcceleratorCache& rCache = impl_getCFG();
104 if (!rCache.hasKey(aKeyEvent))
105 throw css::container::NoSuchElementException(
106 OUString(),
107 static_cast< ::cppu::OWeakObject* >(this));
108 return rCache.getCommandByKey(aKeyEvent);
111 void SAL_CALL XMLBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
112 const OUString& sCommand )
113 throw(css::lang::IllegalArgumentException,
114 css::uno::RuntimeException, std::exception )
116 if (
117 (aKeyEvent.KeyCode == 0) &&
118 (aKeyEvent.KeyChar == 0) &&
119 (aKeyEvent.KeyFunc == 0) &&
120 (aKeyEvent.Modifiers == 0)
122 throw css::lang::IllegalArgumentException(
123 OUString("Such key event seems not to be supported by any operating system."),
124 static_cast< ::cppu::OWeakObject* >(this),
127 if (sCommand.isEmpty())
128 throw css::lang::IllegalArgumentException(
129 OUString("Empty command strings are not allowed here."),
130 static_cast< ::cppu::OWeakObject* >(this),
133 SolarMutexGuard g;
134 AcceleratorCache& rCache = impl_getCFG(true); // sal_True => force getting of a writeable cache!
135 rCache.setKeyCommandPair(aKeyEvent, sCommand);
138 void SAL_CALL XMLBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
139 throw(css::container::NoSuchElementException,
140 css::uno::RuntimeException, std::exception )
142 SolarMutexGuard g;
143 AcceleratorCache& rCache = impl_getCFG(true); // true => force using of a writeable cache
144 if (!rCache.hasKey(aKeyEvent))
145 throw css::container::NoSuchElementException(
146 OUString(),
147 static_cast< ::cppu::OWeakObject* >(this));
148 rCache.removeKey(aKeyEvent);
151 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
152 throw(css::lang::IllegalArgumentException ,
153 css::container::NoSuchElementException,
154 css::uno::RuntimeException, std::exception )
156 if (sCommand.isEmpty())
157 throw css::lang::IllegalArgumentException(
158 OUString("Empty command strings are not allowed here."),
159 static_cast< ::cppu::OWeakObject* >(this),
162 SolarMutexGuard g;
163 AcceleratorCache& rCache = impl_getCFG();
164 if (!rCache.hasCommand(sCommand))
165 throw css::container::NoSuchElementException(
166 OUString(),
167 static_cast< ::cppu::OWeakObject* >(this));
169 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(sCommand);
170 return comphelper::containerToSequence(lKeys);
173 css::uno::Sequence< css::uno::Any > SAL_CALL XMLBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
174 throw (css::lang::IllegalArgumentException, css::container::NoSuchElementException,
175 css::uno::RuntimeException, std::exception)
177 SolarMutexGuard g;
179 sal_Int32 i = 0;
180 sal_Int32 c = lCommandList.getLength();
181 css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // don't pack list!
182 AcceleratorCache& rCache = impl_getCFG();
184 for (i=0; i<c; ++i)
186 const OUString& rCommand = lCommandList[i];
187 if (rCommand.isEmpty())
188 throw css::lang::IllegalArgumentException(
189 OUString("Empty command strings are not allowed here."),
190 static_cast< ::cppu::OWeakObject* >(this),
191 (sal_Int16)i);
193 if (!rCache.hasCommand(rCommand))
194 continue;
196 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
197 if ( lKeys.empty() )
198 continue;
200 css::uno::Any& rAny = lPreferredOnes[i];
201 rAny <<= *(lKeys.begin());
204 return lPreferredOnes;
207 void SAL_CALL XMLBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const OUString& sCommand)
208 throw(css::lang::IllegalArgumentException ,
209 css::container::NoSuchElementException,
210 css::uno::RuntimeException, std::exception )
212 if (sCommand.isEmpty())
213 throw css::lang::IllegalArgumentException(
214 OUString("Empty command strings are not allowed here."),
215 static_cast< ::cppu::OWeakObject* >(this),
218 SolarMutexGuard g;
219 AcceleratorCache& rCache = impl_getCFG(true); // sal_True => force getting of a writeable cache!
220 if (!rCache.hasCommand(sCommand))
221 throw css::container::NoSuchElementException(
222 OUString("Command does not exists inside this container."),
223 static_cast< ::cppu::OWeakObject* >(this));
224 rCache.removeCommand(sCommand);
227 void SAL_CALL XMLBasedAcceleratorConfiguration::reload()
228 throw(css::uno::Exception ,
229 css::uno::RuntimeException, std::exception)
231 css::uno::Reference< css::io::XStream > xStream;
232 css::uno::Reference< css::io::XStream > xStreamNoLang;
234 SolarMutexGuard g;
235 xStream = m_aPresetHandler.openTarget(TARGET_CURRENT,
236 css::embed::ElementModes::READ);
239 xStreamNoLang = m_aPresetHandler.openPreset(PRESET_DEFAULT);
241 catch(const css::io::IOException&) {} // does not have to exist
244 css::uno::Reference< css::io::XInputStream > xIn;
245 if (xStream.is())
246 xIn = xStream->getInputStream();
247 if (!xIn.is())
248 throw css::io::IOException(
249 OUString("Could not open accelerator configuration for reading."),
250 static_cast< ::cppu::OWeakObject* >(this));
252 // impl_ts_load() does not clear the cache
254 SolarMutexGuard g;
255 m_aReadCache = AcceleratorCache();
258 impl_ts_load(xIn);
260 // Load also the general language independent default accelerators
261 // (ignoring the already defined accelerators)
262 if (xStreamNoLang.is())
264 xIn = xStreamNoLang->getInputStream();
265 if (xIn.is())
266 impl_ts_load(xIn);
270 void SAL_CALL XMLBasedAcceleratorConfiguration::store()
271 throw(css::uno::Exception ,
272 css::uno::RuntimeException, std::exception)
274 css::uno::Reference< css::io::XStream > xStream;
276 SolarMutexGuard g;
277 xStream = m_aPresetHandler.openTarget(TARGET_CURRENT,
278 css::embed::ElementModes::READWRITE); // open or create!
281 css::uno::Reference< css::io::XOutputStream > xOut;
282 if (xStream.is())
283 xOut = xStream->getOutputStream();
285 if (!xOut.is())
286 throw css::io::IOException(
287 OUString("Could not open accelerator configuration for saving."),
288 static_cast< ::cppu::OWeakObject* >(this));
290 impl_ts_save(xOut);
292 xOut.clear();
293 xStream.clear();
295 m_aPresetHandler.commitUserChanges();
298 void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
299 throw(css::uno::Exception ,
300 css::uno::RuntimeException, std::exception)
302 css::uno::Reference< css::io::XStream > xStream = StorageHolder::openSubStreamWithFallback(
303 xStorage,
304 TARGET_CURRENT,
305 css::embed::ElementModes::READWRITE,
306 false); // False => no fallback from read/write to readonly!
307 css::uno::Reference< css::io::XOutputStream > xOut;
308 if (xStream.is())
309 xOut = xStream->getOutputStream();
311 if (!xOut.is())
312 throw css::io::IOException(
313 OUString("Could not open accelerator configuration for saving."),
314 static_cast< ::cppu::OWeakObject* >(this));
316 impl_ts_save(xOut);
318 // TODO inform listener about success, so it can flush the root and sub storage of this stream!
321 sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isModified()
322 throw(css::uno::RuntimeException, std::exception)
324 SolarMutexGuard g;
325 return (m_pWriteCache != nullptr);
328 sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isReadOnly()
329 throw(css::uno::RuntimeException, std::exception)
331 css::uno::Reference< css::io::XStream > xStream;
333 SolarMutexGuard g;
334 xStream = m_aPresetHandler.openTarget(TARGET_CURRENT,
335 css::embed::ElementModes::READWRITE); // open or create!
338 css::uno::Reference< css::io::XOutputStream > xOut;
339 if (xStream.is())
340 xOut = xStream->getOutputStream();
341 return !(xOut.is());
344 void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
345 throw(css::uno::RuntimeException, std::exception)
347 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
350 sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::hasStorage()
351 throw(css::uno::RuntimeException, std::exception)
353 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
354 return false;
357 void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
358 throw(css::uno::RuntimeException, std::exception)
360 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
363 void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
364 throw(css::uno::RuntimeException, std::exception)
366 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
369 void SAL_CALL XMLBasedAcceleratorConfiguration::reset()
370 throw(css::uno::RuntimeException, std::exception)
373 SolarMutexGuard g;
374 m_aPresetHandler.copyPresetToTarget(PRESET_DEFAULT, TARGET_CURRENT);
377 reload();
380 void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
381 throw(css::uno::RuntimeException, std::exception)
383 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::addResetListener(): implement me");
386 void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
387 throw(css::uno::RuntimeException, std::exception)
389 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::removeResetListener(): implement me");
392 // IStorageListener
393 void XMLBasedAcceleratorConfiguration::changesOccurred()
395 reload();
398 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
400 css::uno::Reference< css::uno::XComponentContext > xContext;
402 SolarMutexGuard g;
403 xContext = m_xContext;
404 if (m_pWriteCache)
406 // be aware of reentrance problems - use temp variable for calling delete ... :-)
407 AcceleratorCache* pTemp = m_pWriteCache;
408 m_pWriteCache = nullptr;
409 delete pTemp;
413 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
414 if (xSeek.is())
415 xSeek->seek(0);
417 SolarMutexGuard g;
419 // create the parser queue
420 // Note: Use special filter object between parser and reader
421 // to get filtered xml with right namespaces ...
422 // Use further a temp cache for reading!
423 AcceleratorConfigurationReader* pReader = new AcceleratorConfigurationReader(m_aReadCache);
424 css::uno::Reference< css::xml::sax::XDocumentHandler > xReader (static_cast< ::cppu::OWeakObject* >(pReader), css::uno::UNO_QUERY_THROW);
425 SaxNamespaceFilter* pFilter = new SaxNamespaceFilter(xReader);
426 css::uno::Reference< css::xml::sax::XDocumentHandler > xFilter (static_cast< ::cppu::OWeakObject* >(pFilter), css::uno::UNO_QUERY_THROW);
428 // connect parser, filter and stream
429 css::uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create(xContext);
430 xParser->setDocumentHandler(xFilter);
432 css::xml::sax::InputSource aSource;
433 aSource.aInputStream = xStream;
435 // TODO think about error handling
436 xParser->parseStream(aSource);
439 void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
441 bool bChanged;
442 AcceleratorCache aCache;
443 css::uno::Reference< css::uno::XComponentContext > xContext;
445 SolarMutexGuard g;
446 bChanged = (m_pWriteCache != nullptr);
447 if (bChanged)
448 aCache.takeOver(*m_pWriteCache);
449 else
450 aCache.takeOver(m_aReadCache);
451 xContext = m_xContext;
454 css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
455 xClearable->truncate();
457 // TODO can be removed if seek(0) is done by truncate() automatically!
458 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
459 if (xSeek.is())
460 xSeek->seek(0);
462 // combine writer/cache/stream etcpp.
463 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(xContext);
464 xWriter->setOutputStream(xStream);
466 // write into the stream
467 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
468 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
469 aWriter.flush();
471 SolarMutexGuard g;
472 // take over all changes into the readonly cache ...
473 // and forget the copy-on-write copied cache
474 if (bChanged)
476 m_aReadCache.takeOver(*m_pWriteCache);
477 // live with reentrance .-)
478 AcceleratorCache* pTemp = m_pWriteCache;
479 m_pWriteCache = nullptr;
480 delete pTemp;
484 AcceleratorCache& XMLBasedAcceleratorConfiguration::impl_getCFG(bool bWriteAccessRequested)
486 SolarMutexGuard g;
488 //create copy of our readonly-cache, if write access is forced ... but
489 //not still possible!
490 if (
491 (bWriteAccessRequested) &&
492 (!m_pWriteCache )
495 m_pWriteCache = new AcceleratorCache(m_aReadCache);
498 // in case, we have a writeable cache, we use it for reading too!
499 // Otherwise the API user can't find its own changes ...
500 if (m_pWriteCache)
501 return *m_pWriteCache;
502 else
503 return m_aReadCache;
506 OUString XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
508 OUString sISOLocale = officecfg::Setup::L10N::ooLocale::get();
510 if (sISOLocale.isEmpty())
511 return OUString("en-US");
512 return sISOLocale;
515 /*******************************************************************************
517 * XCU based accelerator configuration
519 *******************************************************************************/
521 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext >& xContext)
522 : m_xContext (xContext )
523 , m_pPrimaryWriteCache(nullptr )
524 , m_pSecondaryWriteCache(nullptr )
526 const OUString CFG_ENTRY_ACCELERATORS("org.openoffice.Office.Accelerators");
527 m_xCfg.set(
528 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_ACCELERATORS, ::comphelper::EConfigurationModes::AllLocales ),
529 css::uno::UNO_QUERY );
532 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
536 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
537 throw(css::uno::RuntimeException, std::exception)
539 SolarMutexGuard g;
541 AcceleratorCache::TKeyList lKeys = impl_getCFG(true).getAllKeys(); //get keys from PrimaryKeys set
543 AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(false).getAllKeys(); //get keys from SecondaryKeys set
544 lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
545 AcceleratorCache::TKeyList::const_iterator pIt;
546 AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
547 for ( pIt = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
548 lKeys.push_back(*pIt);
550 return comphelper::containerToSequence(lKeys);
553 OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
554 throw(css::container::NoSuchElementException,
555 css::uno::RuntimeException, std::exception )
557 SolarMutexGuard g;
559 AcceleratorCache& rPrimaryCache = impl_getCFG(true );
560 AcceleratorCache& rSecondaryCache = impl_getCFG(false);
562 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
563 throw css::container::NoSuchElementException(
564 OUString(),
565 static_cast< ::cppu::OWeakObject* >(this));
567 if (rPrimaryCache.hasKey(aKeyEvent))
568 return rPrimaryCache.getCommandByKey(aKeyEvent);
569 else
570 return rSecondaryCache.getCommandByKey(aKeyEvent);
573 void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
574 const OUString& sCommand )
575 throw (css::lang::IllegalArgumentException,
576 css::container::NoSuchElementException,
577 css::uno::RuntimeException, std::exception)
579 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::setKeyEvent" );
581 if (
582 (aKeyEvent.KeyCode == 0) &&
583 (aKeyEvent.KeyChar == 0) &&
584 (aKeyEvent.KeyFunc == 0) &&
585 (aKeyEvent.Modifiers == 0)
587 throw css::lang::IllegalArgumentException(
588 OUString("Such key event seems not to be supported by any operating system."),
589 static_cast< ::cppu::OWeakObject* >(this),
592 if (sCommand.isEmpty())
593 throw css::lang::IllegalArgumentException(
594 OUString("Empty command strings are not allowed here."),
595 static_cast< ::cppu::OWeakObject* >(this),
598 SolarMutexGuard g;
600 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true ); // sal_True => force getting of a writeable cache!
601 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true); // sal_True => force getting of a writeable cache!
603 if ( rPrimaryCache.hasKey(aKeyEvent) )
605 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
606 if ( sCommand != sOriginalCommand )
608 if (rSecondaryCache.hasCommand(sOriginalCommand))
610 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
611 rSecondaryCache.removeKey(lSecondaryKeys[0]);
612 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
615 if (rPrimaryCache.hasCommand(sCommand))
617 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
618 rPrimaryCache.removeKey(lPrimaryKeys[0]);
619 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
622 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
626 else if ( rSecondaryCache.hasKey(aKeyEvent) )
628 OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
629 if (sCommand != sOriginalCommand)
631 if (rPrimaryCache.hasCommand(sCommand))
633 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
634 rPrimaryCache.removeKey(lPrimaryKeys[0]);
635 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
638 rSecondaryCache.removeKey(aKeyEvent);
639 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
643 else
645 if (rPrimaryCache.hasCommand(sCommand))
647 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
648 rPrimaryCache.removeKey(lPrimaryKeys[0]);
649 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
652 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
656 void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
657 throw(css::container::NoSuchElementException,
658 css::uno::RuntimeException, std::exception )
660 SolarMutexGuard g;
662 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true );
663 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true);
665 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
666 throw css::container::NoSuchElementException(
667 OUString(),
668 static_cast< ::cppu::OWeakObject* >(this));
670 if (rPrimaryCache.hasKey(aKeyEvent))
672 OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
673 if (!sDelCommand.isEmpty())
675 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
676 if (rSecondaryCache.hasCommand(sOriginalCommand))
678 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
679 rSecondaryCache.removeKey(lSecondaryKeys[0]);
680 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
683 rPrimaryCache.removeKey(aKeyEvent);
687 else
689 OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
690 if (!sDelCommand.isEmpty())
691 rSecondaryCache.removeKey(aKeyEvent);
695 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
696 throw(css::lang::IllegalArgumentException ,
697 css::container::NoSuchElementException,
698 css::uno::RuntimeException, std::exception )
700 if (sCommand.isEmpty())
701 throw css::lang::IllegalArgumentException(
702 OUString("Empty command strings are not allowed here."),
703 static_cast< ::cppu::OWeakObject* >(this),
706 SolarMutexGuard g;
708 AcceleratorCache& rPrimaryCache = impl_getCFG(true );
709 AcceleratorCache& rSecondaryCache = impl_getCFG(false);
711 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
712 throw css::container::NoSuchElementException(
713 OUString(),
714 static_cast< ::cppu::OWeakObject* >(this));
716 AcceleratorCache::TKeyList lKeys = rPrimaryCache.getKeysByCommand(sCommand);
718 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
719 AcceleratorCache::TKeyList::const_iterator pIt;
720 for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
721 lKeys.push_back(*pIt);
723 return comphelper::containerToSequence(lKeys);
726 AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
728 AcceleratorCache::TKeyList::const_iterator pIt;
729 for ( pIt = lKeys.begin ();
730 pIt != lKeys.end ();
731 ++pIt )
733 const css::awt::KeyEvent& rAWTKey = *pIt;
734 const vcl::KeyCode aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
735 const OUString sName = aVCLKey.GetName();
737 if (!sName.isEmpty())
738 return pIt;
741 return lKeys.end();
744 css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
745 throw(css::lang::IllegalArgumentException, css::container::NoSuchElementException,
746 css::uno::RuntimeException, std::exception)
748 SolarMutexGuard g;
750 sal_Int32 i = 0;
751 sal_Int32 c = lCommandList.getLength();
752 css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // don't pack list!
753 AcceleratorCache& rCache = impl_getCFG(true);
755 for (i=0; i<c; ++i)
757 const OUString& rCommand = lCommandList[i];
758 if (rCommand.isEmpty())
759 throw css::lang::IllegalArgumentException(
760 OUString("Empty command strings are not allowed here."),
761 static_cast< ::cppu::OWeakObject* >(this),
762 (sal_Int16)i);
764 if (!rCache.hasCommand(rCommand))
765 continue;
767 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
768 if ( lKeys.empty() )
769 continue;
771 AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
772 if (pPreferredKey != lKeys.end ())
774 css::uno::Any& rAny = lPreferredOnes[i];
775 rAny <<= *(pPreferredKey);
779 return lPreferredOnes;
782 void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const OUString& sCommand)
783 throw(css::lang::IllegalArgumentException ,
784 css::container::NoSuchElementException,
785 css::uno::RuntimeException, std::exception )
787 if (sCommand.isEmpty())
788 throw css::lang::IllegalArgumentException(
789 OUString("Empty command strings are not allowed here."),
790 static_cast< ::cppu::OWeakObject* >(this),
793 SolarMutexGuard g;
795 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true );
796 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true);
798 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
799 throw css::container::NoSuchElementException(
800 OUString("Command does not exists inside this container."),
801 static_cast< ::cppu::OWeakObject* >(this));
803 if (rPrimaryCache.hasCommand(sCommand))
804 rPrimaryCache.removeCommand(sCommand);
805 if (rSecondaryCache.hasCommand(sCommand))
806 rSecondaryCache.removeCommand(sCommand);
809 void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
810 throw(css::uno::Exception ,
811 css::uno::RuntimeException, std::exception)
813 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::reload()" );
815 SolarMutexGuard g;
817 bool bPreferred;
818 css::uno::Reference< css::container::XNameAccess > xAccess;
820 bPreferred = true;
821 m_aPrimaryReadCache = AcceleratorCache();
822 if (m_pPrimaryWriteCache)
824 // be aware of reentrance problems - use temp variable for calling delete ... :-)
825 AcceleratorCache* pTemp = m_pPrimaryWriteCache;
826 m_pPrimaryWriteCache = nullptr;
827 delete pTemp;
829 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
830 impl_ts_load(bPreferred, xAccess); // load the preferred keys
832 bPreferred = false;
833 m_aSecondaryReadCache = AcceleratorCache();
834 if (m_pSecondaryWriteCache)
836 // be aware of reentrance problems - use temp variable for calling delete ... :-)
837 AcceleratorCache* pTemp = m_pSecondaryWriteCache;
838 m_pSecondaryWriteCache = nullptr;
839 delete pTemp;
841 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
842 impl_ts_load(bPreferred, xAccess); // load the secondary keys
845 void SAL_CALL XCUBasedAcceleratorConfiguration::store()
846 throw(css::uno::Exception ,
847 css::uno::RuntimeException, std::exception)
849 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::store()" );
851 SolarMutexGuard g;
853 bool bPreferred;
854 css::uno::Reference< css::container::XNameAccess > xAccess;
856 bPreferred = true;
857 // on-demand creation of the primary write cache
858 impl_getCFG(bPreferred, true);
859 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
860 impl_ts_save(bPreferred, xAccess);
862 bPreferred = false;
863 // on-demand creation of the secondary write cache
864 impl_getCFG(bPreferred, true);
865 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
866 impl_ts_save(bPreferred, xAccess);
869 void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
870 throw(css::uno::Exception ,
871 css::uno::RuntimeException, std::exception)
873 // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
874 if (!xStorage.is())
875 return;
877 long nOpenModes = css::embed::ElementModes::READWRITE;
878 css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement("accelerator", nOpenModes);
879 if (!xAcceleratorTypeStorage.is())
880 return;
882 css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement("current", nOpenModes);
883 css::uno::Reference< css::io::XOutputStream > xOut;
884 if (xStream.is())
885 xOut = xStream->getOutputStream();
886 if (!xOut.is())
887 throw css::io::IOException(
888 OUString("Could not open accelerator configuration for saving."),
889 static_cast< ::cppu::OWeakObject* >(this));
891 // the original m_aCache has been split into primary cache and secondary cache...
892 // we should merge them before storing to storage
893 AcceleratorCache aCache;
895 SolarMutexGuard g;
897 if (m_pPrimaryWriteCache != nullptr)
898 aCache.takeOver(*m_pPrimaryWriteCache);
899 else
900 aCache.takeOver(m_aPrimaryReadCache);
902 AcceleratorCache::TKeyList lKeys;
903 AcceleratorCache::TKeyList::const_iterator pIt;
904 if (m_pSecondaryWriteCache!=nullptr)
906 lKeys = m_pSecondaryWriteCache->getAllKeys();
907 for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
908 aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
910 else
912 lKeys = m_aSecondaryReadCache.getAllKeys();
913 for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
914 aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
918 css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
919 xClearable->truncate();
920 css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
921 if (xSeek.is())
922 xSeek->seek(0);
924 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(m_xContext);
925 xWriter->setOutputStream(xOut);
927 // write into the stream
928 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
929 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
930 aWriter.flush();
933 sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
934 throw(css::uno::RuntimeException, std::exception)
936 return false;
939 sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
940 throw(css::uno::RuntimeException, std::exception)
942 return false;
945 void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
946 throw(css::uno::RuntimeException, std::exception)
948 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
951 sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
952 throw(css::uno::RuntimeException, std::exception)
954 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
955 return false;
958 void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
959 throw(css::uno::RuntimeException, std::exception)
961 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
964 void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
965 throw(css::uno::RuntimeException, std::exception)
967 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
970 void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
971 throw(css::uno::RuntimeException, std::exception)
973 css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
974 OUString sConfig = xNamed->getName();
975 if ( sConfig == "Global" )
977 m_xCfg.set(
978 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_GLOBAL, ::comphelper::EConfigurationModes::AllLocales ),
979 css::uno::UNO_QUERY );
980 XCUBasedAcceleratorConfiguration::reload();
982 else if ( sConfig == "Modules" )
984 m_xCfg.set(
985 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_MODULES, ::comphelper::EConfigurationModes::AllLocales ),
986 css::uno::UNO_QUERY );
987 XCUBasedAcceleratorConfiguration::reload();
991 void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
992 throw(css::uno::RuntimeException, std::exception)
994 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::addResetListener(): implement me");
997 void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
998 throw(css::uno::RuntimeException, std::exception)
1000 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::removeResetListener(): implement me");
1003 void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
1004 throw(css::uno::RuntimeException, std::exception)
1006 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1008 css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
1009 aEvent.Base >>= xHAccess;
1010 if (! xHAccess.is ())
1011 return;
1013 css::util::ChangesEvent aReceivedEvents( aEvent );
1014 const sal_Int32 c = aReceivedEvents.Changes.getLength();
1015 sal_Int32 i = 0;
1016 for (i=0; i<c; ++i)
1018 const css::util::ElementChange& aChange = aReceivedEvents.Changes[i];
1020 // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1021 // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1022 // So we try to split the path into 3 parts (module isn't important here, because we already know it ... because
1023 // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1025 OUString sOrgPath;
1026 OUString sPath;
1027 OUString sKey;
1029 aChange.Accessor >>= sOrgPath;
1030 sPath = sOrgPath;
1031 OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1032 OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1034 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1036 OUString sModule;
1037 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1038 if ( !sKey.isEmpty() && !sPath.isEmpty() )
1039 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1041 else if ( sGlobalModules == CFG_ENTRY_MODULES )
1043 OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1044 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1046 if ( !sKey.isEmpty() && !sPath.isEmpty() )
1048 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1054 void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
1055 throw(css::uno::RuntimeException, std::exception)
1059 void SAL_CALL XCUBasedAcceleratorConfiguration::dispose()
1060 throw(css::uno::RuntimeException, std::exception)
1062 // nop
1065 void SAL_CALL XCUBasedAcceleratorConfiguration::addEventListener( const css::uno::Reference< css::lang::XEventListener >& /*xListener*/ )
1066 throw(css::uno::RuntimeException, std::exception)
1068 // nop
1071 void SAL_CALL XCUBasedAcceleratorConfiguration::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& /*xListener*/ )
1072 throw(css::uno::RuntimeException, std::exception)
1074 // nop
1077 void XCUBasedAcceleratorConfiguration::impl_ts_load( bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
1079 AcceleratorCache aReadCache = AcceleratorCache();
1080 css::uno::Reference< css::container::XNameAccess > xAccess;
1081 if ( m_sGlobalOrModules == "Global" )
1082 xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
1083 else if ( m_sGlobalOrModules == "Modules" )
1085 css::uno::Reference< css::container::XNameAccess > xModules;
1086 xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
1087 xModules->getByName(m_sModuleCFG) >>= xAccess;
1090 const OUString sIsoLang = impl_ts_getLocale();
1091 const OUString sDefaultLocale("en-US");
1093 css::uno::Reference< css::container::XNameAccess > xKey;
1094 css::uno::Reference< css::container::XNameAccess > xCommand;
1095 if (xAccess.is())
1097 css::uno::Sequence< OUString > lKeys = xAccess->getElementNames();
1098 sal_Int32 nKeys = lKeys.getLength();
1099 for ( sal_Int32 i=0; i<nKeys; ++i )
1101 OUString sKey = lKeys[i];
1102 xAccess->getByName(sKey) >>= xKey;
1103 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1105 css::uno::Sequence< OUString > lLocales = xCommand->getElementNames();
1106 sal_Int32 nLocales = lLocales.getLength();
1107 ::std::vector< OUString > aLocales;
1108 for ( sal_Int32 j=0; j<nLocales; ++j )
1109 aLocales.push_back(lLocales[j]);
1111 ::std::vector< OUString >::const_iterator pFound;
1112 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1114 if ( *pFound == sIsoLang )
1115 break;
1118 if ( pFound == aLocales.end() )
1120 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1122 if ( *pFound == sDefaultLocale )
1123 break;
1126 if ( pFound == aLocales.end() )
1127 continue;
1130 OUString sLocale = *pFound;
1131 OUString sCommand;
1132 xCommand->getByName(sLocale) >>= sCommand;
1133 if (sCommand.isEmpty())
1134 continue;
1136 css::awt::KeyEvent aKeyEvent;
1138 sal_Int32 nIndex = 0;
1139 OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
1140 OUString sPrefix("KEY_");
1141 aKeyEvent.KeyCode = KeyMapping::get().mapIdentifierToCode(sPrefix + sKeyCommand);
1143 css::uno::Sequence< OUString > sToken(4);
1144 const sal_Int32 nToken = 4;
1145 bool bValid = true;
1146 sal_Int32 k;
1147 for (k=0; k<nToken; ++k)
1149 if (nIndex < 0)
1150 break;
1152 sToken[k] = sKey.getToken(0, '_', nIndex);
1153 if (sToken[k].isEmpty())
1155 bValid = false;
1156 break;
1159 if ( sToken[k] == "SHIFT" )
1160 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1161 else if ( sToken[k] == "MOD1" )
1162 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1163 else if ( sToken[k] == "MOD2" )
1164 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1165 else if ( sToken[k] == "MOD3" )
1166 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1167 else
1169 bValid = false;
1170 break;
1174 if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1175 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1179 if (bPreferred)
1180 m_aPrimaryReadCache.takeOver(aReadCache);
1181 else
1182 m_aSecondaryReadCache.takeOver(aReadCache);
1185 void XCUBasedAcceleratorConfiguration::impl_ts_save(bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
1187 if (bPreferred)
1189 AcceleratorCache::TKeyList::const_iterator pIt;
1190 AcceleratorCache::TKeyList lPrimaryReadKeys = m_aPrimaryReadCache.getAllKeys();
1191 AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1193 for ( pIt = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
1195 if (!m_pPrimaryWriteCache->hasKey(*pIt))
1196 removeKeyFromConfiguration(*pIt, true);
1199 for ( pIt = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
1201 OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
1202 if (!m_aPrimaryReadCache.hasKey(*pIt))
1204 insertKeyToConfiguration(*pIt, sCommand, true);
1206 else
1208 OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
1209 if (sReadCommand != sCommand)
1210 insertKeyToConfiguration(*pIt, sCommand, true);
1214 // take over all changes into the original container
1215 SolarMutexGuard g;
1216 // coverity[check_after_deref]
1217 if (m_pPrimaryWriteCache)
1219 m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
1220 AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1221 m_pPrimaryWriteCache = nullptr;
1222 delete pTemp;
1226 else
1228 AcceleratorCache::TKeyList::const_iterator pIt;
1229 AcceleratorCache::TKeyList lSecondaryReadKeys = m_aSecondaryReadCache.getAllKeys();
1230 AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1232 for ( pIt = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
1234 if (!m_pSecondaryWriteCache->hasKey(*pIt))
1235 removeKeyFromConfiguration(*pIt, false);
1238 for ( pIt = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
1240 OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
1241 if (!m_aSecondaryReadCache.hasKey(*pIt))
1243 insertKeyToConfiguration(*pIt, sCommand, false);
1245 else
1247 OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
1248 if (sReadCommand != sCommand)
1249 insertKeyToConfiguration(*pIt, sCommand, false);
1253 // take over all changes into the original container
1254 SolarMutexGuard g;
1255 // coverity[check_after_deref]
1256 if (m_pSecondaryWriteCache)
1258 m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
1259 AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1260 m_pSecondaryWriteCache = nullptr;
1261 delete pTemp;
1265 ::comphelper::ConfigurationHelper::flush(m_xCfg);
1268 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const OUString& sCommand, const bool bPreferred )
1270 css::uno::Reference< css::container::XNameAccess > xAccess;
1271 css::uno::Reference< css::container::XNameContainer > xContainer;
1272 css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1273 css::uno::Reference< css::uno::XInterface > xInst;
1275 if ( bPreferred )
1276 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1277 else
1278 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1280 if ( m_sGlobalOrModules == CFG_ENTRY_GLOBAL )
1281 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1282 else if ( m_sGlobalOrModules == CFG_ENTRY_MODULES )
1284 css::uno::Reference< css::container::XNameContainer > xModules;
1285 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1286 if ( !xModules->hasByName(m_sModuleCFG) )
1288 xFac.set(xModules, css::uno::UNO_QUERY);
1289 xInst = xFac->createInstance();
1290 xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
1292 xModules->getByName(m_sModuleCFG) >>= xContainer;
1295 const OUString sKey = lcl_getKeyString(aKeyEvent);
1296 css::uno::Reference< css::container::XNameAccess > xKey;
1297 css::uno::Reference< css::container::XNameContainer > xCommand;
1298 if ( !xContainer->hasByName(sKey) )
1300 xFac.set(xContainer, css::uno::UNO_QUERY);
1301 xInst = xFac->createInstance();
1302 xContainer->insertByName(sKey, css::uno::makeAny(xInst));
1304 xContainer->getByName(sKey) >>= xKey;
1306 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1307 OUString sLocale = impl_ts_getLocale();
1308 if ( !xCommand->hasByName(sLocale) )
1309 xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
1310 else
1311 xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
1314 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const bool bPreferred )
1316 css::uno::Reference< css::container::XNameAccess > xAccess;
1317 css::uno::Reference< css::container::XNameContainer > xContainer;
1319 if ( bPreferred )
1320 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1321 else
1322 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1324 if ( m_sGlobalOrModules == CFG_ENTRY_GLOBAL )
1325 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1326 else if ( m_sGlobalOrModules == CFG_ENTRY_MODULES )
1328 css::uno::Reference< css::container::XNameAccess > xModules;
1329 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1330 if ( !xModules->hasByName(m_sModuleCFG) )
1331 return;
1332 xModules->getByName(m_sModuleCFG) >>= xContainer;
1335 const OUString sKey = lcl_getKeyString(aKeyEvent);
1336 xContainer->removeByName(sKey);
1339 void XCUBasedAcceleratorConfiguration::reloadChanged( const OUString& sPrimarySecondary, const OUString& sGlobalModules, const OUString& sModule, const OUString& sKey )
1341 css::uno::Reference< css::container::XNameAccess > xAccess;
1342 css::uno::Reference< css::container::XNameContainer > xContainer;
1344 m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1345 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1346 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1347 else
1349 css::uno::Reference< css::container::XNameAccess > xModules;
1350 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1351 if ( !xModules->hasByName(sModule) )
1352 return;
1353 xModules->getByName(sModule) >>= xContainer;
1356 css::awt::KeyEvent aKeyEvent;
1357 OUString sKeyIdentifier;
1359 sal_Int32 nIndex = 0;
1360 sKeyIdentifier = sKey.getToken(0, '_', nIndex);
1361 aKeyEvent.KeyCode = KeyMapping::get().mapIdentifierToCode("KEY_"+sKeyIdentifier);
1363 css::uno::Sequence< OUString > sToken(3);
1364 const sal_Int32 nToken = 3;
1365 for (sal_Int32 i=0; i<nToken; ++i)
1367 if ( nIndex < 0 )
1368 break;
1370 sToken[i] = sKey.getToken(0, '_', nIndex);
1371 if ( sToken[i] == "SHIFT" )
1372 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1373 else if ( sToken[i] == "MOD1" )
1374 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1375 else if ( sToken[i] == "MOD2" )
1376 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1377 else if ( sToken[i] == "MOD3" )
1378 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1381 css::uno::Reference< css::container::XNameAccess > xKey;
1382 css::uno::Reference< css::container::XNameAccess > xCommand;
1383 OUString sCommand;
1385 if (xContainer->hasByName(sKey))
1387 OUString sLocale = impl_ts_getLocale();
1388 xContainer->getByName(sKey) >>= xKey;
1389 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1390 xCommand->getByName(sLocale) >>= sCommand;
1393 if ( sPrimarySecondary == CFG_ENTRY_PRIMARY )
1395 if (sCommand.isEmpty())
1396 m_aPrimaryReadCache.removeKey(aKeyEvent);
1397 else
1398 m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1400 else if ( sPrimarySecondary == CFG_ENTRY_SECONDARY )
1402 if (sCommand.isEmpty())
1403 m_aSecondaryReadCache.removeKey(aKeyEvent);
1404 else
1405 m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1409 AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(bool bPreferred, bool bWriteAccessRequested)
1411 SolarMutexGuard g;
1413 if (bPreferred)
1415 //create copy of our readonly-cache, if write access is forced ... but
1416 //not still possible!
1417 if (
1418 (bWriteAccessRequested) &&
1419 (!m_pPrimaryWriteCache )
1422 m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
1425 // in case, we have a writeable cache, we use it for reading too!
1426 // Otherwise the API user can't find its own changes ...
1427 if (m_pPrimaryWriteCache)
1428 return *m_pPrimaryWriteCache;
1429 else
1430 return m_aPrimaryReadCache;
1433 else
1435 //create copy of our readonly-cache, if write access is forced ... but
1436 //not still possible!
1437 if (
1438 (bWriteAccessRequested) &&
1439 (!m_pSecondaryWriteCache )
1442 m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
1445 // in case, we have a writeable cache, we use it for reading too!
1446 // Otherwise the API user can't find its own changes ...
1447 if (m_pSecondaryWriteCache)
1448 return *m_pSecondaryWriteCache;
1449 else
1450 return m_aSecondaryReadCache;
1454 OUString XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1456 OUString sISOLocale = officecfg::Setup::L10N::ooLocale::get();
1458 if (sISOLocale.isEmpty())
1459 return OUString("en-US");
1460 return sISOLocale;
1463 } // namespace framework
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */