LibreOffice Module framework (master) 1
acceleratorconfiguration.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <utility>
23
27
31
32#include <com/sun/star/xml/sax/Parser.hpp>
33#include <com/sun/star/xml/sax/InputSource.hpp>
34#include <com/sun/star/xml/sax/Writer.hpp>
35#include <com/sun/star/io/IOException.hpp>
36#include <com/sun/star/embed/ElementModes.hpp>
37#include <com/sun/star/io/XSeekable.hpp>
38#include <com/sun/star/io/XTruncate.hpp>
39
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/container/XHierarchicalNameAccess.hpp>
44#include <com/sun/star/awt/KeyEvent.hpp>
45#include <com/sun/star/awt/KeyModifier.hpp>
46#include <com/sun/star/lang/XSingleServiceFactory.hpp>
49#include <officecfg/Setup.hxx>
52#include <sal/log.hxx>
53#include <rtl/ustrbuf.hxx>
54#include <o3tl/string_view.hxx>
55
56constexpr OUStringLiteral PRESET_DEFAULT = u"default";
57constexpr OUStringLiteral TARGET_CURRENT = u"current";
58
59namespace framework
60{
61 constexpr OUStringLiteral CFG_ENTRY_SECONDARY = u"SecondaryKeys";
62 constexpr OUStringLiteral CFG_PROP_COMMAND = u"Command";
63
64 static OUString lcl_getKeyString(const css::awt::KeyEvent& aKeyEvent)
65 {
66 const sal_Int32 nBeginIndex = 4; // "KEY_" is the prefix of an identifier...
67 OUString sKey(KeyMapping::get().mapCodeToIdentifier(aKeyEvent.KeyCode));
68 if (sKey.getLength() < nBeginIndex) // dead key
69 return OUString();
70 OUStringBuffer sKeyBuffer(sKey.subView(nBeginIndex));
71
72 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT )
73 sKeyBuffer.append("_SHIFT");
74 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 )
75 sKeyBuffer.append("_MOD1");
76 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 )
77 sKeyBuffer.append("_MOD2");
78 if ( (aKeyEvent.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 )
79 sKeyBuffer.append("_MOD3");
80
81 return sKeyBuffer.makeStringAndClear();
82 }
83
84XMLBasedAcceleratorConfiguration::XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext >& xContext)
85 : m_xContext (xContext )
86 , m_aPresetHandler(xContext )
87{
88}
89
91{
92 SAL_WARN_IF(m_pWriteCache, "fwk.accelerators", "XMLBasedAcceleratorConfiguration::~XMLBasedAcceleratorConfiguration(): Changes not flushed. Ignore it ...");
93}
94
95css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getAllKeyEvents()
96{
98 AcceleratorCache& rCache = impl_getCFG();
101}
102
103OUString SAL_CALL XMLBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
104{
106 AcceleratorCache& rCache = impl_getCFG();
107 if (!rCache.hasKey(aKeyEvent))
108 throw css::container::NoSuchElementException(
109 OUString(),
110 static_cast< ::cppu::OWeakObject* >(this));
111 return rCache.getCommandByKey(aKeyEvent);
112}
113
114void SAL_CALL XMLBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
115 const OUString& sCommand )
116{
117 if (
118 (aKeyEvent.KeyCode == 0) &&
119 (aKeyEvent.KeyChar == 0) &&
120 (aKeyEvent.KeyFunc == 0) &&
121 (aKeyEvent.Modifiers == 0)
122 )
123 throw css::lang::IllegalArgumentException(
124 "Such key event seems not to be supported by any operating system.",
125 static_cast< ::cppu::OWeakObject* >(this),
126 0);
127
128 if (sCommand.isEmpty())
129 throw css::lang::IllegalArgumentException(
130 "Empty command strings are not allowed here.",
131 static_cast< ::cppu::OWeakObject* >(this),
132 1);
133
135 AcceleratorCache& rCache = impl_getCFG(true); // sal_True => force getting of a writeable cache!
136 rCache.setKeyCommandPair(aKeyEvent, sCommand);
137}
138
139void SAL_CALL XMLBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
140{
142 AcceleratorCache& rCache = impl_getCFG(true); // true => force using of a writeable cache
143 if (!rCache.hasKey(aKeyEvent))
144 throw css::container::NoSuchElementException(
145 OUString(),
146 static_cast< ::cppu::OWeakObject* >(this));
147 rCache.removeKey(aKeyEvent);
148}
149
150css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XMLBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
151{
152 if (sCommand.isEmpty())
153 throw css::lang::IllegalArgumentException(
154 "Empty command strings are not allowed here.",
155 static_cast< ::cppu::OWeakObject* >(this),
156 1);
157
159 AcceleratorCache& rCache = impl_getCFG();
160 if (!rCache.hasCommand(sCommand))
161 throw css::container::NoSuchElementException(
162 OUString(),
163 static_cast< ::cppu::OWeakObject* >(this));
164
165 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(sCommand);
167}
168
169css::uno::Sequence< css::uno::Any > SAL_CALL XMLBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
170{
172
173 sal_Int32 i = 0;
174 sal_Int32 c = lCommandList.getLength();
175 css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // don't pack list!
176 AcceleratorCache& rCache = impl_getCFG();
177
178 auto lPreferredOnesRange = asNonConstRange(lPreferredOnes);
179 for (i=0; i<c; ++i)
180 {
181 const OUString& rCommand = lCommandList[i];
182 if (rCommand.isEmpty())
183 throw css::lang::IllegalArgumentException(
184 "Empty command strings are not allowed here.",
185 static_cast< ::cppu::OWeakObject* >(this),
186 static_cast<sal_Int16>(i));
187
188 if (!rCache.hasCommand(rCommand))
189 continue;
190
191 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
192 if ( lKeys.empty() )
193 continue;
194
195 css::uno::Any& rAny = lPreferredOnesRange[i];
196 rAny <<= *(lKeys.begin());
197 }
198
199 return lPreferredOnes;
200}
201
203{
204 if (sCommand.isEmpty())
205 throw css::lang::IllegalArgumentException(
206 "Empty command strings are not allowed here.",
207 static_cast< ::cppu::OWeakObject* >(this),
208 0);
209
211 AcceleratorCache& rCache = impl_getCFG(true); // sal_True => force getting of a writeable cache!
212 if (!rCache.hasCommand(sCommand))
213 throw css::container::NoSuchElementException(
214 "Command does not exists inside this container.",
215 static_cast< ::cppu::OWeakObject* >(this));
216 rCache.removeCommand(sCommand);
217}
218
220{
221 css::uno::Reference< css::io::XStream > xStream;
222 css::uno::Reference< css::io::XStream > xStreamNoLang;
223 {
226 css::embed::ElementModes::READ);
227 try
228 {
230 }
231 catch(const css::io::IOException&) {} // does not have to exist
232 }
233
234 css::uno::Reference< css::io::XInputStream > xIn;
235 if (xStream.is())
236 xIn = xStream->getInputStream();
237 if (!xIn.is())
238 throw css::io::IOException(
239 "Could not open accelerator configuration for reading.",
240 static_cast< ::cppu::OWeakObject* >(this));
241
242 // impl_ts_load() does not clear the cache
243 {
246 }
247
248 impl_ts_load(xIn);
249
250 // Load also the general language independent default accelerators
251 // (ignoring the already defined accelerators)
252 if (xStreamNoLang.is())
253 {
254 xIn = xStreamNoLang->getInputStream();
255 if (xIn.is())
256 impl_ts_load(xIn);
257 }
258}
259
261{
262 css::uno::Reference< css::io::XStream > xStream;
263 {
266 css::embed::ElementModes::READWRITE); // open or create!
267 }
268
269 css::uno::Reference< css::io::XOutputStream > xOut;
270 if (xStream.is())
271 xOut = xStream->getOutputStream();
272
273 if (!xOut.is())
274 throw css::io::IOException(
275 "Could not open accelerator configuration for saving.",
276 static_cast< ::cppu::OWeakObject* >(this));
277
278 impl_ts_save(xOut);
279
280 xOut.clear();
281 xStream.clear();
282
284}
285
286void SAL_CALL XMLBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
287{
288 // no fallback from read/write to readonly!
289 css::uno::Reference< css::io::XStream > xStream = xStorage->openStreamElement(TARGET_CURRENT, css::embed::ElementModes::READWRITE);
290
291 css::uno::Reference< css::io::XOutputStream > xOut;
292 if (xStream.is())
293 xOut = xStream->getOutputStream();
294
295 if (!xOut.is())
296 throw css::io::IOException(
297 "Could not open accelerator configuration for saving.",
298 static_cast< ::cppu::OWeakObject* >(this));
299
300 impl_ts_save(xOut);
301
302 // TODO inform listener about success, so it can flush the root and sub storage of this stream!
303}
304
306{
308 return (m_pWriteCache != nullptr);
309}
310
312{
313 css::uno::Reference< css::io::XStream > xStream;
314 {
317 css::embed::ElementModes::READWRITE); // open or create!
318 }
319
320 css::uno::Reference< css::io::XOutputStream > xOut;
321 if (xStream.is())
322 xOut = xStream->getOutputStream();
323 return !(xOut.is());
324}
325
326void SAL_CALL XMLBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
327{
328 SAL_INFO("fwk.accelerators", "XMLBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
329}
330
332{
333 SAL_INFO("fwk.accelerators", "XMLBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
334 return false;
335}
336
337void SAL_CALL XMLBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
338{
339 SAL_INFO("fwk.accelerators", "XMLBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
340}
341
342void SAL_CALL XMLBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
343{
344 SAL_INFO("fwk.accelerators", "XMLBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
345}
346
348{
349 {
352 }
353
354 reload();
355}
356
357void SAL_CALL XMLBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
358{
359 SAL_INFO("fwk.accelerators", "XMLBasedAcceleratorConfiguration::addResetListener(): implement me");
360}
361
362void SAL_CALL XMLBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
363{
364 SAL_INFO("fwk.accelerators", "XMLBasedAcceleratorConfiguration::removeResetListener(): implement me");
365}
366
367// IStorageListener
369{
370 reload();
371}
372
373void XMLBasedAcceleratorConfiguration::impl_ts_load(const css::uno::Reference< css::io::XInputStream >& xStream)
374{
375 css::uno::Reference< css::uno::XComponentContext > xContext;
376 {
378 xContext = m_xContext;
379 m_pWriteCache.reset();
380 }
381
382 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
383 if (xSeek.is())
384 xSeek->seek(0);
385
387
388 // create the parser queue
389 // Note: Use special filter object between parser and reader
390 // to get filtered xml with right namespaces ...
391 // Use further a temp cache for reading!
394
395 // connect parser, filter and stream
396 css::uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create(xContext);
397 xParser->setDocumentHandler(pFilter);
398
399 css::xml::sax::InputSource aSource;
400 aSource.aInputStream = xStream;
401
402 // TODO think about error handling
403 xParser->parseStream(aSource);
404}
405
406void XMLBasedAcceleratorConfiguration::impl_ts_save(const css::uno::Reference< css::io::XOutputStream >& xStream)
407{
408 bool bChanged;
409 AcceleratorCache aCache;
410 css::uno::Reference< css::uno::XComponentContext > xContext;
411 {
413 bChanged = (m_pWriteCache != nullptr);
414 if (bChanged)
415 aCache = *m_pWriteCache;
416 else
417 aCache = m_aReadCache;
418 xContext = m_xContext;
419 }
420
421 css::uno::Reference< css::io::XTruncate > xClearable(xStream, css::uno::UNO_QUERY_THROW);
422 xClearable->truncate();
423
424 // TODO can be removed if seek(0) is done by truncate() automatically!
425 css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
426 if (xSeek.is())
427 xSeek->seek(0);
428
429 // combine writer/cache/stream etcpp.
430 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(xContext);
431 xWriter->setOutputStream(xStream);
432
433 // write into the stream
434 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
435 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
436 aWriter.flush();
437
439 // take over all changes into the readonly cache ...
440 // and forget the copy-on-write copied cache
441 if (bChanged)
442 {
444 m_pWriteCache.reset();
445 }
446}
447
449{
451
452 //create copy of our readonly-cache, if write access is forced ... but
453 //not still possible!
454 if ( bWriteAccessRequested && !m_pWriteCache )
455 {
457 }
458
459 // in case, we have a writeable cache, we use it for reading too!
460 // Otherwise the API user can't find its own changes...
461 if (m_pWriteCache)
462 return *m_pWriteCache;
463 else
464 return m_aReadCache;
465}
466
468{
469 OUString sISOLocale = officecfg::Setup::L10N::ooLocale::get();
470
471 if (sISOLocale.isEmpty())
472 return "en-US";
473 return sISOLocale;
474}
475
476/*******************************************************************************
477*
478* XCU based accelerator configuration
479*
480*******************************************************************************/
481
482XCUBasedAcceleratorConfiguration::XCUBasedAcceleratorConfiguration(css::uno::Reference< css::uno::XComponentContext > xContext)
483 : m_xContext (std::move(xContext ))
484{
485 m_xCfg.set(
486 ::comphelper::ConfigurationHelper::openConfig( m_xContext, "org.openoffice.Office.Accelerators", ::comphelper::EConfigurationModes::AllLocales ),
487 css::uno::UNO_QUERY );
488}
489
491{
492}
493
494css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getAllKeyEvents()
495{
497
498 AcceleratorCache::TKeyList lKeys = impl_getCFG(true).getAllKeys(); //get keys from PrimaryKeys set
499
500 AcceleratorCache::TKeyList lSecondaryKeys = impl_getCFG(false).getAllKeys(); //get keys from SecondaryKeys set
501 lKeys.reserve(lKeys.size()+lSecondaryKeys.size());
502 for (auto const& secondaryKey : lSecondaryKeys)
503 lKeys.push_back(secondaryKey);
504
506}
507
508OUString SAL_CALL XCUBasedAcceleratorConfiguration::getCommandByKeyEvent(const css::awt::KeyEvent& aKeyEvent)
509{
511
512 AcceleratorCache& rPrimaryCache = impl_getCFG(true );
513 AcceleratorCache& rSecondaryCache = impl_getCFG(false);
514
515 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
516 throw css::container::NoSuchElementException(
517 OUString(),
518 static_cast< ::cppu::OWeakObject* >(this));
519
520 if (rPrimaryCache.hasKey(aKeyEvent))
521 return rPrimaryCache.getCommandByKey(aKeyEvent);
522 else
523 return rSecondaryCache.getCommandByKey(aKeyEvent);
524}
525
526void SAL_CALL XCUBasedAcceleratorConfiguration::setKeyEvent(const css::awt::KeyEvent& aKeyEvent,
527 const OUString& sCommand )
528{
529 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::setKeyEvent" );
530
531 if (
532 (aKeyEvent.KeyCode == 0) &&
533 (aKeyEvent.KeyChar == 0) &&
534 (aKeyEvent.KeyFunc == 0) &&
535 (aKeyEvent.Modifiers == 0)
536 )
537 throw css::lang::IllegalArgumentException(
538 "Such key event seems not to be supported by any operating system.",
539 static_cast< ::cppu::OWeakObject* >(this),
540 0);
541
542 if (sCommand.isEmpty())
543 throw css::lang::IllegalArgumentException(
544 "Empty command strings are not allowed here.",
545 static_cast< ::cppu::OWeakObject* >(this),
546 1);
547
549
550 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true ); // sal_True => force getting of a writeable cache!
551 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true); // sal_True => force getting of a writeable cache!
552
553 if ( rPrimaryCache.hasKey(aKeyEvent) )
554 {
555 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
556 if ( sCommand != sOriginalCommand )
557 {
558 if (rSecondaryCache.hasCommand(sOriginalCommand))
559 {
560 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
561 rSecondaryCache.removeKey(lSecondaryKeys[0]);
562 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
563 }
564
565 if (rPrimaryCache.hasCommand(sCommand))
566 {
567 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
568 rPrimaryCache.removeKey(lPrimaryKeys[0]);
569 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
570 }
571
572 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
573 }
574 }
575
576 else if ( rSecondaryCache.hasKey(aKeyEvent) )
577 {
578 OUString sOriginalCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
579 if (sCommand != sOriginalCommand)
580 {
581 if (rPrimaryCache.hasCommand(sCommand))
582 {
583 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
584 rPrimaryCache.removeKey(lPrimaryKeys[0]);
585 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
586 }
587
588 rSecondaryCache.removeKey(aKeyEvent);
589 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
590 }
591 }
592
593 else
594 {
595 if (rPrimaryCache.hasCommand(sCommand))
596 {
597 AcceleratorCache::TKeyList lPrimaryKeys = rPrimaryCache.getKeysByCommand(sCommand);
598 rPrimaryCache.removeKey(lPrimaryKeys[0]);
599 rSecondaryCache.setKeyCommandPair(lPrimaryKeys[0], sCommand);
600 }
601
602 rPrimaryCache.setKeyCommandPair(aKeyEvent, sCommand);
603 }
604}
605
606void SAL_CALL XCUBasedAcceleratorConfiguration::removeKeyEvent(const css::awt::KeyEvent& aKeyEvent)
607{
609
610 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true );
611 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true);
612
613 if (!rPrimaryCache.hasKey(aKeyEvent) && !rSecondaryCache.hasKey(aKeyEvent))
614 throw css::container::NoSuchElementException(
615 OUString(),
616 static_cast< ::cppu::OWeakObject* >(this));
617
618 if (rPrimaryCache.hasKey(aKeyEvent))
619 {
620 OUString sOriginalCommand = rPrimaryCache.getCommandByKey(aKeyEvent);
621 if (!sOriginalCommand.isEmpty())
622 {
623 if (rSecondaryCache.hasCommand(sOriginalCommand))
624 {
625 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sOriginalCommand);
626 rSecondaryCache.removeKey(lSecondaryKeys[0]);
627 rPrimaryCache.setKeyCommandPair(lSecondaryKeys[0], sOriginalCommand);
628 }
629
630 rPrimaryCache.removeKey(aKeyEvent);
631 }
632
633 }
634 else
635 {
636 OUString sDelCommand = rSecondaryCache.getCommandByKey(aKeyEvent);
637 if (!sDelCommand.isEmpty())
638 rSecondaryCache.removeKey(aKeyEvent);
639 }
640}
641
642css::uno::Sequence< css::awt::KeyEvent > SAL_CALL XCUBasedAcceleratorConfiguration::getKeyEventsByCommand(const OUString& sCommand)
643{
644 if (sCommand.isEmpty())
645 throw css::lang::IllegalArgumentException(
646 "Empty command strings are not allowed here.",
647 static_cast< ::cppu::OWeakObject* >(this),
648 1);
649
651
652 AcceleratorCache& rPrimaryCache = impl_getCFG(true );
653 AcceleratorCache& rSecondaryCache = impl_getCFG(false);
654
655 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
656 throw css::container::NoSuchElementException(
657 OUString(),
658 static_cast< ::cppu::OWeakObject* >(this));
659
660 AcceleratorCache::TKeyList lKeys = rPrimaryCache.getKeysByCommand(sCommand);
661
662 AcceleratorCache::TKeyList lSecondaryKeys = rSecondaryCache.getKeysByCommand(sCommand);
663 for (auto const& secondaryKey : lSecondaryKeys)
664 lKeys.push_back(secondaryKey);
665
667}
668
669static AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList& lKeys)
670{
671 return std::find_if(lKeys.begin(), lKeys.end(), [](const css::awt::KeyEvent& rAWTKey) {
672 return !::svt::AcceleratorExecute::st_AWTKey2VCLKey(rAWTKey).GetName().isEmpty(); });
673}
674
675css::uno::Sequence< css::uno::Any > SAL_CALL XCUBasedAcceleratorConfiguration::getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString >& lCommandList)
676{
678
679 sal_Int32 i = 0;
680 sal_Int32 c = lCommandList.getLength();
681 css::uno::Sequence< css::uno::Any > lPreferredOnes (c); // don't pack list!
682 AcceleratorCache& rCache = impl_getCFG(true);
683
684 auto lPreferredOnesRange = asNonConstRange(lPreferredOnes);
685 for (i=0; i<c; ++i)
686 {
687 const OUString& rCommand = lCommandList[i];
688 if (rCommand.isEmpty())
689 throw css::lang::IllegalArgumentException(
690 "Empty command strings are not allowed here.",
691 static_cast< ::cppu::OWeakObject* >(this),
692 static_cast<sal_Int16>(i));
693
694 if (!rCache.hasCommand(rCommand))
695 continue;
696
697 AcceleratorCache::TKeyList lKeys = rCache.getKeysByCommand(rCommand);
698 if ( lKeys.empty() )
699 continue;
700
701 AcceleratorCache::TKeyList::const_iterator pPreferredKey = lcl_getPreferredKey(lKeys);
702 if (pPreferredKey != lKeys.end ())
703 {
704 css::uno::Any& rAny = lPreferredOnesRange[i];
705 rAny <<= *pPreferredKey;
706 }
707 }
708
709 return lPreferredOnes;
710}
711
713{
714 if (sCommand.isEmpty())
715 throw css::lang::IllegalArgumentException(
716 "Empty command strings are not allowed here.",
717 static_cast< ::cppu::OWeakObject* >(this),
718 0);
719
721
722 AcceleratorCache& rPrimaryCache = impl_getCFG(true, true );
723 AcceleratorCache& rSecondaryCache = impl_getCFG(false, true);
724
725 if (!rPrimaryCache.hasCommand(sCommand) && !rSecondaryCache.hasCommand(sCommand))
726 throw css::container::NoSuchElementException(
727 "Command does not exists inside this container.",
728 static_cast< ::cppu::OWeakObject* >(this));
729
730 if (rPrimaryCache.hasCommand(sCommand))
731 rPrimaryCache.removeCommand(sCommand);
732 if (rSecondaryCache.hasCommand(sCommand))
733 rSecondaryCache.removeCommand(sCommand);
734}
735
737{
738 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::reload()" );
739
741
742 bool bPreferred;
743 css::uno::Reference< css::container::XNameAccess > xAccess;
744
745 bPreferred = true;
747 m_pPrimaryWriteCache.reset();
748 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
749 impl_ts_load(bPreferred, xAccess); // load the preferred keys
750
751 bPreferred = false;
754 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
755 impl_ts_load(bPreferred, xAccess); // load the secondary keys
756}
757
759{
760 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::store()" );
761
763
764 bool bPreferred;
765
766 bPreferred = true;
767 // on-demand creation of the primary write cache
768 impl_getCFG(bPreferred, true);
769 impl_ts_save(bPreferred);
770
771 bPreferred = false;
772 // on-demand creation of the secondary write cache
773 impl_getCFG(bPreferred, true);
774 impl_ts_save(bPreferred);
775}
776
777void SAL_CALL XCUBasedAcceleratorConfiguration::storeToStorage(const css::uno::Reference< css::embed::XStorage >& xStorage)
778{
779 // use m_aCache + old AcceleratorXMLWriter to store data directly on storage given as parameter ...
780 if (!xStorage.is())
781 return;
782
783 tools::Long nOpenModes = css::embed::ElementModes::READWRITE;
784 css::uno::Reference< css::embed::XStorage > xAcceleratorTypeStorage = xStorage->openStorageElement("accelerator", nOpenModes);
785 if (!xAcceleratorTypeStorage.is())
786 return;
787
788 css::uno::Reference< css::io::XStream > xStream = xAcceleratorTypeStorage->openStreamElement("current", nOpenModes);
789 css::uno::Reference< css::io::XOutputStream > xOut;
790 if (xStream.is())
791 xOut = xStream->getOutputStream();
792 if (!xOut.is())
793 throw css::io::IOException(
794 "Could not open accelerator configuration for saving.",
795 static_cast< ::cppu::OWeakObject* >(this));
796
797 // the original m_aCache has been split into primary cache and secondary cache...
798 // we should merge them before storing to storage
799 AcceleratorCache aCache;
800 {
802
803 if (m_pPrimaryWriteCache != nullptr)
804 aCache = *m_pPrimaryWriteCache;
805 else
806 aCache = m_aPrimaryReadCache;
807
809 if (m_pSecondaryWriteCache!=nullptr)
810 {
811 lKeys = m_pSecondaryWriteCache->getAllKeys();
812 for (auto const& lKey : lKeys)
813 aCache.setKeyCommandPair(lKey, m_pSecondaryWriteCache->getCommandByKey(lKey));
814 }
815 else
816 {
818 for (auto const& lKey : lKeys)
820 }
821 }
822
823 css::uno::Reference< css::io::XTruncate > xClearable(xOut, css::uno::UNO_QUERY_THROW);
824 xClearable->truncate();
825 css::uno::Reference< css::io::XSeekable > xSeek(xOut, css::uno::UNO_QUERY);
826 if (xSeek.is())
827 xSeek->seek(0);
828
829 css::uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(m_xContext);
830 xWriter->setOutputStream(xOut);
831
832 // write into the stream
833 css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler(xWriter, css::uno::UNO_QUERY_THROW);
834 AcceleratorConfigurationWriter aWriter(aCache, xHandler);
835 aWriter.flush();
836}
837
839{
840 return false;
841}
842
844{
845 return false;
846}
847
848void SAL_CALL XCUBasedAcceleratorConfiguration::setStorage(const css::uno::Reference< css::embed::XStorage >& /*xStorage*/)
849{
850 SAL_INFO("fwk.accelerators", "XCUBasedAcceleratorConfiguration::setStorage(): implement this HACK .-)");
851}
852
854{
855 SAL_INFO("fwk.accelerators", "XCUBasedAcceleratorConfiguration::hasStorage(): implement this HACK .-)");
856 return false;
857}
858
859void SAL_CALL XCUBasedAcceleratorConfiguration::addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
860{
861 SAL_INFO("fwk.accelerators", "XCUBasedAcceleratorConfiguration::addConfigurationListener(): implement me");
862}
863
864void SAL_CALL XCUBasedAcceleratorConfiguration::removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener >& /*xListener*/)
865{
866 SAL_INFO("fwk.accelerators", "XCUBasedAcceleratorConfiguration::removeConfigurationListener(): implement me");
867}
868
870{
871 css::uno::Reference< css::container::XNamed > xNamed(m_xCfg, css::uno::UNO_QUERY);
872 OUString sConfig = xNamed->getName();
873 if ( sConfig == "Global" )
874 {
875 m_xCfg.set(
876 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_GLOBAL, ::comphelper::EConfigurationModes::AllLocales ),
877 css::uno::UNO_QUERY );
879 }
880 else if ( sConfig == "Modules" )
881 {
882 m_xCfg.set(
883 ::comphelper::ConfigurationHelper::openConfig( m_xContext, CFG_ENTRY_MODULES, ::comphelper::EConfigurationModes::AllLocales ),
884 css::uno::UNO_QUERY );
886 }
887}
888
889void SAL_CALL XCUBasedAcceleratorConfiguration::addResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
890{
891 SAL_INFO("fwk.accelerators", "XCUBasedAcceleratorConfiguration::addResetListener(): implement me");
892}
893
894void SAL_CALL XCUBasedAcceleratorConfiguration::removeResetListener(const css::uno::Reference< css::form::XResetListener >& /*xListener*/)
895{
896 SAL_INFO("fwk.accelerators", "XCUBasedAcceleratorConfiguration::removeResetListener(): implement me");
897}
898
899void SAL_CALL XCUBasedAcceleratorConfiguration::changesOccurred(const css::util::ChangesEvent& aEvent)
900{
901 SAL_INFO( "fwk.accelerators", "XCUBasedAcceleratorConfiguration::changesOccurred()" );
902
903 css::uno::Reference< css::container::XHierarchicalNameAccess > xHAccess;
904 aEvent.Base >>= xHAccess;
905 if (! xHAccess.is ())
906 return;
907
908 css::util::ChangesEvent aReceivedEvents( aEvent );
909 const sal_Int32 c = aReceivedEvents.Changes.getLength();
910 for (sal_Int32 i=0; i<c; ++i)
911 {
912 const css::util::ElementChange& aChange = aReceivedEvents.Changes[i];
913
914 // Only path of form "PrimaryKeys/Modules/Module['<module_name>']/Key['<command_url>']/Command[<locale>]" will
915 // be interesting for use. Sometimes short path values are given also by the broadcaster ... but they must be ignored :-)
916 // So we try to split the path into 3 parts (module isn't important here, because we already know it ... because
917 // these instance is bound to a specific module configuration ... or it''s the global configuration where no module is given at all.
918
919 OUString sOrgPath;
920 OUString sPath;
921 OUString sKey;
922
923 aChange.Accessor >>= sOrgPath;
924 sPath = sOrgPath;
925 OUString sPrimarySecondary = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
926 OUString sGlobalModules = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
927
928 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
929 {
930 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
931 if ( !sKey.isEmpty() && !sPath.isEmpty() )
932 reloadChanged(sPrimarySecondary, sGlobalModules, OUString(), sKey);
933 }
934 else if ( sGlobalModules == CFG_ENTRY_MODULES )
935 {
936 OUString sModule = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
937 sKey = ::utl::extractFirstFromConfigurationPath(sPath, &sPath);
938
939 if ( !sKey.isEmpty() && !sPath.isEmpty() )
940 {
941 reloadChanged(sPrimarySecondary, sGlobalModules, sModule, sKey);
942 }
943 }
944 }
945}
946
947void SAL_CALL XCUBasedAcceleratorConfiguration::disposing(const css::lang::EventObject& /*aSource*/)
948{
949}
950
951void XCUBasedAcceleratorConfiguration::impl_ts_load( bool bPreferred, const css::uno::Reference< css::container::XNameAccess >& xCfg )
952{
953 AcceleratorCache aReadCache;
954 css::uno::Reference< css::container::XNameAccess > xAccess;
955 if ( m_sGlobalOrModules == "Global" )
956 xCfg->getByName(CFG_ENTRY_GLOBAL) >>= xAccess;
957 else if ( m_sGlobalOrModules == "Modules" )
958 {
959 css::uno::Reference< css::container::XNameAccess > xModules;
960 xCfg->getByName(CFG_ENTRY_MODULES) >>= xModules;
961 xModules->getByName(m_sModuleCFG) >>= xAccess;
962 }
963
964 const OUString sIsoLang = impl_ts_getLocale();
965 static constexpr OUStringLiteral sDefaultLocale(u"en-US");
966
967 css::uno::Reference< css::container::XNameAccess > xKey;
968 css::uno::Reference< css::container::XNameAccess > xCommand;
969 if (xAccess.is())
970 {
971 css::uno::Sequence< OUString > lKeys = xAccess->getElementNames();
972 sal_Int32 nKeys = lKeys.getLength();
973 for ( sal_Int32 i=0; i<nKeys; ++i )
974 {
975 OUString sKey = lKeys[i];
976 xAccess->getByName(sKey) >>= xKey;
977 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
978
979 const css::uno::Sequence< OUString > lLocales = xCommand->getElementNames();
980 ::std::vector< OUString > aLocales { lLocales.begin(), lLocales.end() };
981
982 OUString sLocale;
983 for (auto const& locale : aLocales)
984 {
985 if ( locale == sIsoLang )
986 {
987 sLocale = locale;
988 break;
989 }
990 }
991
992 if (sLocale.isEmpty())
993 {
994 for (auto const& locale : aLocales)
995 {
996 if ( locale == sDefaultLocale )
997 {
998 sLocale = locale;
999 break;
1000 }
1001 }
1002
1003 if (sLocale.isEmpty())
1004 continue;
1005 }
1006
1007 OUString sCommand;
1008 xCommand->getByName(sLocale) >>= sCommand;
1009 if (sCommand.isEmpty())
1010 continue;
1011
1012 css::awt::KeyEvent aKeyEvent;
1013
1014 sal_Int32 nIndex = 0;
1015 std::u16string_view sKeyCommand = o3tl::getToken(sKey, 0, '_', nIndex);
1016 aKeyEvent.KeyCode = KeyMapping::get().mapIdentifierToCode(OUString::Concat("KEY_") + sKeyCommand);
1017
1018 const sal_Int32 nToken = 4;
1019 bool bValid = true;
1020 sal_Int32 k;
1021 for (k = 0; k < nToken; ++k)
1022 {
1023 if (nIndex < 0)
1024 break;
1025
1026 std::u16string_view sToken = o3tl::getToken(sKey, 0, '_', nIndex);
1027 if (sToken.empty())
1028 {
1029 bValid = false;
1030 break;
1031 }
1032
1033 if ( sToken == u"SHIFT" )
1034 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1035 else if ( sToken == u"MOD1" )
1036 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1037 else if ( sToken == u"MOD2" )
1038 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1039 else if ( sToken == u"MOD3" )
1040 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1041 else
1042 {
1043 bValid = false;
1044 break;
1045 }
1046 }
1047
1048 if ( !aReadCache.hasKey(aKeyEvent) && bValid && k<nToken)
1049 aReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1050 }
1051 }
1052
1053 if (bPreferred)
1054 m_aPrimaryReadCache = std::move(aReadCache);
1055 else
1056 m_aSecondaryReadCache = std::move(aReadCache);
1057}
1058
1060{
1061 if (bPreferred)
1062 {
1064 AcceleratorCache::TKeyList lPrimaryWriteKeys = m_pPrimaryWriteCache->getAllKeys();
1065
1066 for (auto const& primaryReadKey : lPrimaryReadKeys)
1067 {
1068 if (!m_pPrimaryWriteCache->hasKey(primaryReadKey))
1069 removeKeyFromConfiguration(primaryReadKey, true);
1070 }
1071
1072 for (auto const& primaryWriteKey : lPrimaryWriteKeys)
1073 {
1074 OUString sCommand = m_pPrimaryWriteCache->getCommandByKey(primaryWriteKey);
1075 if (!m_aPrimaryReadCache.hasKey(primaryWriteKey))
1076 {
1077 insertKeyToConfiguration(primaryWriteKey, sCommand, true);
1078 }
1079 else
1080 {
1081 OUString sReadCommand = m_aPrimaryReadCache.getCommandByKey(primaryWriteKey);
1082 if (sReadCommand != sCommand)
1083 insertKeyToConfiguration(primaryWriteKey, sCommand, true);
1084 }
1085 }
1086
1087 // take over all changes into the original container
1089 // coverity[check_after_deref] - confusing but correct
1091 {
1093 m_pPrimaryWriteCache.reset();
1094 }
1095 }
1096
1097 else
1098 {
1100 AcceleratorCache::TKeyList lSecondaryWriteKeys = m_pSecondaryWriteCache->getAllKeys();
1101
1102 for (auto const& secondaryReadKey : lSecondaryReadKeys)
1103 {
1104 if (!m_pSecondaryWriteCache->hasKey(secondaryReadKey))
1105 removeKeyFromConfiguration(secondaryReadKey, false);
1106 }
1107
1108 for (auto const& secondaryWriteKey : lSecondaryWriteKeys)
1109 {
1110 OUString sCommand = m_pSecondaryWriteCache->getCommandByKey(secondaryWriteKey);
1111 if (!m_aSecondaryReadCache.hasKey(secondaryWriteKey))
1112 {
1113 insertKeyToConfiguration(secondaryWriteKey, sCommand, false);
1114 }
1115 else
1116 {
1117 OUString sReadCommand = m_aSecondaryReadCache.getCommandByKey(secondaryWriteKey);
1118 if (sReadCommand != sCommand)
1119 insertKeyToConfiguration(secondaryWriteKey, sCommand, false);
1120 }
1121 }
1122
1123 // take over all changes into the original container
1125 // coverity[check_after_deref] - confusing but correct
1127 {
1129 m_pSecondaryWriteCache.reset();
1130 }
1131 }
1132
1134}
1135
1136void XCUBasedAcceleratorConfiguration::insertKeyToConfiguration( const css::awt::KeyEvent& aKeyEvent, const OUString& sCommand, const bool bPreferred )
1137{
1138 css::uno::Reference< css::container::XNameAccess > xAccess;
1139 css::uno::Reference< css::container::XNameContainer > xContainer;
1140 css::uno::Reference< css::lang::XSingleServiceFactory > xFac;
1141 css::uno::Reference< css::uno::XInterface > xInst;
1142
1143 if ( bPreferred )
1144 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1145 else
1146 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1147
1149 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1151 {
1152 css::uno::Reference< css::container::XNameContainer > xModules;
1153 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1154 if ( !xModules->hasByName(m_sModuleCFG) )
1155 {
1156 xFac.set(xModules, css::uno::UNO_QUERY);
1157 xInst = xFac->createInstance();
1158 xModules->insertByName(m_sModuleCFG, css::uno::Any(xInst));
1159 }
1160 xModules->getByName(m_sModuleCFG) >>= xContainer;
1161 }
1162
1163 const OUString sKey = lcl_getKeyString(aKeyEvent);
1164 css::uno::Reference< css::container::XNameAccess > xKey;
1165 css::uno::Reference< css::container::XNameContainer > xCommand;
1166 if ( !xContainer->hasByName(sKey) )
1167 {
1168 xFac.set(xContainer, css::uno::UNO_QUERY);
1169 xInst = xFac->createInstance();
1170 xContainer->insertByName(sKey, css::uno::Any(xInst));
1171 }
1172 xContainer->getByName(sKey) >>= xKey;
1173
1174 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1175 OUString sLocale = impl_ts_getLocale();
1176 if ( !xCommand->hasByName(sLocale) )
1177 xCommand->insertByName(sLocale, css::uno::Any(sCommand));
1178 else
1179 xCommand->replaceByName(sLocale, css::uno::Any(sCommand));
1180}
1181
1182void XCUBasedAcceleratorConfiguration::removeKeyFromConfiguration( const css::awt::KeyEvent& aKeyEvent, const bool bPreferred )
1183{
1184 css::uno::Reference< css::container::XNameAccess > xAccess;
1185 css::uno::Reference< css::container::XNameContainer > xContainer;
1186
1187 if ( bPreferred )
1188 m_xCfg->getByName(CFG_ENTRY_PRIMARY) >>= xAccess;
1189 else
1190 m_xCfg->getByName(CFG_ENTRY_SECONDARY) >>= xAccess;
1191
1193 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1195 {
1196 css::uno::Reference< css::container::XNameAccess > xModules;
1197 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1198 if ( !xModules->hasByName(m_sModuleCFG) )
1199 return;
1200 xModules->getByName(m_sModuleCFG) >>= xContainer;
1201 }
1202
1203 const OUString sKey = lcl_getKeyString(aKeyEvent);
1204 xContainer->removeByName(sKey);
1205}
1206
1207void XCUBasedAcceleratorConfiguration::reloadChanged( const OUString& sPrimarySecondary, std::u16string_view sGlobalModules, const OUString& sModule, const OUString& sKey )
1208{
1209 css::uno::Reference< css::container::XNameAccess > xAccess;
1210 css::uno::Reference< css::container::XNameContainer > xContainer;
1211
1212 m_xCfg->getByName(sPrimarySecondary) >>= xAccess;
1213 if ( sGlobalModules == CFG_ENTRY_GLOBAL )
1214 xAccess->getByName(CFG_ENTRY_GLOBAL) >>= xContainer;
1215 else
1216 {
1217 css::uno::Reference< css::container::XNameAccess > xModules;
1218 xAccess->getByName(CFG_ENTRY_MODULES) >>= xModules;
1219 if ( !xModules->hasByName(sModule) )
1220 return;
1221 xModules->getByName(sModule) >>= xContainer;
1222 }
1223
1224 css::awt::KeyEvent aKeyEvent;
1225
1226 sal_Int32 nIndex = 0;
1227 std::u16string_view sKeyIdentifier = o3tl::getToken(sKey, 0, '_', nIndex);
1228 aKeyEvent.KeyCode = KeyMapping::get().mapIdentifierToCode(OUString::Concat("KEY_") + sKeyIdentifier);
1229
1230 const int nToken = 4;
1231 for (sal_Int32 i = 0; i < nToken; ++i)
1232 {
1233 if ( nIndex < 0 )
1234 break;
1235
1236 std::u16string_view sToken = o3tl::getToken(sKey, 0, '_', nIndex);
1237 if ( sToken == u"SHIFT" )
1238 aKeyEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
1239 else if ( sToken == u"MOD1" )
1240 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD1;
1241 else if ( sToken == u"MOD2" )
1242 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD2;
1243 else if ( sToken == u"MOD3" )
1244 aKeyEvent.Modifiers |= css::awt::KeyModifier::MOD3;
1245 }
1246
1247 css::uno::Reference< css::container::XNameAccess > xKey;
1248 css::uno::Reference< css::container::XNameAccess > xCommand;
1249 OUString sCommand;
1250
1251 if (xContainer->hasByName(sKey))
1252 {
1253 OUString sLocale = impl_ts_getLocale();
1254 xContainer->getByName(sKey) >>= xKey;
1255 xKey->getByName(CFG_PROP_COMMAND) >>= xCommand;
1256 xCommand->getByName(sLocale) >>= sCommand;
1257 }
1258
1259 if ( sPrimarySecondary == CFG_ENTRY_PRIMARY )
1260 {
1261 if (sCommand.isEmpty())
1262 m_aPrimaryReadCache.removeKey(aKeyEvent);
1263 else
1264 m_aPrimaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1265 }
1266 else if ( sPrimarySecondary == CFG_ENTRY_SECONDARY )
1267 {
1268 if (sCommand.isEmpty())
1270 else
1271 m_aSecondaryReadCache.setKeyCommandPair(aKeyEvent, sCommand);
1272 }
1273}
1274
1275AcceleratorCache& XCUBasedAcceleratorConfiguration::impl_getCFG(bool bPreferred, bool bWriteAccessRequested)
1276{
1278
1279 if (bPreferred)
1280 {
1281 //create copy of our readonly-cache, if write access is forced ... but
1282 //not still possible!
1283 if ( bWriteAccessRequested && !m_pPrimaryWriteCache )
1284 {
1286 }
1287
1288 // in case, we have a writeable cache, we use it for reading too!
1289 // Otherwise the API user can't find its own changes...
1291 return *m_pPrimaryWriteCache;
1292 else
1293 return m_aPrimaryReadCache;
1294 }
1295
1296 else
1297 {
1298 //create copy of our readonly-cache, if write access is forced ... but
1299 //not still possible!
1300 if ( bWriteAccessRequested && !m_pSecondaryWriteCache )
1301 {
1303 }
1304
1305 // in case, we have a writeable cache, we use it for reading too!
1306 // Otherwise the API user can't find its own changes...
1308 return *m_pSecondaryWriteCache;
1309 else
1310 return m_aSecondaryReadCache;
1311 }
1312}
1313
1315{
1316 OUString sISOLocale = officecfg::Setup::L10N::ooLocale::get();
1317
1318 if (sISOLocale.isEmpty())
1319 return "en-US";
1320 return sISOLocale;
1321}
1322
1323} // namespace framework
1324
1325/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XInputStream > xStream
constexpr OUStringLiteral TARGET_CURRENT
constexpr OUStringLiteral PRESET_DEFAULT
AnyEventRef aEvent
static css::uno::Reference< css::uno::XInterface > openConfig(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &sPackage, EConfigurationModes eMode)
static void flush(const css::uno::Reference< css::uno::XInterface > &xCFG)
implements a cache for any accelerator configuration.
TKeyList getKeysByCommand(const OUString &sCommand) const
returns the list of keys, which are registered for this command.
void setKeyCommandPair(const css::awt::KeyEvent &aKey, const OUString &sCommand)
add a new or change an existing key-command pair of this container.
::std::vector< css::awt::KeyEvent > TKeyList
commands -> keys
void removeCommand(const OUString &sCommand)
bool hasCommand(const OUString &sCommand) const
OUString getCommandByKey(const css::awt::KeyEvent &aKey) const
void removeKey(const css::awt::KeyEvent &aKey)
bool hasKey(const css::awt::KeyEvent &aKey) const
checks if the specified key exists.
static KeyMapping & get()
Definition: keymapping.cxx:159
sal_uInt16 mapIdentifierToCode(const OUString &sIdentifier)
return a suitable key code for the specified key identifier.
Definition: keymapping.cxx:164
css::uno::Reference< css::io::XStream > openPreset(std::u16string_view sPreset)
open the specified preset as stream object and return it.
void commitUserChanges()
do anything which is necessary to flush all changes back to disk.
void copyPresetToTarget(std::u16string_view sPreset, std::u16string_view sTarget)
try to copy the specified preset from the share layer to the user layer and establish it as the speci...
css::uno::Reference< css::io::XStream > openTarget(std::u16string_view sTarget, sal_Int32 nMode)
open the specified target as stream object and return it.
virtual OUString SAL_CALL getCommandByKeyEvent(const css::awt::KeyEvent &aKeyEvent) override
virtual void SAL_CALL removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener > &xListener) override
void reloadChanged(const OUString &sPrimarySecondary, std::u16string_view sGlobalModules, const OUString &sModule, const OUString &sKey)
virtual void SAL_CALL removeKeyEvent(const css::awt::KeyEvent &aKeyEvent) override
virtual void SAL_CALL addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener > &xListener) override
virtual void SAL_CALL removeCommandFromAllKeyEvents(const OUString &sCommand) override
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString > &lCommandList) override
virtual sal_Bool SAL_CALL isModified() override
virtual css::uno::Sequence< css::awt::KeyEvent > SAL_CALL getAllKeyEvents() override
virtual void SAL_CALL removeResetListener(const css::uno::Reference< css::form::XResetListener > &xListener) override
virtual css::uno::Sequence< css::awt::KeyEvent > SAL_CALL getKeyEventsByCommand(const OUString &sCommand) override
css::uno::Reference< css::container::XNameAccess > m_xCfg
virtual void SAL_CALL storeToStorage(const css::uno::Reference< css::embed::XStorage > &xStorage) override
std::unique_ptr< AcceleratorCache > m_pSecondaryWriteCache
void insertKeyToConfiguration(const css::awt::KeyEvent &aKeyEvent, const OUString &sCommand, const bool bPreferred)
virtual sal_Bool SAL_CALL hasStorage() override
virtual void SAL_CALL setKeyEvent(const css::awt::KeyEvent &aKeyEvent, const OUString &sCommand) override
void removeKeyFromConfiguration(const css::awt::KeyEvent &aKeyEvent, const bool bPreferred)
std::unique_ptr< AcceleratorCache > m_pPrimaryWriteCache
virtual void SAL_CALL disposing(const css::lang::EventObject &aEvent) override
css::uno::Reference< css::uno::XComponentContext > m_xContext
the global uno service manager.
AcceleratorCache & impl_getCFG(bool bPreferred, bool bWriteAccessRequested=false)
XCUBasedAcceleratorConfiguration(css::uno::Reference< css::uno::XComponentContext > xContext)
virtual void SAL_CALL addResetListener(const css::uno::Reference< css::form::XResetListener > &xListener) override
virtual sal_Bool SAL_CALL isReadOnly() override
virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent &aEvent) override
OUString impl_ts_getLocale() const
return the current office locale.
void impl_ts_load(bool bPreferred, const css::uno::Reference< css::container::XNameAccess > &xCfg)
virtual void SAL_CALL setStorage(const css::uno::Reference< css::embed::XStorage > &xStorage) override
virtual void SAL_CALL removeCommandFromAllKeyEvents(const OUString &sCommand) override
virtual void SAL_CALL setStorage(const css::uno::Reference< css::embed::XStorage > &xStorage) override
virtual sal_Bool SAL_CALL isModified() override
std::unique_ptr< AcceleratorCache > m_pWriteCache
used to implement the copy on write pattern!
virtual void SAL_CALL removeResetListener(const css::uno::Reference< css::form::XResetListener > &xListener) override
virtual void SAL_CALL setKeyEvent(const css::awt::KeyEvent &aKeyEvent, const OUString &sCommand) override
virtual void SAL_CALL removeConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener > &xListener) override
virtual css::uno::Sequence< css::awt::KeyEvent > SAL_CALL getKeyEventsByCommand(const OUString &sCommand) override
AcceleratorCache & impl_getCFG(bool bWriteAccessRequested=false)
returns a reference to one of our internal cache members.
virtual void SAL_CALL addConfigurationListener(const css::uno::Reference< css::ui::XUIConfigurationListener > &xListener) override
PresetHandler m_aPresetHandler
used to: i ) copy configuration files from the share to the user layer ii ) provide access to these c...
virtual sal_Bool SAL_CALL hasStorage() override
virtual void SAL_CALL addResetListener(const css::uno::Reference< css::form::XResetListener > &xListener) override
OUString impl_ts_getLocale() const
return the current office locale.
void impl_ts_save(const css::uno::Reference< css::io::XOutputStream > &xStream)
save a configuration set, using the given stream.
XMLBasedAcceleratorConfiguration(const css::uno::Reference< css::uno::XComponentContext > &xContext)
css::uno::Reference< css::uno::XComponentContext > m_xContext
the global uno service manager.
virtual sal_Bool SAL_CALL isReadOnly() override
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPreferredKeyEventsForCommandList(const css::uno::Sequence< OUString > &lCommandList) override
virtual void SAL_CALL removeKeyEvent(const css::awt::KeyEvent &aKeyEvent) override
void impl_ts_load(const css::uno::Reference< css::io::XInputStream > &xStream)
load a configuration set, using the given stream.
virtual void SAL_CALL storeToStorage(const css::uno::Reference< css::embed::XStorage > &xStorage) override
AcceleratorCache m_aReadCache
contains the cached configuration data
virtual css::uno::Sequence< css::awt::KeyEvent > SAL_CALL getAllKeyEvents() override
virtual OUString SAL_CALL getCommandByKeyEvent(const css::awt::KeyEvent &aKeyEvent) override
float u
css::uno::Reference< css::uno::XComponentContext > m_xContext
sal_Int32 nIndex
#define SAL_WARN_IF(condition, area, stream)
#define SAL_INFO(area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
constexpr OUStringLiteral CFG_PROP_COMMAND
static OUString lcl_getKeyString(const css::awt::KeyEvent &aKeyEvent)
constexpr OUStringLiteral CFG_ENTRY_GLOBAL
static AcceleratorCache::TKeyList::const_iterator lcl_getPreferredKey(const AcceleratorCache::TKeyList &lKeys)
constexpr OUStringLiteral CFG_ENTRY_MODULES
constexpr OUStringLiteral CFG_ENTRY_PRIMARY
constexpr OUStringLiteral CFG_ENTRY_SECONDARY
int i
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
long Long
DefTokenId nToken
unsigned char sal_Bool