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