1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <unotools/compatibility.hxx>
21 #include <unotools/configitem.hxx>
22 #include <unotools/syslocale.hxx>
23 #include <tools/debug.hxx>
24 #include <sal/log.hxx>
25 #include <com/sun/star/uno/Any.hxx>
26 #include <com/sun/star/uno/Sequence.hxx>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/lang/Locale.hpp>
29 #include <i18nlangtag/languagetag.hxx>
31 #include "itemholder1.hxx"
36 using namespace ::std
;
37 using namespace ::utl
;
38 using namespace ::osl
;
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::beans
;
42 #define ROOTNODE_OPTIONS "Office.Compatibility"
43 #define PATHDELIMITER "/"
44 #define SETNODE_ALLFILEFORMATS "AllFileFormats"
46 SvtCompatibilityEntry::SvtCompatibilityEntry()
47 : m_aPropertyValue( SvtCompatibilityEntry::getElementCount() )
49 /* Should be in the start. Do not remove it. */
50 setValue
<OUString
>( Index::Name
, OUString() );
51 setValue
<OUString
>( Index::Module
, OUString() );
53 /* Editable list of default values. Sync it with the SvtCompatibilityEntry::Index enum class. */
54 setValue
<bool>( Index::UsePrtMetrics
, false );
55 setValue
<bool>( Index::AddSpacing
, false );
56 setValue
<bool>( Index::AddSpacingAtPages
, false );
57 setValue
<bool>( Index::UseOurTabStops
, false );
58 setValue
<bool>( Index::NoExtLeading
, false );
59 setValue
<bool>( Index::UseLineSpacing
, false );
60 setValue
<bool>( Index::AddTableSpacing
, false );
61 setValue
<bool>( Index::UseObjectPositioning
, false );
62 setValue
<bool>( Index::UseOurTextWrapping
, false );
63 setValue
<bool>( Index::ConsiderWrappingStyle
, false );
64 setValue
<bool>( Index::ExpandWordSpace
, true );
65 setValue
<bool>( Index::ProtectForm
, false );
66 setValue
<bool>( Index::MsWordTrailingBlanks
, false );
67 setValue
<bool>( Index::SubtractFlysAnchoredAtFlys
, false );
68 setValue
<bool>( Index::EmptyDbFieldHidesPara
, true );
70 setDefaultEntry( false );
73 OUString
SvtCompatibilityEntry::getName( const Index rIdx
)
75 static const char* sPropertyName
[] =
77 /* Should be in the start. Do not remove it. */
81 /* Editable list of compatibility option names. Sync it with the SvtCompatibilityEntry::Index enum class. */
85 "UseOurTabStopFormat",
89 "UseObjectPositioning",
91 "ConsiderWrappingStyle",
94 "MsWordCompTrailingBlanks",
95 "SubtractFlysAnchoredAtFlys",
96 "EmptyDbFieldHidesPara",
99 /* Size of sPropertyName array not equal size of the SvtCompatibilityEntry::Index enum class */
100 assert( SAL_N_ELEMENTS(sPropertyName
) == static_cast<int>( SvtCompatibilityEntry::getElementCount() ) );
102 return OUString::createFromAscii( sPropertyName
[ static_cast<int>(rIdx
) ] );
105 /*-****************************************************************************************************************
106 @descr support simple menu structures and operations on it
107 ****************************************************************************************************************-*/
109 /*-****************************************************************************************************
110 @short base implementation of public interface for "SvtCompatibilityOptions"!
111 @descr These class is used as static member of "SvtCompatibilityOptions" ...
112 => The code exist only for one time and isn't duplicated for every instance!
113 *//*-*****************************************************************************************************/
114 class SvtCompatibilityOptions_Impl
: public ConfigItem
117 SvtCompatibilityOptions_Impl();
118 virtual ~SvtCompatibilityOptions_Impl() override
;
120 void AppendItem( const SvtCompatibilityEntry
& aItem
);
123 void SetDefault( SvtCompatibilityEntry::Index rIdx
, bool rValue
);
124 bool GetDefault( SvtCompatibilityEntry::Index rIdx
) const;
126 Sequence
< Sequence
< PropertyValue
> > GetList() const;
128 /*-****************************************************************************************************
129 @short called for notify of configmanager
130 @descr This method is called from the ConfigManager before the application ends or from the
131 PropertyChangeListener if the sub tree broadcasts changes. You must update your
134 @seealso baseclass ConfigItem
136 @param "lPropertyNames" is the list of properties which should be updated.
137 *//*-*****************************************************************************************************/
138 virtual void Notify( const Sequence
< OUString
>& lPropertyNames
) override
;
141 virtual void ImplCommit() override
;
143 /*-****************************************************************************************************
144 @short return list of key names of our configuration management which represent one module tree
145 @descr These methods return the current list of key names! We need it to get needed values from our
146 configuration management and support dynamical menu item lists!
147 @return A list of configuration key names is returned.
148 *//*-*****************************************************************************************************/
149 Sequence
< OUString
> impl_GetPropertyNames( Sequence
< OUString
>& rItems
);
152 std::vector
< SvtCompatibilityEntry
> m_aOptions
;
153 SvtCompatibilityEntry m_aDefOptions
;
156 SvtCompatibilityOptions_Impl::SvtCompatibilityOptions_Impl() : ConfigItem( ROOTNODE_OPTIONS
)
158 // Get names and values of all accessible menu entries and fill internal structures.
159 // See impl_GetPropertyNames() for further information.
160 Sequence
< OUString
> lNodes
;
161 Sequence
< OUString
> lNames
= impl_GetPropertyNames( lNodes
);
162 Sequence
< Any
> lValues
= GetProperties( lNames
);
164 // Safe impossible cases.
165 // We need values from ALL configuration keys.
166 // Follow assignment use order of values in relation to our list of key names!
167 DBG_ASSERT( !( lNames
.getLength()!=lValues
.getLength() ), "SvtCompatibilityOptions_Impl::SvtCompatibilityOptions_Impl()\nI miss some values of configuration keys!\n" );
169 // Get names/values for new menu.
170 // 4 subkeys for every item!
171 bool bDefaultFound
= false;
172 sal_Int32 nDestStep
= 0;
173 for ( const auto& rNode
: std::as_const(lNodes
) )
175 SvtCompatibilityEntry aItem
;
177 aItem
.setValue
<OUString
>( SvtCompatibilityEntry::Index::Name
, rNode
);
179 for ( int i
= static_cast<int>(SvtCompatibilityEntry::Index::Module
); i
< static_cast<int>(SvtCompatibilityEntry::Index::INVALID
); ++i
)
181 aItem
.setValue( SvtCompatibilityEntry::Index(i
), lValues
[ nDestStep
] );
185 m_aOptions
.push_back( aItem
);
187 if ( !bDefaultFound
&& aItem
.getValue
<OUString
>( SvtCompatibilityEntry::Index::Name
) == SvtCompatibilityEntry::getDefaultEntryName() )
189 SvtSysLocale aSysLocale
;
190 css::lang::Locale aLocale
= aSysLocale
.GetLanguageTag().getLocale();
191 if ( aLocale
.Language
== "zh" || aLocale
.Language
== "ja" || aLocale
.Language
== "ko" )
192 aItem
.setValue
<bool>( SvtCompatibilityEntry::Index::ExpandWordSpace
, false );
194 m_aDefOptions
= aItem
;
195 bDefaultFound
= true;
200 SvtCompatibilityOptions_Impl::~SvtCompatibilityOptions_Impl()
202 assert( !IsModified() ); // should have been committed
205 void SvtCompatibilityOptions_Impl::AppendItem( const SvtCompatibilityEntry
& aItem
)
207 m_aOptions
.push_back( aItem
);
209 // default item reset?
210 if ( aItem
.getValue
<OUString
>( SvtCompatibilityEntry::Index::Name
) == SvtCompatibilityEntry::getDefaultEntryName() )
211 m_aDefOptions
= aItem
;
216 void SvtCompatibilityOptions_Impl::Clear()
223 void SvtCompatibilityOptions_Impl::SetDefault( SvtCompatibilityEntry::Index rIdx
, bool rValue
)
225 /* Are not set Name and Module */
226 assert( rIdx
!= SvtCompatibilityEntry::Index::Name
&& rIdx
!= SvtCompatibilityEntry::Index::Module
);
228 m_aDefOptions
.setValue
<bool>( rIdx
, rValue
);
231 bool SvtCompatibilityOptions_Impl::GetDefault( SvtCompatibilityEntry::Index rIdx
) const
233 /* Are not set Name and Module */
234 assert( rIdx
!= SvtCompatibilityEntry::Index::Name
&& rIdx
!= SvtCompatibilityEntry::Index::Module
);
236 return m_aDefOptions
.getValue
<bool>( rIdx
);
239 Sequence
< Sequence
< PropertyValue
> > SvtCompatibilityOptions_Impl::GetList() const
241 Sequence
< PropertyValue
> lProperties( SvtCompatibilityEntry::getElementCount() );
242 Sequence
< Sequence
< PropertyValue
> > lResult( m_aOptions
.size() );
244 for ( int i
= static_cast<int>(SvtCompatibilityEntry::Index::Name
); i
< static_cast<int>(SvtCompatibilityEntry::Index::INVALID
); ++i
)
245 lProperties
[i
].Name
= SvtCompatibilityEntry::getName( SvtCompatibilityEntry::Index(i
) );
248 for ( const auto& rItem
: m_aOptions
)
250 for ( int i
= static_cast<int>(SvtCompatibilityEntry::Index::Name
); i
< static_cast<int>(SvtCompatibilityEntry::Index::INVALID
); ++i
)
251 lProperties
[i
].Value
= rItem
.getValue( SvtCompatibilityEntry::Index(i
) );
252 lResult
[ j
++ ] = lProperties
;
258 void SvtCompatibilityOptions_Impl::Notify( const Sequence
< OUString
>& )
260 SAL_WARN( "unotools.config", "SvtCompatibilityOptions_Impl::Notify() Not implemented yet! I don't know how I can handle a dynamical list of unknown properties ..." );
263 void SvtCompatibilityOptions_Impl::ImplCommit()
265 // Write all properties!
266 // Delete complete set first.
267 ClearNodeSet( SETNODE_ALLFILEFORMATS
);
269 Sequence
< PropertyValue
> lPropertyValues( SvtCompatibilityEntry::getElementCount() - 1 );
270 sal_uInt32 nNewCount
= m_aOptions
.size();
271 for ( sal_uInt32 nItem
= 0; nItem
< nNewCount
; ++nItem
)
273 SvtCompatibilityEntry aItem
= m_aOptions
[ nItem
];
274 OUString sNode
= SETNODE_ALLFILEFORMATS PATHDELIMITER
+ aItem
.getValue
<OUString
>( SvtCompatibilityEntry::Index::Name
) + PATHDELIMITER
;
276 for ( int i
= static_cast<int>(SvtCompatibilityEntry::Index::Module
); i
< static_cast<int>(SvtCompatibilityEntry::Index::INVALID
); ++i
)
278 lPropertyValues
[ i
- 1 ].Name
= sNode
+ SvtCompatibilityEntry::getName( SvtCompatibilityEntry::Index(i
) );
279 lPropertyValues
[ i
- 1 ].Value
= aItem
.getValue( SvtCompatibilityEntry::Index(i
) );
282 SetSetProperties( SETNODE_ALLFILEFORMATS
, lPropertyValues
);
286 Sequence
< OUString
> SvtCompatibilityOptions_Impl::impl_GetPropertyNames( Sequence
< OUString
>& rItems
)
288 // First get ALL names of current existing list items in configuration!
289 rItems
= GetNodeNames( SETNODE_ALLFILEFORMATS
);
291 // expand list to result list ...
292 Sequence
< OUString
> lProperties( rItems
.getLength() * ( SvtCompatibilityEntry::getElementCount() - 1 ) );
294 sal_Int32 nDestStep
= 0;
295 // Copy entries to destination and expand every item with 2 supported sub properties.
296 for ( const auto& rItem
: std::as_const(rItems
) )
298 OUString sFixPath
= SETNODE_ALLFILEFORMATS PATHDELIMITER
+ rItem
+ PATHDELIMITER
;
299 for ( int i
= static_cast<int>(SvtCompatibilityEntry::Index::Module
); i
< static_cast<int>(SvtCompatibilityEntry::Index::INVALID
); ++i
)
301 lProperties
[ nDestStep
] = sFixPath
+ SvtCompatibilityEntry::getName( SvtCompatibilityEntry::Index(i
) );
312 std::weak_ptr
<SvtCompatibilityOptions_Impl
> theOptions
;
315 SvtCompatibilityOptions::SvtCompatibilityOptions()
317 // Global access, must be guarded (multithreading!).
318 MutexGuard
aGuard( GetOwnStaticMutex() );
320 m_pImpl
= theOptions
.lock();
323 m_pImpl
= std::make_shared
<SvtCompatibilityOptions_Impl
>();
324 theOptions
= m_pImpl
;
325 ItemHolder1::holdConfigItem( EItem::Compatibility
);
329 SvtCompatibilityOptions::~SvtCompatibilityOptions()
331 // Global access, must be guarded (multithreading!)
332 MutexGuard
aGuard( GetOwnStaticMutex() );
336 void SvtCompatibilityOptions::AppendItem( const SvtCompatibilityEntry
& aItem
)
338 MutexGuard
aGuard( GetOwnStaticMutex() );
339 m_pImpl
->AppendItem( aItem
);
342 void SvtCompatibilityOptions::Clear()
344 MutexGuard
aGuard( GetOwnStaticMutex() );
348 void SvtCompatibilityOptions::SetDefault( SvtCompatibilityEntry::Index rIdx
, bool rValue
)
350 MutexGuard
aGuard( GetOwnStaticMutex() );
351 m_pImpl
->SetDefault( rIdx
, rValue
);
354 bool SvtCompatibilityOptions::GetDefault( SvtCompatibilityEntry::Index rIdx
) const
356 MutexGuard
aGuard( GetOwnStaticMutex() );
357 return m_pImpl
->GetDefault( rIdx
);
360 Sequence
< Sequence
< PropertyValue
> > SvtCompatibilityOptions::GetList() const
362 MutexGuard
aGuard( GetOwnStaticMutex() );
363 return m_pImpl
->GetList();
368 class theCompatibilityOptionsMutex
: public rtl::Static
<osl::Mutex
, theCompatibilityOptionsMutex
>{};
371 Mutex
& SvtCompatibilityOptions::GetOwnStaticMutex()
373 return theCompatibilityOptionsMutex::get();
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */