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 <unotools/lingucfg.hxx>
28 #include <unotools/linguprops.hxx>
29 #include <editeng/unolingu.hxx>
30 #include <linguistic/misc.hxx>
31 #include <sfx2/sfxsids.hrc>
32 #include <tools/debug.hxx>
33 #include <tools/urlobj.hxx>
34 #include <comphelper/diagnose_ex.hxx>
35 #include <comphelper/dispatchcommand.hxx>
36 #include <comphelper/lok.hxx>
37 #include <comphelper/processfactory.hxx>
38 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
39 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
40 #include <com/sun/star/linguistic2/XSpellChecker.hpp>
41 #include <com/sun/star/linguistic2/XProofreader.hpp>
42 #include <com/sun/star/linguistic2/XHyphenator.hpp>
43 #include <com/sun/star/linguistic2/XThesaurus.hpp>
44 #include <com/sun/star/linguistic2/XDictionary.hpp>
45 #include <com/sun/star/linguistic2/XDictionaryList.hpp>
46 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
47 #include <com/sun/star/lang/XServiceDisplayName.hpp>
48 #include <com/sun/star/frame/XStorable.hpp>
49 #include <unotools/extendedsecurityoptions.hxx>
50 #include <svl/eitem.hxx>
51 #include <vcl/svapp.hxx>
52 #include <sal/log.hxx>
53 #include <osl/diagnose.h>
55 #include <svx/svxdlg.hxx>
56 #include <editeng/optitems.hxx>
57 #include <optlingu.hxx>
58 #include <dialmgr.hxx>
59 #include <strings.hrc>
61 #include <ucbhelper/content.hxx>
67 using namespace ::ucbhelper
;
68 using namespace ::com::sun::star
;
69 using namespace css::lang
;
70 using namespace css::uno
;
71 using namespace css::linguistic2
;
72 using namespace css::beans
;
74 constexpr OUStringLiteral
cSpell(SN_SPELLCHECKER
);
75 constexpr OUStringLiteral
cGrammar(SN_GRAMMARCHECKER
);
76 constexpr OUStringLiteral
cHyph(SN_HYPHENATOR
);
77 constexpr OUStringLiteral
cThes(SN_THESAURUS
);
79 // static ----------------------------------------------------------------
81 static sal_Int32
lcl_SeqGetEntryPos(
82 const Sequence
< OUString
> &rSeq
, std::u16string_view rEntry
)
85 sal_Int32 nLen
= rSeq
.getLength();
86 const OUString
*pItem
= rSeq
.getConstArray();
87 for (i
= 0; i
< nLen
; ++i
)
89 if (rEntry
== pItem
[i
])
92 return i
< nLen
? i
: -1;
95 static bool KillFile_Impl( const OUString
& rURL
)
100 Content
aCnt( rURL
, uno::Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
101 aCnt
.executeCommand( "delete", Any( true ) );
105 TOOLS_WARN_EXCEPTION( "cui.options", "KillFile" );
114 // t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar
115 // c: 1 -> checked 0 -> unchecked
118 #define TYPE_SPELL sal_uInt8(1)
119 #define TYPE_GRAMMAR sal_uInt8(2)
120 #define TYPE_HYPH sal_uInt8(3)
121 #define TYPE_THES sal_uInt8(4)
125 class ModuleUserData_Impl
134 ModuleUserData_Impl( OUString sImpName
, bool bIsParent
, bool bChecked
, sal_uInt8 nSetType
, sal_uInt8 nSetIndex
) :
136 bIsChecked(bChecked
),
139 sImplName(std::move(sImpName
))
142 bool IsParent() const {return bParent
;}
143 sal_uInt8
GetType() const {return nType
;}
144 bool IsChecked() const {return bIsChecked
;}
145 sal_uInt8
GetIndex() const {return nIndex
;}
146 const OUString
& GetImplName() const {return sImplName
;}
151 // User for user-dictionaries (XDictionary interface)
158 explicit DicUserData(sal_uInt32 nUserData
) : nVal( nUserData
) {}
159 DicUserData( sal_uInt16 nEID
,
160 bool bChecked
, bool bEditable
, bool bDeletable
);
162 sal_uInt32
GetUserData() const { return nVal
; }
163 sal_uInt16
GetEntryId() const { return static_cast<sal_uInt16
>(nVal
>> 16); }
164 bool IsChecked() const { return static_cast<bool>((nVal
>> 8) & 0x01); }
165 bool IsDeletable() const { return static_cast<bool>((nVal
>> 10) & 0x01); }
170 DicUserData::DicUserData(
172 bool bChecked
, bool bEditable
, bool bDeletable
)
174 DBG_ASSERT( nEID
< 65000, "Entry Id out of range" );
175 nVal
= (static_cast<sal_uInt32
>(0xFFFF & nEID
) << 16) |
176 (static_cast<sal_uInt32
>(bChecked
? 1 : 0) << 8) |
177 (static_cast<sal_uInt32
>(bEditable
? 1 : 0) << 9) |
178 (static_cast<sal_uInt32
>(bDeletable
? 1 : 0) << 10);
181 /*--------------------------------------------------
182 Entry IDs for options listbox of dialog
183 --------------------------------------------------*/
192 EID_WORDS_WITH_DIGITS
,
199 EID_SPELL_CLOSED_COMPOUND
,
200 EID_SPELL_HYPHENATED_COMPOUND
205 static OUString
lcl_GetPropertyName( EID_OPTIONS eEntryId
)
209 case EID_SPELL_AUTO
: return UPN_IS_SPELL_AUTO
;
210 case EID_GRAMMAR_AUTO
: return UPN_IS_GRAMMAR_AUTO
;
211 case EID_CAPITAL_WORDS
: return UPN_IS_SPELL_UPPER_CASE
;
212 case EID_SPELL_CLOSED_COMPOUND
: return UPN_IS_SPELL_CLOSED_COMPOUND
;
213 case EID_SPELL_HYPHENATED_COMPOUND
: return UPN_IS_SPELL_HYPHENATED_COMPOUND
;
214 case EID_WORDS_WITH_DIGITS
: return UPN_IS_SPELL_WITH_DIGITS
;
215 case EID_SPELL_SPECIAL
: return UPN_IS_SPELL_SPECIAL
;
216 case EID_NUM_MIN_WORDLEN
: return UPN_HYPH_MIN_WORD_LENGTH
;
217 case EID_NUM_PRE_BREAK
: return UPN_HYPH_MIN_LEADING
;
218 case EID_NUM_POST_BREAK
: return UPN_HYPH_MIN_TRAILING
;
219 case EID_HYPH_AUTO
: return UPN_IS_HYPH_AUTO
;
220 case EID_HYPH_SPECIAL
: return UPN_IS_HYPH_SPECIAL
;
221 default: assert (false); abort();
227 class OptionsBreakSet
: public weld::GenericDialogController
229 std::unique_ptr
<weld::Widget
> m_xBeforeFrame
;
230 std::unique_ptr
<weld::Widget
> m_xAfterFrame
;
231 std::unique_ptr
<weld::Widget
> m_xMinimalFrame
;
232 std::unique_ptr
<weld::SpinButton
> m_xBreakNF
;
235 OptionsBreakSet(weld::Window
* pParent
, sal_uInt16 nRID
)
236 : GenericDialogController(pParent
, "cui/ui/breaknumberoption.ui", "BreakNumberOption")
237 , m_xBeforeFrame(m_xBuilder
->weld_widget("beforeframe"))
238 , m_xAfterFrame(m_xBuilder
->weld_widget("afterframe"))
239 , m_xMinimalFrame(m_xBuilder
->weld_widget("miniframe"))
241 assert(EID_NUM_PRE_BREAK
== nRID
|| EID_NUM_POST_BREAK
== nRID
|| EID_NUM_MIN_WORDLEN
== nRID
); //unexpected ID
243 if (nRID
== EID_NUM_PRE_BREAK
)
245 m_xBeforeFrame
->show();
246 m_xBreakNF
= m_xBuilder
->weld_spin_button("beforebreak");
248 else if(nRID
== EID_NUM_POST_BREAK
)
250 m_xAfterFrame
->show();
251 m_xBreakNF
= m_xBuilder
->weld_spin_button("afterbreak");
253 else if(nRID
== EID_NUM_MIN_WORDLEN
)
255 m_xMinimalFrame
->show();
256 m_xBreakNF
= m_xBuilder
->weld_spin_button("wordlength");
260 weld::SpinButton
& GetNumericFld()
266 // class OptionsUserData -------------------------------------------------
268 class OptionsUserData
273 explicit OptionsUserData( sal_uInt32 nUserData
) : nVal( nUserData
) {}
274 OptionsUserData( sal_uInt16 nEID
,
275 bool bHasNV
, sal_uInt16 nNumVal
,
276 bool bCheckable
, bool bChecked
);
278 sal_uInt32
GetUserData() const { return nVal
; }
279 sal_uInt16
GetEntryId() const { return static_cast<sal_uInt16
>(nVal
>> 16); }
280 bool HasNumericValue() const { return static_cast<bool>((nVal
>> 10) & 0x01); }
281 sal_uInt16
GetNumericValue() const { return static_cast<sal_uInt16
>(nVal
& 0xFF); }
282 bool IsCheckable() const { return static_cast<bool>((nVal
>> 9) & 0x01); }
283 bool IsModified() const { return static_cast<bool>((nVal
>> 11) & 0x01); }
285 void SetNumericValue( sal_uInt8 nNumVal
);
290 OptionsUserData::OptionsUserData( sal_uInt16 nEID
,
291 bool bHasNV
, sal_uInt16 nNumVal
,
292 bool bCheckable
, bool bChecked
)
294 DBG_ASSERT( nEID
< 65000, "Entry Id out of range" );
295 DBG_ASSERT( nNumVal
< 256, "value out of range" );
296 nVal
= (static_cast<sal_uInt32
>(0xFFFF & nEID
) << 16) |
297 (static_cast<sal_uInt32
>(bHasNV
? 1 : 0) << 10) |
298 (static_cast<sal_uInt32
>(bCheckable
? 1 : 0) << 9) |
299 (static_cast<sal_uInt32
>(bChecked
? 1 : 0) << 8) |
300 static_cast<sal_uInt32
>(0xFF & nNumVal
);
303 void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal
)
305 if (HasNumericValue() && (GetNumericValue() != nNumVal
))
309 nVal
|= sal_uInt32(1) << 11; // mark as modified
313 // ServiceInfo_Impl ----------------------------------------------------
317 struct ServiceInfo_Impl
319 OUString sDisplayName
;
320 OUString sSpellImplName
;
321 OUString sHyphImplName
;
322 OUString sThesImplName
;
323 OUString sGrammarImplName
;
324 uno::Reference
< XSpellChecker
> xSpell
;
325 uno::Reference
< XHyphenator
> xHyph
;
326 uno::Reference
< XThesaurus
> xThes
;
327 uno::Reference
< XProofreader
> xGrammar
;
330 ServiceInfo_Impl() : bConfigured(false) {}
335 bool operator()(const css::lang::Locale
& lhs
, const css::lang::Locale
& rhs
) const
337 if (lhs
.Language
< rhs
.Language
)
339 if (lhs
.Language
> rhs
.Language
)
341 if (lhs
.Country
< rhs
.Country
)
343 if (lhs
.Country
> rhs
.Country
)
345 return lhs
.Variant
< rhs
.Variant
;
351 typedef std::vector
< ServiceInfo_Impl
> ServiceInfoArr
;
352 typedef std::map
< LanguageType
, Sequence
< OUString
> > LangImplNameTable
;
355 // SvxLinguData_Impl ----------------------------------------------------
357 class SvxLinguData_Impl
359 //contains services and implementation names sorted by implementation names
360 ServiceInfoArr aDisplayServiceArr
;
361 sal_uInt32 nDisplayServices
;
363 std::set
<Locale
, Locale_less
> aAllServiceLocales
;
364 LangImplNameTable aCfgSpellTable
;
365 LangImplNameTable aCfgHyphTable
;
366 LangImplNameTable aCfgThesTable
;
367 LangImplNameTable aCfgGrammarTable
;
368 uno::Reference
< XLinguServiceManager2
> xLinguSrvcMgr
;
371 static bool AddRemove( Sequence
< OUString
> &rConfigured
,
372 const OUString
&rImplName
, bool bAdd
);
377 uno::Reference
<XLinguServiceManager2
> & GetManager() { return xLinguSrvcMgr
; }
379 void SetChecked( const Sequence
< OUString
> &rConfiguredServices
);
380 void Reconfigure( std::u16string_view rDisplayName
, bool bEnable
);
382 const auto& GetAllSupportedLocales() const { return aAllServiceLocales
; }
384 LangImplNameTable
& GetSpellTable() { return aCfgSpellTable
; }
385 LangImplNameTable
& GetHyphTable() { return aCfgHyphTable
; }
386 LangImplNameTable
& GetThesTable() { return aCfgThesTable
; }
387 LangImplNameTable
& GetGrammarTable() { return aCfgGrammarTable
; }
389 ServiceInfoArr
& GetDisplayServiceArray() { return aDisplayServiceArr
; }
391 const sal_uInt32
& GetDisplayServiceCount() const { return nDisplayServices
; }
392 void SetDisplayServiceCount( sal_uInt32 nVal
) { nDisplayServices
= nVal
; }
394 // returns the list of service implementation names for the specified
395 // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in
396 // the proper order for the SvxEditModulesDlg (the ones from the
397 // configuration (keeping that order!) first and then the other ones.
398 // I.e. the ones available but not configured in arbitrary order).
399 // They available ones may contain names that do not(!) support that
401 Sequence
< OUString
> GetSortedImplNames( LanguageType nLang
, sal_uInt8 nType
);
403 ServiceInfo_Impl
* GetInfoByImplName( std::u16string_view rSvcImplName
);
407 static sal_Int32
lcl_SeqGetIndex( const Sequence
< OUString
> &rSeq
, std::u16string_view rTxt
)
410 sal_Int32 nLen
= rSeq
.getLength();
411 const OUString
*pString
= rSeq
.getConstArray();
412 for (sal_Int32 i
= 0; i
< nLen
&& nRes
== -1; ++i
)
414 if (pString
[i
] == rTxt
)
421 Sequence
< OUString
> SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang
, sal_uInt8 nType
)
423 LangImplNameTable
*pTable
= nullptr;
426 case TYPE_SPELL
: pTable
= &aCfgSpellTable
; break;
427 case TYPE_HYPH
: pTable
= &aCfgHyphTable
; break;
428 case TYPE_THES
: pTable
= &aCfgThesTable
; break;
429 case TYPE_GRAMMAR
: pTable
= &aCfgGrammarTable
; break;
431 Sequence
< OUString
> aRes
;
434 SAL_WARN( "cui.options", "unknown linguistic type" );
437 if (pTable
->count( nLang
))
438 aRes
= (*pTable
)[ nLang
]; // add configured services
439 sal_Int32 nIdx
= aRes
.getLength();
440 DBG_ASSERT( nDisplayServices
>= o3tl::make_unsigned(nIdx
), "size mismatch" );
441 aRes
.realloc( nDisplayServices
);
442 OUString
*pRes
= aRes
.getArray();
444 // add not configured services
445 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
447 const ServiceInfo_Impl
&rInfo
= aDisplayServiceArr
[ i
];
451 case TYPE_SPELL
: aImplName
= rInfo
.sSpellImplName
; break;
452 case TYPE_HYPH
: aImplName
= rInfo
.sHyphImplName
; break;
453 case TYPE_THES
: aImplName
= rInfo
.sThesImplName
; break;
454 case TYPE_GRAMMAR
: aImplName
= rInfo
.sGrammarImplName
; break;
457 if (!aImplName
.isEmpty() && (lcl_SeqGetIndex( aRes
, aImplName
) == -1)) // name not yet added
459 DBG_ASSERT( nIdx
< aRes
.getLength(), "index out of range" );
460 if (nIdx
< aRes
.getLength())
461 pRes
[ nIdx
++ ] = aImplName
;
464 // don't forget to put aRes back to its actual size just in case you allocated too much
465 // since all of the names may have already been added
466 // otherwise you get duplicate entries in the edit dialog
467 aRes
.realloc( nIdx
);
472 ServiceInfo_Impl
* SvxLinguData_Impl::GetInfoByImplName( std::u16string_view rSvcImplName
)
474 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
476 ServiceInfo_Impl
&rTmp
= aDisplayServiceArr
[ i
];
477 if (rTmp
.sSpellImplName
== rSvcImplName
||
478 rTmp
.sHyphImplName
== rSvcImplName
||
479 rTmp
.sThesImplName
== rSvcImplName
||
480 rTmp
.sGrammarImplName
== rSvcImplName
)
488 static void lcl_MergeDisplayArray(
489 SvxLinguData_Impl
&rData
,
490 const ServiceInfo_Impl
&rToAdd
)
494 ServiceInfoArr
&rSvcInfoArr
= rData
.GetDisplayServiceArray();
495 sal_uInt32 nEntries
= rData
.GetDisplayServiceCount();
497 for (sal_uInt32 i
= 0; i
< nEntries
; ++i
)
499 ServiceInfo_Impl
& rEntry
= rSvcInfoArr
[i
];
500 if (rEntry
.sDisplayName
== rToAdd
.sDisplayName
)
502 if(rToAdd
.xSpell
.is())
504 DBG_ASSERT( !rEntry
.xSpell
.is() &&
505 rEntry
.sSpellImplName
.isEmpty(),
507 rEntry
.sSpellImplName
= rToAdd
.sSpellImplName
;
508 rEntry
.xSpell
= rToAdd
.xSpell
;
510 if(rToAdd
.xGrammar
.is())
512 DBG_ASSERT( !rEntry
.xGrammar
.is() &&
513 rEntry
.sGrammarImplName
.isEmpty(),
515 rEntry
.sGrammarImplName
= rToAdd
.sGrammarImplName
;
516 rEntry
.xGrammar
= rToAdd
.xGrammar
;
518 if(rToAdd
.xHyph
.is())
520 DBG_ASSERT( !rEntry
.xHyph
.is() &&
521 rEntry
.sHyphImplName
.isEmpty(),
523 rEntry
.sHyphImplName
= rToAdd
.sHyphImplName
;
524 rEntry
.xHyph
= rToAdd
.xHyph
;
526 if(rToAdd
.xThes
.is())
528 DBG_ASSERT( !rEntry
.xThes
.is() &&
529 rEntry
.sThesImplName
.isEmpty(),
531 rEntry
.sThesImplName
= rToAdd
.sThesImplName
;
532 rEntry
.xThes
= rToAdd
.xThes
;
538 rData
.GetDisplayServiceArray().push_back( rToAdd
);
539 rData
.SetDisplayServiceCount( nCnt
+ 1 );
542 SvxLinguData_Impl::SvxLinguData_Impl() :
545 uno::Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
546 xLinguSrvcMgr
= LinguServiceManager::create(xContext
);
548 const Locale
& rCurrentLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
551 Any(LinguMgr::GetLinguPropertySet()),
552 Any() // second argument has to be empty!
556 const Sequence
< OUString
> aSpellNames
= xLinguSrvcMgr
->getAvailableServices(
559 for(const OUString
& spellName
: aSpellNames
)
561 ServiceInfo_Impl aInfo
;
562 aInfo
.sSpellImplName
= spellName
;
564 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sSpellImplName
, aArgs
, xContext
), UNO_QUERY
);
566 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xSpell
, UNO_QUERY
);
568 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
570 const Sequence
< Locale
> aLocales( aInfo
.xSpell
->getLocales() );
571 //! suppress display of entries with no supported languages (see feature 110994)
572 if (aLocales
.hasElements())
574 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
575 lcl_MergeDisplayArray( *this, aInfo
);
579 //read grammar checker
580 const Sequence
< OUString
> aGrammarNames
= xLinguSrvcMgr
->getAvailableServices(
581 cGrammar
, Locale() );
582 for(const OUString
& grammarName
: aGrammarNames
)
584 ServiceInfo_Impl aInfo
;
585 aInfo
.sGrammarImplName
= grammarName
;
587 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sGrammarImplName
, aArgs
, xContext
), UNO_QUERY
);
589 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xGrammar
, UNO_QUERY
);
591 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
593 const Sequence
< Locale
> aLocales( aInfo
.xGrammar
->getLocales() );
594 //! suppress display of entries with no supported languages (see feature 110994)
595 if (aLocales
.hasElements())
597 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
598 lcl_MergeDisplayArray( *this, aInfo
);
603 const Sequence
< OUString
> aHyphNames
= xLinguSrvcMgr
->getAvailableServices(
605 for(const OUString
& hyphName
: aHyphNames
)
607 ServiceInfo_Impl aInfo
;
608 aInfo
.sHyphImplName
= hyphName
;
609 aInfo
.xHyph
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sHyphImplName
, aArgs
, xContext
), UNO_QUERY
);
611 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xHyph
, UNO_QUERY
);
613 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
615 const Sequence
< Locale
> aLocales( aInfo
.xHyph
->getLocales() );
616 //! suppress display of entries with no supported languages (see feature 110994)
617 if (aLocales
.hasElements())
619 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
620 lcl_MergeDisplayArray( *this, aInfo
);
625 const Sequence
< OUString
> aThesNames
= xLinguSrvcMgr
->getAvailableServices(
627 for(const OUString
& thesName
: aThesNames
)
629 ServiceInfo_Impl aInfo
;
630 aInfo
.sThesImplName
= thesName
;
631 aInfo
.xThes
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sThesImplName
, aArgs
, xContext
), UNO_QUERY
);
633 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xThes
, UNO_QUERY
);
635 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
637 const Sequence
< Locale
> aLocales( aInfo
.xThes
->getLocales() );
638 //! suppress display of entries with no supported languages (see feature 110994)
639 if (aLocales
.hasElements())
641 aAllServiceLocales
.insert(aLocales
.begin(), aLocales
.end());
642 lcl_MergeDisplayArray( *this, aInfo
);
646 Sequence
< OUString
> aCfgSvcs
;
647 for(auto const & locale
: std::as_const(aAllServiceLocales
))
649 LanguageType nLang
= LanguageTag::convertToLanguageType( locale
);
651 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cSpell
, locale
);
652 SetChecked( aCfgSvcs
);
653 if (aCfgSvcs
.hasElements())
654 aCfgSpellTable
[ nLang
] = aCfgSvcs
;
656 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cGrammar
, locale
);
657 SetChecked( aCfgSvcs
);
658 if (aCfgSvcs
.hasElements())
659 aCfgGrammarTable
[ nLang
] = aCfgSvcs
;
661 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cHyph
, locale
);
662 SetChecked( aCfgSvcs
);
663 if (aCfgSvcs
.hasElements())
664 aCfgHyphTable
[ nLang
] = aCfgSvcs
;
666 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cThes
, locale
);
667 SetChecked( aCfgSvcs
);
668 if (aCfgSvcs
.hasElements())
669 aCfgThesTable
[ nLang
] = aCfgSvcs
;
673 void SvxLinguData_Impl::SetChecked(const Sequence
<OUString
>& rConfiguredServices
)
675 for(OUString
const & configService
: rConfiguredServices
)
677 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
679 ServiceInfo_Impl
& rEntry
= aDisplayServiceArr
[i
];
680 if (!rEntry
.bConfigured
)
682 const OUString
&rSrvcImplName
= configService
;
683 if (!rSrvcImplName
.isEmpty() &&
684 (rEntry
.sSpellImplName
== rSrvcImplName
||
685 rEntry
.sGrammarImplName
== rSrvcImplName
||
686 rEntry
.sHyphImplName
== rSrvcImplName
||
687 rEntry
.sThesImplName
== rSrvcImplName
))
689 rEntry
.bConfigured
= true;
697 bool SvxLinguData_Impl::AddRemove(
698 Sequence
< OUString
> &rConfigured
,
699 const OUString
&rImplName
, bool bAdd
)
701 bool bRet
= false; // modified?
703 sal_Int32 nEntries
= rConfigured
.getLength();
704 sal_Int32 nPos
= lcl_SeqGetEntryPos(rConfigured
, rImplName
);
705 if (bAdd
&& nPos
< 0) // add new entry
707 rConfigured
.realloc( ++nEntries
);
708 OUString
*pConfigured
= rConfigured
.getArray();
709 pConfigured
[nEntries
- 1] = rImplName
;
712 else if (!bAdd
&& nPos
>= 0) // remove existing entry
714 OUString
*pConfigured
= rConfigured
.getArray();
715 for (sal_Int32 i
= nPos
; i
< nEntries
- 1; ++i
)
716 pConfigured
[i
] = pConfigured
[i
+ 1];
717 rConfigured
.realloc(--nEntries
);
725 void SvxLinguData_Impl::Reconfigure( std::u16string_view rDisplayName
, bool bEnable
)
727 DBG_ASSERT( !rDisplayName
.empty(), "empty DisplayName" );
729 ServiceInfo_Impl
*pInfo
= nullptr;
730 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
732 ServiceInfo_Impl
& rTmp
= aDisplayServiceArr
[i
];
733 if (rTmp
.sDisplayName
== rDisplayName
)
739 DBG_ASSERT( pInfo
, "DisplayName entry not found" );
743 pInfo
->bConfigured
= bEnable
;
745 Sequence
< Locale
> aLocales
;
746 const Locale
*pLocale
= nullptr;
747 sal_Int32 nLocales
= 0;
750 // update configured spellchecker entries
751 if (pInfo
->xSpell
.is())
753 aLocales
= pInfo
->xSpell
->getLocales();
754 pLocale
= aLocales
.getConstArray();
755 nLocales
= aLocales
.getLength();
756 for (i
= 0; i
< nLocales
; ++i
)
758 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
759 if (!aCfgSpellTable
.count( nLang
) && bEnable
)
760 aCfgSpellTable
[ nLang
] = Sequence
< OUString
>();
761 if (aCfgSpellTable
.count( nLang
))
762 AddRemove( aCfgSpellTable
[ nLang
], pInfo
->sSpellImplName
, bEnable
);
766 // update configured grammar checker entries
767 if (pInfo
->xGrammar
.is())
769 aLocales
= pInfo
->xGrammar
->getLocales();
770 pLocale
= aLocales
.getConstArray();
771 nLocales
= aLocales
.getLength();
772 for (i
= 0; i
< nLocales
; ++i
)
774 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
775 if (!aCfgGrammarTable
.count( nLang
) && bEnable
)
776 aCfgGrammarTable
[ nLang
] = Sequence
< OUString
>();
777 if (aCfgGrammarTable
.count( nLang
))
778 AddRemove( aCfgGrammarTable
[ nLang
], pInfo
->sGrammarImplName
, bEnable
);
782 // update configured hyphenator entries
783 if (pInfo
->xHyph
.is())
785 aLocales
= pInfo
->xHyph
->getLocales();
786 pLocale
= aLocales
.getConstArray();
787 nLocales
= aLocales
.getLength();
788 for (i
= 0; i
< nLocales
; ++i
)
790 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
791 if (!aCfgHyphTable
.count( nLang
) && bEnable
)
792 aCfgHyphTable
[ nLang
] = Sequence
< OUString
>();
793 if (aCfgHyphTable
.count( nLang
))
794 AddRemove( aCfgHyphTable
[ nLang
], pInfo
->sHyphImplName
, bEnable
);
798 // update configured spellchecker entries
799 if (!pInfo
->xThes
.is())
802 aLocales
= pInfo
->xThes
->getLocales();
803 pLocale
= aLocales
.getConstArray();
804 nLocales
= aLocales
.getLength();
805 for (i
= 0; i
< nLocales
; ++i
)
807 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
808 if (!aCfgThesTable
.count( nLang
) && bEnable
)
809 aCfgThesTable
[ nLang
] = Sequence
< OUString
>();
810 if (aCfgThesTable
.count( nLang
))
811 AddRemove( aCfgThesTable
[ nLang
], pInfo
->sThesImplName
, bEnable
);
816 // class SvxLinguTabPage -------------------------------------------------
818 SvxLinguTabPage::SvxLinguTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rSet
)
819 : SfxTabPage(pPage
, pController
, "cui/ui/optlingupage.ui", "OptLinguPage", &rSet
)
820 , sCapitalWords (CuiResId(RID_CUISTR_CAPITAL_WORDS
))
821 , sWordsWithDigits(CuiResId(RID_CUISTR_WORDS_WITH_DIGITS
))
822 , sSpellSpecial (CuiResId(RID_CUISTR_SPELL_SPECIAL
))
823 , sSpellAuto (CuiResId(RID_CUISTR_SPELL_AUTO
))
824 , sSpellClosedCompound (CuiResId(RID_CUISTR_SPELL_CLOSED_COMPOUND
))
825 , sSpellHyphenatedCompound (CuiResId(RID_CUISTR_SPELL_HYPHENATED_COMPOUND
))
826 , sGrammarAuto (CuiResId(RID_CUISTR_GRAMMAR_AUTO
))
827 , sNumMinWordlen (CuiResId(RID_CUISTR_NUM_MIN_WORDLEN
))
828 , sNumPreBreak (CuiResId(RID_CUISTR_NUM_PRE_BREAK
))
829 , sNumPostBreak (CuiResId(RID_CUISTR_NUM_POST_BREAK
))
830 , sHyphAuto (CuiResId(RID_CUISTR_HYPH_AUTO
))
831 , sHyphSpecial (CuiResId(RID_CUISTR_HYPH_SPECIAL
))
832 , nUPN_HYPH_MIN_WORD_LENGTH(-1)
833 , nUPN_HYPH_MIN_LEADING(-1)
834 , nUPN_HYPH_MIN_TRAILING(-1)
835 , m_nDlbClickEventId(nullptr)
836 , m_xLinguModulesFT(m_xBuilder
->weld_label("lingumodulesft"))
837 , m_xLinguModulesCLB(m_xBuilder
->weld_tree_view("lingumodules"))
838 , m_xLinguModulesEditPB(m_xBuilder
->weld_button("lingumodulesedit"))
839 , m_xLinguDicsFT(m_xBuilder
->weld_label("lingudictsft"))
840 , m_xLinguDicsCLB(m_xBuilder
->weld_tree_view("lingudicts"))
841 , m_xLinguDicsNewPB(m_xBuilder
->weld_button("lingudictsnew"))
842 , m_xLinguDicsEditPB(m_xBuilder
->weld_button("lingudictsedit"))
843 , m_xLinguDicsDelPB(m_xBuilder
->weld_button("lingudictsdelete"))
844 , m_xLinguOptionsCLB(m_xBuilder
->weld_tree_view("linguoptions"))
845 , m_xLinguOptionsEditPB(m_xBuilder
->weld_button("linguoptionsedit"))
846 , m_xMoreDictsBox(m_xBuilder
->weld_box("moredictsbox"))
847 , m_xMoreDictsLink(m_xBuilder
->weld_link_button("moredictslink"))
849 m_xLinguModulesCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
850 m_xLinguDicsCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
851 m_xLinguOptionsCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
853 m_xLinguModulesCLB
->connect_changed( LINK( this, SvxLinguTabPage
, SelectHdl_Impl
));
854 m_xLinguModulesCLB
->connect_row_activated(LINK(this, SvxLinguTabPage
, BoxDoubleClickHdl_Impl
));
855 m_xLinguModulesCLB
->connect_toggled(LINK(this, SvxLinguTabPage
, ModulesBoxCheckButtonHdl_Impl
));
857 m_xLinguModulesEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
858 m_xLinguOptionsEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
860 m_xLinguDicsCLB
->connect_changed( LINK( this, SvxLinguTabPage
, SelectHdl_Impl
));
861 m_xLinguDicsCLB
->connect_toggled(LINK(this, SvxLinguTabPage
, DicsBoxCheckButtonHdl_Impl
));
863 m_xLinguDicsNewPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
864 m_xLinguDicsEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
865 m_xLinguDicsDelPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
867 m_xLinguOptionsCLB
->connect_changed( LINK( this, SvxLinguTabPage
, SelectHdl_Impl
));
868 m_xLinguOptionsCLB
->connect_row_activated(LINK(this, SvxLinguTabPage
, BoxDoubleClickHdl_Impl
));
870 m_xMoreDictsLink
->connect_activate_link(LINK(this, SvxLinguTabPage
, OnLinkClick
));
871 if (officecfg::Office::Security::Hyperlinks::Open::get() == SvtExtendedSecurityOptions::OPEN_NEVER
)
872 m_xMoreDictsBox
->hide();
874 if (comphelper::LibreOfficeKit::isActive())
876 // hide User-defined Dictionaries part
877 m_xBuilder
->weld_frame("dictsframe")->hide();
878 // hide Get more dictionaries URL + icon
879 m_xMoreDictsBox
->hide();
882 xProp
= LinguMgr::GetLinguPropertySet();
883 xDicList
.set( LinguMgr::GetDictionaryList() );
886 // keep references to all **currently** available dictionaries,
887 // since the diclist may get changed meanwhile (e.g. through the API).
888 // We want the dialog to operate on the same set of dictionaries it
890 // Also we have to take care to not lose the last reference when
891 // someone else removes a dictionary from the list.
892 // removed dics will be replaced by NULL new entries be added to the end
893 // Thus we may use indices as consistent references.
894 aDics
= xDicList
->getDictionaries();
900 m_xLinguDicsFT
->set_sensitive(false);
901 m_xLinguDicsCLB
->set_sensitive(false);
902 m_xLinguDicsNewPB
->set_sensitive(false);
903 m_xLinguDicsEditPB
->set_sensitive(false);
904 m_xLinguDicsDelPB
->set_sensitive(false);
908 SvxLinguTabPage::~SvxLinguTabPage()
910 if (m_nDlbClickEventId
)
912 Application::RemoveUserEvent(m_nDlbClickEventId
);
913 m_nDlbClickEventId
= nullptr;
918 std::unique_ptr
<SfxTabPage
> SvxLinguTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
919 const SfxItemSet
* rAttrSet
)
921 return std::make_unique
<SvxLinguTabPage
>( pPage
, pController
, *rAttrSet
);
924 bool SvxLinguTabPage::FillItemSet( SfxItemSet
* rCoreSet
)
926 bool bModified
= true; // !!!!
928 // if not HideGroups was called with GROUP_MODULES...
929 if (m_xLinguModulesCLB
->get_visible())
931 DBG_ASSERT( pLinguData
, "pLinguData not yet initialized" );
933 pLinguData
.reset( new SvxLinguData_Impl
);
935 // update spellchecker configuration entries
936 const LangImplNameTable
*pTable
= &pLinguData
->GetSpellTable();
937 for (auto const& elem
: *pTable
)
939 LanguageType nLang
= elem
.first
;
940 const Sequence
< OUString
> aImplNames(elem
.second
);
941 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
942 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
944 xMgr
->setConfiguredServices( cSpell
, aLocale
, aImplNames
);
947 // update grammar checker configuration entries
948 pTable
= &pLinguData
->GetGrammarTable();
949 for (auto const& elem
: *pTable
)
951 LanguageType nLang
= elem
.first
;
952 const Sequence
< OUString
> aImplNames(elem
.second
);
953 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
954 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
956 xMgr
->setConfiguredServices( cGrammar
, aLocale
, aImplNames
);
959 // update hyphenator configuration entries
960 pTable
= &pLinguData
->GetHyphTable();
961 for (auto const& elem
: *pTable
)
963 LanguageType nLang
= elem
.first
;
964 const Sequence
< OUString
> aImplNames(elem
.second
);
965 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
966 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
968 xMgr
->setConfiguredServices( cHyph
, aLocale
, aImplNames
);
971 // update thesaurus configuration entries
972 pTable
= &pLinguData
->GetThesTable();
973 for (auto const& elem
: *pTable
)
975 LanguageType nLang
= elem
.first
;
976 const Sequence
< OUString
> aImplNames(elem
.second
);
977 uno::Reference
< XLinguServiceManager2
> xMgr( pLinguData
->GetManager() );
978 Locale
aLocale( LanguageTag::convertToLocale(nLang
) );
980 xMgr
->setConfiguredServices( cThes
, aLocale
, aImplNames
);
985 // activate dictionaries according to checkbox state
987 Sequence
< OUString
> aActiveDics
;
988 sal_Int32 nActiveDics
= 0;
989 int nEntries
= m_xLinguDicsCLB
->n_children();
990 for (int i
= 0; i
< nEntries
; ++i
)
992 sal_Int32 nDics
= aDics
.getLength();
994 aActiveDics
.realloc( nDics
);
995 OUString
*pActiveDic
= aActiveDics
.getArray();
997 DicUserData
aData(m_xLinguDicsCLB
->get_id(i
).toUInt32());
998 if (aData
.GetEntryId() < nDics
)
1000 bool bChecked
= m_xLinguDicsCLB
->get_toggle(i
) == TRISTATE_TRUE
;
1001 uno::Reference
< XDictionary
> xDic( aDics
.getConstArray()[ i
] );
1004 if (LinguMgr::GetIgnoreAllList() == xDic
)
1006 xDic
->setActive( bChecked
);
1010 OUString
aDicName( xDic
->getName() );
1011 pActiveDic
[ nActiveDics
++ ] = aDicName
;
1017 aActiveDics
.realloc( nActiveDics
);
1019 aTmp
<<= aActiveDics
;
1020 SvtLinguConfig aLngCfg
;
1021 aLngCfg
.SetProperty( UPH_ACTIVE_DICTIONARIES
, aTmp
);
1024 nEntries
= m_xLinguOptionsCLB
->n_children();
1025 for (int j
= 0; j
< nEntries
; ++j
)
1027 OptionsUserData
aData(m_xLinguOptionsCLB
->get_id(j
).toUInt32());
1028 OUString
aPropName( lcl_GetPropertyName( static_cast<EID_OPTIONS
>(aData
.GetEntryId()) ) );
1031 if (aData
.IsCheckable())
1033 bool bChecked
= m_xLinguOptionsCLB
->get_toggle(j
) == TRISTATE_TRUE
;
1036 else if (aData
.HasNumericValue())
1038 sal_Int16 nVal
= aData
.GetNumericValue();
1043 xProp
->setPropertyValue( aPropName
, aAny
);
1044 aLngCfg
.SetProperty( aPropName
, aAny
);
1047 OptionsUserData
aPreBreakData(m_xLinguOptionsCLB
->get_id(EID_NUM_PRE_BREAK
).toUInt32());
1048 OptionsUserData
aPostBreakData(m_xLinguOptionsCLB
->get_id(EID_NUM_POST_BREAK
).toUInt32());
1049 if ( aPreBreakData
.IsModified() || aPostBreakData
.IsModified() )
1051 SfxHyphenRegionItem
aHyp( SID_ATTR_HYPHENREGION
);
1052 aHyp
.GetMinLead() = static_cast<sal_uInt8
>(aPreBreakData
.GetNumericValue());
1053 aHyp
.GetMinTrail() = static_cast<sal_uInt8
>(aPostBreakData
.GetNumericValue());
1054 rCoreSet
->Put( aHyp
);
1057 // automatic spell checking
1058 bool bNewAutoCheck
= m_xLinguOptionsCLB
->get_toggle(EID_SPELL_AUTO
) == TRISTATE_TRUE
;
1059 const SfxPoolItem
* pOld
= GetOldItem( *rCoreSet
, SID_AUTOSPELL_CHECK
);
1060 if ( !pOld
|| static_cast<const SfxBoolItem
*>(pOld
)->GetValue() != bNewAutoCheck
)
1062 rCoreSet
->Put( SfxBoolItem( SID_AUTOSPELL_CHECK
, bNewAutoCheck
) );
1069 sal_uInt32
SvxLinguTabPage::GetDicUserData( const uno::Reference
< XDictionary
> &rxDic
, sal_uInt16 nIdx
)
1071 sal_uInt32 nRes
= 0;
1072 DBG_ASSERT( rxDic
.is(), "dictionary not supplied" );
1075 uno::Reference
< frame::XStorable
> xStor( rxDic
, UNO_QUERY
);
1077 bool bChecked
= rxDic
->isActive();
1078 bool bEditable
= !xStor
.is() || !xStor
->isReadonly();
1079 bool bDeletable
= bEditable
;
1081 nRes
= DicUserData( nIdx
,
1082 bChecked
, bEditable
, bDeletable
).GetUserData();
1088 void SvxLinguTabPage::AddDicBoxEntry(
1089 const uno::Reference
< XDictionary
> &rxDic
,
1092 m_xLinguDicsCLB
->freeze();
1094 OUString
aTxt( ::GetDicInfoStr( rxDic
->getName(),
1095 LanguageTag( rxDic
->getLocale() ).getLanguageType(),
1096 DictionaryType_NEGATIVE
== rxDic
->getDictionaryType() ) );
1097 m_xLinguDicsCLB
->append(); // append at end
1098 int nEntry
= m_xLinguDicsCLB
->n_children() - 1;
1099 DicUserData
aData( GetDicUserData( rxDic
, nIdx
) );
1100 m_xLinguDicsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1101 m_xLinguDicsCLB
->set_toggle(nEntry
, aData
.IsChecked() ? TRISTATE_TRUE
: TRISTATE_FALSE
);
1102 m_xLinguDicsCLB
->set_text(nEntry
, aTxt
, 0); // append at end
1104 m_xLinguDicsCLB
->thaw();
1107 void SvxLinguTabPage::UpdateDicBox_Impl()
1109 m_xLinguDicsCLB
->freeze();
1110 m_xLinguDicsCLB
->clear();
1112 sal_Int32 nDics
= aDics
.getLength();
1113 const uno::Reference
< XDictionary
> *pDic
= aDics
.getConstArray();
1114 for (sal_Int32 i
= 0; i
< nDics
; ++i
)
1116 const uno::Reference
< XDictionary
> &rDic
= pDic
[i
];
1118 AddDicBoxEntry( rDic
, static_cast<sal_uInt16
>(i
) );
1121 m_xLinguDicsCLB
->thaw();
1122 if (m_xLinguDicsCLB
->n_children())
1124 m_xLinguDicsCLB
->select(0);
1125 SelectHdl_Impl(*m_xLinguDicsCLB
);
1129 void SvxLinguTabPage::UpdateModulesBox_Impl()
1134 const ServiceInfoArr
&rAllDispSrvcArr
= pLinguData
->GetDisplayServiceArray();
1135 const sal_uInt32 nDispSrvcCount
= pLinguData
->GetDisplayServiceCount();
1137 m_xLinguModulesCLB
->clear();
1139 for (sal_uInt32 i
= 0; i
< nDispSrvcCount
; ++i
)
1141 const ServiceInfo_Impl
&rInfo
= rAllDispSrvcArr
[i
];
1142 m_xLinguModulesCLB
->append();
1143 m_xLinguModulesCLB
->set_id(i
, weld::toId(&rInfo
));
1144 m_xLinguModulesCLB
->set_toggle(i
, rInfo
.bConfigured
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1145 m_xLinguModulesCLB
->set_text(i
, rInfo
.sDisplayName
, 0);
1149 m_xLinguModulesCLB
->select(0);
1150 SelectHdl_Impl(*m_xLinguModulesCLB
);
1152 m_xLinguModulesEditPB
->set_sensitive( nDispSrvcCount
> 0 );
1155 void SvxLinguTabPage::Reset( const SfxItemSet
* rSet
)
1157 // if not HideGroups was called with GROUP_MODULES...
1158 if (m_xLinguModulesCLB
->get_visible())
1161 pLinguData
.reset( new SvxLinguData_Impl
);
1162 UpdateModulesBox_Impl();
1166 // get data from configuration
1167 SvtLinguConfig aLngCfg
;
1169 m_xLinguOptionsCLB
->freeze();
1170 m_xLinguOptionsCLB
->clear();
1174 sal_uInt32 nUserData
= 0;
1176 m_xLinguOptionsCLB
->append();
1179 aLngCfg
.GetProperty( UPN_IS_SPELL_AUTO
) >>= bVal
;
1180 const SfxPoolItem
* pItem
= GetItem( *rSet
, SID_AUTOSPELL_CHECK
);
1182 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1183 nUserData
= OptionsUserData( EID_SPELL_AUTO
, false, 0, true, bVal
).GetUserData();
1184 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1185 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellAuto
, 0);
1186 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1188 m_xLinguOptionsCLB
->append();
1191 aLngCfg
.GetProperty( UPN_IS_GRAMMAR_AUTO
) >>= bVal
;
1192 nUserData
= OptionsUserData( EID_GRAMMAR_AUTO
, false, 0, true, bVal
).GetUserData();
1193 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1194 m_xLinguOptionsCLB
->set_text(nEntry
, sGrammarAuto
, 0);
1195 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1197 m_xLinguOptionsCLB
->append();
1200 aLngCfg
.GetProperty( UPN_IS_SPELL_UPPER_CASE
) >>= bVal
;
1201 nUserData
= OptionsUserData( EID_CAPITAL_WORDS
, false, 0, true, bVal
).GetUserData();
1202 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1203 m_xLinguOptionsCLB
->set_text(nEntry
, sCapitalWords
, 0);
1204 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1206 m_xLinguOptionsCLB
->append();
1209 aLngCfg
.GetProperty( UPN_IS_SPELL_WITH_DIGITS
) >>= bVal
;
1210 nUserData
= OptionsUserData( EID_WORDS_WITH_DIGITS
, false, 0, true, bVal
).GetUserData();
1211 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1212 m_xLinguOptionsCLB
->set_text(nEntry
, sWordsWithDigits
, 0);
1213 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1215 m_xLinguOptionsCLB
->append();
1218 aLngCfg
.GetProperty( UPN_IS_SPELL_CLOSED_COMPOUND
) >>= bVal
;
1219 nUserData
= OptionsUserData( EID_SPELL_CLOSED_COMPOUND
, false, 0, true, bVal
).GetUserData();
1220 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1221 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellClosedCompound
, 0);
1222 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1224 m_xLinguOptionsCLB
->append();
1227 aLngCfg
.GetProperty( UPN_IS_SPELL_HYPHENATED_COMPOUND
) >>= bVal
;
1228 nUserData
= OptionsUserData( EID_SPELL_HYPHENATED_COMPOUND
, false, 0, true, bVal
).GetUserData();
1229 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1230 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellHyphenatedCompound
, 0);
1231 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1233 m_xLinguOptionsCLB
->append();
1236 aLngCfg
.GetProperty( UPN_IS_SPELL_SPECIAL
) >>= bVal
;
1237 nUserData
= OptionsUserData( EID_SPELL_SPECIAL
, false, 0, true, bVal
).GetUserData();
1238 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1239 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellSpecial
, 0);
1240 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1242 m_xLinguOptionsCLB
->append();
1245 aLngCfg
.GetProperty( UPN_HYPH_MIN_WORD_LENGTH
) >>= nVal
;
1246 nUserData
= OptionsUserData( EID_NUM_MIN_WORDLEN
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1247 m_xLinguOptionsCLB
->set_text(nEntry
, sNumMinWordlen
+ " " + OUString::number(nVal
), 0);
1248 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1249 nUPN_HYPH_MIN_WORD_LENGTH
= nEntry
;
1251 const SfxHyphenRegionItem
*pHyp
= nullptr;
1252 if ( rSet
->GetItemState( SID_ATTR_HYPHENREGION
, false ) == SfxItemState::SET
)
1253 pHyp
= & rSet
->Get( SID_ATTR_HYPHENREGION
);
1255 m_xLinguOptionsCLB
->append();
1258 aLngCfg
.GetProperty( UPN_HYPH_MIN_LEADING
) >>= nVal
;
1260 nVal
= static_cast<sal_Int16
>(pHyp
->GetMinLead());
1261 nUserData
= OptionsUserData( EID_NUM_PRE_BREAK
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1262 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPreBreak
+ " " + OUString::number(nVal
), 0);
1263 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1264 nUPN_HYPH_MIN_LEADING
= nEntry
;
1266 m_xLinguOptionsCLB
->append();
1269 aLngCfg
.GetProperty( UPN_HYPH_MIN_TRAILING
) >>= nVal
;
1271 nVal
= static_cast<sal_Int16
>(pHyp
->GetMinTrail());
1272 nUserData
= OptionsUserData( EID_NUM_POST_BREAK
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1273 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPostBreak
+ " " + OUString::number(nVal
), 0);
1274 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1275 nUPN_HYPH_MIN_TRAILING
= nEntry
;
1277 m_xLinguOptionsCLB
->append();
1280 aLngCfg
.GetProperty( UPN_IS_HYPH_AUTO
) >>= bVal
;
1281 nUserData
= OptionsUserData( EID_HYPH_AUTO
, false, 0, true, bVal
).GetUserData();
1282 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1283 m_xLinguOptionsCLB
->set_text(nEntry
, sHyphAuto
, 0);
1284 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1286 m_xLinguOptionsCLB
->append();
1289 aLngCfg
.GetProperty( UPN_IS_HYPH_SPECIAL
) >>= bVal
;
1290 nUserData
= OptionsUserData( EID_HYPH_SPECIAL
, false, 0, true, bVal
).GetUserData();
1291 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1292 m_xLinguOptionsCLB
->set_text(nEntry
, sHyphSpecial
, 0);
1293 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1295 m_xLinguOptionsCLB
->thaw();
1297 m_xLinguOptionsCLB
->select(0);
1298 SelectHdl_Impl(*m_xLinguOptionsCLB
);
1300 m_xLinguModulesCLB
->set_size_request(m_xLinguModulesCLB
->get_preferred_size().Width(),
1301 m_xLinguModulesCLB
->get_height_rows(3));
1302 m_xLinguDicsCLB
->set_size_request(m_xLinguDicsCLB
->get_preferred_size().Width(),
1303 m_xLinguDicsCLB
->get_height_rows(5));
1304 m_xLinguOptionsCLB
->set_size_request(m_xLinguOptionsCLB
->get_preferred_size().Width(),
1305 m_xLinguOptionsCLB
->get_height_rows(5));
1308 IMPL_LINK(SvxLinguTabPage
, BoxDoubleClickHdl_Impl
, weld::TreeView
&, rBox
, bool)
1310 if (&rBox
== m_xLinguModulesCLB
.get() && !m_nDlbClickEventId
)
1312 //! in order to avoid a bug causing a GPF when double clicking
1313 //! on a module entry and exiting the "Edit Modules" dialog
1315 m_nDlbClickEventId
= Application::PostUserEvent(LINK(this, SvxLinguTabPage
, PostDblClickHdl_Impl
));
1317 else if (&rBox
== m_xLinguOptionsCLB
.get())
1319 ClickHdl_Impl(*m_xLinguOptionsEditPB
);
1324 IMPL_LINK_NOARG(SvxLinguTabPage
, PostDblClickHdl_Impl
, void*, void)
1326 m_nDlbClickEventId
= nullptr;
1327 ClickHdl_Impl(*m_xLinguModulesEditPB
);
1330 IMPL_LINK(SvxLinguTabPage
, ModulesBoxCheckButtonHdl_Impl
, const weld::TreeView::iter_col
&, rRowCol
, void)
1334 pLinguData
->Reconfigure(m_xLinguModulesCLB
->get_text(rRowCol
.first
),
1335 m_xLinguModulesCLB
->get_toggle(rRowCol
.first
) == TRISTATE_TRUE
);
1338 IMPL_LINK(SvxLinguTabPage
, DicsBoxCheckButtonHdl_Impl
, const weld::TreeView::iter_col
&, rRowCol
, void)
1340 const uno::Reference
<XDictionary
> &rDic
= aDics
.getConstArray()[m_xLinguDicsCLB
->get_iter_index_in_parent(rRowCol
.first
)];
1341 if (LinguMgr::GetIgnoreAllList() == rDic
)
1342 m_xLinguDicsCLB
->set_toggle(rRowCol
.first
, TRISTATE_TRUE
);
1345 IMPL_LINK(SvxLinguTabPage
, ClickHdl_Impl
, weld::Button
&, rBtn
, void)
1347 if (m_xLinguModulesEditPB
.get() == &rBtn
)
1350 pLinguData
.reset( new SvxLinguData_Impl
);
1352 SvxLinguData_Impl
aOldLinguData( *pLinguData
);
1353 SvxEditModulesDlg
aDlg(GetFrameWeld(), *pLinguData
);
1354 if (aDlg
.run() != RET_OK
)
1355 *pLinguData
= aOldLinguData
;
1357 // evaluate new status of 'bConfigured' flag
1358 sal_uInt32 nLen
= pLinguData
->GetDisplayServiceCount();
1359 for (sal_uInt32 i
= 0; i
< nLen
; ++i
)
1360 pLinguData
->GetDisplayServiceArray()[i
].bConfigured
= false;
1361 for (const auto& locale
: pLinguData
->GetAllSupportedLocales())
1363 LanguageType nLang
= LanguageTag::convertToLanguageType(locale
);
1364 if (pLinguData
->GetSpellTable().count( nLang
))
1365 pLinguData
->SetChecked( pLinguData
->GetSpellTable()[ nLang
] );
1366 if (pLinguData
->GetGrammarTable().count( nLang
))
1367 pLinguData
->SetChecked( pLinguData
->GetGrammarTable()[ nLang
] );
1368 if (pLinguData
->GetHyphTable().count( nLang
))
1369 pLinguData
->SetChecked( pLinguData
->GetHyphTable()[ nLang
] );
1370 if (pLinguData
->GetThesTable().count( nLang
))
1371 pLinguData
->SetChecked( pLinguData
->GetThesTable()[ nLang
] );
1374 // show new status of modules
1375 UpdateModulesBox_Impl();
1377 else if (m_xLinguDicsNewPB
.get() == &rBtn
)
1379 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1380 ScopedVclPtr
<AbstractSvxNewDictionaryDialog
> aDlg(pFact
->CreateSvxNewDictionaryDialog(GetFrameWeld()));
1381 uno::Reference
< XDictionary
> xNewDic
;
1382 if ( aDlg
->Execute() == RET_OK
)
1383 xNewDic
= aDlg
->GetNewDictionary();
1386 // add new dics to the end
1387 sal_Int32 nLen
= aDics
.getLength();
1388 aDics
.realloc( nLen
+ 1 );
1390 aDics
.getArray()[ nLen
] = xNewDic
;
1392 AddDicBoxEntry( xNewDic
, static_cast<sal_uInt16
>(nLen
) );
1395 else if (m_xLinguDicsEditPB
.get() == &rBtn
)
1397 int nEntry
= m_xLinguDicsCLB
->get_selected_index();
1400 DicUserData
aData(m_xLinguDicsCLB
->get_id(nEntry
).toUInt32());
1401 sal_uInt16 nDicPos
= aData
.GetEntryId();
1402 sal_Int32 nDics
= aDics
.getLength();
1403 if (nDicPos
< nDics
)
1405 uno::Reference
< XDictionary
> xDic
= aDics
.getConstArray()[ nDicPos
];
1408 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1409 ScopedVclPtr
<VclAbstractDialog
> aDlg(pFact
->CreateSvxEditDictionaryDialog(GetFrameWeld(), xDic
->getName()));
1415 else if (m_xLinguDicsDelPB
.get() == &rBtn
)
1417 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletedictionarydialog.ui"));
1418 std::unique_ptr
<weld::MessageDialog
> xQuery(xBuilder
->weld_message_dialog("QueryDeleteDictionaryDialog"));
1419 if (RET_NO
== xQuery
->run())
1422 int nEntry
= m_xLinguDicsCLB
->get_selected_index();
1425 DicUserData
aData(m_xLinguDicsCLB
->get_id(nEntry
).toUInt32());
1426 sal_uInt16 nDicPos
= aData
.GetEntryId();
1427 sal_Int32 nDics
= aDics
.getLength();
1428 if (nDicPos
< nDics
)
1430 uno::Reference
< XDictionary
> xDic
= aDics
.getConstArray()[ nDicPos
];
1433 if (LinguMgr::GetIgnoreAllList() == xDic
)
1438 xDicList
->removeDictionary( xDic
);
1440 uno::Reference
< frame::XStorable
> xStor( xDic
, UNO_QUERY
);
1441 if ( xStor
->hasLocation() && !xStor
->isReadonly() )
1443 OUString sURL
= xStor
->getLocation();
1444 INetURLObject
aObj(sURL
);
1445 DBG_ASSERT( aObj
.GetProtocol() == INetProtocol::File
,
1446 "non-file URLs cannot be deleted" );
1447 if ( aObj
.GetProtocol() == INetProtocol::File
)
1449 KillFile_Impl( aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1453 aDics
.getArray()[ nDicPos
] = nullptr;
1455 // remove entry from checklistbox
1456 int nCnt
= m_xLinguDicsCLB
->n_children();
1457 for (int i
= 0; i
< nCnt
; ++i
)
1459 DicUserData
aDicData(m_xLinguDicsCLB
->get_id(i
).toUInt32());
1460 if (aDicData
.GetEntryId() == nDicPos
)
1462 m_xLinguDicsCLB
->remove(i
);
1466 DBG_ASSERT( nCnt
> m_xLinguDicsCLB
->n_children(),
1473 else if (m_xLinguOptionsEditPB
.get() == &rBtn
)
1475 int nEntry
= m_xLinguOptionsCLB
->get_selected_index();
1476 DBG_ASSERT(nEntry
!= -1, "no entry selected");
1479 OptionsUserData
aData(m_xLinguOptionsCLB
->get_id(nEntry
).toUInt32());
1480 if (aData
.HasNumericValue())
1482 sal_uInt16 nRID
= aData
.GetEntryId();
1483 OptionsBreakSet
aDlg(GetFrameWeld(), nRID
);
1484 aDlg
.GetNumericFld().set_value(aData
.GetNumericValue());
1485 if (RET_OK
== aDlg
.run())
1487 int nVal
= aDlg
.GetNumericFld().get_value();
1488 if (-1 != nVal
&& aData
.GetNumericValue() != nVal
)
1490 aData
.SetNumericValue( static_cast<sal_uInt8
>(nVal
) ); //! sets IsModified !
1491 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1492 if (nEntry
== nUPN_HYPH_MIN_WORD_LENGTH
)
1493 m_xLinguOptionsCLB
->set_text(nEntry
, sNumMinWordlen
+ " " + OUString::number(nVal
), 0);
1494 else if (nEntry
== nUPN_HYPH_MIN_LEADING
)
1495 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPreBreak
+ " " + OUString::number(nVal
), 0);
1496 else if (nEntry
== nUPN_HYPH_MIN_TRAILING
)
1497 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPostBreak
+ " " + OUString::number(nVal
), 0);
1498 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1506 SAL_WARN("cui.options", "rBtn unexpected value");
1510 IMPL_LINK(SvxLinguTabPage
, SelectHdl_Impl
, weld::TreeView
&, rBox
, void)
1512 if (m_xLinguModulesCLB
.get() == &rBox
)
1515 else if (m_xLinguDicsCLB
.get() == &rBox
)
1517 int nEntry
= rBox
.get_selected_index();
1520 DicUserData
aData(rBox
.get_id(nEntry
).toUInt32());
1522 // always allow to edit (i.e. at least view the content of the dictionary)
1523 m_xLinguDicsEditPB
->set_sensitive( true );
1524 m_xLinguDicsDelPB
->set_sensitive( aData
.IsDeletable() );
1527 else if (m_xLinguOptionsCLB
.get() == &rBox
)
1529 int nEntry
= rBox
.get_selected_index();
1532 OptionsUserData
aData(rBox
.get_id(nEntry
).toUInt32());
1533 m_xLinguOptionsEditPB
->set_sensitive( aData
.HasNumericValue() );
1538 SAL_WARN("cui.options", "rBtn unexpected value");
1542 void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp
)
1544 if ( 0 != ( GROUP_MODULES
& nGrp
) )
1546 m_xLinguModulesFT
->hide();
1547 m_xLinguModulesCLB
->hide();
1548 m_xLinguModulesEditPB
->hide();
1550 if (officecfg::Office::Security::Hyperlinks::Open::get() != SvtExtendedSecurityOptions::OPEN_NEVER
&&
1551 !comphelper::LibreOfficeKit::isActive())
1553 m_xMoreDictsBox
->show();
1558 IMPL_STATIC_LINK_NOARG(SvxLinguTabPage
, OnLinkClick
, weld::LinkButton
&, bool)
1560 comphelper::dispatchCommand(".uno:MoreDictionaries", {});
1564 SvxEditModulesDlg::SvxEditModulesDlg(weld::Window
* pParent
, SvxLinguData_Impl
& rData
)
1565 : GenericDialogController(pParent
, "cui/ui/editmodulesdialog.ui", "EditModulesDialog")
1566 , sSpell(CuiResId(RID_CUISTR_SPELL
))
1567 , sHyph(CuiResId(RID_CUISTR_HYPH
))
1568 , sThes(CuiResId(RID_CUISTR_THES
))
1569 , sGrammar(CuiResId(RID_CUISTR_GRAMMAR
))
1571 , m_xModulesCLB(m_xBuilder
->weld_tree_view("lingudicts"))
1572 , m_xPrioUpPB(m_xBuilder
->weld_button("up"))
1573 , m_xPrioDownPB(m_xBuilder
->weld_button("down"))
1574 , m_xBackPB(m_xBuilder
->weld_button("back"))
1575 , m_xMoreDictsLink(m_xBuilder
->weld_link_button("moredictslink"))
1576 , m_xClosePB(m_xBuilder
->weld_button("close"))
1577 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder
->weld_combo_box("language")))
1579 m_xModulesCLB
->set_size_request(m_xModulesCLB
->get_approximate_digit_width() * 40,
1580 m_xModulesCLB
->get_height_rows(12));
1582 m_xModulesCLB
->enable_toggle_buttons(weld::ColumnToggleType::Check
);
1584 pDefaultLinguData
.reset( new SvxLinguData_Impl( rLinguData
) );
1586 m_xModulesCLB
->connect_changed( LINK( this, SvxEditModulesDlg
, SelectHdl_Impl
));
1587 m_xModulesCLB
->connect_toggled(LINK(this, SvxEditModulesDlg
, BoxCheckButtonHdl_Impl
));
1589 m_xClosePB
->connect_clicked( LINK( this, SvxEditModulesDlg
, ClickHdl_Impl
));
1590 m_xPrioUpPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, UpDownHdl_Impl
));
1591 m_xPrioDownPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, UpDownHdl_Impl
));
1592 m_xBackPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, BackHdl_Impl
));
1593 // in case of not installed language modules
1594 m_xPrioUpPB
->set_sensitive( false );
1595 m_xPrioDownPB
->set_sensitive( false );
1597 m_xMoreDictsLink
->connect_activate_link(LINK(this, SvxEditModulesDlg
, OnLinkClick
));
1598 if (officecfg::Office::Security::Hyperlinks::Open::get() == SvtExtendedSecurityOptions::OPEN_NEVER
)
1599 m_xMoreDictsLink
->hide();
1601 // set that we want the checkbox shown if spellchecking is available
1602 m_xLanguageLB
->SetLanguageList(SvxLanguageListFlags::EMPTY
, false, false, true);
1605 const auto& rLoc
= rLinguData
.GetAllSupportedLocales();
1606 std::vector
<LanguageType
> aLanguages
;
1607 aLanguages
.reserve(rLoc
.size());
1608 std::transform(rLoc
.begin(), rLoc
.end(), std::back_inserter(aLanguages
),
1609 [](Locale
const& locale
) { return LanguageTag::convertToLanguageType(locale
); });
1610 m_xLanguageLB
->InsertLanguages(aLanguages
);
1611 LanguageType eSysLang
= MsLangId::getConfiguredSystemLanguage();
1612 m_xLanguageLB
->set_active_id( eSysLang
);
1613 if (m_xLanguageLB
->get_active_id() != eSysLang
)
1614 m_xLanguageLB
->set_active(0);
1616 m_xLanguageLB
->connect_changed( LINK( this, SvxEditModulesDlg
, LangSelectListBoxHdl_Impl
));
1617 LangSelectHdl_Impl(m_xLanguageLB
.get());
1620 SvxEditModulesDlg::~SvxEditModulesDlg()
1622 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1623 delete weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1626 IMPL_LINK( SvxEditModulesDlg
, SelectHdl_Impl
, weld::TreeView
&, rBox
, void )
1628 int nCurPos
= rBox
.get_selected_index();
1632 bool bDisableUp
= true;
1633 bool bDisableDown
= true;
1634 ModuleUserData_Impl
* pData
= weld::fromId
<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
));
1635 if (!pData
->IsParent() && pData
->GetType() != TYPE_HYPH
)
1637 if (nCurPos
< rBox
.n_children() - 1)
1639 bDisableDown
= weld::fromId
<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
+ 1))->IsParent();
1643 bDisableUp
= weld::fromId
<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
- 1))->IsParent();
1646 m_xPrioUpPB
->set_sensitive(!bDisableUp
);
1647 m_xPrioDownPB
->set_sensitive(!bDisableDown
);
1650 IMPL_LINK( SvxEditModulesDlg
, BoxCheckButtonHdl_Impl
, const weld::TreeView::iter_col
&, rRowCol
, void )
1652 ModuleUserData_Impl
* pData
= weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(rRowCol
.first
));
1653 if (pData
->IsParent() || pData
->GetType() != TYPE_HYPH
)
1656 // make hyphenator checkboxes function as radio-buttons
1657 // (at most one box may be checked)
1658 auto nPos
= m_xModulesCLB
->get_iter_index_in_parent(rRowCol
.first
);
1659 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1661 pData
= weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1662 if (!pData
->IsParent() && pData
->GetType() == TYPE_HYPH
&& i
!= nPos
)
1664 m_xModulesCLB
->set_toggle(i
, TRISTATE_FALSE
);
1669 IMPL_LINK_NOARG(SvxEditModulesDlg
, LangSelectListBoxHdl_Impl
, weld::ComboBox
&, void)
1671 LangSelectHdl_Impl(m_xLanguageLB
.get());
1674 void SvxEditModulesDlg::LangSelectHdl_Impl(const SvxLanguageBox
* pBox
)
1676 LanguageType eCurLanguage
= m_xLanguageLB
->get_active_id();
1677 static Locale aLastLocale
;
1678 Locale
aCurLocale( LanguageTag::convertToLocale( eCurLanguage
));
1682 // save old probably changed settings
1683 // before switching to new language entries
1685 LanguageType nLang
= LanguageTag::convertToLanguageType( aLastLocale
);
1687 sal_Int32 nStart
= 0, nLocalIndex
= 0;
1688 Sequence
< OUString
> aChange
;
1689 bool bChanged
= false;
1690 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1692 ModuleUserData_Impl
* pData
= weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1693 if (pData
->IsParent())
1697 LangImplNameTable
*pTable
= nullptr;
1698 sal_uInt8 nType
= pData
->GetType();
1701 case TYPE_SPELL
: pTable
= &rLinguData
.GetSpellTable(); break;
1702 case TYPE_GRAMMAR
: pTable
= &rLinguData
.GetGrammarTable(); break;
1703 case TYPE_HYPH
: pTable
= &rLinguData
.GetHyphTable(); break;
1704 case TYPE_THES
: pTable
= &rLinguData
.GetThesTable(); break;
1708 aChange
.realloc(nStart
);
1709 (*pTable
)[ nLang
] = aChange
;
1712 nLocalIndex
= nStart
= 0;
1713 aChange
.realloc(nEntryCount
);
1718 OUString
* pChange
= aChange
.getArray();
1719 pChange
[nStart
] = pData
->GetImplName();
1720 bChanged
|= pData
->GetIndex() != nLocalIndex
||
1721 static_cast<TriState
>(pData
->IsChecked()) != m_xModulesCLB
->get_toggle(i
);
1722 if (m_xModulesCLB
->get_toggle(i
))
1729 aChange
.realloc(nStart
);
1730 rLinguData
.GetThesTable()[ nLang
] = aChange
;
1734 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1735 delete weld::fromId
<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
));
1736 m_xModulesCLB
->clear();
1738 // display entries for new selected language
1740 if (LANGUAGE_DONTKNOW
!= eCurLanguage
)
1743 ServiceInfo_Impl
* pInfo
;
1746 // spellchecker entries
1748 ModuleUserData_Impl
* pUserData
= new ModuleUserData_Impl(
1749 OUString(), true, false, TYPE_SPELL
, 0 );
1750 OUString
sId(weld::toId(pUserData
));
1751 m_xModulesCLB
->append(nullptr);
1752 m_xModulesCLB
->set_id(nRow
, sId
);
1753 m_xModulesCLB
->set_text(nRow
, sSpell
, 0);
1754 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1757 Sequence
< OUString
> aNames( rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_SPELL
) );
1758 const OUString
*pName
= aNames
.getConstArray();
1759 sal_Int32 nNames
= aNames
.getLength();
1760 sal_Int32 nLocalIndex
= 0; // index relative to parent
1761 for (n
= 0; n
< nNames
; ++n
)
1764 bool bIsSuppLang
= false;
1766 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1769 bIsSuppLang
= pInfo
->xSpell
.is() &&
1770 pInfo
->xSpell
->hasLocale( aCurLocale
);
1771 aImplName
= pInfo
->sSpellImplName
;
1773 if (!aImplName
.isEmpty() && bIsSuppLang
)
1775 OUString
aTxt( pInfo
->sDisplayName
);
1777 LangImplNameTable
&rTable
= rLinguData
.GetSpellTable();
1778 const bool bHasLang
= rTable
.count( eCurLanguage
);
1781 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1783 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1784 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1785 bCheck
, TYPE_SPELL
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1786 sId
= weld::toId(pUserData
);
1788 m_xModulesCLB
->append(nullptr);
1789 m_xModulesCLB
->set_id(nRow
, sId
);
1790 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1791 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1792 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1797 // grammar checker entries
1799 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMAR
, 0 );
1800 sId
= weld::toId(pUserData
);
1801 m_xModulesCLB
->append(nullptr);
1802 m_xModulesCLB
->set_id(nRow
, sId
);
1803 m_xModulesCLB
->set_text(nRow
, sGrammar
, 0);
1804 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1807 aNames
= rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_GRAMMAR
);
1808 pName
= aNames
.getConstArray();
1809 nNames
= aNames
.getLength();
1811 for (n
= 0; n
< nNames
; ++n
)
1814 bool bIsSuppLang
= false;
1816 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1819 bIsSuppLang
= pInfo
->xGrammar
.is() &&
1820 pInfo
->xGrammar
->hasLocale( aCurLocale
);
1821 aImplName
= pInfo
->sGrammarImplName
;
1823 if (!aImplName
.isEmpty() && bIsSuppLang
)
1825 OUString
aTxt( pInfo
->sDisplayName
);
1827 LangImplNameTable
&rTable
= rLinguData
.GetGrammarTable();
1828 const bool bHasLang
= rTable
.count( eCurLanguage
);
1831 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1833 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1834 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1835 bCheck
, TYPE_GRAMMAR
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1837 sId
= weld::toId(pUserData
);
1839 m_xModulesCLB
->append(nullptr);
1840 m_xModulesCLB
->set_id(nRow
, sId
);
1841 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1842 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1843 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1848 // hyphenator entries
1850 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPH
, 0 );
1851 sId
= weld::toId(pUserData
);
1852 m_xModulesCLB
->append(nullptr);
1853 m_xModulesCLB
->set_id(nRow
, sId
);
1854 m_xModulesCLB
->set_text(nRow
, sHyph
, 0);
1855 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1858 aNames
= rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_HYPH
);
1859 pName
= aNames
.getConstArray();
1860 nNames
= aNames
.getLength();
1862 for (n
= 0; n
< nNames
; ++n
)
1865 bool bIsSuppLang
= false;
1867 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1870 bIsSuppLang
= pInfo
->xHyph
.is() &&
1871 pInfo
->xHyph
->hasLocale( aCurLocale
);
1872 aImplName
= pInfo
->sHyphImplName
;
1874 if (!aImplName
.isEmpty() && bIsSuppLang
)
1876 OUString
aTxt( pInfo
->sDisplayName
);
1878 LangImplNameTable
&rTable
= rLinguData
.GetHyphTable();
1879 const bool bHasLang
= rTable
.count( eCurLanguage
);
1882 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1884 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1885 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1886 bCheck
, TYPE_HYPH
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1887 sId
= weld::toId(pUserData
);
1889 m_xModulesCLB
->append(nullptr);
1890 m_xModulesCLB
->set_id(nRow
, sId
);
1891 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1892 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1893 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1898 // thesaurus entries
1900 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_THES
, 0 );
1901 sId
= weld::toId(pUserData
);
1902 m_xModulesCLB
->append(nullptr);
1903 m_xModulesCLB
->set_id(nRow
, sId
);
1904 m_xModulesCLB
->set_text(nRow
, sThes
, 0);
1905 m_xModulesCLB
->set_text_emphasis(nRow
, true, 0);
1908 aNames
= rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_THES
);
1909 pName
= aNames
.getConstArray();
1910 nNames
= aNames
.getLength();
1912 for (n
= 0; n
< nNames
; ++n
)
1915 bool bIsSuppLang
= false;
1917 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1920 bIsSuppLang
= pInfo
->xThes
.is() &&
1921 pInfo
->xThes
->hasLocale( aCurLocale
);
1922 aImplName
= pInfo
->sThesImplName
;
1924 if (!aImplName
.isEmpty() && bIsSuppLang
)
1926 OUString
aTxt( pInfo
->sDisplayName
);
1928 LangImplNameTable
&rTable
= rLinguData
.GetThesTable();
1929 const bool bHasLang
= rTable
.count( eCurLanguage
);
1932 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1934 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1935 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1936 bCheck
, TYPE_THES
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1937 sId
= weld::toId(pUserData
);
1939 m_xModulesCLB
->append(nullptr);
1940 m_xModulesCLB
->set_id(nRow
, sId
);
1941 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1942 m_xModulesCLB
->set_text(nRow
, aTxt
, 0);
1943 m_xModulesCLB
->set_text_emphasis(nRow
, false, 0);
1948 aLastLocale
= aCurLocale
;
1951 IMPL_LINK( SvxEditModulesDlg
, UpDownHdl_Impl
, weld::Button
&, rBtn
, void )
1953 bool bUp
= m_xPrioUpPB
.get() == &rBtn
;
1954 int nCurPos
= m_xModulesCLB
->get_selected_index();
1958 m_xModulesCLB
->freeze();
1960 OUString
sId(m_xModulesCLB
->get_id(nCurPos
));
1961 OUString
sStr(m_xModulesCLB
->get_text(nCurPos
));
1962 bool bIsChecked
= m_xModulesCLB
->get_toggle(nCurPos
);
1964 m_xModulesCLB
->remove(nCurPos
);
1966 int nDestPos
= bUp
? nCurPos
- 1 : nCurPos
+ 1;
1968 m_xModulesCLB
->insert_text(nDestPos
, sStr
);
1969 m_xModulesCLB
->set_id(nDestPos
, sId
);
1970 m_xModulesCLB
->set_toggle(nDestPos
, bIsChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
);
1972 m_xModulesCLB
->thaw();
1974 m_xModulesCLB
->select(nDestPos
);
1975 SelectHdl_Impl(*m_xModulesCLB
);
1978 IMPL_LINK_NOARG(SvxEditModulesDlg
, ClickHdl_Impl
, weld::Button
&, void)
1980 // store language config
1981 LangSelectHdl_Impl(m_xLanguageLB
.get());
1982 m_xDialog
->response(RET_OK
);
1985 IMPL_LINK_NOARG(SvxEditModulesDlg
, BackHdl_Impl
, weld::Button
&, void)
1987 rLinguData
= *pDefaultLinguData
;
1988 LangSelectHdl_Impl(nullptr);
1991 IMPL_STATIC_LINK_NOARG(SvxEditModulesDlg
, OnLinkClick
, weld::LinkButton
&, bool)
1993 comphelper::dispatchCommand(".uno:MoreDictionaries", {});
1997 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */