LibreOffice Module sc (master)  1
tpformula.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 #undef SC_DLLIMPLEMENTATION
21 
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"
31 
33 
35  : SfxTabPage(pPage, pController, "modules/scalc/ui/optformula.ui", "OptFormula", &rCoreAttrs)
36  , mnDecSep(0)
37  , mxLbFormulaSyntax(m_xBuilder->weld_combo_box("formulasyntax"))
38  , mxCbEnglishFuncName(m_xBuilder->weld_check_button("englishfuncname"))
39  , mxBtnCustomCalcDefault(m_xBuilder->weld_radio_button("calcdefault"))
40  , mxBtnCustomCalcCustom(m_xBuilder->weld_radio_button("calccustom"))
41  , mxBtnCustomCalcDetails(m_xBuilder->weld_button("details"))
42  , mxEdSepFuncArg(m_xBuilder->weld_entry("function"))
43  , mxEdSepArrayCol(m_xBuilder->weld_entry("arraycolumn"))
44  , mxEdSepArrayRow(m_xBuilder->weld_entry("arrayrow"))
45  , mxBtnSepReset(m_xBuilder->weld_button("reset"))
46  , mxLbOOXMLRecalcOptions(m_xBuilder->weld_combo_box("ooxmlrecalc"))
47  , mxLbODFRecalcOptions(m_xBuilder->weld_combo_box("odfrecalc"))
48 {
49  mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_CALC_A1));
50  mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_XL_A1));
51  mxLbFormulaSyntax->append_text(ScResId(SCSTR_FORMULA_SYNTAX_XL_R1C1));
52 
53  Link<weld::Button&,void> aLink2 = LINK( this, ScTpFormulaOptions, ButtonHdl );
54  mxBtnSepReset->connect_clicked(aLink2);
55  mxBtnCustomCalcDetails->connect_clicked(aLink2);
56 
57  Link<weld::Toggleable&,void> aToggleLink = LINK( this, ScTpFormulaOptions, ToggleHdl );
58  mxBtnCustomCalcDefault->connect_toggled(aToggleLink);
59  mxBtnCustomCalcCustom->connect_toggled(aToggleLink);
60 
61  mxEdSepFuncArg->connect_insert_text(LINK( this, ScTpFormulaOptions, SepInsertTextHdl ));
62  mxEdSepArrayCol->connect_insert_text(LINK( this, ScTpFormulaOptions, ColSepInsertTextHdl ));
63  mxEdSepArrayRow->connect_insert_text(LINK( this, ScTpFormulaOptions, RowSepInsertTextHdl ));
64 
65  Link<weld::Entry&,void> aLink = LINK( this, ScTpFormulaOptions, SepModifyHdl );
66  mxEdSepFuncArg->connect_changed(aLink);
67  mxEdSepArrayCol->connect_changed(aLink);
68  mxEdSepArrayRow->connect_changed(aLink);
69 
70  Link<weld::Widget&,void> aLink3 = LINK( this, ScTpFormulaOptions, SepEditOnFocusHdl );
71  mxEdSepFuncArg->connect_focus_in(aLink3);
72  mxEdSepArrayCol->connect_focus_in(aLink3);
73  mxEdSepArrayRow->connect_focus_in(aLink3);
74 
75  // Get the decimal separator for current locale.
76  OUString aSep = ScGlobal::getLocaleData().getNumDecimalSep();
77  mnDecSep = aSep.isEmpty() ? u'.' : aSep[0];
78 
79  maSavedDocOptions = static_cast<const ScTpCalcItem&>(rCoreAttrs.Get(
80  GetWhich(SID_SCDOCOPTIONS))).GetDocOptions();
81 }
82 
84 {
85 }
86 
88 {
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);
94 }
95 
97 {
98  if (!pEdit)
99  return;
100 
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;
106 }
107 
109 {
110  if (bDefault)
111  {
112  mxBtnCustomCalcDefault->set_active(true);
113  mxBtnCustomCalcCustom->set_active(false);
114  mxBtnCustomCalcDetails->set_sensitive(false);
115  }
116  else
117  {
118  mxBtnCustomCalcDefault->set_active(false);
119  mxBtnCustomCalcCustom->set_active(true);
120  mxBtnCustomCalcDetails->set_sensitive(true);
121  }
122 }
123 
125 {
127  if (aDlg.run() == RET_OK)
128  {
129  maCurrentConfig = aDlg.GetConfig();
130  maCurrentDocOptions.SetWriteCalcConfig(aDlg.GetWriteCalcConfig());
131  }
132 }
133 
134 bool ScTpFormulaOptions::IsValidSeparator(const OUString& rSep, bool bArray) const
135 {
136  if (rSep.getLength() != 1)
137  // Must be one-character long.
138  return false;
139 
140  const sal_Unicode c = rSep[0];
141 
142  if (c == mnDecSep)
143  // decimal separator is not allowed.
144  return false;
145 
146  if (c <= 0x20 || c == 0x7f)
147  // Disallow non-printables including space and DEL.
148  return false;
149 
150  if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9'))
151  // Disallow alphanumeric.
152  return false;
153 
154  if (bArray)
155  {
156  switch (c)
157  {
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;
179  }
180  }
181  else if (c <= 0x7f)
182  {
183  switch (c)
184  {
185  default:
186  // Anything bad except the knowns.
187  return false;
188  case ';':
189  case ',':
190  ; // nothing
191  }
192  }
193  else
194  {
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;
200  }
201 
202  return true;
203 }
204 
205 IMPL_LINK( ScTpFormulaOptions, ButtonHdl, weld::Button&, rBtn, void )
206 {
207  if (&rBtn == mxBtnSepReset.get())
208  ResetSeparators();
209  else if (&rBtn == mxBtnCustomCalcDetails.get())
210  LaunchCustomCalcSettings();
211 }
212 
213 IMPL_LINK( ScTpFormulaOptions, ToggleHdl, weld::Toggleable&, rBtn, void )
214 {
215  if (!rBtn.get_active())
216  return;
217  if (mxBtnCustomCalcDefault->get_active())
218  UpdateCustomCalcRadioButtons(true);
219  else if (mxBtnCustomCalcCustom->get_active())
220  UpdateCustomCalcRadioButtons(false);
221 }
222 
223 IMPL_LINK(ScTpFormulaOptions, SepInsertTextHdl, OUString&, rTest, bool)
224 {
225  if (!IsValidSeparator(rTest, false) && !maOldSepValue.isEmpty())
226  // Invalid separator. Restore the old value.
227  rTest = maOldSepValue;
228  return true;
229 }
230 
231 IMPL_LINK(ScTpFormulaOptions, RowSepInsertTextHdl, OUString&, rTest, bool)
232 {
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;
237 }
238 
239 IMPL_LINK(ScTpFormulaOptions, ColSepInsertTextHdl, OUString&, rTest, bool)
240 {
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;
245 }
246 
247 IMPL_LINK( ScTpFormulaOptions, SepModifyHdl, weld::Entry&, rEdit, void )
248 {
249  OnFocusSeparatorInput(&rEdit);
250 }
251 
252 IMPL_LINK( ScTpFormulaOptions, SepEditOnFocusHdl, weld::Widget&, rControl, void )
253 {
254  OnFocusSeparatorInput(dynamic_cast<weld::Entry*>(&rControl));
255 }
256 
257 std::unique_ptr<SfxTabPage> ScTpFormulaOptions::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rCoreSet)
258 {
259  return std::make_unique<ScTpFormulaOptions>(pPage, pController, *rCoreSet);
260 }
261 
263 {
264  bool bRet = false;
265  ScFormulaOptions aOpt;
266  bool bEnglishFuncName = mxCbEnglishFuncName->get_active();
267  sal_Int16 aSyntaxPos = mxLbFormulaSyntax->get_active();
268  OUString aSep = mxEdSepFuncArg->get_text();
269  OUString aSepArrayCol = mxEdSepArrayCol->get_text();
270  OUString aSepArrayRow = mxEdSepArrayRow->get_text();
271  sal_Int16 nOOXMLRecalcMode = mxLbOOXMLRecalcOptions->get_active();
272  sal_Int16 nODFRecalcMode = mxLbODFRecalcOptions->get_active();
273 
274  if (mxBtnCustomCalcDefault->get_active())
275  {
276  // When Default is selected, reset all the calc config settings to default.
278  }
279 
280  if ( mxLbFormulaSyntax->get_saved_value() != mxLbFormulaSyntax->get_text(aSyntaxPos)
281  || mxCbEnglishFuncName->get_saved_state() != (bEnglishFuncName ? 1 : 0)
282  || mxEdSepFuncArg->get_saved_value() != aSep
283  || mxEdSepArrayCol->get_saved_value() != aSepArrayCol
284  || mxEdSepArrayRow->get_saved_value() != aSepArrayRow
285  || mxLbOOXMLRecalcOptions->get_saved_value() != mxLbOOXMLRecalcOptions->get_text(nOOXMLRecalcMode)
286  || mxLbODFRecalcOptions->get_saved_value() != mxLbODFRecalcOptions->get_text(nODFRecalcMode)
289  {
291 
292  switch (aSyntaxPos)
293  {
294  case 0:
296  break;
297  case 1:
299  break;
300  case 2:
302  break;
303  }
304 
305  ScRecalcOptions eOOXMLRecalc = static_cast<ScRecalcOptions>(nOOXMLRecalcMode);
306  ScRecalcOptions eODFRecalc = static_cast<ScRecalcOptions>(nODFRecalcMode);
307 
308  aOpt.SetFormulaSyntax(eGram);
309  aOpt.SetUseEnglishFuncName(bEnglishFuncName);
310  aOpt.SetFormulaSepArg(aSep);
311  aOpt.SetFormulaSepArrayCol(aSepArrayCol);
312  aOpt.SetFormulaSepArrayRow(aSepArrayRow);
314  aOpt.SetOOXMLRecalcOptions(eOOXMLRecalc);
315  aOpt.SetODFRecalcOptions(eODFRecalc);
317 
318  rCoreSet->Put( ScTpFormulaItem( aOpt ) );
319  rCoreSet->Put( ScTpCalcItem( SID_SCDOCOPTIONS, maCurrentDocOptions ) );
320 
321  bRet = true;
322  }
323  return bRet;
324 }
325 
327 {
328  ScFormulaOptions aOpt;
329  const SfxPoolItem* pItem = nullptr;
330 
331  if(SfxItemState::SET == rCoreSet->GetItemState(SID_SCFORMULAOPTIONS, false , &pItem))
332  aOpt = static_cast<const ScTpFormulaItem*>(pItem)->GetFormulaOptions();
333 
334  // formula grammar.
336 
337  switch (eGram)
338  {
339  case ::formula::FormulaGrammar::GRAM_NATIVE:
340  mxLbFormulaSyntax->set_active(0);
341  break;
342  case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1:
343  mxLbFormulaSyntax->set_active(1);
344  break;
345  case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1:
346  mxLbFormulaSyntax->set_active(2);
347  break;
348  default:
349  mxLbFormulaSyntax->set_active(0);
350  }
351 
352  mxLbFormulaSyntax->save_value();
353  mxLbFormulaSyntax->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::Grammar::isReadOnly() );
354 
355  ScRecalcOptions eOOXMLRecalc = aOpt.GetOOXMLRecalcOptions();
356  mxLbOOXMLRecalcOptions->set_active(static_cast<sal_uInt16>(eOOXMLRecalc));
357  mxLbOOXMLRecalcOptions->save_value();
358  mxLbOOXMLRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::isReadOnly() );
359 
360  ScRecalcOptions eODFRecalc = aOpt.GetODFRecalcOptions();
361  mxLbODFRecalcOptions->set_active(static_cast<sal_uInt16>(eODFRecalc));
362  mxLbODFRecalcOptions->save_value();
363  mxLbODFRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::ODFRecalcMode::isReadOnly() );
364 
365  // english function name.
366  mxCbEnglishFuncName->set_active( aOpt.GetUseEnglishFuncName() );
367  mxCbEnglishFuncName->save_state();
368  mxCbEnglishFuncName->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::EnglishFunctionName::isReadOnly() );
369 
370  // Separators
371  OUString aSep = aOpt.GetFormulaSepArg();
372  OUString aSepArrayRow = aOpt.GetFormulaSepArrayRow();
373  OUString aSepArrayCol = aOpt.GetFormulaSepArrayCol();
374 
375  if (IsValidSeparator(aSep, false) && IsValidSeparator(aSepArrayRow, true) && IsValidSeparator(aSepArrayCol, true))
376  {
377  // Each and all separators must be valid.
378  mxEdSepFuncArg->set_text(aSep);
379  mxEdSepArrayCol->set_text(aSepArrayCol);
380  mxEdSepArrayRow->set_text(aSepArrayRow);
381 
382  mxEdSepFuncArg->save_value();
383  mxEdSepArrayCol->save_value();
384  mxEdSepArrayRow->save_value();
385  }
386  else
387  ResetSeparators();
388 
389  mxEdSepFuncArg->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() );
390  mxEdSepArrayCol->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() );
391  mxEdSepArrayRow->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
392  mxBtnSepReset->set_sensitive ( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() &&
393  !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() &&
394  !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
395 
396  // detailed calc settings.
397  ScFormulaOptions aDefaults;
398 
399  maSavedConfig = aOpt.GetCalcConfig();
400  bool bDefault = aDefaults.GetCalcConfig() == maSavedConfig;
402 
404 
406 }
407 
409 {
410  // What's this method for ?
411  return DeactivateRC::KeepPage;
412 }
413 
414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsWriteCalcConfig() const
Definition: docoptio.hxx:101
static void GetDefaultFormulaSeparators(OUString &rSepArg, OUString &rSepArrayCol, OUString &rSepArrayRow)
Definition: formulaopt.cxx:49
sal_Unicode mnDecSep
Definition: tpformula.hxx:67
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
ScCalcConfig maSavedConfig
Definition: tpformula.hxx:61
virtual bool FillItemSet(SfxItemSet *rCoreSet) override
Definition: tpformula.cxx:262
ScRecalcOptions GetODFRecalcOptions() const
Definition: formulaopt.hxx:65
void SetOOXMLRecalcOptions(ScRecalcOptions eOpt)
Definition: formulaopt.hxx:61
std::unique_ptr< weld::RadioButton > mxBtnCustomCalcDefault
Definition: tpformula.hxx:72
bool GetUseEnglishFuncName() const
Definition: formulaopt.hxx:47
ScDocOptions maSavedDocOptions
Definition: tpformula.hxx:64
std::unique_ptr< weld::Button > mxBtnSepReset
Definition: tpformula.hxx:79
std::unique_ptr< weld::RadioButton > mxBtnCustomCalcCustom
Definition: tpformula.hxx:73
const OUString & GetFormulaSepArrayRow() const
Definition: formulaopt.hxx:56
sal_uInt16 sal_Unicode
static SC_DLLPUBLIC const LocaleDataWrapper & getLocaleData()
Definition: global.cxx:1006
void SetFormulaSyntax(::formula::FormulaGrammar::Grammar eGram)
Definition: formulaopt.hxx:39
std::unique_ptr< weld::CheckButton > mxCbEnglishFuncName
Definition: tpformula.hxx:70
std::unique_ptr< weld::Entry > mxEdSepFuncArg
Definition: tpformula.hxx:76
const OUString & getNumDecimalSep() const
bool IsValidSeparator(const OUString &rSep, bool bArray) const
Definition: tpformula.cxx:134
ScCalcConfig & GetCalcConfig()
Definition: formulaopt.hxx:42
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
std::unique_ptr< weld::ComboBox > mxLbODFRecalcOptions
Definition: tpformula.hxx:82
void LaunchCustomCalcSettings()
Definition: tpformula.cxx:124
void SetFormulaSepArg(const OUString &rSep)
Definition: formulaopt.hxx:52
virtual void select_region(int nStartPos, int nEndPos)=0
float u
std::unique_ptr< weld::Entry > mxEdSepArrayCol
Definition: tpformula.hxx:77
ScCalcConfig maCurrentConfig
Definition: tpformula.hxx:62
void SetFormulaSepArrayCol(const OUString &rSep)
Definition: formulaopt.hxx:58
virtual void Reset(const SfxItemSet *rCoreSet) override
Definition: tpformula.cxx:326
void SetFormulaSepArrayRow(const OUString &rSep)
Definition: formulaopt.hxx:55
void SetUseEnglishFuncName(bool bVal)
Definition: formulaopt.hxx:46
virtual OUString get_text() const =0
const OUString & GetFormulaSepArg() const
Definition: formulaopt.hxx:53
const OUString & GetFormulaSepArrayCol() const
Definition: formulaopt.hxx:59
std::unique_ptr< weld::ComboBox > mxLbFormulaSyntax
Definition: tpformula.hxx:69
ScDocOptions maCurrentDocOptions
Definition: tpformula.hxx:65
void SetCalcConfig(const ScCalcConfig &rConfig)
Definition: formulaopt.hxx:44
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
std::unique_ptr< weld::Entry > mxEdSepArrayRow
Definition: tpformula.hxx:78
weld::Window * GetFrameWeld() const
weld::Entry & rEdit
ScRecalcOptions GetOOXMLRecalcOptions() const
Definition: formulaopt.hxx:62
virtual ~ScTpFormulaOptions() override
Definition: tpformula.cxx:83
void OnFocusSeparatorInput(weld::Entry *pEdit)
Definition: tpformula.cxx:96
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
void UpdateCustomCalcRadioButtons(bool bDefault)
Definition: tpformula.cxx:108
RET_OK
ScTpFormulaOptions(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rCoreSet)
Definition: tpformula.cxx:34
void ResetSeparators()
Definition: tpformula.cxx:87
ScRecalcOptions
Definition: calcconfig.hxx:23
::formula::FormulaGrammar::Grammar GetFormulaSyntax() const
Definition: formulaopt.hxx:40
DeactivateRC
void SetWriteCalcConfig(bool bVal)
Definition: docoptio.hxx:100
std::unique_ptr< weld::ComboBox > mxLbOOXMLRecalcOptions
Definition: tpformula.hxx:81
void SetWriteCalcConfig(bool bVal)
Definition: formulaopt.hxx:49
virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override
Definition: tpformula.cxx:408
IMPL_LINK(ScTpFormulaOptions, ButtonHdl, weld::Button &, rBtn, void)
Definition: tpformula.cxx:205
OUString maOldSepValue
Stores old separator value of currently focused separator edit box.
Definition: tpformula.hxx:59
std::unique_ptr< weld::Button > mxBtnCustomCalcDetails
Definition: tpformula.hxx:74
static std::unique_ptr< SfxTabPage > Create(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rCoreSet)
Definition: tpformula.cxx:257
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
void SetODFRecalcOptions(ScRecalcOptions eOpt)
Definition: formulaopt.hxx:64