1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/settings.hxx>
21 #include <vcl/weld.hxx>
22 #include <i18nlangtag/languagetag.hxx>
23 #include <i18nlangtag/mslangid.hxx>
24 #include <unotools/lingucfg.hxx>
25 #include <unotools/linguprops.hxx>
26 #include <editeng/unolingu.hxx>
27 #include <linguistic/misc.hxx>
28 #include <sfx2/sfxsids.hrc>
29 #include <tools/debug.hxx>
30 #include <tools/urlobj.hxx>
31 #include <tools/diagnose_ex.h>
32 #include <comphelper/processfactory.hxx>
33 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
34 #include <com/sun/star/linguistic2/XSpellChecker.hpp>
35 #include <com/sun/star/linguistic2/XProofreader.hpp>
36 #include <com/sun/star/linguistic2/XHyphenator.hpp>
37 #include <com/sun/star/linguistic2/XThesaurus.hpp>
38 #include <com/sun/star/linguistic2/XDictionary.hpp>
39 #include <com/sun/star/linguistic2/XDictionaryList.hpp>
40 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
41 #include <com/sun/star/lang/XServiceDisplayName.hpp>
42 #include <com/sun/star/frame/XStorable.hpp>
43 #include <unotools/extendedsecurityoptions.hxx>
44 #include <svl/eitem.hxx>
45 #include <vcl/svapp.hxx>
46 #include <sal/log.hxx>
47 #include <osl/diagnose.h>
49 #include <svx/svxdlg.hxx>
50 #include <editeng/optitems.hxx>
51 #include <optlingu.hxx>
52 #include <dialmgr.hxx>
53 #include <strings.hrc>
55 #include <ucbhelper/content.hxx>
60 using namespace ::ucbhelper
;
61 using namespace ::com::sun::star
;
62 using namespace css::lang
;
63 using namespace css::uno
;
64 using namespace css::linguistic2
;
65 using namespace css::beans
;
67 static const sal_Char cSpell
[] = SN_SPELLCHECKER
;
68 static const sal_Char cGrammar
[] = SN_GRAMMARCHECKER
;
69 static const sal_Char cHyph
[] = SN_HYPHENATOR
;
70 static const sal_Char cThes
[] = SN_THESAURUS
;
72 // static ----------------------------------------------------------------
74 static sal_Int32
lcl_SeqGetEntryPos(
75 const Sequence
< OUString
> &rSeq
, const OUString
&rEntry
)
78 sal_Int32 nLen
= rSeq
.getLength();
79 const OUString
*pItem
= rSeq
.getConstArray();
80 for (i
= 0; i
< nLen
; ++i
)
82 if (rEntry
== pItem
[i
])
85 return i
< nLen
? i
: -1;
88 static bool KillFile_Impl( const OUString
& rURL
)
93 Content
aCnt( rURL
, uno::Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
94 aCnt
.executeCommand( "delete", Any( true ) );
98 TOOLS_WARN_EXCEPTION( "cui.options", "KillFile" );
107 // t: 1 -> spell, 2 -> hyph, 3 -> thes, 4 -> grammar
108 // c: 1 -> checked 0 -> unchecked
111 #define TYPE_SPELL sal_uInt8(1)
112 #define TYPE_GRAMMAR sal_uInt8(2)
113 #define TYPE_HYPH sal_uInt8(3)
114 #define TYPE_THES sal_uInt8(4)
116 class ModuleUserData_Impl
125 ModuleUserData_Impl( const OUString
& sImpName
, bool bIsParent
, bool bChecked
, sal_uInt8 nSetType
, sal_uInt8 nSetIndex
) :
127 bIsChecked(bChecked
),
133 bool IsParent() const {return bParent
;}
134 sal_uInt8
GetType() const {return nType
;}
135 bool IsChecked() const {return bIsChecked
;}
136 sal_uInt8
GetIndex() const {return nIndex
;}
137 const OUString
& GetImplName() const {return sImplName
;}
142 // User for user-dictionaries (XDictionary interface)
149 explicit DicUserData(sal_uInt32 nUserData
) : nVal( nUserData
) {}
150 DicUserData( sal_uInt16 nEID
,
151 bool bChecked
, bool bEditable
, bool bDeletable
);
153 sal_uInt32
GetUserData() const { return nVal
; }
154 sal_uInt16
GetEntryId() const { return static_cast<sal_uInt16
>(nVal
>> 16); }
155 bool IsChecked() const { return static_cast<bool>((nVal
>> 8) & 0x01); }
156 bool IsDeletable() const { return static_cast<bool>((nVal
>> 10) & 0x01); }
160 DicUserData::DicUserData(
162 bool bChecked
, bool bEditable
, bool bDeletable
)
164 DBG_ASSERT( nEID
< 65000, "Entry Id out of range" );
165 nVal
= (static_cast<sal_uInt32
>(0xFFFF & nEID
) << 16) |
166 (static_cast<sal_uInt32
>(bChecked
? 1 : 0) << 8) |
167 (static_cast<sal_uInt32
>(bEditable
? 1 : 0) << 9) |
168 (static_cast<sal_uInt32
>(bDeletable
? 1 : 0) << 10);
171 /*--------------------------------------------------
172 Entry IDs for options listbox of dialog
173 --------------------------------------------------*/
180 EID_WORDS_WITH_DIGITS
,
189 //! this array must have an entry for every value of EID_OPTIONS.
190 // It is used to get the respective property name.
191 static const char * aEidToPropName
[] =
193 UPN_IS_SPELL_AUTO
, // EID_SPELL_AUTO
194 UPN_IS_GRAMMAR_AUTO
, // EID_GRAMMAR_AUTO
195 UPN_IS_SPELL_UPPER_CASE
, // EID_CAPITAL_WORDS
196 UPN_IS_SPELL_WITH_DIGITS
, // EID_WORDS_WITH_DIGITS
197 UPN_IS_SPELL_SPECIAL
, // EID_SPELL_SPECIAL
198 UPN_HYPH_MIN_WORD_LENGTH
, // EID_NUM_MIN_WORDLEN,
199 UPN_HYPH_MIN_LEADING
, // EID_NUM_PRE_BREAK
200 UPN_HYPH_MIN_TRAILING
, // EID_NUM_POST_BREAK
201 UPN_IS_HYPH_AUTO
, // EID_HYPH_AUTO
202 UPN_IS_HYPH_SPECIAL
// EID_HYPH_SPECIAL
205 static OUString
lcl_GetPropertyName( EID_OPTIONS eEntryId
)
207 DBG_ASSERT( static_cast<unsigned int>(eEntryId
) < SAL_N_ELEMENTS(aEidToPropName
), "index out of range" );
208 return OUString::createFromAscii( aEidToPropName
[ static_cast<int>(eEntryId
) ] );
211 class OptionsBreakSet
: public weld::GenericDialogController
213 std::unique_ptr
<weld::Widget
> m_xBeforeFrame
;
214 std::unique_ptr
<weld::Widget
> m_xAfterFrame
;
215 std::unique_ptr
<weld::Widget
> m_xMinimalFrame
;
216 std::unique_ptr
<weld::SpinButton
> m_xBreakNF
;
219 OptionsBreakSet(weld::Window
* pParent
, sal_uInt16 nRID
)
220 : GenericDialogController(pParent
, "cui/ui/breaknumberoption.ui", "BreakNumberOption")
221 , m_xBeforeFrame(m_xBuilder
->weld_widget("beforeframe"))
222 , m_xAfterFrame(m_xBuilder
->weld_widget("afterframe"))
223 , m_xMinimalFrame(m_xBuilder
->weld_widget("miniframe"))
225 assert(EID_NUM_PRE_BREAK
== nRID
|| EID_NUM_POST_BREAK
== nRID
|| EID_NUM_MIN_WORDLEN
== nRID
); //unexpected ID
227 if (nRID
== EID_NUM_PRE_BREAK
)
229 m_xBeforeFrame
->show();
230 m_xBreakNF
= m_xBuilder
->weld_spin_button("beforebreak");
232 else if(nRID
== EID_NUM_POST_BREAK
)
234 m_xAfterFrame
->show();
235 m_xBreakNF
= m_xBuilder
->weld_spin_button("afterbreak");
237 else if(nRID
== EID_NUM_MIN_WORDLEN
)
239 m_xMinimalFrame
->show();
240 m_xBreakNF
= m_xBuilder
->weld_spin_button("wordlength");
244 weld::SpinButton
& GetNumericFld()
250 // class OptionsUserData -------------------------------------------------
252 class OptionsUserData
257 explicit OptionsUserData( sal_uInt32 nUserData
) : nVal( nUserData
) {}
258 OptionsUserData( sal_uInt16 nEID
,
259 bool bHasNV
, sal_uInt16 nNumVal
,
260 bool bCheckable
, bool bChecked
);
262 sal_uInt32
GetUserData() const { return nVal
; }
263 sal_uInt16
GetEntryId() const { return static_cast<sal_uInt16
>(nVal
>> 16); }
264 bool HasNumericValue() const { return static_cast<bool>((nVal
>> 10) & 0x01); }
265 sal_uInt16
GetNumericValue() const { return static_cast<sal_uInt16
>(nVal
& 0xFF); }
266 bool IsCheckable() const { return static_cast<bool>((nVal
>> 9) & 0x01); }
267 bool IsModified() const { return static_cast<bool>((nVal
>> 11) & 0x01); }
269 void SetNumericValue( sal_uInt8 nNumVal
);
272 OptionsUserData::OptionsUserData( sal_uInt16 nEID
,
273 bool bHasNV
, sal_uInt16 nNumVal
,
274 bool bCheckable
, bool bChecked
)
276 DBG_ASSERT( nEID
< 65000, "Entry Id out of range" );
277 DBG_ASSERT( nNumVal
< 256, "value out of range" );
278 nVal
= (static_cast<sal_uInt32
>(0xFFFF & nEID
) << 16) |
279 (static_cast<sal_uInt32
>(bHasNV
? 1 : 0) << 10) |
280 (static_cast<sal_uInt32
>(bCheckable
? 1 : 0) << 9) |
281 (static_cast<sal_uInt32
>(bChecked
? 1 : 0) << 8) |
282 static_cast<sal_uInt32
>(0xFF & nNumVal
);
285 void OptionsUserData::SetNumericValue( sal_uInt8 nNumVal
)
287 if (HasNumericValue() && (GetNumericValue() != nNumVal
))
291 nVal
|= sal_uInt32(1) << 11; // mark as modified
295 // ServiceInfo_Impl ----------------------------------------------------
297 struct ServiceInfo_Impl
299 OUString sDisplayName
;
300 OUString sSpellImplName
;
301 OUString sHyphImplName
;
302 OUString sThesImplName
;
303 OUString sGrammarImplName
;
304 uno::Reference
< XSpellChecker
> xSpell
;
305 uno::Reference
< XHyphenator
> xHyph
;
306 uno::Reference
< XThesaurus
> xThes
;
307 uno::Reference
< XProofreader
> xGrammar
;
310 ServiceInfo_Impl() : bConfigured(false) {}
313 typedef std::vector
< ServiceInfo_Impl
> ServiceInfoArr
;
314 typedef std::map
< LanguageType
, Sequence
< OUString
> > LangImplNameTable
;
317 // SvxLinguData_Impl ----------------------------------------------------
319 class SvxLinguData_Impl
321 //contains services and implementation names sorted by implementation names
322 ServiceInfoArr aDisplayServiceArr
;
323 sal_uInt32 nDisplayServices
;
325 Sequence
< Locale
> aAllServiceLocales
;
326 LangImplNameTable aCfgSpellTable
;
327 LangImplNameTable aCfgHyphTable
;
328 LangImplNameTable aCfgThesTable
;
329 LangImplNameTable aCfgGrammarTable
;
330 uno::Reference
< XLinguServiceManager2
> xLinguSrvcMgr
;
333 static bool AddRemove( Sequence
< OUString
> &rConfigured
,
334 const OUString
&rImplName
, bool bAdd
);
339 uno::Reference
<XLinguServiceManager2
> & GetManager() { return xLinguSrvcMgr
; }
341 void SetChecked( const Sequence
< OUString
> &rConfiguredServices
);
342 void Reconfigure( const OUString
&rDisplayName
, bool bEnable
);
344 const Sequence
<Locale
> & GetAllSupportedLocales() const { return aAllServiceLocales
; }
346 LangImplNameTable
& GetSpellTable() { return aCfgSpellTable
; }
347 LangImplNameTable
& GetHyphTable() { return aCfgHyphTable
; }
348 LangImplNameTable
& GetThesTable() { return aCfgThesTable
; }
349 LangImplNameTable
& GetGrammarTable() { return aCfgGrammarTable
; }
351 ServiceInfoArr
& GetDisplayServiceArray() { return aDisplayServiceArr
; }
353 const sal_uInt32
& GetDisplayServiceCount() const { return nDisplayServices
; }
354 void SetDisplayServiceCount( sal_uInt32 nVal
) { nDisplayServices
= nVal
; }
356 // returns the list of service implementation names for the specified
357 // language and service (TYPE_SPELL, TYPE_HYPH, TYPE_THES) sorted in
358 // the proper order for the SvxEditModulesDlg (the ones from the
359 // configuration (keeping that order!) first and then the other ones.
360 // I.e. the ones available but not configured in arbitrary order).
361 // They available ones may contain names that do not(!) support that
363 Sequence
< OUString
> GetSortedImplNames( LanguageType nLang
, sal_uInt8 nType
);
365 ServiceInfo_Impl
* GetInfoByImplName( const OUString
&rSvcImplName
);
369 static sal_Int32
lcl_SeqGetIndex( const Sequence
< OUString
> &rSeq
, const OUString
&rTxt
)
372 sal_Int32 nLen
= rSeq
.getLength();
373 const OUString
*pString
= rSeq
.getConstArray();
374 for (sal_Int32 i
= 0; i
< nLen
&& nRes
== -1; ++i
)
376 if (pString
[i
] == rTxt
)
383 Sequence
< OUString
> SvxLinguData_Impl::GetSortedImplNames( LanguageType nLang
, sal_uInt8 nType
)
385 LangImplNameTable
*pTable
= nullptr;
388 case TYPE_SPELL
: pTable
= &aCfgSpellTable
; break;
389 case TYPE_HYPH
: pTable
= &aCfgHyphTable
; break;
390 case TYPE_THES
: pTable
= &aCfgThesTable
; break;
391 case TYPE_GRAMMAR
: pTable
= &aCfgGrammarTable
; break;
393 Sequence
< OUString
> aRes
;
396 SAL_WARN( "cui.options", "unknown linguistic type" );
399 if (pTable
->count( nLang
))
400 aRes
= (*pTable
)[ nLang
]; // add configured services
401 sal_Int32 nIdx
= aRes
.getLength();
402 DBG_ASSERT( static_cast<sal_Int32
>(nDisplayServices
) >= nIdx
, "size mismatch" );
403 aRes
.realloc( nDisplayServices
);
404 OUString
*pRes
= aRes
.getArray();
406 // add not configured services
407 for (sal_Int32 i
= 0; i
< static_cast<sal_Int32
>(nDisplayServices
); ++i
)
409 const ServiceInfo_Impl
&rInfo
= aDisplayServiceArr
[ i
];
413 case TYPE_SPELL
: aImplName
= rInfo
.sSpellImplName
; break;
414 case TYPE_HYPH
: aImplName
= rInfo
.sHyphImplName
; break;
415 case TYPE_THES
: aImplName
= rInfo
.sThesImplName
; break;
416 case TYPE_GRAMMAR
: aImplName
= rInfo
.sGrammarImplName
; break;
419 if (!aImplName
.isEmpty() && (lcl_SeqGetIndex( aRes
, aImplName
) == -1)) // name not yet added
421 DBG_ASSERT( nIdx
< aRes
.getLength(), "index out of range" );
422 if (nIdx
< aRes
.getLength())
423 pRes
[ nIdx
++ ] = aImplName
;
426 // don't forget to put aRes back to its actual size just in case you allocated too much
427 // since all of the names may have already been added
428 // otherwise you get duplicate entries in the edit dialog
429 aRes
.realloc( nIdx
);
434 ServiceInfo_Impl
* SvxLinguData_Impl::GetInfoByImplName( const OUString
&rSvcImplName
)
436 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
438 ServiceInfo_Impl
&rTmp
= aDisplayServiceArr
[ i
];
439 if (rTmp
.sSpellImplName
== rSvcImplName
||
440 rTmp
.sHyphImplName
== rSvcImplName
||
441 rTmp
.sThesImplName
== rSvcImplName
||
442 rTmp
.sGrammarImplName
== rSvcImplName
)
451 static void lcl_MergeLocales(Sequence
< Locale
>& aAllLocales
, const Sequence
< Locale
>& rAdd
)
453 const Locale
* pAdd
= rAdd
.getConstArray();
454 Sequence
<Locale
> aLocToAdd(rAdd
.getLength());
455 const Locale
* pAllLocales
= aAllLocales
.getConstArray();
456 Locale
* pLocToAdd
= aLocToAdd
.getArray();
457 sal_Int32 nFound
= 0;
459 for(i
= 0; i
< rAdd
.getLength(); i
++)
462 for(sal_Int32 j
= 0; j
< aAllLocales
.getLength() && !bFound
; j
++)
464 bFound
= pAdd
[i
].Language
== pAllLocales
[j
].Language
&&
465 pAdd
[i
].Country
== pAllLocales
[j
].Country
&&
466 pAdd
[i
].Variant
== pAllLocales
[j
].Variant
;
470 pLocToAdd
[nFound
++] = pAdd
[i
];
473 sal_Int32 nLength
= aAllLocales
.getLength();
474 aAllLocales
.realloc( nLength
+ nFound
);
475 Locale
* pAllLocales2
= aAllLocales
.getArray();
476 for(i
= 0; i
< nFound
; i
++)
477 pAllLocales2
[nLength
++] = pLocToAdd
[i
];
480 static void lcl_MergeDisplayArray(
481 SvxLinguData_Impl
&rData
,
482 const ServiceInfo_Impl
&rToAdd
)
486 ServiceInfoArr
&rSvcInfoArr
= rData
.GetDisplayServiceArray();
487 sal_uInt32 nEntries
= rData
.GetDisplayServiceCount();
489 for (sal_uInt32 i
= 0; i
< nEntries
; ++i
)
491 ServiceInfo_Impl
& rEntry
= rSvcInfoArr
[i
];
492 if (rEntry
.sDisplayName
== rToAdd
.sDisplayName
)
494 if(rToAdd
.xSpell
.is())
496 DBG_ASSERT( !rEntry
.xSpell
.is() &&
497 rEntry
.sSpellImplName
.isEmpty(),
499 rEntry
.sSpellImplName
= rToAdd
.sSpellImplName
;
500 rEntry
.xSpell
= rToAdd
.xSpell
;
502 if(rToAdd
.xGrammar
.is())
504 DBG_ASSERT( !rEntry
.xGrammar
.is() &&
505 rEntry
.sGrammarImplName
.isEmpty(),
507 rEntry
.sGrammarImplName
= rToAdd
.sGrammarImplName
;
508 rEntry
.xGrammar
= rToAdd
.xGrammar
;
510 if(rToAdd
.xHyph
.is())
512 DBG_ASSERT( !rEntry
.xHyph
.is() &&
513 rEntry
.sHyphImplName
.isEmpty(),
515 rEntry
.sHyphImplName
= rToAdd
.sHyphImplName
;
516 rEntry
.xHyph
= rToAdd
.xHyph
;
518 if(rToAdd
.xThes
.is())
520 DBG_ASSERT( !rEntry
.xThes
.is() &&
521 rEntry
.sThesImplName
.isEmpty(),
523 rEntry
.sThesImplName
= rToAdd
.sThesImplName
;
524 rEntry
.xThes
= rToAdd
.xThes
;
530 rData
.GetDisplayServiceArray().push_back( rToAdd
);
531 rData
.SetDisplayServiceCount( nCnt
+ 1 );
534 SvxLinguData_Impl::SvxLinguData_Impl() :
537 uno::Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
538 xLinguSrvcMgr
= LinguServiceManager::create(xContext
);
540 const Locale
& rCurrentLocale
= Application::GetSettings().GetLanguageTag().getLocale();
541 Sequence
<Any
> aArgs(2);//second arguments has to be empty!
542 aArgs
.getArray()[0] <<= LinguMgr::GetLinguPropertySet();
545 Sequence
< OUString
> aSpellNames
= xLinguSrvcMgr
->getAvailableServices(
547 const OUString
* pSpellNames
= aSpellNames
.getConstArray();
550 for(nIdx
= 0; nIdx
< aSpellNames
.getLength(); nIdx
++)
552 ServiceInfo_Impl aInfo
;
553 aInfo
.sSpellImplName
= pSpellNames
[nIdx
];
555 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sSpellImplName
, aArgs
, xContext
), UNO_QUERY
);
557 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xSpell
, UNO_QUERY
);
559 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
561 const Sequence
< Locale
> aLocales( aInfo
.xSpell
->getLocales() );
562 //! suppress display of entries with no supported languages (see feature 110994)
563 if (aLocales
.hasElements())
565 lcl_MergeLocales( aAllServiceLocales
, aLocales
);
566 lcl_MergeDisplayArray( *this, aInfo
);
570 //read grammar checker
571 Sequence
< OUString
> aGrammarNames
= xLinguSrvcMgr
->getAvailableServices(
572 cGrammar
, Locale() );
573 const OUString
* pGrammarNames
= aGrammarNames
.getConstArray();
574 for(nIdx
= 0; nIdx
< aGrammarNames
.getLength(); nIdx
++)
576 ServiceInfo_Impl aInfo
;
577 aInfo
.sGrammarImplName
= pGrammarNames
[nIdx
];
579 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sGrammarImplName
, aArgs
, xContext
), UNO_QUERY
);
581 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xGrammar
, UNO_QUERY
);
583 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
585 const Sequence
< Locale
> aLocales( aInfo
.xGrammar
->getLocales() );
586 //! suppress display of entries with no supported languages (see feature 110994)
587 if (aLocales
.hasElements())
589 lcl_MergeLocales( aAllServiceLocales
, aLocales
);
590 lcl_MergeDisplayArray( *this, aInfo
);
595 Sequence
< OUString
> aHyphNames
= xLinguSrvcMgr
->getAvailableServices(
597 const OUString
* pHyphNames
= aHyphNames
.getConstArray();
598 for(nIdx
= 0; nIdx
< aHyphNames
.getLength(); nIdx
++)
600 ServiceInfo_Impl aInfo
;
601 aInfo
.sHyphImplName
= pHyphNames
[nIdx
];
602 aInfo
.xHyph
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sHyphImplName
, aArgs
, xContext
), UNO_QUERY
);
604 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xHyph
, UNO_QUERY
);
606 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
608 const Sequence
< Locale
> aLocales( aInfo
.xHyph
->getLocales() );
609 //! suppress display of entries with no supported languages (see feature 110994)
610 if (aLocales
.hasElements())
612 lcl_MergeLocales( aAllServiceLocales
, aLocales
);
613 lcl_MergeDisplayArray( *this, aInfo
);
618 Sequence
< OUString
> aThesNames
= xLinguSrvcMgr
->getAvailableServices(
620 const OUString
* pThesNames
= aThesNames
.getConstArray();
621 for(nIdx
= 0; nIdx
< aThesNames
.getLength(); nIdx
++)
623 ServiceInfo_Impl aInfo
;
624 aInfo
.sThesImplName
= pThesNames
[nIdx
];
625 aInfo
.xThes
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aInfo
.sThesImplName
, aArgs
, xContext
), UNO_QUERY
);
627 uno::Reference
<XServiceDisplayName
> xDispName(aInfo
.xThes
, UNO_QUERY
);
629 aInfo
.sDisplayName
= xDispName
->getServiceDisplayName( rCurrentLocale
);
631 const Sequence
< Locale
> aLocales( aInfo
.xThes
->getLocales() );
632 //! suppress display of entries with no supported languages (see feature 110994)
633 if (aLocales
.hasElements())
635 lcl_MergeLocales( aAllServiceLocales
, aLocales
);
636 lcl_MergeDisplayArray( *this, aInfo
);
640 Sequence
< OUString
> aCfgSvcs
;
641 const Locale
* pAllLocales
= aAllServiceLocales
.getConstArray();
642 for(sal_Int32 nLocale
= 0; nLocale
< aAllServiceLocales
.getLength(); nLocale
++)
644 LanguageType nLang
= LanguageTag::convertToLanguageType( pAllLocales
[nLocale
] );
646 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cSpell
, pAllLocales
[nLocale
]);
647 SetChecked( aCfgSvcs
);
648 if (aCfgSvcs
.hasElements())
649 aCfgSpellTable
[ nLang
] = aCfgSvcs
;
651 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cGrammar
, pAllLocales
[nLocale
]);
652 SetChecked( aCfgSvcs
);
653 if (aCfgSvcs
.hasElements())
654 aCfgGrammarTable
[ nLang
] = aCfgSvcs
;
656 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cHyph
, pAllLocales
[nLocale
]);
657 SetChecked( aCfgSvcs
);
658 if (aCfgSvcs
.hasElements())
659 aCfgHyphTable
[ nLang
] = aCfgSvcs
;
661 aCfgSvcs
= xLinguSrvcMgr
->getConfiguredServices(cThes
, pAllLocales
[nLocale
]);
662 SetChecked( aCfgSvcs
);
663 if (aCfgSvcs
.hasElements())
664 aCfgThesTable
[ nLang
] = aCfgSvcs
;
668 void SvxLinguData_Impl::SetChecked(const Sequence
<OUString
>& rConfiguredServices
)
670 const OUString
* pConfiguredServices
= rConfiguredServices
.getConstArray();
671 for(sal_Int32 n
= 0; n
< rConfiguredServices
.getLength(); n
++)
673 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
675 ServiceInfo_Impl
& rEntry
= aDisplayServiceArr
[i
];
676 if (!rEntry
.bConfigured
)
678 const OUString
&rSrvcImplName
= pConfiguredServices
[n
];
679 if (!rSrvcImplName
.isEmpty() &&
680 (rEntry
.sSpellImplName
== rSrvcImplName
||
681 rEntry
.sGrammarImplName
== rSrvcImplName
||
682 rEntry
.sHyphImplName
== rSrvcImplName
||
683 rEntry
.sThesImplName
== rSrvcImplName
))
685 rEntry
.bConfigured
= true;
693 bool SvxLinguData_Impl::AddRemove(
694 Sequence
< OUString
> &rConfigured
,
695 const OUString
&rImplName
, bool bAdd
)
697 bool bRet
= false; // modified?
699 sal_Int32 nEntries
= rConfigured
.getLength();
700 sal_Int32 nPos
= lcl_SeqGetEntryPos(rConfigured
, rImplName
);
701 if (bAdd
&& nPos
< 0) // add new entry
703 rConfigured
.realloc( ++nEntries
);
704 OUString
*pConfigured
= rConfigured
.getArray();
705 pConfigured
[nEntries
- 1] = rImplName
;
708 else if (!bAdd
&& nPos
>= 0) // remove existing entry
710 OUString
*pConfigured
= rConfigured
.getArray();
711 for (sal_Int32 i
= nPos
; i
< nEntries
- 1; ++i
)
712 pConfigured
[i
] = pConfigured
[i
+ 1];
713 rConfigured
.realloc(--nEntries
);
721 void SvxLinguData_Impl::Reconfigure( const OUString
&rDisplayName
, bool bEnable
)
723 DBG_ASSERT( !rDisplayName
.isEmpty(), "empty DisplayName" );
725 ServiceInfo_Impl
*pInfo
= nullptr;
726 for (sal_uInt32 i
= 0; i
< nDisplayServices
; ++i
)
728 ServiceInfo_Impl
& rTmp
= aDisplayServiceArr
[i
];
729 if (rTmp
.sDisplayName
== rDisplayName
)
735 DBG_ASSERT( pInfo
, "DisplayName entry not found" );
738 pInfo
->bConfigured
= bEnable
;
740 Sequence
< Locale
> aLocales
;
741 const Locale
*pLocale
= nullptr;
742 sal_Int32 nLocales
= 0;
745 // update configured spellchecker entries
746 if (pInfo
->xSpell
.is())
748 aLocales
= pInfo
->xSpell
->getLocales();
749 pLocale
= aLocales
.getConstArray();
750 nLocales
= aLocales
.getLength();
751 for (i
= 0; i
< nLocales
; ++i
)
753 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
754 if (!aCfgSpellTable
.count( nLang
) && bEnable
)
755 aCfgSpellTable
[ nLang
] = Sequence
< OUString
>();
756 if (aCfgSpellTable
.count( nLang
))
757 AddRemove( aCfgSpellTable
[ nLang
], pInfo
->sSpellImplName
, bEnable
);
761 // update configured grammar checker entries
762 if (pInfo
->xGrammar
.is())
764 aLocales
= pInfo
->xGrammar
->getLocales();
765 pLocale
= aLocales
.getConstArray();
766 nLocales
= aLocales
.getLength();
767 for (i
= 0; i
< nLocales
; ++i
)
769 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
770 if (!aCfgGrammarTable
.count( nLang
) && bEnable
)
771 aCfgGrammarTable
[ nLang
] = Sequence
< OUString
>();
772 if (aCfgGrammarTable
.count( nLang
))
773 AddRemove( aCfgGrammarTable
[ nLang
], pInfo
->sGrammarImplName
, bEnable
);
777 // update configured hyphenator entries
778 if (pInfo
->xHyph
.is())
780 aLocales
= pInfo
->xHyph
->getLocales();
781 pLocale
= aLocales
.getConstArray();
782 nLocales
= aLocales
.getLength();
783 for (i
= 0; i
< nLocales
; ++i
)
785 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
786 if (!aCfgHyphTable
.count( nLang
) && bEnable
)
787 aCfgHyphTable
[ nLang
] = Sequence
< OUString
>();
788 if (aCfgHyphTable
.count( nLang
))
789 AddRemove( aCfgHyphTable
[ nLang
], pInfo
->sHyphImplName
, bEnable
);
793 // update configured spellchecker entries
794 if (pInfo
->xThes
.is())
796 aLocales
= pInfo
->xThes
->getLocales();
797 pLocale
= aLocales
.getConstArray();
798 nLocales
= aLocales
.getLength();
799 for (i
= 0; i
< nLocales
; ++i
)
801 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocale
[i
] );
802 if (!aCfgThesTable
.count( nLang
) && bEnable
)
803 aCfgThesTable
[ nLang
] = Sequence
< OUString
>();
804 if (aCfgThesTable
.count( nLang
))
805 AddRemove( aCfgThesTable
[ nLang
], pInfo
->sThesImplName
, bEnable
);
812 // class SvxLinguTabPage -------------------------------------------------
814 SvxLinguTabPage::SvxLinguTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rSet
)
815 : SfxTabPage(pPage
, pController
, "cui/ui/optlingupage.ui", "OptLinguPage", &rSet
)
816 , sCapitalWords (CuiResId(RID_SVXSTR_CAPITAL_WORDS
))
817 , sWordsWithDigits(CuiResId(RID_SVXSTR_WORDS_WITH_DIGITS
))
818 , sSpellSpecial (CuiResId(RID_SVXSTR_SPELL_SPECIAL
))
819 , sSpellAuto (CuiResId(RID_SVXSTR_SPELL_AUTO
))
820 , sGrammarAuto (CuiResId(RID_SVXSTR_GRAMMAR_AUTO
))
821 , sNumMinWordlen (CuiResId(RID_SVXSTR_NUM_MIN_WORDLEN
))
822 , sNumPreBreak (CuiResId(RID_SVXSTR_NUM_PRE_BREAK
))
823 , sNumPostBreak (CuiResId(RID_SVXSTR_NUM_POST_BREAK
))
824 , sHyphAuto (CuiResId(RID_SVXSTR_HYPH_AUTO
))
825 , sHyphSpecial (CuiResId(RID_SVXSTR_HYPH_SPECIAL
))
826 , nUPN_HYPH_MIN_WORD_LENGTH(-1)
827 , nUPN_HYPH_MIN_LEADING(-1)
828 , nUPN_HYPH_MIN_TRAILING(-1)
829 , m_xLinguModulesFT(m_xBuilder
->weld_label("lingumodulesft"))
830 , m_xLinguModulesCLB(m_xBuilder
->weld_tree_view("lingumodules"))
831 , m_xLinguModulesEditPB(m_xBuilder
->weld_button("lingumodulesedit"))
832 , m_xLinguDicsFT(m_xBuilder
->weld_label("lingudictsft"))
833 , m_xLinguDicsCLB(m_xBuilder
->weld_tree_view("lingudicts"))
834 , m_xLinguDicsNewPB(m_xBuilder
->weld_button("lingudictsnew"))
835 , m_xLinguDicsEditPB(m_xBuilder
->weld_button("lingudictsedit"))
836 , m_xLinguDicsDelPB(m_xBuilder
->weld_button("lingudictsdelete"))
837 , m_xLinguOptionsCLB(m_xBuilder
->weld_tree_view("linguoptions"))
838 , m_xLinguOptionsEditPB(m_xBuilder
->weld_button("linguoptionsedit"))
839 , m_xMoreDictsLink(m_xBuilder
->weld_link_button("moredictslink"))
841 std::vector
<int> aWidths
;
842 aWidths
.push_back(m_xLinguModulesCLB
->get_checkbox_column_width());
844 m_xLinguModulesCLB
->set_column_fixed_widths(aWidths
);
845 m_xLinguDicsCLB
->set_column_fixed_widths(aWidths
);
846 m_xLinguOptionsCLB
->set_column_fixed_widths(aWidths
);
848 m_xLinguModulesCLB
->connect_changed( LINK( this, SvxLinguTabPage
, SelectHdl_Impl
));
849 m_xLinguModulesCLB
->connect_row_activated(LINK(this, SvxLinguTabPage
, BoxDoubleClickHdl_Impl
));
850 m_xLinguModulesCLB
->connect_toggled(LINK(this, SvxLinguTabPage
, ModulesBoxCheckButtonHdl_Impl
));
852 m_xLinguModulesEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
853 m_xLinguOptionsEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
855 m_xLinguDicsCLB
->connect_changed( LINK( this, SvxLinguTabPage
, SelectHdl_Impl
));
856 m_xLinguDicsCLB
->connect_toggled(LINK(this, SvxLinguTabPage
, DicsBoxCheckButtonHdl_Impl
));
858 m_xLinguDicsNewPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
859 m_xLinguDicsEditPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
860 m_xLinguDicsDelPB
->connect_clicked( LINK( this, SvxLinguTabPage
, ClickHdl_Impl
));
862 m_xLinguOptionsCLB
->connect_changed( LINK( this, SvxLinguTabPage
, SelectHdl_Impl
));
863 m_xLinguOptionsCLB
->connect_row_activated(LINK(this, SvxLinguTabPage
, BoxDoubleClickHdl_Impl
));
865 if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode() == SvtExtendedSecurityOptions::OPEN_NEVER
)
866 m_xMoreDictsLink
->hide();
868 xProp
= LinguMgr::GetLinguPropertySet();
869 xDicList
.set( LinguMgr::GetDictionaryList(), UNO_QUERY
);
872 // keep references to all **currently** available dictionaries,
873 // since the diclist may get changed meanwhile (e.g. through the API).
874 // We want the dialog to operate on the same set of dictionaries it
876 // Also we have to take care to not lose the last reference when
877 // someone else removes a dictionary from the list.
878 // removed dics will be replaced by NULL new entries be added to the end
879 // Thus we may use indices as consistent references.
880 aDics
= xDicList
->getDictionaries();
886 m_xLinguDicsFT
->set_sensitive(false);
887 m_xLinguDicsCLB
->set_sensitive(false);
888 m_xLinguDicsNewPB
->set_sensitive(false);
889 m_xLinguDicsEditPB
->set_sensitive(false);
890 m_xLinguDicsDelPB
->set_sensitive(false);
894 SvxLinguTabPage::~SvxLinguTabPage()
899 std::unique_ptr
<SfxTabPage
> SvxLinguTabPage::Create( weld::Container
* pPage
, weld::DialogController
* pController
,
900 const SfxItemSet
* rAttrSet
)
902 return std::make_unique
<SvxLinguTabPage
>( pPage
, pController
, *rAttrSet
);
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
, 0) == TRISTATE_TRUE
;
982 uno::Reference
< XDictionary
> xDic( aDics
.getConstArray()[ i
] );
985 if (LinguMgr::GetIgnoreAllList() == xDic
)
987 xDic
->setActive( bChecked
);
991 OUString
aDicName( xDic
->getName() );
992 pActiveDic
[ nActiveDics
++ ] = aDicName
;
998 aActiveDics
.realloc( nActiveDics
);
1000 aTmp
<<= aActiveDics
;
1001 SvtLinguConfig aLngCfg
;
1002 aLngCfg
.SetProperty( UPH_ACTIVE_DICTIONARIES
, aTmp
);
1005 nEntries
= m_xLinguOptionsCLB
->n_children();
1006 for (int j
= 0; j
< nEntries
; ++j
)
1008 OptionsUserData
aData(m_xLinguOptionsCLB
->get_id(j
).toUInt32());
1009 OUString
aPropName( lcl_GetPropertyName( static_cast<EID_OPTIONS
>(aData
.GetEntryId()) ) );
1012 if (aData
.IsCheckable())
1014 bool bChecked
= m_xLinguOptionsCLB
->get_toggle(j
, 0) == TRISTATE_TRUE
;
1017 else if (aData
.HasNumericValue())
1019 sal_Int16 nVal
= aData
.GetNumericValue();
1024 xProp
->setPropertyValue( aPropName
, aAny
);
1025 aLngCfg
.SetProperty( aPropName
, aAny
);
1028 OptionsUserData
aPreBreakData(m_xLinguOptionsCLB
->get_id(EID_NUM_PRE_BREAK
).toUInt32());
1029 OptionsUserData
aPostBreakData(m_xLinguOptionsCLB
->get_id(EID_NUM_POST_BREAK
).toUInt32());
1030 if ( aPreBreakData
.IsModified() || aPostBreakData
.IsModified() )
1032 SfxHyphenRegionItem
aHyp( GetWhich( SID_ATTR_HYPHENREGION
) );
1033 aHyp
.GetMinLead() = static_cast<sal_uInt8
>(aPreBreakData
.GetNumericValue());
1034 aHyp
.GetMinTrail() = static_cast<sal_uInt8
>(aPostBreakData
.GetNumericValue());
1035 rCoreSet
->Put( aHyp
);
1038 // automatic spell checking
1039 bool bNewAutoCheck
= m_xLinguOptionsCLB
->get_toggle(EID_SPELL_AUTO
, 0) == TRISTATE_TRUE
;
1040 const SfxPoolItem
* pOld
= GetOldItem( *rCoreSet
, SID_AUTOSPELL_CHECK
);
1041 if ( !pOld
|| static_cast<const SfxBoolItem
*>(pOld
)->GetValue() != bNewAutoCheck
)
1043 rCoreSet
->Put( SfxBoolItem( GetWhich( SID_AUTOSPELL_CHECK
),
1051 sal_uInt32
SvxLinguTabPage::GetDicUserData( const uno::Reference
< XDictionary
> &rxDic
, sal_uInt16 nIdx
)
1053 sal_uInt32 nRes
= 0;
1054 DBG_ASSERT( rxDic
.is(), "dictionary not supplied" );
1057 uno::Reference
< frame::XStorable
> xStor( rxDic
, UNO_QUERY
);
1059 bool bChecked
= rxDic
->isActive();
1060 bool bEditable
= !xStor
.is() || !xStor
->isReadonly();
1061 bool bDeletable
= bEditable
;
1063 nRes
= DicUserData( nIdx
,
1064 bChecked
, bEditable
, bDeletable
).GetUserData();
1070 void SvxLinguTabPage::AddDicBoxEntry(
1071 const uno::Reference
< XDictionary
> &rxDic
,
1074 m_xLinguDicsCLB
->freeze();
1076 OUString
aTxt( ::GetDicInfoStr( rxDic
->getName(),
1077 LanguageTag( rxDic
->getLocale() ).getLanguageType(),
1078 DictionaryType_NEGATIVE
== rxDic
->getDictionaryType() ) );
1079 m_xLinguDicsCLB
->append(); // append at end
1080 int nEntry
= m_xLinguDicsCLB
->n_children() - 1;
1081 DicUserData
aData( GetDicUserData( rxDic
, nIdx
) );
1082 m_xLinguDicsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1083 m_xLinguDicsCLB
->set_toggle(nEntry
, aData
.IsChecked() ? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1084 m_xLinguDicsCLB
->set_text(nEntry
, aTxt
, 1); // append at end
1086 m_xLinguDicsCLB
->thaw();
1089 void SvxLinguTabPage::UpdateDicBox_Impl()
1091 m_xLinguDicsCLB
->freeze();
1092 m_xLinguDicsCLB
->clear();
1094 sal_Int32 nDics
= aDics
.getLength();
1095 const uno::Reference
< XDictionary
> *pDic
= aDics
.getConstArray();
1096 for (sal_Int32 i
= 0; i
< nDics
; ++i
)
1098 const uno::Reference
< XDictionary
> &rDic
= pDic
[i
];
1100 AddDicBoxEntry( rDic
, static_cast<sal_uInt16
>(i
) );
1103 m_xLinguDicsCLB
->thaw();
1104 if (m_xLinguDicsCLB
->n_children())
1106 m_xLinguDicsCLB
->select(0);
1107 SelectHdl_Impl(*m_xLinguDicsCLB
);
1111 void SvxLinguTabPage::UpdateModulesBox_Impl()
1115 const ServiceInfoArr
&rAllDispSrvcArr
= pLinguData
->GetDisplayServiceArray();
1116 const sal_uInt32 nDispSrvcCount
= pLinguData
->GetDisplayServiceCount();
1118 m_xLinguModulesCLB
->clear();
1120 for (sal_uInt32 i
= 0; i
< nDispSrvcCount
; ++i
)
1122 const ServiceInfo_Impl
&rInfo
= rAllDispSrvcArr
[i
];
1123 m_xLinguModulesCLB
->append();
1124 m_xLinguModulesCLB
->set_id(i
, OUString::number(reinterpret_cast<sal_Int64
>(&rInfo
)));
1125 m_xLinguModulesCLB
->set_toggle(i
, rInfo
.bConfigured
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1126 m_xLinguModulesCLB
->set_text(i
, rInfo
.sDisplayName
, 1);
1130 m_xLinguModulesCLB
->select(0);
1131 SelectHdl_Impl(*m_xLinguModulesCLB
);
1133 m_xLinguModulesEditPB
->set_sensitive( nDispSrvcCount
> 0 );
1137 void SvxLinguTabPage::Reset( const SfxItemSet
* rSet
)
1139 // if not HideGroups was called with GROUP_MODULES...
1140 if (m_xLinguModulesCLB
->get_visible())
1143 pLinguData
.reset( new SvxLinguData_Impl
);
1144 UpdateModulesBox_Impl();
1148 // get data from configuration
1149 SvtLinguConfig aLngCfg
;
1151 m_xLinguOptionsCLB
->freeze();
1152 m_xLinguOptionsCLB
->clear();
1156 sal_uInt32 nUserData
= 0;
1158 m_xLinguOptionsCLB
->append();
1161 aLngCfg
.GetProperty( UPN_IS_SPELL_AUTO
) >>= bVal
;
1162 const SfxPoolItem
* pItem
= GetItem( *rSet
, SID_AUTOSPELL_CHECK
);
1164 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1165 nUserData
= OptionsUserData( EID_SPELL_AUTO
, false, 0, true, bVal
).GetUserData();
1166 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1167 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellAuto
, 1);
1168 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1170 m_xLinguOptionsCLB
->append();
1173 aLngCfg
.GetProperty( UPN_IS_GRAMMAR_AUTO
) >>= bVal
;
1174 nUserData
= OptionsUserData( EID_GRAMMAR_AUTO
, false, 0, true, bVal
).GetUserData();
1175 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1176 m_xLinguOptionsCLB
->set_text(nEntry
, sGrammarAuto
, 1);
1177 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1179 m_xLinguOptionsCLB
->append();
1182 aLngCfg
.GetProperty( UPN_IS_SPELL_UPPER_CASE
) >>= bVal
;
1183 nUserData
= OptionsUserData( EID_CAPITAL_WORDS
, false, 0, true, bVal
).GetUserData();
1184 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1185 m_xLinguOptionsCLB
->set_text(nEntry
, sCapitalWords
, 1);
1186 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1188 m_xLinguOptionsCLB
->append();
1191 aLngCfg
.GetProperty( UPN_IS_SPELL_WITH_DIGITS
) >>= bVal
;
1192 nUserData
= OptionsUserData( EID_WORDS_WITH_DIGITS
, false, 0, true, bVal
).GetUserData();
1193 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1194 m_xLinguOptionsCLB
->set_text(nEntry
, sWordsWithDigits
, 1);
1195 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1197 m_xLinguOptionsCLB
->append();
1200 aLngCfg
.GetProperty( UPN_IS_SPELL_SPECIAL
) >>= bVal
;
1201 nUserData
= OptionsUserData( EID_SPELL_SPECIAL
, false, 0, true, bVal
).GetUserData();
1202 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1203 m_xLinguOptionsCLB
->set_text(nEntry
, sSpellSpecial
, 1);
1204 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1206 m_xLinguOptionsCLB
->append();
1209 aLngCfg
.GetProperty( UPN_HYPH_MIN_WORD_LENGTH
) >>= nVal
;
1210 nUserData
= OptionsUserData( EID_NUM_MIN_WORDLEN
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1211 m_xLinguOptionsCLB
->set_text(nEntry
, sNumMinWordlen
+ " " + OUString::number(nVal
), 1);
1212 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1213 nUPN_HYPH_MIN_WORD_LENGTH
= nEntry
;
1215 const SfxHyphenRegionItem
*pHyp
= nullptr;
1216 sal_uInt16 nWhich
= GetWhich( SID_ATTR_HYPHENREGION
);
1217 if ( rSet
->GetItemState( nWhich
, false ) == SfxItemState::SET
)
1218 pHyp
= &static_cast<const SfxHyphenRegionItem
&>( rSet
->Get( nWhich
) );
1220 m_xLinguOptionsCLB
->append();
1223 aLngCfg
.GetProperty( UPN_HYPH_MIN_LEADING
) >>= nVal
;
1225 nVal
= static_cast<sal_Int16
>(pHyp
->GetMinLead());
1226 nUserData
= OptionsUserData( EID_NUM_PRE_BREAK
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1227 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPreBreak
+ " " + OUString::number(nVal
), 1);
1228 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1229 nUPN_HYPH_MIN_LEADING
= nEntry
;
1231 m_xLinguOptionsCLB
->append();
1234 aLngCfg
.GetProperty( UPN_HYPH_MIN_TRAILING
) >>= nVal
;
1236 nVal
= static_cast<sal_Int16
>(pHyp
->GetMinTrail());
1237 nUserData
= OptionsUserData( EID_NUM_POST_BREAK
, true, static_cast<sal_uInt16
>(nVal
), false, false).GetUserData();
1238 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPostBreak
+ " " + OUString::number(nVal
), 1);
1239 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1240 nUPN_HYPH_MIN_TRAILING
= nEntry
;
1242 m_xLinguOptionsCLB
->append();
1245 aLngCfg
.GetProperty( UPN_IS_HYPH_AUTO
) >>= bVal
;
1246 nUserData
= OptionsUserData( EID_HYPH_AUTO
, false, 0, true, bVal
).GetUserData();
1247 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1248 m_xLinguOptionsCLB
->set_text(nEntry
, sHyphAuto
, 1);
1249 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1251 m_xLinguOptionsCLB
->append();
1254 aLngCfg
.GetProperty( UPN_IS_HYPH_SPECIAL
) >>= bVal
;
1255 nUserData
= OptionsUserData( EID_HYPH_SPECIAL
, false, 0, true, bVal
).GetUserData();
1256 m_xLinguOptionsCLB
->set_toggle(nEntry
, bVal
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1257 m_xLinguOptionsCLB
->set_text(nEntry
, sHyphSpecial
, 1);
1258 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(nUserData
));
1260 m_xLinguOptionsCLB
->thaw();
1262 m_xLinguOptionsCLB
->select(0);
1263 SelectHdl_Impl(*m_xLinguOptionsCLB
);
1265 m_xLinguModulesCLB
->set_size_request(m_xLinguModulesCLB
->get_preferred_size().Width(),
1266 m_xLinguModulesCLB
->get_height_rows(3));
1267 m_xLinguDicsCLB
->set_size_request(m_xLinguDicsCLB
->get_preferred_size().Width(),
1268 m_xLinguDicsCLB
->get_height_rows(5));
1269 m_xLinguOptionsCLB
->set_size_request(m_xLinguOptionsCLB
->get_preferred_size().Width(),
1270 m_xLinguOptionsCLB
->get_height_rows(5));
1273 IMPL_LINK(SvxLinguTabPage
, BoxDoubleClickHdl_Impl
, weld::TreeView
&, rBox
, bool)
1275 if (&rBox
== m_xLinguModulesCLB
.get())
1277 //! in order to avoid a bug causing a GPF when double clicking
1278 //! on a module entry and exiting the "Edit Modules" dialog
1280 Application::PostUserEvent( LINK(
1281 this, SvxLinguTabPage
, PostDblClickHdl_Impl
), nullptr, true);
1283 else if (&rBox
== m_xLinguOptionsCLB
.get())
1285 ClickHdl_Impl(*m_xLinguOptionsEditPB
);
1290 IMPL_LINK_NOARG(SvxLinguTabPage
, PostDblClickHdl_Impl
, void*, void)
1292 ClickHdl_Impl(*m_xLinguModulesEditPB
);
1295 IMPL_LINK(SvxLinguTabPage
, ModulesBoxCheckButtonHdl_Impl
, const row_col
&, rRowCol
, void)
1299 auto nPos
= rRowCol
.first
;
1300 pLinguData
->Reconfigure(m_xLinguModulesCLB
->get_text(nPos
, 1),
1301 m_xLinguModulesCLB
->get_toggle(nPos
, 0) == TRISTATE_TRUE
);
1304 IMPL_LINK(SvxLinguTabPage
, DicsBoxCheckButtonHdl_Impl
, const row_col
&, rRowCol
, void)
1306 auto nPos
= rRowCol
.first
;
1307 const uno::Reference
<XDictionary
> &rDic
= aDics
.getConstArray()[ nPos
];
1308 if (LinguMgr::GetIgnoreAllList() == rDic
)
1309 m_xLinguDicsCLB
->set_toggle(nPos
, TRISTATE_TRUE
, 0);
1312 IMPL_LINK(SvxLinguTabPage
, ClickHdl_Impl
, weld::Button
&, rBtn
, void)
1314 if (m_xLinguModulesEditPB
.get() == &rBtn
)
1317 pLinguData
.reset( new SvxLinguData_Impl
);
1319 SvxLinguData_Impl
aOldLinguData( *pLinguData
);
1320 SvxEditModulesDlg
aDlg(GetFrameWeld(), *pLinguData
);
1321 if (aDlg
.run() != RET_OK
)
1322 *pLinguData
= aOldLinguData
;
1324 // evaluate new status of 'bConfigured' flag
1325 sal_uInt32 nLen
= pLinguData
->GetDisplayServiceCount();
1326 for (sal_uInt32 i
= 0; i
< nLen
; ++i
)
1327 pLinguData
->GetDisplayServiceArray()[i
].bConfigured
= false;
1328 const Locale
* pAllLocales
= pLinguData
->GetAllSupportedLocales().getConstArray();
1329 sal_Int32 nLocales
= pLinguData
->GetAllSupportedLocales().getLength();
1330 for (sal_Int32 k
= 0; k
< nLocales
; ++k
)
1332 LanguageType nLang
= LanguageTag::convertToLanguageType( pAllLocales
[k
] );
1333 if (pLinguData
->GetSpellTable().count( nLang
))
1334 pLinguData
->SetChecked( pLinguData
->GetSpellTable()[ nLang
] );
1335 if (pLinguData
->GetGrammarTable().count( nLang
))
1336 pLinguData
->SetChecked( pLinguData
->GetGrammarTable()[ nLang
] );
1337 if (pLinguData
->GetHyphTable().count( nLang
))
1338 pLinguData
->SetChecked( pLinguData
->GetHyphTable()[ nLang
] );
1339 if (pLinguData
->GetThesTable().count( nLang
))
1340 pLinguData
->SetChecked( pLinguData
->GetThesTable()[ nLang
] );
1343 // show new status of modules
1344 UpdateModulesBox_Impl();
1346 else if (m_xLinguDicsNewPB
.get() == &rBtn
)
1348 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1349 ScopedVclPtr
<AbstractSvxNewDictionaryDialog
> aDlg(pFact
->CreateSvxNewDictionaryDialog(GetFrameWeld()));
1350 uno::Reference
< XDictionary
> xNewDic
;
1351 if ( aDlg
->Execute() == RET_OK
)
1352 xNewDic
= aDlg
->GetNewDictionary();
1355 // add new dics to the end
1356 sal_Int32 nLen
= aDics
.getLength();
1357 aDics
.realloc( nLen
+ 1 );
1359 aDics
.getArray()[ nLen
] = xNewDic
;
1361 AddDicBoxEntry( xNewDic
, static_cast<sal_uInt16
>(nLen
) );
1364 else if (m_xLinguDicsEditPB
.get() == &rBtn
)
1366 int nEntry
= m_xLinguDicsCLB
->get_selected_index();
1369 DicUserData
aData(m_xLinguDicsCLB
->get_id(nEntry
).toUInt32());
1370 sal_uInt16 nDicPos
= aData
.GetEntryId();
1371 sal_Int32 nDics
= aDics
.getLength();
1372 if (nDicPos
< nDics
)
1374 uno::Reference
< XDictionary
> xDic
= aDics
.getConstArray()[ nDicPos
];
1377 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1378 ScopedVclPtr
<VclAbstractDialog
> aDlg(pFact
->CreateSvxEditDictionaryDialog(GetFrameWeld(), xDic
->getName()));
1384 else if (m_xLinguDicsDelPB
.get() == &rBtn
)
1386 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "cui/ui/querydeletedictionarydialog.ui"));
1387 std::unique_ptr
<weld::MessageDialog
> xQuery(xBuilder
->weld_message_dialog("QueryDeleteDictionaryDialog"));
1388 if (RET_NO
== xQuery
->run())
1391 int nEntry
= m_xLinguDicsCLB
->get_selected_index();
1394 DicUserData
aData(m_xLinguDicsCLB
->get_id(nEntry
).toUInt32());
1395 sal_uInt16 nDicPos
= aData
.GetEntryId();
1396 sal_Int32 nDics
= aDics
.getLength();
1397 if (nDicPos
< nDics
)
1399 uno::Reference
< XDictionary
> xDic
= aDics
.getConstArray()[ nDicPos
];
1402 if (LinguMgr::GetIgnoreAllList() == xDic
)
1407 xDicList
->removeDictionary( xDic
);
1409 uno::Reference
< frame::XStorable
> xStor( xDic
, UNO_QUERY
);
1410 if ( xStor
->hasLocation() && !xStor
->isReadonly() )
1412 OUString sURL
= xStor
->getLocation();
1413 INetURLObject
aObj(sURL
);
1414 DBG_ASSERT( aObj
.GetProtocol() == INetProtocol::File
,
1415 "non-file URLs cannot be deleted" );
1416 if ( aObj
.GetProtocol() == INetProtocol::File
)
1418 KillFile_Impl( aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1422 aDics
.getArray()[ nDicPos
] = nullptr;
1424 // remove entry from checklistbox
1425 int nCnt
= m_xLinguDicsCLB
->n_children();
1426 for (int i
= 0; i
< nCnt
; ++i
)
1428 DicUserData
aDicData(m_xLinguDicsCLB
->get_id(i
).toUInt32());
1429 if (aDicData
.GetEntryId() == nDicPos
)
1431 m_xLinguDicsCLB
->remove(i
);
1435 DBG_ASSERT( nCnt
> m_xLinguDicsCLB
->n_children(),
1442 else if (m_xLinguOptionsEditPB
.get() == &rBtn
)
1444 int nEntry
= m_xLinguOptionsCLB
->get_selected_index();
1445 DBG_ASSERT(nEntry
!= -1, "no entry selected");
1448 OptionsUserData
aData(m_xLinguOptionsCLB
->get_id(nEntry
).toUInt32());
1449 if (aData
.HasNumericValue())
1451 sal_uInt16 nRID
= aData
.GetEntryId();
1452 OptionsBreakSet
aDlg(GetFrameWeld(), nRID
);
1453 aDlg
.GetNumericFld().set_value(aData
.GetNumericValue());
1454 if (RET_OK
== aDlg
.run())
1456 int nVal
= aDlg
.GetNumericFld().get_value();
1457 if (-1 != nVal
&& aData
.GetNumericValue() != nVal
)
1459 aData
.SetNumericValue( static_cast<sal_uInt8
>(nVal
) ); //! sets IsModified !
1460 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1461 if (nEntry
== nUPN_HYPH_MIN_WORD_LENGTH
)
1462 m_xLinguOptionsCLB
->set_text(nEntry
, sNumMinWordlen
+ " " + OUString::number(nVal
), 1);
1463 else if (nEntry
== nUPN_HYPH_MIN_LEADING
)
1464 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPreBreak
+ " " + OUString::number(nVal
), 1);
1465 else if (nEntry
== nUPN_HYPH_MIN_TRAILING
)
1466 m_xLinguOptionsCLB
->set_text(nEntry
, sNumPostBreak
+ " " + OUString::number(nVal
), 1);
1467 m_xLinguOptionsCLB
->set_id(nEntry
, OUString::number(aData
.GetUserData()));
1475 OSL_FAIL( "rBtn unexpected value" );
1479 IMPL_LINK(SvxLinguTabPage
, SelectHdl_Impl
, weld::TreeView
&, rBox
, void)
1481 if (m_xLinguModulesCLB
.get() == &rBox
)
1484 else if (m_xLinguDicsCLB
.get() == &rBox
)
1486 int nEntry
= rBox
.get_selected_index();
1489 DicUserData
aData(rBox
.get_id(nEntry
).toUInt32());
1491 // always allow to edit (i.e. at least view the content of the dictionary)
1492 m_xLinguDicsEditPB
->set_sensitive( true );
1493 m_xLinguDicsDelPB
->set_sensitive( aData
.IsDeletable() );
1496 else if (m_xLinguOptionsCLB
.get() == &rBox
)
1498 int nEntry
= rBox
.get_selected_index();
1501 OptionsUserData
aData(rBox
.get_id(nEntry
).toUInt32());
1502 m_xLinguOptionsEditPB
->set_sensitive( aData
.HasNumericValue() );
1507 OSL_FAIL( "rBox unexpected value" );
1511 void SvxLinguTabPage::HideGroups( sal_uInt16 nGrp
)
1513 if ( 0 != ( GROUP_MODULES
& nGrp
) )
1515 m_xLinguModulesFT
->hide();
1516 m_xLinguModulesCLB
->hide();
1517 m_xLinguModulesEditPB
->hide();
1519 if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode()
1520 != SvtExtendedSecurityOptions::OPEN_NEVER
)
1522 m_xMoreDictsLink
->show();
1527 SvxEditModulesDlg::SvxEditModulesDlg(weld::Window
* pParent
, SvxLinguData_Impl
& rData
)
1528 : GenericDialogController(pParent
, "cui/ui/editmodulesdialog.ui", "EditModulesDialog")
1529 , sSpell(CuiResId(RID_SVXSTR_SPELL
))
1530 , sHyph(CuiResId(RID_SVXSTR_HYPH
))
1531 , sThes(CuiResId(RID_SVXSTR_THES
))
1532 , sGrammar(CuiResId(RID_SVXSTR_GRAMMAR
))
1534 , m_xModulesCLB(m_xBuilder
->weld_tree_view("lingudicts"))
1535 , m_xPrioUpPB(m_xBuilder
->weld_button("up"))
1536 , m_xPrioDownPB(m_xBuilder
->weld_button("down"))
1537 , m_xBackPB(m_xBuilder
->weld_button("back"))
1538 , m_xMoreDictsLink(m_xBuilder
->weld_link_button("moredictslink"))
1539 , m_xClosePB(m_xBuilder
->weld_button("close"))
1540 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder
->weld_combo_box("language")))
1542 m_xModulesCLB
->set_size_request(m_xModulesCLB
->get_approximate_digit_width() * 40,
1543 m_xModulesCLB
->get_height_rows(12));
1545 std::vector
<int> aWidths
;
1546 aWidths
.push_back(m_xModulesCLB
->get_checkbox_column_width());
1547 m_xModulesCLB
->set_column_fixed_widths(aWidths
);
1549 pDefaultLinguData
.reset( new SvxLinguData_Impl( rLinguData
) );
1551 m_xModulesCLB
->connect_changed( LINK( this, SvxEditModulesDlg
, SelectHdl_Impl
));
1552 m_xModulesCLB
->connect_toggled(LINK(this, SvxEditModulesDlg
, BoxCheckButtonHdl_Impl
));
1554 m_xClosePB
->connect_clicked( LINK( this, SvxEditModulesDlg
, ClickHdl_Impl
));
1555 m_xPrioUpPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, UpDownHdl_Impl
));
1556 m_xPrioDownPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, UpDownHdl_Impl
));
1557 m_xBackPB
->connect_clicked( LINK( this, SvxEditModulesDlg
, BackHdl_Impl
));
1558 // in case of not installed language modules
1559 m_xPrioUpPB
->set_sensitive( false );
1560 m_xPrioDownPB
->set_sensitive( false );
1562 if ( SvtExtendedSecurityOptions().GetOpenHyperlinkMode() == SvtExtendedSecurityOptions::OPEN_NEVER
)
1563 m_xMoreDictsLink
->hide();
1565 // set that we want the checkbox shown if spellchecking is available
1566 m_xLanguageLB
->SetLanguageList(SvxLanguageListFlags::EMPTY
, false, false, true);
1569 const Sequence
< Locale
>& rLoc
= rLinguData
.GetAllSupportedLocales();
1570 const Locale
* pLocales
= rLoc
.getConstArray();
1571 for (int i
= 0; i
< rLoc
.getLength(); ++i
)
1573 LanguageType nLang
= LanguageTag::convertToLanguageType( pLocales
[i
] );
1574 m_xLanguageLB
->InsertLanguage(nLang
);
1576 LanguageType eSysLang
= MsLangId::getSystemLanguage();
1577 m_xLanguageLB
->set_active_id( eSysLang
);
1578 if (m_xLanguageLB
->get_active_id() != eSysLang
)
1579 m_xLanguageLB
->set_active(0);
1581 m_xLanguageLB
->connect_changed( LINK( this, SvxEditModulesDlg
, LangSelectListBoxHdl_Impl
));
1582 LangSelectHdl_Impl(m_xLanguageLB
.get());
1585 SvxEditModulesDlg::~SvxEditModulesDlg()
1587 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1588 delete reinterpret_cast<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
).toInt64());
1591 IMPL_LINK( SvxEditModulesDlg
, SelectHdl_Impl
, weld::TreeView
&, rBox
, void )
1593 int nCurPos
= rBox
.get_selected_index();
1596 bool bDisableUp
= true;
1597 bool bDisableDown
= true;
1598 ModuleUserData_Impl
* pData
= reinterpret_cast<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
).toInt64());
1599 if (!pData
->IsParent() && pData
->GetType() != TYPE_HYPH
)
1601 if (nCurPos
< rBox
.n_children() - 1)
1603 bDisableDown
= reinterpret_cast<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
+ 1).toInt64())->IsParent();
1607 bDisableUp
= reinterpret_cast<ModuleUserData_Impl
*>(rBox
.get_id(nCurPos
- 1).toInt64())->IsParent();
1610 m_xPrioUpPB
->set_sensitive(!bDisableUp
);
1611 m_xPrioDownPB
->set_sensitive(!bDisableDown
);
1615 IMPL_LINK( SvxEditModulesDlg
, BoxCheckButtonHdl_Impl
, const row_col
&, rRowCol
, void )
1617 auto nPos
= rRowCol
.first
;
1618 ModuleUserData_Impl
* pData
= reinterpret_cast<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(nPos
).toInt64());
1619 if (!pData
->IsParent() && pData
->GetType() == TYPE_HYPH
)
1621 // make hyphenator checkboxes function as radio-buttons
1622 // (at most one box may be checked)
1623 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1625 pData
= reinterpret_cast<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
).toInt64());
1626 if (!pData
->IsParent() && pData
->GetType() == TYPE_HYPH
&& i
!= nPos
)
1628 m_xModulesCLB
->set_toggle(i
, TRISTATE_FALSE
, 0);
1634 IMPL_LINK_NOARG(SvxEditModulesDlg
, LangSelectListBoxHdl_Impl
, weld::ComboBox
&, void)
1636 LangSelectHdl_Impl(m_xLanguageLB
.get());
1639 void SvxEditModulesDlg::LangSelectHdl_Impl(const SvxLanguageBox
* pBox
)
1641 LanguageType eCurLanguage
= m_xLanguageLB
->get_active_id();
1642 static Locale aLastLocale
;
1643 Locale
aCurLocale( LanguageTag::convertToLocale( eCurLanguage
));
1647 // save old probably changed settings
1648 // before switching to new language entries
1650 LanguageType nLang
= LanguageTag::convertToLanguageType( aLastLocale
);
1652 sal_Int32 nStart
= 0, nLocalIndex
= 0;
1653 Sequence
< OUString
> aChange
;
1654 bool bChanged
= false;
1655 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1657 ModuleUserData_Impl
* pData
= reinterpret_cast<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
).toInt64());
1658 if (pData
->IsParent())
1662 LangImplNameTable
*pTable
= nullptr;
1663 sal_uInt8 nType
= pData
->GetType();
1666 case TYPE_SPELL
: pTable
= &rLinguData
.GetSpellTable(); break;
1667 case TYPE_GRAMMAR
: pTable
= &rLinguData
.GetGrammarTable(); break;
1668 case TYPE_HYPH
: pTable
= &rLinguData
.GetHyphTable(); break;
1669 case TYPE_THES
: pTable
= &rLinguData
.GetThesTable(); break;
1673 aChange
.realloc(nStart
);
1674 (*pTable
)[ nLang
] = aChange
;
1677 nLocalIndex
= nStart
= 0;
1678 aChange
.realloc(nEntryCount
);
1683 OUString
* pChange
= aChange
.getArray();
1684 pChange
[nStart
] = pData
->GetImplName();
1685 bChanged
|= pData
->GetIndex() != nLocalIndex
||
1686 static_cast<TriState
>(pData
->IsChecked()) != m_xModulesCLB
->get_toggle(i
, 0);
1687 if (m_xModulesCLB
->get_toggle(i
, 0))
1694 aChange
.realloc(nStart
);
1695 rLinguData
.GetThesTable()[ nLang
] = aChange
;
1699 for (int i
= 0, nEntryCount
= m_xModulesCLB
->n_children(); i
< nEntryCount
; ++i
)
1700 delete reinterpret_cast<ModuleUserData_Impl
*>(m_xModulesCLB
->get_id(i
).toInt64());
1701 m_xModulesCLB
->clear();
1703 // display entries for new selected language
1705 if (LANGUAGE_DONTKNOW
!= eCurLanguage
)
1708 ServiceInfo_Impl
* pInfo
;
1711 // spellchecker entries
1713 ModuleUserData_Impl
* pUserData
= new ModuleUserData_Impl(
1714 OUString(), true, false, TYPE_SPELL
, 0 );
1715 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pUserData
)));
1716 m_xModulesCLB
->append(nullptr);
1717 m_xModulesCLB
->set_id(nRow
, sId
);
1718 m_xModulesCLB
->set_text(nRow
, sSpell
, 1);
1719 m_xModulesCLB
->set_text_emphasis(nRow
, true, 1);
1722 Sequence
< OUString
> aNames( rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_SPELL
) );
1723 const OUString
*pName
= aNames
.getConstArray();
1724 sal_uLong nNames
= static_cast<sal_uLong
>(aNames
.getLength());
1725 sal_Int32 nLocalIndex
= 0; // index relative to parent
1726 for (n
= 0; n
< nNames
; ++n
)
1729 bool bIsSuppLang
= false;
1731 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1734 bIsSuppLang
= pInfo
->xSpell
.is() &&
1735 pInfo
->xSpell
->hasLocale( aCurLocale
);
1736 aImplName
= pInfo
->sSpellImplName
;
1738 if (!aImplName
.isEmpty() && bIsSuppLang
)
1740 OUString
aTxt( pInfo
->sDisplayName
);
1742 LangImplNameTable
&rTable
= rLinguData
.GetSpellTable();
1743 const bool bHasLang
= rTable
.count( eCurLanguage
);
1746 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1748 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1749 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1750 bCheck
, TYPE_SPELL
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1751 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1753 m_xModulesCLB
->append(nullptr);
1754 m_xModulesCLB
->set_id(nRow
, sId
);
1755 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1756 m_xModulesCLB
->set_text(nRow
, aTxt
, 1);
1761 // grammar checker entries
1763 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_GRAMMAR
, 0 );
1764 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1765 m_xModulesCLB
->append(nullptr);
1766 m_xModulesCLB
->set_id(nRow
, sId
);
1767 m_xModulesCLB
->set_text(nRow
, sGrammar
, 1);
1768 m_xModulesCLB
->set_text_emphasis(nRow
, true, 1);
1771 aNames
= rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_GRAMMAR
);
1772 pName
= aNames
.getConstArray();
1773 nNames
= static_cast<sal_uLong
>(aNames
.getLength());
1775 for (n
= 0; n
< nNames
; ++n
)
1778 bool bIsSuppLang
= false;
1780 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1783 bIsSuppLang
= pInfo
->xGrammar
.is() &&
1784 pInfo
->xGrammar
->hasLocale( aCurLocale
);
1785 aImplName
= pInfo
->sGrammarImplName
;
1787 if (!aImplName
.isEmpty() && bIsSuppLang
)
1789 OUString
aTxt( pInfo
->sDisplayName
);
1791 LangImplNameTable
&rTable
= rLinguData
.GetGrammarTable();
1792 const bool bHasLang
= rTable
.count( eCurLanguage
);
1795 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1797 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1798 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1799 bCheck
, TYPE_GRAMMAR
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1801 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1803 m_xModulesCLB
->append(nullptr);
1804 m_xModulesCLB
->set_id(nRow
, sId
);
1805 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1806 m_xModulesCLB
->set_text(nRow
, aTxt
, 1);
1811 // hyphenator entries
1813 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_HYPH
, 0 );
1814 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1815 m_xModulesCLB
->append(nullptr);
1816 m_xModulesCLB
->set_id(nRow
, sId
);
1817 m_xModulesCLB
->set_text(nRow
, sHyph
, 1);
1818 m_xModulesCLB
->set_text_emphasis(nRow
, true, 1);
1821 aNames
= rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_HYPH
);
1822 pName
= aNames
.getConstArray();
1823 nNames
= static_cast<sal_uLong
>(aNames
.getLength());
1825 for (n
= 0; n
< nNames
; ++n
)
1828 bool bIsSuppLang
= false;
1830 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1833 bIsSuppLang
= pInfo
->xHyph
.is() &&
1834 pInfo
->xHyph
->hasLocale( aCurLocale
);
1835 aImplName
= pInfo
->sHyphImplName
;
1837 if (!aImplName
.isEmpty() && bIsSuppLang
)
1839 OUString
aTxt( pInfo
->sDisplayName
);
1841 LangImplNameTable
&rTable
= rLinguData
.GetHyphTable();
1842 const bool bHasLang
= rTable
.count( eCurLanguage
);
1845 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1847 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1848 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1849 bCheck
, TYPE_HYPH
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1850 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1852 m_xModulesCLB
->append(nullptr);
1853 m_xModulesCLB
->set_id(nRow
, sId
);
1854 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1855 m_xModulesCLB
->set_text(nRow
, aTxt
, 1);
1860 // thesaurus entries
1862 pUserData
= new ModuleUserData_Impl( OUString(), true, false, TYPE_THES
, 0 );
1863 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1864 m_xModulesCLB
->append(nullptr);
1865 m_xModulesCLB
->set_id(nRow
, sId
);
1866 m_xModulesCLB
->set_text(nRow
, sThes
, 1);
1867 m_xModulesCLB
->set_text_emphasis(nRow
, true, 1);
1870 aNames
= rLinguData
.GetSortedImplNames( eCurLanguage
, TYPE_THES
);
1871 pName
= aNames
.getConstArray();
1872 nNames
= static_cast<sal_uLong
>(aNames
.getLength());
1874 for (n
= 0; n
< nNames
; ++n
)
1877 bool bIsSuppLang
= false;
1879 pInfo
= rLinguData
.GetInfoByImplName( pName
[n
] );
1882 bIsSuppLang
= pInfo
->xThes
.is() &&
1883 pInfo
->xThes
->hasLocale( aCurLocale
);
1884 aImplName
= pInfo
->sThesImplName
;
1886 if (!aImplName
.isEmpty() && bIsSuppLang
)
1888 OUString
aTxt( pInfo
->sDisplayName
);
1890 LangImplNameTable
&rTable
= rLinguData
.GetThesTable();
1891 const bool bHasLang
= rTable
.count( eCurLanguage
);
1894 SAL_INFO( "cui.options", "language entry missing" ); // only relevant if all languages found should be supported
1896 const bool bCheck
= bHasLang
&& lcl_SeqGetEntryPos( rTable
[ eCurLanguage
], aImplName
) >= 0;
1897 pUserData
= new ModuleUserData_Impl( aImplName
, false,
1898 bCheck
, TYPE_THES
, static_cast<sal_uInt8
>(nLocalIndex
++) );
1899 sId
= OUString::number(reinterpret_cast<sal_Int64
>(pUserData
));
1901 m_xModulesCLB
->append(nullptr);
1902 m_xModulesCLB
->set_id(nRow
, sId
);
1903 m_xModulesCLB
->set_toggle(nRow
, bCheck
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1904 m_xModulesCLB
->set_text(nRow
, aTxt
, 1);
1909 aLastLocale
= aCurLocale
;
1912 IMPL_LINK( SvxEditModulesDlg
, UpDownHdl_Impl
, weld::Button
&, rBtn
, void )
1914 bool bUp
= m_xPrioUpPB
.get() == &rBtn
;
1915 int nCurPos
= m_xModulesCLB
->get_selected_index();
1918 m_xModulesCLB
->freeze();
1920 OUString
sId(m_xModulesCLB
->get_id(nCurPos
));
1921 OUString
sStr(m_xModulesCLB
->get_text(nCurPos
));
1922 bool bIsChecked
= m_xModulesCLB
->get_toggle(nCurPos
, nCurPos
);
1924 m_xModulesCLB
->remove(nCurPos
);
1926 int nDestPos
= bUp
? nCurPos
- 1 : nCurPos
+ 1;
1928 m_xModulesCLB
->insert_text(nDestPos
, sStr
);
1929 m_xModulesCLB
->set_id(nDestPos
, sId
);
1930 m_xModulesCLB
->set_toggle(nDestPos
, bIsChecked
? TRISTATE_TRUE
: TRISTATE_FALSE
, 0);
1932 m_xModulesCLB
->thaw();
1934 m_xModulesCLB
->select(nDestPos
);
1935 SelectHdl_Impl(*m_xModulesCLB
);
1939 IMPL_LINK_NOARG(SvxEditModulesDlg
, ClickHdl_Impl
, weld::Button
&, void)
1941 // store language config
1942 LangSelectHdl_Impl(m_xLanguageLB
.get());
1943 m_xDialog
->response(RET_OK
);
1946 IMPL_LINK_NOARG(SvxEditModulesDlg
, BackHdl_Impl
, weld::Button
&, void)
1948 rLinguData
= *pDefaultLinguData
;
1949 LangSelectHdl_Impl(nullptr);
1952 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */