LibreOffice Module unotools (master) 1
syslocaleoptions.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <com/sun/star/uno/Sequence.hxx>
21#include <sal/log.hxx>
24#include <tools/debug.hxx>
25#include <tools/link.hxx>
29#include <com/sun/star/uno/Any.hxx>
30
31#include "itemholder1.hxx"
32
33#define CFG_READONLY_DEFAULT false
34
35using namespace osl;
36using namespace utl;
37using namespace com::sun::star::uno;
38using namespace com::sun::star::lang;
39
40namespace
41{
42 std::weak_ptr<SvtSysLocaleOptions_Impl> g_pSysLocaleOptions;
43 Link<LinkParamNone*,void> g_CurrencyChangeLink;
44
45Mutex& GetMutex()
46{
47 // #i77768# Due to a static reference in the toolkit lib
48 // we need a mutex that lives longer than the svl library.
49 // Otherwise the dtor would use a destructed mutex!!
50 static Mutex* persistentMutex(new Mutex);
51
52 return *persistentMutex;
53}
54
55}
56
58{
61 OUString m_aLocaleString; // en-US or de-DE or empty for SYSTEM
62 OUString m_aUILocaleString; // en-US or de-DE or empty for SYSTEM
63 OUString m_aCurrencyString; // USD-en-US or EUR-de-DE
64 OUString m_aDatePatternsString; // "Y-M-D;M-D"
65 bool m_bDecimalSeparator; //use decimal separator same as locale
66 bool m_bIgnoreLanguageChange; //OS language change doesn't affect LO document language
67
74
76 void MakeRealLocale();
77 void MakeRealUILocale();
78
79 virtual void ImplCommit() override;
80
81public:
83 virtual ~SvtSysLocaleOptions_Impl() override;
84
85 virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
86
87 const OUString& GetLocaleString() const
88 { return m_aLocaleString; }
89 void SetLocaleString( const OUString& rStr );
90
91 void SetUILocaleString( const OUString& rStr );
92
93 const OUString& GetCurrencyString() const
94 { return m_aCurrencyString; }
95 void SetCurrencyString( const OUString& rStr );
96
97 const OUString& GetDatePatternsString() const
98 { return m_aDatePatternsString; }
99 void SetDatePatternsString( const OUString& rStr );
100
102 void SetDecimalSeparatorAsLocale( bool bSet);
103
105 void SetIgnoreLanguageChange( bool bSet);
106
107 bool IsReadOnly( SvtSysLocaleOptions::EOption eOption ) const;
108 const LanguageTag& GetRealLocale() const { return m_aRealLocale; }
109 const LanguageTag& GetRealUILocale() const { return m_aRealUILocale; }
110};
111
112constexpr OUStringLiteral ROOTNODE_SYSLOCALE = u"Setup/L10N";
113
114constexpr OUStringLiteral PROPERTYNAME_LOCALE = u"ooSetupSystemLocale";
115constexpr OUStringLiteral PROPERTYNAME_UILOCALE = u"ooLocale";
116constexpr OUStringLiteral PROPERTYNAME_CURRENCY = u"ooSetupCurrency";
117constexpr OUStringLiteral PROPERTYNAME_DECIMALSEPARATOR = u"DecimalSeparatorAsLocale";
118constexpr OUStringLiteral PROPERTYNAME_DATEPATTERNS = u"DateAcceptancePatterns";
119constexpr OUStringLiteral PROPERTYNAME_IGNORELANGCHANGE = u"IgnoreLanguageChange";
120
121#define PROPERTYHANDLE_LOCALE 0
122#define PROPERTYHANDLE_UILOCALE 1
123#define PROPERTYHANDLE_CURRENCY 2
124#define PROPERTYHANDLE_DECIMALSEPARATOR 3
125#define PROPERTYHANDLE_DATEPATTERNS 4
126#define PROPERTYHANDLE_IGNORELANGCHANGE 5
127
129{
131 {
138 };
139}
140
143 , m_aRealLocale( LANGUAGE_SYSTEM)
144 , m_aRealUILocale( LANGUAGE_SYSTEM)
145 , m_bDecimalSeparator( true )
146 , m_bIgnoreLanguageChange( false)
147 , m_bROLocale(CFG_READONLY_DEFAULT)
148 , m_bROUILocale(CFG_READONLY_DEFAULT)
149 , m_bROCurrency(CFG_READONLY_DEFAULT)
150 , m_bRODatePatterns(CFG_READONLY_DEFAULT)
151 , m_bRODecimalSeparator(false)
152 , m_bROIgnoreLanguageChange(false)
153
154{
155 const Sequence< OUString > aNames = GetPropertyNames();
156 Sequence< Any > aValues = GetProperties( aNames );
157 Sequence< sal_Bool > aROStates = GetReadOnlyStates( aNames );
158 const Any* pValues = aValues.getConstArray();
159 const sal_Bool* pROStates = aROStates.getConstArray();
160 DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" );
161 DBG_ASSERT( aROStates.getLength() == aNames.getLength(), "GetReadOnlyStates failed" );
162 if ( aValues.getLength() == aNames.getLength() && aROStates.getLength() == aNames.getLength() )
163 {
164 for ( sal_Int32 nProp = 0; nProp < aNames.getLength(); nProp++ )
165 {
166 if ( pValues[nProp].hasValue() )
167 {
168 switch ( nProp )
169 {
171 {
172 OUString aStr;
173 if ( pValues[nProp] >>= aStr )
175 else
176 {
177 SAL_WARN( "unotools.config", "Wrong property type!" );
178 }
179 m_bROLocale = pROStates[nProp];
180 }
181 break;
183 {
184 OUString aStr;
185 if ( pValues[nProp] >>= aStr )
187 else
188 {
189 SAL_WARN( "unotools.config", "Wrong property type!" );
190 }
191 m_bROUILocale = pROStates[nProp];
192 }
193 break;
195 {
196 OUString aStr;
197 if ( pValues[nProp] >>= aStr )
199 else
200 {
201 SAL_WARN( "unotools.config", "Wrong property type!" );
202 }
203 m_bROCurrency = pROStates[nProp];
204 }
205 break;
207 {
208 bool bValue = false;
209 if ( pValues[nProp] >>= bValue )
210 m_bDecimalSeparator = bValue;
211 else
212 {
213 SAL_WARN( "unotools.config", "Wrong property type!" );
214 }
215 m_bRODecimalSeparator = pROStates[nProp];
216 }
217 break;
219 {
220 OUString aStr;
221 if ( pValues[nProp] >>= aStr )
223 else
224 {
225 SAL_WARN( "unotools.config", "Wrong property type!" );
226 }
227 m_bRODatePatterns = pROStates[nProp];
228 }
229 break;
231 {
232 bool bValue = false;
233 if ( pValues[nProp] >>= bValue )
235 else
236 {
237 SAL_WARN( "unotools.config", "Wrong property type!" );
238 }
239 m_bROIgnoreLanguageChange = pROStates[nProp];
240 }
241 break;
242 default:
243 SAL_WARN( "unotools.config", "Wrong property type!" );
244 }
245 }
246 }
247 }
248 EnableNotification( aNames );
249
252}
253
255{
256 assert(!IsModified()); // should have been committed
257}
258
260{
261 if (m_aLocaleString.isEmpty())
262 {
265 }
266 else
267 {
269 }
270}
271
273{
274 if (m_aUILocaleString.isEmpty())
275 {
278 }
279 else
280 {
282 }
283}
284
286{
288 switch(eOption)
289 {
291 {
293 break;
294 }
296 {
298 break;
299 }
301 {
303 break;
304 }
305 }
306 return bReadOnly;
307}
308
310{
311 const Sequence< OUString > aOrgNames = GetPropertyNames();
312 sal_Int32 nOrgCount = aOrgNames.getLength();
313
314 Sequence< OUString > aNames( nOrgCount );
315 Sequence< Any > aValues( nOrgCount );
316
317 OUString* pNames = aNames.getArray();
318 Any* pValues = aValues.getArray();
319 sal_Int32 nRealCount = 0;
320
321 for ( sal_Int32 nProp = 0; nProp < nOrgCount; nProp++ )
322 {
323 switch ( nProp )
324 {
326 {
327 if (!m_bROLocale)
328 {
329 pNames[nRealCount] = aOrgNames[nProp];
330 pValues[nRealCount] <<= m_aLocaleString;
331 ++nRealCount;
332 }
333 }
334 break;
336 {
337 if (!m_bROUILocale)
338 {
339 pNames[nRealCount] = aOrgNames[nProp];
340 pValues[nRealCount] <<= m_aUILocaleString;
341 ++nRealCount;
342 }
343 }
344 break;
346 {
347 if (!m_bROCurrency)
348 {
349 pNames[nRealCount] = aOrgNames[nProp];
350 pValues[nRealCount] <<= m_aCurrencyString;
351 ++nRealCount;
352 }
353 }
354 break;
357 {
358 pNames[nRealCount] = aOrgNames[nProp];
359 pValues[nRealCount] <<= m_bDecimalSeparator;
360 ++nRealCount;
361 }
362 break;
365 {
366 pNames[nRealCount] = aOrgNames[nProp];
367 pValues[nRealCount] <<= m_aDatePatternsString;
368 ++nRealCount;
369 }
370 break;
373 {
374 pNames[nRealCount] = aOrgNames[nProp];
375 pValues[nRealCount] <<= m_bIgnoreLanguageChange;
376 ++nRealCount;
377 }
378 break;
379 default:
380 SAL_WARN( "unotools.config", "invalid index to save a path" );
381 }
382 }
383 aNames.realloc(nRealCount);
384 aValues.realloc(nRealCount);
385 PutProperties( aNames, aValues );
386}
387
389{
391 {
392 MutexGuard aGuard( GetMutex() );
393 if (m_bROLocale || rStr == m_aLocaleString )
394 {
395 return;
396 }
397 m_aLocaleString = rStr;
400 SetModified();
401 if ( m_aCurrencyString.isEmpty() )
403 }
404 NotifyListeners( nHint );
405}
406
408{
409 {
410 MutexGuard aGuard( GetMutex() );
411 if (m_bROUILocale || rStr == m_aUILocaleString )
412 {
413 return;
414 }
415 m_aUILocaleString = rStr;
416
417 // as we can't switch UILocale at runtime, we only store changes in the configuration
419 SetModified();
420 }
422}
423
425{
426 {
427 MutexGuard aGuard( GetMutex() );
428 if (m_bROCurrency || rStr == m_aCurrencyString )
429 {
430 return;
431 }
432 m_aCurrencyString = rStr;
433 SetModified();
434 }
436}
437
439{
440 {
441 MutexGuard aGuard( GetMutex() );
443 {
444 return;
445 }
447 SetModified();
448 }
450}
451
453{
454 {
455 MutexGuard aGuard( GetMutex() );
456 if(bSet == m_bDecimalSeparator)
457 {
458 return;
459 }
460 m_bDecimalSeparator = bSet;
461 SetModified();
462 }
464}
465
467{
468 {
469 MutexGuard aGuard( GetMutex() );
470 if(bSet == m_bIgnoreLanguageChange)
471 {
472 return;
473 }
475 SetModified();
476 }
478}
479
481{
483 Sequence< Any > seqValues = GetProperties( seqPropertyNames );
484 Sequence< sal_Bool > seqROStates = GetReadOnlyStates( seqPropertyNames );
485 sal_Int32 nCount = seqPropertyNames.getLength();
486 for( sal_Int32 nProp = 0; nProp < nCount; ++nProp )
487 {
488 if( seqPropertyNames[nProp] == PROPERTYNAME_LOCALE )
489 {
490 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "Locale property type" );
491 seqValues[nProp] >>= m_aLocaleString;
492 m_bROLocale = seqROStates[nProp];
494 if ( m_aCurrencyString.isEmpty() )
497 }
498 if( seqPropertyNames[nProp] == PROPERTYNAME_UILOCALE )
499 {
500 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "Locale property type" );
501 seqValues[nProp] >>= m_aUILocaleString;
502 m_bROUILocale = seqROStates[nProp];
505 }
506 else if( seqPropertyNames[nProp] == PROPERTYNAME_CURRENCY )
507 {
508 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "Currency property type" );
509 seqValues[nProp] >>= m_aCurrencyString;
510 m_bROCurrency = seqROStates[nProp];
512 }
513 else if( seqPropertyNames[nProp] == PROPERTYNAME_DECIMALSEPARATOR )
514 {
515 seqValues[nProp] >>= m_bDecimalSeparator;
516 m_bRODecimalSeparator = seqROStates[nProp];
517 }
518 else if( seqPropertyNames[nProp] == PROPERTYNAME_IGNORELANGCHANGE )
519 {
520 seqValues[nProp] >>= m_bIgnoreLanguageChange;
521 m_bROIgnoreLanguageChange = seqROStates[nProp];
522 }
523 else if( seqPropertyNames[nProp] == PROPERTYNAME_DATEPATTERNS )
524 {
525 DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "DatePatterns property type" );
526 seqValues[nProp] >>= m_aDatePatternsString;
527 m_bRODatePatterns = seqROStates[nProp];
529 }
530 }
531 if ( nHint != ConfigurationHints::NONE )
532 NotifyListeners( nHint );
533}
534
536{
537 MutexGuard aGuard( GetMutex() );
538 pImpl = g_pSysLocaleOptions.lock();
539 if ( !pImpl )
540 {
541 pImpl = std::make_shared<SvtSysLocaleOptions_Impl>();
542 g_pSysLocaleOptions = pImpl;
545 }
546 pImpl->AddListener(this);
547}
548
550{
551 MutexGuard aGuard( GetMutex() );
552 pImpl->RemoveListener(this);
553 pImpl.reset();
554}
555
557{
558 MutexGuard aGuard( GetMutex() );
559 return pImpl->IsModified();
560}
561
563{
564 MutexGuard aGuard( GetMutex() );
565 pImpl->Commit();
566}
567
569{
570 MutexGuard aGuard( GetMutex() );
571 pImpl->BlockBroadcasts( bBlock );
572}
573
575{
576 pImpl->SetLocaleString( rStr );
577}
578
580{
581 pImpl->SetUILocaleString( rStr );
582}
583
585{
586 MutexGuard aGuard( GetMutex() );
587 return pImpl->GetCurrencyString();
588}
589
591{
592 pImpl->SetCurrencyString( rStr );
593}
594
596{
597 MutexGuard aGuard( GetMutex() );
598 return pImpl->GetDatePatternsString();
599}
600
602{
603 pImpl->SetDatePatternsString( rStr );
604}
605
607{
608 MutexGuard aGuard( GetMutex() );
609 return pImpl->IsDecimalSeparatorAsLocale();
610}
611
613{
614 pImpl->SetDecimalSeparatorAsLocale(bSet);
615}
616
618{
619 MutexGuard aGuard( GetMutex() );
620 return pImpl->IsIgnoreLanguageChange();
621}
622
624{
625 pImpl->SetIgnoreLanguageChange(bSet);
626}
627
629{
630 MutexGuard aGuard( GetMutex() );
631 return pImpl->IsReadOnly( eOption );
632}
633
634// static
636 LanguageType& eLang,
637 const OUString& rConfigString )
638{
639 sal_Int32 nDelim = rConfigString.indexOf( '-' );
640 if ( nDelim >= 0 )
641 {
642 rAbbrev = rConfigString.copy( 0, nDelim );
643 OUString aIsoStr( rConfigString.copy( nDelim+1 ) );
645 }
646 else
647 {
648 rAbbrev = rConfigString;
649 eLang = (rAbbrev.isEmpty() ? LANGUAGE_SYSTEM : LANGUAGE_NONE);
650 }
651}
652
653// static
655 const OUString& rAbbrev, LanguageType eLang )
656{
657 OUString aIsoStr( LanguageTag::convertToBcp47( eLang ) );
658 if ( !aIsoStr.isEmpty() )
659 {
660 return rAbbrev + "-" + aIsoStr;
661 }
662 else
663 return rAbbrev;
664}
665
666// static
668{
669 MutexGuard aGuard( GetMutex() );
670 DBG_ASSERT( !g_CurrencyChangeLink.IsSet(), "SvtSysLocaleOptions::SetCurrencyChangeLink: already set" );
671 g_CurrencyChangeLink = rLink;
672}
673
674// static
676{
677 MutexGuard aGuard( GetMutex() );
678 return g_CurrencyChangeLink;
679}
680
682{
683 if ( nHint & ConfigurationHints::Currency )
684 {
686 rLink.Call( nullptr );
687 }
688
690}
691
693{
694 MutexGuard aGuard( GetMutex() );
695 return LanguageTag( pImpl->GetLocaleString() );
696}
697
699{
700 return pImpl->GetRealLocale();
701}
702
704{
705 return pImpl->GetRealUILocale();
706}
707
708/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
static void holdConfigItem(EItem eItem)
Definition: itemholder1.cxx:68
LanguageType getLanguageType(bool bResolveSystem=true) const
static void setConfiguredSystemLanguage(LanguageType nLang)
LanguageTag & makeFallback()
static OUString convertToBcp47(LanguageType nLangID)
static LanguageType convertToLanguageTypeWithFallback(const OUString &rBcp47)
LanguageTag & reset(const OUString &rBcp47LanguageTag)
static LanguageType getConfiguredSystemUILanguage()
static LanguageType getConfiguredSystemLanguage()
virtual ~SvtSysLocaleOptions_Impl() override
void SetUILocaleString(const OUString &rStr)
void SetCurrencyString(const OUString &rStr)
void SetLocaleString(const OUString &rStr)
const OUString & GetLocaleString() const
static Sequence< OUString > GetPropertyNames()
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames) override
is called from the ConfigManager before application ends of from the PropertyChangeListener if the su...
void SetDatePatternsString(const OUString &rStr)
void SetIgnoreLanguageChange(bool bSet)
virtual void ImplCommit() override
writes the changed values into the sub tree.
const LanguageTag & GetRealUILocale() const
void SetDecimalSeparatorAsLocale(bool bSet)
const OUString & GetDatePatternsString() const
const LanguageTag & GetRealLocale() const
bool IsDecimalSeparatorAsLocale() const
bool IsReadOnly(SvtSysLocaleOptions::EOption eOption) const
const OUString & GetCurrencyString() const
bool IsDecimalSeparatorAsLocale() const
const OUString & GetDatePatternsConfigString() const
The config string may be empty to denote the default DateAcceptancePatterns of the locale.
void SetDatePatternsConfigString(const OUString &rStr)
static void SetCurrencyChangeLink(const Link< LinkParamNone *, void > &rLink)
Set a link to a method to be called whenever the default currency changes.
std::shared_ptr< SvtSysLocaleOptions_Impl > pImpl
const LanguageTag & GetRealUILanguageTag() const
Get UI locale set, always resolved to the real locale.
virtual void BlockBroadcasts(bool bBlock) override
Add a listener to react on config changes which are broadcasted in a SfxSimpleHint.
static OUString CreateCurrencyConfigString(const OUString &rAbbrev, LanguageType eLang)
Create an USD-en-US or EUR-de-DE string.
void SetLocaleConfigString(const OUString &rStr)
The config string may be empty to denote the SYSTEM locale.
static void GetCurrencyAbbrevAndLanguage(OUString &rAbbrev, LanguageType &eLang, const OUString &rConfigString)
Get currency abbreviation and locale from an USD-en-US or EUR-de-DE string.
virtual void ConfigurationChanged(utl::ConfigurationBroadcaster *p, ConfigurationHints nHint) override
bool IsIgnoreLanguageChange() const
static const Link< LinkParamNone *, void > & GetCurrencyChangeLink()
void SetUILocaleConfigString(const OUString &rStr)
The config string may be empty to denote the SYSTEM locale.
void SetCurrencyConfigString(const OUString &rStr)
bool IsReadOnly(EOption eOption) const
return the readonly state of the queried option.
const OUString & GetCurrencyConfigString() const
The config string may be empty to denote the default currency of the locale.
void SetDecimalSeparatorAsLocale(bool bSet)
LanguageTag GetLanguageTag() const
Get locale set, not resolved to the real locale.
void SetIgnoreLanguageChange(bool bSet)
const LanguageTag & GetRealLanguageTag() const
Get locale set, always resolved to the real locale.
virtual ~SvtSysLocaleOptions() override
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
bool EnableNotification(const css::uno::Sequence< OUString > &rNames, bool bEnableInternalNotification=false)
enables notifications about changes on selected sub nodes/values
Definition: configitem.cxx:604
bool IsModified() const
Definition: configitem.hxx:177
bool PutProperties(const css::uno::Sequence< OUString > &rNames, const css::uno::Sequence< css::uno::Any > &rValues)
css::uno::Sequence< sal_Bool > GetReadOnlyStates(const css::uno::Sequence< OUString > &rNames)
Definition: configitem.cxx:316
static bool IsFuzzing()
Definition: configmgr.cxx:181
void NotifyListeners(ConfigurationHints nHint)
Definition: options.cxx:75
virtual void ConfigurationChanged(::utl::ConfigurationBroadcaster *p, ConfigurationHints nHint) override
Definition: options.cxx:109
int nCount
#define DBG_ASSERT(sCon, aError)
float u
bool bReadOnly
@ SysLocaleOptions
void * p
#define LANGUAGE_SYSTEM
#define LANGUAGE_NONE
#define SAL_WARN(area, stream)
aStr
ConfigurationHints
Definition: options.hxx:30
constexpr OUStringLiteral PROPERTYNAME_DECIMALSEPARATOR
constexpr OUStringLiteral PROPERTYNAME_DATEPATTERNS
constexpr OUStringLiteral ROOTNODE_SYSLOCALE
constexpr OUStringLiteral PROPERTYNAME_IGNORELANGCHANGE
#define PROPERTYHANDLE_CURRENCY
#define PROPERTYHANDLE_LOCALE
#define PROPERTYHANDLE_DATEPATTERNS
constexpr OUStringLiteral PROPERTYNAME_UILOCALE
#define PROPERTYHANDLE_UILOCALE
#define PROPERTYHANDLE_IGNORELANGCHANGE
#define PROPERTYHANDLE_DECIMALSEPARATOR
constexpr OUStringLiteral PROPERTYNAME_CURRENCY
constexpr OUStringLiteral PROPERTYNAME_LOCALE
#define CFG_READONLY_DEFAULT
unsigned char sal_Bool