tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / unotools / source / config / lingucfg.cxx
blobb49dec173ed82f37ce5b0e710a6130b0b362a29d
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 , bIsSpellClosedCompound(true)
120 , bIsSpellHyphenatedCompound(true)
121 , bROIsSpellWithDigits(false)
122 , bROIsSpellUpperCase(false)
123 , bROIsSpellClosedCompound(false)
124 , bROIsSpellHyphenatedCompound(false)
125 , bIsIgnorePostPositionalWord(true)
126 , bIsAutoCloseDialog(false)
127 , bIsShowEntriesRecentlyUsedFirst(false)
128 , bIsAutoReplaceUniqueEntries(false)
129 , bIsDirectionToSimplified(true)
130 , bIsUseCharacterVariants(false)
131 , bIsTranslateCommonTerms(false)
132 , bIsReverseMapping(false)
133 , bROIsIgnorePostPositionalWord(false)
134 , bROIsAutoCloseDialog(false)
135 , bROIsShowEntriesRecentlyUsedFirst(false)
136 , bROIsAutoReplaceUniqueEntries(false)
137 , bROIsDirectionToSimplified(false)
138 , bROIsUseCharacterVariants(false)
139 , bROIsTranslateCommonTerms(false)
140 , bROIsReverseMapping(false)
141 , nDataFilesChangedCheckValue(0)
142 , bRODataFilesChangedCheckValue(false)
143 , bIsGrammarAuto(false)
144 , bIsGrammarInteractive(false)
145 , bROIsGrammarAuto(false)
146 , bROIsGrammarInteractive(false)
150 class SvtLinguConfigItem : public utl::ConfigItem
152 SvtLinguOptions aOpt;
154 static bool GetHdlByName( sal_Int32 &rnHdl, std::u16string_view rPropertyName, bool bFullPropName = false );
155 static uno::Sequence< OUString > GetPropertyNames();
156 void LoadOptions( const uno::Sequence< OUString > &rProperyNames );
157 bool SaveOptions( const uno::Sequence< OUString > &rProperyNames );
159 SvtLinguConfigItem(const SvtLinguConfigItem&) = delete;
160 SvtLinguConfigItem& operator=(const SvtLinguConfigItem&) = delete;
161 virtual void ImplCommit() override;
163 public:
164 SvtLinguConfigItem();
166 // utl::ConfigItem
167 virtual void Notify( const css::uno::Sequence< OUString > &rPropertyNames ) override;
169 // make some protected functions of utl::ConfigItem public
170 using utl::ConfigItem::GetNodeNames;
171 using utl::ConfigItem::GetProperties;
172 //using utl::ConfigItem::PutProperties;
173 //using utl::ConfigItem::SetSetProperties;
174 using utl::ConfigItem::ReplaceSetProperties;
175 //using utl::ConfigItem::GetReadOnlyStates;
177 css::uno::Any
178 GetProperty( std::u16string_view rPropertyName ) const;
179 css::uno::Any
180 GetProperty( sal_Int32 nPropertyHandle ) const;
182 bool SetProperty( std::u16string_view rPropertyName,
183 const css::uno::Any &rValue );
184 bool SetProperty( sal_Int32 nPropertyHandle,
185 const css::uno::Any &rValue );
187 void GetOptions( SvtLinguOptions& ) const;
189 bool IsReadOnly( std::u16string_view rPropertyName ) const;
190 bool IsReadOnly( sal_Int32 nPropertyHandle ) const;
193 SvtLinguConfigItem::SvtLinguConfigItem() :
194 utl::ConfigItem( u"Office.Linguistic"_ustr )
196 const uno::Sequence< OUString > aPropertyNames = GetPropertyNames();
197 LoadOptions( aPropertyNames );
198 ClearModified();
200 // request notify events when properties change
201 EnableNotification( aPropertyNames );
204 void SvtLinguConfigItem::Notify( const uno::Sequence< OUString > &rPropertyNames )
207 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
208 LoadOptions( rPropertyNames );
210 NotifyListeners(ConfigurationHints::NONE);
213 void SvtLinguConfigItem::ImplCommit()
215 SaveOptions( GetPropertyNames() );
218 namespace {
220 struct NamesToHdl
222 OUString aFullPropName; // full qualified name as used in configuration
223 OUString aPropName; // property name only (atom) of above
224 sal_Int32 nHdl; // numeric handle representing the property
229 NamesToHdl constexpr aNamesToHdl[] =
231 {/* 0 */ u"General/DefaultLocale"_ustr, UPN_DEFAULT_LOCALE, UPH_DEFAULT_LOCALE},
232 {/* 1 */ u"General/DictionaryList/ActiveDictionaries"_ustr, UPN_ACTIVE_DICTIONARIES, UPH_ACTIVE_DICTIONARIES},
233 {/* 2 */ u"General/DictionaryList/IsUseDictionaryList"_ustr, UPN_IS_USE_DICTIONARY_LIST, UPH_IS_USE_DICTIONARY_LIST},
234 {/* 3 */ u"General/IsIgnoreControlCharacters"_ustr, UPN_IS_IGNORE_CONTROL_CHARACTERS, UPH_IS_IGNORE_CONTROL_CHARACTERS},
235 {/* 5 */ u"General/DefaultLocale_CJK"_ustr, UPN_DEFAULT_LOCALE_CJK, UPH_DEFAULT_LOCALE_CJK},
236 {/* 6 */ u"General/DefaultLocale_CTL"_ustr, UPN_DEFAULT_LOCALE_CTL, UPH_DEFAULT_LOCALE_CTL},
238 {/* 7 */ u"SpellChecking/IsSpellUpperCase"_ustr, UPN_IS_SPELL_UPPER_CASE, UPH_IS_SPELL_UPPER_CASE},
239 {/* 8 */ u"SpellChecking/IsSpellWithDigits"_ustr, UPN_IS_SPELL_WITH_DIGITS, UPH_IS_SPELL_WITH_DIGITS},
240 {/* 9 */ u"SpellChecking/IsSpellAuto"_ustr, UPN_IS_SPELL_AUTO, UPH_IS_SPELL_AUTO},
241 {/* 10 */ u"SpellChecking/IsSpellSpecial"_ustr, UPN_IS_SPELL_SPECIAL, UPH_IS_SPELL_SPECIAL},
242 {/* 11 */ u"SpellChecking/IsSpellClosedCompound"_ustr, UPN_IS_SPELL_CLOSED_COMPOUND, UPH_IS_SPELL_CLOSED_COMPOUND},
243 {/* 12 */ u"SpellChecking/IsSpellHyphenatedCompound"_ustr, UPN_IS_SPELL_HYPHENATED_COMPOUND, UPH_IS_SPELL_HYPHENATED_COMPOUND},
244 {/* 13 */ u"SpellChecking/IsReverseDirection"_ustr, UPN_IS_WRAP_REVERSE, UPH_IS_WRAP_REVERSE},
246 {/* 14 */ u"Hyphenation/MinLeading"_ustr, UPN_HYPH_MIN_LEADING, UPH_HYPH_MIN_LEADING},
247 {/* 15 */ u"Hyphenation/MinTrailing"_ustr, UPN_HYPH_MIN_TRAILING, UPH_HYPH_MIN_TRAILING},
248 {/* 16 */ u"Hyphenation/MinWordLength"_ustr, UPN_HYPH_MIN_WORD_LENGTH, UPH_HYPH_MIN_WORD_LENGTH},
249 {/* 17*/ u"Hyphenation/IsHyphSpecial"_ustr, UPN_IS_HYPH_SPECIAL, UPH_IS_HYPH_SPECIAL},
250 {/* 18 */ u"Hyphenation/IsHyphAuto"_ustr, UPN_IS_HYPH_AUTO, UPH_IS_HYPH_AUTO},
252 {/* 19 */ u"TextConversion/ActiveConversionDictionaries"_ustr, UPN_ACTIVE_CONVERSION_DICTIONARIES, UPH_ACTIVE_CONVERSION_DICTIONARIES},
253 {/* 20 */ u"TextConversion/IsIgnorePostPositionalWord"_ustr, UPN_IS_IGNORE_POST_POSITIONAL_WORD, UPH_IS_IGNORE_POST_POSITIONAL_WORD},
254 {/* 21 */ u"TextConversion/IsAutoCloseDialog"_ustr, UPN_IS_AUTO_CLOSE_DIALOG, UPH_IS_AUTO_CLOSE_DIALOG},
255 {/* 22 */ u"TextConversion/IsShowEntriesRecentlyUsedFirst"_ustr, UPN_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST, UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST},
256 {/* 23 */ u"TextConversion/IsAutoReplaceUniqueEntries"_ustr, UPN_IS_AUTO_REPLACE_UNIQUE_ENTRIES, UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES},
257 {/* 24 */ u"TextConversion/IsDirectionToSimplified"_ustr, UPN_IS_DIRECTION_TO_SIMPLIFIED, UPH_IS_DIRECTION_TO_SIMPLIFIED},
258 {/* 25 */ u"TextConversion/IsUseCharacterVariants"_ustr, UPN_IS_USE_CHARACTER_VARIANTS, UPH_IS_USE_CHARACTER_VARIANTS},
259 {/* 26 */ u"TextConversion/IsTranslateCommonTerms"_ustr, UPN_IS_TRANSLATE_COMMON_TERMS, UPH_IS_TRANSLATE_COMMON_TERMS},
260 {/* 27 */ u"TextConversion/IsReverseMapping"_ustr, UPN_IS_REVERSE_MAPPING, UPH_IS_REVERSE_MAPPING},
262 {/* 28 */ u"ServiceManager/DataFilesChangedCheckValue"_ustr, UPN_DATA_FILES_CHANGED_CHECK_VALUE, UPH_DATA_FILES_CHANGED_CHECK_VALUE},
264 {/* 29 */ u"GrammarChecking/IsAutoCheck"_ustr, UPN_IS_GRAMMAR_AUTO, UPH_IS_GRAMMAR_AUTO},
265 {/* 30 */ u"GrammarChecking/IsInteractiveCheck"_ustr, UPN_IS_GRAMMAR_INTERACTIVE, UPH_IS_GRAMMAR_INTERACTIVE},
267 /* similar to entry 0 (thus no own configuration entry) but with different property name and type */
268 { u""_ustr, UPN_DEFAULT_LANGUAGE, UPH_DEFAULT_LANGUAGE},
270 { u""_ustr, u""_ustr, -1}
273 uno::Sequence< OUString > SvtLinguConfigItem::GetPropertyNames()
275 uno::Sequence< OUString > aNames;
276 aNames.realloc(std::size(aNamesToHdl));
277 OUString *pNames = aNames.getArray();
278 sal_Int32 nIdx = 0;
279 for (auto const & nameToHdl: aNamesToHdl)
281 if (!nameToHdl.aFullPropName.isEmpty())
282 pNames[ nIdx++ ] = nameToHdl.aFullPropName;
284 aNames.realloc( nIdx );
286 return aNames;
289 bool SvtLinguConfigItem::GetHdlByName(
290 sal_Int32 &rnHdl,
291 std::u16string_view rPropertyName,
292 bool bFullPropName )
294 NamesToHdl const *pEntry = &aNamesToHdl[0];
296 if (bFullPropName)
298 while (pEntry && !pEntry->aFullPropName.isEmpty())
300 if (pEntry->aFullPropName == rPropertyName)
302 rnHdl = pEntry->nHdl;
303 break;
305 ++pEntry;
307 return pEntry && !pEntry->aFullPropName.isEmpty();
309 else
311 while (pEntry && !pEntry->aFullPropName.isEmpty())
313 if (rPropertyName == pEntry->aPropName )
315 rnHdl = pEntry->nHdl;
316 break;
318 ++pEntry;
320 return pEntry && !pEntry->aFullPropName.isEmpty();
324 uno::Any SvtLinguConfigItem::GetProperty( std::u16string_view rPropertyName ) const
326 sal_Int32 nHdl;
327 return GetHdlByName( nHdl, rPropertyName ) ? GetProperty( nHdl ) : uno::Any();
330 uno::Any SvtLinguConfigItem::GetProperty( sal_Int32 nPropertyHandle ) const
332 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
334 uno::Any aRes;
336 const sal_Int16 *pnVal = nullptr;
337 const LanguageType *plVal = nullptr;
338 const bool *pbVal = nullptr;
339 const sal_Int32 *pnInt32Val = nullptr;
341 const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
342 switch (nPropertyHandle)
344 case UPH_IS_USE_DICTIONARY_LIST : pbVal = &rOpt.bIsUseDictionaryList; break;
345 case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters; break;
346 case UPH_IS_HYPH_AUTO : pbVal = &rOpt.bIsHyphAuto; break;
347 case UPH_IS_HYPH_SPECIAL : pbVal = &rOpt.bIsHyphSpecial; break;
348 case UPH_IS_SPELL_AUTO : pbVal = &rOpt.bIsSpellAuto; break;
349 case UPH_IS_SPELL_SPECIAL : pbVal = &rOpt.bIsSpellSpecial; break;
350 case UPH_IS_WRAP_REVERSE : pbVal = &rOpt.bIsSpellReverse; break;
351 case UPH_DEFAULT_LANGUAGE : plVal = &rOpt.nDefaultLanguage; break;
352 case UPH_IS_SPELL_CLOSED_COMPOUND: pbVal = &rOpt.bIsSpellClosedCompound; break;
353 case UPH_IS_SPELL_HYPHENATED_COMPOUND: pbVal = &rOpt.bIsSpellHyphenatedCompound; break;
354 case UPH_IS_SPELL_WITH_DIGITS : pbVal = &rOpt.bIsSpellWithDigits; break;
355 case UPH_IS_SPELL_UPPER_CASE : pbVal = &rOpt.bIsSpellUpperCase; break;
356 case UPH_HYPH_MIN_LEADING : pnVal = &rOpt.nHyphMinLeading; break;
357 case UPH_HYPH_MIN_TRAILING : pnVal = &rOpt.nHyphMinTrailing; break;
358 case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &rOpt.nHyphMinWordLength; break;
359 case UPH_ACTIVE_DICTIONARIES :
361 aRes <<= rOpt.aActiveDics;
362 break;
364 case UPH_ACTIVE_CONVERSION_DICTIONARIES :
366 aRes <<= rOpt.aActiveConvDics;
367 break;
369 case UPH_DEFAULT_LOCALE :
371 aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage, false);
372 break;
374 case UPH_DEFAULT_LOCALE_CJK :
376 aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CJK, false);
377 break;
379 case UPH_DEFAULT_LOCALE_CTL :
381 aRes <<= LanguageTag::convertToLocale( rOpt.nDefaultLanguage_CTL, false);
382 break;
384 case UPH_IS_IGNORE_POST_POSITIONAL_WORD : pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
385 case UPH_IS_AUTO_CLOSE_DIALOG : pbVal = &rOpt.bIsAutoCloseDialog; break;
386 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
387 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
389 case UPH_IS_DIRECTION_TO_SIMPLIFIED: pbVal = &rOpt.bIsDirectionToSimplified; break;
390 case UPH_IS_USE_CHARACTER_VARIANTS : pbVal = &rOpt.bIsUseCharacterVariants; break;
391 case UPH_IS_TRANSLATE_COMMON_TERMS : pbVal = &rOpt.bIsTranslateCommonTerms; break;
392 case UPH_IS_REVERSE_MAPPING : pbVal = &rOpt.bIsReverseMapping; break;
394 case UPH_DATA_FILES_CHANGED_CHECK_VALUE : pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
395 case UPH_IS_GRAMMAR_AUTO: pbVal = &rOpt.bIsGrammarAuto; break;
396 case UPH_IS_GRAMMAR_INTERACTIVE: pbVal = &rOpt.bIsGrammarInteractive; break;
397 default :
398 SAL_WARN( "unotools.config", "unexpected property handle" );
401 if (pbVal)
402 aRes <<= *pbVal;
403 else if (pnVal)
404 aRes <<= *pnVal;
405 else if (plVal)
406 aRes <<= static_cast<sal_Int16>(static_cast<sal_uInt16>(*plVal));
407 else if (pnInt32Val)
408 aRes <<= *pnInt32Val;
410 return aRes;
413 bool SvtLinguConfigItem::SetProperty( std::u16string_view rPropertyName, const uno::Any &rValue )
415 bool bSucc = false;
416 sal_Int32 nHdl;
417 if (GetHdlByName( nHdl, rPropertyName ))
418 bSucc = SetProperty( nHdl, rValue );
419 return bSucc;
422 bool SvtLinguConfigItem::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
424 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
426 bool bSucc = false;
427 if (!rValue.hasValue())
428 return bSucc;
430 bool bMod = false;
432 sal_Int16 *pnVal = nullptr;
433 LanguageType *plVal = nullptr;
434 bool *pbVal = nullptr;
435 sal_Int32 *pnInt32Val = nullptr;
437 SvtLinguOptions &rOpt = aOpt;
438 switch (nPropertyHandle)
440 case UPH_IS_USE_DICTIONARY_LIST : pbVal = &rOpt.bIsUseDictionaryList; break;
441 case UPH_IS_IGNORE_CONTROL_CHARACTERS : pbVal = &rOpt.bIsIgnoreControlCharacters; break;
442 case UPH_IS_HYPH_AUTO : pbVal = &rOpt.bIsHyphAuto; break;
443 case UPH_IS_HYPH_SPECIAL : pbVal = &rOpt.bIsHyphSpecial; break;
444 case UPH_IS_SPELL_AUTO : pbVal = &rOpt.bIsSpellAuto; break;
445 case UPH_IS_SPELL_SPECIAL : pbVal = &rOpt.bIsSpellSpecial; break;
446 case UPH_IS_WRAP_REVERSE : pbVal = &rOpt.bIsSpellReverse; break;
447 case UPH_DEFAULT_LANGUAGE : plVal = &rOpt.nDefaultLanguage; break;
448 case UPH_IS_SPELL_CLOSED_COMPOUND: pbVal = &rOpt.bIsSpellClosedCompound; break;
449 case UPH_IS_SPELL_HYPHENATED_COMPOUND: pbVal = &rOpt.bIsSpellHyphenatedCompound; break;
450 case UPH_IS_SPELL_WITH_DIGITS : pbVal = &rOpt.bIsSpellWithDigits; break;
451 case UPH_IS_SPELL_UPPER_CASE : pbVal = &rOpt.bIsSpellUpperCase; break;
452 case UPH_HYPH_MIN_LEADING : pnVal = &rOpt.nHyphMinLeading; break;
453 case UPH_HYPH_MIN_TRAILING : pnVal = &rOpt.nHyphMinTrailing; break;
454 case UPH_HYPH_MIN_WORD_LENGTH : pnVal = &rOpt.nHyphMinWordLength; break;
455 case UPH_ACTIVE_DICTIONARIES :
457 rValue >>= rOpt.aActiveDics;
458 bMod = true;
459 break;
461 case UPH_ACTIVE_CONVERSION_DICTIONARIES :
463 rValue >>= rOpt.aActiveConvDics;
464 bMod = true;
465 break;
467 case UPH_DEFAULT_LOCALE :
469 bSucc = lcl_SetLocale( rOpt.nDefaultLanguage, rValue );
470 bMod = bSucc;
471 break;
473 case UPH_DEFAULT_LOCALE_CJK :
475 bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CJK, rValue );
476 bMod = bSucc;
477 break;
479 case UPH_DEFAULT_LOCALE_CTL :
481 bSucc = lcl_SetLocale( rOpt.nDefaultLanguage_CTL, rValue );
482 bMod = bSucc;
483 break;
485 case UPH_IS_IGNORE_POST_POSITIONAL_WORD : pbVal = &rOpt.bIsIgnorePostPositionalWord; break;
486 case UPH_IS_AUTO_CLOSE_DIALOG : pbVal = &rOpt.bIsAutoCloseDialog; break;
487 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : pbVal = &rOpt.bIsShowEntriesRecentlyUsedFirst; break;
488 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : pbVal = &rOpt.bIsAutoReplaceUniqueEntries; break;
490 case UPH_IS_DIRECTION_TO_SIMPLIFIED : pbVal = &rOpt.bIsDirectionToSimplified; break;
491 case UPH_IS_USE_CHARACTER_VARIANTS : pbVal = &rOpt.bIsUseCharacterVariants; break;
492 case UPH_IS_TRANSLATE_COMMON_TERMS : pbVal = &rOpt.bIsTranslateCommonTerms; break;
493 case UPH_IS_REVERSE_MAPPING : pbVal = &rOpt.bIsReverseMapping; break;
495 case UPH_DATA_FILES_CHANGED_CHECK_VALUE : pnInt32Val = &rOpt.nDataFilesChangedCheckValue; break;
496 case UPH_IS_GRAMMAR_AUTO: pbVal = &rOpt.bIsGrammarAuto; break;
497 case UPH_IS_GRAMMAR_INTERACTIVE: pbVal = &rOpt.bIsGrammarInteractive; break;
498 default :
499 SAL_WARN( "unotools.config", "unexpected property handle" );
502 if (pbVal)
504 bool bNew = bool();
505 if (rValue >>= bNew)
507 if (bNew != *pbVal)
509 *pbVal = bNew;
510 bMod = true;
512 bSucc = true;
515 else if (pnVal)
517 sal_Int16 nNew = sal_Int16();
518 if (rValue >>= nNew)
520 if (nNew != *pnVal)
522 *pnVal = nNew;
523 bMod = true;
525 bSucc = true;
528 else if (plVal)
530 sal_Int16 nNew = sal_Int16();
531 if (rValue >>= nNew)
533 if (nNew != static_cast<sal_uInt16>(*plVal))
535 *plVal = LanguageType(static_cast<sal_uInt16>(nNew));
536 bMod = true;
538 bSucc = true;
541 else if (pnInt32Val)
543 sal_Int32 nNew = sal_Int32();
544 if (rValue >>= nNew)
546 if (nNew != *pnInt32Val)
548 *pnInt32Val = nNew;
549 bMod = true;
551 bSucc = true;
555 if (bMod)
556 SetModified();
558 NotifyListeners(ConfigurationHints::NONE);
559 return bSucc;
562 void SvtLinguConfigItem::GetOptions(SvtLinguOptions &rOptions) const
564 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
565 rOptions = aOpt;
568 void SvtLinguConfigItem::LoadOptions( const uno::Sequence< OUString > &rProperyNames )
570 bool bRes = false;
572 const OUString *pProperyNames = rProperyNames.getConstArray();
573 sal_Int32 nProps = rProperyNames.getLength();
575 const uno::Sequence< uno::Any > aValues = GetProperties( rProperyNames );
576 const uno::Sequence< sal_Bool > aROStates = GetReadOnlyStates( rProperyNames );
578 if (nProps && aValues.getLength() == nProps && aROStates.getLength() == nProps)
580 SvtLinguOptions &rOpt = aOpt;
582 const uno::Any *pValue = aValues.getConstArray();
583 const sal_Bool *pROStates = aROStates.getConstArray();
584 for (sal_Int32 i = 0; i < nProps; ++i)
586 const uno::Any &rVal = pValue[i];
587 sal_Int32 nPropertyHandle(0);
588 GetHdlByName( nPropertyHandle, pProperyNames[i], true );
589 switch ( nPropertyHandle )
591 case UPH_DEFAULT_LOCALE :
592 { rOpt.bRODefaultLanguage = pROStates[i]; rOpt.nDefaultLanguage = lcl_CfgAnyToLanguage( rVal ); } break;
593 case UPH_ACTIVE_DICTIONARIES :
594 { rOpt.bROActiveDics = pROStates[i]; rVal >>= rOpt.aActiveDics; } break;
595 case UPH_IS_USE_DICTIONARY_LIST :
596 { rOpt.bROIsUseDictionaryList = pROStates[i]; rVal >>= rOpt.bIsUseDictionaryList; } break;
597 case UPH_IS_IGNORE_CONTROL_CHARACTERS :
598 { rOpt.bROIsIgnoreControlCharacters = pROStates[i]; rVal >>= rOpt.bIsIgnoreControlCharacters; } break;
599 case UPH_DEFAULT_LOCALE_CJK :
600 { rOpt.bRODefaultLanguage_CJK = pROStates[i]; rOpt.nDefaultLanguage_CJK = lcl_CfgAnyToLanguage( rVal ); } break;
601 case UPH_DEFAULT_LOCALE_CTL :
602 { rOpt.bRODefaultLanguage_CTL = pROStates[i]; rOpt.nDefaultLanguage_CTL = lcl_CfgAnyToLanguage( rVal ); } break;
604 case UPH_IS_SPELL_UPPER_CASE :
605 { rOpt.bROIsSpellUpperCase = pROStates[i]; rVal >>= rOpt.bIsSpellUpperCase; } break;
606 case UPH_IS_SPELL_WITH_DIGITS :
607 { rOpt.bROIsSpellWithDigits = pROStates[i]; rVal >>= rOpt.bIsSpellWithDigits; } break;
608 case UPH_IS_SPELL_CLOSED_COMPOUND :
609 { rOpt.bROIsSpellClosedCompound = pROStates[i]; rVal >>= rOpt.bIsSpellClosedCompound; } break;
610 case UPH_IS_SPELL_HYPHENATED_COMPOUND :
611 { rOpt.bROIsSpellHyphenatedCompound = pROStates[i]; rVal >>= rOpt.bIsSpellHyphenatedCompound; } break;
613 case UPH_IS_SPELL_AUTO :
614 { rOpt.bROIsSpellAuto = pROStates[i]; rVal >>= rOpt.bIsSpellAuto; } break;
615 case UPH_IS_SPELL_SPECIAL :
616 { rOpt.bROIsSpellSpecial = pROStates[i]; rVal >>= rOpt.bIsSpellSpecial; } break;
617 case UPH_IS_WRAP_REVERSE :
618 { rOpt.bROIsSpellReverse = pROStates[i]; rVal >>= rOpt.bIsSpellReverse; } break;
620 case UPH_HYPH_MIN_LEADING :
621 { rOpt.bROHyphMinLeading = pROStates[i]; rVal >>= rOpt.nHyphMinLeading; } break;
622 case UPH_HYPH_MIN_TRAILING :
623 { rOpt.bROHyphMinTrailing = pROStates[i]; rVal >>= rOpt.nHyphMinTrailing; } break;
624 case UPH_HYPH_MIN_WORD_LENGTH :
625 { rOpt.bROHyphMinWordLength = pROStates[i]; rVal >>= rOpt.nHyphMinWordLength; } break;
626 case UPH_IS_HYPH_SPECIAL :
627 { rOpt.bROIsHyphSpecial = pROStates[i]; rVal >>= rOpt.bIsHyphSpecial; } break;
628 case UPH_IS_HYPH_AUTO :
629 { rOpt.bROIsHyphAuto = pROStates[i]; rVal >>= rOpt.bIsHyphAuto; } break;
631 case UPH_ACTIVE_CONVERSION_DICTIONARIES : { rOpt.bROActiveConvDics = pROStates[i]; rVal >>= rOpt.aActiveConvDics; } break;
633 case UPH_IS_IGNORE_POST_POSITIONAL_WORD :
634 { rOpt.bROIsIgnorePostPositionalWord = pROStates[i]; rVal >>= rOpt.bIsIgnorePostPositionalWord; } break;
635 case UPH_IS_AUTO_CLOSE_DIALOG :
636 { rOpt.bROIsAutoCloseDialog = pROStates[i]; rVal >>= rOpt.bIsAutoCloseDialog; } break;
637 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST :
638 { rOpt.bROIsShowEntriesRecentlyUsedFirst = pROStates[i]; rVal >>= rOpt.bIsShowEntriesRecentlyUsedFirst; } break;
639 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES :
640 { rOpt.bROIsAutoReplaceUniqueEntries = pROStates[i]; rVal >>= rOpt.bIsAutoReplaceUniqueEntries; } break;
642 case UPH_IS_DIRECTION_TO_SIMPLIFIED :
644 rOpt.bROIsDirectionToSimplified = pROStates[i];
645 if( ! (rVal >>= rOpt.bIsDirectionToSimplified) )
647 //default is locale dependent:
648 if (MsLangId::isTraditionalChinese(rOpt.nDefaultLanguage_CJK))
650 rOpt.bIsDirectionToSimplified = false;
652 else
654 rOpt.bIsDirectionToSimplified = true;
657 } break;
658 case UPH_IS_USE_CHARACTER_VARIANTS :
659 { rOpt.bROIsUseCharacterVariants = pROStates[i]; rVal >>= rOpt.bIsUseCharacterVariants; } break;
660 case UPH_IS_TRANSLATE_COMMON_TERMS :
661 { rOpt.bROIsTranslateCommonTerms = pROStates[i]; rVal >>= rOpt.bIsTranslateCommonTerms; } break;
662 case UPH_IS_REVERSE_MAPPING :
663 { rOpt.bROIsReverseMapping = pROStates[i]; rVal >>= rOpt.bIsReverseMapping; } break;
665 case UPH_DATA_FILES_CHANGED_CHECK_VALUE :
666 { rOpt.bRODataFilesChangedCheckValue = pROStates[i]; rVal >>= rOpt.nDataFilesChangedCheckValue; } break;
668 case UPH_IS_GRAMMAR_AUTO:
669 { rOpt.bROIsGrammarAuto = pROStates[i]; rVal >>= rOpt.bIsGrammarAuto; }
670 break;
671 case UPH_IS_GRAMMAR_INTERACTIVE:
672 { rOpt.bROIsGrammarInteractive = pROStates[i]; rVal >>= rOpt.bIsGrammarInteractive; }
673 break;
675 default:
676 SAL_WARN( "unotools.config", "unexpected case" );
680 bRes = true;
682 DBG_ASSERT( bRes, "LoadOptions failed" );
685 bool SvtLinguConfigItem::SaveOptions( const uno::Sequence< OUString > &rProperyNames )
687 if (!IsModified())
688 return true;
690 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
692 bool bRet = false;
694 sal_Int32 nProps = rProperyNames.getLength();
695 uno::Sequence< uno::Any > aValues( nProps );
696 uno::Any *pValue = aValues.getArray();
698 if (nProps && aValues.getLength() == nProps)
700 const SvtLinguOptions &rOpt = aOpt;
702 OUString aTmp( lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage ) );
703 *pValue++ <<= aTmp; // 0
704 *pValue++ <<= rOpt.aActiveDics; // 1
705 *pValue++ <<= rOpt.bIsUseDictionaryList; // 2
706 *pValue++ <<= rOpt.bIsIgnoreControlCharacters; // 3
707 aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CJK );
708 *pValue++ <<= aTmp; // 5
709 aTmp = lcl_LanguageToCfgLocaleStr( rOpt.nDefaultLanguage_CTL );
710 *pValue++ <<= aTmp; // 6
712 *pValue++ <<= rOpt.bIsSpellUpperCase; // 7
713 *pValue++ <<= rOpt.bIsSpellWithDigits; // 8
714 *pValue++ <<= rOpt.bIsSpellAuto; // 9
715 *pValue++ <<= rOpt.bIsSpellSpecial; // 10
716 *pValue++ <<= rOpt.bIsSpellClosedCompound; // 11
717 *pValue++ <<= rOpt.bIsSpellHyphenatedCompound; // 12
718 *pValue++ <<= rOpt.bIsSpellReverse; // 13
720 *pValue++ <<= rOpt.nHyphMinLeading; // 14
721 *pValue++ <<= rOpt.nHyphMinTrailing; // 15
722 *pValue++ <<= rOpt.nHyphMinWordLength; // 16
723 *pValue++ <<= rOpt.bIsHyphSpecial; // 17
724 *pValue++ <<= rOpt.bIsHyphAuto; // 18
726 *pValue++ <<= rOpt.aActiveConvDics; // 19
728 *pValue++ <<= rOpt.bIsIgnorePostPositionalWord; // 20
729 *pValue++ <<= rOpt.bIsAutoCloseDialog; // 21
730 *pValue++ <<= rOpt.bIsShowEntriesRecentlyUsedFirst; // 22
731 *pValue++ <<= rOpt.bIsAutoReplaceUniqueEntries; // 23
733 *pValue++ <<= rOpt.bIsDirectionToSimplified; // 24
734 *pValue++ <<= rOpt.bIsUseCharacterVariants; // 25
735 *pValue++ <<= rOpt.bIsTranslateCommonTerms; // 26
736 *pValue++ <<= rOpt.bIsReverseMapping; // 27
738 *pValue++ <<= rOpt.nDataFilesChangedCheckValue; // 28
739 *pValue++ <<= rOpt.bIsGrammarAuto; // 29
740 *pValue++ <<= rOpt.bIsGrammarInteractive; // 30
742 bRet |= PutProperties( rProperyNames, aValues );
745 if (bRet)
746 ClearModified();
748 return bRet;
751 bool SvtLinguConfigItem::IsReadOnly( std::u16string_view rPropertyName ) const
753 bool bReadOnly = false;
754 sal_Int32 nHdl;
755 if (GetHdlByName( nHdl, rPropertyName ))
756 bReadOnly = IsReadOnly( nHdl );
757 return bReadOnly;
760 bool SvtLinguConfigItem::IsReadOnly( sal_Int32 nPropertyHandle ) const
762 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
764 bool bReadOnly = false;
766 const SvtLinguOptions &rOpt = const_cast< SvtLinguConfigItem * >(this)->aOpt;
767 switch(nPropertyHandle)
769 case UPH_IS_USE_DICTIONARY_LIST : bReadOnly = rOpt.bROIsUseDictionaryList; break;
770 case UPH_IS_IGNORE_CONTROL_CHARACTERS : bReadOnly = rOpt.bROIsIgnoreControlCharacters; break;
771 case UPH_IS_HYPH_AUTO : bReadOnly = rOpt.bROIsHyphAuto; break;
772 case UPH_IS_HYPH_SPECIAL : bReadOnly = rOpt.bROIsHyphSpecial; break;
773 case UPH_IS_SPELL_AUTO : bReadOnly = rOpt.bROIsSpellAuto; break;
774 case UPH_IS_SPELL_SPECIAL : bReadOnly = rOpt.bROIsSpellSpecial; break;
775 case UPH_IS_WRAP_REVERSE : bReadOnly = rOpt.bROIsSpellReverse; break;
776 case UPH_DEFAULT_LANGUAGE : bReadOnly = rOpt.bRODefaultLanguage; break;
777 case UPH_IS_SPELL_CLOSED_COMPOUND : bReadOnly = rOpt.bROIsSpellClosedCompound; break;
778 case UPH_IS_SPELL_HYPHENATED_COMPOUND : bReadOnly = rOpt.bROIsSpellHyphenatedCompound; break;
779 case UPH_IS_SPELL_WITH_DIGITS : bReadOnly = rOpt.bROIsSpellWithDigits; break;
780 case UPH_IS_SPELL_UPPER_CASE : bReadOnly = rOpt.bROIsSpellUpperCase; break;
781 case UPH_HYPH_MIN_LEADING : bReadOnly = rOpt.bROHyphMinLeading; break;
782 case UPH_HYPH_MIN_TRAILING : bReadOnly = rOpt.bROHyphMinTrailing; break;
783 case UPH_HYPH_MIN_WORD_LENGTH : bReadOnly = rOpt.bROHyphMinWordLength; break;
784 case UPH_ACTIVE_DICTIONARIES : bReadOnly = rOpt.bROActiveDics; break;
785 case UPH_ACTIVE_CONVERSION_DICTIONARIES : bReadOnly = rOpt.bROActiveConvDics; break;
786 case UPH_DEFAULT_LOCALE : bReadOnly = rOpt.bRODefaultLanguage; break;
787 case UPH_DEFAULT_LOCALE_CJK : bReadOnly = rOpt.bRODefaultLanguage_CJK; break;
788 case UPH_DEFAULT_LOCALE_CTL : bReadOnly = rOpt.bRODefaultLanguage_CTL; break;
789 case UPH_IS_IGNORE_POST_POSITIONAL_WORD : bReadOnly = rOpt.bROIsIgnorePostPositionalWord; break;
790 case UPH_IS_AUTO_CLOSE_DIALOG : bReadOnly = rOpt.bROIsAutoCloseDialog; break;
791 case UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST : bReadOnly = rOpt.bROIsShowEntriesRecentlyUsedFirst; break;
792 case UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES : bReadOnly = rOpt.bROIsAutoReplaceUniqueEntries; break;
793 case UPH_IS_DIRECTION_TO_SIMPLIFIED : bReadOnly = rOpt.bROIsDirectionToSimplified; break;
794 case UPH_IS_USE_CHARACTER_VARIANTS : bReadOnly = rOpt.bROIsUseCharacterVariants; break;
795 case UPH_IS_TRANSLATE_COMMON_TERMS : bReadOnly = rOpt.bROIsTranslateCommonTerms; break;
796 case UPH_IS_REVERSE_MAPPING : bReadOnly = rOpt.bROIsReverseMapping; break;
797 case UPH_DATA_FILES_CHANGED_CHECK_VALUE : bReadOnly = rOpt.bRODataFilesChangedCheckValue; break;
798 case UPH_IS_GRAMMAR_AUTO: bReadOnly = rOpt.bROIsGrammarAuto; break;
799 case UPH_IS_GRAMMAR_INTERACTIVE: bReadOnly = rOpt.bROIsGrammarInteractive; break;
800 default :
801 SAL_WARN( "unotools.config", "unexpected property handle" );
803 return bReadOnly;
806 static SvtLinguConfigItem *pCfgItem = nullptr;
807 static sal_Int32 nCfgItemRefCount = 0;
809 constexpr OUString aG_Dictionaries = u"Dictionaries"_ustr;
811 SvtLinguConfig::SvtLinguConfig()
813 // Global access, must be guarded (multithreading)
814 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
815 ++nCfgItemRefCount;
818 SvtLinguConfig::~SvtLinguConfig()
820 if (pCfgItem && pCfgItem->IsModified())
821 pCfgItem->Commit();
823 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
825 if (--nCfgItemRefCount <= 0)
827 delete pCfgItem;
828 pCfgItem = nullptr;
832 SvtLinguConfigItem & SvtLinguConfig::GetConfigItem()
834 // Global access, must be guarded (multithreading)
835 std::unique_lock aGuard(theSvtLinguConfigItemMutex());
836 if (!pCfgItem)
838 pCfgItem = new SvtLinguConfigItem;
839 aGuard.unlock();
840 ItemHolder1::holdConfigItem(EItem::LinguConfig);
842 return *pCfgItem;
845 uno::Sequence< OUString > SvtLinguConfig::GetNodeNames( const OUString &rNode ) const
847 return GetConfigItem().GetNodeNames( rNode );
850 uno::Sequence< uno::Any > SvtLinguConfig::GetProperties( const uno::Sequence< OUString > &rNames ) const
852 return GetConfigItem().GetProperties(rNames);
855 bool SvtLinguConfig::ReplaceSetProperties(
856 const OUString &rNode, const uno::Sequence< beans::PropertyValue >& rValues )
858 return GetConfigItem().ReplaceSetProperties( rNode, rValues );
861 uno::Any SvtLinguConfig::GetProperty( std::u16string_view rPropertyName ) const
863 return GetConfigItem().GetProperty( rPropertyName );
866 uno::Any SvtLinguConfig::GetProperty( sal_Int32 nPropertyHandle ) const
868 return GetConfigItem().GetProperty( nPropertyHandle );
871 bool SvtLinguConfig::SetProperty( std::u16string_view rPropertyName, const uno::Any &rValue )
873 return GetConfigItem().SetProperty( rPropertyName, rValue );
876 bool SvtLinguConfig::SetProperty( sal_Int32 nPropertyHandle, const uno::Any &rValue )
878 return GetConfigItem().SetProperty( nPropertyHandle, rValue );
881 void SvtLinguConfig::GetOptions( SvtLinguOptions &rOptions ) const
883 GetConfigItem().GetOptions(rOptions);
886 bool SvtLinguConfig::IsReadOnly( std::u16string_view rPropertyName ) const
888 return GetConfigItem().IsReadOnly( rPropertyName );
891 bool SvtLinguConfig::GetElementNamesFor(
892 const OUString &rNodeName,
893 uno::Sequence< OUString > &rElementNames ) const
895 bool bSuccess = false;
898 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY );
899 if (!xNA)
900 return false;
901 xNA.set( xNA->getByName(u"ServiceManager"_ustr), uno::UNO_QUERY );
902 if (!xNA)
903 return false;
904 xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY );
905 if (!xNA)
906 return false;
907 rElementNames = xNA->getElementNames();
908 bSuccess = true;
910 catch (uno::Exception &)
913 return bSuccess;
916 bool SvtLinguConfig::GetSupportedDictionaryFormatsFor(
917 const OUString &rSetName,
918 const OUString &rSetEntry,
919 uno::Sequence< OUString > &rFormatList ) const
921 if (rSetName.isEmpty() || rSetEntry.isEmpty())
922 return false;
923 bool bSuccess = false;
926 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY );
927 if (!xNA)
928 return false;
929 xNA.set( xNA->getByName(u"ServiceManager"_ustr), uno::UNO_QUERY );
930 if (!xNA)
931 return false;
932 xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY );
933 if (!xNA)
934 return false;
935 xNA.set( xNA->getByName( rSetEntry ), uno::UNO_QUERY );
936 if (!xNA)
937 return false;
938 if (xNA->getByName( u"SupportedDictionaryFormats"_ustr ) >>= rFormatList)
939 bSuccess = true;
940 DBG_ASSERT( rFormatList.hasElements(), "supported dictionary format list is empty" );
942 catch (uno::Exception &)
945 return bSuccess;
948 bool SvtLinguConfig::GetLocaleListFor( const OUString &rSetName, const OUString &rSetEntry, css::uno::Sequence< OUString > &rLocaleList ) const
950 if (rSetName.isEmpty() || rSetEntry.isEmpty())
951 return false;
952 bool bSuccess = false;
955 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY );
956 if (!xNA)
957 return false;
958 xNA.set( xNA->getByName(u"ServiceManager"_ustr), uno::UNO_QUERY );
959 if (!xNA)
960 return false;
961 xNA.set( xNA->getByName( rSetName ), uno::UNO_QUERY );
962 if (!xNA)
963 return false;
964 xNA.set( xNA->getByName( rSetEntry ), uno::UNO_QUERY );
965 if (!xNA)
966 return false;
967 if (xNA->getByName( u"Locales"_ustr ) >>= rLocaleList)
968 bSuccess = true;
969 DBG_ASSERT( rLocaleList.hasElements(), "Locale list is empty" );
971 catch (uno::Exception &)
974 return bSuccess;
977 static bool lcl_GetFileUrlFromOrigin(
978 OUString /*out*/ &rFileUrl,
979 const OUString &rOrigin )
981 OUString aURL(
982 comphelper::getExpandedUri(
983 comphelper::getProcessComponentContext(), rOrigin));
984 if (aURL.startsWith( FILE_PROTOCOL ))
986 rFileUrl = aURL;
987 return true;
989 else
991 SAL_WARN(
992 "unotools.config", "not a file URL, <" << aURL << ">" );
993 return false;
997 bool SvtLinguConfig::GetDictionaryEntry(
998 const OUString &rNodeName,
999 SvtLinguConfigDictionaryEntry &rDicEntry ) const
1001 if (rNodeName.isEmpty())
1002 return false;
1003 bool bSuccess = false;
1006 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1007 xNA.set( xNA->getByName(u"ServiceManager"_ustr), uno::UNO_QUERY_THROW );
1008 xNA.set( xNA->getByName( aG_Dictionaries ), uno::UNO_QUERY_THROW );
1009 xNA.set( xNA->getByName( rNodeName ), uno::UNO_QUERY_THROW );
1011 // read group data...
1012 uno::Sequence< OUString > aLocations;
1013 OUString aFormatName;
1014 uno::Sequence< OUString > aLocaleNames;
1015 bSuccess = (xNA->getByName( u"Locations"_ustr ) >>= aLocations) &&
1016 (xNA->getByName( u"Format"_ustr ) >>= aFormatName) &&
1017 (xNA->getByName( u"Locales"_ustr ) >>= aLocaleNames);
1018 DBG_ASSERT( aLocations.hasElements(), "Dictionary locations not set" );
1019 DBG_ASSERT( !aFormatName.isEmpty(), "Dictionary format name not set" );
1020 DBG_ASSERT( aLocaleNames.hasElements(), "No locales set for the dictionary" );
1022 // if successful continue
1023 if (bSuccess)
1025 // get file URL's for the locations
1026 for (OUString& rLocation : asNonConstRange(aLocations))
1028 if (!lcl_GetFileUrlFromOrigin( rLocation, rLocation ))
1029 bSuccess = false;
1032 // if everything was fine return the result
1033 if (bSuccess)
1035 rDicEntry.aLocations = std::move(aLocations);
1036 rDicEntry.aFormatName = aFormatName;
1037 rDicEntry.aLocaleNames = std::move(aLocaleNames);
1041 catch (uno::Exception &)
1044 return bSuccess;
1047 uno::Sequence< OUString > SvtLinguConfig::GetDisabledDictionaries() const
1049 uno::Sequence< OUString > aResult;
1052 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY );
1053 if (!xNA)
1054 return aResult;
1055 xNA.set( xNA->getByName(u"ServiceManager"_ustr), uno::UNO_QUERY );
1056 if (!xNA)
1057 return aResult;
1058 xNA->getByName( u"DisabledDictionaries"_ustr ) >>= aResult;
1060 catch (uno::Exception &)
1063 return aResult;
1066 std::vector< SvtLinguConfigDictionaryEntry > SvtLinguConfig::GetActiveDictionariesByFormat(
1067 std::u16string_view rFormatName ) const
1069 std::vector< SvtLinguConfigDictionaryEntry > aRes;
1070 if (rFormatName.empty())
1071 return aRes;
1075 uno::Sequence< OUString > aElementNames;
1076 GetElementNamesFor( aG_Dictionaries, aElementNames );
1078 const uno::Sequence< OUString > aDisabledDics( GetDisabledDictionaries() );
1080 SvtLinguConfigDictionaryEntry aDicEntry;
1081 for (const OUString& rElementName : aElementNames)
1083 // does dictionary match the format we are looking for?
1084 if (GetDictionaryEntry( rElementName, aDicEntry ) &&
1085 aDicEntry.aFormatName == rFormatName)
1087 // check if it is active or not
1088 bool bDicIsActive = std::none_of(aDisabledDics.begin(), aDisabledDics.end(),
1089 [&rElementName](const OUString& rDic) { return rDic == rElementName; });
1091 if (bDicIsActive)
1093 DBG_ASSERT( !aDicEntry.aFormatName.isEmpty(),
1094 "FormatName not set" );
1095 DBG_ASSERT( aDicEntry.aLocations.hasElements(),
1096 "Locations not set" );
1097 DBG_ASSERT( aDicEntry.aLocaleNames.hasElements(),
1098 "Locales not set" );
1099 aRes.push_back( aDicEntry );
1104 catch (uno::Exception &)
1108 return aRes;
1111 uno::Reference< util::XChangesBatch > const & SvtLinguConfig::GetMainUpdateAccess() const
1113 if (m_xMainUpdateAccess)
1114 return m_xMainUpdateAccess;
1117 // get configuration provider
1118 const uno::Reference< uno::XComponentContext >& xContext = comphelper::getProcessComponentContext();
1119 uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider =
1120 configuration::theDefaultProvider::get( xContext );
1122 // get configuration update access
1123 beans::PropertyValue aValue;
1124 aValue.Name = "nodepath";
1125 aValue.Value <<= u"org.openoffice.Office.Linguistic"_ustr;
1126 uno::Sequence< uno::Any > aProps{ uno::Any(aValue) };
1127 m_xMainUpdateAccess.set(
1128 xConfigurationProvider->createInstanceWithArguments(
1129 u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr, aProps),
1130 uno::UNO_QUERY );
1132 catch (uno::Exception &)
1136 return m_xMainUpdateAccess;
1139 OUString SvtLinguConfig::GetVendorImageUrl_Impl(
1140 const OUString &rServiceImplName,
1141 const OUString &rImageName ) const
1143 OUString aRes;
1146 uno::Reference< container::XNameAccess > xImagesNA( GetMainUpdateAccess(), uno::UNO_QUERY_THROW );
1147 xImagesNA.set( xImagesNA->getByName(u"Images"_ustr), uno::UNO_QUERY_THROW );
1149 uno::Reference< container::XNameAccess > xNA( xImagesNA->getByName(u"ServiceNameEntries"_ustr), uno::UNO_QUERY_THROW );
1150 xNA.set( xNA->getByName( rServiceImplName ), uno::UNO_QUERY_THROW );
1151 uno::Any aAny(xNA->getByName(u"VendorImagesNode"_ustr));
1152 OUString aVendorImagesNode;
1153 if (aAny >>= aVendorImagesNode)
1155 xNA = std::move(xImagesNA);
1156 xNA.set( xNA->getByName(u"VendorImages"_ustr), uno::UNO_QUERY_THROW );
1157 xNA.set( xNA->getByName( aVendorImagesNode ), uno::UNO_QUERY_THROW );
1158 aAny = xNA->getByName( rImageName );
1159 OUString aTmp;
1160 if (aAny >>= aTmp)
1162 if (lcl_GetFileUrlFromOrigin( aTmp, aTmp ))
1163 aRes = aTmp;
1167 catch (uno::Exception &)
1169 DBG_UNHANDLED_EXCEPTION("unotools");
1171 return aRes;
1174 OUString SvtLinguConfig::GetSpellAndGrammarContextSuggestionImage(
1175 const OUString &rServiceImplName
1176 ) const
1178 OUString aRes;
1179 if (!rServiceImplName.isEmpty())
1181 aRes = GetVendorImageUrl_Impl( rServiceImplName, u"SpellAndGrammarContextMenuSuggestionImage"_ustr );
1183 return aRes;
1186 OUString SvtLinguConfig::GetSpellAndGrammarContextDictionaryImage(
1187 const OUString &rServiceImplName
1188 ) const
1190 OUString aRes;
1191 if (!rServiceImplName.isEmpty())
1193 aRes = GetVendorImageUrl_Impl( rServiceImplName, u"SpellAndGrammarContextMenuDictionaryImage"_ustr );
1195 return aRes;
1198 OUString SvtLinguConfig::GetSynonymsContextImage(
1199 const OUString &rServiceImplName
1200 ) const
1202 OUString aRes;
1203 if (!rServiceImplName.isEmpty())
1204 aRes = GetVendorImageUrl_Impl(rServiceImplName, u"SynonymsContextMenuImage"_ustr);
1205 return aRes;
1208 bool SvtLinguConfig::HasGrammarChecker() const
1210 bool bRes = false;
1214 uno::Reference< container::XNameAccess > xNA( GetMainUpdateAccess(), uno::UNO_QUERY );
1215 if (!xNA)
1216 return false;
1217 xNA.set( xNA->getByName(u"ServiceManager"_ustr), uno::UNO_QUERY );
1218 if (!xNA)
1219 return false;
1220 xNA.set( xNA->getByName(u"GrammarCheckerList"_ustr), uno::UNO_QUERY );
1221 if (!xNA)
1222 return false;
1224 uno::Sequence< OUString > aElementNames( xNA->getElementNames() );
1225 bRes = aElementNames.hasElements();
1227 catch (const uno::Exception&)
1231 return bRes;
1234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */