Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / lingu / olmenu.cxx
blob80e32a4cdb30635138baeb002c0a57fcd48ba06c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <SwRewriter.hxx>
21 #include <cmdid.h>
22 #include <strings.hrc>
23 #include <doc.hxx>
24 #include <edtwin.hxx>
25 #include <helpids.h>
26 #include <langhelper.hxx>
27 #include <bitmaps.hlst>
28 #include <olmenu.hxx>
29 #include <swmodule.hxx>
30 #include <swtypes.hxx>
31 #include <swundo.hxx>
32 #include <utility>
33 #include <view.hxx>
34 #include <wrtsh.hxx>
36 #include <comphelper/lok.hxx>
37 #include <comphelper/anytostring.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <cppuhelper/exc_hlp.hxx>
40 #include <editeng/acorrcfg.hxx>
41 #include <editeng/svxacorr.hxx>
42 #include <editeng/splwrap.hxx>
43 #include <editeng/unolingu.hxx>
44 #include <editeng/editview.hxx>
45 #include <i18nlangtag/languagetag.hxx>
46 #include <linguistic/misc.hxx>
47 #include <rtl/string.hxx>
48 #include <vcl/commandinfoprovider.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/weld.hxx>
51 #include <sfx2/dispatch.hxx>
52 #include <sfx2/request.hxx>
53 #include <sfx2/viewfrm.hxx>
54 #include <svl/itemset.hxx>
55 #include <svl/languageoptions.hxx>
56 #include <svl/stritem.hxx>
57 #include <svtools/langtab.hxx>
58 #include <unotools/lingucfg.hxx>
59 #include <unotools/linguprops.hxx>
60 #include <vcl/settings.hxx>
61 #include <osl/diagnose.h>
63 #include <map>
65 #include <com/sun/star/document/XDocumentLanguages.hpp>
66 #include <com/sun/star/frame/XFrame.hpp>
67 #include <com/sun/star/frame/XStorable.hpp>
68 #include <com/sun/star/lang/XServiceInfo.hpp>
69 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
70 #include <com/sun/star/uno/Any.hxx>
71 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
72 #include <com/sun/star/system/SystemShellExecute.hpp>
73 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
75 using namespace ::com::sun::star;
77 /// @returns : the language for the selected text that is set for the
78 /// specified attribute (script type).
79 /// If there are more than one languages used LANGUAGE_DONTKNOW will be returned.
80 /// @param nLangWhichId : one of
81 /// RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
82 /// @returns: the language in use for the selected text.
83 /// 'In use' means the language(s) matching the script type(s) of the
84 /// selected text. Or in other words, the language a spell checker would use.
85 /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
86 // check if nScriptType includes the script type associated to nLang
87 static bool lcl_checkScriptType( SvtScriptType nScriptType, LanguageType nLang )
89 return bool(nScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ));
92 void SwSpellPopup::fillLangPopupMenu(
93 PopupMenu *pPopupMenu,
94 sal_uInt16 nLangItemIdStart,
95 const uno::Sequence< OUString >& aSeq,
96 SwWrtShell* pWrtSh,
97 std::map< sal_Int16, OUString > &rLangTable )
99 if (!pPopupMenu)
100 return;
102 // set of languages to be displayed in the sub menus
103 std::set< OUString > aLangItems;
105 OUString aCurLang( aSeq[0] );
106 SvtScriptType nScriptType = static_cast<SvtScriptType>(aSeq[1].toInt32());
107 OUString aKeyboardLang( aSeq[2] );
108 OUString aGuessedTextLang( aSeq[3] );
110 if (!aCurLang.isEmpty() &&
111 LANGUAGE_DONTKNOW != SvtLanguageTable::GetLanguageType( aCurLang ))
112 aLangItems.insert( aCurLang );
114 //2--System
115 const AllSettings& rAllSettings = Application::GetSettings();
116 LanguageType rSystemLanguage = rAllSettings.GetLanguageTag().getLanguageType();
117 if (rSystemLanguage != LANGUAGE_DONTKNOW)
119 if (lcl_checkScriptType( nScriptType, rSystemLanguage ))
120 aLangItems.insert( SvtLanguageTable::GetLanguageString(rSystemLanguage) );
123 //3--UI
124 LanguageType rUILanguage = rAllSettings.GetUILanguageTag().getLanguageType();
125 if (rUILanguage != LANGUAGE_DONTKNOW)
127 if (lcl_checkScriptType(nScriptType, rUILanguage ))
128 aLangItems.insert( SvtLanguageTable::GetLanguageString(rUILanguage) );
131 //4--guessed language
132 if (!aGuessedTextLang.isEmpty())
134 if (lcl_checkScriptType(nScriptType, SvtLanguageTable::GetLanguageType(aGuessedTextLang)))
135 aLangItems.insert( aGuessedTextLang );
138 //5--keyboard language
139 if (!aKeyboardLang.isEmpty())
141 if (lcl_checkScriptType(nScriptType, SvtLanguageTable::GetLanguageType(aKeyboardLang)))
142 aLangItems.insert( aKeyboardLang );
145 //6--all languages used in current document
146 uno::Reference< css::frame::XModel > xModel;
147 uno::Reference< css::frame::XController > xController = pWrtSh->GetView().GetViewFrame().GetFrame().GetFrameInterface()->getController();
148 if ( xController.is() )
149 xModel = xController->getModel();
150 uno::Reference< document::XDocumentLanguages > xDocumentLanguages( xModel, uno::UNO_QUERY );
151 /*the description of nScriptType flags
152 LATIN : 0x0001
153 ASIAN : 0x0002
154 COMPLEX: 0x0004
156 const sal_Int16 nMaxCount = 7;
157 if (xDocumentLanguages.is())
159 const uno::Sequence< lang::Locale > rLocales( xDocumentLanguages->getDocumentLanguages( static_cast<sal_Int16>(nScriptType), nMaxCount ) );
160 for (const lang::Locale& rLocale : rLocales)
162 if (aLangItems.size() == size_t(nMaxCount))
163 break;
164 if (lcl_checkScriptType( nScriptType, SvtLanguageTable::GetLanguageType( rLocale.Language )))
165 aLangItems.insert( rLocale.Language );
169 sal_uInt16 nItemId = nLangItemIdStart;
170 for (const OUString& aEntryText : aLangItems)
172 if (aEntryText != SvtLanguageTable::GetLanguageString( LANGUAGE_NONE ) &&
173 aEntryText != "*" && // multiple languages in current selection
174 !aEntryText.isEmpty()) // 'no language found' from language guessing
176 OSL_ENSURE( nLangItemIdStart <= nItemId && nItemId <= nLangItemIdStart + MN_MAX_NUM_LANG,
177 "nItemId outside of expected range!" );
178 pPopupMenu->InsertItem( nItemId, aEntryText, MenuItemBits::RADIOCHECK );
179 if (aEntryText == aCurLang)
181 //make a check mark for the current language
182 pPopupMenu->CheckItem( nItemId );
184 rLangTable[ nItemId ] = aEntryText;
185 ++nItemId;
189 pPopupMenu->InsertItem( nLangItemIdStart + MN_NONE_OFFSET, SwResId( STR_LANGSTATUS_NONE ), MenuItemBits::RADIOCHECK );
190 if ( SvtLanguageTable::GetLanguageString( LANGUAGE_NONE ) == aCurLang )
191 pPopupMenu->CheckItem( nLangItemIdStart + MN_NONE_OFFSET );
193 pPopupMenu->InsertItem( nLangItemIdStart + MN_RESET_OFFSET, SwResId( STR_RESET_TO_DEFAULT_LANGUAGE ) );
194 pPopupMenu->InsertItem( nLangItemIdStart + MN_MORE_OFFSET, SwResId( STR_LANGSTATUS_MORE ) );
197 SwSpellPopup::SwSpellPopup(
198 SwWrtShell* pWrtSh,
199 uno::Reference< linguistic2::XSpellAlternatives > xAlt,
200 const OUString &rParaText)
201 : m_aBuilder(nullptr, AllSettings::GetUIRootDir(), "modules/swriter/ui/spellmenu.ui", "")
202 , m_xPopupMenu(m_aBuilder.get_menu(u"menu"))
203 , m_nIgnoreWordId(m_xPopupMenu->GetItemId(u"ignoreall"))
204 , m_nAddMenuId(m_xPopupMenu->GetItemId(u"addmenu"))
205 , m_nAddId(m_xPopupMenu->GetItemId(u"add"))
206 , m_nSpellDialogId(m_xPopupMenu->GetItemId(u"spelldialog"))
207 , m_nCorrectMenuId(m_xPopupMenu->GetItemId(u"correctmenu"))
208 , m_nCorrectDialogId(m_xPopupMenu->GetItemId(u"correctdialog"))
209 , m_nLangSelectionMenuId(m_xPopupMenu->GetItemId(u"langselection"))
210 , m_nLangParaMenuId(m_xPopupMenu->GetItemId(u"langpara"))
211 , m_nRedlineAcceptId(m_xPopupMenu->GetItemId(u"accept"))
212 , m_nRedlineRejectId(m_xPopupMenu->GetItemId(u"reject"))
213 , m_nRedlineNextId(m_xPopupMenu->GetItemId(u"next"))
214 , m_nRedlinePrevId(m_xPopupMenu->GetItemId(u"prev"))
215 , m_pSh( pWrtSh )
216 , m_xSpellAlt(std::move(xAlt))
217 , m_bGrammarResults(false)
219 OSL_ENSURE(m_xSpellAlt.is(), "no spelling alternatives available");
221 m_xPopupMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
222 bool bUseImagesInMenus = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
224 m_nCheckedLanguage = LANGUAGE_NONE;
225 css::uno::Sequence< OUString > aSuggestions;
226 if (m_xSpellAlt.is())
228 m_nCheckedLanguage = LanguageTag( m_xSpellAlt->getLocale() ).getLanguageType();
229 aSuggestions = m_xSpellAlt->getAlternatives();
231 sal_Int16 nStringCount = static_cast< sal_Int16 >( aSuggestions.getLength() );
233 SvtLinguConfig aCfg;
235 PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nCorrectMenuId);
236 pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
237 bool bEnable = false;
238 if( nStringCount )
240 Image aImage;
241 OUString aSuggestionImageUrl;
243 if (bUseImagesInMenus)
245 uno::Reference< container::XNamed > xNamed( m_xSpellAlt, uno::UNO_QUERY );
246 if (xNamed.is())
248 aSuggestionImageUrl = aCfg.GetSpellAndGrammarContextSuggestionImage( xNamed->getName() );
249 aImage = Image( aSuggestionImageUrl );
253 m_xPopupMenu->InsertSeparator({}, 0);
254 bEnable = true;
255 sal_uInt16 nAutoCorrItemId = MN_AUTOCORR_START;
256 sal_uInt16 nItemId = MN_SUGGESTION_START;
257 for (sal_uInt16 i = 0; i < nStringCount; ++i)
259 const OUString aEntry = aSuggestions[ i ];
260 m_xPopupMenu->InsertItem(nItemId, aEntry, MenuItemBits::NONE, {}, i);
261 m_xPopupMenu->SetHelpId(nItemId, HID_LINGU_REPLACE);
262 if (!aSuggestionImageUrl.isEmpty())
263 m_xPopupMenu->SetItemImage(nItemId, aImage);
265 pMenu->InsertItem( nAutoCorrItemId, aEntry );
266 pMenu->SetHelpId( nAutoCorrItemId, HID_LINGU_AUTOCORR);
268 ++nAutoCorrItemId;
269 ++nItemId;
273 uno::Reference< frame::XFrame > xFrame = pWrtSh->GetView().GetViewFrame().GetFrame().GetFrameInterface();
274 OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
277 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:SpellingAndGrammarDialog", aModuleName);
278 m_xPopupMenu->SetItemText(m_nSpellDialogId,
279 vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties));
282 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:AutoCorrectDlg", aModuleName);
283 m_xPopupMenu->SetItemText(m_nCorrectDialogId,
284 vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties));
287 sal_uInt16 nItemPos = m_xPopupMenu->GetItemPos(m_nIgnoreWordId);
288 OUString aIgnoreSelection( SwResId( STR_IGNORE_SELECTION ) );
289 m_xPopupMenu->InsertItem(MN_IGNORE_SELECTION, aIgnoreSelection, MenuItemBits::NONE, {}, nItemPos);
290 m_xPopupMenu->SetHelpId(MN_IGNORE_SELECTION, HID_LINGU_IGNORE_SELECTION);
292 m_xPopupMenu->EnableItem(m_nCorrectMenuId, bEnable);
294 uno::Reference< linguistic2::XLanguageGuessing > xLG = SW_MOD()->GetLanguageGuesser();
295 LanguageType nGuessLangWord = LANGUAGE_NONE;
296 LanguageType nGuessLangPara = LANGUAGE_NONE;
297 if (m_xSpellAlt.is() && xLG.is())
299 nGuessLangWord = EditView::CheckLanguage( m_xSpellAlt->getWord(), ::GetSpellChecker(), xLG, false );
300 nGuessLangPara = EditView::CheckLanguage( rParaText, ::GetSpellChecker(), xLG, true );
302 if (nGuessLangWord != LANGUAGE_NONE || nGuessLangPara != LANGUAGE_NONE)
304 // make sure LANGUAGE_NONE gets not used as menu entry
305 if (nGuessLangWord == LANGUAGE_NONE)
306 nGuessLangWord = nGuessLangPara;
307 if (nGuessLangPara == LANGUAGE_NONE)
308 nGuessLangPara = nGuessLangWord;
311 pMenu = m_xPopupMenu->GetPopupMenu(m_nAddMenuId);
312 pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics); //! necessary to retrieve the correct dictionary name in 'Execute' below
313 uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
314 sal_uInt16 nItemId = MN_DICTIONARIES_START;
315 if (xDicList.is())
317 // add the default positive dictionary to dic-list (if not already done).
318 // This is to ensure that there is at least one dictionary to which
319 // words could be added.
320 uno::Reference< linguistic2::XDictionary > xDic( LinguMgr::GetStandardDic() );
321 if (xDic.is())
322 xDic->setActive( true );
324 m_aDics = xDicList->getDictionaries();
326 for( const uno::Reference< linguistic2::XDictionary >& rDic : std::as_const(m_aDics) )
328 uno::Reference< linguistic2::XDictionary > xDicTmp = rDic;
329 if (!xDicTmp.is() || LinguMgr::GetIgnoreAllList() == xDicTmp)
330 continue;
332 uno::Reference< frame::XStorable > xStor( xDicTmp, uno::UNO_QUERY );
333 LanguageType nActLanguage = LanguageTag( xDicTmp->getLocale() ).getLanguageType();
334 if( xDicTmp->isActive()
335 && xDicTmp->getDictionaryType() != linguistic2::DictionaryType_NEGATIVE
336 && (m_nCheckedLanguage == nActLanguage || LANGUAGE_NONE == nActLanguage )
337 && (!xStor.is() || !xStor->isReadonly()) )
339 // the extra 1 is because of the (possible) external
340 // linguistic entry above
341 pMenu->InsertItem( nItemId, xDicTmp->getName() );
342 m_aDicNameSingle = xDicTmp->getName();
344 if (bUseImagesInMenus)
346 uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY );
347 if (xSvcInfo.is())
349 OUString aDictionaryImageUrl( aCfg.GetSpellAndGrammarContextDictionaryImage(
350 xSvcInfo->getImplementationName() ) );
351 if (!aDictionaryImageUrl.isEmpty())
353 Image aImage( aDictionaryImageUrl );
354 pMenu->SetItemImage( nItemId, aImage );
359 ++nItemId;
363 m_xPopupMenu->EnableItem(m_nAddMenuId, (nItemId - MN_DICTIONARIES_START) > 1);
364 m_xPopupMenu->EnableItem(m_nAddId, (nItemId - MN_DICTIONARIES_START) == 1);
366 //ADD NEW LANGUAGE MENU ITEM
368 OUString aScriptTypesInUse( OUString::number( static_cast<int>(pWrtSh->GetScriptType()) ) );
370 // get keyboard language
371 OUString aKeyboardLang;
372 SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
373 LanguageType nLang = rEditWin.GetInputLanguage();
374 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
375 aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
377 // get the language that is in use
378 OUString aCurrentLang("*");
379 nLang = SwLangHelper::GetCurrentLanguage( *pWrtSh );
380 if (nLang != LANGUAGE_DONTKNOW)
381 aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
383 // build sequence for status value
384 uno::Sequence< OUString > aSeq{ aCurrentLang,
385 aScriptTypesInUse,
386 aKeyboardLang,
387 SvtLanguageTable::GetLanguageString(nGuessLangWord) };
389 pMenu = m_xPopupMenu->GetPopupMenu(m_nLangSelectionMenuId);
390 fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_SELECTION_START, aSeq, pWrtSh, m_aLangTable_Text );
391 m_xPopupMenu->EnableItem(m_nLangSelectionMenuId);
393 pMenu = m_xPopupMenu->GetPopupMenu(m_nLangParaMenuId);
394 fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_PARAGRAPH_START, aSeq, pWrtSh, m_aLangTable_Paragraph );
395 m_xPopupMenu->EnableItem(m_nLangParaMenuId);
397 if (bUseImagesInMenus)
398 m_xPopupMenu->SetItemImage(m_nSpellDialogId,
399 vcl::CommandInfoProvider::GetImageForCommand(".uno:SpellingAndGrammarDialog", xFrame));
401 checkRedline();
402 m_xPopupMenu->RemoveDisabledEntries( true );
404 InitItemCommands(aSuggestions);
407 SwSpellPopup::SwSpellPopup(
408 SwWrtShell *pWrtSh,
409 const linguistic2::ProofreadingResult &rResult,
410 sal_Int32 nErrorInResult,
411 const uno::Sequence< OUString > &rSuggestions,
412 const OUString &rParaText )
413 : m_aBuilder(nullptr, AllSettings::GetUIRootDir(), "modules/swriter/ui/spellmenu.ui", "")
414 , m_xPopupMenu(m_aBuilder.get_menu(u"menu"))
415 , m_nIgnoreWordId(m_xPopupMenu->GetItemId(u"ignoreall"))
416 , m_nAddMenuId(m_xPopupMenu->GetItemId(u"addmenu"))
417 , m_nAddId(m_xPopupMenu->GetItemId(u"add"))
418 , m_nSpellDialogId(m_xPopupMenu->GetItemId(u"spelldialog"))
419 , m_nCorrectMenuId(m_xPopupMenu->GetItemId(u"correctmenu"))
420 , m_nCorrectDialogId(m_xPopupMenu->GetItemId(u"correctdialog"))
421 , m_nLangSelectionMenuId(m_xPopupMenu->GetItemId(u"langselection"))
422 , m_nLangParaMenuId(m_xPopupMenu->GetItemId(u"langpara"))
423 , m_nRedlineAcceptId(m_xPopupMenu->GetItemId(u"accept"))
424 , m_nRedlineRejectId(m_xPopupMenu->GetItemId(u"reject"))
425 , m_nRedlineNextId(m_xPopupMenu->GetItemId(u"next"))
426 , m_nRedlinePrevId(m_xPopupMenu->GetItemId(u"prev"))
427 , m_pSh(pWrtSh)
428 , m_bGrammarResults(true)
430 m_nCheckedLanguage = LanguageTag::convertToLanguageType( rResult.aLocale );
431 bool bUseImagesInMenus = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
433 sal_uInt16 nPos = 0;
434 OUString aMessageText( rResult.aErrors[ nErrorInResult ].aShortComment );
435 m_xPopupMenu->InsertSeparator({}, nPos++);
436 m_xPopupMenu->InsertItem(MN_SHORT_COMMENT, aMessageText, MenuItemBits::NOSELECT, {}, nPos++);
437 if (bUseImagesInMenus)
438 m_xPopupMenu->SetItemImage(MN_SHORT_COMMENT, Image(StockImage::Yes, BMP_INFO_16));
440 // Add an item to show detailed infos if the FullCommentURL property is defined
441 const beans::PropertyValues aProperties = rResult.aErrors[ nErrorInResult ].aProperties;
442 for ( const auto& rProp : aProperties )
444 if ( rProp.Name == "FullCommentURL" )
446 uno::Any aValue = rProp.Value;
447 aValue >>= m_sExplanationLink;
449 if ( !m_sExplanationLink.isEmpty( ) )
450 break;
454 if ( !m_sExplanationLink.isEmpty( ) )
456 m_xPopupMenu->InsertItem(MN_EXPLANATION_LINK, SwResId(STR_EXPLANATION_LINK), MenuItemBits::TEXT | MenuItemBits::HELP, {}, nPos++);
459 m_xPopupMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics);
461 m_xPopupMenu->InsertSeparator({}, nPos++);
462 if ( rSuggestions.hasElements() ) // suggestions available...
464 Image aImage;
465 OUString aSuggestionImageUrl;
467 if (bUseImagesInMenus)
469 uno::Reference< lang::XServiceInfo > xInfo( rResult.xProofreader, uno::UNO_QUERY );
470 if (xInfo.is())
472 aSuggestionImageUrl = SvtLinguConfig().GetSpellAndGrammarContextSuggestionImage( xInfo->getImplementationName() );
473 aImage = Image( aSuggestionImageUrl );
477 sal_uInt16 nItemId = MN_SUGGESTION_START;
478 for (const OUString& aEntry : std::as_const(rSuggestions))
480 m_xPopupMenu->InsertItem(nItemId, aEntry, MenuItemBits::NONE, {}, nPos++);
481 m_xPopupMenu->SetHelpId(nItemId, HID_LINGU_REPLACE);
482 if (!aSuggestionImageUrl.isEmpty())
483 m_xPopupMenu->SetItemImage(nItemId, aImage);
485 ++nItemId;
487 m_xPopupMenu->InsertSeparator({}, nPos++);
490 uno::Reference< frame::XFrame > xFrame = pWrtSh->GetView().GetViewFrame().GetFrame().GetFrameInterface();
491 OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
493 OUString aIgnoreSelection( SwResId( STR_IGNORE_SELECTION ) );
494 auto aCommandProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:SpellingAndGrammarDialog", aModuleName);
495 m_xPopupMenu->SetItemText(m_nSpellDialogId,
496 vcl::CommandInfoProvider::GetPopupLabelForCommand(aCommandProperties));
497 sal_uInt16 nItemPos = m_xPopupMenu->GetItemPos(m_nIgnoreWordId);
498 m_xPopupMenu->InsertItem(MN_IGNORE_SELECTION, aIgnoreSelection, MenuItemBits::NONE, {}, nItemPos);
499 m_xPopupMenu->SetHelpId(MN_IGNORE_SELECTION, HID_LINGU_IGNORE_SELECTION);
501 m_xPopupMenu->EnableItem(m_nCorrectMenuId, false);
502 m_xPopupMenu->EnableItem(m_nCorrectDialogId, false);
504 uno::Reference< linguistic2::XLanguageGuessing > xLG = SW_MOD()->GetLanguageGuesser();
505 LanguageType nGuessLangWord = LANGUAGE_NONE;
506 LanguageType nGuessLangPara = LANGUAGE_NONE;
507 if (xLG.is())
509 nGuessLangPara = EditView::CheckLanguage( rParaText, ::GetSpellChecker(), xLG, true );
511 if (nGuessLangWord != LANGUAGE_NONE || nGuessLangPara != LANGUAGE_NONE)
513 // make sure LANGUAGE_NONE gets not used as menu entry
514 if (nGuessLangWord == LANGUAGE_NONE)
515 nGuessLangWord = nGuessLangPara;
516 if (nGuessLangPara == LANGUAGE_NONE)
517 nGuessLangPara = nGuessLangWord;
520 m_xPopupMenu->EnableItem(m_nAddMenuId, false);
521 m_xPopupMenu->EnableItem(m_nAddId, false);
523 //ADD NEW LANGUAGE MENU ITEM
525 OUString aScriptTypesInUse( OUString::number( static_cast<int>(pWrtSh->GetScriptType()) ) );
527 // get keyboard language
528 OUString aKeyboardLang;
529 SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
530 LanguageType nLang = rEditWin.GetInputLanguage();
531 if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
532 aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
534 // get the language that is in use
535 OUString aCurrentLang("*");
536 nLang = SwLangHelper::GetCurrentLanguage( *pWrtSh );
537 if (nLang != LANGUAGE_DONTKNOW)
538 aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
540 // build sequence for status value
541 uno::Sequence< OUString > aSeq{ aCurrentLang,
542 aScriptTypesInUse,
543 aKeyboardLang,
544 SvtLanguageTable::GetLanguageString(nGuessLangWord) };
546 PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nLangSelectionMenuId);
547 fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_SELECTION_START, aSeq, pWrtSh, m_aLangTable_Text );
548 m_xPopupMenu->EnableItem(m_nLangSelectionMenuId);
550 pMenu = m_xPopupMenu->GetPopupMenu(m_nLangParaMenuId);
551 fillLangPopupMenu( pMenu, MN_SET_LANGUAGE_PARAGRAPH_START, aSeq, pWrtSh, m_aLangTable_Paragraph );
552 m_xPopupMenu->EnableItem(m_nLangParaMenuId);
554 if (bUseImagesInMenus)
555 m_xPopupMenu->SetItemImage(m_nSpellDialogId,
556 vcl::CommandInfoProvider::GetImageForCommand(".uno:SpellingAndGrammarDialog", xFrame));
558 checkRedline();
559 m_xPopupMenu->RemoveDisabledEntries(true);
561 SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE, uno::Any( true ));
563 InitItemCommands(rSuggestions);
566 SwSpellPopup::~SwSpellPopup() {}
568 void SwSpellPopup::InitItemCommands(const css::uno::Sequence< OUString >& aSuggestions)
570 if (!comphelper::LibreOfficeKit::isActive())
571 return;
573 // None is added only for LOK, it means there is no need to execute anything
574 m_xPopupMenu->SetItemCommand(MN_SHORT_COMMENT, ".uno:None");
575 m_xPopupMenu->SetItemCommand(m_nSpellDialogId, ".uno:SpellingAndGrammarDialog");
576 if(m_bGrammarResults)
577 m_xPopupMenu->SetItemCommand(m_nIgnoreWordId, ".uno:SpellCheckIgnoreAll?Type:string=Grammar");
578 else
579 m_xPopupMenu->SetItemCommand(m_nIgnoreWordId, ".uno:SpellCheckIgnoreAll?Type:string=Spelling");
580 if(m_bGrammarResults)
581 m_xPopupMenu->SetItemCommand(MN_IGNORE_SELECTION, ".uno:SpellCheckIgnore?Type:string=Grammar");
582 else
583 m_xPopupMenu->SetItemCommand(MN_IGNORE_SELECTION, ".uno:SpellCheckIgnore?Type:string=Spelling");
585 for(int i = 0; i < aSuggestions.getLength(); ++i)
587 sal_uInt16 nItemId = MN_SUGGESTION_START + i;
588 OUString sCommandString = ".uno:SpellCheckApplySuggestion?ApplyRule:string=";
589 if(m_bGrammarResults)
590 sCommandString += "Grammar_";
591 else if (m_xSpellAlt.is())
592 sCommandString += "Spelling_";
593 sCommandString += m_xPopupMenu->GetItemText(nItemId);
594 m_xPopupMenu->SetItemCommand(nItemId, sCommandString);
597 PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nLangSelectionMenuId);
598 m_xPopupMenu->SetItemCommand(m_nLangSelectionMenuId, ".uno:SetSelectionLanguageMenu");
599 if(pMenu)
601 for (const auto& item : m_aLangTable_Text)
603 OUString sCommandString = ".uno:LanguageStatus?Language:string=Current_" + item.second;
604 pMenu->SetItemCommand(item.first, sCommandString);
607 pMenu->SetItemCommand(MN_SET_SELECTION_NONE, ".uno:LanguageStatus?Language:string=Current_LANGUAGE_NONE");
608 pMenu->SetItemCommand(MN_SET_SELECTION_RESET, ".uno:LanguageStatus?Language:string=Current_RESET_LANGUAGES");
609 pMenu->SetItemCommand(MN_SET_SELECTION_MORE, ".uno:FontDialog?Page:string=font");
612 pMenu = m_xPopupMenu->GetPopupMenu(m_nLangParaMenuId);
613 m_xPopupMenu->SetItemCommand(m_nLangParaMenuId, ".uno:SetParagraphLanguageMenu");
614 if(pMenu)
616 for (const auto& item : m_aLangTable_Paragraph)
618 OUString sCommandString = ".uno:LanguageStatus?Language:string=Paragraph_" + item.second;
619 pMenu->SetItemCommand(item.first, sCommandString);
622 pMenu->SetItemCommand(MN_SET_PARA_NONE, ".uno:LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE");
623 pMenu->SetItemCommand(MN_SET_PARA_RESET, ".uno:LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES");
624 pMenu->SetItemCommand(MN_SET_PARA_MORE, ".uno:FontDialogForParagraph");
628 void SwSpellPopup::checkRedline()
630 // Let SwView::GetState() already has the logic on when to disable the
631 // accept/reject and the next/prev change items, let it do the decision.
633 // Build an item set that contains a void item for each menu entry. The
634 // WhichId of each item is set, so SwView may clear it.
635 static const sal_uInt16 pRedlineIds[] = {
636 FN_REDLINE_ACCEPT_DIRECT,
637 FN_REDLINE_REJECT_DIRECT,
638 FN_REDLINE_NEXT_CHANGE,
639 FN_REDLINE_PREV_CHANGE
641 SwDoc *pDoc = m_pSh->GetDoc();
642 SfxItemSetFixed<FN_REDLINE_ACCEPT_DIRECT, FN_REDLINE_PREV_CHANGE> aSet(pDoc->GetAttrPool());
643 for (sal_uInt16 nWhich : pRedlineIds)
645 aSet.Put(SfxVoidItem(nWhich));
647 m_pSh->GetView().GetState(aSet);
649 // Enable/disable items based on if the which id of the void items are
650 // cleared or not.
651 for (sal_uInt16 nWhich : pRedlineIds)
653 sal_uInt16 nId(0);
654 if (nWhich == FN_REDLINE_ACCEPT_DIRECT)
655 nId = m_nRedlineAcceptId;
656 else if (nWhich == FN_REDLINE_REJECT_DIRECT)
657 nId = m_nRedlineRejectId;
658 else if (nWhich == FN_REDLINE_NEXT_CHANGE)
659 nId = m_nRedlineNextId;
660 else if (nWhich == FN_REDLINE_PREV_CHANGE)
661 nId = m_nRedlinePrevId;
662 m_xPopupMenu->EnableItem(nId, aSet.Get(nWhich).Which() != 0);
666 void SwSpellPopup::Execute( const tools::Rectangle& rWordPos, vcl::Window* pWin )
668 sal_uInt16 nRet = m_xPopupMenu->Execute(pWin, pWin->LogicToPixel(rWordPos));
669 Execute( nRet );
672 void SwSpellPopup::Execute( sal_uInt16 nId )
674 if (nId == USHRT_MAX)
675 return;
677 if (/*m_bGrammarResults && */nId == MN_SHORT_COMMENT)
678 return; // nothing to do since it is the error message (short comment)
680 if (MN_SUGGESTION_START <= nId && nId <= MN_SUGGESTION_END)
682 OUString sApplyRule("");
683 if(m_bGrammarResults)
684 sApplyRule += "Grammar_";
685 else if (m_xSpellAlt.is())
686 sApplyRule += "Spelling_";
687 sApplyRule += m_xPopupMenu->GetItemText(nId);
689 SfxStringItem aApplyItem(FN_PARAM_1, sApplyRule);
690 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_SPELLCHECK_APPLY_SUGGESTION, SfxCallMode::SYNCHRON, { &aApplyItem });
692 else if(MN_AUTOCORR_START <= nId && nId <= MN_AUTOCORR_END)
694 if (m_xSpellAlt.is())
696 bool bOldIns = m_pSh->IsInsMode();
697 m_pSh->SetInsMode();
699 PopupMenu* pMenu = m_xPopupMenu->GetPopupMenu(m_nCorrectMenuId);
700 assert(pMenu);
701 OUString aTmp( pMenu->GetItemText(nId) );
702 OUString aOrig( m_xSpellAlt->getWord() );
704 // if original word has a trailing . (likely the end of a sentence)
705 // and the replacement text hasn't, then add it to the replacement
706 if (!aTmp.isEmpty() && !aOrig.isEmpty() &&
707 aOrig.endsWith(".") && /* !IsAlphaNumeric ??*/
708 !aTmp.endsWith("."))
710 aTmp += ".";
713 SwRewriter aRewriter;
715 aRewriter.AddRule(UndoArg1, m_pSh->GetCursorDescr());
716 aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
718 OUString aTmpStr = SwResId(STR_START_QUOTE) +
719 aTmp + SwResId(STR_END_QUOTE);
720 aRewriter.AddRule(UndoArg3, aTmpStr);
722 m_pSh->StartUndo(SwUndoId::UI_REPLACE, &aRewriter);
723 m_pSh->StartAction();
725 m_pSh->Replace(aTmp, false);
727 /* #102505# EndAction/EndUndo moved down since insertion
728 of temporary auto correction is now undoable two and
729 must reside in the same undo group.*/
731 // record only if it's NOT already present in autocorrection
732 SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
734 OUString aOrigWord( m_xSpellAlt->getWord() ) ;
735 OUString aNewWord( pMenu->GetItemText(nId) );
736 SvxPrepareAutoCorrect( aOrigWord, aNewWord );
738 pACorr->PutText( aOrigWord, aNewWord, m_nCheckedLanguage );
740 /* #102505# EndAction/EndUndo moved down since insertion
741 of temporary auto correction is now undoable two and
742 must reside in the same undo group.*/
743 m_pSh->EndAction();
744 m_pSh->EndUndo();
746 m_pSh->SetInsMode( bOldIns );
749 else if (nId == m_nSpellDialogId)
751 m_pSh->Left(SwCursorSkipMode::Chars, false, 1, false );
753 m_pSh->GetView().GetViewFrame().GetDispatcher()->
754 Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON );
757 else if (nId == m_nCorrectDialogId)
759 m_pSh->GetView().GetViewFrame().GetDispatcher()->Execute( SID_AUTO_CORRECT_DLG, SfxCallMode::ASYNCHRON );
761 else if (nId == MN_IGNORE_SELECTION)
763 SfxStringItem aIgnoreString(FN_PARAM_1, m_bGrammarResults ? OUString("Grammar") : OUString("Spelling"));
764 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_SPELLCHECK_IGNORE, SfxCallMode::SYNCHRON, { &aIgnoreString });
766 else if (nId == m_nIgnoreWordId)
768 SfxStringItem aIgnoreString(FN_PARAM_1, m_bGrammarResults ? OUString("Grammar") : OUString("Spelling"));
769 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_SPELLCHECK_IGNORE_ALL, SfxCallMode::SYNCHRON, { &aIgnoreString });
771 else if ((MN_DICTIONARIES_START <= nId && nId <= MN_DICTIONARIES_END) || nId == m_nAddId)
773 OUString sWord( m_xSpellAlt->getWord() );
774 OUString aDicName;
776 if (MN_DICTIONARIES_START <= nId && nId <= MN_DICTIONARIES_END)
778 PopupMenu *pMenu = m_xPopupMenu->GetPopupMenu(m_nAddMenuId);
779 aDicName = pMenu->GetItemText(nId);
781 else
782 aDicName = m_aDicNameSingle;
784 uno::Reference< linguistic2::XDictionary > xDic;
785 uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
786 if (xDicList.is())
787 xDic = xDicList->getDictionaryByName( aDicName );
789 if (xDic.is())
791 linguistic::DictionaryError nAddRes = linguistic::AddEntryToDic(xDic, sWord, false, OUString());
792 // save modified user-dictionary if it is persistent
793 uno::Reference< frame::XStorable > xSavDic( xDic, uno::UNO_QUERY );
794 if (xSavDic.is())
795 xSavDic->store();
797 if (linguistic::DictionaryError::NONE != nAddRes && !xDic->getEntry(sWord).is())
799 SvxDicError(m_pSh->GetView().GetFrameWeld(), nAddRes);
803 else if ( nId == MN_EXPLANATION_LINK && !m_sExplanationLink.isEmpty() )
807 uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute(
808 css::system::SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
809 xSystemShellExecute->execute( m_sExplanationLink, OUString(),
810 css::system::SystemShellExecuteFlags::URIS_ONLY );
812 catch (const uno::Exception&)
814 uno::Any exc( ::cppu::getCaughtException() );
815 OUString msg( ::comphelper::anyToString( exc ) );
816 const SolarMutexGuard guard;
817 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_pSh->GetView().GetFrameWeld(),
818 VclMessageType::Warning, VclButtonsType::Ok, msg));
819 xBox->set_title("Explanations");
820 xBox->run();
823 else if (nId == m_nRedlineAcceptId || nId == m_nRedlineRejectId
824 || nId == m_nRedlineNextId || nId == m_nRedlinePrevId)
826 if (nId == m_nRedlineAcceptId)
827 nId = FN_REDLINE_ACCEPT_DIRECT;
828 else if (nId == m_nRedlineRejectId)
829 nId = FN_REDLINE_REJECT_DIRECT;
830 else if (nId == m_nRedlineNextId)
831 nId = FN_REDLINE_NEXT_CHANGE;
832 else if (nId == m_nRedlinePrevId)
833 nId = FN_REDLINE_PREV_CHANGE;
834 // Let SwView::Execute() handle the redline actions.
835 SfxRequest aReq(m_pSh->GetView().GetViewFrame(), nId);
836 m_pSh->GetView().Execute(aReq);
838 else
840 if (MN_SET_LANGUAGE_SELECTION_START <= nId && nId <= MN_SET_LANGUAGE_SELECTION_END)
842 SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Current_" + m_aLangTable_Text[nId]);
843 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
845 else if (nId == MN_SET_SELECTION_NONE)
847 SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Current_LANGUAGE_NONE");
848 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
850 else if (nId == MN_SET_SELECTION_RESET)
852 SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Current_RESET_LANGUAGES");
853 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
855 else if (nId == MN_SET_SELECTION_MORE)
857 SfxStringItem aDlgString(FN_PARAM_1, "font");
858 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_CHAR_DLG, SfxCallMode::SYNCHRON, { &aDlgString });
860 else if (MN_SET_LANGUAGE_PARAGRAPH_START <= nId && nId <= MN_SET_LANGUAGE_PARAGRAPH_END)
862 SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Paragraph_" + m_aLangTable_Paragraph[nId]);
863 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
865 else if (nId == MN_SET_PARA_NONE)
867 SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Paragraph_LANGUAGE_NONE");
868 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
870 else if (nId == MN_SET_PARA_RESET)
872 SfxStringItem aLangString(SID_LANGUAGE_STATUS, "Paragraph_RESET_LANGUAGES");
873 m_pSh->GetView().GetViewFrame().GetDispatcher()->ExecuteList(SID_LANGUAGE_STATUS, SfxCallMode::SYNCHRON, { &aLangString });
875 else if (nId == MN_SET_PARA_MORE)
877 m_pSh->GetView().GetViewFrame().GetDispatcher()->Execute( SID_CHAR_DLG_FOR_PARAGRAPH );
881 m_pSh->EnterStdMode();
884 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */