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 .
21 #include <vcl/settings.hxx>
22 #include <vcl/weld.hxx>
23 #include <i18nlangtag/languagetag.hxx>
24 #include <i18nlangtag/mslangid.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <officecfg/Office/Security.hxx>
27 #include <officecfg/Office/Linguistic.hxx>
28 #include <unotools/lingucfg.hxx>
29 #include <unotools/linguprops.hxx>
30 #include <editeng/unolingu.hxx>
31 #include <linguistic/misc.hxx>
32 #include <sfx2/sfxsids.hrc>
33 #include <tools/debug.hxx>
34 #include <tools/urlobj.hxx>
35 #include <comphelper/diagnose_ex.hxx>
36 #include <comphelper/dispatchcommand.hxx>
37 #include <comphelper/lok.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
40 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
41 #include <com/sun/star/linguistic2/XSpellChecker.hpp>
42 #include <com/sun/star/linguistic2/XProofreader.hpp>
43 #include <com/sun/star/linguistic2/XHyphenator.hpp>
44 #include <com/sun/star/linguistic2/XThesaurus.hpp>
45 #include <com/sun/star/linguistic2/XDictionary.hpp>
46 #include <com/sun/star/linguistic2/XDictionaryList.hpp>
47 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
48 #include <com/sun/star/lang/XServiceDisplayName.hpp>
49 #include <com/sun/star/frame/XStorable.hpp>
50 #include <com/sun/star/container/XNameAccess.hpp>
51 #include <com/sun/star/beans/PropertyAttribute.hpp>
52 #include <unotools/extendedsecurityoptions.hxx>
53 #include <svl/eitem.hxx>
54 #include <vcl/svapp.hxx>
55 #include <sal/log.hxx>
56 #include <osl/diagnose.h>
58 #include <svx/svxdlg.hxx>
59 #include <editeng/optitems.hxx>
60 #include <optlingu.hxx>
61 #include <dialmgr.hxx>
62 #include <strings.hrc>
64 #include <ucbhelper/content.hxx>
70 using namespace ::ucbhelper
;
71 using namespace ::com::sun::star
;
72 using namespace css::lang
;
73 using namespace css::uno
;
74 using namespace css::linguistic2
;
75 using namespace css::beans
;
77 constexpr OUString
cSpell(SN_SPELLCHECKER
);
78 constexpr OUString
cGrammar(SN_GRAMMARCHECKER
);
79 constexpr OUString
cHyph(SN_HYPHENATOR
);
80 constexpr OUString
cThes(SN_THESAURUS
);
82 // static ----------------------------------------------------------------
84 static sal_Int32
lcl_SeqGetEntryPos(
85 const Sequence
< OUString
> &rSeq
, std::u16string_view rEntry
)
87 auto it
= std::find(rSeq
.begin(), rSeq
.end(), rEntry
);
88 return it
== rSeq
.end() ? -1 : std::distance(rSeq
.begin(), it
);
91 static bool KillFile_Impl( const OUString
& rURL
)
96 Content
aCnt( rURL
, uno::Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
97 aCnt
.executeCommand( u
"delete"_ustr
, Any( true ) );
101 TOOLS_WARN_EXCEPTION( "cui.options", "KillFile" );
110 // t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar
111 // c: 1 -> checked 0 -> unchecked
114 #define TYPE_SPELL sal_uInt8(1)
115 #define TYPE_GRAMMAR sal_uInt8(2)
116 #define TYPE_HYPH sal_uInt8(3)
117 #define TYPE_THES sal_uInt8(4)
121 class ModuleUserData_Impl
130 ModuleUserData_Impl( OUString sImpName
, bool bIsParent
, bool bChecked
, sal_uInt8 nSetType
, sal_uInt8 nSetIndex
) :
132 bIsChecked(bChecked
),
135 sImplName(std::move(sImpName
))
138 bool IsParent() const {return bParent
;}
139 sal_uInt8
GetType() const {return nType
;}
140 bool IsChecked() const {return bIsChecked
;}
141 sal_uInt8
GetIndex() const {return nIndex
;}
142 const OUString
& GetImplName() const {return sImplName
;}
147 // User for user-dictionaries (XDictionary interface)
154 explicit DicUserData(sal_uInt32 nUserData
) : nVal( nUserData
) {}
155 DicUserData( sal_uInt16 nEID
,
156 bool bChecked
, bool bEditable
, bool bDeletable
);
158 sal_uInt32
GetUserData() const { return nVal
; }
159 sal_uInt16
GetEntryId() const { return static_cast<sal_uInt16
>(nVal
>> 16); }
160 bool IsChecked() const { return static_cast<bool>((nVal
>> 8) & 0x01); }
161 bool IsDeletable() const { return static_cast<bool>((nVal
>> 10) & 0x01); }
166 DicUserData::DicUserData(
168 bool bChecked
, bool bEditable
, bool bDeletable
)
170 DBG_ASSERT( nEID
< 65000, "Entry Id out of range" );
171 nVal
= (static_cast<sal_uInt32
>(0xFFFF & nEID
) << 16) |
172 (static_cast<sal_uInt32
>(bChecked
? 1 : 0) << 8) |
173 (static_cast<sal_uInt32
>(bEditable
? 1 : 0) << 9) |
174 (static_cast<sal_uInt32
>(bDeletable
? 1 : 0) << 10);
177 /*--------------------------------------------------
178 Entry IDs for options listbox of dialog
179 --------------------------------------------------*/
188 EID_WORDS_WITH_DIGITS
,
195 EID_SPELL_CLOSED_COMPOUND
,
196 EID_SPELL_HYPHENATED_COMPOUND
201 static const OUString
& lcl_GetPropertyName( EID_OPTIONS eEntryId
)
205 case EID_SPELL_AUTO
: return UPN_IS_SPELL_AUTO
;
206 case EID_GRAMMAR_AUTO
: return UPN_IS_GRAMMAR_AUTO
;
207 case EID_CAPITAL_WORDS
: return UPN_IS_SPELL_UPPER_CASE
;
208 case EID_SPELL_CLOSED_COMPOUND
: return UPN_IS_SPELL_CLOSED_COMPOUND
;
209 case EID_SPELL_HYPHENATED_COMPOUND
: return UPN_IS_SPELL_HYPHENATED_COMPOUND
;
210 case EID_WORDS_WITH_DIGITS
: return UPN_IS_SPELL_WITH_DIGITS
;
211 case EID_SPELL_SPECIAL
: return UPN_IS_SPELL_SPECIAL
;
212 case EID_NUM_MIN_WORDLEN
: return UPN_HYPH_MIN_WORD_LENGTH
;
213 case EID_NUM_PRE_BREAK
: return UPN_HYPH_MIN_LEADING
;
214 case EID_NUM_POST_BREAK
: return UPN_HYPH_MIN_TRAILING
;
215 case EID_HYPH_AUTO
: return UPN_IS_HYPH_AUTO
;
216 case EID_HYPH_SPECIAL
: return UPN_IS_HYPH_SPECIAL
;
217 default: assert (false); abort();
223 class OptionsBreakSet
: public weld::GenericDialogController
225 std::unique_ptr
<weld::Widget
> m_xBeforeFrame
;
226 std::unique_ptr
<weld::Widget
> m_xAfterFrame
;
227 std::unique_ptr
<weld::Widget
> m_xMinimalFrame
;
228 std::unique_ptr
<weld::SpinButton
> m_xBreakNF
;
231 OptionsBreakSet(weld::Window
* pParent
, sal_uInt16 nRID
)
232 : GenericDialogController(pParent
, u
"cui/ui/breaknumberoption.ui"_ustr
, u
"BreakNumberOption"_ustr
)
233 , m_xBeforeFrame(m_xBuilder
->weld_widget(u
"beforeframe"_ustr
))
234 , m_xAfterFrame(m_xBuilder
->weld_widget(u
"afterframe"_ustr
))
235 , m_xMinimalFrame(m_xBuilder
->weld_widget(u
"miniframe"_ustr
))
237 assert(EID_NUM_PRE_BREAK
== nRID
|| EID_NUM_POST_BREAK
== nRID
|| EID_NUM_MIN_WORDLEN
== nRID
); //unexpected ID
239 if (nRID
== EID_NUM_PRE_BREAK
)
241 m_xBeforeFrame
->show();
242 m_xBreakNF
= m_xBuilder
->weld_spin_button(u
"beforebreak"_ustr
);
244 else if(nRID
== EID_NUM_POST_BREAK
)
246 m_xAfterFrame
->show();
247 m_xBreakNF
= m_xBuilder
->weld_spin_button(u
"afterbreak"_ustr
);
249 else if(nRID
== EID_NUM_MIN_WORDLEN
)
251 m_xMinimalFrame
->show();
252 m_xBreakNF
= m_xBuilder
->weld_spin_button(u
"wordlength"_ustr
);
256 weld::SpinButton
& GetNumericFld()
262 // class OptionsUserData -------------------------------------------------
264 class OptionsUserData
269 explicit OptionsUserData( sal_uInt32 nUserData
) : nVal( nUserData
) {}
270 OptionsUserData( sal_uInt16 nEID
,
271 bool bHasNV
, sal_uInt16 nNumVal
,
272 bool bCheckable
, bool bChecked
);
274 sal_uInt32
GetUserData() const { return nVal
; }
275 sal_uInt16
GetEntryId() const { return static_cast<sal_uInt16
>(nVal
>> 16); }
276 bool HasNumericValue() const { return static_cast<bool>((nVal
>> 10) & 0x01); }
277 sal_uInt16
GetNumericValue() const { return static_cast<sal_uInt16
>(nVal
& 0xFF); }
278 bool IsCheckable() const { return static_cast<bool>((nVal
>> 9) & 0x01); }
279 bool IsModified() const { return static_cast<bool>((nVal
>> 11) & 0x01); }
281 void SetNumericValue( sal_uInt8 nNumVal
);
286 OptionsUserData::OptionsUserData( sal_uInt16 nEID
,
287 bool bHasNV
, sal_uInt16 nNumVal
,
288 bool bCheckable
, bool bChecked
)
290 DBG_ASSERT( nEID
< 65000, "Entry Id out of range" );
291 DBG_ASSERT( nNumVal
< 256, "value out of range" );
292 nVal
= (static_cast<sal_uInt32
>(0xFFFF & nEID
) << 16) |
293 (static_cast<sal_uInt32
>(bHasNV
? 1 : 0) << 10) |
294 (static_cast<sal_uInt32
>(bCheckable
? 1 : 0) << 9) |
295 (static_cast<sal_uInt32
>(bChecked
? 1 : 0) << 8) |
296 static_cast<sal_uInt32
>(0xFF & nNumVal
);
299 void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal
)
301 if (HasNumericValue() && (GetNumericValue() != nNumVal
))
305 nVal
|= sal_uInt32(1) << 11; // mark as modified
309 // ServiceInfo_Impl ----------------------------------------------------
313 struct ServiceInfo_Impl
315 OUString sDisplayName
;
316 OUString sSpellImplName
;
317 OUString sHyphImplName
;
318 OUString sThesImplName
;
319 OUString sGrammarImplName
;
320 uno::Reference
< XSpellChecker
> xSpell
;
321 uno::Reference
< XHyphenator
> xHyph
;
322 uno::Reference
< XThesaurus
> xThes
;
323 uno::Reference
< XProofreader
> xGrammar
;
326 ServiceInfo_Impl() : bConfigured(false) {}
331 bool operator()(const css::lang::Locale
& lhs
, const css::lang::Locale
& rhs
) const
333 if (lhs
.Language
< rhs
.Language
)
335 if (lhs
.Language
> rhs
.Language
)
337 if (lhs
.Country
< rhs
.Country
)
339 if (lhs
.Country
> rhs
.Country
)
341 return lhs
.Variant
< rhs
.Variant
;
347 typedef std::vector
< ServiceInfo_Impl
> ServiceInfoArr
;
348 typedef std::map
< LanguageType
, Sequence
< OUString
> > LangImplNameTable
;
351 // SvxLinguData_Impl ----------------------------------------------------
353 class SvxLinguData_Impl
355 //contains services and implementation names sorted by implementation names
356 ServiceInfoArr aDisplayServiceArr
;
357 sal_uInt32 nDisplayServices
;
359 std::set
<Locale
, Locale_less
> aAllServiceLocales
;
360 LangImplNameTable aCfgSpellTable
;
361 LangImplNameTable aCfgHyphTable
;
362 LangImplNameTable aCfgThesTable
;
363 LangImplNameTable aCfgGrammarTable
;
364 uno::Reference
< XLinguServiceManager2
> xLinguSrvcMgr
;
367 static bool AddRemove( Sequence
< OUString
> &rConfigured
,
368 const OUString
&rImplName
, bool bAdd
);
373 uno::Reference
<XLinguServiceManager2
> & GetManager() { return xLinguSrvcMgr
; }
375 void SetChecked( const Sequence
< OUString
> &rConfiguredServices
);
376 void Reconfigure( std::u16string_view rDisplayName
, bool bEnable
);
378 const auto& GetAllSupportedLocales() const { return aAllServiceLocales
; }
380 LangImplNameTable
& GetSpellTable() { return aCfgSpellTable
; }
381 LangImplNameTable
& GetHyphTable() { return aCfgHyphTable
; }
382 LangImplNameTable
& GetThesTable() { return aCfgThesTable
; }
383 LangImplNameTable
& GetGrammarTable() { return aCfgGrammarTable
; }
385 ServiceInfoArr
& GetDisplayServiceArray() { return aDisplayServiceArr
; }
387 const sal_uInt32
& GetDisplayServiceCount() const { return nDisplayServices
; }
388 void SetDisplayServiceCount( sal_uInt32 nVal
) { nDisplayServices
= nVal
; }
390 // returns the list of service implementation names for the specified
391 // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in
392 // the proper order for the SvxEditModulesDlg (the ones from the
393 // configuration (keeping that order!) first and then the other ones.
394 // I.e. the ones available but not configured in arbitrary order).
395 // They available ones may contain names that do not(!) support that
397 Sequence
< OUString
> GetSortedImplNames( LanguageType nLang
, sal_uInt8 nType
);
399 ServiceInfo_Impl
* GetInfoByImplName( std::u16string_view rSvcImplName
);
403 Sequence
< OUString
> SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang
, sal_uInt8 nType
)
405 LangImplNameTable
*pTable
= nullptr;
408 case TYPE_SPELL
: pTable
= &aCfgSpellTable
; break;
409 case TYPE_HYPH
: pTable
= &aCfgHyphTable
; break;
410 case TYPE_THES
: pTable
= &aCfgThesTable
; break;
411 case TYPE_GRAMMAR
: pTable
= &aCfgGrammarTable
; break;
413 Sequence
< OUString
> aRes
;
416 SAL_WARN( "cui.options", "unknown linguistic type" );
419 if (pTable
->count( nLang
))
420 aRes
= (*pTable
)[ nLang
]; // add configured services
421 sal_Int32 nIdx
= aRes
.getLength();
422 DBG_ASSERT( nDisplayServices
>= o3tl::make_unsigned(nIdx
), "size mismatch" );
423 aRes
.realloc( nDisplayServices
);
424 OUString
*pRes
= aRes
.getArray();
426 // add not configured services
427 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
429 const ServiceInfo_Impl
&rInfo
= aDisplayServiceArr
[ i
];
433 case TYPE_SPELL
: aImplName
= rInfo
.sSpellImplName
; break;
434 case TYPE_HYPH
: aImplName
= rInfo
.sHyphImplName
; break;
435 case TYPE_THES
: aImplName
= rInfo
.sThesImplName
; break;
436 case TYPE_GRAMMAR
: aImplName
= rInfo
.sGrammarImplName
; break;
439 if (!aImplName
.isEmpty() && (lcl_SeqGetEntryPos( aRes
, aImplName
) == -1)) // name not yet added
441 DBG_ASSERT( nIdx
< aRes
.getLength(), "index out of range" );
442 if (nIdx
< aRes
.getLength())
443 pRes
[ nIdx
++ ] = aImplName
;
446 // don't forget to put aRes back to its actual size just in case you allocated too much
447 // since all of the names may have already been added
448 // otherwise you get duplicate entries in the edit dialog
449 aRes
.realloc( nIdx
);
454 ServiceInfo_Impl
* SvxLinguData_Impl::GetInfoByImplName( std::u16string_view rSvcImplName
)
456 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
458 ServiceInfo_Impl
&rTmp
= aDisplayServiceArr
[ i
];
459 if (rTmp
.sSpellImplName
== rSvcImplName
||
460 rTmp
.sHyphImplName
== rSvcImplName
||
461 rTmp
.sThesImplName
== rSvcImplName
||
462 rTmp
.sGrammarImplName
== rSvcImplName
)
470 static void lcl_MergeDisplayArray(
471 SvxLinguData_Impl
&rData
,
472 const ServiceInfo_Impl
&rToAdd
)
476 ServiceInfoArr
&rSvcInfoArr
= rData
.GetDisplayServiceArray();
477 sal_uInt32 nEntries
= rData
.GetDisplayServiceCount();
479 for (sal_uInt32 i
= 0; i
< nEntries
; ++i
)
481 ServiceInfo_Impl
& rEntry
= rSvcInfoArr
[i
];
482 if (rEntry
.sDisplayName
== rToAdd
.sDisplayName
)
484 if(rToAdd
.xSpell
.is())
486 DBG_ASSERT( !rEntry
.xSpell
.is() &&
487 rEntry
.sSpellImplName
.isEmpty(),
489 rEntry
.sSpellImplName
= rToAdd
.sSpellImplName
;
490 rEntry
.xSpell
= rToAdd
.xSpell
;
492 if(rToAdd
.xGrammar
.is())
494 DBG_ASSERT( !rEntry
.xGrammar
.is() &&
495 rEntry
.sGrammarImplName
.isEmpty(),
497 rEntry
.sGrammarImplName
= rToAdd
.sGrammarImplName
;
498 rEntry
.xGrammar
= rToAdd
.xGrammar
;
500 if(rToAdd
.xHyph
.is())
502 DBG_ASSERT( !rEntry
.xHyph
.is() &&
503 rEntry
.sHyphImplName
.isEmpty(),
505 rEntry
.sHyphImplName
= rToAdd
.sHyphImplName
;
506 rEntry
.xHyph
= rToAdd
.xHyph
;
508 if(rToAdd
.xThes
.is())
510 DBG_ASSERT( !rEntry
.xThes
.is() &&
511 rEntry
.sThesImplName
.isEmpty(),
513 rEntry
.sThesImplName
= rToAdd
.sThesImplName
;
514 rEntry
.xThes
= rToAdd
.xThes
;
520 rData
.GetDisplayServiceArray().push_back( rToAdd
);
521 rData
.SetDisplayServiceCount( nCnt
+ 1 );
524 SvxLinguData_Impl::SvxLinguData_Impl() :
527 const uno::Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
528 xLinguSrvcMgr
= LinguServiceManager::create(xContext
);
530 const Locale
& rCurrentLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
533 Any(LinguMgr::GetLinguPropertySet()),
534 Any() // second argument has to be empty!
538 const Sequence
< OUString
> aSpellNames
= xLinguSrvcMgr
->getAvailableServices(
541 for(const OUString
& spellName
: aSpellNames
)
543 ServiceInfo_Impl aInfo
;
544 aInfo
.sSpellImplName
= spellName
;
546 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sSpellImplName
, aArgs
, xContext
), UNO_QUERY
);
548 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xSpell
, UNO_QUERY
);
550 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
552 const Sequence
< Locale
> aLocales( aInfo
.xSpell
->getLocales() );
553 //! suppress display of entries with no supported languages (see feature 110994)
554 if (aLocales
.hasElements())
556 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
557 lcl_MergeDisplayArray( *this, aInfo
);
561 //read grammar checker
562 const Sequence
< OUString
> aGrammarNames
= xLinguSrvcMgr
->getAvailableServices(
563 cGrammar
, Locale() );
564 for(const OUString
& grammarName
: aGrammarNames
)
566 ServiceInfo_Impl aInfo
;
567 aInfo
.sGrammarImplName
= grammarName
;
569 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sGrammarImplName
, aArgs
, xContext
), UNO_QUERY
);
571 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xGrammar
, UNO_QUERY
);
573 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
575 const Sequence
< Locale
> aLocales( aInfo
.xGrammar
->getLocales() );
576 //! suppress display of entries with no supported languages (see feature 110994)
577 if (aLocales
.hasElements())
579 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
580 lcl_MergeDisplayArray( *this, aInfo
);
585 const Sequence
< OUString
> aHyphNames
= xLinguSrvcMgr
->getAvailableServices(
587 for(const OUString
& hyphName
: aHyphNames
)
589 ServiceInfo_Impl aInfo
;
590 aInfo
.sHyphImplName
= hyphName
;
591 aInfo
.xHyph
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sHyphImplName
, aArgs
, xContext
), UNO_QUERY
);
593 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xHyph
, UNO_QUERY
);
595 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
597 const Sequence
< Locale
> aLocales( aInfo
.xHyph
->getLocales() );
598 //! suppress display of entries with no supported languages (see feature 110994)
599 if (aLocales
.hasElements())
601 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
602 lcl_MergeDisplayArray( *this, aInfo
);
607 const Sequence
< OUString
> aThesNames
= xLinguSrvcMgr
->getAvailableServices(
609 for(const OUString
& thesName
: aThesNames
)
611 ServiceInfo_Impl aInfo
;
612 aInfo
.sThesImplName
= thesName
;
613 aInfo
.xThes
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sThesImplName
, aArgs
, xContext
), UNO_QUERY
);
615 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xThes
, UNO_QUERY
);
617 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
619 const Sequence
< Locale
> aLocales( aInfo
.xThes
->getLocales() );
620 //! suppress display of entries with no supported languages (see feature 110994)
621 if (aLocales
.hasElements())
623 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
624 lcl_MergeDisplayArray( *this, aInfo
);
628 Sequence
< OUString
> aCfgSvcs
;
629 for (auto const& locale
: aAllServiceLocales
)
631 LanguageType nLang
= LanguageTag::convertToLanguageType( locale
);
633 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cSpell
, locale
);
634 SetChecked( aCfgSvcs
);
635 if (aCfgSvcs
.hasElements())
636 aCfgSpellTable
[ nLang
] = aCfgSvcs
;
638 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cGrammar
, locale
);
639 SetChecked( aCfgSvcs
);
640 if (aCfgSvcs
.hasElements())
641 aCfgGrammarTable
[ nLang
] = aCfgSvcs
;
643 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cHyph
, locale
);
644 SetChecked( aCfgSvcs
);
645 if (aCfgSvcs
.hasElements())
646 aCfgHyphTable
[ nLang
] = aCfgSvcs
;
648 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cThes
, locale
);
649 SetChecked( aCfgSvcs
);
650 if (aCfgSvcs
.hasElements())
651 aCfgThesTable
[ nLang
] = aCfgSvcs
;
655 void SvxLinguData_Impl::SetChecked(const Sequence
<OUString
>& rConfiguredServices
)
657 for(OUString
const & configService
: rConfiguredServices
)
659 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
661 ServiceInfo_Impl
& rEntry
= aDisplayServiceArr
[i
];
662 if (!rEntry
.bConfigured
)
664 const OUString
&rSrvcImplName
= configService
;
665 if (!rSrvcImplName
.isEmpty() &&
666 (rEntry
.sSpellImplName
== rSrvcImplName
||
667 rEntry
.sGrammarImplName
== rSrvcImplName
||
668 rEntry
.sHyphImplName
== rSrvcImplName
||
669 rEntry
.sThesImplName
== rSrvcImplName
))
671 rEntry
.bConfigured
= true;
679 bool SvxLinguData_Impl::AddRemove(
680 Sequence
< OUString
> &rConfigured
,
681 const OUString
&rImplName
, bool bAdd
)
683 bool bRet
= false; // modified?
685 sal_Int32 nEntries
= rConfigured
.getLength();
686 sal_Int32 nPos
= lcl_SeqGetEntryPos(rConfigured
, rImplName
);
687 if (bAdd
&& nPos
< 0) // add new entry
689 rConfigured
.realloc( ++nEntries
);
690 OUString
*pConfigured
= rConfigured
.getArray();
691 pConfigured
[nEntries
- 1] = rImplName
;
694 else if (!bAdd
&& nPos
>= 0) // remove existing entry
696 OUString
*pConfigured
= rConfigured
.getArray();
697 for (sal_Int32 i
= nPos
; i
< nEntries
- 1; ++i
)
698 pConfigured
[i
] = pConfigured
[i
+ 1];
699 rConfigured
.realloc(--nEntries
);
707 void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName
, bool bEnable
)
709 DBG_ASSERT( !rDisplayName
.empty(), "empty DisplayName" );
711 ServiceInfo_Impl
*pInfo
= nullptr;
712 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
714 ServiceInfo_Impl
& rTmp
= aDisplayServiceArr
[i
];
715 if (rTmp
.sDisplayName
== rDisplayName
)
721 DBG_ASSERT( pInfo
, "DisplayName entry not found" );
725 pInfo
->bConfigured
= bEnable
;
727 // update configured spellchecker entries
728 if (pInfo
->xSpell
.is())
730 for (auto& locale
: pInfo
->xSpell
->getLocales())
732 LanguageType nLang
= LanguageTag::convertToLanguageType(locale
);
733 if (!aCfgSpellTable
.count( nLang
) && bEnable
)
734 aCfgSpellTable
[ nLang
] = Sequence
< OUString
>();
735 if (aCfgSpellTable
.count( nLang
))
736 AddRemove( aCfgSpellTable
[ nLang
], pInfo
->sSpellImplName
, bEnable
);
740 // update configured grammar checker entries
741 if (pInfo
->xGrammar
.is())
743 for (auto& locale
: pInfo
->xGrammar
->getLocales())
745 LanguageType nLang
= LanguageTag::convertToLanguageType(locale
);
746 if (!aCfgGrammarTable
.count( nLang
) && bEnable
)
747 aCfgGrammarTable
[ nLang
] = Sequence
< OUString
>();
748 if (aCfgGrammarTable
.count( nLang
))
749 AddRemove( aCfgGrammarTable
[ nLang
], pInfo
->sGrammarImplName
, bEnable
);
753 // update configured hyphenator entries
754 if (pInfo
->xHyph
.is())
756 for (auto& locale
: pInfo
->xHyph
->getLocales())
758 LanguageType nLang
= LanguageTag::convertToLanguageType(locale
);
759 if (!aCfgHyphTable
.count( nLang
) && bEnable
)
760 aCfgHyphTable
[ nLang
] = Sequence
< OUString
>();
761 if (aCfgHyphTable
.count( nLang
))
762 AddRemove( aCfgHyphTable
[ nLang
], pInfo
->sHyphImplName
, bEnable
);
766 // update configured spellchecker entries
767 if (!pInfo
->xThes
.is())
770 for (auto& locale
: pInfo
->xThes
->getLocales())
772 LanguageType nLang
= LanguageTag::convertToLanguageType(locale
);
773 if (!aCfgThesTable
.count( nLang
) && bEnable
)
774 aCfgThesTable
[ nLang
] = Sequence
< OUString
>();
775 if (aCfgThesTable
.count( nLang
))
776 AddRemove( aCfgThesTable
[ nLang
], pInfo
->sThesImplName
, bEnable
);
781 // class SvxLinguTabPage -------------------------------------------------
783 SvxLinguTabPage::SvxLinguTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rSet
)
784 : SfxTabPage(pPage
, pController
, u
"cui/ui/optlingupage.ui"_ustr
, u
"OptLinguPage"_ustr
, &rSet
)
785 , sCapitalWords (CuiResId(RID_CUISTR_CAPITAL_WORDS
))
786 , sWordsWithDigits(CuiResId(RID_CUISTR_WORDS_WITH_DIGITS
))
787 , sSpellSpecial (CuiResId(RID_CUISTR_SPELL_SPECIAL
))
788 , sSpellAuto (CuiResId(RID_CUISTR_SPELL_AUTO
))
789 , sSpellClosedCompound (CuiResId(RID_CUISTR_SPELL_CLOSED_COMPOUND
))
790 , sSpellHyphenatedCompound (CuiResId(RID_CUISTR_SPELL_HYPHENATED_COMPOUND
))
791 , sGrammarAuto (CuiResId(RID_CUISTR_GRAMMAR_AUTO
))
792 , sNumMinWordlen (CuiResId(RID_CUISTR_NUM_MIN_WORDLEN
))
793 , sNumPreBreak (CuiResId(RID_CUISTR_NUM_PRE_BREAK
))
794 , sNumPostBreak (CuiResId(RID_CUISTR_NUM_POST_BREAK
))
795 , sHyphAuto (CuiResId(RID_CUISTR_HYPH_AUTO
))
796 , sHyphSpecial (CuiResId(RID_CUISTR_HYPH_SPECIAL
))
797 , nUPN_HYPH_MIN_WORD_LENGTH(-1)
798 , nUPN_HYPH_MIN_LEADING(-1)
799 , nUPN_HYPH_MIN_TRAILING(-1)
800 , m_nDlbClickEventId(nullptr)
801 , m_xLinguModulesFT(m_xBuilder
->weld_label(u
"lingumodulesft"_ustr
))
802 , m_xLinguModulesCLB(m_xBuilder
->weld_tree_view(u
"lingumodules"_ustr
))
803 , m_xLinguModulesEditPB(m_xBuilder
->weld_button(u
"lingumodulesedit"_ustr
))
804 , m_xLinguDicsFT(m_xBuilder
->weld_label(u
"lingudictsft"_ustr
))
805 , m_xLinguDicsCLB(m_xBuilder
->weld_tree_view(u
"lingudicts"_ustr
))
806 , m_xLinguDicsNewPB(m_xBuilder
->weld_button(u
"lingudictsnew"_ustr
))
807 , m_xLinguDicsEditPB(m_xBuilder
->weld_button(u
"lingudictsedit"_ustr
))
808 , m_xLinguDicsDelPB(m_xBuilder
->weld_button(u
"lingudictsdelete"_ustr
))
809 , m_xLinguOptionsCLB(m_xBuilder
->weld_tree_view(u
"linguoptions"_ustr
))
810 , m_xLinguOptionsEditPB(m_xBuilder
->weld_button(u
"linguoptionsedit"_ustr
))
811 , m_xMoreDictsBox(m_xBuilder
->weld_box(u
"moredictsbox"_ustr
))
812 , m_xMoreDictsLink(m_xBuilder
->weld_link_button(u
"moredictslink"_ustr
))
814 m_xLinguModulesCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
815 m_xLinguDicsCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
816 m_xLinguOptionsCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
818 m_xLinguModulesCLB
->connect_selection_changed(LINK(this, SvxLinguTabPage
, SelectHdl_Impl
));
819 m_xLinguModulesCLB
->connect_row_activated(LINK(this, SvxLinguTabPage
, BoxDoubleClickHdl_Impl
));
820 m_xLinguModulesCLB
->connect_toggled(LINK(this, SvxLinguTabPage
, ModulesBoxCheckButtonHdl_Impl
));
822 m_xLinguModulesEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
823 m_xLinguOptionsEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
825 m_xLinguDicsCLB
->connect_selection_changed(LINK(this, SvxLinguTabPage
, SelectHdl_Impl
));
826 m_xLinguDicsCLB
->connect_toggled(LINK(this, SvxLinguTabPage
, DicsBoxCheckButtonHdl_Impl
));
828 m_xLinguDicsNewPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
829 m_xLinguDicsEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
830 m_xLinguDicsDelPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
832 m_xLinguOptionsCLB
->connect_selection_changed(LINK(this, SvxLinguTabPage
, SelectHdl_Impl
));
833 m_xLinguOptionsCLB
->connect_row_activated(LINK(this, SvxLinguTabPage
, BoxDoubleClickHdl_Impl
));
835 m_xMoreDictsLink
->connect_activate_link(LINK(this, SvxLinguTabPage
, OnLinkClick
));
836 if (officecfg::Office::Security::Hyperlinks::Open::get() == SvtExtendedSecurityOptions::OPEN_NEVER
)
837 m_xMoreDictsBox
->hide();
839 if (comphelper::LibreOfficeKit::isActive())
841 // hide User-defined Dictionaries part
842 m_xBuilder
->weld_frame(u
"dictsframe"_ustr
)->hide();
843 // hide Get more dictionaries URL + icon
844 m_xMoreDictsBox
->hide();
847 xProp
= LinguMgr::GetLinguPropertySet();
848 xDicList
.set( LinguMgr::GetDictionaryList() );
851 // keep references to all **currently** available dictionaries,
852 // since the diclist may get changed meanwhile (e.g. through the API).
853 // We want the dialog to operate on the same set of dictionaries it
855 // Also we have to take care to not lose the last reference when
856 // someone else removes a dictionary from the list.
857 // removed dics will be replaced by NULL new entries be added to the end
858 // Thus we may use indices as consistent references.
859 aDics
= xDicList
->getDictionaries();
865 m_xLinguDicsFT
->set_sensitive(false);
866 m_xLinguDicsCLB
->set_sensitive(false);
867 m_xLinguDicsNewPB
->set_sensitive(false);
868 m_xLinguDicsEditPB
->set_sensitive(false);
869 m_xLinguDicsDelPB
->set_sensitive(false);
873 SvxLinguTabPage::~SvxLinguTabPage()
875 if (m_nDlbClickEventId
)
877 Application::RemoveUserEvent(m_nDlbClickEventId
);
878 m_nDlbClickEventId
= nullptr;
883 std::unique_ptr
<SfxTabPage
> SvxLinguTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
884 const SfxItemSet
* rAttrSet
)
886 return std::make_unique
<SvxLinguTabPage
>( pPage
, pController
, *rAttrSet
);
889 OUString
SvxLinguTabPage::GetAllStrings()
891 OUString sAllStrings
;
892 OUString labels
[] = { u
"lingumodulesft"_ustr
, u
"lingudictsft"_ustr
, u
"label4"_ustr
};
894 for (const auto& label
: labels
)
896 if (const auto pString
= m_xBuilder
->weld_label(label
))
897 sAllStrings
+= pString
->get_label() + " ";
900 sAllStrings
+= m_xMoreDictsLink
->get_label() + " ";
902 return sAllStrings
.replaceAll("_", "");
905 bool SvxLinguTabPage::FillItemSet( SfxItemSet
* rCoreSet
)
907 bool bModified
= true; // !!!!
909 // if not HideGroups was called with GROUP_MODULES...
910 if (m_xLinguModulesCLB
->get_visible())
912 DBG_ASSERT( pLinguData
, "pLinguData not yet initialized" );
914 pLinguData
.reset( new SvxLinguData_Impl
);
916 // update spellchecker configuration entries
917 const LangImplNameTable
*pTable
= &pLinguData
->GetSpellTable();
918 for (auto const& elem
: *pTable
)
920 LanguageType nLang
= elem
.first
;
921 const Sequence
< OUString
> aImplNames(elem
.second
);
922 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
923 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
925 xMgr
->setConfiguredServices( cSpell
, aLocale
, aImplNames
);
928 // update grammar checker configuration entries
929 pTable
= &pLinguData
->GetGrammarTable();
930 for (auto const& elem
: *pTable
)
932 LanguageType nLang
= elem
.first
;
933 const Sequence
< OUString
> aImplNames(elem
.second
);
934 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
935 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
937 xMgr
->setConfiguredServices( cGrammar
, aLocale
, aImplNames
);
940 // update hyphenator configuration entries
941 pTable
= &pLinguData
->GetHyphTable();
942 for (auto const& elem
: *pTable
)
944 LanguageType nLang
= elem
.first
;
945 const Sequence
< OUString
> aImplNames(elem
.second
);
946 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
947 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
949 xMgr
->setConfiguredServices( cHyph
, aLocale
, aImplNames
);
952 // update thesaurus configuration entries
953 pTable
= &pLinguData
->GetThesTable();
954 for (auto const& elem
: *pTable
)
956 LanguageType nLang
= elem
.first
;
957 const Sequence
< OUString
> aImplNames(elem
.second
);
958 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
959 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
961 xMgr
->setConfiguredServices( cThes
, aLocale
, aImplNames
);
966 // activate dictionaries according to checkbox state
968 Sequence
< OUString
> aActiveDics
;
969 sal_Int32 nActiveDics
= 0;
970 int nEntries
= m_xLinguDicsCLB
->n_children();
971 for (int i
= 0; i
< nEntries
; ++i
)
973 sal_Int32 nDics
= aDics
.getLength();
975 aActiveDics
.realloc( nDics
);
976 OUString
*pActiveDic
= aActiveDics
.getArray();
978 DicUserData
aData(m_xLinguDicsCLB
->get_id(i
).toUInt32());
979 if (aData
.GetEntryId() < nDics
)
981 bool bChecked
= m_xLinguDicsCLB
->get_toggle(i
) == TRISTATE_TRUE
;
982 uno::Reference
<XDictionary
> xDic(aDics
[i
]);
985 if (LinguMgr::GetIgnoreAllList() == xDic
)
987 xDic
->setActive( bChecked
);
989 pActiveDic
[nActiveDics
++] = xDic
->getName();
994 aActiveDics
.realloc( nActiveDics
);
996 aTmp
<<= aActiveDics
;
997 SvtLinguConfig aLngCfg
;
998 aLngCfg
.SetProperty( UPH_ACTIVE_DICTIONARIES
, aTmp
);
1001 nEntries
= m_xLinguOptionsCLB
->n_children();
1002 for (int j
= 0; j
< nEntries
; ++j
)
1004 OptionsUserData
aData(m_xLinguOptionsCLB
->get_id(j
).toUInt32());
1005 OUString
aPropName( lcl_GetPropertyName( static_cast<EID_OPTIONS
>(aData
.GetEntryId()) ) );
1008 if (aData
.IsCheckable())
1010 bool bChecked
= m_xLinguOptionsCLB
->get_toggle(j
) == TRISTATE_TRUE
;
1013 else if (aData
.HasNumericValue())
1015 sal_Int16 nVal
= aData
.GetNumericValue();
1020 xProp
->setPropertyValue( aPropName
, aAny
);
1021 aLngCfg
.SetProperty( aPropName
, aAny
);
1024 OptionsUserData
aPreBreakData(m_xLinguOptionsCLB
->get_id(EID_NUM_PRE_BREAK
).toUInt32());
1025 OptionsUserData
aPostBreakData(m_xLinguOptionsCLB
->get_id(EID_NUM_POST_BREAK
).toUInt32());
1026 if ( aPreBreakData
.IsModified() || aPostBreakData
.IsModified() )
1028 SfxHyphenRegionItem
aHyp( SID_ATTR_HYPHENREGION
);
1029 aHyp
.GetMinLead() = static_cast<sal_uInt8
>(aPreBreakData
.GetNumericValue());
1030 aHyp
.GetMinTrail() = static_cast<sal_uInt8
>(aPostBreakData
.GetNumericValue());
1031 rCoreSet
->Put( aHyp
);
1034 // automatic spell checking
1035 bool bNewAutoCheck
= m_xLinguOptionsCLB
->get_toggle(EID_SPELL_AUTO
) == TRISTATE_TRUE
;
1036 const SfxPoolItem
* pOld
= GetOldItem( *rCoreSet
, SID_AUTOSPELL_CHECK
);
1037 if ( !pOld
|| static_cast<const SfxBoolItem
*>(pOld
)->GetValue() != bNewAutoCheck
)
1039 rCoreSet
->Put( SfxBoolItem( SID_AUTOSPELL_CHECK
, bNewAutoCheck
) );
1046 sal_uInt32
SvxLinguTabPage::GetDicUserData( const uno::Reference
< XDictionary
> &rxDic
, sal_uInt16 nIdx
)
1048 sal_uInt32 nRes
= 0;
1049 DBG_ASSERT( rxDic
.is(), "dictionary not supplied" );
1052 uno::Reference
< frame::XStorable
> xStor( rxDic
, UNO_QUERY
);
1054 bool bChecked
= rxDic
->isActive();
1055 bool bEditable
= !xStor
.is() || !xStor
->isReadonly();
1056 bool bDeletable
= bEditable
;
1058 nRes
= DicUserData( nIdx
,
1059 bChecked
, bEditable
, bDeletable
).GetUserData();
1065 void SvxLinguTabPage::AddDicBoxEntry(
1066 const uno::Reference
< XDictionary
> &rxDic
,
1069 m_xLinguDicsCLB
->freeze();
1071 OUString
aTxt( ::GetDicInfoStr( rxDic
->getName(),
1072 LanguageTag( rxDic
->getLocale() ).getLanguageType(),
1073 DictionaryType_NEGATIVE
== rxDic
->getDictionaryType() ) );
1074 m_xLinguDicsCLB
->append(); // append at end
1075 int nEntry
= m_xLinguDicsCLB
->n_children() - 1;
1076 DicUserData
aData( GetDicUserData( rxDic
, nIdx
) );
1077 m_xLinguDicsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1078 m_xLinguDicsCLB
->set_toggle(nEntry
, aData
.IsChecked() ? TRISTATE_TRUE
: TRISTATE_FALSE
);
1079 m_xLinguDicsCLB
->set_text(nEntry
, aTxt
, 0); // append at end
1081 m_xLinguDicsCLB
->thaw();
1084 void SvxLinguTabPage::UpdateDicBox_Impl()
1086 m_xLinguDicsCLB
->freeze();
1087 m_xLinguDicsCLB
->clear();
1089 for (sal_Int32 i
= 0; i
< aDics
.getLength(); ++i
)
1091 const uno::Reference
<XDictionary
>& rDic
= aDics
[i
];
1093 AddDicBoxEntry( rDic
, static_cast<sal_uInt16
>(i
) );
1096 m_xLinguDicsCLB
->thaw();
1097 if (m_xLinguDicsCLB
->n_children())
1099 m_xLinguDicsCLB
->select(0);
1100 SelectHdl_Impl(*m_xLinguDicsCLB
);
1104 void SvxLinguTabPage::UpdateModulesBox_Impl()
1109 const ServiceInfoArr
&rAllDispSrvcArr
= pLinguData
->GetDisplayServiceArray();
1110 const sal_uInt32 nDispSrvcCount
= pLinguData
->GetDisplayServiceCount();
1112 m_xLinguModulesCLB
->clear();
1114 for (sal_uInt32 i
= 0; i
< nDispSrvcCount
; ++i
)
1116 const ServiceInfo_Impl
&rInfo
= rAllDispSrvcArr
[i
];
1117 m_xLinguModulesCLB
->append();
1118 m_xLinguModulesCLB
->set_id(i
, weld::toId(&rInfo
));
1119 m_xLinguModulesCLB
->set_toggle(i
, rInfo
.bConfigured
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1120 m_xLinguModulesCLB
->set_text(i
, rInfo
.sDisplayName
, 0);
1124 m_xLinguModulesCLB
->select(0);
1125 SelectHdl_Impl(*m_xLinguModulesCLB
);
1127 m_xLinguModulesEditPB
->set_sensitive( nDispSrvcCount
> 0 );
1130 void SvxLinguTabPage::Reset( const SfxItemSet
* rSet
)
1132 // if not HideGroups was called with GROUP_MODULES...
1133 if (m_xLinguModulesCLB
->get_visible())
1136 pLinguData
.reset( new SvxLinguData_Impl
);
1137 UpdateModulesBox_Impl();
1141 // get data from configuration
1142 SvtLinguConfig aLngCfg
;
1144 m_xLinguOptionsCLB
->freeze();
1145 m_xLinguOptionsCLB
->clear();
1149 sal_uInt32 nUserData
= 0;
1151 m_xLinguOptionsCLB
->append();
1154 aLngCfg
.GetProperty( UPN_IS_SPELL_AUTO
) >>= bVal
;
1155 const SfxPoolItem
* pItem
= GetItem( *rSet
, SID_AUTOSPELL_CHECK
);
1157 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1158 nUserData
= OptionsUserData( EID_SPELL_AUTO
, false, 0, true, bVal
).GetUserData();
1159 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1160 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellAuto
, 0);
1161 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1162 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_SPELL_AUTO
));
1164 m_xLinguOptionsCLB
->append();
1167 aLngCfg
.GetProperty( UPN_IS_GRAMMAR_AUTO
) >>= bVal
;
1168 nUserData
= OptionsUserData( EID_GRAMMAR_AUTO
, false, 0, true, bVal
).GetUserData();
1169 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1170 m_xLinguOptionsCLB
->set_text(nEntry
, sGrammarAuto
, 0);
1171 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1172 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_GRAMMAR_AUTO
));
1174 m_xLinguOptionsCLB
->append();
1177 aLngCfg
.GetProperty( UPN_IS_SPELL_UPPER_CASE
) >>= bVal
;
1178 nUserData
= OptionsUserData( EID_CAPITAL_WORDS
, false, 0, true, bVal
).GetUserData();
1179 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1180 m_xLinguOptionsCLB
->set_text(nEntry
, sCapitalWords
, 0);
1181 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1182 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_SPELL_UPPER_CASE
));
1184 m_xLinguOptionsCLB
->append();
1187 aLngCfg
.GetProperty( UPN_IS_SPELL_WITH_DIGITS
) >>= bVal
;
1188 nUserData
= OptionsUserData( EID_WORDS_WITH_DIGITS
, false, 0, true, bVal
).GetUserData();
1189 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1190 m_xLinguOptionsCLB
->set_text(nEntry
, sWordsWithDigits
, 0);
1191 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1192 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_SPELL_WITH_DIGITS
));
1194 m_xLinguOptionsCLB
->append();
1197 aLngCfg
.GetProperty( UPN_IS_SPELL_CLOSED_COMPOUND
) >>= bVal
;
1198 nUserData
= OptionsUserData( EID_SPELL_CLOSED_COMPOUND
, false, 0, true, bVal
).GetUserData();
1199 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1200 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellClosedCompound
, 0);
1201 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1202 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_SPELL_CLOSED_COMPOUND
));
1204 m_xLinguOptionsCLB
->append();
1207 aLngCfg
.GetProperty( UPN_IS_SPELL_HYPHENATED_COMPOUND
) >>= bVal
;
1208 nUserData
= OptionsUserData( EID_SPELL_HYPHENATED_COMPOUND
, false, 0, true, bVal
).GetUserData();
1209 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1210 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellHyphenatedCompound
, 0);
1211 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1212 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_SPELL_HYPHENATED_COMPOUND
));
1214 m_xLinguOptionsCLB
->append();
1217 aLngCfg
.GetProperty( UPN_IS_SPELL_SPECIAL
) >>= bVal
;
1218 nUserData
= OptionsUserData( EID_SPELL_SPECIAL
, false, 0, true, bVal
).GetUserData();
1219 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1220 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellSpecial
, 0);
1221 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1222 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_SPELL_SPECIAL
));
1224 m_xLinguOptionsCLB
->append();
1227 aLngCfg
.GetProperty( UPN_HYPH_MIN_WORD_LENGTH
) >>= nVal
;
1228 nUserData
= OptionsUserData( EID_NUM_MIN_WORDLEN
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1229 m_xLinguOptionsCLB
->set_text(nEntry
, sNumMinWordlen
+ " " + OUString::number(nVal
), 0);
1230 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1231 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_HYPH_MIN_WORD_LENGTH
));
1232 nUPN_HYPH_MIN_WORD_LENGTH
= nEntry
;
1234 const SfxHyphenRegionItem
*pHyp
= nullptr;
1235 if ( rSet
->GetItemState( SID_ATTR_HYPHENREGION
, false ) == SfxItemState::SET
)
1236 pHyp
= & rSet
->Get( SID_ATTR_HYPHENREGION
);
1238 m_xLinguOptionsCLB
->append();
1241 aLngCfg
.GetProperty( UPN_HYPH_MIN_LEADING
) >>= nVal
;
1243 nVal
= static_cast<sal_Int16
>(pHyp
->GetMinLead());
1244 nUserData
= OptionsUserData( EID_NUM_PRE_BREAK
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1245 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPreBreak
+ " " + OUString::number(nVal
), 0);
1246 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1247 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_HYPH_MIN_LEADING
));
1248 nUPN_HYPH_MIN_LEADING
= nEntry
;
1250 m_xLinguOptionsCLB
->append();
1253 aLngCfg
.GetProperty( UPN_HYPH_MIN_TRAILING
) >>= nVal
;
1255 nVal
= static_cast<sal_Int16
>(pHyp
->GetMinTrail());
1256 nUserData
= OptionsUserData( EID_NUM_POST_BREAK
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1257 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPostBreak
+ " " + OUString::number(nVal
), 0);
1258 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1259 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_HYPH_MIN_TRAILING
));
1260 nUPN_HYPH_MIN_TRAILING
= nEntry
;
1262 m_xLinguOptionsCLB
->append();
1265 aLngCfg
.GetProperty( UPN_IS_HYPH_AUTO
) >>= bVal
;
1266 nUserData
= OptionsUserData( EID_HYPH_AUTO
, false, 0, true, bVal
).GetUserData();
1267 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1268 m_xLinguOptionsCLB
->set_text(nEntry
, sHyphAuto
, 0);
1269 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1270 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_HYPH_AUTO
));
1272 m_xLinguOptionsCLB
->append();
1275 aLngCfg
.GetProperty( UPN_IS_HYPH_SPECIAL
) >>= bVal
;
1276 nUserData
= OptionsUserData( EID_HYPH_SPECIAL
, false, 0, true, bVal
).GetUserData();
1277 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1278 m_xLinguOptionsCLB
->set_text(nEntry
, sHyphSpecial
, 0);
1279 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1280 m_xLinguOptionsCLB
->set_sensitive(nEntry
, !aLngCfg
.IsReadOnly(UPN_IS_HYPH_SPECIAL
));
1282 m_xLinguOptionsCLB
->thaw();
1284 m_xLinguOptionsCLB
->select(0);
1285 SelectHdl_Impl(*m_xLinguOptionsCLB
);
1287 m_xLinguModulesCLB
->set_size_request(m_xLinguModulesCLB
->get_preferred_size().Width(),
1288 m_xLinguModulesCLB
->get_height_rows(3));
1289 m_xLinguDicsCLB
->set_size_request(m_xLinguDicsCLB
->get_preferred_size().Width(),
1290 m_xLinguDicsCLB
->get_height_rows(5));
1291 m_xLinguOptionsCLB
->set_size_request(m_xLinguOptionsCLB
->get_preferred_size().Width(),
1292 m_xLinguOptionsCLB
->get_height_rows(5));
1294 if (officecfg::Office::Linguistic::General::DictionaryList::ActiveDictionaries::isReadOnly())
1296 m_xLinguDicsFT
->set_sensitive(false);
1297 m_xLinguDicsCLB
->set_sensitive(false);
1298 m_xLinguDicsNewPB
->set_sensitive(false);
1299 m_xLinguDicsEditPB
->set_sensitive(false);
1300 m_xLinguDicsDelPB
->set_sensitive(false);
1304 IMPL_LINK(SvxLinguTabPage
, BoxDoubleClickHdl_Impl
, weld::TreeView
&, rBox
, bool)
1306 if (&rBox
== m_xLinguModulesCLB
.get() && !m_nDlbClickEventId
)
1308 //! in order to avoid a bug causing a GPF when double clicking
1309 //! on a module entry and exiting the "Edit Modules" dialog
1311 m_nDlbClickEventId
= Application::PostUserEvent(LINK(this, SvxLinguTabPage
, PostDblClickHdl_Impl
));
1313 else if (&rBox
== m_xLinguOptionsCLB
.get())
1315 ClickHdl_Impl(*m_xLinguOptionsEditPB
);
1320 IMPL_LINK_NOARG(SvxLinguTabPage
, PostDblClickHdl_Impl
, void*, void)
1322 m_nDlbClickEventId
= nullptr;
1323 ClickHdl_Impl(*m_xLinguModulesEditPB
);
1326 IMPL_LINK(SvxLinguTabPage
, ModulesBoxCheckButtonHdl_Impl
, const weld::TreeView::iter_col
&, rRowCol
, void)
1330 pLinguData
->Reconfigure(m_xLinguModulesCLB
->get_text(rRowCol
.first
),
1331 m_xLinguModulesCLB
->get_toggle(rRowCol
.first
) == TRISTATE_TRUE
);
1334 IMPL_LINK(SvxLinguTabPage
, DicsBoxCheckButtonHdl_Impl
, const weld::TreeView::iter_col
&, rRowCol
, void)
1336 const uno::Reference
<XDictionary
> &rDic
= aDics
[m_xLinguDicsCLB
->get_iter_index_in_parent(rRowCol
.first
)];
1337 if (LinguMgr::GetIgnoreAllList() == rDic
)
1338 m_xLinguDicsCLB
->set_toggle(rRowCol
.first
, TRISTATE_TRUE
);
1341 IMPL_LINK(SvxLinguTabPage
, ClickHdl_Impl
, weld::Button
&, rBtn
, void)
1343 if (m_xLinguModulesEditPB
.get() == &rBtn
)
1346 pLinguData
.reset( new SvxLinguData_Impl
);
1348 SvxLinguData_Impl
aOldLinguData(*pLinguData
);
1349 SvxEditModulesDlg
aDlg(GetFrameWeld(), *pLinguData
);
1350 if (aDlg
.run() != RET_OK
)
1351 *pLinguData
= std::move(aOldLinguData
);
1353 // evaluate new status of 'bConfigured' flag
1354 sal_uInt32 nLen
= pLinguData
->GetDisplayServiceCount();
1355 for (sal_uInt32 i
= 0; i
< nLen
; ++i
)
1356 pLinguData
->GetDisplayServiceArray()[i
].bConfigured
= false;
1357 for (const auto& locale
: pLinguData
->GetAllSupportedLocales())
1359 LanguageType nLang
= LanguageTag::convertToLanguageType(locale
);
1360 if (pLinguData
->GetSpellTable().count( nLang
))
1361 pLinguData
->SetChecked( pLinguData
->GetSpellTable()[ nLang
] );
1362 if (pLinguData
->GetGrammarTable().count( nLang
))
1363 pLinguData
->SetChecked( pLinguData
->GetGrammarTable()[ nLang
] );
1364 if (pLinguData
->GetHyphTable().count( nLang
))
1365 pLinguData
->SetChecked( pLinguData
->GetHyphTable()[ nLang
] );
1366 if (pLinguData
->GetThesTable().count( nLang
))
1367 pLinguData
->SetChecked( pLinguData
->GetThesTable()[ nLang
] );
1370 // show new status of modules
1371 UpdateModulesBox_Impl();
1373 else if (m_xLinguDicsNewPB
.get() == &rBtn
)
1375 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1376 ScopedVclPtr
<AbstractSvxNewDictionaryDialog
> aDlg(pFact
->CreateSvxNewDictionaryDialog(GetFrameWeld()));
1377 uno::Reference
< XDictionary
> xNewDic
;
1378 if ( aDlg
->Execute() == RET_OK
)
1379 xNewDic
= aDlg
->GetNewDictionary();
1382 // add new dics to the end
1383 sal_Int32 nLen
= aDics
.getLength();
1384 aDics
.realloc( nLen
+ 1 );
1386 aDics
.getArray()[ nLen
] = xNewDic
;
1388 AddDicBoxEntry( xNewDic
, static_cast<sal_uInt16
>(nLen
) );
1391 else if (m_xLinguDicsEditPB
.get() == &rBtn
)
1393 int nEntry
= m_xLinguDicsCLB
->get_selected_index();
1396 DicUserData
aData(m_xLinguDicsCLB
->get_id(nEntry
).toUInt32());
1397 sal_uInt16 nDicPos
= aData
.GetEntryId();
1398 sal_Int32 nDics
= aDics
.getLength();
1399 if (nDicPos
< nDics
)
1401 uno::Reference
<XDictionary
> xDic
= aDics
[nDicPos
];
1404 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1405 ScopedVclPtr
<VclAbstractDialog
> aDlg(pFact
->CreateSvxEditDictionaryDialog(GetFrameWeld(), xDic
->getName()));
1411 else if (m_xLinguDicsDelPB
.get() == &rBtn
)
1413 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), u
"cui/ui/querydeletedictionarydialog.ui"_ustr
));
1414 std::unique_ptr
<weld::MessageDialog
> xQuery(xBuilder
->weld_message_dialog(u
"QueryDeleteDictionaryDialog"_ustr
));
1415 if (RET_NO
== xQuery
->run())
1418 int nEntry
= m_xLinguDicsCLB
->get_selected_index();
1421 DicUserData
aData(m_xLinguDicsCLB
->get_id(nEntry
).toUInt32());
1422 sal_uInt16 nDicPos
= aData
.GetEntryId();
1423 sal_Int32 nDics
= aDics
.getLength();
1424 if (nDicPos
< nDics
)
1426 uno::Reference
<XDictionary
> xDic
= aDics
[nDicPos
];
1429 if (LinguMgr::GetIgnoreAllList() == xDic
)
1434 xDicList
->removeDictionary( xDic
);
1436 uno::Reference
< frame::XStorable
> xStor( xDic
, UNO_QUERY
);
1437 if ( xStor
->hasLocation() && !xStor
->isReadonly() )
1439 OUString sURL
= xStor
->getLocation();
1440 INetURLObject
aObj(sURL
);
1441 DBG_ASSERT( aObj
.GetProtocol() == INetProtocol::File
,
1442 "non-file URLs cannot be deleted" );
1443 if ( aObj
.GetProtocol() == INetProtocol::File
)
1445 KillFile_Impl( aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1449 aDics
.getArray()[ nDicPos
] = nullptr;
1451 // remove entry from checklistbox
1452 int nCnt
= m_xLinguDicsCLB
->n_children();
1453 for (int i
= 0; i
< nCnt
; ++i
)
1455 DicUserData
aDicData(m_xLinguDicsCLB
->get_id(i
).toUInt32());
1456 if (aDicData
.GetEntryId() == nDicPos
)
1458 m_xLinguDicsCLB
->remove(i
);
1462 DBG_ASSERT( nCnt
> m_xLinguDicsCLB
->n_children(),
1469 else if (m_xLinguOptionsEditPB
.get() == &rBtn
)
1471 int nEntry
= m_xLinguOptionsCLB
->get_selected_index();
1472 DBG_ASSERT(nEntry
!= -1, "no entry selected");
1475 OptionsUserData
aData(m_xLinguOptionsCLB
->get_id(nEntry
).toUInt32());
1476 if (aData
.HasNumericValue())
1478 sal_uInt16 nRID
= aData
.GetEntryId();
1479 OptionsBreakSet
aDlg(GetFrameWeld(), nRID
);
1480 aDlg
.GetNumericFld().set_value(aData
.GetNumericValue());
1481 if (RET_OK
== aDlg
.run())
1483 int nVal
= aDlg
.GetNumericFld().get_value();
1484 if (-1 != nVal
&& aData
.GetNumericValue() != nVal
)
1486 aData
.SetNumericValue( static_cast<sal_uInt8
>(nVal
) ); //! sets IsModified !
1487 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1488 if (nEntry
== nUPN_HYPH_MIN_WORD_LENGTH
)
1489 m_xLinguOptionsCLB
->set_text(nEntry
, sNumMinWordlen
+ " " + OUString::number(nVal
), 0);
1490 else if (nEntry
== nUPN_HYPH_MIN_LEADING
)
1491 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPreBreak
+ " " + OUString::number(nVal
), 0);
1492 else if (nEntry
== nUPN_HYPH_MIN_TRAILING
)
1493 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPostBreak
+ " " + OUString::number(nVal
), 0);
1494 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1502 SAL_WARN("cui.options", "rBtn unexpected value");
1506 IMPL_LINK(SvxLinguTabPage
, SelectHdl_Impl
, weld::TreeView
&, rBox
, void)
1508 if (m_xLinguModulesCLB
.get() == &rBox
)
1511 else if (m_xLinguDicsCLB
.get() == &rBox
)
1513 int nEntry
= rBox
.get_selected_index();
1516 DicUserData
aData(rBox
.get_id(nEntry
).toUInt32());
1518 // always allow to edit (i.e. at least view the content of the dictionary)
1519 m_xLinguDicsEditPB
->set_sensitive( true );
1520 m_xLinguDicsDelPB
->set_sensitive( aData
.IsDeletable() );
1523 else if (m_xLinguOptionsCLB
.get() == &rBox
)
1525 int nEntry
= rBox
.get_selected_index();
1528 OptionsUserData
aData(rBox
.get_id(nEntry
).toUInt32());
1529 m_xLinguOptionsEditPB
->set_sensitive( aData
.HasNumericValue() );
1534 SAL_WARN("cui.options", "rBtn unexpected value");
1538 void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp
)
1540 if ( 0 != ( GROUP_MODULES
& nGrp
) )
1542 m_xLinguModulesFT
->hide();
1543 m_xLinguModulesCLB
->hide();
1544 m_xLinguModulesEditPB
->hide();
1546 if (officecfg::Office::Security::Hyperlinks::Open::get() != SvtExtendedSecurityOptions::OPEN_NEVER
&&
1547 !comphelper::LibreOfficeKit::isActive())
1549 m_xMoreDictsBox
->show();
1554 IMPL_STATIC_LINK_NOARG(SvxLinguTabPage
, OnLinkClick
, weld::LinkButton
&, bool)
1556 comphelper::dispatchCommand(u
".uno:MoreDictionaries"_ustr
, {});
1560 SvxEditModulesDlg::SvxEditModulesDlg(weld::Window
* pParent
, SvxLinguData_Impl
& rData
)
1561 : GenericDialogController(pParent
, u
"cui/ui/editmodulesdialog.ui"_ustr
, u
"EditModulesDialog"_ustr
)
1562 , sSpell(CuiResId(RID_CUISTR_SPELL
))
1563 , sHyph(CuiResId(RID_CUISTR_HYPH
))
1564 , sThes(CuiResId(RID_CUISTR_THES
))
1565 , sGrammar(CuiResId(RID_CUISTR_GRAMMAR
))
1567 , m_xModulesCLB(m_xBuilder
->weld_tree_view(u
"lingudicts"_ustr
))
1568 , m_xPrioUpPB(m_xBuilder
->weld_button(u
"up"_ustr
))
1569 , m_xPrioDownPB(m_xBuilder
->weld_button(u
"down"_ustr
))
1570 , m_xBackPB(m_xBuilder
->weld_button(u
"back"_ustr
))
1571 , m_xMoreDictsLink(m_xBuilder
->weld_link_button(u
"moredictslink"_ustr
))
1572 , m_xClosePB(m_xBuilder
->weld_button(u
"close"_ustr
))
1573 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder
->weld_combo_box(u
"language"_ustr
)))
1575 m_xModulesCLB
->set_size_request(m_xModulesCLB
->get_approximate_digit_width() * 40,
1576 m_xModulesCLB
->get_height_rows(12));
1578 m_xModulesCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
1580 pDefaultLinguData
.reset( new SvxLinguData_Impl( rLinguData
) );
1582 m_xModulesCLB
->connect_selection_changed(LINK(this, SvxEditModulesDlg
, SelectHdl_Impl
));
1583 m_xModulesCLB
->connect_toggled(LINK(this, SvxEditModulesDlg
, BoxCheckButtonHdl_Impl
));
1585 m_xClosePB
->connect_clicked( LINK( this, SvxEditModulesDlg
, ClickHdl_Impl
));
1586 m_xPrioUpPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, UpDownHdl_Impl
));
1587 m_xPrioDownPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, UpDownHdl_Impl
));
1588 m_xBackPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, BackHdl_Impl
));
1589 // in case of not installed language modules
1590 m_xPrioUpPB
->set_sensitive( false );
1591 m_xPrioDownPB
->set_sensitive( false );
1593 m_xMoreDictsLink
->connect_activate_link(LINK(this, SvxEditModulesDlg
, OnLinkClick
));
1594 if (officecfg::Office::Security::Hyperlinks::Open::get() == SvtExtendedSecurityOptions::OPEN_NEVER
)
1595 m_xMoreDictsLink
->hide();
1597 // set that we want the checkbox shown if spellchecking is available
1598 m_xLanguageLB
->SetLanguageList(SvxLanguageListFlags::EMPTY
, false, false, true);
1601 const auto& rLoc
= rLinguData
.GetAllSupportedLocales();
1602 std::vector
<LanguageType
> aLanguages
;
1603 aLanguages
.reserve(rLoc
.size());
1604 std::transform(rLoc
.begin(), rLoc
.end(), std::back_inserter(aLanguages
),
1605 [](Locale
const& locale
) { return LanguageTag::convertToLanguageType(locale
); });
1606 m_xLanguageLB
->InsertLanguages(aLanguages
);
1607 LanguageType eSysLang
= MsLangId::getConfiguredSystemLanguage();
1608 m_xLanguageLB
->set_active_id( eSysLang
);
1609 if (m_xLanguageLB
->get_active_id() != eSysLang
)
1610 m_xLanguageLB
->set_active(0);
1612 const css::uno::Reference
< css::uno::XComponentContext
>& xContext(::comphelper::getProcessComponentContext());
1613 m_xReadWriteAccess
= css::configuration::ReadWriteAccess::create(xContext
, u
"*"_ustr
);
1615 m_xLanguageLB
->connect_changed( LINK( this, SvxEditModulesDlg
, LangSelectListBoxHdl_Impl
));
1616 LangSelectHdl_Impl(m_xLanguageLB
.get());
1619 SvxEditModulesDlg::~SvxEditModulesDlg()
1621 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1622 delete weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1625 IMPL_LINK( SvxEditModulesDlg
, SelectHdl_Impl
, weld::TreeView
&, rBox
, void )
1627 int nCurPos
= rBox
.get_selected_index();
1631 bool bDisableUp
= true;
1632 bool bDisableDown
= true;
1633 ModuleUserData_Impl
* pData
= weld::fromId
<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
));
1634 if (!pData
->IsParent() && pData
->GetType() != TYPE_HYPH
)
1636 if (nCurPos
< rBox
.n_children() - 1)
1638 bDisableDown
= weld::fromId
<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
+ 1))->IsParent();
1642 bDisableUp
= weld::fromId
<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
- 1))->IsParent();
1645 m_xPrioUpPB
->set_sensitive(!bDisableUp
);
1646 m_xPrioDownPB
->set_sensitive(!bDisableDown
);
1649 IMPL_LINK( SvxEditModulesDlg
, BoxCheckButtonHdl_Impl
, const weld::TreeView::iter_col
&, rRowCol
, void )
1651 ModuleUserData_Impl
* pData
= weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(rRowCol
.first
));
1652 if (pData
->IsParent() || pData
->GetType() != TYPE_HYPH
)
1655 // make hyphenator checkboxes function as radio-buttons
1656 // (at most one box may be checked)
1657 auto nPos
= m_xModulesCLB
->get_iter_index_in_parent(rRowCol
.first
);
1658 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1660 pData
= weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1661 if (!pData
->IsParent() && pData
->GetType() == TYPE_HYPH
&& i
!= nPos
)
1663 m_xModulesCLB
->set_toggle(i
, TRISTATE_FALSE
);
1668 IMPL_LINK_NOARG(SvxEditModulesDlg
, LangSelectListBoxHdl_Impl
, weld::ComboBox
&, void)
1670 LangSelectHdl_Impl(m_xLanguageLB
.get());
1673 void SvxEditModulesDlg::LangSelectHdl_Impl(const SvxLanguageBox
* pBox
)
1675 LanguageType eCurLanguage
= m_xLanguageLB
->get_active_id();
1676 static Locale aLastLocale
;
1677 Locale
aCurLocale( LanguageTag::convertToLocale( eCurLanguage
));
1681 // save old probably changed settings
1682 // before switching to new language entries
1684 LanguageType nLang
= LanguageTag::convertToLanguageType( aLastLocale
);
1686 sal_Int32 nStart
= 0, nLocalIndex
= 0;
1687 Sequence
< OUString
> aChange
;
1688 bool bChanged
= false;
1689 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1691 ModuleUserData_Impl
* pData
= weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1692 if (pData
->IsParent())
1696 LangImplNameTable
*pTable
= nullptr;
1697 sal_uInt8 nType
= pData
->GetType();
1700 case TYPE_SPELL
: pTable
= &rLinguData
.GetSpellTable(); break;
1701 case TYPE_GRAMMAR
: pTable
= &rLinguData
.GetGrammarTable(); break;
1702 case TYPE_HYPH
: pTable
= &rLinguData
.GetHyphTable(); break;
1703 case TYPE_THES
: pTable
= &rLinguData
.GetThesTable(); break;
1707 aChange
.realloc(nStart
);
1708 (*pTable
)[ nLang
] = aChange
;
1711 nLocalIndex
= nStart
= 0;
1712 aChange
.realloc(nEntryCount
);
1717 OUString
* pChange
= aChange
.getArray();
1718 pChange
[nStart
] = pData
->GetImplName();
1719 bChanged
|= pData
->GetIndex() != nLocalIndex
||
1720 static_cast<TriState
>(pData
->IsChecked()) != m_xModulesCLB
->get_toggle(i
);
1721 if (m_xModulesCLB
->get_toggle(i
))
1728 aChange
.realloc(nStart
);
1729 rLinguData
.GetThesTable()[ nLang
] = std::move(aChange
);
1733 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1734 delete weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1735 m_xModulesCLB
->clear();
1737 // display entries for new selected language
1739 if (LANGUAGE_DONTKNOW
!= eCurLanguage
)
1741 bool bReadOnly
= false;
1744 // spellchecker entries
1746 ModuleUserData_Impl
* pUserData
= new ModuleUserData_Impl(
1747 OUString(), true, false, TYPE_SPELL
, 0 );
1748 OUString
sId(weld::toId(pUserData
));
1749 m_xModulesCLB
->append(nullptr);
1750 m_xModulesCLB
->set_id(nRow
, sId
);
1751 m_xModulesCLB
->set_text(nRow
, sSpell
, 0);
1752 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1755 OUString aLangNodeName
= LanguageTag::convertToBcp47(aCurLocale
);
1756 OUString aConfigPath
= officecfg::Office::Linguistic::ServiceManager::path() + "/SpellCheckerList/" + aLangNodeName
;
1757 if (m_xReadWriteAccess
->hasPropertyByHierarchicalName(aConfigPath
))
1759 css::beans::Property aProperty
= m_xReadWriteAccess
->getPropertyByHierarchicalName(aConfigPath
);
1760 bReadOnly
= (aProperty
.Attributes
& css::beans::PropertyAttribute::READONLY
) != 0;
1763 sal_Int32 nLocalIndex
= 0; // index relative to parent
1764 for (auto& name
: rLinguData
.GetSortedImplNames(eCurLanguage
, TYPE_SPELL
))
1767 bool bIsSuppLang
= false;
1769 ServiceInfo_Impl
* pInfo
= rLinguData
.GetInfoByImplName(name
);
1772 bIsSuppLang
= pInfo
->xSpell
.is() &&
1773 pInfo
->xSpell
->hasLocale( aCurLocale
);
1774 aImplName
= pInfo
->sSpellImplName
;
1776 if (!aImplName
.isEmpty() && bIsSuppLang
)
1778 OUString
aTxt( pInfo
->sDisplayName
);
1780 LangImplNameTable
&rTable
= rLinguData
.GetSpellTable();
1781 const bool bHasLang
= rTable
.count( eCurLanguage
);
1784 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1786 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1787 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1788 bCheck
, TYPE_SPELL
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1789 sId
= weld::toId(pUserData
);
1791 m_xModulesCLB
->append(nullptr);
1792 m_xModulesCLB
->set_id(nRow
, sId
);
1793 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1794 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1795 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1796 m_xModulesCLB
->set_sensitive(nRow
, !bReadOnly
);
1801 // grammar checker entries
1803 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMAR
, 0 );
1804 sId
= weld::toId(pUserData
);
1805 m_xModulesCLB
->append(nullptr);
1806 m_xModulesCLB
->set_id(nRow
, sId
);
1807 m_xModulesCLB
->set_text(nRow
, sGrammar
, 0);
1808 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1811 aConfigPath
= officecfg::Office::Linguistic::ServiceManager::path() + "/GrammarCheckerList/" + aLangNodeName
;
1812 if (m_xReadWriteAccess
->hasPropertyByHierarchicalName(aConfigPath
))
1814 css::beans::Property aProperty
= m_xReadWriteAccess
->getPropertyByHierarchicalName(aConfigPath
);
1815 bReadOnly
= (aProperty
.Attributes
& css::beans::PropertyAttribute::READONLY
) != 0;
1819 for (auto& name
: rLinguData
.GetSortedImplNames(eCurLanguage
, TYPE_GRAMMAR
))
1822 bool bIsSuppLang
= false;
1824 ServiceInfo_Impl
* pInfo
= rLinguData
.GetInfoByImplName(name
);
1827 bIsSuppLang
= pInfo
->xGrammar
.is() &&
1828 pInfo
->xGrammar
->hasLocale( aCurLocale
);
1829 aImplName
= pInfo
->sGrammarImplName
;
1831 if (!aImplName
.isEmpty() && bIsSuppLang
)
1833 OUString
aTxt( pInfo
->sDisplayName
);
1835 LangImplNameTable
&rTable
= rLinguData
.GetGrammarTable();
1836 const bool bHasLang
= rTable
.count( eCurLanguage
);
1839 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1841 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1842 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1843 bCheck
, TYPE_GRAMMAR
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1845 sId
= weld::toId(pUserData
);
1847 m_xModulesCLB
->append(nullptr);
1848 m_xModulesCLB
->set_id(nRow
, sId
);
1849 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1850 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1851 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1852 m_xModulesCLB
->set_sensitive(nRow
, !bReadOnly
);
1857 // hyphenator entries
1859 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPH
, 0 );
1860 sId
= weld::toId(pUserData
);
1861 m_xModulesCLB
->append(nullptr);
1862 m_xModulesCLB
->set_id(nRow
, sId
);
1863 m_xModulesCLB
->set_text(nRow
, sHyph
, 0);
1864 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1867 aConfigPath
= officecfg::Office::Linguistic::ServiceManager::path() + "/HyphenatorList/" + aLangNodeName
;
1868 if (m_xReadWriteAccess
->hasPropertyByHierarchicalName(aConfigPath
))
1870 css::beans::Property aProperty
= m_xReadWriteAccess
->getPropertyByHierarchicalName(aConfigPath
);
1871 bReadOnly
= (aProperty
.Attributes
& css::beans::PropertyAttribute::READONLY
) != 0;
1875 for (auto& name
: rLinguData
.GetSortedImplNames(eCurLanguage
, TYPE_HYPH
))
1878 bool bIsSuppLang
= false;
1880 ServiceInfo_Impl
* pInfo
= rLinguData
.GetInfoByImplName(name
);
1883 bIsSuppLang
= pInfo
->xHyph
.is() &&
1884 pInfo
->xHyph
->hasLocale( aCurLocale
);
1885 aImplName
= pInfo
->sHyphImplName
;
1887 if (!aImplName
.isEmpty() && bIsSuppLang
)
1889 OUString
aTxt( pInfo
->sDisplayName
);
1891 LangImplNameTable
&rTable
= rLinguData
.GetHyphTable();
1892 const bool bHasLang
= rTable
.count( eCurLanguage
);
1895 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1897 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1898 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1899 bCheck
, TYPE_HYPH
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1900 sId
= weld::toId(pUserData
);
1902 m_xModulesCLB
->append(nullptr);
1903 m_xModulesCLB
->set_id(nRow
, sId
);
1904 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1905 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1906 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1907 m_xModulesCLB
->set_sensitive(nRow
, !bReadOnly
);
1912 // thesaurus entries
1914 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_THES
, 0 );
1915 sId
= weld::toId(pUserData
);
1916 m_xModulesCLB
->append(nullptr);
1917 m_xModulesCLB
->set_id(nRow
, sId
);
1918 m_xModulesCLB
->set_text(nRow
, sThes
, 0);
1919 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1922 aConfigPath
= officecfg::Office::Linguistic::ServiceManager::path() + "/ThesaurusList/" + aLangNodeName
;
1923 if (m_xReadWriteAccess
->hasPropertyByHierarchicalName(aConfigPath
))
1925 css::beans::Property aProperty
= m_xReadWriteAccess
->getPropertyByHierarchicalName(aConfigPath
);
1926 bReadOnly
= (aProperty
.Attributes
& css::beans::PropertyAttribute::READONLY
) != 0;
1930 for (auto& name
: rLinguData
.GetSortedImplNames(eCurLanguage
, TYPE_THES
))
1933 bool bIsSuppLang
= false;
1935 ServiceInfo_Impl
* pInfo
= rLinguData
.GetInfoByImplName(name
);
1938 bIsSuppLang
= pInfo
->xThes
.is() &&
1939 pInfo
->xThes
->hasLocale( aCurLocale
);
1940 aImplName
= pInfo
->sThesImplName
;
1942 if (!aImplName
.isEmpty() && bIsSuppLang
)
1944 OUString
aTxt( pInfo
->sDisplayName
);
1946 LangImplNameTable
&rTable
= rLinguData
.GetThesTable();
1947 const bool bHasLang
= rTable
.count( eCurLanguage
);
1950 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1952 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1953 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1954 bCheck
, TYPE_THES
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1955 sId
= weld::toId(pUserData
);
1957 m_xModulesCLB
->append(nullptr);
1958 m_xModulesCLB
->set_id(nRow
, sId
);
1959 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1960 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1961 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1962 m_xModulesCLB
->set_sensitive(nRow
, !bReadOnly
);
1967 aLastLocale
= std::move(aCurLocale
);
1970 IMPL_LINK( SvxEditModulesDlg
, UpDownHdl_Impl
, weld::Button
&, rBtn
, void )
1972 bool bUp
= m_xPrioUpPB
.get() == &rBtn
;
1973 int nCurPos
= m_xModulesCLB
->get_selected_index();
1977 m_xModulesCLB
->freeze();
1979 OUString
sId(m_xModulesCLB
->get_id(nCurPos
));
1980 OUString
sStr(m_xModulesCLB
->get_text(nCurPos
));
1981 bool bIsChecked
= m_xModulesCLB
->get_toggle(nCurPos
);
1983 m_xModulesCLB
->remove(nCurPos
);
1985 int nDestPos
= bUp
? nCurPos
- 1 : nCurPos
+ 1;
1987 m_xModulesCLB
->insert_text(nDestPos
, sStr
);
1988 m_xModulesCLB
->set_id(nDestPos
, sId
);
1989 m_xModulesCLB
->set_toggle(nDestPos
, bIsChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1991 m_xModulesCLB
->thaw();
1993 m_xModulesCLB
->select(nDestPos
);
1994 SelectHdl_Impl(*m_xModulesCLB
);
1997 IMPL_LINK_NOARG(SvxEditModulesDlg
, ClickHdl_Impl
, weld::Button
&, void)
1999 // store language config
2000 LangSelectHdl_Impl(m_xLanguageLB
.get());
2001 m_xDialog
->response(RET_OK
);
2004 IMPL_LINK_NOARG(SvxEditModulesDlg
, BackHdl_Impl
, weld::Button
&, void)
2006 rLinguData
= *pDefaultLinguData
;
2007 LangSelectHdl_Impl(nullptr);
2010 IMPL_STATIC_LINK_NOARG(SvxEditModulesDlg
, OnLinkClick
, weld::LinkButton
&, bool)
2012 comphelper::dispatchCommand(u
".uno:MoreDictionaries"_ustr
, {});
2016 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */