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