Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / unotools / source / config / syslocaleoptions.cxx
blob7cbb817ee1bfeec655403fb024796c049ce1cb05
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 <com/sun/star/uno/Sequence.hxx>
21 #include <rtl/instance.hxx>
22 #include <sal/log.hxx>
23 #include <i18nlangtag/mslangid.hxx>
24 #include <i18nlangtag/languagetag.hxx>
25 #include <tools/debug.hxx>
26 #include <tools/link.hxx>
27 #include <unotools/syslocaleoptions.hxx>
28 #include <unotools/configmgr.hxx>
29 #include <unotools/configitem.hxx>
30 #include <com/sun/star/uno/Any.hxx>
32 #include "itemholder1.hxx"
34 #define CFG_READONLY_DEFAULT false
36 using namespace osl;
37 using namespace utl;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::lang;
41 namespace
43 std::weak_ptr<SvtSysLocaleOptions_Impl> g_pSysLocaleOptions;
44 struct CurrencyChangeLink
45 : public rtl::Static<Link<LinkParamNone*,void>, CurrencyChangeLink> {};
47 Mutex& GetMutex()
49 // #i77768# Due to a static reference in the toolkit lib
50 // we need a mutex that lives longer than the svl library.
51 // Otherwise the dtor would use a destructed mutex!!
52 static Mutex* persistentMutex(new Mutex);
54 return *persistentMutex;
59 class SvtSysLocaleOptions_Impl : public utl::ConfigItem
61 LanguageTag m_aRealLocale;
62 LanguageTag m_aRealUILocale;
63 OUString m_aLocaleString; // en-US or de-DE or empty for SYSTEM
64 OUString m_aUILocaleString; // en-US or de-DE or empty for SYSTEM
65 OUString m_aCurrencyString; // USD-en-US or EUR-de-DE
66 OUString m_aDatePatternsString; // "Y-M-D;M-D"
67 bool m_bDecimalSeparator; //use decimal separator same as locale
68 bool m_bIgnoreLanguageChange; //OS language change doesn't affect LO document language
70 bool m_bROLocale;
71 bool m_bROUILocale;
72 bool m_bROCurrency;
73 bool m_bRODatePatterns;
74 bool m_bRODecimalSeparator;
75 bool m_bROIgnoreLanguageChange;
77 static Sequence<OUString> GetPropertyNames();
78 void MakeRealLocale();
79 void MakeRealUILocale();
81 virtual void ImplCommit() override;
83 public:
84 SvtSysLocaleOptions_Impl();
85 virtual ~SvtSysLocaleOptions_Impl() override;
87 virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
89 const OUString& GetLocaleString() const
90 { return m_aLocaleString; }
91 void SetLocaleString( const OUString& rStr );
93 void SetUILocaleString( const OUString& rStr );
95 const OUString& GetCurrencyString() const
96 { return m_aCurrencyString; }
97 void SetCurrencyString( const OUString& rStr );
99 const OUString& GetDatePatternsString() const
100 { return m_aDatePatternsString; }
101 void SetDatePatternsString( const OUString& rStr );
103 bool IsDecimalSeparatorAsLocale() const { return m_bDecimalSeparator;}
104 void SetDecimalSeparatorAsLocale( bool bSet);
106 bool IsIgnoreLanguageChange() const { return m_bIgnoreLanguageChange;}
107 void SetIgnoreLanguageChange( bool bSet);
109 bool IsReadOnly( SvtSysLocaleOptions::EOption eOption ) const;
110 const LanguageTag& GetRealLocale() const { return m_aRealLocale; }
111 const LanguageTag& GetRealUILocale() const { return m_aRealUILocale; }
114 #define ROOTNODE_SYSLOCALE "Setup/L10N"
116 #define PROPERTYNAME_LOCALE "ooSetupSystemLocale"
117 #define PROPERTYNAME_UILOCALE "ooLocale"
118 #define PROPERTYNAME_CURRENCY "ooSetupCurrency"
119 #define PROPERTYNAME_DECIMALSEPARATOR "DecimalSeparatorAsLocale"
120 #define PROPERTYNAME_DATEPATTERNS "DateAcceptancePatterns"
121 #define PROPERTYNAME_IGNORELANGCHANGE "IgnoreLanguageChange"
123 #define PROPERTYHANDLE_LOCALE 0
124 #define PROPERTYHANDLE_UILOCALE 1
125 #define PROPERTYHANDLE_CURRENCY 2
126 #define PROPERTYHANDLE_DECIMALSEPARATOR 3
127 #define PROPERTYHANDLE_DATEPATTERNS 4
128 #define PROPERTYHANDLE_IGNORELANGCHANGE 5
130 Sequence< OUString > SvtSysLocaleOptions_Impl::GetPropertyNames()
132 return Sequence< OUString >
134 PROPERTYNAME_LOCALE,
135 PROPERTYNAME_UILOCALE,
136 PROPERTYNAME_CURRENCY,
137 PROPERTYNAME_DECIMALSEPARATOR,
138 PROPERTYNAME_DATEPATTERNS,
139 PROPERTYNAME_IGNORELANGCHANGE
143 SvtSysLocaleOptions_Impl::SvtSysLocaleOptions_Impl()
144 : ConfigItem( ROOTNODE_SYSLOCALE )
145 , m_aRealLocale( LANGUAGE_SYSTEM)
146 , m_aRealUILocale( LANGUAGE_SYSTEM)
147 , m_bDecimalSeparator( true )
148 , m_bIgnoreLanguageChange( false)
149 , m_bROLocale(CFG_READONLY_DEFAULT)
150 , m_bROUILocale(CFG_READONLY_DEFAULT)
151 , m_bROCurrency(CFG_READONLY_DEFAULT)
152 , m_bRODatePatterns(CFG_READONLY_DEFAULT)
153 , m_bRODecimalSeparator(false)
154 , m_bROIgnoreLanguageChange(false)
157 const Sequence< OUString > aNames = GetPropertyNames();
158 Sequence< Any > aValues = GetProperties( aNames );
159 Sequence< sal_Bool > aROStates = GetReadOnlyStates( aNames );
160 const Any* pValues = aValues.getConstArray();
161 const sal_Bool* pROStates = aROStates.getConstArray();
162 DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
163 DBG_ASSERT( aROStates.getLength() == aNames.getLength(), "GetReadOnlyStates failed" );
164 if ( aValues.getLength() == aNames.getLength() && aROStates.getLength() == aNames.getLength() )
166 for ( sal_Int32 nProp = 0; nProp < aNames.getLength(); nProp++ )
168 if ( pValues[nProp].hasValue() )
170 switch ( nProp )
172 case PROPERTYHANDLE_LOCALE :
174 OUString aStr;
175 if ( pValues[nProp] >>= aStr )
176 m_aLocaleString = aStr;
177 else
179 SAL_WARN( "unotools.config", "Wrong property type!" );
181 m_bROLocale = pROStates[nProp];
183 break;
184 case PROPERTYHANDLE_UILOCALE :
186 OUString aStr;
187 if ( pValues[nProp] >>= aStr )
188 m_aUILocaleString = aStr;
189 else
191 SAL_WARN( "unotools.config", "Wrong property type!" );
193 m_bROUILocale = pROStates[nProp];
195 break;
196 case PROPERTYHANDLE_CURRENCY :
198 OUString aStr;
199 if ( pValues[nProp] >>= aStr )
200 m_aCurrencyString = aStr;
201 else
203 SAL_WARN( "unotools.config", "Wrong property type!" );
205 m_bROCurrency = pROStates[nProp];
207 break;
208 case PROPERTYHANDLE_DECIMALSEPARATOR:
210 bool bValue = false;
211 if ( pValues[nProp] >>= bValue )
212 m_bDecimalSeparator = bValue;
213 else
215 SAL_WARN( "unotools.config", "Wrong property type!" );
217 m_bRODecimalSeparator = pROStates[nProp];
219 break;
220 case PROPERTYHANDLE_DATEPATTERNS :
222 OUString aStr;
223 if ( pValues[nProp] >>= aStr )
224 m_aDatePatternsString = aStr;
225 else
227 SAL_WARN( "unotools.config", "Wrong property type!" );
229 m_bRODatePatterns = pROStates[nProp];
231 break;
232 case PROPERTYHANDLE_IGNORELANGCHANGE :
234 bool bValue = false;
235 if ( pValues[nProp] >>= bValue )
236 m_bIgnoreLanguageChange = bValue;
237 else
239 SAL_WARN( "unotools.config", "Wrong property type!" );
241 m_bROIgnoreLanguageChange = pROStates[nProp];
243 break;
244 default:
245 SAL_WARN( "unotools.config", "Wrong property type!" );
250 EnableNotification( aNames );
252 MakeRealLocale();
253 MakeRealUILocale();
256 SvtSysLocaleOptions_Impl::~SvtSysLocaleOptions_Impl()
258 assert(!IsModified()); // should have been committed
261 void SvtSysLocaleOptions_Impl::MakeRealLocale()
263 if (m_aLocaleString.isEmpty())
265 LanguageType nLang = MsLangId::getSystemLanguage();
266 m_aRealLocale.reset( nLang).makeFallback();
268 else
270 m_aRealLocale.reset( m_aLocaleString).makeFallback();
274 void SvtSysLocaleOptions_Impl::MakeRealUILocale()
276 if (m_aUILocaleString.isEmpty())
278 LanguageType nLang = MsLangId::getSystemUILanguage();
279 m_aRealUILocale.reset( nLang).makeFallback();
281 else
283 m_aRealUILocale.reset( m_aUILocaleString).makeFallback();
287 bool SvtSysLocaleOptions_Impl::IsReadOnly( SvtSysLocaleOptions::EOption eOption ) const
289 bool bReadOnly = CFG_READONLY_DEFAULT;
290 switch(eOption)
292 case SvtSysLocaleOptions::EOption::Locale :
294 bReadOnly = m_bROLocale;
295 break;
297 case SvtSysLocaleOptions::EOption::Currency :
299 bReadOnly = m_bROCurrency;
300 break;
302 case SvtSysLocaleOptions::EOption::DatePatterns :
304 bReadOnly = m_bRODatePatterns;
305 break;
308 return bReadOnly;
311 void SvtSysLocaleOptions_Impl::ImplCommit()
313 const Sequence< OUString > aOrgNames = GetPropertyNames();
314 sal_Int32 nOrgCount = aOrgNames.getLength();
316 Sequence< OUString > aNames( nOrgCount );
317 Sequence< Any > aValues( nOrgCount );
319 OUString* pNames = aNames.getArray();
320 Any* pValues = aValues.getArray();
321 sal_Int32 nRealCount = 0;
323 for ( sal_Int32 nProp = 0; nProp < nOrgCount; nProp++ )
325 switch ( nProp )
327 case PROPERTYHANDLE_LOCALE :
329 if (!m_bROLocale)
331 pNames[nRealCount] = aOrgNames[nProp];
332 pValues[nRealCount] <<= m_aLocaleString;
333 ++nRealCount;
336 break;
337 case PROPERTYHANDLE_UILOCALE :
339 if (!m_bROUILocale)
341 pNames[nRealCount] = aOrgNames[nProp];
342 pValues[nRealCount] <<= m_aUILocaleString;
343 ++nRealCount;
346 break;
347 case PROPERTYHANDLE_CURRENCY :
349 if (!m_bROCurrency)
351 pNames[nRealCount] = aOrgNames[nProp];
352 pValues[nRealCount] <<= m_aCurrencyString;
353 ++nRealCount;
356 break;
357 case PROPERTYHANDLE_DECIMALSEPARATOR:
358 if( !m_bRODecimalSeparator )
360 pNames[nRealCount] = aOrgNames[nProp];
361 pValues[nRealCount] <<= m_bDecimalSeparator;
362 ++nRealCount;
364 break;
365 case PROPERTYHANDLE_DATEPATTERNS :
366 if (!m_bRODatePatterns)
368 pNames[nRealCount] = aOrgNames[nProp];
369 pValues[nRealCount] <<= m_aDatePatternsString;
370 ++nRealCount;
372 break;
373 case PROPERTYHANDLE_IGNORELANGCHANGE :
374 if (!m_bROIgnoreLanguageChange)
376 pNames[nRealCount] = aOrgNames[nProp];
377 pValues[nRealCount] <<= m_bIgnoreLanguageChange;
378 ++nRealCount;
380 break;
381 default:
382 SAL_WARN( "unotools.config", "invalid index to save a path" );
385 aNames.realloc(nRealCount);
386 aValues.realloc(nRealCount);
387 PutProperties( aNames, aValues );
390 void SvtSysLocaleOptions_Impl::SetLocaleString( const OUString& rStr )
392 ConfigurationHints nHint = ConfigurationHints::Locale;
394 MutexGuard aGuard( GetMutex() );
395 if (m_bROLocale || rStr == m_aLocaleString )
397 return;
399 m_aLocaleString = rStr;
400 MakeRealLocale();
401 LanguageTag::setConfiguredSystemLanguage( m_aRealLocale.getLanguageType() );
402 SetModified();
403 if ( m_aCurrencyString.isEmpty() )
404 nHint |= ConfigurationHints::Currency;
406 NotifyListeners( nHint );
409 void SvtSysLocaleOptions_Impl::SetUILocaleString( const OUString& rStr )
412 MutexGuard aGuard( GetMutex() );
413 if (m_bROUILocale || rStr == m_aUILocaleString )
415 return;
417 m_aUILocaleString = rStr;
419 // as we can't switch UILocale at runtime, we only store changes in the configuration
420 MakeRealUILocale();
421 SetModified();
423 NotifyListeners( ConfigurationHints::UiLocale );
426 void SvtSysLocaleOptions_Impl::SetCurrencyString( const OUString& rStr )
429 MutexGuard aGuard( GetMutex() );
430 if (m_bROCurrency || rStr == m_aCurrencyString )
432 return;
434 m_aCurrencyString = rStr;
435 SetModified();
437 NotifyListeners( ConfigurationHints::Currency );
440 void SvtSysLocaleOptions_Impl::SetDatePatternsString( const OUString& rStr )
443 MutexGuard aGuard( GetMutex() );
444 if (m_bRODatePatterns || rStr == m_aDatePatternsString )
446 return;
448 m_aDatePatternsString = rStr;
449 SetModified();
451 NotifyListeners( ConfigurationHints::DatePatterns );
454 void SvtSysLocaleOptions_Impl::SetDecimalSeparatorAsLocale( bool bSet)
457 MutexGuard aGuard( GetMutex() );
458 if(bSet == m_bDecimalSeparator)
460 return;
462 m_bDecimalSeparator = bSet;
463 SetModified();
465 NotifyListeners( ConfigurationHints::DecSep );
468 void SvtSysLocaleOptions_Impl::SetIgnoreLanguageChange( bool bSet)
471 MutexGuard aGuard( GetMutex() );
472 if(bSet == m_bIgnoreLanguageChange)
474 return;
476 m_bIgnoreLanguageChange = bSet;
477 SetModified();
479 NotifyListeners( ConfigurationHints::IgnoreLang );
482 void SvtSysLocaleOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
484 ConfigurationHints nHint = ConfigurationHints::NONE;
485 Sequence< Any > seqValues = GetProperties( seqPropertyNames );
486 Sequence< sal_Bool > seqROStates = GetReadOnlyStates( seqPropertyNames );
487 sal_Int32 nCount = seqPropertyNames.getLength();
488 for( sal_Int32 nProp = 0; nProp < nCount; ++nProp )
490 if( seqPropertyNames[nProp] == PROPERTYNAME_LOCALE )
492 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "Locale property type" );
493 seqValues[nProp] >>= m_aLocaleString;
494 m_bROLocale = seqROStates[nProp];
495 nHint |= ConfigurationHints::Locale;
496 if ( m_aCurrencyString.isEmpty() )
497 nHint |= ConfigurationHints::Currency;
498 MakeRealLocale();
500 if( seqPropertyNames[nProp] == PROPERTYNAME_UILOCALE )
502 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "Locale property type" );
503 seqValues[nProp] >>= m_aUILocaleString;
504 m_bROUILocale = seqROStates[nProp];
505 nHint |= ConfigurationHints::UiLocale;
506 MakeRealUILocale();
508 else if( seqPropertyNames[nProp] == PROPERTYNAME_CURRENCY )
510 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "Currency property type" );
511 seqValues[nProp] >>= m_aCurrencyString;
512 m_bROCurrency = seqROStates[nProp];
513 nHint |= ConfigurationHints::Currency;
515 else if( seqPropertyNames[nProp] == PROPERTYNAME_DECIMALSEPARATOR )
517 seqValues[nProp] >>= m_bDecimalSeparator;
518 m_bRODecimalSeparator = seqROStates[nProp];
520 else if( seqPropertyNames[nProp] == PROPERTYNAME_IGNORELANGCHANGE )
522 seqValues[nProp] >>= m_bIgnoreLanguageChange;
523 m_bROIgnoreLanguageChange = seqROStates[nProp];
525 else if( seqPropertyNames[nProp] == PROPERTYNAME_DATEPATTERNS )
527 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "DatePatterns property type" );
528 seqValues[nProp] >>= m_aDatePatternsString;
529 m_bRODatePatterns = seqROStates[nProp];
530 nHint |= ConfigurationHints::DatePatterns;
533 if ( nHint != ConfigurationHints::NONE )
534 NotifyListeners( nHint );
537 SvtSysLocaleOptions::SvtSysLocaleOptions()
539 MutexGuard aGuard( GetMutex() );
540 pImpl = g_pSysLocaleOptions.lock();
541 if ( !pImpl )
543 pImpl = std::make_shared<SvtSysLocaleOptions_Impl>();
544 g_pSysLocaleOptions = pImpl;
545 if (!utl::ConfigManager::IsFuzzing())
546 ItemHolder1::holdConfigItem(EItem::SysLocaleOptions);
548 pImpl->AddListener(this);
551 SvtSysLocaleOptions::~SvtSysLocaleOptions()
553 MutexGuard aGuard( GetMutex() );
554 pImpl->RemoveListener(this);
555 pImpl.reset();
558 bool SvtSysLocaleOptions::IsModified() const
560 MutexGuard aGuard( GetMutex() );
561 return pImpl->IsModified();
564 void SvtSysLocaleOptions::Commit()
566 MutexGuard aGuard( GetMutex() );
567 pImpl->Commit();
570 void SvtSysLocaleOptions::BlockBroadcasts( bool bBlock )
572 MutexGuard aGuard( GetMutex() );
573 pImpl->BlockBroadcasts( bBlock );
576 void SvtSysLocaleOptions::SetLocaleConfigString( const OUString& rStr )
578 pImpl->SetLocaleString( rStr );
581 void SvtSysLocaleOptions::SetUILocaleConfigString( const OUString& rStr )
583 pImpl->SetUILocaleString( rStr );
586 const OUString& SvtSysLocaleOptions::GetCurrencyConfigString() const
588 MutexGuard aGuard( GetMutex() );
589 return pImpl->GetCurrencyString();
592 void SvtSysLocaleOptions::SetCurrencyConfigString( const OUString& rStr )
594 pImpl->SetCurrencyString( rStr );
597 const OUString& SvtSysLocaleOptions::GetDatePatternsConfigString() const
599 MutexGuard aGuard( GetMutex() );
600 return pImpl->GetDatePatternsString();
603 void SvtSysLocaleOptions::SetDatePatternsConfigString( const OUString& rStr )
605 pImpl->SetDatePatternsString( rStr );
608 bool SvtSysLocaleOptions::IsDecimalSeparatorAsLocale() const
610 MutexGuard aGuard( GetMutex() );
611 return pImpl->IsDecimalSeparatorAsLocale();
614 void SvtSysLocaleOptions::SetDecimalSeparatorAsLocale( bool bSet)
616 pImpl->SetDecimalSeparatorAsLocale(bSet);
619 bool SvtSysLocaleOptions::IsIgnoreLanguageChange() const
621 MutexGuard aGuard( GetMutex() );
622 return pImpl->IsIgnoreLanguageChange();
625 void SvtSysLocaleOptions::SetIgnoreLanguageChange( bool bSet)
627 pImpl->SetIgnoreLanguageChange(bSet);
630 bool SvtSysLocaleOptions::IsReadOnly( EOption eOption ) const
632 MutexGuard aGuard( GetMutex() );
633 return pImpl->IsReadOnly( eOption );
636 // static
637 void SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( OUString& rAbbrev,
638 LanguageType& eLang,
639 const OUString& rConfigString )
641 sal_Int32 nDelim = rConfigString.indexOf( '-' );
642 if ( nDelim >= 0 )
644 rAbbrev = rConfigString.copy( 0, nDelim );
645 OUString aIsoStr( rConfigString.copy( nDelim+1 ) );
646 eLang = LanguageTag::convertToLanguageTypeWithFallback( aIsoStr );
648 else
650 rAbbrev = rConfigString;
651 eLang = (rAbbrev.isEmpty() ? LANGUAGE_SYSTEM : LANGUAGE_NONE);
655 // static
656 OUString SvtSysLocaleOptions::CreateCurrencyConfigString(
657 const OUString& rAbbrev, LanguageType eLang )
659 OUString aIsoStr( LanguageTag::convertToBcp47( eLang ) );
660 if ( !aIsoStr.isEmpty() )
662 return rAbbrev + "-" + aIsoStr;
664 else
665 return rAbbrev;
668 // static
669 void SvtSysLocaleOptions::SetCurrencyChangeLink( const Link<LinkParamNone*,void>& rLink )
671 MutexGuard aGuard( GetMutex() );
672 DBG_ASSERT( !CurrencyChangeLink::get().IsSet(), "SvtSysLocaleOptions::SetCurrencyChangeLink: already set" );
673 CurrencyChangeLink::get() = rLink;
676 // static
677 const Link<LinkParamNone*,void>& SvtSysLocaleOptions::GetCurrencyChangeLink()
679 MutexGuard aGuard( GetMutex() );
680 return CurrencyChangeLink::get();
683 void SvtSysLocaleOptions::ConfigurationChanged( utl::ConfigurationBroadcaster* p, ConfigurationHints nHint )
685 if ( nHint & ConfigurationHints::Currency )
687 const Link<LinkParamNone*,void>& rLink = GetCurrencyChangeLink();
688 rLink.Call( nullptr );
691 ::utl::detail::Options::ConfigurationChanged( p, nHint );
694 LanguageTag SvtSysLocaleOptions::GetLanguageTag() const
696 MutexGuard aGuard( GetMutex() );
697 return LanguageTag( pImpl->GetLocaleString() );
700 const LanguageTag & SvtSysLocaleOptions::GetRealLanguageTag() const
702 return pImpl->GetRealLocale();
705 const LanguageTag & SvtSysLocaleOptions::GetRealUILanguageTag() const
707 return pImpl->GetRealUILocale();
710 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */