fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / accelerators / acceleratorconfiguration.cxx
blob77327232b201859bbeb109d31e2c56b256f47e10
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 <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(salhelper::SingletonRef<framework::KeyMapping>& _rKeyMapping, const css::awt::KeyEvent& aKeyEvent)
62 const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of a identifier...
63 OUStringBuffer sKeyBuffer((_rKeyMapping->mapCodeToIdentifier(aKeyEvent.KeyCode)).copy(nBeginIndex));
65 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
66 sKeyBuffer.appendAscii("_SHIFT");
67 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 )
68 sKeyBuffer.appendAscii("_MOD1");
69 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 )
70 sKeyBuffer.appendAscii("_MOD2");
71 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 )
72 sKeyBuffer.appendAscii("_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 (0 )
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); // dont 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, true); // sal_True => open or create!
238 xStreamNoLang = m_aPresetHandler.openPreset(PRESET_DEFAULT, true);
240 catch(const css::io::IOException&) {} // does not have to exist
243 css::uno::Reference< css::io::XInputStream > xIn;
244 if (xStream.is())
245 xIn = xStream->getInputStream();
246 if (!xIn.is())
247 throw css::io::IOException(
248 OUString("Could not open accelerator configuration for reading."),
249 static_cast< ::cppu::OWeakObject* >(this));
251 // impl_ts_load() does not clear the cache
253 SolarMutexGuard g;
254 m_aReadCache = AcceleratorCache();
257 impl_ts_load(xIn);
259 // Load also the general language independent default accelerators
260 // (ignoring the already defined accelerators)
261 if (xStreamNoLang.is())
263 xIn = xStreamNoLang->getInputStream();
264 if (xIn.is())
265 impl_ts_load(xIn);
269 void SAL_CALL XMLBasedAcceleratorConfiguration::store()
270 throw(css::uno::Exception ,
271 css::uno::RuntimeException, std::exception)
273 css::uno::Reference< css::io::XStream > xStream;
275 SolarMutexGuard g;
276 xStream = m_aPresetHandler.openTarget(TARGET_CURRENT, true); // sal_True => open or create!
279 css::uno::Reference< css::io::XOutputStream > xOut;
280 if (xStream.is())
281 xOut = xStream->getOutputStream();
283 if (!xOut.is())
284 throw css::io::IOException(
285 OUString("Could not open accelerator configuration for saving."),
286 static_cast< ::cppu::OWeakObject* >(this));
288 impl_ts_save(xOut);
290 xOut.clear();
291 xStream.clear();
293 m_aPresetHandler.commitUserChanges();
296 void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
297 throw(css::uno::Exception ,
298 css::uno::RuntimeException, std::exception)
300 css::uno::Reference< css::io::XStream > xStream = StorageHolder::openSubStreamWithFallback(
301 xStorage,
302 TARGET_CURRENT,
303 css::embed::ElementModes::READWRITE,
304 false); // False => no fallback from read/write to readonly!
305 css::uno::Reference< css::io::XOutputStream > xOut;
306 if (xStream.is())
307 xOut = xStream->getOutputStream();
309 if (!xOut.is())
310 throw css::io::IOException(
311 OUString("Could not open accelerator configuration for saving."),
312 static_cast< ::cppu::OWeakObject* >(this));
314 impl_ts_save(xOut);
316 // TODO inform listener about success, so it can flush the root and sub storage of this stream!
319 sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isModified()
320 throw(css::uno::RuntimeException, std::exception)
322 SolarMutexGuard g;
323 return (m_pWriteCache != 0);
326 sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::isReadOnly()
327 throw(css::uno::RuntimeException, std::exception)
329 css::uno::Reference< css::io::XStream > xStream;
331 SolarMutexGuard g;
332 xStream = m_aPresetHandler.openTarget(TARGET_CURRENT, true); // sal_True => open or create!
335 css::uno::Reference< css::io::XOutputStream > xOut;
336 if (xStream.is())
337 xOut = xStream->getOutputStream();
338 return !(xOut.is());
341 void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
342 throw(css::uno::RuntimeException, std::exception)
344 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
347 sal_Bool SAL_CALL XMLBasedAcceleratorConfiguration::hasStorage()
348 throw(css::uno::RuntimeException, std::exception)
350 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
351 return sal_False;
354 void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
355 throw(css::uno::RuntimeException, std::exception)
357 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
360 void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
361 throw(css::uno::RuntimeException, std::exception)
363 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
366 void SAL_CALL XMLBasedAcceleratorConfiguration::reset()
367 throw(css::uno::RuntimeException, std::exception)
370 SolarMutexGuard g;
371 m_aPresetHandler.copyPresetToTarget(PRESET_DEFAULT, TARGET_CURRENT);
374 reload();
377 void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
378 throw(css::uno::RuntimeException, std::exception)
380 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::addResetListener(): implement me");
383 void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
384 throw(css::uno::RuntimeException, std::exception)
386 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::removeResetListener(): implement me");
389 // IStorageListener
390 void XMLBasedAcceleratorConfiguration::changesOccurred(const OUString& /*sPath*/)
392 reload();
395 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
397 css::uno::Reference< css::uno::XComponentContext > xContext;
399 SolarMutexGuard g;
400 xContext = m_xContext;
401 if (m_pWriteCache)
403 // be aware of reentrance problems - use temp variable for calling delete ... :-)
404 AcceleratorCache* pTemp = m_pWriteCache;
405 m_pWriteCache = 0;
406 delete pTemp;
410 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
411 if (xSeek.is())
412 xSeek->seek(0);
414 SolarMutexGuard g;
416 // create the parser queue
417 // Note: Use special filter object between parser and reader
418 // to get filtered xml with right namespaces ...
419 // Use further a temp cache for reading!
420 AcceleratorConfigurationReader* pReader = new AcceleratorConfigurationReader(m_aReadCache);
421 css::uno::Reference< css::xml::sax::XDocumentHandler > xReader (static_cast< ::cppu::OWeakObject* >(pReader), css::uno::UNO_QUERY_THROW);
422 SaxNamespaceFilter* pFilter = new SaxNamespaceFilter(xReader);
423 css::uno::Reference< css::xml::sax::XDocumentHandler > xFilter (static_cast< ::cppu::OWeakObject* >(pFilter), css::uno::UNO_QUERY_THROW);
425 // connect parser, filter and stream
426 css::uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create(xContext);
427 xParser->setDocumentHandler(xFilter);
429 css::xml::sax::InputSource aSource;
430 aSource.aInputStream = xStream;
432 // TODO think about error handling
433 xParser->parseStream(aSource);
436 void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
438 bool bChanged;
439 AcceleratorCache aCache;
440 css::uno::Reference< css::uno::XComponentContext > xContext;
442 SolarMutexGuard g;
443 bChanged = (m_pWriteCache != 0);
444 if (bChanged)
445 aCache.takeOver(*m_pWriteCache);
446 else
447 aCache.takeOver(m_aReadCache);
448 xContext = m_xContext;
451 css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
452 xClearable->truncate();
454 // TODO can be removed if seek(0) is done by truncate() automatically!
455 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
456 if (xSeek.is())
457 xSeek->seek(0);
459 // combine writer/cache/stream etcpp.
460 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(xContext);
461 xWriter->setOutputStream(xStream);
463 // write into the stream
464 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
465 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
466 aWriter.flush();
468 SolarMutexGuard g;
469 // take over all changes into the readonly cache ...
470 // and forget the copy-on-write copied cache
471 if (bChanged)
473 m_aReadCache.takeOver(*m_pWriteCache);
474 // live with reentrance .-)
475 AcceleratorCache* pTemp = m_pWriteCache;
476 m_pWriteCache = 0;
477 delete pTemp;
481 AcceleratorCache& XMLBasedAcceleratorConfiguration::impl_getCFG(bool bWriteAccessRequested)
483 SolarMutexGuard g;
485 //create copy of our readonly-cache, if write access is forced ... but
486 //not still possible!
487 if (
488 (bWriteAccessRequested) &&
489 (!m_pWriteCache )
492 m_pWriteCache = new AcceleratorCache(m_aReadCache);
495 // in case, we have a writeable cache, we use it for reading too!
496 // Otherwise the API user can't find its own changes ...
497 if (m_pWriteCache)
498 return *m_pWriteCache;
499 else
500 return m_aReadCache;
503 OUString XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
505 OUString sISOLocale = officecfg::Setup::L10N::ooLocale::get();
507 if (sISOLocale.isEmpty())
508 return OUString("en-US");
509 return sISOLocale;
512 /*******************************************************************************
514 * XCU based accelerator configuration
516 *******************************************************************************/
518 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext >& xContext)
519 : m_xContext (xContext )
520 , m_pPrimaryWriteCache(0 )
521 , m_pSecondaryWriteCache(0 )
523 const OUString CFG_ENTRY_ACCELERATORS("org.openoffice.Office.Accelerators");
524 m_xCfg = css::uno::Reference< css::container::XNameAccess > (
525 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_ACCELERATORS, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
526 css::uno::UNO_QUERY );
529 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
533 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
534 throw(css::uno::RuntimeException, std::exception)
536 SolarMutexGuard g;
538 AcceleratorCache::TKeyList lKeys = impl_getCFG(true).getAllKeys(); //get keys from PrimaryKeys set
540 AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(false).getAllKeys(); //get keys from SecondaryKeys set
541 lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
542 AcceleratorCache::TKeyList::const_iterator pIt;
543 AcceleratorCache::TKeyList::const_iterator pEnd = lSecondaryKeys.end();
544 for ( pIt = lSecondaryKeys.begin(); pIt != pEnd; ++pIt )
545 lKeys.push_back(*pIt);
547 return comphelper::containerToSequence(lKeys);
550 OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
551 throw(css::container::NoSuchElementException,
552 css::uno::RuntimeException, std::exception )
554 SolarMutexGuard g;
556 AcceleratorCache& rPrimaryCache = impl_getCFG(true );
557 AcceleratorCache& rSecondaryCache = impl_getCFG(false);
559 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
560 throw css::container::NoSuchElementException(
561 OUString(),
562 static_cast< ::cppu::OWeakObject* >(this));
564 if (rPrimaryCache.hasKey(aKeyEvent))
565 return rPrimaryCache.getCommandByKey(aKeyEvent);
566 else
567 return rSecondaryCache.getCommandByKey(aKeyEvent);
570 void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
571 const OUString& sCommand )
572 throw (css::lang::IllegalArgumentException,
573 css::container::NoSuchElementException,
574 css::uno::RuntimeException, std::exception)
576 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::setKeyEvent" );
578 if (
579 (aKeyEvent.KeyCode == 0) &&
580 (aKeyEvent.KeyChar == 0) &&
581 (aKeyEvent.KeyFunc == 0) &&
582 (aKeyEvent.Modifiers == 0)
584 throw css::lang::IllegalArgumentException(
585 OUString("Such key event seems not to be supported by any operating system."),
586 static_cast< ::cppu::OWeakObject* >(this),
589 if (sCommand.isEmpty())
590 throw css::lang::IllegalArgumentException(
591 OUString("Empty command strings are not allowed here."),
592 static_cast< ::cppu::OWeakObject* >(this),
595 SolarMutexGuard g;
597 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true ); // sal_True => force getting of a writeable cache!
598 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true); // sal_True => force getting of a writeable cache!
600 if ( rPrimaryCache.hasKey(aKeyEvent) )
602 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
603 if ( sCommand != sOriginalCommand )
605 if (rSecondaryCache.hasCommand(sOriginalCommand))
607 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
608 rSecondaryCache.removeKey(lSecondaryKeys[0]);
609 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
612 if (rPrimaryCache.hasCommand(sCommand))
614 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
615 rPrimaryCache.removeKey(lPrimaryKeys[0]);
616 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
619 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
623 else if ( rSecondaryCache.hasKey(aKeyEvent) )
625 OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
626 if (sCommand != sOriginalCommand)
628 if (rPrimaryCache.hasCommand(sCommand))
630 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
631 rPrimaryCache.removeKey(lPrimaryKeys[0]);
632 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
635 rSecondaryCache.removeKey(aKeyEvent);
636 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
640 else
642 if (rPrimaryCache.hasCommand(sCommand))
644 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
645 rPrimaryCache.removeKey(lPrimaryKeys[0]);
646 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
649 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
653 void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
654 throw(css::container::NoSuchElementException,
655 css::uno::RuntimeException, std::exception )
657 SolarMutexGuard g;
659 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true );
660 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true);
662 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
663 throw css::container::NoSuchElementException(
664 OUString(),
665 static_cast< ::cppu::OWeakObject* >(this));
667 if (rPrimaryCache.hasKey(aKeyEvent))
669 OUString sDelCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
670 if (!sDelCommand.isEmpty())
672 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
673 if (rSecondaryCache.hasCommand(sOriginalCommand))
675 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
676 rSecondaryCache.removeKey(lSecondaryKeys[0]);
677 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
680 rPrimaryCache.removeKey(aKeyEvent);
684 else
686 OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
687 if (!sDelCommand.isEmpty())
688 rSecondaryCache.removeKey(aKeyEvent);
692 css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
693 throw(css::lang::IllegalArgumentException ,
694 css::container::NoSuchElementException,
695 css::uno::RuntimeException, std::exception )
697 if (sCommand.isEmpty())
698 throw css::lang::IllegalArgumentException(
699 OUString("Empty command strings are not allowed here."),
700 static_cast< ::cppu::OWeakObject* >(this),
703 SolarMutexGuard g;
705 AcceleratorCache& rPrimaryCache = impl_getCFG(true );
706 AcceleratorCache& rSecondaryCache = impl_getCFG(false);
708 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
709 throw css::container::NoSuchElementException(
710 OUString(),
711 static_cast< ::cppu::OWeakObject* >(this));
713 AcceleratorCache::TKeyList lKeys = rPrimaryCache.getKeysByCommand(sCommand);
715 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
716 AcceleratorCache::TKeyList::const_iterator pIt;
717 for (pIt = lSecondaryKeys.begin(); pIt != lSecondaryKeys.end(); ++pIt)
718 lKeys.push_back(*pIt);
720 return comphelper::containerToSequence(lKeys);
723 AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
725 AcceleratorCache::TKeyList::const_iterator pIt;
726 for ( pIt = lKeys.begin ();
727 pIt != lKeys.end ();
728 ++pIt )
730 const css::awt::KeyEvent& rAWTKey = *pIt;
731 const vcl::KeyCode aVCLKey = ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey);
732 const OUString sName = aVCLKey.GetName();
734 if (!sName.isEmpty())
735 return pIt;
738 return lKeys.end();
741 css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
742 throw(css::lang::IllegalArgumentException, css::container::NoSuchElementException,
743 css::uno::RuntimeException, std::exception)
745 SolarMutexGuard g;
747 sal_Int32 i = 0;
748 sal_Int32 c = lCommandList.getLength();
749 css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // dont pack list!
750 AcceleratorCache& rCache = impl_getCFG(true);
752 for (i=0; i<c; ++i)
754 const OUString& rCommand = lCommandList[i];
755 if (rCommand.isEmpty())
756 throw css::lang::IllegalArgumentException(
757 OUString("Empty command strings are not allowed here."),
758 static_cast< ::cppu::OWeakObject* >(this),
759 (sal_Int16)i);
761 if (!rCache.hasCommand(rCommand))
762 continue;
764 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
765 if ( lKeys.empty() )
766 continue;
768 AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
769 if (pPreferredKey != lKeys.end ())
771 css::uno::Any& rAny = lPreferredOnes[i];
772 rAny <<= *(pPreferredKey);
776 return lPreferredOnes;
779 void SAL_CALL XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const OUString& sCommand)
780 throw(css::lang::IllegalArgumentException ,
781 css::container::NoSuchElementException,
782 css::uno::RuntimeException, std::exception )
784 if (sCommand.isEmpty())
785 throw css::lang::IllegalArgumentException(
786 OUString("Empty command strings are not allowed here."),
787 static_cast< ::cppu::OWeakObject* >(this),
790 SolarMutexGuard g;
792 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true );
793 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true);
795 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
796 throw css::container::NoSuchElementException(
797 OUString("Command does not exists inside this container."),
798 static_cast< ::cppu::OWeakObject* >(this));
800 if (rPrimaryCache.hasCommand(sCommand))
801 rPrimaryCache.removeCommand(sCommand);
802 if (rSecondaryCache.hasCommand(sCommand))
803 rSecondaryCache.removeCommand(sCommand);
806 void SAL_CALL XCUBasedAcceleratorConfiguration::reload()
807 throw(css::uno::Exception ,
808 css::uno::RuntimeException, std::exception)
810 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::reload()" );
812 SolarMutexGuard g;
814 bool bPreferred;
815 css::uno::Reference< css::container::XNameAccess > xAccess;
817 bPreferred = true;
818 m_aPrimaryReadCache = AcceleratorCache();
819 if (m_pPrimaryWriteCache)
821 // be aware of reentrance problems - use temp variable for calling delete ... :-)
822 AcceleratorCache* pTemp = m_pPrimaryWriteCache;
823 m_pPrimaryWriteCache = 0;
824 delete pTemp;
826 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
827 impl_ts_load(bPreferred, xAccess); // load the preferred keys
829 bPreferred = false;
830 m_aSecondaryReadCache = AcceleratorCache();
831 if (m_pSecondaryWriteCache)
833 // be aware of reentrance problems - use temp variable for calling delete ... :-)
834 AcceleratorCache* pTemp = m_pSecondaryWriteCache;
835 m_pSecondaryWriteCache = 0;
836 delete pTemp;
838 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
839 impl_ts_load(bPreferred, xAccess); // load the secondary keys
842 void SAL_CALL XCUBasedAcceleratorConfiguration::store()
843 throw(css::uno::Exception ,
844 css::uno::RuntimeException, std::exception)
846 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::store()" );
848 SolarMutexGuard g;
850 bool bPreferred;
851 css::uno::Reference< css::container::XNameAccess > xAccess;
853 bPreferred = true;
854 // on-demand creation of the primary write cache
855 impl_getCFG(bPreferred, true);
856 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
857 impl_ts_save(bPreferred, xAccess);
859 bPreferred = false;
860 // on-demand creation of the secondary write cache
861 impl_getCFG(bPreferred, true);
862 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
863 impl_ts_save(bPreferred, xAccess);
866 void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
867 throw(css::uno::Exception ,
868 css::uno::RuntimeException, std::exception)
870 // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
871 if (!xStorage.is())
872 return;
874 long nOpenModes = css::embed::ElementModes::READWRITE;
875 css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement(OUString("accelerator"), nOpenModes);
876 if (!xAcceleratorTypeStorage.is())
877 return;
879 css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement(OUString("current"), nOpenModes);
880 css::uno::Reference< css::io::XOutputStream > xOut;
881 if (xStream.is())
882 xOut = xStream->getOutputStream();
883 if (!xOut.is())
884 throw css::io::IOException(
885 OUString("Could not open accelerator configuration for saving."),
886 static_cast< ::cppu::OWeakObject* >(this));
888 // the original m_aCache has been split into primay cache and secondary cache...
889 // we should merge them before storing to storage
890 AcceleratorCache aCache;
892 SolarMutexGuard g;
894 if (m_pPrimaryWriteCache != 0)
895 aCache.takeOver(*m_pPrimaryWriteCache);
896 else
897 aCache.takeOver(m_aPrimaryReadCache);
899 AcceleratorCache::TKeyList lKeys;
900 AcceleratorCache::TKeyList::const_iterator pIt;
901 if (m_pSecondaryWriteCache!=0)
903 lKeys = m_pSecondaryWriteCache->getAllKeys();
904 for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
905 aCache.setKeyCommandPair(*pIt, m_pSecondaryWriteCache->getCommandByKey(*pIt));
907 else
909 lKeys = m_aSecondaryReadCache.getAllKeys();
910 for ( pIt=lKeys.begin(); pIt!=lKeys.end(); ++pIt )
911 aCache.setKeyCommandPair(*pIt, m_aSecondaryReadCache.getCommandByKey(*pIt));
915 css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
916 xClearable->truncate();
917 css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
918 if (xSeek.is())
919 xSeek->seek(0);
921 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(m_xContext);
922 xWriter->setOutputStream(xOut);
924 // write into the stream
925 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
926 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
927 aWriter.flush();
930 sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isModified()
931 throw(css::uno::RuntimeException, std::exception)
933 return sal_False;
936 sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::isReadOnly()
937 throw(css::uno::RuntimeException, std::exception)
939 return sal_False;
942 void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
943 throw(css::uno::RuntimeException, std::exception)
945 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
948 sal_Bool SAL_CALL XCUBasedAcceleratorConfiguration::hasStorage()
949 throw(css::uno::RuntimeException, std::exception)
951 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
952 return sal_False;
955 void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
956 throw(css::uno::RuntimeException, std::exception)
958 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
961 void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
962 throw(css::uno::RuntimeException, std::exception)
964 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
967 void SAL_CALL XCUBasedAcceleratorConfiguration::reset()
968 throw(css::uno::RuntimeException, std::exception)
970 css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
971 OUString sConfig = xNamed->getName();
972 if ( sConfig == "Global" )
974 m_xCfg = css::uno::Reference< css::container::XNameAccess > (
975 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_GLOBAL, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
976 css::uno::UNO_QUERY );
977 XCUBasedAcceleratorConfiguration::reload();
979 else if ( sConfig == "Modules" )
981 m_xCfg = css::uno::Reference< css::container::XNameAccess > (
982 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_MODULES, ::comphelper::ConfigurationHelper::E_ALL_LOCALES ),
983 css::uno::UNO_QUERY );
984 XCUBasedAcceleratorConfiguration::reload();
988 void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
989 throw(css::uno::RuntimeException, std::exception)
991 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::addResetListener(): implement me");
994 void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
995 throw(css::uno::RuntimeException, std::exception)
997 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::removeResetListener(): implement me");
1000 void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
1001 throw(css::uno::RuntimeException, std::exception)
1003 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1005 css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
1006 aEvent.Base >>= xHAccess;
1007 if (! xHAccess.is ())
1008 return;
1010 css::util::ChangesEvent aReceivedEvents( aEvent );
1011 const sal_Int32 c = aReceivedEvents.Changes.getLength();
1012 sal_Int32 i = 0;
1013 for (i=0; i<c; ++i)
1015 const css::util::ElementChange& aChange = aReceivedEvents.Changes[i];
1017 // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1018 // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1019 // So we try to split the path into 3 parts (module isn't important here, because we already know it ... because
1020 // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1022 OUString sOrgPath;
1023 OUString sPath;
1024 OUString sKey;
1026 aChange.Accessor >>= sOrgPath;
1027 sPath = sOrgPath;
1028 OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1029 OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1031 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1033 OUString sModule;
1034 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1035 if ( !sKey.isEmpty() && !sPath.isEmpty() )
1036 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1038 else if ( sGlobalModules == CFG_ENTRY_MODULES )
1040 OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1041 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
1043 if ( !sKey.isEmpty() && !sPath.isEmpty() )
1045 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
1051 void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
1052 throw(css::uno::RuntimeException, std::exception)
1056 void SAL_CALL XCUBasedAcceleratorConfiguration::dispose()
1057 throw(css::uno::RuntimeException, std::exception)
1059 // nop
1062 void SAL_CALL XCUBasedAcceleratorConfiguration::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /*xListener*/ )
1063 throw(css::uno::RuntimeException, std::exception)
1065 // nop
1068 void SAL_CALL XCUBasedAcceleratorConfiguration::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& /*xListener*/ )
1069 throw(css::uno::RuntimeException, std::exception)
1071 // nop
1074 void XCUBasedAcceleratorConfiguration::impl_ts_load( bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
1076 AcceleratorCache aReadCache = AcceleratorCache();
1077 css::uno::Reference< css::container::XNameAccess > xAccess;
1078 if ( m_sGlobalOrModules == "Global" )
1079 xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
1080 else if ( m_sGlobalOrModules == "Modules" )
1082 css::uno::Reference< css::container::XNameAccess > xModules;
1083 xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
1084 xModules->getByName(m_sModuleCFG) >>= xAccess;
1087 const OUString sIsoLang = impl_ts_getLocale();
1088 const OUString sDefaultLocale("en-US");
1090 css::uno::Reference< css::container::XNameAccess > xKey;
1091 css::uno::Reference< css::container::XNameAccess > xCommand;
1092 if (xAccess.is())
1094 css::uno::Sequence< OUString > lKeys = xAccess->getElementNames();
1095 sal_Int32 nKeys = lKeys.getLength();
1096 for ( sal_Int32 i=0; i<nKeys; ++i )
1098 OUString sKey = lKeys[i];
1099 xAccess->getByName(sKey) >>= xKey;
1100 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1102 css::uno::Sequence< OUString > lLocales = xCommand->getElementNames();
1103 sal_Int32 nLocales = lLocales.getLength();
1104 ::std::vector< OUString > aLocales;
1105 for ( sal_Int32 j=0; j<nLocales; ++j )
1106 aLocales.push_back(lLocales[j]);
1108 ::std::vector< OUString >::const_iterator pFound;
1109 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1111 if ( *pFound == sIsoLang )
1112 break;
1115 if ( pFound == aLocales.end() )
1117 for ( pFound = aLocales.begin(); pFound != aLocales.end(); ++pFound )
1119 if ( *pFound == sDefaultLocale )
1120 break;
1123 if ( pFound == aLocales.end() )
1124 continue;
1127 OUString sLocale = *pFound;
1128 OUString sCommand;
1129 xCommand->getByName(sLocale) >>= sCommand;
1130 if (sCommand.isEmpty())
1131 continue;
1133 css::awt::KeyEvent aKeyEvent;
1135 sal_Int32 nIndex = 0;
1136 OUString sKeyCommand = sKey.getToken(0, '_', nIndex);
1137 OUString sPrefix("KEY_");
1138 aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sPrefix + sKeyCommand);
1140 css::uno::Sequence< OUString > sToken(4);
1141 const sal_Int32 nToken = 4;
1142 bool bValid = true;
1143 sal_Int32 k;
1144 for (k=0; k<nToken; ++k)
1146 if (nIndex < 0)
1147 break;
1149 sToken[k] = sKey.getToken(0, '_', nIndex);
1150 if (sToken[k].isEmpty())
1152 bValid = false;
1153 break;
1156 if ( sToken[k] == "SHIFT" )
1157 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1158 else if ( sToken[k] == "MOD1" )
1159 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1160 else if ( sToken[k] == "MOD2" )
1161 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1162 else if ( sToken[k] == "MOD3" )
1163 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1164 else
1166 bValid = false;
1167 break;
1171 if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1172 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1176 if (bPreferred)
1177 m_aPrimaryReadCache.takeOver(aReadCache);
1178 else
1179 m_aSecondaryReadCache.takeOver(aReadCache);
1182 void XCUBasedAcceleratorConfiguration::impl_ts_save(bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& /*xCfg*/)
1184 if (bPreferred)
1186 AcceleratorCache::TKeyList::const_iterator pIt;
1187 AcceleratorCache::TKeyList lPrimaryReadKeys = m_aPrimaryReadCache.getAllKeys();
1188 AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1190 for ( pIt = lPrimaryReadKeys.begin(); pIt != lPrimaryReadKeys.end(); ++pIt )
1192 if (!m_pPrimaryWriteCache->hasKey(*pIt))
1193 removeKeyFromConfiguration(*pIt, true);
1196 for ( pIt = lPrimaryWriteKeys.begin(); pIt != lPrimaryWriteKeys.end(); ++pIt )
1198 OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(*pIt);
1199 if (!m_aPrimaryReadCache.hasKey(*pIt))
1201 insertKeyToConfiguration(*pIt, sCommand, true);
1203 else
1205 OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(*pIt);
1206 if (sReadCommand != sCommand)
1207 insertKeyToConfiguration(*pIt, sCommand, true);
1211 // take over all changes into the original container
1212 SolarMutexGuard g;
1213 // coverity[check_after_deref]
1214 if (m_pPrimaryWriteCache)
1216 m_aPrimaryReadCache.takeOver(*m_pPrimaryWriteCache);
1217 AcceleratorCache* pTemp = m_pPrimaryWriteCache;
1218 m_pPrimaryWriteCache = 0;
1219 delete pTemp;
1223 else
1225 AcceleratorCache::TKeyList::const_iterator pIt;
1226 AcceleratorCache::TKeyList lSecondaryReadKeys = m_aSecondaryReadCache.getAllKeys();
1227 AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1229 for ( pIt = lSecondaryReadKeys.begin(); pIt != lSecondaryReadKeys.end(); ++pIt)
1231 if (!m_pSecondaryWriteCache->hasKey(*pIt))
1232 removeKeyFromConfiguration(*pIt, false);
1235 for ( pIt = lSecondaryWriteKeys.begin(); pIt != lSecondaryWriteKeys.end(); ++pIt )
1237 OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(*pIt);
1238 if (!m_aSecondaryReadCache.hasKey(*pIt))
1240 insertKeyToConfiguration(*pIt, sCommand, false);
1242 else
1244 OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(*pIt);
1245 if (sReadCommand != sCommand)
1246 insertKeyToConfiguration(*pIt, sCommand, false);
1250 // take over all changes into the original container
1251 SolarMutexGuard g;
1252 // coverity[check_after_deref]
1253 if (m_pSecondaryWriteCache)
1255 m_aSecondaryReadCache.takeOver(*m_pSecondaryWriteCache);
1256 AcceleratorCache* pTemp = m_pSecondaryWriteCache;
1257 m_pSecondaryWriteCache = 0;
1258 delete pTemp;
1262 ::comphelper::ConfigurationHelper::flush(m_xCfg);
1265 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const OUString& sCommand, const bool bPreferred )
1267 css::uno::Reference< css::container::XNameAccess > xAccess;
1268 css::uno::Reference< css::container::XNameContainer > xContainer;
1269 css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1270 css::uno::Reference< css::uno::XInterface > xInst;
1272 if ( bPreferred )
1273 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1274 else
1275 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1277 if ( m_sGlobalOrModules == CFG_ENTRY_GLOBAL )
1278 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1279 else if ( m_sGlobalOrModules == CFG_ENTRY_MODULES )
1281 css::uno::Reference< css::container::XNameContainer > xModules;
1282 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1283 if ( !xModules->hasByName(m_sModuleCFG) )
1285 xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xModules, css::uno::UNO_QUERY);
1286 xInst = xFac->createInstance();
1287 xModules->insertByName(m_sModuleCFG, css::uno::makeAny(xInst));
1289 xModules->getByName(m_sModuleCFG) >>= xContainer;
1292 const OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1293 css::uno::Reference< css::container::XNameAccess > xKey;
1294 css::uno::Reference< css::container::XNameContainer > xCommand;
1295 if ( !xContainer->hasByName(sKey) )
1297 xFac = css::uno::Reference< css::lang::XSingleServiceFactory >(xContainer, css::uno::UNO_QUERY);
1298 xInst = xFac->createInstance();
1299 xContainer->insertByName(sKey, css::uno::makeAny(xInst));
1301 xContainer->getByName(sKey) >>= xKey;
1303 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1304 OUString sLocale = impl_ts_getLocale();
1305 if ( !xCommand->hasByName(sLocale) )
1306 xCommand->insertByName(sLocale, css::uno::makeAny(sCommand));
1307 else
1308 xCommand->replaceByName(sLocale, css::uno::makeAny(sCommand));
1311 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const bool bPreferred )
1313 css::uno::Reference< css::container::XNameAccess > xAccess;
1314 css::uno::Reference< css::container::XNameContainer > xContainer;
1316 if ( bPreferred )
1317 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1318 else
1319 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1321 if ( m_sGlobalOrModules == CFG_ENTRY_GLOBAL )
1322 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1323 else if ( m_sGlobalOrModules == CFG_ENTRY_MODULES )
1325 css::uno::Reference< css::container::XNameAccess > xModules;
1326 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1327 if ( !xModules->hasByName(m_sModuleCFG) )
1328 return;
1329 xModules->getByName(m_sModuleCFG) >>= xContainer;
1332 const OUString sKey = lcl_getKeyString(m_rKeyMapping,aKeyEvent);
1333 xContainer->removeByName(sKey);
1336 void XCUBasedAcceleratorConfiguration::reloadChanged( const OUString& sPrimarySecondary, const OUString& sGlobalModules, const OUString& sModule, const OUString& sKey )
1338 css::uno::Reference< css::container::XNameAccess > xAccess;
1339 css::uno::Reference< css::container::XNameContainer > xContainer;
1341 m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1342 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1343 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1344 else
1346 css::uno::Reference< css::container::XNameAccess > xModules;
1347 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1348 if ( !xModules->hasByName(sModule) )
1349 return;
1350 xModules->getByName(sModule) >>= xContainer;
1353 css::awt::KeyEvent aKeyEvent;
1354 OUString sKeyIdentifier;
1356 sal_Int32 nIndex = 0;
1357 sKeyIdentifier = sKey.getToken(0, '_', nIndex);
1358 aKeyEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode("KEY_"+sKeyIdentifier);
1360 css::uno::Sequence< OUString > sToken(3);
1361 const sal_Int32 nToken = 3;
1362 for (sal_Int32 i=0; i<nToken; ++i)
1364 if ( nIndex < 0 )
1365 break;
1367 sToken[i] = sKey.getToken(0, '_', nIndex);
1368 if ( sToken[i] == "SHIFT" )
1369 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1370 else if ( sToken[i] == "MOD1" )
1371 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1372 else if ( sToken[i] == "MOD2" )
1373 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1374 else if ( sToken[i] == "MOD3" )
1375 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1378 css::uno::Reference< css::container::XNameAccess > xKey;
1379 css::uno::Reference< css::container::XNameAccess > xCommand;
1380 OUString sCommand;
1382 if (xContainer->hasByName(sKey))
1384 OUString sLocale = impl_ts_getLocale();
1385 xContainer->getByName(sKey) >>= xKey;
1386 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1387 xCommand->getByName(sLocale) >>= sCommand;
1390 if ( sPrimarySecondary == CFG_ENTRY_PRIMARY )
1392 if (sCommand.isEmpty())
1393 m_aPrimaryReadCache.removeKey(aKeyEvent);
1394 else
1395 m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1397 else if ( sPrimarySecondary == CFG_ENTRY_SECONDARY )
1399 if (sCommand.isEmpty())
1400 m_aSecondaryReadCache.removeKey(aKeyEvent);
1401 else
1402 m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1406 AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(bool bPreferred, bool bWriteAccessRequested)
1408 SolarMutexGuard g;
1410 if (bPreferred)
1412 //create copy of our readonly-cache, if write access is forced ... but
1413 //not still possible!
1414 if (
1415 (bWriteAccessRequested) &&
1416 (!m_pPrimaryWriteCache )
1419 m_pPrimaryWriteCache = new AcceleratorCache(m_aPrimaryReadCache);
1422 // in case, we have a writeable cache, we use it for reading too!
1423 // Otherwise the API user can't find its own changes ...
1424 if (m_pPrimaryWriteCache)
1425 return *m_pPrimaryWriteCache;
1426 else
1427 return m_aPrimaryReadCache;
1430 else
1432 //create copy of our readonly-cache, if write access is forced ... but
1433 //not still possible!
1434 if (
1435 (bWriteAccessRequested) &&
1436 (!m_pSecondaryWriteCache )
1439 m_pSecondaryWriteCache = new AcceleratorCache(m_aSecondaryReadCache);
1442 // in case, we have a writeable cache, we use it for reading too!
1443 // Otherwise the API user can't find its own changes ...
1444 if (m_pSecondaryWriteCache)
1445 return *m_pSecondaryWriteCache;
1446 else
1447 return m_aSecondaryReadCache;
1451 OUString XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1453 OUString sISOLocale = officecfg::Setup::L10N::ooLocale::get();
1455 if (sISOLocale.isEmpty())
1456 return OUString("en-US");
1457 return sISOLocale;
1460 } // namespace framework
1462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */