diff options
author | Eike Rathke <erack@redhat.com> | 2012-08-29 20:49:01 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2012-08-29 21:17:46 +0200 |
commit | cda156257003df673fa853a0a5ffcd1cb4848d43 (patch) | |
tree | 5fcd7aa0c1c8e5de2da387e069423530500b15b4 /unotools | |
parent | 332451bea5ebe08136de2d51e0e29cac88f89e8c (diff) |
resolved fdo#52240 fdo#52137 fdo#52288 user editable date patterns
Implemented user editable date acceptance patterns.
The introduction of strict date parsing using locale dependent date
acceptance patterns in 3.6.0 wasn't always welcomed. Besides that not
every locale had patterns for incomplete (only day and month) date
input, users also complained about not being able to key in dates on
numeric keypads if the locale's date separator wasn't '/' or '-'
This commit implements a "Date acceptance patterns" edit field under
Tools->Options->LanguageSettings->Languages that follows the selected
locale and enables the user to add patterns.
Example de-DE locale:
* default patterns: D.M.Y;D.M.
* to enable additional input on numeric keypad: D.M.Y;D.M.;D-M-Y;D-M
* if 3-4 shall not result in a date, D-M- could be used instead of D-M
* note that to enter an ISO 8601 Y-M-D date with a D-M-Y pattern
active one needs to enter a year >31 or with at least 3 digits, e.g.
011
Change-Id: I9e20fcb168578b02d0f0248a0e209942e0f27113
Diffstat (limited to 'unotools')
-rw-r--r-- | unotools/inc/unotools/localedatawrapper.hxx | 6 | ||||
-rw-r--r-- | unotools/inc/unotools/syslocaleoptions.hxx | 18 | ||||
-rw-r--r-- | unotools/source/config/syslocaleoptions.cxx | 68 | ||||
-rw-r--r-- | unotools/source/i18n/localedatawrapper.cxx | 59 | ||||
-rw-r--r-- | unotools/source/misc/syslocale.cxx | 31 |
5 files changed, 174 insertions, 8 deletions
diff --git a/unotools/inc/unotools/localedatawrapper.hxx b/unotools/inc/unotools/localedatawrapper.hxx index 4391719eb7fc..1b6e95beae6d 100644 --- a/unotools/inc/unotools/localedatawrapper.hxx +++ b/unotools/inc/unotools/localedatawrapper.hxx @@ -62,6 +62,7 @@ class UNOTOOLS_DLLPUBLIC LocaleDataWrapper : private boost::noncopyable ::boost::shared_ptr< ::com::sun::star::i18n::Calendar2 > xDefaultCalendar; ::com::sun::star::i18n::LocaleDataItem aLocaleDataItem; ::com::sun::star::uno::Sequence< ::rtl::OUString > aReservedWordSeq; + ::com::sun::star::uno::Sequence< ::rtl::OUString > aDateAcceptancePatterns; ::com::sun::star::uno::Sequence< sal_Int32 > aGrouping; // cached items rtl::OUString aLocaleItem[::com::sun::star::i18n::LocaleItem::COUNT]; @@ -148,6 +149,11 @@ public: ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getAllInstalledLocaleNames() const; ::com::sun::star::uno::Sequence< ::rtl::OUString > getDateAcceptancePatterns() const; + /** Override locale's date acceptance patterns. + An empty sequence resets the patterns to the locale's pattern sequence. + */ + void setDateAcceptancePatterns( const ::com::sun::star::uno::Sequence< ::rtl::OUString > & rPatterns ); + /// same as the wrapper implementation but static static ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getInstalledLocaleNames(); diff --git a/unotools/inc/unotools/syslocaleoptions.hxx b/unotools/inc/unotools/syslocaleoptions.hxx index 6db9a0fd4349..1c62ad809492 100644 --- a/unotools/inc/unotools/syslocaleoptions.hxx +++ b/unotools/inc/unotools/syslocaleoptions.hxx @@ -31,10 +31,11 @@ #include <com/sun/star/lang/Locale.hpp> // bits for broadcasting hints of changes in a SfxSimpleHint, may be combined -const sal_uLong SYSLOCALEOPTIONS_HINT_LOCALE = 0x00000001; -const sal_uLong SYSLOCALEOPTIONS_HINT_CURRENCY = 0x00000002; -const sal_uLong SYSLOCALEOPTIONS_HINT_UILOCALE = 0x00000004; -const sal_uLong SYSLOCALEOPTIONS_HINT_DECSEP = 0x00000008; +const sal_uLong SYSLOCALEOPTIONS_HINT_LOCALE = 0x00000001; +const sal_uLong SYSLOCALEOPTIONS_HINT_CURRENCY = 0x00000002; +const sal_uLong SYSLOCALEOPTIONS_HINT_UILOCALE = 0x00000004; +const sal_uLong SYSLOCALEOPTIONS_HINT_DECSEP = 0x00000008; +const sal_uLong SYSLOCALEOPTIONS_HINT_DATEPATTERNS = 0x00000010; class SvtSysLocaleOptions_Impl; class SvtListener; @@ -54,7 +55,8 @@ public: { E_LOCALE, E_UILOCALE, - E_CURRENCY + E_CURRENCY, + E_DATEPATTERNS }; SvtSysLocaleOptions(); virtual ~SvtSysLocaleOptions(); @@ -108,6 +110,12 @@ public: /// The config string may be empty to denote the default currency of the locale const ::rtl::OUString& GetCurrencyConfigString() const; void SetCurrencyConfigString( const ::rtl::OUString& rStr ); + + /** The config string may be empty to denote the default + DateAcceptancePatterns of the locale */ + const ::rtl::OUString& GetDatePatternsConfigString() const; + void SetDatePatternsConfigString( const ::rtl::OUString& rStr ); + // determine whether the decimal separator defined in the keyboard layout is used // or the one approriate to the locale sal_Bool IsDecimalSeparatorAsLocale() const; diff --git a/unotools/source/config/syslocaleoptions.cxx b/unotools/source/config/syslocaleoptions.cxx index d790d48fdcef..604344ba66f5 100644 --- a/unotools/source/config/syslocaleoptions.cxx +++ b/unotools/source/config/syslocaleoptions.cxx @@ -77,11 +77,13 @@ class SvtSysLocaleOptions_Impl : public utl::ConfigItem OUString m_aLocaleString; // en-US or de-DE or empty for SYSTEM OUString m_aUILocaleString; // en-US or de-DE or empty for SYSTEM OUString m_aCurrencyString; // USD-en-US or EUR-de-DE + OUString m_aDatePatternsString; // "Y-M-D;M-D" sal_Bool m_bDecimalSeparator; //use decimal separator same as locale sal_Bool m_bROLocale; sal_Bool m_bROUILocale; sal_Bool m_bROCurrency; + sal_Bool m_bRODatePatterns; sal_Bool m_bRODecimalSeparator; static const Sequence< /* const */ OUString > GetPropertyNames(); @@ -107,6 +109,10 @@ public: { return m_aCurrencyString; } void SetCurrencyString( const OUString& rStr ); + const OUString& GetDatePatternsString() const + { return m_aDatePatternsString; } + void SetDatePatternsString( const OUString& rStr ); + sal_Bool IsDecimalSeparatorAsLocale() const { return m_bDecimalSeparator;} void SetDecimalSeparatorAsLocale( sal_Bool bSet); @@ -124,13 +130,15 @@ public: #define PROPERTYNAME_UILOCALE OUString(RTL_CONSTASCII_USTRINGPARAM("ooLocale")) #define PROPERTYNAME_CURRENCY OUString(RTL_CONSTASCII_USTRINGPARAM("ooSetupCurrency")) #define PROPERTYNAME_DECIMALSEPARATOR OUString(RTL_CONSTASCII_USTRINGPARAM("DecimalSeparatorAsLocale")) +#define PROPERTYNAME_DATEPATTERNS OUString(RTL_CONSTASCII_USTRINGPARAM("DateAcceptancePatterns")) #define PROPERTYHANDLE_LOCALE 0 #define PROPERTYHANDLE_UILOCALE 1 #define PROPERTYHANDLE_CURRENCY 2 #define PROPERTYHANDLE_DECIMALSEPARATOR 3 +#define PROPERTYHANDLE_DATEPATTERNS 4 -#define PROPERTYCOUNT 4 +#define PROPERTYCOUNT 5 const Sequence< OUString > SvtSysLocaleOptions_Impl::GetPropertyNames() { @@ -139,7 +147,8 @@ const Sequence< OUString > SvtSysLocaleOptions_Impl::GetPropertyNames() PROPERTYNAME_LOCALE, PROPERTYNAME_UILOCALE, PROPERTYNAME_CURRENCY, - PROPERTYNAME_DECIMALSEPARATOR + PROPERTYNAME_DECIMALSEPARATOR, + PROPERTYNAME_DATEPATTERNS }; const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT ); return seqPropertyNames; @@ -153,6 +162,7 @@ SvtSysLocaleOptions_Impl::SvtSysLocaleOptions_Impl() , m_bROLocale(CFG_READONLY_DEFAULT) , m_bROUILocale(CFG_READONLY_DEFAULT) , m_bROCurrency(CFG_READONLY_DEFAULT) + , m_bRODatePatterns(CFG_READONLY_DEFAULT) , m_bRODecimalSeparator(sal_False) { @@ -221,6 +231,18 @@ SvtSysLocaleOptions_Impl::SvtSysLocaleOptions_Impl() m_bRODecimalSeparator = pROStates[nProp]; } break; + case PROPERTYHANDLE_DATEPATTERNS : + { + OUString aStr; + if ( pValues[nProp] >>= aStr ) + m_aDatePatternsString = aStr; + else + { + SAL_WARN( "unotools.config", "Wrong property type!" ); + } + m_bRODatePatterns = pROStates[nProp]; + } + break; default: SAL_WARN( "unotools.config", "Wrong property type!" ); } @@ -290,6 +312,11 @@ sal_Bool SvtSysLocaleOptions_Impl::IsReadOnly( SvtSysLocaleOptions::EOption eOpt bReadOnly = m_bROCurrency; break; } + case SvtSysLocaleOptions::E_DATEPATTERNS : + { + bReadOnly = m_bRODatePatterns; + break; + } } return bReadOnly; } @@ -349,6 +376,14 @@ void SvtSysLocaleOptions_Impl::Commit() ++nRealCount; } break; + case PROPERTYHANDLE_DATEPATTERNS : + if (!m_bRODatePatterns) + { + pNames[nRealCount] = aOrgNames[nProp]; + pValues[nRealCount] <<= m_aDatePatternsString; + ++nRealCount; + } + break; default: SAL_WARN( "unotools.config", "invalid index to save a path" ); } @@ -399,6 +434,16 @@ void SvtSysLocaleOptions_Impl::SetCurrencyString( const OUString& rStr ) } } +void SvtSysLocaleOptions_Impl::SetDatePatternsString( const OUString& rStr ) +{ + if (!m_bRODatePatterns && rStr != m_aDatePatternsString ) + { + m_aDatePatternsString = rStr; + SetModified(); + NotifyListeners( SYSLOCALEOPTIONS_HINT_DATEPATTERNS ); + } +} + void SvtSysLocaleOptions_Impl::SetDecimalSeparatorAsLocale( sal_Bool bSet) { if(bSet != m_bDecimalSeparator) @@ -447,6 +492,13 @@ void SvtSysLocaleOptions_Impl::Notify( const Sequence< rtl::OUString >& seqPrope seqValues[nProp] >>= m_bDecimalSeparator; m_bRODecimalSeparator = seqROStates[nProp]; } + else if( seqPropertyNames[nProp] == PROPERTYNAME_DATEPATTERNS ) + { + DBG_ASSERT( seqValues[nProp].getValueTypeClass() == TypeClass_STRING, "DatePatterns property type" ); + seqValues[nProp] >>= m_aDatePatternsString; + m_bRODatePatterns = seqROStates[nProp]; + nHint |= SYSLOCALEOPTIONS_HINT_DATEPATTERNS; + } } if ( nHint ) NotifyListeners( nHint ); @@ -552,6 +604,18 @@ void SvtSysLocaleOptions::SetCurrencyConfigString( const OUString& rStr ) pOptions->SetCurrencyString( rStr ); } +const OUString& SvtSysLocaleOptions::GetDatePatternsConfigString() const +{ + MutexGuard aGuard( GetMutex() ); + return pOptions->GetDatePatternsString(); +} + +void SvtSysLocaleOptions::SetDatePatternsConfigString( const OUString& rStr ) +{ + MutexGuard aGuard( GetMutex() ); + pOptions->SetDatePatternsString( rStr ); +} + sal_Bool SvtSysLocaleOptions::IsDecimalSeparatorAsLocale() const { MutexGuard aGuard( GetMutex() ); diff --git a/unotools/source/i18n/localedatawrapper.cxx b/unotools/source/i18n/localedatawrapper.cxx index 8faab07f0cd7..db5e2b85e266 100644 --- a/unotools/source/i18n/localedatawrapper.cxx +++ b/unotools/source/i18n/localedatawrapper.cxx @@ -120,6 +120,8 @@ void LocaleDataWrapper::invalidateData() xDefaultCalendar.reset(); if (aGrouping.getLength()) aGrouping[0] = 0; + if (aDateAcceptancePatterns.getLength()) + aDateAcceptancePatterns = Sequence<OUString>(); // dummies cCurrZeroChar = '0'; } @@ -1845,10 +1847,21 @@ void LocaleDataWrapper::evaluateLocaleDataChecking() ::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getDateAcceptancePatterns() const { + ::utl::ReadWriteGuard aGuard( aMutex ); + + if (aDateAcceptancePatterns.getLength()) + return aDateAcceptancePatterns; + + aGuard.changeReadToWrite(); + try { if ( xLD.is() ) - return xLD->getDateAcceptancePatterns( getLocale() ); + { + const_cast<LocaleDataWrapper*>(this)->aDateAcceptancePatterns = + xLD->getDateAcceptancePatterns( getLocale() ); + return aDateAcceptancePatterns; + } } catch (const Exception& e) { @@ -1857,4 +1870,48 @@ void LocaleDataWrapper::evaluateLocaleDataChecking() return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0); } +// --- Override layer -------------------------------------------------------- + +void LocaleDataWrapper::setDateAcceptancePatterns( + const ::com::sun::star::uno::Sequence< ::rtl::OUString > & rPatterns ) +{ + ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nWrite ); + + if (!aDateAcceptancePatterns.getLength() || !rPatterns.getLength()) + { + try + { + if ( xLD.is() ) + aDateAcceptancePatterns = xLD->getDateAcceptancePatterns( getLocale() ); + } + catch (const Exception& e) + { + SAL_WARN( "unotools.i18n", "setDateAcceptancePatterns: Exception caught " << e.Message ); + } + if (!rPatterns.getLength()) + return; // just a reset + if (!aDateAcceptancePatterns.getLength()) + { + aDateAcceptancePatterns = rPatterns; + return; + } + } + + // Never overwrite the locale's full date pattern! The first. + if (aDateAcceptancePatterns[0] == rPatterns[0]) + aDateAcceptancePatterns = rPatterns; // sane + else + { + // Copy existing full date pattern and append the sequence passed. + /* TODO: could check for duplicates and shrink target sequence */ + Sequence< OUString > aTmp( rPatterns.getLength() + 1 ); + OUString* pArray1 = aTmp.getArray(); + const OUString* pArray2 = rPatterns.getConstArray(); + pArray1[0] = aDateAcceptancePatterns[0]; + for (sal_Int32 i=0; i < rPatterns.getLength(); ++i) + pArray1[i+1] = pArray2[i]; + aDateAcceptancePatterns = aTmp; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/unotools/source/misc/syslocale.cxx b/unotools/source/misc/syslocale.cxx index 2441a528fc40..ead6e92eeb3e 100644 --- a/unotools/source/misc/syslocale.cxx +++ b/unotools/source/misc/syslocale.cxx @@ -26,6 +26,7 @@ #include <rtl/tencinfo.h> #include <rtl/locale.h> #include <osl/nlsupport.h> +#include <vector> using namespace osl; using namespace com::sun::star; @@ -47,6 +48,9 @@ public: CharClass* GetCharClass(); virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ); + +private: + void setDateAcceptancePatternsConfig(); }; // ----------------------------------------------------------------------- @@ -54,6 +58,7 @@ public: SvtSysLocale_Impl::SvtSysLocale_Impl() : pCharClass(NULL) { pLocaleData = new LocaleDataWrapper( ::comphelper::getProcessServiceFactory(), aSysLocaleOptions.GetRealLocale() ); + setDateAcceptancePatternsConfig(); // listen for further changes aSysLocaleOptions.AddListener( this ); @@ -77,12 +82,38 @@ CharClass* SvtSysLocale_Impl::GetCharClass() void SvtSysLocale_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 nHint ) { MutexGuard aGuard( SvtSysLocale::GetMutex() ); + if ( nHint & SYSLOCALEOPTIONS_HINT_LOCALE ) { com::sun::star::lang::Locale aLocale( aSysLocaleOptions.GetRealLocale() ); pLocaleData->setLocale( aLocale ); GetCharClass()->setLocale( aLocale ); } + if ( nHint & SYSLOCALEOPTIONS_HINT_DATEPATTERNS ) + { + setDateAcceptancePatternsConfig(); + } +} + +void SvtSysLocale_Impl::setDateAcceptancePatternsConfig() +{ + OUString aStr( aSysLocaleOptions.GetDatePatternsConfigString()); + if (aStr.isEmpty()) + pLocaleData->setDateAcceptancePatterns( uno::Sequence<OUString>()); // reset + else + { + ::std::vector< OUString > aVec; + for (sal_Int32 nIndex = 0; nIndex >= 0; /*nop*/) + { + OUString aTok( aStr.getToken( 0, ';', nIndex)); + if (!aTok.isEmpty()) + aVec.push_back( aTok); + } + uno::Sequence< OUString > aSeq( aVec.size()); + for (sal_Int32 i=0; i < aSeq.getLength(); ++i) + aSeq[i] = aVec[i]; + pLocaleData->setDateAcceptancePatterns( aSeq); + } } // ==================================================================== |