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>
21 #include <accelerators/keymapping.hxx>
22 #include <accelerators/presethandler.hxx>
24 #include <xml/saxnamespacefilter.hxx>
25 #include <xml/acceleratorconfigurationreader.hxx>
26 #include <xml/acceleratorconfigurationwriter.hxx>
28 #include <acceleratorconst.h>
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(const css::awt::KeyEvent
& aKeyEvent
)
62 const sal_Int32 nBeginIndex
= 4; // "KEY_" is the prefix of a identifier...
63 OUStringBuffer
sKeyBuffer((KeyMapping::get().mapCodeToIdentifier(aKeyEvent
.KeyCode
)).copy(nBeginIndex
));
65 if ( (aKeyEvent
.Modifiers
& css::awt::KeyModifier::SHIFT
) == css::awt::KeyModifier::SHIFT
)
66 sKeyBuffer
.append("_SHIFT");
67 if ( (aKeyEvent
.Modifiers
& css::awt::KeyModifier::MOD1
) == css::awt::KeyModifier::MOD1
)
68 sKeyBuffer
.append("_MOD1");
69 if ( (aKeyEvent
.Modifiers
& css::awt::KeyModifier::MOD2
) == css::awt::KeyModifier::MOD2
)
70 sKeyBuffer
.append("_MOD2");
71 if ( (aKeyEvent
.Modifiers
& css::awt::KeyModifier::MOD3
) == css::awt::KeyModifier::MOD3
)
72 sKeyBuffer
.append("_MOD3");
74 return sKeyBuffer
.makeStringAndClear();
77 XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
78 : m_xContext (xContext
)
79 , m_aPresetHandler(xContext
)
80 , m_pWriteCache (nullptr )
84 XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration()
86 SAL_WARN_IF(m_pWriteCache
, "fwk", "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration(): Changes not flushed. Ignore it ...");
89 css::uno::Sequence
< css::awt::KeyEvent
> SAL_CALL
XMLBasedAcceleratorConfiguration::getAllKeyEvents()
90 throw(css::uno::RuntimeException
, std::exception
)
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
); // don't 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
,
236 css::embed::ElementModes::READ
);
239 xStreamNoLang
= m_aPresetHandler
.openPreset(PRESET_DEFAULT
);
241 catch(const css::io::IOException
&) {} // does not have to exist
244 css::uno::Reference
< css::io::XInputStream
> xIn
;
246 xIn
= xStream
->getInputStream();
248 throw css::io::IOException(
249 OUString("Could not open accelerator configuration for reading."),
250 static_cast< ::cppu::OWeakObject
* >(this));
252 // impl_ts_load() does not clear the cache
255 m_aReadCache
= AcceleratorCache();
260 // Load also the general language independent default accelerators
261 // (ignoring the already defined accelerators)
262 if (xStreamNoLang
.is())
264 xIn
= xStreamNoLang
->getInputStream();
270 void SAL_CALL
XMLBasedAcceleratorConfiguration::store()
271 throw(css::uno::Exception
,
272 css::uno::RuntimeException
, std::exception
)
274 css::uno::Reference
< css::io::XStream
> xStream
;
277 xStream
= m_aPresetHandler
.openTarget(TARGET_CURRENT
,
278 css::embed::ElementModes::READWRITE
); // open or create!
281 css::uno::Reference
< css::io::XOutputStream
> xOut
;
283 xOut
= xStream
->getOutputStream();
286 throw css::io::IOException(
287 OUString("Could not open accelerator configuration for saving."),
288 static_cast< ::cppu::OWeakObject
* >(this));
295 m_aPresetHandler
.commitUserChanges();
298 void SAL_CALL
XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
299 throw(css::uno::Exception
,
300 css::uno::RuntimeException
, std::exception
)
302 css::uno::Reference
< css::io::XStream
> xStream
= StorageHolder::openSubStreamWithFallback(
305 css::embed::ElementModes::READWRITE
,
306 false); // False => no fallback from read/write to readonly!
307 css::uno::Reference
< css::io::XOutputStream
> xOut
;
309 xOut
= xStream
->getOutputStream();
312 throw css::io::IOException(
313 OUString("Could not open accelerator configuration for saving."),
314 static_cast< ::cppu::OWeakObject
* >(this));
318 // TODO inform listener about success, so it can flush the root and sub storage of this stream!
321 sal_Bool SAL_CALL
XMLBasedAcceleratorConfiguration::isModified()
322 throw(css::uno::RuntimeException
, std::exception
)
325 return (m_pWriteCache
!= nullptr);
328 sal_Bool SAL_CALL
XMLBasedAcceleratorConfiguration::isReadOnly()
329 throw(css::uno::RuntimeException
, std::exception
)
331 css::uno::Reference
< css::io::XStream
> xStream
;
334 xStream
= m_aPresetHandler
.openTarget(TARGET_CURRENT
,
335 css::embed::ElementModes::READWRITE
); // open or create!
338 css::uno::Reference
< css::io::XOutputStream
> xOut
;
340 xOut
= xStream
->getOutputStream();
344 void SAL_CALL
XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference
< css::embed::XStorage
>& /*xStorage*/)
345 throw(css::uno::RuntimeException
, std::exception
)
347 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
350 sal_Bool SAL_CALL
XMLBasedAcceleratorConfiguration::hasStorage()
351 throw(css::uno::RuntimeException
, std::exception
)
353 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
357 void SAL_CALL
XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference
< css::ui::XUIConfigurationListener
>& /*xListener*/)
358 throw(css::uno::RuntimeException
, std::exception
)
360 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
363 void SAL_CALL
XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference
< css::ui::XUIConfigurationListener
>& /*xListener*/)
364 throw(css::uno::RuntimeException
, std::exception
)
366 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
369 void SAL_CALL
XMLBasedAcceleratorConfiguration::reset()
370 throw(css::uno::RuntimeException
, std::exception
)
374 m_aPresetHandler
.copyPresetToTarget(PRESET_DEFAULT
, TARGET_CURRENT
);
380 void SAL_CALL
XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference
< css::form::XResetListener
>& /*xListener*/)
381 throw(css::uno::RuntimeException
, std::exception
)
383 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::addResetListener(): implement me");
386 void SAL_CALL
XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference
< css::form::XResetListener
>& /*xListener*/)
387 throw(css::uno::RuntimeException
, std::exception
)
389 SAL_INFO("fwk", "XMLBasedAcceleratorConfiguration::removeResetListener(): implement me");
393 void XMLBasedAcceleratorConfiguration::changesOccurred()
398 void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference
< css::io::XInputStream
>& xStream
)
400 css::uno::Reference
< css::uno::XComponentContext
> xContext
;
403 xContext
= m_xContext
;
406 // be aware of reentrance problems - use temp variable for calling delete ... :-)
407 AcceleratorCache
* pTemp
= m_pWriteCache
;
408 m_pWriteCache
= nullptr;
413 css::uno::Reference
< css::io::XSeekable
> xSeek(xStream
, css::uno::UNO_QUERY
);
419 // create the parser queue
420 // Note: Use special filter object between parser and reader
421 // to get filtered xml with right namespaces ...
422 // Use further a temp cache for reading!
423 AcceleratorConfigurationReader
* pReader
= new AcceleratorConfigurationReader(m_aReadCache
);
424 css::uno::Reference
< css::xml::sax::XDocumentHandler
> xReader (static_cast< ::cppu::OWeakObject
* >(pReader
), css::uno::UNO_QUERY_THROW
);
425 SaxNamespaceFilter
* pFilter
= new SaxNamespaceFilter(xReader
);
426 css::uno::Reference
< css::xml::sax::XDocumentHandler
> xFilter (static_cast< ::cppu::OWeakObject
* >(pFilter
), css::uno::UNO_QUERY_THROW
);
428 // connect parser, filter and stream
429 css::uno::Reference
< css::xml::sax::XParser
> xParser
= css::xml::sax::Parser::create(xContext
);
430 xParser
->setDocumentHandler(xFilter
);
432 css::xml::sax::InputSource aSource
;
433 aSource
.aInputStream
= xStream
;
435 // TODO think about error handling
436 xParser
->parseStream(aSource
);
439 void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference
< css::io::XOutputStream
>& xStream
)
442 AcceleratorCache aCache
;
443 css::uno::Reference
< css::uno::XComponentContext
> xContext
;
446 bChanged
= (m_pWriteCache
!= nullptr);
448 aCache
.takeOver(*m_pWriteCache
);
450 aCache
.takeOver(m_aReadCache
);
451 xContext
= m_xContext
;
454 css::uno::Reference
< css::io::XTruncate
> xClearable(xStream
, css::uno::UNO_QUERY_THROW
);
455 xClearable
->truncate();
457 // TODO can be removed if seek(0) is done by truncate() automatically!
458 css::uno::Reference
< css::io::XSeekable
> xSeek(xStream
, css::uno::UNO_QUERY
);
462 // combine writer/cache/stream etcpp.
463 css::uno::Reference
< css::xml::sax::XWriter
> xWriter
= css::xml::sax::Writer::create(xContext
);
464 xWriter
->setOutputStream(xStream
);
466 // write into the stream
467 css::uno::Reference
< css::xml::sax::XDocumentHandler
> xHandler(xWriter
, css::uno::UNO_QUERY_THROW
);
468 AcceleratorConfigurationWriter
aWriter(aCache
, xHandler
);
472 // take over all changes into the readonly cache ...
473 // and forget the copy-on-write copied cache
476 m_aReadCache
.takeOver(*m_pWriteCache
);
477 // live with reentrance .-)
478 AcceleratorCache
* pTemp
= m_pWriteCache
;
479 m_pWriteCache
= nullptr;
484 AcceleratorCache
& XMLBasedAcceleratorConfiguration::impl_getCFG(bool bWriteAccessRequested
)
488 //create copy of our readonly-cache, if write access is forced ... but
489 //not still possible!
491 (bWriteAccessRequested
) &&
495 m_pWriteCache
= new AcceleratorCache(m_aReadCache
);
498 // in case, we have a writeable cache, we use it for reading too!
499 // Otherwise the API user can't find its own changes ...
501 return *m_pWriteCache
;
506 OUString
XMLBasedAcceleratorConfiguration::impl_ts_getLocale() const
508 OUString sISOLocale
= officecfg::Setup::L10N::ooLocale::get();
510 if (sISOLocale
.isEmpty())
511 return OUString("en-US");
515 /*******************************************************************************
517 * XCU based accelerator configuration
519 *******************************************************************************/
521 XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
522 : m_xContext (xContext
)
523 , m_pPrimaryWriteCache(nullptr )
524 , m_pSecondaryWriteCache(nullptr )
526 const OUString
CFG_ENTRY_ACCELERATORS("org.openoffice.Office.Accelerators");
528 ::comphelper::ConfigurationHelper::openConfig( m_xContext
, CFG_ENTRY_ACCELERATORS
, ::comphelper::EConfigurationModes::AllLocales
),
529 css::uno::UNO_QUERY
);
532 XCUBasedAcceleratorConfiguration::~XCUBasedAcceleratorConfiguration()
536 css::uno::Sequence
< css::awt::KeyEvent
> SAL_CALL
XCUBasedAcceleratorConfiguration::getAllKeyEvents()
537 throw(css::uno::RuntimeException
, std::exception
)
541 AcceleratorCache::TKeyList lKeys
= impl_getCFG(true).getAllKeys(); //get keys from PrimaryKeys set
543 AcceleratorCache::TKeyList lSecondaryKeys
= impl_getCFG(false).getAllKeys(); //get keys from SecondaryKeys set
544 lKeys
.reserve(lKeys
.size()+lSecondaryKeys
.size());
545 AcceleratorCache::TKeyList::const_iterator pIt
;
546 AcceleratorCache::TKeyList::const_iterator pEnd
= lSecondaryKeys
.end();
547 for ( pIt
= lSecondaryKeys
.begin(); pIt
!= pEnd
; ++pIt
)
548 lKeys
.push_back(*pIt
);
550 return comphelper::containerToSequence(lKeys
);
553 OUString SAL_CALL
XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent
& aKeyEvent
)
554 throw(css::container::NoSuchElementException
,
555 css::uno::RuntimeException
, std::exception
)
559 AcceleratorCache
& rPrimaryCache
= impl_getCFG(true );
560 AcceleratorCache
& rSecondaryCache
= impl_getCFG(false);
562 if (!rPrimaryCache
.hasKey(aKeyEvent
) && !rSecondaryCache
.hasKey(aKeyEvent
))
563 throw css::container::NoSuchElementException(
565 static_cast< ::cppu::OWeakObject
* >(this));
567 if (rPrimaryCache
.hasKey(aKeyEvent
))
568 return rPrimaryCache
.getCommandByKey(aKeyEvent
);
570 return rSecondaryCache
.getCommandByKey(aKeyEvent
);
573 void SAL_CALL
XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent
& aKeyEvent
,
574 const OUString
& sCommand
)
575 throw (css::lang::IllegalArgumentException
,
576 css::container::NoSuchElementException
,
577 css::uno::RuntimeException
, std::exception
)
579 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::setKeyEvent" );
582 (aKeyEvent
.KeyCode
== 0) &&
583 (aKeyEvent
.KeyChar
== 0) &&
584 (aKeyEvent
.KeyFunc
== 0) &&
585 (aKeyEvent
.Modifiers
== 0)
587 throw css::lang::IllegalArgumentException(
588 OUString("Such key event seems not to be supported by any operating system."),
589 static_cast< ::cppu::OWeakObject
* >(this),
592 if (sCommand
.isEmpty())
593 throw css::lang::IllegalArgumentException(
594 OUString("Empty command strings are not allowed here."),
595 static_cast< ::cppu::OWeakObject
* >(this),
600 AcceleratorCache
& rPrimaryCache
= impl_getCFG(true, true ); // sal_True => force getting of a writeable cache!
601 AcceleratorCache
& rSecondaryCache
= impl_getCFG(false, true); // sal_True => force getting of a writeable cache!
603 if ( rPrimaryCache
.hasKey(aKeyEvent
) )
605 OUString sOriginalCommand
= rPrimaryCache
.getCommandByKey(aKeyEvent
);
606 if ( sCommand
!= sOriginalCommand
)
608 if (rSecondaryCache
.hasCommand(sOriginalCommand
))
610 AcceleratorCache::TKeyList lSecondaryKeys
= rSecondaryCache
.getKeysByCommand(sOriginalCommand
);
611 rSecondaryCache
.removeKey(lSecondaryKeys
[0]);
612 rPrimaryCache
.setKeyCommandPair(lSecondaryKeys
[0], sOriginalCommand
);
615 if (rPrimaryCache
.hasCommand(sCommand
))
617 AcceleratorCache::TKeyList lPrimaryKeys
= rPrimaryCache
.getKeysByCommand(sCommand
);
618 rPrimaryCache
.removeKey(lPrimaryKeys
[0]);
619 rSecondaryCache
.setKeyCommandPair(lPrimaryKeys
[0], sCommand
);
622 rPrimaryCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
626 else if ( rSecondaryCache
.hasKey(aKeyEvent
) )
628 OUString sOriginalCommand
= rSecondaryCache
.getCommandByKey(aKeyEvent
);
629 if (sCommand
!= sOriginalCommand
)
631 if (rPrimaryCache
.hasCommand(sCommand
))
633 AcceleratorCache::TKeyList lPrimaryKeys
= rPrimaryCache
.getKeysByCommand(sCommand
);
634 rPrimaryCache
.removeKey(lPrimaryKeys
[0]);
635 rSecondaryCache
.setKeyCommandPair(lPrimaryKeys
[0], sCommand
);
638 rSecondaryCache
.removeKey(aKeyEvent
);
639 rPrimaryCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
645 if (rPrimaryCache
.hasCommand(sCommand
))
647 AcceleratorCache::TKeyList lPrimaryKeys
= rPrimaryCache
.getKeysByCommand(sCommand
);
648 rPrimaryCache
.removeKey(lPrimaryKeys
[0]);
649 rSecondaryCache
.setKeyCommandPair(lPrimaryKeys
[0], sCommand
);
652 rPrimaryCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
656 void SAL_CALL
XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent
& aKeyEvent
)
657 throw(css::container::NoSuchElementException
,
658 css::uno::RuntimeException
, std::exception
)
662 AcceleratorCache
& rPrimaryCache
= impl_getCFG(true, true );
663 AcceleratorCache
& rSecondaryCache
= impl_getCFG(false, true);
665 if (!rPrimaryCache
.hasKey(aKeyEvent
) && !rSecondaryCache
.hasKey(aKeyEvent
))
666 throw css::container::NoSuchElementException(
668 static_cast< ::cppu::OWeakObject
* >(this));
670 if (rPrimaryCache
.hasKey(aKeyEvent
))
672 OUString sDelCommand
= rPrimaryCache
.getCommandByKey(aKeyEvent
);
673 if (!sDelCommand
.isEmpty())
675 OUString sOriginalCommand
= rPrimaryCache
.getCommandByKey(aKeyEvent
);
676 if (rSecondaryCache
.hasCommand(sOriginalCommand
))
678 AcceleratorCache::TKeyList lSecondaryKeys
= rSecondaryCache
.getKeysByCommand(sOriginalCommand
);
679 rSecondaryCache
.removeKey(lSecondaryKeys
[0]);
680 rPrimaryCache
.setKeyCommandPair(lSecondaryKeys
[0], sOriginalCommand
);
683 rPrimaryCache
.removeKey(aKeyEvent
);
689 OUString sDelCommand
= rSecondaryCache
.getCommandByKey(aKeyEvent
);
690 if (!sDelCommand
.isEmpty())
691 rSecondaryCache
.removeKey(aKeyEvent
);
695 css::uno::Sequence
< css::awt::KeyEvent
> SAL_CALL
XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString
& sCommand
)
696 throw(css::lang::IllegalArgumentException
,
697 css::container::NoSuchElementException
,
698 css::uno::RuntimeException
, std::exception
)
700 if (sCommand
.isEmpty())
701 throw css::lang::IllegalArgumentException(
702 OUString("Empty command strings are not allowed here."),
703 static_cast< ::cppu::OWeakObject
* >(this),
708 AcceleratorCache
& rPrimaryCache
= impl_getCFG(true );
709 AcceleratorCache
& rSecondaryCache
= impl_getCFG(false);
711 if (!rPrimaryCache
.hasCommand(sCommand
) && !rSecondaryCache
.hasCommand(sCommand
))
712 throw css::container::NoSuchElementException(
714 static_cast< ::cppu::OWeakObject
* >(this));
716 AcceleratorCache::TKeyList lKeys
= rPrimaryCache
.getKeysByCommand(sCommand
);
718 AcceleratorCache::TKeyList lSecondaryKeys
= rSecondaryCache
.getKeysByCommand(sCommand
);
719 AcceleratorCache::TKeyList::const_iterator pIt
;
720 for (pIt
= lSecondaryKeys
.begin(); pIt
!= lSecondaryKeys
.end(); ++pIt
)
721 lKeys
.push_back(*pIt
);
723 return comphelper::containerToSequence(lKeys
);
726 AcceleratorCache::TKeyList::const_iterator
lcl_getPreferredKey(const AcceleratorCache::TKeyList
& lKeys
)
728 AcceleratorCache::TKeyList::const_iterator pIt
;
729 for ( pIt
= lKeys
.begin ();
733 const css::awt::KeyEvent
& rAWTKey
= *pIt
;
734 const vcl::KeyCode aVCLKey
= ::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey
);
735 const OUString sName
= aVCLKey
.GetName();
737 if (!sName
.isEmpty())
744 css::uno::Sequence
< css::uno::Any
> SAL_CALL
XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence
< OUString
>& lCommandList
)
745 throw(css::lang::IllegalArgumentException
, css::container::NoSuchElementException
,
746 css::uno::RuntimeException
, std::exception
)
751 sal_Int32 c
= lCommandList
.getLength();
752 css::uno::Sequence
< css::uno::Any
> lPreferredOnes (c
); // don't pack list!
753 AcceleratorCache
& rCache
= impl_getCFG(true);
757 const OUString
& rCommand
= lCommandList
[i
];
758 if (rCommand
.isEmpty())
759 throw css::lang::IllegalArgumentException(
760 OUString("Empty command strings are not allowed here."),
761 static_cast< ::cppu::OWeakObject
* >(this),
764 if (!rCache
.hasCommand(rCommand
))
767 AcceleratorCache::TKeyList lKeys
= rCache
.getKeysByCommand(rCommand
);
771 AcceleratorCache::TKeyList::const_iterator pPreferredKey
= lcl_getPreferredKey(lKeys
);
772 if (pPreferredKey
!= lKeys
.end ())
774 css::uno::Any
& rAny
= lPreferredOnes
[i
];
775 rAny
<<= *(pPreferredKey
);
779 return lPreferredOnes
;
782 void SAL_CALL
XCUBasedAcceleratorConfiguration::removeCommandFromAllKeyEvents(const OUString
& sCommand
)
783 throw(css::lang::IllegalArgumentException
,
784 css::container::NoSuchElementException
,
785 css::uno::RuntimeException
, std::exception
)
787 if (sCommand
.isEmpty())
788 throw css::lang::IllegalArgumentException(
789 OUString("Empty command strings are not allowed here."),
790 static_cast< ::cppu::OWeakObject
* >(this),
795 AcceleratorCache
& rPrimaryCache
= impl_getCFG(true, true );
796 AcceleratorCache
& rSecondaryCache
= impl_getCFG(false, true);
798 if (!rPrimaryCache
.hasCommand(sCommand
) && !rSecondaryCache
.hasCommand(sCommand
))
799 throw css::container::NoSuchElementException(
800 OUString("Command does not exists inside this container."),
801 static_cast< ::cppu::OWeakObject
* >(this));
803 if (rPrimaryCache
.hasCommand(sCommand
))
804 rPrimaryCache
.removeCommand(sCommand
);
805 if (rSecondaryCache
.hasCommand(sCommand
))
806 rSecondaryCache
.removeCommand(sCommand
);
809 void SAL_CALL
XCUBasedAcceleratorConfiguration::reload()
810 throw(css::uno::Exception
,
811 css::uno::RuntimeException
, std::exception
)
813 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::reload()" );
818 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
821 m_aPrimaryReadCache
= AcceleratorCache();
822 if (m_pPrimaryWriteCache
)
824 // be aware of reentrance problems - use temp variable for calling delete ... :-)
825 AcceleratorCache
* pTemp
= m_pPrimaryWriteCache
;
826 m_pPrimaryWriteCache
= nullptr;
829 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
830 impl_ts_load(bPreferred
, xAccess
); // load the preferred keys
833 m_aSecondaryReadCache
= AcceleratorCache();
834 if (m_pSecondaryWriteCache
)
836 // be aware of reentrance problems - use temp variable for calling delete ... :-)
837 AcceleratorCache
* pTemp
= m_pSecondaryWriteCache
;
838 m_pSecondaryWriteCache
= nullptr;
841 m_xCfg
->getByName(CFG_ENTRY_SECONDARY
) >>= xAccess
;
842 impl_ts_load(bPreferred
, xAccess
); // load the secondary keys
845 void SAL_CALL
XCUBasedAcceleratorConfiguration::store()
846 throw(css::uno::Exception
,
847 css::uno::RuntimeException
, std::exception
)
849 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::store()" );
854 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
857 // on-demand creation of the primary write cache
858 impl_getCFG(bPreferred
, true);
859 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
860 impl_ts_save(bPreferred
, xAccess
);
863 // on-demand creation of the secondary write cache
864 impl_getCFG(bPreferred
, true);
865 m_xCfg
->getByName(CFG_ENTRY_SECONDARY
) >>= xAccess
;
866 impl_ts_save(bPreferred
, xAccess
);
869 void SAL_CALL
XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
870 throw(css::uno::Exception
,
871 css::uno::RuntimeException
, std::exception
)
873 // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
877 long nOpenModes
= css::embed::ElementModes::READWRITE
;
878 css::uno::Reference
< css::embed::XStorage
> xAcceleratorTypeStorage
= xStorage
->openStorageElement("accelerator", nOpenModes
);
879 if (!xAcceleratorTypeStorage
.is())
882 css::uno::Reference
< css::io::XStream
> xStream
= xAcceleratorTypeStorage
->openStreamElement("current", nOpenModes
);
883 css::uno::Reference
< css::io::XOutputStream
> xOut
;
885 xOut
= xStream
->getOutputStream();
887 throw css::io::IOException(
888 OUString("Could not open accelerator configuration for saving."),
889 static_cast< ::cppu::OWeakObject
* >(this));
891 // the original m_aCache has been split into primary cache and secondary cache...
892 // we should merge them before storing to storage
893 AcceleratorCache aCache
;
897 if (m_pPrimaryWriteCache
!= nullptr)
898 aCache
.takeOver(*m_pPrimaryWriteCache
);
900 aCache
.takeOver(m_aPrimaryReadCache
);
902 AcceleratorCache::TKeyList lKeys
;
903 AcceleratorCache::TKeyList::const_iterator pIt
;
904 if (m_pSecondaryWriteCache
!=nullptr)
906 lKeys
= m_pSecondaryWriteCache
->getAllKeys();
907 for ( pIt
=lKeys
.begin(); pIt
!=lKeys
.end(); ++pIt
)
908 aCache
.setKeyCommandPair(*pIt
, m_pSecondaryWriteCache
->getCommandByKey(*pIt
));
912 lKeys
= m_aSecondaryReadCache
.getAllKeys();
913 for ( pIt
=lKeys
.begin(); pIt
!=lKeys
.end(); ++pIt
)
914 aCache
.setKeyCommandPair(*pIt
, m_aSecondaryReadCache
.getCommandByKey(*pIt
));
918 css::uno::Reference
< css::io::XTruncate
> xClearable(xOut
, css::uno::UNO_QUERY_THROW
);
919 xClearable
->truncate();
920 css::uno::Reference
< css::io::XSeekable
> xSeek(xOut
, css::uno::UNO_QUERY
);
924 css::uno::Reference
< css::xml::sax::XWriter
> xWriter
= css::xml::sax::Writer::create(m_xContext
);
925 xWriter
->setOutputStream(xOut
);
927 // write into the stream
928 css::uno::Reference
< css::xml::sax::XDocumentHandler
> xHandler(xWriter
, css::uno::UNO_QUERY_THROW
);
929 AcceleratorConfigurationWriter
aWriter(aCache
, xHandler
);
933 sal_Bool SAL_CALL
XCUBasedAcceleratorConfiguration::isModified()
934 throw(css::uno::RuntimeException
, std::exception
)
939 sal_Bool SAL_CALL
XCUBasedAcceleratorConfiguration::isReadOnly()
940 throw(css::uno::RuntimeException
, std::exception
)
945 void SAL_CALL
XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference
< css::embed::XStorage
>& /*xStorage*/)
946 throw(css::uno::RuntimeException
, std::exception
)
948 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
951 sal_Bool SAL_CALL
XCUBasedAcceleratorConfiguration::hasStorage()
952 throw(css::uno::RuntimeException
, std::exception
)
954 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
958 void SAL_CALL
XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference
< css::ui::XUIConfigurationListener
>& /*xListener*/)
959 throw(css::uno::RuntimeException
, std::exception
)
961 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
964 void SAL_CALL
XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference
< css::ui::XUIConfigurationListener
>& /*xListener*/)
965 throw(css::uno::RuntimeException
, std::exception
)
967 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
970 void SAL_CALL
XCUBasedAcceleratorConfiguration::reset()
971 throw(css::uno::RuntimeException
, std::exception
)
973 css::uno::Reference
< css::container::XNamed
> xNamed(m_xCfg
, css::uno::UNO_QUERY
);
974 OUString sConfig
= xNamed
->getName();
975 if ( sConfig
== "Global" )
978 ::comphelper::ConfigurationHelper::openConfig( m_xContext
, CFG_ENTRY_GLOBAL
, ::comphelper::EConfigurationModes::AllLocales
),
979 css::uno::UNO_QUERY
);
980 XCUBasedAcceleratorConfiguration::reload();
982 else if ( sConfig
== "Modules" )
985 ::comphelper::ConfigurationHelper::openConfig( m_xContext
, CFG_ENTRY_MODULES
, ::comphelper::EConfigurationModes::AllLocales
),
986 css::uno::UNO_QUERY
);
987 XCUBasedAcceleratorConfiguration::reload();
991 void SAL_CALL
XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference
< css::form::XResetListener
>& /*xListener*/)
992 throw(css::uno::RuntimeException
, std::exception
)
994 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::addResetListener(): implement me");
997 void SAL_CALL
XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference
< css::form::XResetListener
>& /*xListener*/)
998 throw(css::uno::RuntimeException
, std::exception
)
1000 SAL_INFO("fwk", "XCUBasedAcceleratorConfiguration::removeResetListener(): implement me");
1003 void SAL_CALL
XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent
& aEvent
)
1004 throw(css::uno::RuntimeException
, std::exception
)
1006 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::changesOccurred()" );
1008 css::uno::Reference
< css::container::XHierarchicalNameAccess
> xHAccess
;
1009 aEvent
.Base
>>= xHAccess
;
1010 if (! xHAccess
.is ())
1013 css::util::ChangesEvent
aReceivedEvents( aEvent
);
1014 const sal_Int32 c
= aReceivedEvents
.Changes
.getLength();
1018 const css::util::ElementChange
& aChange
= aReceivedEvents
.Changes
[i
];
1020 // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
1021 // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
1022 // So we try to split the path into 3 parts (module isn't important here, because we already know it ... because
1023 // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
1029 aChange
.Accessor
>>= sOrgPath
;
1031 OUString sPrimarySecondary
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1032 OUString sGlobalModules
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1034 if ( sGlobalModules
== CFG_ENTRY_GLOBAL
)
1037 sKey
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1038 if ( !sKey
.isEmpty() && !sPath
.isEmpty() )
1039 reloadChanged(sPrimarySecondary
, sGlobalModules
, sModule
, sKey
);
1041 else if ( sGlobalModules
== CFG_ENTRY_MODULES
)
1043 OUString sModule
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1044 sKey
= ::utl::extractFirstFromConfigurationPath(sPath
, &sPath
);
1046 if ( !sKey
.isEmpty() && !sPath
.isEmpty() )
1048 reloadChanged(sPrimarySecondary
, sGlobalModules
, sModule
, sKey
);
1054 void SAL_CALL
XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject
& /*aSource*/)
1055 throw(css::uno::RuntimeException
, std::exception
)
1059 void SAL_CALL
XCUBasedAcceleratorConfiguration::dispose()
1060 throw(css::uno::RuntimeException
, std::exception
)
1065 void SAL_CALL
XCUBasedAcceleratorConfiguration::addEventListener( const css::uno::Reference
< css::lang::XEventListener
>& /*xListener*/ )
1066 throw(css::uno::RuntimeException
, std::exception
)
1071 void SAL_CALL
XCUBasedAcceleratorConfiguration::removeEventListener( const css::uno::Reference
< css::lang::XEventListener
>& /*xListener*/ )
1072 throw(css::uno::RuntimeException
, std::exception
)
1077 void XCUBasedAcceleratorConfiguration::impl_ts_load( bool bPreferred
, const css::uno::Reference
< css::container::XNameAccess
>& xCfg
)
1079 AcceleratorCache aReadCache
= AcceleratorCache();
1080 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
1081 if ( m_sGlobalOrModules
== "Global" )
1082 xCfg
->getByName(CFG_ENTRY_GLOBAL
) >>= xAccess
;
1083 else if ( m_sGlobalOrModules
== "Modules" )
1085 css::uno::Reference
< css::container::XNameAccess
> xModules
;
1086 xCfg
->getByName(CFG_ENTRY_MODULES
) >>= xModules
;
1087 xModules
->getByName(m_sModuleCFG
) >>= xAccess
;
1090 const OUString sIsoLang
= impl_ts_getLocale();
1091 const OUString
sDefaultLocale("en-US");
1093 css::uno::Reference
< css::container::XNameAccess
> xKey
;
1094 css::uno::Reference
< css::container::XNameAccess
> xCommand
;
1097 css::uno::Sequence
< OUString
> lKeys
= xAccess
->getElementNames();
1098 sal_Int32 nKeys
= lKeys
.getLength();
1099 for ( sal_Int32 i
=0; i
<nKeys
; ++i
)
1101 OUString sKey
= lKeys
[i
];
1102 xAccess
->getByName(sKey
) >>= xKey
;
1103 xKey
->getByName(CFG_PROP_COMMAND
) >>= xCommand
;
1105 css::uno::Sequence
< OUString
> lLocales
= xCommand
->getElementNames();
1106 sal_Int32 nLocales
= lLocales
.getLength();
1107 ::std::vector
< OUString
> aLocales
;
1108 for ( sal_Int32 j
=0; j
<nLocales
; ++j
)
1109 aLocales
.push_back(lLocales
[j
]);
1111 ::std::vector
< OUString
>::const_iterator pFound
;
1112 for ( pFound
= aLocales
.begin(); pFound
!= aLocales
.end(); ++pFound
)
1114 if ( *pFound
== sIsoLang
)
1118 if ( pFound
== aLocales
.end() )
1120 for ( pFound
= aLocales
.begin(); pFound
!= aLocales
.end(); ++pFound
)
1122 if ( *pFound
== sDefaultLocale
)
1126 if ( pFound
== aLocales
.end() )
1130 OUString sLocale
= *pFound
;
1132 xCommand
->getByName(sLocale
) >>= sCommand
;
1133 if (sCommand
.isEmpty())
1136 css::awt::KeyEvent aKeyEvent
;
1138 sal_Int32 nIndex
= 0;
1139 OUString sKeyCommand
= sKey
.getToken(0, '_', nIndex
);
1140 OUString
sPrefix("KEY_");
1141 aKeyEvent
.KeyCode
= KeyMapping::get().mapIdentifierToCode(sPrefix
+ sKeyCommand
);
1143 css::uno::Sequence
< OUString
> sToken(4);
1144 const sal_Int32 nToken
= 4;
1147 for (k
=0; k
<nToken
; ++k
)
1152 sToken
[k
] = sKey
.getToken(0, '_', nIndex
);
1153 if (sToken
[k
].isEmpty())
1159 if ( sToken
[k
] == "SHIFT" )
1160 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::SHIFT
;
1161 else if ( sToken
[k
] == "MOD1" )
1162 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::MOD1
;
1163 else if ( sToken
[k
] == "MOD2" )
1164 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::MOD2
;
1165 else if ( sToken
[k
] == "MOD3" )
1166 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::MOD3
;
1174 if ( !aReadCache
.hasKey(aKeyEvent
) && bValid
&& k
<nToken
)
1175 aReadCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
1180 m_aPrimaryReadCache
.takeOver(aReadCache
);
1182 m_aSecondaryReadCache
.takeOver(aReadCache
);
1185 void XCUBasedAcceleratorConfiguration::impl_ts_save(bool bPreferred
, const css::uno::Reference
< css::container::XNameAccess
>& /*xCfg*/)
1189 AcceleratorCache::TKeyList::const_iterator pIt
;
1190 AcceleratorCache::TKeyList lPrimaryReadKeys
= m_aPrimaryReadCache
.getAllKeys();
1191 AcceleratorCache::TKeyList lPrimaryWriteKeys
= m_pPrimaryWriteCache
->getAllKeys();
1193 for ( pIt
= lPrimaryReadKeys
.begin(); pIt
!= lPrimaryReadKeys
.end(); ++pIt
)
1195 if (!m_pPrimaryWriteCache
->hasKey(*pIt
))
1196 removeKeyFromConfiguration(*pIt
, true);
1199 for ( pIt
= lPrimaryWriteKeys
.begin(); pIt
!= lPrimaryWriteKeys
.end(); ++pIt
)
1201 OUString sCommand
= m_pPrimaryWriteCache
->getCommandByKey(*pIt
);
1202 if (!m_aPrimaryReadCache
.hasKey(*pIt
))
1204 insertKeyToConfiguration(*pIt
, sCommand
, true);
1208 OUString sReadCommand
= m_aPrimaryReadCache
.getCommandByKey(*pIt
);
1209 if (sReadCommand
!= sCommand
)
1210 insertKeyToConfiguration(*pIt
, sCommand
, true);
1214 // take over all changes into the original container
1216 // coverity[check_after_deref]
1217 if (m_pPrimaryWriteCache
)
1219 m_aPrimaryReadCache
.takeOver(*m_pPrimaryWriteCache
);
1220 AcceleratorCache
* pTemp
= m_pPrimaryWriteCache
;
1221 m_pPrimaryWriteCache
= nullptr;
1228 AcceleratorCache::TKeyList::const_iterator pIt
;
1229 AcceleratorCache::TKeyList lSecondaryReadKeys
= m_aSecondaryReadCache
.getAllKeys();
1230 AcceleratorCache::TKeyList lSecondaryWriteKeys
= m_pSecondaryWriteCache
->getAllKeys();
1232 for ( pIt
= lSecondaryReadKeys
.begin(); pIt
!= lSecondaryReadKeys
.end(); ++pIt
)
1234 if (!m_pSecondaryWriteCache
->hasKey(*pIt
))
1235 removeKeyFromConfiguration(*pIt
, false);
1238 for ( pIt
= lSecondaryWriteKeys
.begin(); pIt
!= lSecondaryWriteKeys
.end(); ++pIt
)
1240 OUString sCommand
= m_pSecondaryWriteCache
->getCommandByKey(*pIt
);
1241 if (!m_aSecondaryReadCache
.hasKey(*pIt
))
1243 insertKeyToConfiguration(*pIt
, sCommand
, false);
1247 OUString sReadCommand
= m_aSecondaryReadCache
.getCommandByKey(*pIt
);
1248 if (sReadCommand
!= sCommand
)
1249 insertKeyToConfiguration(*pIt
, sCommand
, false);
1253 // take over all changes into the original container
1255 // coverity[check_after_deref]
1256 if (m_pSecondaryWriteCache
)
1258 m_aSecondaryReadCache
.takeOver(*m_pSecondaryWriteCache
);
1259 AcceleratorCache
* pTemp
= m_pSecondaryWriteCache
;
1260 m_pSecondaryWriteCache
= nullptr;
1265 ::comphelper::ConfigurationHelper::flush(m_xCfg
);
1268 void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent
& aKeyEvent
, const OUString
& sCommand
, const bool bPreferred
)
1270 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
1271 css::uno::Reference
< css::container::XNameContainer
> xContainer
;
1272 css::uno::Reference
< css::lang::XSingleServiceFactory
> xFac
;
1273 css::uno::Reference
< css::uno::XInterface
> xInst
;
1276 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
1278 m_xCfg
->getByName(CFG_ENTRY_SECONDARY
) >>= xAccess
;
1280 if ( m_sGlobalOrModules
== CFG_ENTRY_GLOBAL
)
1281 xAccess
->getByName(CFG_ENTRY_GLOBAL
) >>= xContainer
;
1282 else if ( m_sGlobalOrModules
== CFG_ENTRY_MODULES
)
1284 css::uno::Reference
< css::container::XNameContainer
> xModules
;
1285 xAccess
->getByName(CFG_ENTRY_MODULES
) >>= xModules
;
1286 if ( !xModules
->hasByName(m_sModuleCFG
) )
1288 xFac
.set(xModules
, css::uno::UNO_QUERY
);
1289 xInst
= xFac
->createInstance();
1290 xModules
->insertByName(m_sModuleCFG
, css::uno::makeAny(xInst
));
1292 xModules
->getByName(m_sModuleCFG
) >>= xContainer
;
1295 const OUString sKey
= lcl_getKeyString(aKeyEvent
);
1296 css::uno::Reference
< css::container::XNameAccess
> xKey
;
1297 css::uno::Reference
< css::container::XNameContainer
> xCommand
;
1298 if ( !xContainer
->hasByName(sKey
) )
1300 xFac
.set(xContainer
, css::uno::UNO_QUERY
);
1301 xInst
= xFac
->createInstance();
1302 xContainer
->insertByName(sKey
, css::uno::makeAny(xInst
));
1304 xContainer
->getByName(sKey
) >>= xKey
;
1306 xKey
->getByName(CFG_PROP_COMMAND
) >>= xCommand
;
1307 OUString sLocale
= impl_ts_getLocale();
1308 if ( !xCommand
->hasByName(sLocale
) )
1309 xCommand
->insertByName(sLocale
, css::uno::makeAny(sCommand
));
1311 xCommand
->replaceByName(sLocale
, css::uno::makeAny(sCommand
));
1314 void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent
& aKeyEvent
, const bool bPreferred
)
1316 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
1317 css::uno::Reference
< css::container::XNameContainer
> xContainer
;
1320 m_xCfg
->getByName(CFG_ENTRY_PRIMARY
) >>= xAccess
;
1322 m_xCfg
->getByName(CFG_ENTRY_SECONDARY
) >>= xAccess
;
1324 if ( m_sGlobalOrModules
== CFG_ENTRY_GLOBAL
)
1325 xAccess
->getByName(CFG_ENTRY_GLOBAL
) >>= xContainer
;
1326 else if ( m_sGlobalOrModules
== CFG_ENTRY_MODULES
)
1328 css::uno::Reference
< css::container::XNameAccess
> xModules
;
1329 xAccess
->getByName(CFG_ENTRY_MODULES
) >>= xModules
;
1330 if ( !xModules
->hasByName(m_sModuleCFG
) )
1332 xModules
->getByName(m_sModuleCFG
) >>= xContainer
;
1335 const OUString sKey
= lcl_getKeyString(aKeyEvent
);
1336 xContainer
->removeByName(sKey
);
1339 void XCUBasedAcceleratorConfiguration::reloadChanged( const OUString
& sPrimarySecondary
, const OUString
& sGlobalModules
, const OUString
& sModule
, const OUString
& sKey
)
1341 css::uno::Reference
< css::container::XNameAccess
> xAccess
;
1342 css::uno::Reference
< css::container::XNameContainer
> xContainer
;
1344 m_xCfg
->getByName(sPrimarySecondary
) >>= xAccess
;
1345 if ( sGlobalModules
== CFG_ENTRY_GLOBAL
)
1346 xAccess
->getByName(CFG_ENTRY_GLOBAL
) >>= xContainer
;
1349 css::uno::Reference
< css::container::XNameAccess
> xModules
;
1350 xAccess
->getByName(CFG_ENTRY_MODULES
) >>= xModules
;
1351 if ( !xModules
->hasByName(sModule
) )
1353 xModules
->getByName(sModule
) >>= xContainer
;
1356 css::awt::KeyEvent aKeyEvent
;
1357 OUString sKeyIdentifier
;
1359 sal_Int32 nIndex
= 0;
1360 sKeyIdentifier
= sKey
.getToken(0, '_', nIndex
);
1361 aKeyEvent
.KeyCode
= KeyMapping::get().mapIdentifierToCode("KEY_"+sKeyIdentifier
);
1363 css::uno::Sequence
< OUString
> sToken(3);
1364 const sal_Int32 nToken
= 3;
1365 for (sal_Int32 i
=0; i
<nToken
; ++i
)
1370 sToken
[i
] = sKey
.getToken(0, '_', nIndex
);
1371 if ( sToken
[i
] == "SHIFT" )
1372 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::SHIFT
;
1373 else if ( sToken
[i
] == "MOD1" )
1374 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::MOD1
;
1375 else if ( sToken
[i
] == "MOD2" )
1376 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::MOD2
;
1377 else if ( sToken
[i
] == "MOD3" )
1378 aKeyEvent
.Modifiers
|= css::awt::KeyModifier::MOD3
;
1381 css::uno::Reference
< css::container::XNameAccess
> xKey
;
1382 css::uno::Reference
< css::container::XNameAccess
> xCommand
;
1385 if (xContainer
->hasByName(sKey
))
1387 OUString sLocale
= impl_ts_getLocale();
1388 xContainer
->getByName(sKey
) >>= xKey
;
1389 xKey
->getByName(CFG_PROP_COMMAND
) >>= xCommand
;
1390 xCommand
->getByName(sLocale
) >>= sCommand
;
1393 if ( sPrimarySecondary
== CFG_ENTRY_PRIMARY
)
1395 if (sCommand
.isEmpty())
1396 m_aPrimaryReadCache
.removeKey(aKeyEvent
);
1398 m_aPrimaryReadCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
1400 else if ( sPrimarySecondary
== CFG_ENTRY_SECONDARY
)
1402 if (sCommand
.isEmpty())
1403 m_aSecondaryReadCache
.removeKey(aKeyEvent
);
1405 m_aSecondaryReadCache
.setKeyCommandPair(aKeyEvent
, sCommand
);
1409 AcceleratorCache
& XCUBasedAcceleratorConfiguration::impl_getCFG(bool bPreferred
, bool bWriteAccessRequested
)
1415 //create copy of our readonly-cache, if write access is forced ... but
1416 //not still possible!
1418 (bWriteAccessRequested
) &&
1419 (!m_pPrimaryWriteCache
)
1422 m_pPrimaryWriteCache
= new AcceleratorCache(m_aPrimaryReadCache
);
1425 // in case, we have a writeable cache, we use it for reading too!
1426 // Otherwise the API user can't find its own changes ...
1427 if (m_pPrimaryWriteCache
)
1428 return *m_pPrimaryWriteCache
;
1430 return m_aPrimaryReadCache
;
1435 //create copy of our readonly-cache, if write access is forced ... but
1436 //not still possible!
1438 (bWriteAccessRequested
) &&
1439 (!m_pSecondaryWriteCache
)
1442 m_pSecondaryWriteCache
= new AcceleratorCache(m_aSecondaryReadCache
);
1445 // in case, we have a writeable cache, we use it for reading too!
1446 // Otherwise the API user can't find its own changes ...
1447 if (m_pSecondaryWriteCache
)
1448 return *m_pSecondaryWriteCache
;
1450 return m_aSecondaryReadCache
;
1454 OUString
XCUBasedAcceleratorConfiguration::impl_ts_getLocale() const
1456 OUString sISOLocale
= officecfg::Setup::L10N::ooLocale::get();
1458 if (sISOLocale
.isEmpty())
1459 return OUString("en-US");
1463 } // namespace framework
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */