tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / optdlg / tpformula.cxx
blob877ca4381cb1db0b5ace62de1818b7c3de8562af
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 #undef SC_DLLIMPLEMENTATION
22 #include <global.hxx>
23 #include <tpformula.hxx>
24 #include <formulaopt.hxx>
25 #include <sc.hrc>
26 #include <strings.hrc>
27 #include <scresid.hxx>
28 #include <formula/grammar.hxx>
29 #include <officecfg/Office/Calc.hxx>
30 #include "calcoptionsdlg.hxx"
32 #include <unotools/localedatawrapper.hxx>
34 ScTpFormulaOptions::ScTpFormulaOptions(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreAttrs)
35 : SfxTabPage(pPage, pController, u"modules/scalc/ui/optformula.ui"_ustr, u"OptFormula"_ustr, &rCoreAttrs)
36 , mnDecSep(0)
37 , mxLbFormulaSyntax(m_xBuilder->weld_combo_box(u"formulasyntax"_ustr))
38 , mxCbEnglishFuncName(m_xBuilder->weld_check_button(u"englishfuncname"_ustr))
39 , mxBtnCustomCalcDefault(m_xBuilder->weld_radio_button(u"calcdefault"_ustr))
40 , mxBtnCustomCalcCustom(m_xBuilder->weld_radio_button(u"calccustom"_ustr))
41 , mxBtnCustomCalcDetails(m_xBuilder->weld_button(u"details"_ustr))
42 , mxEdSepFuncArg(m_xBuilder->weld_entry(u"function"_ustr))
43 , mxEdSepArrayCol(m_xBuilder->weld_entry(u"arraycolumn"_ustr))
44 , mxEdSepArrayRow(m_xBuilder->weld_entry(u"arrayrow"_ustr))
45 , mxBtnSepReset(m_xBuilder->weld_button(u"reset"_ustr))
46 , mxLbOOXMLRecalcOptions(m_xBuilder->weld_combo_box(u"ooxmlrecalc"_ustr))
47 , mxLbODFRecalcOptions(m_xBuilder->weld_combo_box(u"odfrecalc"_ustr))
48 , mxLbRowHeightReCalcOptions(m_xBuilder->weld_combo_box(u"rowheightrecalc"_ustr))
50 mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_CALC_A1));
51 mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_XL_A1));
52 mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_XL_R1C1));
54 Link<weld::Button&,void> aLink2 = LINK( this, ScTpFormulaOptions, ButtonHdl );
55 mxBtnSepReset->connect_clicked(aLink2);
56 mxBtnCustomCalcDetails->connect_clicked(aLink2);
58 Link<weld::Toggleable&,void> aToggleLink = LINK( this, ScTpFormulaOptions, ToggleHdl );
59 mxBtnCustomCalcDefault->connect_toggled(aToggleLink);
60 mxBtnCustomCalcCustom->connect_toggled(aToggleLink);
62 mxEdSepFuncArg->connect_insert_text(LINK( this, ScTpFormulaOptions, SepInsertTextHdl ));
63 mxEdSepArrayCol->connect_insert_text(LINK( this, ScTpFormulaOptions, ColSepInsertTextHdl ));
64 mxEdSepArrayRow->connect_insert_text(LINK( this, ScTpFormulaOptions, RowSepInsertTextHdl ));
66 Link<weld::Entry&,void> aLink = LINK( this, ScTpFormulaOptions, SepModifyHdl );
67 mxEdSepFuncArg->connect_changed(aLink);
68 mxEdSepArrayCol->connect_changed(aLink);
69 mxEdSepArrayRow->connect_changed(aLink);
71 Link<weld::Widget&,void> aLink3 = LINK( this, ScTpFormulaOptions, SepEditOnFocusHdl );
72 mxEdSepFuncArg->connect_focus_in(aLink3);
73 mxEdSepArrayCol->connect_focus_in(aLink3);
74 mxEdSepArrayRow->connect_focus_in(aLink3);
76 // Get the decimal separator for current locale.
77 OUString aSep = ScGlobal::getLocaleData().getNumDecimalSep();
78 mnDecSep = aSep.isEmpty() ? u'.' : aSep[0];
80 maSavedDocOptions = rCoreAttrs.Get(SID_SCDOCOPTIONS).GetDocOptions();
83 ScTpFormulaOptions::~ScTpFormulaOptions()
87 void ScTpFormulaOptions::ResetSeparators()
89 OUString aFuncArg, aArrayCol, aArrayRow;
90 ScFormulaOptions::GetDefaultFormulaSeparators(aFuncArg, aArrayCol, aArrayRow);
91 mxEdSepFuncArg->set_text(aFuncArg);
92 mxEdSepArrayCol->set_text(aArrayCol);
93 mxEdSepArrayRow->set_text(aArrayRow);
96 void ScTpFormulaOptions::OnFocusSeparatorInput(weld::Entry* pEdit)
98 if (!pEdit)
99 return;
101 // Make sure the entire text is selected.
102 pEdit->select_region(0, -1);
103 OUString sSepValue = pEdit->get_text();
104 if (!sSepValue.isEmpty())
105 maOldSepValue = sSepValue;
108 void ScTpFormulaOptions::UpdateCustomCalcRadioButtons(bool bDefault)
110 if (bDefault)
112 mxBtnCustomCalcDefault->set_active(true);
113 mxBtnCustomCalcCustom->set_active(false);
114 mxBtnCustomCalcDetails->set_sensitive(false);
116 else
118 mxBtnCustomCalcDefault->set_active(false);
119 mxBtnCustomCalcCustom->set_active(true);
120 mxBtnCustomCalcDetails->set_sensitive(true);
124 void ScTpFormulaOptions::LaunchCustomCalcSettings()
126 ScCalcOptionsDialog aDlg(GetFrameWeld(), maCurrentConfig, maCurrentDocOptions.IsWriteCalcConfig());
127 if (aDlg.run() == RET_OK)
129 maCurrentConfig = aDlg.GetConfig();
130 maCurrentDocOptions.SetWriteCalcConfig(aDlg.GetWriteCalcConfig());
134 bool ScTpFormulaOptions::IsValidSeparator(std::u16string_view aSep, bool bArray) const
136 if (aSep.size() != 1)
137 // Must be one-character long.
138 return false;
140 const sal_Unicode c = aSep[0];
142 if (c == mnDecSep)
143 // decimal separator is not allowed.
144 return false;
146 if (c <= 0x20 || c == 0x7f)
147 // Disallow non-printables including space and DEL.
148 return false;
150 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9'))
151 // Disallow alphanumeric.
152 return false;
154 if (bArray)
156 switch (c)
158 case '+':
159 case '-':
160 case '{':
161 case '}':
162 case '"':
163 // All following just to prevent confusion, they are not
164 // evaluated in inline arrays and theoretically would be
165 // possible.
166 case '%':
167 case '/':
168 case '*':
169 case '=':
170 case '<':
171 case '>':
172 case '[':
173 case ']':
174 case '(':
175 case ')':
176 case '\'':
177 // Disallowed characters. Anything else we want to disallow ?
178 return false;
181 else if (c <= 0x7f)
183 switch (c)
185 default:
186 // Anything bad except the knowns.
187 return false;
188 case ';':
189 case ',':
190 ; // nothing
193 else
195 // Any Unicode character, would have to ask the compiler's localized
196 // symbol map whether it's a known symbol but not a separator
197 // (ocSep,ocArrayRowSep,ocArrayColSep), which we're about to set here.
198 // But really..
199 return false;
202 return true;
205 IMPL_LINK( ScTpFormulaOptions, ButtonHdl, weld::Button&, rBtn, void )
207 if (&rBtn == mxBtnSepReset.get())
208 ResetSeparators();
209 else if (&rBtn == mxBtnCustomCalcDetails.get())
210 LaunchCustomCalcSettings();
213 IMPL_LINK( ScTpFormulaOptions, ToggleHdl, weld::Toggleable&, rBtn, void )
215 if (!rBtn.get_active())
216 return;
217 if (mxBtnCustomCalcDefault->get_active())
218 UpdateCustomCalcRadioButtons(true);
219 else if (mxBtnCustomCalcCustom->get_active())
220 UpdateCustomCalcRadioButtons(false);
223 IMPL_LINK(ScTpFormulaOptions, SepInsertTextHdl, OUString&, rTest, bool)
225 if (!IsValidSeparator(rTest, false) && !maOldSepValue.isEmpty())
226 // Invalid separator. Restore the old value.
227 rTest = maOldSepValue;
228 return true;
231 IMPL_LINK(ScTpFormulaOptions, RowSepInsertTextHdl, OUString&, rTest, bool)
233 // Invalid separator or same as ColStr - Restore the old value.
234 if ((!IsValidSeparator(rTest, true) || rTest == mxEdSepArrayCol->get_text()) && !maOldSepValue.isEmpty())
235 rTest = maOldSepValue;
236 return true;
239 IMPL_LINK(ScTpFormulaOptions, ColSepInsertTextHdl, OUString&, rTest, bool)
241 // Invalid separator or same as RowStr - Restore the old value.
242 if ((!IsValidSeparator(rTest, true) || rTest == mxEdSepArrayRow->get_text()) && !maOldSepValue.isEmpty())
243 rTest = maOldSepValue;
244 return true;
247 IMPL_LINK( ScTpFormulaOptions, SepModifyHdl, weld::Entry&, rEdit, void )
249 OnFocusSeparatorInput(&rEdit);
252 IMPL_LINK( ScTpFormulaOptions, SepEditOnFocusHdl, weld::Widget&, rControl, void )
254 OnFocusSeparatorInput(dynamic_cast<weld::Entry*>(&rControl));
257 std::unique_ptr<SfxTabPage> ScTpFormulaOptions::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rCoreSet)
259 return std::make_unique<ScTpFormulaOptions>(pPage, pController, *rCoreSet);
262 OUString ScTpFormulaOptions::GetAllStrings()
264 OUString sAllStrings;
265 OUString labels[] = { u"label1"_ustr, u"formulasyntaxlabel"_ustr,
266 u"label3"_ustr, u"label6"_ustr,
267 u"label7"_ustr, u"label8"_ustr,
268 u"label2"_ustr, u"label4"_ustr,
269 u"label9"_ustr, u"label10"_ustr };
271 for (const auto& label : labels)
273 if (const auto pString = m_xBuilder->weld_label(label))
274 sAllStrings += pString->get_label() + " ";
277 OUString radioButton[] = { u"calcdefault"_ustr, u"calccustom"_ustr };
279 for (const auto& radio : radioButton)
281 if (const auto pString = m_xBuilder->weld_radio_button(radio))
282 sAllStrings += pString->get_label() + " ";
285 OUString buttons[] = { u"reset"_ustr, u"details"_ustr };
287 for (const auto& btn : buttons)
289 if (const auto pString = m_xBuilder->weld_button(btn))
290 sAllStrings += pString->get_label() + " ";
293 // check button
294 sAllStrings += mxCbEnglishFuncName->get_label() + " ";
296 return sAllStrings.replaceAll("_", "");
299 bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
301 bool bRet = false;
302 ScFormulaOptions aOpt;
303 bool bEnglishFuncName = mxCbEnglishFuncName->get_active();
304 sal_Int16 aSyntaxPos = mxLbFormulaSyntax->get_active();
305 OUString aSep = mxEdSepFuncArg->get_text();
306 OUString aSepArrayCol = mxEdSepArrayCol->get_text();
307 OUString aSepArrayRow = mxEdSepArrayRow->get_text();
308 sal_Int16 nOOXMLRecalcMode = mxLbOOXMLRecalcOptions->get_active();
309 sal_Int16 nODFRecalcMode = mxLbODFRecalcOptions->get_active();
310 sal_Int16 nReCalcOptRowHeights = mxLbRowHeightReCalcOptions->get_active();
312 if (mxBtnCustomCalcDefault->get_active())
314 // When Default is selected, reset all the calc config settings to default.
315 maCurrentConfig.reset();
318 if ( mxLbFormulaSyntax->get_saved_value() != mxLbFormulaSyntax->get_text(aSyntaxPos)
319 || mxCbEnglishFuncName->get_saved_state() != (bEnglishFuncName ? 1 : 0)
320 || mxEdSepFuncArg->get_saved_value() != aSep
321 || mxEdSepArrayCol->get_saved_value() != aSepArrayCol
322 || mxEdSepArrayRow->get_saved_value() != aSepArrayRow
323 || mxLbOOXMLRecalcOptions->get_saved_value() != mxLbOOXMLRecalcOptions->get_text(nOOXMLRecalcMode)
324 || mxLbODFRecalcOptions->get_saved_value() != mxLbODFRecalcOptions->get_text(nODFRecalcMode)
325 || mxLbRowHeightReCalcOptions->get_saved_value() != mxLbRowHeightReCalcOptions->get_text(nReCalcOptRowHeights)
326 || maSavedConfig != maCurrentConfig
327 || maSavedDocOptions != maCurrentDocOptions )
329 ::formula::FormulaGrammar::Grammar eGram = ::formula::FormulaGrammar::GRAM_DEFAULT;
331 switch (aSyntaxPos)
333 case 0:
334 eGram = ::formula::FormulaGrammar::GRAM_NATIVE;
335 break;
336 case 1:
337 eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1;
338 break;
339 case 2:
340 eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1;
341 break;
344 ScRecalcOptions eOOXMLRecalc = static_cast<ScRecalcOptions>(nOOXMLRecalcMode);
345 ScRecalcOptions eODFRecalc = static_cast<ScRecalcOptions>(nODFRecalcMode);
346 ScRecalcOptions eReCalcOptRowHeights = static_cast<ScRecalcOptions>(nReCalcOptRowHeights);
348 aOpt.SetFormulaSyntax(eGram);
349 aOpt.SetUseEnglishFuncName(bEnglishFuncName);
350 aOpt.SetFormulaSepArg(aSep);
351 aOpt.SetFormulaSepArrayCol(aSepArrayCol);
352 aOpt.SetFormulaSepArrayRow(aSepArrayRow);
353 aOpt.SetCalcConfig(maCurrentConfig);
354 aOpt.SetOOXMLRecalcOptions(eOOXMLRecalc);
355 aOpt.SetODFRecalcOptions(eODFRecalc);
356 aOpt.SetReCalcOptiRowHeights(eReCalcOptRowHeights);
357 aOpt.SetWriteCalcConfig( maCurrentDocOptions.IsWriteCalcConfig());
359 rCoreSet->Put( ScTpFormulaItem( std::move(aOpt) ) );
360 rCoreSet->Put( ScTpCalcItem( SID_SCDOCOPTIONS, maCurrentDocOptions ) );
362 bRet = true;
364 return bRet;
367 void ScTpFormulaOptions::Reset(const SfxItemSet* rCoreSet)
369 ScFormulaOptions aOpt;
370 if(const ScTpFormulaItem* pItem = rCoreSet->GetItemIfSet(SID_SCFORMULAOPTIONS, false))
371 aOpt = pItem->GetFormulaOptions();
373 // formula grammar.
374 ::formula::FormulaGrammar::Grammar eGram = aOpt.GetFormulaSyntax();
376 switch (eGram)
378 case ::formula::FormulaGrammar::GRAM_NATIVE:
379 mxLbFormulaSyntax->set_active(0);
380 break;
381 case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1:
382 mxLbFormulaSyntax->set_active(1);
383 break;
384 case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1:
385 mxLbFormulaSyntax->set_active(2);
386 break;
387 default:
388 mxLbFormulaSyntax->set_active(0);
391 mxLbFormulaSyntax->save_value();
392 mxLbFormulaSyntax->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::Grammar::isReadOnly() );
394 ScRecalcOptions eOOXMLRecalc = aOpt.GetOOXMLRecalcOptions();
395 mxLbOOXMLRecalcOptions->set_active(static_cast<sal_uInt16>(eOOXMLRecalc));
396 mxLbOOXMLRecalcOptions->save_value();
397 mxLbOOXMLRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::isReadOnly() );
399 ScRecalcOptions eODFRecalc = aOpt.GetODFRecalcOptions();
400 mxLbODFRecalcOptions->set_active(static_cast<sal_uInt16>(eODFRecalc));
401 mxLbODFRecalcOptions->save_value();
402 mxLbODFRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::ODFRecalcMode::isReadOnly() );
404 // Recalc optimal row heights at load
405 ScRecalcOptions eReCalcOptRowHeights = aOpt.GetReCalcOptiRowHeights();
406 mxLbRowHeightReCalcOptions->set_active(static_cast<sal_uInt16>(eReCalcOptRowHeights));
407 mxLbRowHeightReCalcOptions->save_value();
408 mxLbRowHeightReCalcOptions->set_sensitive(
409 !officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::isReadOnly() );
411 // english function name.
412 mxCbEnglishFuncName->set_active( aOpt.GetUseEnglishFuncName() );
413 mxCbEnglishFuncName->save_state();
414 mxCbEnglishFuncName->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::EnglishFunctionName::isReadOnly() );
416 // Separators
417 OUString aSep = aOpt.GetFormulaSepArg();
418 OUString aSepArrayRow = aOpt.GetFormulaSepArrayRow();
419 OUString aSepArrayCol = aOpt.GetFormulaSepArrayCol();
421 if (IsValidSeparator(aSep, false) && IsValidSeparator(aSepArrayRow, true) && IsValidSeparator(aSepArrayCol, true))
423 // Each and all separators must be valid.
424 mxEdSepFuncArg->set_text(aSep);
425 mxEdSepArrayCol->set_text(aSepArrayCol);
426 mxEdSepArrayRow->set_text(aSepArrayRow);
428 mxEdSepFuncArg->save_value();
429 mxEdSepArrayCol->save_value();
430 mxEdSepArrayRow->save_value();
432 else
433 ResetSeparators();
435 mxEdSepFuncArg->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() );
436 mxEdSepArrayCol->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() );
437 mxEdSepArrayRow->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
438 mxBtnSepReset->set_sensitive ( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() &&
439 !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() &&
440 !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
442 // detailed calc settings.
443 ScFormulaOptions aDefaults;
445 maSavedConfig = aOpt.GetCalcConfig();
446 bool bDefault = aDefaults.GetCalcConfig() == maSavedConfig;
447 UpdateCustomCalcRadioButtons(bDefault);
449 maCurrentConfig = maSavedConfig;
451 maCurrentDocOptions = maSavedDocOptions;
454 DeactivateRC ScTpFormulaOptions::DeactivatePage(SfxItemSet* /*pSet*/)
456 // What's this method for ?
457 return DeactivateRC::KeepPage;
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */