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  mxBtnCustomCalcDefault->connect_clicked(aLink2);
56  mxBtnCustomCalcCustom->connect_clicked(aLink2);
57  mxBtnCustomCalcDetails->connect_clicked(aLink2);
58 
59  mxEdSepFuncArg->connect_insert_text(LINK( this, ScTpFormulaOptions, SepInsertTextHdl ));
60  mxEdSepArrayCol->connect_insert_text(LINK( this, ScTpFormulaOptions, ColSepInsertTextHdl ));
61  mxEdSepArrayRow->connect_insert_text(LINK( this, ScTpFormulaOptions, RowSepInsertTextHdl ));
62 
63  Link<weld::Entry&,void> aLink = LINK( this, ScTpFormulaOptions, SepModifyHdl );
64  mxEdSepFuncArg->connect_changed(aLink);
65  mxEdSepArrayCol->connect_changed(aLink);
66  mxEdSepArrayRow->connect_changed(aLink);
67 
68  Link<weld::Widget&,void> aLink3 = LINK( this, ScTpFormulaOptions, SepEditOnFocusHdl );
69  mxEdSepFuncArg->connect_focus_in(aLink3);
70  mxEdSepArrayCol->connect_focus_in(aLink3);
71  mxEdSepArrayRow->connect_focus_in(aLink3);
72 
73  // Get the decimal separator for current locale.
74  OUString aSep = ScGlobal::getLocaleDataPtr()->getNumDecimalSep();
75  mnDecSep = aSep.isEmpty() ? u'.' : aSep[0];
76 
77  maSavedDocOptions = static_cast<const ScTpCalcItem&>(rCoreAttrs.Get(
78  GetWhich(SID_SCDOCOPTIONS))).GetDocOptions();
79 }
80 
82 {
83 }
84 
86 {
87  OUString aFuncArg, aArrayCol, aArrayRow;
88  ScFormulaOptions::GetDefaultFormulaSeparators(aFuncArg, aArrayCol, aArrayRow);
89  mxEdSepFuncArg->set_text(aFuncArg);
90  mxEdSepArrayCol->set_text(aArrayCol);
91  mxEdSepArrayRow->set_text(aArrayRow);
92 }
93 
95 {
96  if (!pEdit)
97  return;
98 
99  // Make sure the entire text is selected.
100  pEdit->select_region(0, -1);
101  OUString sSepValue = pEdit->get_text();
102  if (!sSepValue.isEmpty())
103  maOldSepValue = sSepValue;
104 }
105 
107 {
108  if (bDefault)
109  {
110  mxBtnCustomCalcDefault->set_active(true);
111  mxBtnCustomCalcCustom->set_active(false);
112  mxBtnCustomCalcDetails->set_sensitive(false);
113  }
114  else
115  {
116  mxBtnCustomCalcDefault->set_active(false);
117  mxBtnCustomCalcCustom->set_active(true);
118  mxBtnCustomCalcDetails->set_sensitive(true);
119  }
120 }
121 
123 {
125  if (aDlg.run() == RET_OK)
126  {
127  maCurrentConfig = aDlg.GetConfig();
128  maCurrentDocOptions.SetWriteCalcConfig(aDlg.GetWriteCalcConfig());
129  }
130 }
131 
132 bool ScTpFormulaOptions::IsValidSeparator(const OUString& rSep) const
133 {
134  if (rSep.getLength() != 1)
135  // Must be one-character long.
136  return false;
137 
138  if (rSep.compareToAscii("a") >= 0 && rSep.compareToAscii("z") <= 0)
139  return false;
140 
141  if (rSep.compareToAscii("A") >= 0 && rSep.compareToAscii("Z") <= 0)
142  return false;
143 
144  sal_Unicode c = rSep[0];
145  switch (c)
146  {
147  case '+':
148  case '-':
149  case '/':
150  case '*':
151  case '<':
152  case '>':
153  case '[':
154  case ']':
155  case '(':
156  case ')':
157  case '"':
158  case '\'':
159  // Disallowed characters. Anything else we want to disallow ?
160  return false;
161  }
162 
163  if (c == mnDecSep)
164  // decimal separator is not allowed.
165  return false;
166 
167  return true;
168 }
169 
170 IMPL_LINK( ScTpFormulaOptions, ButtonHdl, weld::Button&, rBtn, void )
171 {
172  if (&rBtn == mxBtnSepReset.get())
173  ResetSeparators();
174  else if (&rBtn == mxBtnCustomCalcDefault.get())
175  UpdateCustomCalcRadioButtons(true);
176  else if (&rBtn == mxBtnCustomCalcCustom.get())
177  UpdateCustomCalcRadioButtons(false);
178  else if (&rBtn == mxBtnCustomCalcDetails.get())
179  LaunchCustomCalcSettings();
180 }
181 
182 IMPL_LINK(ScTpFormulaOptions, SepInsertTextHdl, OUString&, rTest, bool)
183 {
184  if (!IsValidSeparator(rTest) && !maOldSepValue.isEmpty())
185  // Invalid separator. Restore the old value.
186  rTest = maOldSepValue;
187  return true;
188 }
189 
190 IMPL_LINK(ScTpFormulaOptions, RowSepInsertTextHdl, OUString&, rTest, bool)
191 {
192  // Invalid separator or same as ColStr - Restore the old value.
193  if ((!IsValidSeparator(rTest) || rTest == mxEdSepArrayCol->get_text()) && !maOldSepValue.isEmpty())
194  rTest = maOldSepValue;
195  return true;
196 }
197 
198 IMPL_LINK(ScTpFormulaOptions, ColSepInsertTextHdl, OUString&, rTest, bool)
199 {
200  // Invalid separator or same as RowStr - Restore the old value.
201  if ((!IsValidSeparator(rTest) || rTest == mxEdSepArrayRow->get_text()) && !maOldSepValue.isEmpty())
202  rTest = maOldSepValue;
203  return true;
204 }
205 
206 IMPL_LINK( ScTpFormulaOptions, SepModifyHdl, weld::Entry&, rEdit, void )
207 {
208  OnFocusSeparatorInput(&rEdit);
209 }
210 
211 IMPL_LINK( ScTpFormulaOptions, SepEditOnFocusHdl, weld::Widget&, rControl, void )
212 {
213  OnFocusSeparatorInput(dynamic_cast<weld::Entry*>(&rControl));
214 }
215 
216 std::unique_ptr<SfxTabPage> ScTpFormulaOptions::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rCoreSet)
217 {
218  return std::make_unique<ScTpFormulaOptions>(pPage, pController, *rCoreSet);
219 }
220 
222 {
223  bool bRet = false;
224  ScFormulaOptions aOpt;
225  bool bEnglishFuncName = mxCbEnglishFuncName->get_active();
226  sal_Int16 aSyntaxPos = mxLbFormulaSyntax->get_active();
227  OUString aSep = mxEdSepFuncArg->get_text();
228  OUString aSepArrayCol = mxEdSepArrayCol->get_text();
229  OUString aSepArrayRow = mxEdSepArrayRow->get_text();
230  sal_Int16 nOOXMLRecalcMode = mxLbOOXMLRecalcOptions->get_active();
231  sal_Int16 nODFRecalcMode = mxLbODFRecalcOptions->get_active();
232 
233  if (mxBtnCustomCalcDefault->get_active())
234  {
235  // When Default is selected, reset all the calc config settings to default.
237  }
238 
239  if ( mxLbFormulaSyntax->get_saved_value() != mxLbFormulaSyntax->get_text(aSyntaxPos)
240  || mxCbEnglishFuncName->get_saved_state() != (bEnglishFuncName ? 1 : 0)
241  || mxEdSepFuncArg->get_saved_value() != aSep
242  || mxEdSepArrayCol->get_saved_value() != aSepArrayCol
243  || mxEdSepArrayRow->get_saved_value() != aSepArrayRow
244  || mxLbOOXMLRecalcOptions->get_saved_value() != mxLbOOXMLRecalcOptions->get_text(nOOXMLRecalcMode)
245  || mxLbODFRecalcOptions->get_saved_value() != mxLbODFRecalcOptions->get_text(nODFRecalcMode)
248  {
250 
251  switch (aSyntaxPos)
252  {
253  case 0:
255  break;
256  case 1:
258  break;
259  case 2:
261  break;
262  }
263 
264  ScRecalcOptions eOOXMLRecalc = static_cast<ScRecalcOptions>(nOOXMLRecalcMode);
265  ScRecalcOptions eODFRecalc = static_cast<ScRecalcOptions>(nODFRecalcMode);
266 
267  aOpt.SetFormulaSyntax(eGram);
268  aOpt.SetUseEnglishFuncName(bEnglishFuncName);
269  aOpt.SetFormulaSepArg(aSep);
270  aOpt.SetFormulaSepArrayCol(aSepArrayCol);
271  aOpt.SetFormulaSepArrayRow(aSepArrayRow);
273  aOpt.SetOOXMLRecalcOptions(eOOXMLRecalc);
274  aOpt.SetODFRecalcOptions(eODFRecalc);
276 
277  rCoreSet->Put( ScTpFormulaItem( aOpt ) );
278  rCoreSet->Put( ScTpCalcItem( SID_SCDOCOPTIONS, maCurrentDocOptions ) );
279 
280  bRet = true;
281  }
282  return bRet;
283 }
284 
286 {
287  ScFormulaOptions aOpt;
288  const SfxPoolItem* pItem = nullptr;
289 
290  if(SfxItemState::SET == rCoreSet->GetItemState(SID_SCFORMULAOPTIONS, false , &pItem))
291  aOpt = static_cast<const ScTpFormulaItem*>(pItem)->GetFormulaOptions();
292 
293  // formula grammar.
295 
296  switch (eGram)
297  {
298  case ::formula::FormulaGrammar::GRAM_NATIVE:
299  mxLbFormulaSyntax->set_active(0);
300  break;
301  case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1:
302  mxLbFormulaSyntax->set_active(1);
303  break;
304  case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1:
305  mxLbFormulaSyntax->set_active(2);
306  break;
307  default:
308  mxLbFormulaSyntax->set_active(0);
309  }
310 
311  mxLbFormulaSyntax->save_value();
312  mxLbFormulaSyntax->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::Grammar::isReadOnly() );
313 
314  ScRecalcOptions eOOXMLRecalc = aOpt.GetOOXMLRecalcOptions();
315  mxLbOOXMLRecalcOptions->set_active(static_cast<sal_uInt16>(eOOXMLRecalc));
316  mxLbOOXMLRecalcOptions->save_value();
317  mxLbOOXMLRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::isReadOnly() );
318 
319  ScRecalcOptions eODFRecalc = aOpt.GetODFRecalcOptions();
320  mxLbODFRecalcOptions->set_active(static_cast<sal_uInt16>(eODFRecalc));
321  mxLbODFRecalcOptions->save_value();
322  mxLbODFRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::ODFRecalcMode::isReadOnly() );
323 
324  // english function name.
325  mxCbEnglishFuncName->set_active( aOpt.GetUseEnglishFuncName() );
326  mxCbEnglishFuncName->save_state();
327  mxCbEnglishFuncName->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::EnglishFunctionName::isReadOnly() );
328 
329  // Separators
330  OUString aSep = aOpt.GetFormulaSepArg();
331  OUString aSepArrayRow = aOpt.GetFormulaSepArrayRow();
332  OUString aSepArrayCol = aOpt.GetFormulaSepArrayCol();
333 
334  if (aSep.getLength() == 1 && aSepArrayRow.getLength() == 1 && aSepArrayCol.getLength() == 1)
335  {
336  // Each separator must be one character long.
337  mxEdSepFuncArg->set_text(aSep);
338  mxEdSepArrayCol->set_text(aSepArrayCol);
339  mxEdSepArrayRow->set_text(aSepArrayRow);
340 
341  mxEdSepFuncArg->save_value();
342  mxEdSepArrayCol->save_value();
343  mxEdSepArrayRow->save_value();
344  }
345  else
346  ResetSeparators();
347 
348  mxEdSepFuncArg->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() );
349  mxEdSepArrayCol->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() );
350  mxEdSepArrayRow->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
351  mxBtnSepReset->set_sensitive ( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() &&
352  !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() &&
353  !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
354 
355  // detailed calc settings.
356  ScFormulaOptions aDefaults;
357 
358  maSavedConfig = aOpt.GetCalcConfig();
359  bool bDefault = aDefaults.GetCalcConfig() == maSavedConfig;
361 
363 
365 }
366 
368 {
369  // What's this method for ?
370  return DeactivateRC::KeepPage;
371 }
372 
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsWriteCalcConfig() const
Definition: docoptio.hxx:101
bool IsValidSeparator(const OUString &rSep) const
Definition: tpformula.cxx:132
static void GetDefaultFormulaSeparators(OUString &rSepArg, OUString &rSepArrayCol, OUString &rSepArrayRow)
Definition: formulaopt.cxx:49
sal_Unicode mnDecSep
Definition: tpformula.hxx:66
ScCalcConfig maSavedConfig
Definition: tpformula.hxx:60
virtual bool FillItemSet(SfxItemSet *rCoreSet) override
Definition: tpformula.cxx:221
ScRecalcOptions GetODFRecalcOptions() const
Definition: formulaopt.hxx:65
void SetOOXMLRecalcOptions(ScRecalcOptions eOpt)
Definition: formulaopt.hxx:61
std::unique_ptr< weld::RadioButton > mxBtnCustomCalcDefault
Definition: tpformula.hxx:71
bool GetUseEnglishFuncName() const
Definition: formulaopt.hxx:47
ScDocOptions maSavedDocOptions
Definition: tpformula.hxx:63
std::unique_ptr< weld::Button > mxBtnSepReset
Definition: tpformula.hxx:78
std::unique_ptr< weld::RadioButton > mxBtnCustomCalcCustom
Definition: tpformula.hxx:72
const OUString & GetFormulaSepArrayRow() const
Definition: formulaopt.hxx:56
sal_uInt16 sal_Unicode
void SetFormulaSyntax(::formula::FormulaGrammar::Grammar eGram)
Definition: formulaopt.hxx:39
std::unique_ptr< weld::CheckButton > mxCbEnglishFuncName
Definition: tpformula.hxx:69
std::unique_ptr< weld::Entry > mxEdSepFuncArg
Definition: tpformula.hxx:75
const OUString & getNumDecimalSep() const
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:81
void LaunchCustomCalcSettings()
Definition: tpformula.cxx:122
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:76
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
ScCalcConfig maCurrentConfig
Definition: tpformula.hxx:61
void SetFormulaSepArrayCol(const OUString &rSep)
Definition: formulaopt.hxx:58
virtual void Reset(const SfxItemSet *rCoreSet) override
Definition: tpformula.cxx:285
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:68
ScDocOptions maCurrentDocOptions
Definition: tpformula.hxx:64
void SetCalcConfig(const ScCalcConfig &rConfig)
Definition: formulaopt.hxx:44
static SC_DLLPUBLIC const LocaleDataWrapper * getLocaleDataPtr()
Definition: global.cxx:1000
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
std::unique_ptr< weld::Entry > mxEdSepArrayRow
Definition: tpformula.hxx:77
weld::Window * GetFrameWeld() const
weld::Entry & rEdit
ScRecalcOptions GetOOXMLRecalcOptions() const
Definition: formulaopt.hxx:62
virtual ~ScTpFormulaOptions() override
Definition: tpformula.cxx:81
void OnFocusSeparatorInput(weld::Entry *pEdit)
Definition: tpformula.cxx:94
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
void UpdateCustomCalcRadioButtons(bool bDefault)
Definition: tpformula.cxx:106
RET_OK
ScTpFormulaOptions(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rCoreSet)
Definition: tpformula.cxx:34
void ResetSeparators()
Definition: tpformula.cxx:85
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:80
void SetWriteCalcConfig(bool bVal)
Definition: formulaopt.hxx:49
virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override
Definition: tpformula.cxx:367
IMPL_LINK(ScTpFormulaOptions, ButtonHdl, weld::Button &, rBtn, void)
Definition: tpformula.cxx:170
OUString maOldSepValue
Stores old separator value of currently focused separator edit box.
Definition: tpformula.hxx:58
std::unique_ptr< weld::Button > mxBtnCustomCalcDetails
Definition: tpformula.hxx:73
static std::unique_ptr< SfxTabPage > Create(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rCoreSet)
Definition: tpformula.cxx:216
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
void SetODFRecalcOptions(ScRecalcOptions eOpt)
Definition: formulaopt.hxx:64