1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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"
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
)
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
)
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
)
103 AcceleratorCache
& rCache
= impl_getCFG();
104 if (!rCache
.hasKey(aKeyEvent
))
105 throw css::container::NoSuchElementException(
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
)
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),
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
)
143 AcceleratorCache
& rCache
= impl_getCFG(true); // true => force using of a writeable cache
144 if (!rCache
.hasKey(aKeyEvent
))
145 throw css::container::NoSuchElementException(
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),
163 AcceleratorCache
& rCache
= impl_getCFG();
164 if (!rCache
.hasCommand(sCommand
))
165 throw css::container::NoSuchElementException(
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
)
180 sal_Int32 c
= lCommandList
.getLength();
181 css::uno::Sequence
< css::uno::Any
> lPreferredOnes (c
); // dont pack list!
182 AcceleratorCache
& rCache
= impl_getCFG();
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),
193 if (!rCache
.hasCommand(rCommand
))
196 AcceleratorCache::TKeyList lKeys
= rCache
.getKeysByCommand(rCommand
);
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),
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
;
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
;
245 xIn
= xStream
->getInputStream();
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
254 m_aReadCache
= AcceleratorCache();
259 // Load also the general language independent default accelerators
260 // (ignoring the already defined accelerators)
261 if (xStreamNoLang
.is())
263 xIn
= xStreamNoLang
->getInputStream();
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
;
276 xStream
= m_aPresetHandler
.openTarget(TARGET_CURRENT
, true); // sal_True => open or create!
279 css::uno::Reference
< css::io::XOutputStream
> xOut
;
281 xOut
= xStream
->getOutputStream();
284 throw css::io::IOException(
285 OUString("Could not open accelerator configuration for saving."),
286 static_cast< ::cppu::OWeakObject
* >(this));
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(
303 css::embed::ElementModes::READWRITE
,
304 false); // False => no fallback from read/write to readonly!
305 css::uno::Reference
< css::io::XOutputStream
> xOut
;
307 xOut
= xStream
->getOutputStream();
310 throw css::io::IOException(
311 OUString("Could not open accelerator configuration for saving."),
312 static_cast< ::cppu::OWeakObject
* >(this));
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
)
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
;
332 xStream
= m_aPresetHandler
.openTarget(TARGET_CURRENT
, true); // sal_True => open or create!
335 css::uno::Reference
< css::io::XOutputStream
> xOut
;
337 xOut
= xStream
->getOutputStream();
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 .-)");
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
)
371 m_aPresetHandler
.copyPresetToTarget(PRESET_DEFAULT
, TARGET_CURRENT
);
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");
390 void XMLBasedAcceleratorConfiguration::changesOccurred(const OUString
& /*sPath*/)
395 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference
< css::io::XInputStream
>& xStream
)
397 css::uno::Reference
< css::uno::XComponentContext
> xContext
;
400 xContext
= m_xContext
;
403 // be aware of reentrance problems - use temp variable for calling delete ... :-)
404 AcceleratorCache
* pTemp
= m_pWriteCache
;
410 css::uno::Reference
< css::io::XSeekable
> xSeek(xStream
, css::uno::UNO_QUERY
);
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
)
439 AcceleratorCache aCache
;
440 css::uno::Reference
< css::uno::XComponentContext
> xContext
;
443 bChanged
= (m_pWriteCache
!= 0);
445 aCache
.takeOver(*m_pWriteCache
);
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
);
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
);
469 // take over all changes into the readonly cache ...
470 // and forget the copy-on-write copied cache
473 m_aReadCache
.takeOver(*m_pWriteCache
);
474 // live with reentrance .-)
475 AcceleratorCache
* pTemp
= m_pWriteCache
;
481 AcceleratorCache
& XMLBasedAcceleratorConfiguration::impl_getCFG(bool bWriteAccessRequested
)
485 //create copy of our readonly-cache, if write access is forced ... but
486 //not still possible!
488 (bWriteAccessRequested
) &&
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 ...
498 return *m_pWriteCache
;
503 OUString
XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
505 OUString sISOLocale
= officecfg::Setup::L10N::ooLocale::get();
507 if (sISOLocale
.isEmpty())
508 return OUString("en-US");
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
)
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
)
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(
562 static_cast< ::cppu::OWeakObject
* >(this));
564 if (rPrimaryCache
.hasKey(aKeyEvent
))
565 return rPrimaryCache
.getCommandByKey(aKeyEvent
);
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" );
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),
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
);
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
)
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(
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
);
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),
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(
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 ();
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())
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
)
748 sal_Int32 c
= lCommandList
.getLength();
749 css::uno::Sequence
< css::uno::Any
> lPreferredOnes (c
); // dont pack list!
750 AcceleratorCache
& rCache
= impl_getCFG(true);
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),
761 if (!rCache
.hasCommand(rCommand
))
764 AcceleratorCache::TKeyList lKeys
= rCache
.getKeysByCommand(rCommand
);
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),
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()" );
815 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
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;
826 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
827 impl_ts_load(bPreferred
, xAccess
); // load the preferred keys
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;
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()" );
851 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
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
);
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 ...
874 long nOpenModes
= css::embed::ElementModes::READWRITE
;
875 css::uno::Reference
< css::embed::XStorage
> xAcceleratorTypeStorage
= xStorage
->openStorageElement(OUString("accelerator"), nOpenModes
);
876 if (!xAcceleratorTypeStorage
.is())
879 css::uno::Reference
< css::io::XStream
> xStream
= xAcceleratorTypeStorage
->openStreamElement(OUString("current"), nOpenModes
);
880 css::uno::Reference
< css::io::XOutputStream
> xOut
;
882 xOut
= xStream
->getOutputStream();
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
;
894 if (m_pPrimaryWriteCache
!= 0)
895 aCache
.takeOver(*m_pPrimaryWriteCache
);
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
));
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
);
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
);
930 sal_Bool SAL_CALL
XCUBasedAcceleratorConfiguration::isModified()
931 throw(css::uno::RuntimeException
, std::exception
)
936 sal_Bool SAL_CALL
XCUBasedAcceleratorConfiguration::isReadOnly()
937 throw(css::uno::RuntimeException
, std::exception
)
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 .-)");
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 ())
1010 css::util::ChangesEvent
aReceivedEvents( aEvent
);
1011 const sal_Int32 c
= aReceivedEvents
.Changes
.getLength();
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.
1026 aChange
.Accessor
>>= sOrgPath
;
1028 OUString sPrimarySecondary
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1029 OUString sGlobalModules
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1031 if ( sGlobalModules
== CFG_ENTRY_GLOBAL
)
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
)
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
)
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
)
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
;
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
)
1115 if ( pFound
== aLocales
.end() )
1117 for ( pFound
= aLocales
.begin(); pFound
!= aLocales
.end(); ++pFound
)
1119 if ( *pFound
== sDefaultLocale
)
1123 if ( pFound
== aLocales
.end() )
1127 OUString sLocale
= *pFound
;
1129 xCommand
->getByName(sLocale
) >>= sCommand
;
1130 if (sCommand
.isEmpty())
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;
1144 for (k
=0; k
<nToken
; ++k
)
1149 sToken
[k
] = sKey
.getToken(0, '_', nIndex
);
1150 if (sToken
[k
].isEmpty())
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
;
1171 if ( !aReadCache
.hasKey(aKeyEvent
) && bValid
&& k
<nToken
)
1172 aReadCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
1177 m_aPrimaryReadCache
.takeOver(aReadCache
);
1179 m_aSecondaryReadCache
.takeOver(aReadCache
);
1182 void XCUBasedAcceleratorConfiguration::impl_ts_save(bool bPreferred
, const css::uno::Reference
< css::container::XNameAccess
>& /*xCfg*/)
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);
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
1213 // coverity[check_after_deref]
1214 if (m_pPrimaryWriteCache
)
1216 m_aPrimaryReadCache
.takeOver(*m_pPrimaryWriteCache
);
1217 AcceleratorCache
* pTemp
= m_pPrimaryWriteCache
;
1218 m_pPrimaryWriteCache
= 0;
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);
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
1252 // coverity[check_after_deref]
1253 if (m_pSecondaryWriteCache
)
1255 m_aSecondaryReadCache
.takeOver(*m_pSecondaryWriteCache
);
1256 AcceleratorCache
* pTemp
= m_pSecondaryWriteCache
;
1257 m_pSecondaryWriteCache
= 0;
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
;
1273 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
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
));
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
;
1317 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
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
) )
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
;
1346 css::uno::Reference
< css::container::XNameAccess
> xModules
;
1347 xAccess
->getByName(CFG_ENTRY_MODULES
) >>= xModules
;
1348 if ( !xModules
->hasByName(sModule
) )
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
)
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
;
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
);
1395 m_aPrimaryReadCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
1397 else if ( sPrimarySecondary
== CFG_ENTRY_SECONDARY
)
1399 if (sCommand
.isEmpty())
1400 m_aSecondaryReadCache
.removeKey(aKeyEvent
);
1402 m_aSecondaryReadCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
1406 AcceleratorCache
& XCUBasedAcceleratorConfiguration::impl_getCFG(bool bPreferred
, bool bWriteAccessRequested
)
1412 //create copy of our readonly-cache, if write access is forced ... but
1413 //not still possible!
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
;
1427 return m_aPrimaryReadCache
;
1432 //create copy of our readonly-cache, if write access is forced ... but
1433 //not still possible!
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
;
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");
1460 } // namespace framework
1462 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */