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