Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / unotools / source / config / lingucfg.cxx
blob0b39db9172ef5d2bcde61c71f5cd0f4170b2c24d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <com/sun/star/lang/Locale.hpp>
23 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/container/XNameAccess.hpp>
27 #include <com/sun/star/util/XChangesBatch.hpp>
28 #include <sal/log.hxx>
29 #include <comphelper/diagnose_ex.hxx>
30 #include <i18nlangtag/mslangid.hxx>
31 #include <i18nlangtag/languagetag.hxx>
32 #include <tools/debug.hxx>
33 #include <unotools/configitem.hxx>
34 #include <unotools/lingucfg.hxx>
35 #include <unotools/linguprops.hxx>
36 #include <comphelper/getexpandeduri.hxx>
37 #include <comphelper/processfactory.hxx>
38 #include <o3tl/string_view.hxx>
39 #include <mutex>
41 #include "itemholder1.hxx"
43 using namespace com::sun::star;
45 constexpr OUStringLiteral FILE_PROTOCOL = u"file:///";
47 namespace
49 std::mutex& theSvtLinguConfigItemMutex()
51 static std::mutex SINGLETON;
52 return SINGLETON;
56 static bool lcl_SetLocale( LanguageType &rLanguage, const uno::Any &rVal )
58 bool bSucc = false;
60 lang::Locale aNew;
61 if (rVal >>= aNew) // conversion successful?
63 LanguageType nNew = LanguageTag::convertToLanguageType( aNew, false);
64 if (nNew != rLanguage)
66 rLanguage = nNew;
67 bSucc = true;
70 return bSucc;
73 static OUString lcl_LanguageToCfgLocaleStr( LanguageType nLanguage )
75 OUString aRes;
76 if (LANGUAGE_SYSTEM != nLanguage)
77 aRes = LanguageTag::convertToBcp47( nLanguage );
78 return aRes;
81 static LanguageType lcl_CfgAnyToLanguage( const uno::Any &rVal )
83 OUString aTmp;
84 rVal >>= aTmp;
85 return (aTmp.isEmpty()) ? LANGUAGE_SYSTEM : LanguageTag::convertToLanguageTypeWithFallback( aTmp );
88 SvtLinguOptions::SvtLinguOptions()
89 : bROActiveDics(false)
90 , bROActiveConvDics(false)
91 , nHyphMinLeading(2)
92 , nHyphMinTrailing(2)
93 , nHyphMinWordLength(0)
94 , bROHyphMinLeading(false)
95 , bROHyphMinTrailing(false)
96 , bROHyphMinWordLength(false)
97 , nDefaultLanguage(LANGUAGE_NONE)
98 , nDefaultLanguage_CJK(LANGUAGE_NONE)
99 , nDefaultLanguage_CTL(LANGUAGE_NONE)
100 , bRODefaultLanguage(false)
101 , bRODefaultLanguage_CJK(false)
102 , bRODefaultLanguage_CTL(false)
103 , bIsSpellSpecial(true)
104 , bIsSpellAuto(false)
105 , bIsSpellReverse(false)
106 , bROIsSpellSpecial(false)
107 , bROIsSpellAuto(false)
108 , bROIsSpellReverse(false)
109 , bIsHyphSpecial(true)
110 , bIsHyphAuto(false)
111 , bROIsHyphSpecial(false)
112 , bROIsHyphAuto(false)
113 , bIsUseDictionaryList(true)
114 , bIsIgnoreControlCharacters(true)
115 , bROIsUseDictionaryList(false)
116 , bROIsIgnoreControlCharacters(false)
117 , bIsSpellWithDigits(false)
118 , bIsSpellUpperCase(false)
119 , bIsSpellCapitalization(true)
120 , bIsSpellClosedCompound(true)
121 , bIsSpellHyphenatedCompound(true)
122 , bROIsSpellWithDigits(false)
123 , bROIsSpellUpperCase(false)
124 , bROIsSpellCapitalization(false)
125 , bROIsSpellClosedCompound(false)
126 , bROIsSpellHyphenatedCompound(false)
127 , bIsIgnorePostPositionalWord(true)
128 , bIsAutoCloseDialog(false)
129 , bIsShowEntriesRecentlyUsedFirst(false)
130 , bIsAutoReplaceUniqueEntries(false)
131 , bIsDirectionToSimplified(true)
132 , bIsUseCharacterVariants(false)
133 , bIsTranslateCommonTerms(false)
134 , bIsReverseMapping(false)
135 , bROIsIgnorePostPositionalWord(false)
136 , bROIsAutoCloseDialog(false)
137 , bROIsShowEntriesRecentlyUsedFirst(false)
138 , bROIsAutoReplaceUniqueEntries(false)
139 , bROIsDirectionToSimplified(false)
140 , bROIsUseCharacterVariants(false)
141 , bROIsTranslateCommonTerms(false)
142 , bROIsReverseMapping(false)
143 , nDataFilesChangedCheckValue(0)
144 , bRODataFilesChangedCheckValue(false)
145 , bIsGrammarAuto(false)
146 , bIsGrammarInteractive(false)
147 , bROIsGrammarAuto(false)
148 , bROIsGrammarInteractive(false)
152 class SvtLinguConfigItem : public utl::ConfigItem
154 SvtLinguOptions aOpt;
156 static bool GetHdlByName( sal_Int32 &rnHdl, std::u16string_view rPropertyName, bool bFullPropName = false );
157 static uno::Sequence< OUString > GetPropertyNames();
158 void LoadOptions( const uno::Sequence< OUString > &rProperyNames );
159 bool SaveOptions( const uno::Sequence< OUString > &rProperyNames );
161 SvtLinguConfigItem(const SvtLinguConfigItem&) = delete;
162 SvtLinguConfigItem& operator=(const SvtLinguConfigItem&) = delete;
163 virtual void ImplCommit() override;
165 public:
166 SvtLinguConfigItem();
168 // utl::ConfigItem
169 virtual void Notify( const css::uno::Sequence< OUString > &rPropertyNames ) override;
171 // make some protected functions of utl::ConfigItem public
172 using utl::ConfigItem::GetNodeNames;
173 using utl::ConfigItem::GetProperties;
174 //using utl::ConfigItem::PutProperties;
175 //using utl::ConfigItem::SetSetProperties;
176 using utl::ConfigItem::ReplaceSetProperties;
177 //using utl::ConfigItem::GetReadOnlyStates;
179 css::uno::Any
180 GetProperty( std::u16string_view rPropertyName ) const;
181 css::uno::Any
182 GetProperty( sal_Int32 nPropertyHandle ) const;
184 bool SetProperty( std::u16string_view rPropertyName,
185 const css::uno::Any &rValue );
186 bool SetProperty( sal_Int32 nPropertyHandle,
187 const css::uno::Any &rValue );
189 void GetOptions( SvtLinguOptions& ) const;
191 bool IsReadOnly( std::u16string_view rPropertyName ) const;
192 bool IsReadOnly( sal_Int32 nPropertyHandle ) const;
195 SvtLinguConfigItem::SvtLinguConfigItem() :
196 utl::ConfigItem( "Office.Linguistic" )
198 const uno::Sequence< OUString > &rPropertyNames = GetPropertyNames();
199 LoadOptions( rPropertyNames );
200 ClearModified();
202 // request notify events when properties change
203 EnableNotification( rPropertyNames );
206 void SvtLinguConfigItem::Notify( const uno::Sequence< OUString > &rPropertyNames )
209 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
210 LoadOptions( rPropertyNames );
212 NotifyListeners(ConfigurationHints::NONE);
215 void SvtLinguConfigItem::ImplCommit()
217 SaveOptions( GetPropertyNames() );
220 namespace {
222 struct NamesToHdl
224 const char *pFullPropName; // full qualified name as used in configuration
225 OUString aPropName; // property name only (atom) of above
226 sal_Int32 nHdl; // numeric handle representing the property
231 NamesToHdl const aNamesToHdl[] =
233 {/* 0 */ "General/DefaultLocale", UPN_DEFAULT_LOCALE, UPH_DEFAULT_LOCALE},
234 {/* 1 */ "General/DictionaryList/ActiveDictionaries", UPN_ACTIVE_DICTIONARIES, UPH_ACTIVE_DICTIONARIES},
235 {/* 2 */ "General/DictionaryList/IsUseDictionaryList", UPN_IS_USE_DICTIONARY_LIST, UPH_IS_USE_DICTIONARY_LIST},
236 {/* 3 */ "General/IsIgnoreControlCharacters", UPN_IS_IGNORE_CONTROL_CHARACTERS, UPH_IS_IGNORE_CONTROL_CHARACTERS},
237 {/* 5 */ "General/DefaultLocale_CJK", UPN_DEFAULT_LOCALE_CJK, UPH_DEFAULT_LOCALE_CJK},
238 {/* 6 */ "General/DefaultLocale_CTL", UPN_DEFAULT_LOCALE_CTL, UPH_DEFAULT_LOCALE_CTL},
240 {/* 7 */ "SpellChecking/IsSpellUpperCase", UPN_IS_SPELL_UPPER_CASE, UPH_IS_SPELL_UPPER_CASE},
241 {/* 8 */ "SpellChecking/IsSpellWithDigits", UPN_IS_SPELL_WITH_DIGITS, UPH_IS_SPELL_WITH_DIGITS},
242 {/* 9 */ "SpellChecking/IsSpellCapitalization", UPN_IS_SPELL_CAPITALIZATION, UPH_IS_SPELL_CAPITALIZATION},
243 {/* 10 */ "SpellChecking/IsSpellAuto", UPN_IS_SPELL_AUTO, UPH_IS_SPELL_AUTO},
244 {/* 11 */ "SpellChecking/IsSpellSpecial", UPN_IS_SPELL_SPECIAL, UPH_IS_SPELL_SPECIAL},
245 {/* 12 */ "SpellChecking/IsSpellClosedCompound", UPN_IS_SPELL_CLOSED_COMPOUND, UPH_IS_SPELL_CLOSED_COMPOUND},
246 {/* 13 */ "SpellChecking/IsSpellHyphenatedCompound", UPN_IS_SPELL_HYPHENATED_COMPOUND, UPH_IS_SPELL_HYPHENATED_COMPOUND},
247 {/* 14 */ "SpellChecking/IsReverseDirection", UPN_IS_WRAP_REVERSE, UPH_IS_WRAP_REVERSE},
249 {/* 15 */ "Hyphenation/MinLeading", UPN_HYPH_MIN_LEADING, UPH_HYPH_MIN_LEADING},
250 {/* 16 */ "Hyphenation/MinTrailing", UPN_HYPH_MIN_TRAILING, UPH_HYPH_MIN_TRAILING},
251 {/* 17 */ "Hyphenation/MinWordLength", UPN_HYPH_MIN_WORD_LENGTH, UPH_HYPH_MIN_WORD_LENGTH},
252 {/* 18 */ "Hyphenation/IsHyphSpecial", UPN_IS_HYPH_SPECIAL, UPH_IS_HYPH_SPECIAL},
253 {/* 19 */ "Hyphenation/IsHyphAuto", UPN_IS_HYPH_AUTO, UPH_IS_HYPH_AUTO},
255 {/* 20 */ "TextConversion/ActiveConversionDictionaries", UPN_ACTIVE_CONVERSION_DICTIONARIES, UPH_ACTIVE_CONVERSION_DICTIONARIES},
256 {/* 21 */ "TextConversion/IsIgnorePostPositionalWord", UPN_IS_IGNORE_POST_POSITIONAL_WORD, UPH_IS_IGNORE_POST_POSITIONAL_WORD},
257 {/* 22 */ "TextConversion/IsAutoCloseDialog", UPN_IS_AUTO_CLOSE_DIALOG, UPH_IS_AUTO_CLOSE_DIALOG},
258 {/* 23 */ "TextConversion/IsShowEntriesRecentlyUsedFirst", UPN_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST},
259 {/* 24 */ "TextConversion/IsAutoReplaceUniqueEntries", UPN_IS_AUTO_REPLACE_UNIQUE_ENTRIES, UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES},
260 {/* 25 */ "TextConversion/IsDirectionToSimplified", UPN_IS_DIRECTION_TO_SIMPLIFIED, UPH_IS_DIRECTION_TO_SIMPLIFIED},
261 {/* 26 */ "TextConversion/IsUseCharacterVariants", UPN_IS_USE_CHARACTER_VARIANTS, UPH_IS_USE_CHARACTER_VARIANTS},
262 {/* 27 */ "TextConversion/IsTranslateCommonTerms", UPN_IS_TRANSLATE_COMMON_TERMS, UPH_IS_TRANSLATE_COMMON_TERMS},
263 {/* 28 */ "TextConversion/IsReverseMapping", UPN_IS_REVERSE_MAPPING, UPH_IS_REVERSE_MAPPING},
265 {/* 29 */ "ServiceManager/DataFilesChangedCheckValue", UPN_DATA_FILES_CHANGED_CHECK_VALUE, UPH_DATA_FILES_CHANGED_CHECK_VALUE},
267 {/* 30 */ "GrammarChecking/IsAutoCheck", UPN_IS_GRAMMAR_AUTO, UPH_IS_GRAMMAR_AUTO},
268 {/* 31 */ "GrammarChecking/IsInteractiveCheck", UPN_IS_GRAMMAR_INTERACTIVE, UPH_IS_GRAMMAR_INTERACTIVE},
270 /* similar to entry 0 (thus no own configuration entry) but with different property name and type */
271 { nullptr, UPN_DEFAULT_LANGUAGE, UPH_DEFAULT_LANGUAGE},
273 { nullptr, "", -1}
276 uno::Sequence< OUString > SvtLinguConfigItem::GetPropertyNames()
278 uno::Sequence< OUString > aNames;
279 aNames.realloc(std::size(aNamesToHdl));
280 OUString *pNames = aNames.getArray();
281 sal_Int32 nIdx = 0;
282 for (auto const & nameToHdl: aNamesToHdl)
284 const char *pFullPropName = nameToHdl.pFullPropName;
285 if (pFullPropName)
286 pNames[ nIdx++ ] = OUString::createFromAscii( pFullPropName );
288 aNames.realloc( nIdx );
290 return aNames;
293 bool SvtLinguConfigItem::GetHdlByName(
294 sal_Int32 &rnHdl,
295 std::u16string_view rPropertyName,
296 bool bFullPropName )
298 NamesToHdl const *pEntry = &aNamesToHdl[0];
300 if (bFullPropName)
302 while (pEntry && pEntry->pFullPropName != nullptr)
304 if (o3tl::equalsAscii(rPropertyName, pEntry->pFullPropName ))
306 rnHdl = pEntry->nHdl;
307 break;
309 ++pEntry;
311 return pEntry && pEntry->pFullPropName != nullptr;
313 else
315 while (pEntry && pEntry->pFullPropName != nullptr)
317 if (rPropertyName == pEntry->aPropName )
319 rnHdl = pEntry->nHdl;
320 break;
322 ++pEntry;
324 return pEntry && pEntry->pFullPropName != nullptr;
328 uno::Any SvtLinguConfigItem::GetProperty( std::u16string_view rPropertyName ) const
330 sal_Int32 nHdl;
331 return GetHdlByName( nHdl, rPropertyName ) ? GetProperty( nHdl ) : uno::Any();
334 uno::Any SvtLinguConfigItem::GetProperty( sal_Int32 nPropertyHandle ) const
336 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
338 uno::Any aRes;
340 const sal_Int16 *pnVal = nullptr;
341 const LanguageType *plVal = nullptr;
342 const bool *pbVal = nullptr;
343 const sal_Int32 *pnInt32Val = nullptr;
345 const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
346 switch (nPropertyHandle)
348 case UPH_IS_USE_DICTIONARY_LIST : pbVal = &rOpt.bIsUseDictionaryList; break;
349 case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters; break;
350 case UPH_IS_HYPH_AUTO : pbVal = &rOpt.bIsHyphAuto; break;
351 case UPH_IS_HYPH_SPECIAL : pbVal = &rOpt.bIsHyphSpecial; break;
352 case UPH_IS_SPELL_AUTO : pbVal = &rOpt.bIsSpellAuto; break;
353 case UPH_IS_SPELL_SPECIAL : pbVal = &rOpt.bIsSpellSpecial; break;
354 case UPH_IS_WRAP_REVERSE : pbVal = &rOpt.bIsSpellReverse; break;
355 case UPH_DEFAULT_LANGUAGE : plVal = &rOpt.nDefaultLanguage; break;
356 case UPH_IS_SPELL_CAPITALIZATION : pbVal = &rOpt.bIsSpellCapitalization; break;
357 case UPH_IS_SPELL_CLOSED_COMPOUND: pbVal = &rOpt.bIsSpellClosedCompound; break;
358 case UPH_IS_SPELL_HYPHENATED_COMPOUND: pbVal = &rOpt.bIsSpellHyphenatedCompound; break;
359 case UPH_IS_SPELL_WITH_DIGITS : pbVal = &rOpt.bIsSpellWithDigits; break;
360 case UPH_IS_SPELL_UPPER_CASE : pbVal = &rOpt.bIsSpellUpperCase; break;
361 case UPH_HYPH_MIN_LEADING : pnVal = &rOpt.nHyphMinLeading; break;
362 case UPH_HYPH_MIN_TRAILING : pnVal = &rOpt.nHyphMinTrailing; break;
363 case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &rOpt.nHyphMinWordLength; break;
364 case UPH_ACTIVE_DICTIONARIES :
366 aRes <<= rOpt.aActiveDics;
367 break;
369 case UPH_ACTIVE_CONVERSION_DICTIONARIES :
371 aRes <<= rOpt.aActiveConvDics;
372 break;
374 case UPH_DEFAULT_LOCALE :
376 aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage, false);
377 break;
379 case UPH_DEFAULT_LOCALE_CJK :
381 aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CJK, false);
382 break;
384 case UPH_DEFAULT_LOCALE_CTL :
386 aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CTL, false);
387 break;
389 case UPH_IS_IGNORE_POST_POSITIONAL_WORD : pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
390 case UPH_IS_AUTO_CLOSE_DIALOG : pbVal = &rOpt.bIsAutoCloseDialog; break;
391 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
392 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
394 case UPH_IS_DIRECTION_TO_SIMPLIFIED: pbVal = &rOpt.bIsDirectionToSimplified; break;
395 case UPH_IS_USE_CHARACTER_VARIANTS : pbVal = &rOpt.bIsUseCharacterVariants; break;
396 case UPH_IS_TRANSLATE_COMMON_TERMS : pbVal = &rOpt.bIsTranslateCommonTerms; break;
397 case UPH_IS_REVERSE_MAPPING : pbVal = &rOpt.bIsReverseMapping; break;
399 case UPH_DATA_FILES_CHANGED_CHECK_VALUE : pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
400 case UPH_IS_GRAMMAR_AUTO: pbVal = &rOpt.bIsGrammarAuto; break;
401 case UPH_IS_GRAMMAR_INTERACTIVE: pbVal = &rOpt.bIsGrammarInteractive; break;
402 default :
403 SAL_WARN( "unotools.config", "unexpected property handle" );
406 if (pbVal)
407 aRes <<= *pbVal;
408 else if (pnVal)
409 aRes <<= *pnVal;
410 else if (plVal)
411 aRes <<= static_cast<sal_Int16>(static_cast<sal_uInt16>(*plVal));
412 else if (pnInt32Val)
413 aRes <<= *pnInt32Val;
415 return aRes;
418 bool SvtLinguConfigItem::SetProperty( std::u16string_view rPropertyName, const uno::Any &rValue )
420 bool bSucc = false;
421 sal_Int32 nHdl;
422 if (GetHdlByName( nHdl, rPropertyName ))
423 bSucc = SetProperty( nHdl, rValue );
424 return bSucc;
427 bool SvtLinguConfigItem::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
429 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
431 bool bSucc = false;
432 if (!rValue.hasValue())
433 return bSucc;
435 bool bMod = false;
437 sal_Int16 *pnVal = nullptr;
438 LanguageType *plVal = nullptr;
439 bool *pbVal = nullptr;
440 sal_Int32 *pnInt32Val = nullptr;
442 SvtLinguOptions &rOpt = aOpt;
443 switch (nPropertyHandle)
445 case UPH_IS_USE_DICTIONARY_LIST : pbVal = &rOpt.bIsUseDictionaryList; break;
446 case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters; break;
447 case UPH_IS_HYPH_AUTO : pbVal = &rOpt.bIsHyphAuto; break;
448 case UPH_IS_HYPH_SPECIAL : pbVal = &rOpt.bIsHyphSpecial; break;
449 case UPH_IS_SPELL_AUTO : pbVal = &rOpt.bIsSpellAuto; break;
450 case UPH_IS_SPELL_SPECIAL : pbVal = &rOpt.bIsSpellSpecial; break;
451 case UPH_IS_WRAP_REVERSE : pbVal = &rOpt.bIsSpellReverse; break;
452 case UPH_DEFAULT_LANGUAGE : plVal = &rOpt.nDefaultLanguage; break;
453 case UPH_IS_SPELL_CAPITALIZATION : pbVal = &rOpt.bIsSpellCapitalization; break;
454 case UPH_IS_SPELL_CLOSED_COMPOUND: pbVal = &rOpt.bIsSpellClosedCompound; break;
455 case UPH_IS_SPELL_HYPHENATED_COMPOUND: pbVal = &rOpt.bIsSpellHyphenatedCompound; break;
456 case UPH_IS_SPELL_WITH_DIGITS : pbVal = &rOpt.bIsSpellWithDigits; break;
457 case UPH_IS_SPELL_UPPER_CASE : pbVal = &rOpt.bIsSpellUpperCase; break;
458 case UPH_HYPH_MIN_LEADING : pnVal = &rOpt.nHyphMinLeading; break;
459 case UPH_HYPH_MIN_TRAILING : pnVal = &rOpt.nHyphMinTrailing; break;
460 case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &rOpt.nHyphMinWordLength; break;
461 case UPH_ACTIVE_DICTIONARIES :
463 rValue >>= rOpt.aActiveDics;
464 bMod = true;
465 break;
467 case UPH_ACTIVE_CONVERSION_DICTIONARIES :
469 rValue >>= rOpt.aActiveConvDics;
470 bMod = true;
471 break;
473 case UPH_DEFAULT_LOCALE :
475 bSucc = lcl_SetLocale( rOpt.nDefaultLanguage, rValue );
476 bMod = bSucc;
477 break;
479 case UPH_DEFAULT_LOCALE_CJK :
481 bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CJK, rValue );
482 bMod = bSucc;
483 break;
485 case UPH_DEFAULT_LOCALE_CTL :
487 bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CTL, rValue );
488 bMod = bSucc;
489 break;
491 case UPH_IS_IGNORE_POST_POSITIONAL_WORD : pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
492 case UPH_IS_AUTO_CLOSE_DIALOG : pbVal = &rOpt.bIsAutoCloseDialog; break;
493 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
494 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
496 case UPH_IS_DIRECTION_TO_SIMPLIFIED : pbVal = &rOpt.bIsDirectionToSimplified; break;
497 case UPH_IS_USE_CHARACTER_VARIANTS : pbVal = &rOpt.bIsUseCharacterVariants; break;
498 case UPH_IS_TRANSLATE_COMMON_TERMS : pbVal = &rOpt.bIsTranslateCommonTerms; break;
499 case UPH_IS_REVERSE_MAPPING : pbVal = &rOpt.bIsReverseMapping; break;
501 case UPH_DATA_FILES_CHANGED_CHECK_VALUE : pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
502 case UPH_IS_GRAMMAR_AUTO: pbVal = &rOpt.bIsGrammarAuto; break;
503 case UPH_IS_GRAMMAR_INTERACTIVE: pbVal = &rOpt.bIsGrammarInteractive; break;
504 default :
505 SAL_WARN( "unotools.config", "unexpected property handle" );
508 if (pbVal)
510 bool bNew = bool();
511 if (rValue >>= bNew)
513 if (bNew != *pbVal)
515 *pbVal = bNew;
516 bMod = true;
518 bSucc = true;
521 else if (pnVal)
523 sal_Int16 nNew = sal_Int16();
524 if (rValue >>= nNew)
526 if (nNew != *pnVal)
528 *pnVal = nNew;
529 bMod = true;
531 bSucc = true;
534 else if (plVal)
536 sal_Int16 nNew = sal_Int16();
537 if (rValue >>= nNew)
539 if (nNew != static_cast<sal_uInt16>(*plVal))
541 *plVal = LanguageType(static_cast<sal_uInt16>(nNew));
542 bMod = true;
544 bSucc = true;
547 else if (pnInt32Val)
549 sal_Int32 nNew = sal_Int32();
550 if (rValue >>= nNew)
552 if (nNew != *pnInt32Val)
554 *pnInt32Val = nNew;
555 bMod = true;
557 bSucc = true;
561 if (bMod)
562 SetModified();
564 NotifyListeners(ConfigurationHints::NONE);
565 return bSucc;
568 void SvtLinguConfigItem::GetOptions(SvtLinguOptions &rOptions) const
570 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
571 rOptions = aOpt;
574 void SvtLinguConfigItem::LoadOptions( const uno::Sequence< OUString > &rProperyNames )
576 bool bRes = false;
578 const OUString *pProperyNames = rProperyNames.getConstArray();
579 sal_Int32 nProps = rProperyNames.getLength();
581 const uno::Sequence< uno::Any > aValues = GetProperties( rProperyNames );
582 const uno::Sequence< sal_Bool > aROStates = GetReadOnlyStates( rProperyNames );
584 if (nProps && aValues.getLength() == nProps && aROStates.getLength() == nProps)
586 SvtLinguOptions &rOpt = aOpt;
588 const uno::Any *pValue = aValues.getConstArray();
589 const sal_Bool *pROStates = aROStates.getConstArray();
590 for (sal_Int32 i = 0; i < nProps; ++i)
592 const uno::Any &rVal = pValue[i];
593 sal_Int32 nPropertyHandle(0);
594 GetHdlByName( nPropertyHandle, pProperyNames[i], true );
595 switch ( nPropertyHandle )
597 case UPH_DEFAULT_LOCALE :
598 { rOpt.bRODefaultLanguage = pROStates[i]; rOpt.nDefaultLanguage = lcl_CfgAnyToLanguage( rVal ); } break;
599 case UPH_ACTIVE_DICTIONARIES :
600 { rOpt.bROActiveDics = pROStates[i]; rVal >>= rOpt.aActiveDics; } break;
601 case UPH_IS_USE_DICTIONARY_LIST :
602 { rOpt.bROIsUseDictionaryList = pROStates[i]; rVal >>= rOpt.bIsUseDictionaryList; } break;
603 case UPH_IS_IGNORE_CONTROL_CHARACTERS :
604 { rOpt.bROIsIgnoreControlCharacters = pROStates[i]; rVal >>= rOpt.bIsIgnoreControlCharacters; } break;
605 case UPH_DEFAULT_LOCALE_CJK :
606 { rOpt.bRODefaultLanguage_CJK = pROStates[i]; rOpt.nDefaultLanguage_CJK = lcl_CfgAnyToLanguage( rVal ); } break;
607 case UPH_DEFAULT_LOCALE_CTL :
608 { rOpt.bRODefaultLanguage_CTL = pROStates[i]; rOpt.nDefaultLanguage_CTL = lcl_CfgAnyToLanguage( rVal ); } break;
610 case UPH_IS_SPELL_UPPER_CASE :
611 { rOpt.bROIsSpellUpperCase = pROStates[i]; rVal >>= rOpt.bIsSpellUpperCase; } break;
612 case UPH_IS_SPELL_WITH_DIGITS :
613 { rOpt.bROIsSpellWithDigits = pROStates[i]; rVal >>= rOpt.bIsSpellWithDigits; } break;
614 case UPH_IS_SPELL_CAPITALIZATION :
615 { rOpt.bROIsSpellCapitalization = pROStates[i]; rVal >>= rOpt.bIsSpellCapitalization; } break;
616 case UPH_IS_SPELL_CLOSED_COMPOUND :
617 { rOpt.bROIsSpellClosedCompound = pROStates[i]; rVal >>= rOpt.bIsSpellClosedCompound; } break;
618 case UPH_IS_SPELL_HYPHENATED_COMPOUND :
619 { rOpt.bROIsSpellHyphenatedCompound = pROStates[i]; rVal >>= rOpt.bIsSpellHyphenatedCompound; } break;
621 case UPH_IS_SPELL_AUTO :
622 { rOpt.bROIsSpellAuto = pROStates[i]; rVal >>= rOpt.bIsSpellAuto; } break;
623 case UPH_IS_SPELL_SPECIAL :
624 { rOpt.bROIsSpellSpecial = pROStates[i]; rVal >>= rOpt.bIsSpellSpecial; } break;
625 case UPH_IS_WRAP_REVERSE :
626 { rOpt.bROIsSpellReverse = pROStates[i]; rVal >>= rOpt.bIsSpellReverse; } break;
628 case UPH_HYPH_MIN_LEADING :
629 { rOpt.bROHyphMinLeading = pROStates[i]; rVal >>= rOpt.nHyphMinLeading; } break;
630 case UPH_HYPH_MIN_TRAILING :
631 { rOpt.bROHyphMinTrailing = pROStates[i]; rVal >>= rOpt.nHyphMinTrailing; } break;
632 case UPH_HYPH_MIN_WORD_LENGTH :
633 { rOpt.bROHyphMinWordLength = pROStates[i]; rVal >>= rOpt.nHyphMinWordLength; } break;
634 case UPH_IS_HYPH_SPECIAL :
635 { rOpt.bROIsHyphSpecial = pROStates[i]; rVal >>= rOpt.bIsHyphSpecial; } break;
636 case UPH_IS_HYPH_AUTO :
637 { rOpt.bROIsHyphAuto = pROStates[i]; rVal >>= rOpt.bIsHyphAuto; } break;
639 case UPH_ACTIVE_CONVERSION_DICTIONARIES : { rOpt.bROActiveConvDics = pROStates[i]; rVal >>= rOpt.aActiveConvDics; } break;
641 case UPH_IS_IGNORE_POST_POSITIONAL_WORD :
642 { rOpt.bROIsIgnorePostPositionalWord = pROStates[i]; rVal >>= rOpt.bIsIgnorePostPositionalWord; } break;
643 case UPH_IS_AUTO_CLOSE_DIALOG :
644 { rOpt.bROIsAutoCloseDialog = pROStates[i]; rVal >>= rOpt.bIsAutoCloseDialog; } break;
645 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :
646 { rOpt.bROIsShowEntriesRecentlyUsedFirst = pROStates[i]; rVal >>= rOpt.bIsShowEntriesRecentlyUsedFirst; } break;
647 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :
648 { rOpt.bROIsAutoReplaceUniqueEntries = pROStates[i]; rVal >>= rOpt.bIsAutoReplaceUniqueEntries; } break;
650 case UPH_IS_DIRECTION_TO_SIMPLIFIED :
652 rOpt.bROIsDirectionToSimplified = pROStates[i];
653 if( ! (rVal >>= rOpt.bIsDirectionToSimplified) )
655 //default is locale dependent:
656 if (MsLangId::isTraditionalChinese(rOpt.nDefaultLanguage_CJK))
658 rOpt.bIsDirectionToSimplified = false;
660 else
662 rOpt.bIsDirectionToSimplified = true;
665 } break;
666 case UPH_IS_USE_CHARACTER_VARIANTS :
667 { rOpt.bROIsUseCharacterVariants = pROStates[i]; rVal >>= rOpt.bIsUseCharacterVariants; } break;
668 case UPH_IS_TRANSLATE_COMMON_TERMS :
669 { rOpt.bROIsTranslateCommonTerms = pROStates[i]; rVal >>= rOpt.bIsTranslateCommonTerms; } break;
670 case UPH_IS_REVERSE_MAPPING :
671 { rOpt.bROIsReverseMapping = pROStates[i]; rVal >>= rOpt.bIsReverseMapping; } break;
673 case UPH_DATA_FILES_CHANGED_CHECK_VALUE :
674 { rOpt.bRODataFilesChangedCheckValue = pROStates[i]; rVal >>= rOpt.nDataFilesChangedCheckValue; } break;
676 case UPH_IS_GRAMMAR_AUTO:
677 { rOpt.bROIsGrammarAuto = pROStates[i]; rVal >>= rOpt.bIsGrammarAuto; }
678 break;
679 case UPH_IS_GRAMMAR_INTERACTIVE:
680 { rOpt.bROIsGrammarInteractive = pROStates[i]; rVal >>= rOpt.bIsGrammarInteractive; }
681 break;
683 default:
684 SAL_WARN( "unotools.config", "unexpected case" );
688 bRes = true;
690 DBG_ASSERT( bRes, "LoadOptions failed" );
693 bool SvtLinguConfigItem::SaveOptions( const uno::Sequence< OUString > &rProperyNames )
695 if (!IsModified())
696 return true;
698 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
700 bool bRet = false;
702 sal_Int32 nProps = rProperyNames.getLength();
703 uno::Sequence< uno::Any > aValues( nProps );
704 uno::Any *pValue = aValues.getArray();
706 if (nProps && aValues.getLength() == nProps)
708 const SvtLinguOptions &rOpt = aOpt;
710 OUString aTmp( lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage ) );
711 *pValue++ <<= aTmp; // 0
712 *pValue++ <<= rOpt.aActiveDics; // 1
713 *pValue++ <<= rOpt.bIsUseDictionaryList; // 2
714 *pValue++ <<= rOpt.bIsIgnoreControlCharacters; // 3
715 aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CJK );
716 *pValue++ <<= aTmp; // 5
717 aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CTL );
718 *pValue++ <<= aTmp; // 6
720 *pValue++ <<= rOpt.bIsSpellUpperCase; // 7
721 *pValue++ <<= rOpt.bIsSpellWithDigits; // 8
722 *pValue++ <<= rOpt.bIsSpellCapitalization; // 9
723 *pValue++ <<= rOpt.bIsSpellAuto; // 10
724 *pValue++ <<= rOpt.bIsSpellSpecial; // 11
725 *pValue++ <<= rOpt.bIsSpellClosedCompound; // 12
726 *pValue++ <<= rOpt.bIsSpellHyphenatedCompound; // 13
727 *pValue++ <<= rOpt.bIsSpellReverse; // 14
729 *pValue++ <<= rOpt.nHyphMinLeading; // 15
730 *pValue++ <<= rOpt.nHyphMinTrailing; // 16
731 *pValue++ <<= rOpt.nHyphMinWordLength; // 17
732 *pValue++ <<= rOpt.bIsHyphSpecial; // 18
733 *pValue++ <<= rOpt.bIsHyphAuto; // 19
735 *pValue++ <<= rOpt.aActiveConvDics; // 20
737 *pValue++ <<= rOpt.bIsIgnorePostPositionalWord; // 21
738 *pValue++ <<= rOpt.bIsAutoCloseDialog; // 22
739 *pValue++ <<= rOpt.bIsShowEntriesRecentlyUsedFirst; // 23
740 *pValue++ <<= rOpt.bIsAutoReplaceUniqueEntries; // 24
742 *pValue++ <<= rOpt.bIsDirectionToSimplified; // 25
743 *pValue++ <<= rOpt.bIsUseCharacterVariants; // 26
744 *pValue++ <<= rOpt.bIsTranslateCommonTerms; // 27
745 *pValue++ <<= rOpt.bIsReverseMapping; // 28
747 *pValue++ <<= rOpt.nDataFilesChangedCheckValue; // 29
748 *pValue++ <<= rOpt.bIsGrammarAuto; // 30
749 *pValue++ <<= rOpt.bIsGrammarInteractive; // 31
751 bRet |= PutProperties( rProperyNames, aValues );
754 if (bRet)
755 ClearModified();
757 return bRet;
760 bool SvtLinguConfigItem::IsReadOnly( std::u16string_view rPropertyName ) const
762 bool bReadOnly = false;
763 sal_Int32 nHdl;
764 if (GetHdlByName( nHdl, rPropertyName ))
765 bReadOnly = IsReadOnly( nHdl );
766 return bReadOnly;
769 bool SvtLinguConfigItem::IsReadOnly( sal_Int32 nPropertyHandle ) const
771 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
773 bool bReadOnly = false;
775 const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
776 switch(nPropertyHandle)
778 case UPH_IS_USE_DICTIONARY_LIST : bReadOnly = rOpt.bROIsUseDictionaryList; break;
779 case UPH_IS_IGNORE_CONTROL_CHARACTERS : bReadOnly = rOpt.bROIsIgnoreControlCharacters; break;
780 case UPH_IS_HYPH_AUTO : bReadOnly = rOpt.bROIsHyphAuto; break;
781 case UPH_IS_HYPH_SPECIAL : bReadOnly = rOpt.bROIsHyphSpecial; break;
782 case UPH_IS_SPELL_AUTO : bReadOnly = rOpt.bROIsSpellAuto; break;
783 case UPH_IS_SPELL_SPECIAL : bReadOnly = rOpt.bROIsSpellSpecial; break;
784 case UPH_IS_WRAP_REVERSE : bReadOnly = rOpt.bROIsSpellReverse; break;
785 case UPH_DEFAULT_LANGUAGE : bReadOnly = rOpt.bRODefaultLanguage; break;
786 case UPH_IS_SPELL_CAPITALIZATION : bReadOnly = rOpt.bROIsSpellCapitalization; break;
787 case UPH_IS_SPELL_CLOSED_COMPOUND : bReadOnly = rOpt.bROIsSpellClosedCompound; break;
788 case UPH_IS_SPELL_HYPHENATED_COMPOUND : bReadOnly = rOpt.bROIsSpellHyphenatedCompound; break;
789 case UPH_IS_SPELL_WITH_DIGITS : bReadOnly = rOpt.bROIsSpellWithDigits; break;
790 case UPH_IS_SPELL_UPPER_CASE : bReadOnly = rOpt.bROIsSpellUpperCase; break;
791 case UPH_HYPH_MIN_LEADING : bReadOnly = rOpt.bROHyphMinLeading; break;
792 case UPH_HYPH_MIN_TRAILING : bReadOnly = rOpt.bROHyphMinTrailing; break;
793 case UPH_HYPH_MIN_WORD_LENGTH : bReadOnly = rOpt.bROHyphMinWordLength; break;
794 case UPH_ACTIVE_DICTIONARIES : bReadOnly = rOpt.bROActiveDics; break;
795 case UPH_ACTIVE_CONVERSION_DICTIONARIES : bReadOnly = rOpt.bROActiveConvDics; break;
796 case UPH_DEFAULT_LOCALE : bReadOnly = rOpt.bRODefaultLanguage; break;
797 case UPH_DEFAULT_LOCALE_CJK : bReadOnly = rOpt.bRODefaultLanguage_CJK; break;
798 case UPH_DEFAULT_LOCALE_CTL : bReadOnly = rOpt.bRODefaultLanguage_CTL; break;
799 case UPH_IS_IGNORE_POST_POSITIONAL_WORD : bReadOnly = rOpt.bROIsIgnorePostPositionalWord; break;
800 case UPH_IS_AUTO_CLOSE_DIALOG : bReadOnly = rOpt.bROIsAutoCloseDialog; break;
801 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : bReadOnly = rOpt.bROIsShowEntriesRecentlyUsedFirst; break;
802 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : bReadOnly = rOpt.bROIsAutoReplaceUniqueEntries; break;
803 case UPH_IS_DIRECTION_TO_SIMPLIFIED : bReadOnly = rOpt.bROIsDirectionToSimplified; break;
804 case UPH_IS_USE_CHARACTER_VARIANTS : bReadOnly = rOpt.bROIsUseCharacterVariants; break;
805 case UPH_IS_TRANSLATE_COMMON_TERMS : bReadOnly = rOpt.bROIsTranslateCommonTerms; break;
806 case UPH_IS_REVERSE_MAPPING : bReadOnly = rOpt.bROIsReverseMapping; break;
807 case UPH_DATA_FILES_CHANGED_CHECK_VALUE : bReadOnly = rOpt.bRODataFilesChangedCheckValue; break;
808 case UPH_IS_GRAMMAR_AUTO: bReadOnly = rOpt.bROIsGrammarAuto; break;
809 case UPH_IS_GRAMMAR_INTERACTIVE: bReadOnly = rOpt.bROIsGrammarInteractive; break;
810 default :
811 SAL_WARN( "unotools.config", "unexpected property handle" );
813 return bReadOnly;
816 static SvtLinguConfigItem *pCfgItem = nullptr;
817 static sal_Int32 nCfgItemRefCount = 0;
819 constexpr OUStringLiteral aG_Dictionaries = u"Dictionaries";
821 SvtLinguConfig::SvtLinguConfig()
823 // Global access, must be guarded (multithreading)
824 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
825 ++nCfgItemRefCount;
828 SvtLinguConfig::~SvtLinguConfig()
830 if (pCfgItem && pCfgItem->IsModified())
831 pCfgItem->Commit();
833 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
835 if (--nCfgItemRefCount <= 0)
837 delete pCfgItem;
838 pCfgItem = nullptr;
842 SvtLinguConfigItem & SvtLinguConfig::GetConfigItem()
844 // Global access, must be guarded (multithreading)
845 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
846 if (!pCfgItem)
848 pCfgItem = new SvtLinguConfigItem;
849 aGuard.unlock();
850 ItemHolder1::holdConfigItem(EItem::LinguConfig);
852 return *pCfgItem;
855 uno::Sequence< OUString > SvtLinguConfig::GetNodeNames( const OUString &rNode ) const
857 return GetConfigItem().GetNodeNames( rNode );
860 uno::Sequence< uno::Any > SvtLinguConfig::GetProperties( const uno::Sequence< OUString > &rNames ) const
862 return GetConfigItem().GetProperties(rNames);
865 bool SvtLinguConfig::ReplaceSetProperties(
866 const OUString &rNode, const uno::Sequence< beans::PropertyValue >& rValues )
868 return GetConfigItem().ReplaceSetProperties( rNode, rValues );
871 uno::Any SvtLinguConfig::GetProperty( std::u16string_view rPropertyName ) const
873 return GetConfigItem().GetProperty( rPropertyName );
876 uno::Any SvtLinguConfig::GetProperty( sal_Int32 nPropertyHandle ) const
878 return GetConfigItem().GetProperty( nPropertyHandle );
881 bool SvtLinguConfig::SetProperty( std::u16string_view rPropertyName, const uno::Any &rValue )
883 return GetConfigItem().SetProperty( rPropertyName, rValue );
886 bool SvtLinguConfig::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
888 return GetConfigItem().SetProperty( nPropertyHandle, rValue );
891 void SvtLinguConfig::GetOptions( SvtLinguOptions &rOptions ) const
893 GetConfigItem().GetOptions(rOptions);
896 bool SvtLinguConfig::IsReadOnly( std::u16string_view rPropertyName ) const
898 return GetConfigItem().IsReadOnly( rPropertyName );
901 bool SvtLinguConfig::GetElementNamesFor(
902 const OUString &rNodeName,
903 uno::Sequence< OUString > &rElementNames ) const
905 bool bSuccess = false;
908 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
909 xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
910 xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
911 rElementNames = xNA->getElementNames();
912 bSuccess = true;
914 catch (uno::Exception &)
917 return bSuccess;
920 bool SvtLinguConfig::GetSupportedDictionaryFormatsFor(
921 const OUString &rSetName,
922 const OUString &rSetEntry,
923 uno::Sequence< OUString > &rFormatList ) const
925 if (rSetName.isEmpty() || rSetEntry.isEmpty())
926 return false;
927 bool bSuccess = false;
930 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
931 xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
932 xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY_THROW );
933 xNA.set( xNA->getByName( rSetEntry ), uno::UNO_QUERY_THROW );
934 if (xNA->getByName( "SupportedDictionaryFormats" ) >>= rFormatList)
935 bSuccess = true;
936 DBG_ASSERT( rFormatList.hasElements(), "supported dictionary format list is empty" );
938 catch (uno::Exception &)
941 return bSuccess;
944 static bool lcl_GetFileUrlFromOrigin(
945 OUString /*out*/ &rFileUrl,
946 const OUString &rOrigin )
948 OUString aURL(
949 comphelper::getExpandedUri(
950 comphelper::getProcessComponentContext(), rOrigin));
951 if (aURL.startsWith( FILE_PROTOCOL ))
953 rFileUrl = aURL;
954 return true;
956 else
958 SAL_WARN(
959 "unotools.config", "not a file URL, <" << aURL << ">" );
960 return false;
964 bool SvtLinguConfig::GetDictionaryEntry(
965 const OUString &rNodeName,
966 SvtLinguConfigDictionaryEntry &rDicEntry ) const
968 if (rNodeName.isEmpty())
969 return false;
970 bool bSuccess = false;
973 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
974 xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
975 xNA.set( xNA->getByName( aG_Dictionaries ), uno::UNO_QUERY_THROW );
976 xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
978 // read group data...
979 uno::Sequence< OUString > aLocations;
980 OUString aFormatName;
981 uno::Sequence< OUString > aLocaleNames;
982 bSuccess = (xNA->getByName( "Locations" ) >>= aLocations) &&
983 (xNA->getByName( "Format" ) >>= aFormatName) &&
984 (xNA->getByName( "Locales" ) >>= aLocaleNames);
985 DBG_ASSERT( aLocations.hasElements(), "Dictionary locations not set" );
986 DBG_ASSERT( !aFormatName.isEmpty(), "Dictionary format name not set" );
987 DBG_ASSERT( aLocaleNames.hasElements(), "No locales set for the dictionary" );
989 // if successful continue
990 if (bSuccess)
992 // get file URL's for the locations
993 for (OUString& rLocation : asNonConstRange(aLocations))
995 if (!lcl_GetFileUrlFromOrigin( rLocation, rLocation ))
996 bSuccess = false;
999 // if everything was fine return the result
1000 if (bSuccess)
1002 rDicEntry.aLocations = aLocations;
1003 rDicEntry.aFormatName = aFormatName;
1004 rDicEntry.aLocaleNames = aLocaleNames;
1008 catch (uno::Exception &)
1011 return bSuccess;
1014 uno::Sequence< OUString > SvtLinguConfig::GetDisabledDictionaries() const
1016 uno::Sequence< OUString > aResult;
1019 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1020 xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
1021 xNA->getByName( "DisabledDictionaries" ) >>= aResult;
1023 catch (uno::Exception &)
1026 return aResult;
1029 std::vector< SvtLinguConfigDictionaryEntry > SvtLinguConfig::GetActiveDictionariesByFormat(
1030 std::u16string_view rFormatName ) const
1032 std::vector< SvtLinguConfigDictionaryEntry > aRes;
1033 if (rFormatName.empty())
1034 return aRes;
1038 uno::Sequence< OUString > aElementNames;
1039 GetElementNamesFor( aG_Dictionaries, aElementNames );
1041 const uno::Sequence< OUString > aDisabledDics( GetDisabledDictionaries() );
1043 SvtLinguConfigDictionaryEntry aDicEntry;
1044 for (const OUString& rElementName : std::as_const(aElementNames))
1046 // does dictionary match the format we are looking for?
1047 if (GetDictionaryEntry( rElementName, aDicEntry ) &&
1048 aDicEntry.aFormatName == rFormatName)
1050 // check if it is active or not
1051 bool bDicIsActive = std::none_of(aDisabledDics.begin(), aDisabledDics.end(),
1052 [&rElementName](const OUString& rDic) { return rDic == rElementName; });
1054 if (bDicIsActive)
1056 DBG_ASSERT( !aDicEntry.aFormatName.isEmpty(),
1057 "FormatName not set" );
1058 DBG_ASSERT( aDicEntry.aLocations.hasElements(),
1059 "Locations not set" );
1060 DBG_ASSERT( aDicEntry.aLocaleNames.hasElements(),
1061 "Locales not set" );
1062 aRes.push_back( aDicEntry );
1067 catch (uno::Exception &)
1071 return aRes;
1074 uno::Reference< util::XChangesBatch > const & SvtLinguConfig::GetMainUpdateAccess() const
1076 if (!m_xMainUpdateAccess.is())
1080 // get configuration provider
1081 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
1082 uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider =
1083 configuration::theDefaultProvider::get( xContext );
1085 // get configuration update access
1086 beans::PropertyValue aValue;
1087 aValue.Name = "nodepath";
1088 aValue.Value <<= OUString("org.openoffice.Office.Linguistic");
1089 uno::Sequence< uno::Any > aProps{ uno::Any(aValue) };
1090 m_xMainUpdateAccess.set(
1091 xConfigurationProvider->createInstanceWithArguments(
1092 "com.sun.star.configuration.ConfigurationUpdateAccess", aProps),
1093 uno::UNO_QUERY_THROW );
1095 catch (uno::Exception &)
1100 return m_xMainUpdateAccess;
1103 OUString SvtLinguConfig::GetVendorImageUrl_Impl(
1104 const OUString &rServiceImplName,
1105 const OUString &rImageName ) const
1107 OUString aRes;
1110 uno::Reference< container::XNameAccess > xImagesNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1111 xImagesNA.set( xImagesNA->getByName("Images"), uno::UNO_QUERY_THROW );
1113 uno::Reference< container::XNameAccess > xNA( xImagesNA->getByName("ServiceNameEntries"), uno::UNO_QUERY_THROW );
1114 xNA.set( xNA->getByName( rServiceImplName ), uno::UNO_QUERY_THROW );
1115 uno::Any aAny(xNA->getByName("VendorImagesNode"));
1116 OUString aVendorImagesNode;
1117 if (aAny >>= aVendorImagesNode)
1119 xNA = xImagesNA;
1120 xNA.set( xNA->getByName("VendorImages"), uno::UNO_QUERY_THROW );
1121 xNA.set( xNA->getByName( aVendorImagesNode ), uno::UNO_QUERY_THROW );
1122 aAny = xNA->getByName( rImageName );
1123 OUString aTmp;
1124 if (aAny >>= aTmp)
1126 if (lcl_GetFileUrlFromOrigin( aTmp, aTmp ))
1127 aRes = aTmp;
1131 catch (uno::Exception &)
1133 DBG_UNHANDLED_EXCEPTION("unotools");
1135 return aRes;
1138 OUString SvtLinguConfig::GetSpellAndGrammarContextSuggestionImage(
1139 const OUString &rServiceImplName
1140 ) const
1142 OUString aRes;
1143 if (!rServiceImplName.isEmpty())
1145 aRes = GetVendorImageUrl_Impl( rServiceImplName, "SpellAndGrammarContextMenuSuggestionImage" );
1147 return aRes;
1150 OUString SvtLinguConfig::GetSpellAndGrammarContextDictionaryImage(
1151 const OUString &rServiceImplName
1152 ) const
1154 OUString aRes;
1155 if (!rServiceImplName.isEmpty())
1157 aRes = GetVendorImageUrl_Impl( rServiceImplName, "SpellAndGrammarContextMenuDictionaryImage" );
1159 return aRes;
1162 OUString SvtLinguConfig::GetSynonymsContextImage(
1163 const OUString &rServiceImplName
1164 ) const
1166 OUString aRes;
1167 if (!rServiceImplName.isEmpty())
1169 OUString aPath( GetVendorImageUrl_Impl( rServiceImplName, "SynonymsContextMenuImage" ) );
1170 aRes = aPath;
1172 return aRes;
1175 bool SvtLinguConfig::HasGrammarChecker() const
1177 bool bRes = false;
1181 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1182 xNA.set( xNA->getByName("ServiceManager"), uno::UNO_QUERY_THROW );
1183 xNA.set( xNA->getByName("GrammarCheckerList"), uno::UNO_QUERY_THROW );
1185 uno::Sequence< OUString > aElementNames( xNA->getElementNames() );
1186 bRes = aElementNames.hasElements();
1188 catch (const uno::Exception&)
1192 return bRes;
1195 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */