LibreOffice Module cui (master) 1
optdict.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <editeng/unolingu.hxx>
21#include <o3tl/safeint.hxx>
22#include <svx/dialmgr.hxx>
23#include <com/sun/star/frame/XStorable.hpp>
24#include <com/sun/star/linguistic2/XDictionary.hpp>
25#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
26#include <comphelper/string.hxx>
27#include <tools/debug.hxx>
31#include <vcl/svapp.hxx>
32#include <vcl/weld.hxx>
33
34#include <linguistic/misc.hxx>
35#include <strings.hrc>
36#include <optdict.hxx>
37#include <dialmgr.hxx>
38#include <svx/svxerr.hxx>
39
40using namespace ::com::sun::star;
41using namespace ::com::sun::star::uno;
42using namespace ::com::sun::star::linguistic2;
43using namespace linguistic;
44
45// static function -------------------------------------------------------
46
47static OUString getNormDicEntry_Impl(std::u16string_view rText)
48{
49 OUString aTmp(comphelper::string::stripEnd(rText, '.'));
50 // non-standard hyphenation
51 if (aTmp.indexOf('[') > -1)
52 {
53 OUStringBuffer aTmp2 ( aTmp.getLength() );
54 bool bSkip = false;
55 for (sal_Int32 i = 0; i < aTmp.getLength(); i++)
56 {
57 sal_Unicode cTmp = aTmp[i];
58 if (cTmp == '[')
59 bSkip = true;
60 else if (!bSkip)
61 aTmp2.append( cTmp );
62 else if (cTmp == ']')
63 bSkip = false;
64 }
65 aTmp = aTmp2.makeStringAndClear();
66 }
67 return aTmp.replaceAll("=", "");
68}
69
70// tdf#154499 separate words of a phrase only by a single space,
71// i.e. trim terminating spaces and replace space sequences with single spaces
72static OUString fixSpace(OUString sText)
73{
74 sText = sText.trim();
75
76 sal_Int32 nLen;
77 do
78 {
79 nLen = sText.getLength();
80 sText = sText.replaceAll(" ", " ");
81 }
82 while ( sText.getLength() < nLen );
83
84 return sText;
85}
86
87namespace {
88
89// Compare Dictionary Entry result
90enum CDE_RESULT { CDE_EQUAL, CDE_SIMILAR, CDE_DIFFERENT };
91
92}
93
94static CDE_RESULT cmpDicEntry_Impl( std::u16string_view rText1, std::u16string_view rText2 )
95{
96 CDE_RESULT eRes = CDE_DIFFERENT;
97
98 if (rText1 == rText2)
99 eRes = CDE_EQUAL;
100 else
101 { // similar = equal up to trailing '.' and hyphenation positions
102 // marked with '=' and '[' + alternative spelling pattern + ']'
103 if (getNormDicEntry_Impl( rText1 ) == getNormDicEntry_Impl( rText2 ))
104 eRes = CDE_SIMILAR;
105 }
106
107 return eRes;
108}
109
110// class SvxNewDictionaryDialog -------------------------------------------
111
113 : GenericDialogController(pParent, "cui/ui/optnewdictionarydialog.ui", "OptNewDictionaryDialog")
114 , m_xNameEdit(m_xBuilder->weld_entry("nameedit"))
115 , m_xLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("language")))
116 , m_xExceptBtn(m_xBuilder->weld_check_button("except"))
117 , m_xOKBtn(m_xBuilder->weld_button("ok"))
118{
119 // Prevent creation of dictionary without a name.
120 m_xOKBtn->set_sensitive(false);
121
122 // install handler
123 m_xNameEdit->connect_changed(LINK(this, SvxNewDictionaryDialog, ModifyHdl_Impl));
124 m_xOKBtn->connect_clicked(LINK(this, SvxNewDictionaryDialog, OKHdl_Impl));
125
126 // display languages
127 m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::ALL, true, true);
128 m_xLanguageLB->set_active(0);
129}
130
132{
133
134 // add extension for personal dictionaries
135 OUString sDict = comphelper::string::stripEnd(m_xNameEdit->get_text(), ' ') + ".dic";
136
137 Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
138
139 Sequence< Reference< XDictionary > > aDics;
140 if (xDicList.is())
141 aDics = xDicList->getDictionaries();
142 const Reference< XDictionary > *pDic = aDics.getConstArray();
143 sal_Int32 nCount = aDics.getLength();
144
145 bool bFound = false;
146 sal_Int32 i;
147 for (i = 0; !bFound && i < nCount; ++i )
148 if ( sDict.equalsIgnoreAsciiCase( pDic[i]->getName()) )
149 bFound = true;
150
151 if ( sDict.indexOf("/") != -1 || sDict.indexOf("\\") != -1 )
152 {
153 // Detected an invalid character.
154 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
155 VclMessageType::Info, VclButtonsType::Ok,
156 CuiResId(RID_CUISTR_OPT_INVALID_DICT_NAME)));
157 xInfoBox->run();
158 m_xNameEdit->grab_focus();
159 return;
160 }
161
162 if ( bFound )
163 {
164 // duplicate names?
165 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
166 VclMessageType::Info, VclButtonsType::Ok,
167 CuiResId(RID_CUISTR_OPT_DOUBLE_DICTS)));
168 xInfoBox->run();
169 m_xNameEdit->grab_focus();
170 return;
171 }
172
173 // create and add
174 LanguageType nLang = m_xLanguageLB->get_active_id();
175 try
176 {
177 // create new dictionary
178 DictionaryType eType = m_xExceptBtn->get_active() ?
179 DictionaryType_NEGATIVE : DictionaryType_POSITIVE;
180 if (xDicList.is())
181 {
182 lang::Locale aLocale( LanguageTag::convertToLocale(nLang) );
183 OUString aURL( linguistic::GetWritableDictionaryURL( sDict ) );
184 m_xNewDic = xDicList->createDictionary(sDict, aLocale, eType, aURL);
185 m_xNewDic->setActive(true);
186 }
187 DBG_ASSERT(m_xNewDic.is(), "NULL pointer");
188 }
189 catch(...)
190 {
191 m_xNewDic = nullptr;
192 // error: couldn't create new dictionary
193 SfxErrorContext aContext( ERRCTX_SVX_LINGU_DICTIONARY, OUString(),
197 m_xDialog->response(RET_CANCEL);
198 }
199
200 if (xDicList.is() && m_xNewDic.is())
201 {
202 xDicList->addDictionary(m_xNewDic);
203
204 // refresh list of dictionaries
206 aDics = xDicList->getDictionaries();
207 }
208
209 m_xDialog->response(RET_OK);
210}
211
213{
214 m_xOKBtn->set_sensitive(!m_xNameEdit->get_text().isEmpty());
215}
216
217// class SvxEditDictionaryDialog -------------------------------------------
218
220 : GenericDialogController(pParent, "cui/ui/editdictionarydialog.ui", "EditDictionaryDialog")
221 , sModify(CuiResId(STR_MODIFY))
222 , bFirstSelect(false)
223 , bDoNothing(false)
224 , bDicIsReadonly(false)
225 , m_xAllDictsLB(m_xBuilder->weld_combo_box("book"))
226 , m_xLangFT(m_xBuilder->weld_label("lang_label"))
227 , m_xLangLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("lang")))
228 , m_xWordED(m_xBuilder->weld_entry("word"))
229 , m_xReplaceFT(m_xBuilder->weld_label("replace_label"))
230 , m_xReplaceED(m_xBuilder->weld_entry("replace"))
231 , m_xSingleColumnLB(m_xBuilder->weld_tree_view("words"))
232 , m_xDoubleColumnLB(m_xBuilder->weld_tree_view("replaces"))
233 , m_xNewReplacePB(m_xBuilder->weld_button("newreplace"))
234 , m_xDeletePB(m_xBuilder->weld_button("delete"))
235{
236 sReplaceFT_Text = m_xReplaceFT->get_label();
237 m_xSingleColumnLB->set_size_request(-1, m_xSingleColumnLB->get_height_rows(8));
238 m_xDoubleColumnLB->set_size_request(-1, m_xDoubleColumnLB->get_height_rows(8));
240 m_xSingleColumnLB->hide();
241
242 //set to max of both sizes to avoid resizes
243 sNew = m_xNewReplacePB->get_label();
244 auto nNewWidth = m_xNewReplacePB->get_preferred_size().Width();
245 m_xNewReplacePB->set_label(sModify);
246 auto nReplaceWidth = m_xNewReplacePB->get_preferred_size().Width();
247 m_xNewReplacePB->set_label(sNew);
248 m_xNewReplacePB->set_size_request(std::max(nNewWidth, nReplaceWidth), -1);
249
251 aDics = LinguMgr::GetDictionaryList()->getDictionaries();
252
253 m_xSingleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl));
254 m_xDoubleColumnLB->connect_changed(LINK(this, SvxEditDictionaryDialog, SelectHdl));
255
256 std::vector<int> aWidths
257 {
258 o3tl::narrowing<int>(m_xDoubleColumnLB->get_approximate_digit_width() * 22)
259 };
260 m_xDoubleColumnLB->set_column_fixed_widths(aWidths);
261
262 // install handler
263 m_xNewReplacePB->connect_clicked(
264 LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl));
265 m_xDeletePB->connect_clicked(
266 LINK( this, SvxEditDictionaryDialog, NewDelButtonHdl));
267
268 m_xLangLB->connect_changed(
269 LINK( this, SvxEditDictionaryDialog, SelectLangHdl_Impl ) );
270 m_xAllDictsLB->connect_changed(
271 LINK( this, SvxEditDictionaryDialog, SelectBookHdl_Impl ) );
272
273 m_xWordED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
274 m_xReplaceED->connect_changed(LINK(this, SvxEditDictionaryDialog, ModifyHdl));
275 m_xWordED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl));
276 m_xReplaceED->connect_activate(LINK(this, SvxEditDictionaryDialog, NewDelActionHdl));
277
278 // fill listbox with all available WB's
279 const Reference< XDictionary > *pDic = aDics.getConstArray();
280 sal_Int32 nCount = aDics.getLength();
281
282 OUString aLookUpEntry;
283 for ( sal_Int32 i = 0; i < nCount; ++i )
284 {
285 Reference< XDictionary > xDic = pDic[i];
286 if (xDic.is())
287 {
288 bool bNegative = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
289 OUString aDicName( xDic->getName() );
290 const OUString aTxt( ::GetDicInfoStr( aDicName,
291 LanguageTag( xDic->getLocale() ).getLanguageType(), bNegative ) );
292 m_xAllDictsLB->append_text(aTxt);
293
294 if (rName == aDicName)
295 aLookUpEntry = aTxt;
296 }
297 }
298
299 m_xLangLB->SetLanguageList( SvxLanguageListFlags::ALL, true, true );
300
301 if ( nCount > 0 )
302 {
303 m_xAllDictsLB->set_active_text(aLookUpEntry);
304 int nPos = m_xAllDictsLB->get_active();
305
306 if (nPos == -1)
307 {
308 nPos = 0;
309 m_xAllDictsLB->set_active(nPos);
310 }
311 Reference< XDictionary > xDic;
312 if (nPos != -1)
313 xDic = aDics[ nPos ];
314 if (xDic.is())
315 SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() );
316
317 // check if dictionary is read-only
319 bool bEnable = !IsDicReadonly_Impl();
320 m_xNewReplacePB->set_sensitive( false );
321 m_xDeletePB->set_sensitive( false );
322 m_xLangFT->set_sensitive( bEnable );
323 m_xLangLB->set_sensitive( bEnable );
325 }
326 else
327 {
328 m_xNewReplacePB->set_sensitive(false);
329 m_xDeletePB->set_sensitive(false);
330 }
331
332 m_xWordED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl));
333 m_xReplaceED->connect_size_allocate(LINK(this, SvxEditDictionaryDialog, EntrySizeAllocHdl));
334}
335
336IMPL_LINK_NOARG(SvxEditDictionaryDialog, EntrySizeAllocHdl, const Size&, void)
337{
338 std::vector<int> aWidths;
339 int x, y, width, height;
340 if (m_xReplaceED->get_extents_relative_to(*m_pWordsLB, x, y, width, height))
341 {
342 aWidths.push_back(x);
343 m_xDoubleColumnLB->set_column_fixed_widths(aWidths);
344 }
345}
346
348{
349}
350
352 Reference< XDictionary > const &xDic )
353{
354 // enable or disable new and delete button according to file attributes
355 bDicIsReadonly = true;
356 if (xDic.is())
357 {
358 Reference< frame::XStorable > xStor( xDic, UNO_QUERY );
359 if ( !xStor.is() // non persistent dictionary
360 || !xStor->hasLocation() // not yet persistent
361 || !xStor->isReadonly() )
362 {
363 bDicIsReadonly = false;
364 }
365 }
366}
367
369{
370 // select language
371 m_xLangLB->set_active_id(nLanguage);
372}
373
374int SvxEditDictionaryDialog::GetLBInsertPos(std::u16string_view rDicWord)
375{
376 IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
377 const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
378 int j;
380 for (j = 0; j < nCount; ++j)
381 {
382 OUString aNormEntry( getNormDicEntry_Impl( rDicWord ) );
383 sal_Int32 nCmpRes = pCollator->
384 compareString( aNormEntry, getNormDicEntry_Impl( m_pWordsLB->get_text(j, 0) ) );
385 if (nCmpRes < 0)
386 break;
387 }
388
389 return j;
390}
391
393{
394 int nLBPos = m_xAllDictsLB->get_active();
395 if (nEntry != -1 && nLBPos != -1)
396 {
397 OUString sTmpShort(m_pWordsLB->get_text(nEntry, 0));
398
399 Reference<XDictionary> xDic = aDics.getConstArray()[nLBPos];
400 if (xDic->remove(sTmpShort)) // sal_True on success
401 {
402 m_pWordsLB->remove(nEntry);
403 SelectHdl(*m_pWordsLB);
404 }
405 }
406}
407
409{
410 int nPos = m_xAllDictsLB->get_active();
411 if (nPos == -1)
412 return;
413
414 m_xNewReplacePB->set_sensitive( false );
415 m_xDeletePB->set_sensitive( false );
416 // display dictionary
417 ShowWords_Impl( nPos );
418 // enable or disable new and delete button according to file attributes
419 Reference< XDictionary > const & xDic = aDics[ nPos ];
420 if (xDic.is())
421 SetLanguage_Impl( LanguageTag( xDic->getLocale() ).getLanguageType() );
422
423 SetDicReadonly_Impl(xDic);
424 bool bEnable = !IsDicReadonly_Impl();
425 m_xLangFT->set_sensitive( bEnable );
426 m_xLangLB->set_sensitive( bEnable );
427}
428
430{
431 int nDicPos = m_xAllDictsLB->get_active();
432 LanguageType nLang = m_xLangLB->get_active_id();
433 Reference< XDictionary > const & xDic = aDics[ nDicPos ];
434 LanguageType nOldLang = LanguageTag( xDic->getLocale() ).getLanguageType();
435
436 if ( nLang == nOldLang )
437 return;
438
439 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
440 VclMessageType::Question, VclButtonsType::YesNo,
441 CuiResId(RID_CUISTR_CONFIRM_SET_LANGUAGE)));
442 OUString sTxt(xBox->get_primary_text());
443 sTxt = sTxt.replaceFirst("%1", m_xAllDictsLB->get_active_text());
444 xBox->set_primary_text(sTxt);
445
446 if (xBox->run() == RET_YES)
447 {
448 xDic->setLocale( LanguageTag::convertToLocale( nLang ) );
449 bool bNegativ = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
450
451 const OUString sName(
452 ::GetDicInfoStr( xDic->getName(),
453 LanguageTag( xDic->getLocale() ).getLanguageType(),
454 bNegativ ) );
455 m_xAllDictsLB->remove(nDicPos);
456 m_xAllDictsLB->insert_text(nDicPos, sName);
457 m_xAllDictsLB->set_active(nDicPos);
458 }
459 else
460 SetLanguage_Impl( nOldLang );
461}
462
464{
465 Reference< XDictionary > xDic = aDics.getConstArray()[ nId ];
466
467 weld::WaitObject aWait(m_xDialog.get());
468
469 m_xWordED->set_text(OUString());
470 m_xReplaceED->set_text(OUString());
471
472 bool bIsNegative = xDic->getDictionaryType() != DictionaryType_POSITIVE;
473 bool bLangNone = LanguageTag(
474 xDic->getLocale() ).getLanguageType() == LANGUAGE_NONE;
475
476 // The label is "Replace By" only in negative dictionaries (forbidden
477 // words), otherwise "Grammar By" in language-specific dictionaries
478 // (where the optional second word is the sample word for
479 // the Hunspell based affixation/compounding of the new dictionary word)
480 if (bIsNegative)
481 {
482 m_xReplaceFT->set_label(sReplaceFT_Text);
483 } else if (!bLangNone) {
484 m_xReplaceFT->set_label(CuiResId(RID_CUISTR_OPT_GRAMMAR_BY));
485 }
486
487 if(bIsNegative || !bLangNone)
488 {
489 // make controls for replacement text active
490 if (!m_xReplaceFT->get_visible())
491 {
492 m_xReplaceFT->show();
493 m_xReplaceED->show();
494 m_xSingleColumnLB->hide();
495 m_xDoubleColumnLB->show();
497 }
498 }
499 else
500 {
501 // deactivate controls for replacement text
502 if (m_xReplaceFT->get_visible())
503 {
504 m_xReplaceFT->hide();
505 m_xReplaceED->hide();
506 m_xDoubleColumnLB->hide();
507 m_xSingleColumnLB->show();
509 }
510 }
511
512 m_pWordsLB->clear();
513
514 Sequence< Reference< XDictionaryEntry > > aEntries( xDic->getEntries() );
515 const Reference< XDictionaryEntry > *pEntry = aEntries.getConstArray();
516 sal_Int32 nCount = aEntries.getLength();
517 std::vector<OUString> aSortedDicEntries;
518 aSortedDicEntries.reserve(nCount);
519 for (sal_Int32 i = 0; i < nCount; i++)
520 {
521 OUString aStr = pEntry[i]->getDictionaryWord();
522 if(!pEntry[i]->getReplacementText().isEmpty())
523 {
524 aStr += "\t" + pEntry[i]->getReplacementText();
525 }
526 aSortedDicEntries.push_back(aStr);
527 }
528
529 IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
530 const CollatorWrapper* pCollator = aIntlWrapper.getCollator();
531 std::sort(aSortedDicEntries.begin(), aSortedDicEntries.end(),
532 [&] (OUString const & lhs, OUString const & rhs)
533 {
534 sal_Int32 nCmpRes = pCollator->
535 compareString( getNormDicEntry_Impl(lhs), getNormDicEntry_Impl( rhs ) );
536 return nCmpRes < 0;
537 });
538
539 m_pWordsLB->freeze(); // speed up insert
540 int nRow = 0;
541 for (OUString const & rStr : aSortedDicEntries)
542 {
543 m_pWordsLB->append_text(rStr.getToken(0, '\t'));
544 if (m_pWordsLB == m_xDoubleColumnLB.get())
545 {
546 OUString sReplace = rStr.getToken(1, '\t');
547 m_pWordsLB->set_text(nRow, sReplace, 1);
548 ++nRow;
549 }
550 }
551 m_pWordsLB->thaw();
552
553 if (m_pWordsLB->n_children())
554 {
555 m_pWordsLB->select(0);
557 SelectHdl(*m_pWordsLB);
558 }
559}
560
562{
563 if (bDoNothing)
564 return;
565
566 int nEntry = rBox.get_selected_index();
567
568 if(!bFirstSelect)
569 {
570 if (nEntry != -1)
571 {
572 OUString sTmpShort(rBox.get_text(nEntry, 0));
573 // without this the cursor is always at the beginning of a word, if the text
574 // is set over the ModifyHdl, although you're editing there at the moment
575 if (m_xWordED->get_text() != sTmpShort)
576 m_xWordED->set_text(sTmpShort);
577 if (&rBox == m_xDoubleColumnLB.get())
578 m_xReplaceED->set_text(rBox.get_text(nEntry, 1));
579 }
580 }
581 else
582 bFirstSelect = false;
583
584 // entries in the list box should exactly correspond to those from the
585 // dictionary. Thus:
586 m_xNewReplacePB->set_sensitive(false);
587 m_xDeletePB->set_sensitive(nEntry != -1 && !IsDicReadonly_Impl());
588}
589
590IMPL_LINK(SvxEditDictionaryDialog, NewDelButtonHdl, weld::Button&, rBtn, void)
591{
592 NewDelHdl(&rBtn);
593}
594
595IMPL_LINK(SvxEditDictionaryDialog, NewDelActionHdl, weld::Entry&, rDictEdit, bool)
596{
597 return NewDelHdl(&rDictEdit);
598}
599
601{
602 if (pBtn == m_xDeletePB.get())
603 {
604 m_xWordED->set_text("");
605 m_xReplaceED->set_text("");
606 m_xDeletePB->set_sensitive(false);
607
608 int nEntry = m_pWordsLB->get_selected_index();
609 RemoveDictEntry(nEntry); // remove entry from dic and list-box
610 }
611 if (pBtn == m_xNewReplacePB.get() || m_xNewReplacePB->get_sensitive())
612 {
613 int nEntry = m_pWordsLB->get_selected_index();
614 OUString aNewWord(fixSpace(m_xWordED->get_text()));
615 OUString sEntry(aNewWord);
616 OUString aReplaceStr(fixSpace(m_xReplaceED->get_text()));
617
618 DictionaryError nAddRes = DictionaryError::UNKNOWN;
619 int nPos = m_xAllDictsLB->get_active();
620 if (nPos != -1 && !aNewWord.isEmpty())
621 {
622 DBG_ASSERT(nPos < aDics.getLength(), "invalid dictionary index");
623 Reference< XDictionary > const & xDic = aDics[ nPos ];
624 if (xDic.is())
625 {
626 // make changes in dic
627
628 bool bIsNegEntry = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
629
630 OUString aRplcText;
631 if(!aReplaceStr.isEmpty())
632 aRplcText = aReplaceStr;
633
634 if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry
635 xDic->remove(m_pWordsLB->get_text(nEntry, 0));
636 // if remove has failed the following add should fail too
637 // and thus a warning message should be triggered...
638
639 nAddRes = linguistic::AddEntryToDic( xDic,
640 aNewWord, bIsNegEntry,
641 aRplcText, false );
642 }
643 }
644 if (DictionaryError::NONE != nAddRes)
645 SvxDicError(m_xDialog.get(), nAddRes);
646
647 if (DictionaryError::NONE == nAddRes && !sEntry.isEmpty())
648 {
649 // insert new entry in list-box etc...
651
652 if (nEntry != -1) // entry selected in m_pWordsLB ie action = modify entry
653 {
654 m_pWordsLB->set_text(nEntry, sEntry);
655 if (!aReplaceStr.isEmpty())
656 m_pWordsLB->set_text(nEntry, aReplaceStr, 1);
657 }
658 else
659 {
660 nEntry = GetLBInsertPos(aNewWord);
661 m_pWordsLB->insert_text(nEntry, sEntry);
662 if(!aReplaceStr.isEmpty())
663 m_pWordsLB->set_text(nEntry, aReplaceStr, 1);
664 }
665
666 m_pWordsLB->thaw();
667 m_pWordsLB->scroll_to_row(nEntry);
668
669 // if the request came from the ReplaceEdit, give focus to the ShortEdit
670 if (m_xReplaceED->has_focus())
671 m_xWordED->grab_focus();
672 }
673 }
674 else
675 {
676 // this can only be an enter in one of the two edit fields
677 // which means EndDialog() - has to be evaluated in KeyInput
678 return false;
679 }
680 ModifyHdl(*m_xWordED);
681 return true;
682}
683
685{
686 OUString rEntry = rEdt.get_text();
687
688 sal_Int32 nWordLen = rEntry.getLength();
689 const OUString& rRepString = fixSpace(m_xReplaceED->get_text());
690
691 bool bEnableNewReplace = false;
692 bool bEnableDelete = false;
693 OUString aNewReplaceText = sNew;
694
695 if (&rEdt == m_xWordED.get())
696 {
697 if(nWordLen>0)
698 {
699 bool bFound = false;
700 bool bTmpSelEntry=false;
701 CDE_RESULT eCmpRes = CDE_DIFFERENT;
702
703 bool bDoubleColumn = m_pWordsLB == m_xDoubleColumnLB.get();
704
705 for (int i = 0, nCount = m_pWordsLB->n_children(); i < nCount; ++i)
706 {
707 OUString aTestStr(m_pWordsLB->get_text(i, 0));
708 eCmpRes = cmpDicEntry_Impl( rEntry, aTestStr );
709 if(CDE_DIFFERENT != eCmpRes)
710 {
711 if(!rRepString.isEmpty())
712 bFirstSelect = true;
713 bDoNothing=true;
714 m_pWordsLB->set_cursor(i);
715 bDoNothing=false;
716 if (bDoubleColumn)
717 m_xReplaceED->set_text(m_pWordsLB->get_text(i, 1));
718
719 if (CDE_SIMILAR == eCmpRes)
720 {
721 aNewReplaceText = sModify;
722 bEnableNewReplace = true;
723 }
724 bFound= true;
725 break;
726 }
727 else if(getNormDicEntry_Impl(aTestStr).indexOf(
728 getNormDicEntry_Impl( rEntry ) ) == 0
729 && !bTmpSelEntry)
730 {
731 bDoNothing=true;
732 m_pWordsLB->scroll_to_row(i);
733 bDoNothing=false;
734 bTmpSelEntry=true;
735
736 aNewReplaceText = sNew;
737 bEnableNewReplace = true;
738 }
739 }
740
741 if(!bFound)
742 {
743 m_pWordsLB->unselect_all();
744 aNewReplaceText = sNew;
745 bEnableNewReplace = true;
746 }
747 bEnableDelete = CDE_DIFFERENT != eCmpRes;
748 }
749 else if (m_pWordsLB->n_children() > 0)
750 {
751 bDoNothing=true;
752 m_pWordsLB->scroll_to_row(0);
753 bDoNothing=false;
754 }
755 }
756 else if(&rEdt == m_xReplaceED.get())
757 {
758 OUString aReplaceText;
759 OUString aWordText;
760 int nFirstSel = m_pWordsLB->get_selected_index();
761 if (nFirstSel != -1) // a m_pWordsLB entry is selected
762 {
763 aWordText = m_pWordsLB->get_text(nFirstSel, 0);
764 aReplaceText = m_pWordsLB->get_text(nFirstSel, 1);
765
766 aNewReplaceText = sModify;
767 bEnableDelete = true;
768 }
769 bool bIsChange =
770 CDE_EQUAL != cmpDicEntry_Impl(fixSpace(m_xWordED->get_text()), aWordText)
771 || CDE_EQUAL != cmpDicEntry_Impl(fixSpace(m_xReplaceED->get_text()), aReplaceText);
772 if (!fixSpace(m_xWordED->get_text()).isEmpty() && bIsChange)
773 bEnableNewReplace = true;
774 }
775
776 m_xNewReplacePB->set_label(aNewReplaceText);
777 m_xNewReplacePB->set_sensitive(bEnableNewReplace && !IsDicReadonly_Impl());
778 m_xDeletePB->set_sensitive(bEnableDelete && !IsDicReadonly_Impl());
779}
780
781/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XExecutableDialog > m_xDialog
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
const CollatorWrapper * getCollator() const
LanguageType getLanguageType(bool bResolveSystem=true) const
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
static css::uno::Reference< css::linguistic2::XSearchableDictionaryList > GetDictionaryList()
std::unique_ptr< weld::TreeView > m_xSingleColumnLB
Definition: optdict.hxx:80
void ShowWords_Impl(sal_uInt16 nId)
Definition: optdict.cxx:463
void SetLanguage_Impl(LanguageType nLanguage)
Definition: optdict.cxx:368
int GetLBInsertPos(std::u16string_view rDicWord)
Definition: optdict.cxx:374
virtual ~SvxEditDictionaryDialog() override
Definition: optdict.cxx:347
std::unique_ptr< weld::Label > m_xLangFT
Definition: optdict.hxx:75
css::uno::Sequence< css::uno::Reference< css::linguistic2::XDictionary > > aDics
Definition: optdict.hxx:67
std::unique_ptr< weld::Label > m_xReplaceFT
Definition: optdict.hxx:78
std::unique_ptr< weld::TreeView > m_xDoubleColumnLB
Definition: optdict.hxx:81
void RemoveDictEntry(int nEntry)
Definition: optdict.cxx:392
std::unique_ptr< weld::Button > m_xNewReplacePB
Definition: optdict.hxx:82
SvxEditDictionaryDialog(weld::Window *pParent, std::u16string_view rName)
Definition: optdict.cxx:219
OUString sReplaceFT_Text
Definition: optdict.hxx:63
void SetDicReadonly_Impl(css::uno::Reference< css::linguistic2::XDictionary > const &xDic)
Definition: optdict.cxx:351
bool NewDelHdl(const weld::Widget *)
Definition: optdict.cxx:600
weld::TreeView * m_pWordsLB
Definition: optdict.hxx:73
bool IsDicReadonly_Impl() const
Definition: optdict.hxx:96
std::unique_ptr< weld::Entry > m_xWordED
Definition: optdict.hxx:77
std::unique_ptr< SvxLanguageBox > m_xLangLB
Definition: optdict.hxx:76
std::unique_ptr< weld::ComboBox > m_xAllDictsLB
Definition: optdict.hxx:74
std::unique_ptr< weld::Entry > m_xReplaceED
Definition: optdict.hxx:79
std::unique_ptr< weld::Button > m_xDeletePB
Definition: optdict.hxx:83
std::unique_ptr< SvxLanguageBox > m_xLanguageLB
Definition: optdict.hxx:42
std::unique_ptr< weld::Entry > m_xNameEdit
Definition: optdict.hxx:41
std::unique_ptr< weld::Button > m_xOKBtn
Definition: optdict.hxx:44
SvxNewDictionaryDialog(weld::Window *pParent)
Definition: optdict.cxx:112
std::shared_ptr< weld::Dialog > m_xDialog
virtual void scroll_to_row(int row)=0
virtual void set_text(int row, const OUString &rText, int col=-1)=0
virtual OUString get_text(int row, int col=-1) const=0
void append_text(const OUString &rStr)
virtual int n_children() const=0
virtual void clear()=0
void insert_text(int pos, const OUString &rStr)
virtual void remove(int pos)=0
virtual void select(int pos)=0
virtual void set_cursor(int pos)=0
virtual int get_selected_index() const=0
virtual void freeze()=0
virtual void thaw()=0
OUString CuiResId(TranslateId aKey)
Definition: cuiresmgr.cxx:23
int nCount
#define DBG_ASSERT(sCon, aError)
SVXCORE_DLLPUBLIC std::locale SvxResLocale()
URL aURL
float y
float x
ScXMLEditAttributeMap::Entry const aEntries[]
DocumentType eType
OUString sName
#define LANGUAGE_NONE
sal_uInt16 nPos
aStr
OString stripEnd(const OString &rIn, char c)
int i
OUString GetWritableDictionaryURL(std::u16string_view rDicName)
DictionaryError
DictionaryError AddEntryToDic(uno::Reference< XDictionary > const &rxDic, const OUString &rWord, bool bIsNeg, const OUString &rRplcTxt, bool bStripDot)
sal_Int16 nId
static CDE_RESULT cmpDicEntry_Impl(std::u16string_view rText1, std::u16string_view rText2)
Definition: optdict.cxx:94
static OUString fixSpace(OUString sText)
Definition: optdict.cxx:72
static OUString getNormDicEntry_Impl(std::u16string_view rText)
Definition: optdict.cxx:47
IMPL_LINK(SvxEditDictionaryDialog, SelectHdl, weld::TreeView &, rBox, void)
Definition: optdict.cxx:561
IMPL_LINK_NOARG(SvxNewDictionaryDialog, OKHdl_Impl, weld::Button &, void)
Definition: optdict.cxx:131
SVX_DLLPUBLIC const ErrMsgCode RID_SVXERRCTX[]
#define ERRCTX_SVX_LINGU_DICTIONARY
#define ERRCODE_SVX_LINGU_DICT_NOTWRITEABLE
sal_uInt16 sal_Unicode
short SvxDicError(weld::Window *pParent, linguistic::DictionaryError nError)
RET_OK
RET_CANCEL
RET_YES