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 = rCoreAttrs.Get(SID_SCDOCOPTIONS).GetDocOptions();
80}
81
83{
84}
85
87{
88 OUString aFuncArg, aArrayCol, aArrayRow;
89 ScFormulaOptions::GetDefaultFormulaSeparators(aFuncArg, aArrayCol, aArrayRow);
90 mxEdSepFuncArg->set_text(aFuncArg);
91 mxEdSepArrayCol->set_text(aArrayCol);
92 mxEdSepArrayRow->set_text(aArrayRow);
93}
94
96{
97 if (!pEdit)
98 return;
99
100 // Make sure the entire text is selected.
101 pEdit->select_region(0, -1);
102 OUString sSepValue = pEdit->get_text();
103 if (!sSepValue.isEmpty())
104 maOldSepValue = sSepValue;
105}
106
108{
109 if (bDefault)
110 {
111 mxBtnCustomCalcDefault->set_active(true);
112 mxBtnCustomCalcCustom->set_active(false);
113 mxBtnCustomCalcDetails->set_sensitive(false);
114 }
115 else
116 {
117 mxBtnCustomCalcDefault->set_active(false);
118 mxBtnCustomCalcCustom->set_active(true);
119 mxBtnCustomCalcDetails->set_sensitive(true);
120 }
121}
122
124{
126 if (aDlg.run() == RET_OK)
127 {
128 maCurrentConfig = aDlg.GetConfig();
130 }
131}
132
133bool ScTpFormulaOptions::IsValidSeparator(std::u16string_view aSep, bool bArray) const
134{
135 if (aSep.size() != 1)
136 // Must be one-character long.
137 return false;
138
139 const sal_Unicode c = aSep[0];
140
141 if (c == mnDecSep)
142 // decimal separator is not allowed.
143 return false;
144
145 if (c <= 0x20 || c == 0x7f)
146 // Disallow non-printables including space and DEL.
147 return false;
148
149 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9'))
150 // Disallow alphanumeric.
151 return false;
152
153 if (bArray)
154 {
155 switch (c)
156 {
157 case '+':
158 case '-':
159 case '{':
160 case '}':
161 case '"':
162 // All following just to prevent confusion, they are not
163 // evaluated in inline arrays and theoretically would be
164 // possible.
165 case '%':
166 case '/':
167 case '*':
168 case '=':
169 case '<':
170 case '>':
171 case '[':
172 case ']':
173 case '(':
174 case ')':
175 case '\'':
176 // Disallowed characters. Anything else we want to disallow ?
177 return false;
178 }
179 }
180 else if (c <= 0x7f)
181 {
182 switch (c)
183 {
184 default:
185 // Anything bad except the knowns.
186 return false;
187 case ';':
188 case ',':
189 ; // nothing
190 }
191 }
192 else
193 {
194 // Any Unicode character, would have to ask the compiler's localized
195 // symbol map whether it's a known symbol but not a separator
196 // (ocSep,ocArrayRowSep,ocArrayColSep), which we're about to set here.
197 // But really..
198 return false;
199 }
200
201 return true;
202}
203
204IMPL_LINK( ScTpFormulaOptions, ButtonHdl, weld::Button&, rBtn, void )
205{
206 if (&rBtn == mxBtnSepReset.get())
207 ResetSeparators();
208 else if (&rBtn == mxBtnCustomCalcDetails.get())
209 LaunchCustomCalcSettings();
210}
211
213{
214 if (!rBtn.get_active())
215 return;
216 if (mxBtnCustomCalcDefault->get_active())
217 UpdateCustomCalcRadioButtons(true);
218 else if (mxBtnCustomCalcCustom->get_active())
219 UpdateCustomCalcRadioButtons(false);
220}
221
222IMPL_LINK(ScTpFormulaOptions, SepInsertTextHdl, OUString&, rTest, bool)
223{
224 if (!IsValidSeparator(rTest, false) && !maOldSepValue.isEmpty())
225 // Invalid separator. Restore the old value.
226 rTest = maOldSepValue;
227 return true;
228}
229
230IMPL_LINK(ScTpFormulaOptions, RowSepInsertTextHdl, OUString&, rTest, bool)
231{
232 // Invalid separator or same as ColStr - Restore the old value.
233 if ((!IsValidSeparator(rTest, true) || rTest == mxEdSepArrayCol->get_text()) && !maOldSepValue.isEmpty())
234 rTest = maOldSepValue;
235 return true;
236}
237
238IMPL_LINK(ScTpFormulaOptions, ColSepInsertTextHdl, OUString&, rTest, bool)
239{
240 // Invalid separator or same as RowStr - Restore the old value.
241 if ((!IsValidSeparator(rTest, true) || rTest == mxEdSepArrayRow->get_text()) && !maOldSepValue.isEmpty())
242 rTest = maOldSepValue;
243 return true;
244}
245
246IMPL_LINK( ScTpFormulaOptions, SepModifyHdl, weld::Entry&, rEdit, void )
247{
248 OnFocusSeparatorInput(&rEdit);
249}
250
251IMPL_LINK( ScTpFormulaOptions, SepEditOnFocusHdl, weld::Widget&, rControl, void )
252{
253 OnFocusSeparatorInput(dynamic_cast<weld::Entry*>(&rControl));
254}
255
256std::unique_ptr<SfxTabPage> ScTpFormulaOptions::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rCoreSet)
257{
258 return std::make_unique<ScTpFormulaOptions>(pPage, pController, *rCoreSet);
259}
260
262{
263 bool bRet = false;
264 ScFormulaOptions aOpt;
265 bool bEnglishFuncName = mxCbEnglishFuncName->get_active();
266 sal_Int16 aSyntaxPos = mxLbFormulaSyntax->get_active();
267 OUString aSep = mxEdSepFuncArg->get_text();
268 OUString aSepArrayCol = mxEdSepArrayCol->get_text();
269 OUString aSepArrayRow = mxEdSepArrayRow->get_text();
270 sal_Int16 nOOXMLRecalcMode = mxLbOOXMLRecalcOptions->get_active();
271 sal_Int16 nODFRecalcMode = mxLbODFRecalcOptions->get_active();
272
273 if (mxBtnCustomCalcDefault->get_active())
274 {
275 // When Default is selected, reset all the calc config settings to default.
277 }
278
279 if ( mxLbFormulaSyntax->get_saved_value() != mxLbFormulaSyntax->get_text(aSyntaxPos)
280 || mxCbEnglishFuncName->get_saved_state() != (bEnglishFuncName ? 1 : 0)
281 || mxEdSepFuncArg->get_saved_value() != aSep
282 || mxEdSepArrayCol->get_saved_value() != aSepArrayCol
283 || mxEdSepArrayRow->get_saved_value() != aSepArrayRow
284 || mxLbOOXMLRecalcOptions->get_saved_value() != mxLbOOXMLRecalcOptions->get_text(nOOXMLRecalcMode)
285 || mxLbODFRecalcOptions->get_saved_value() != mxLbODFRecalcOptions->get_text(nODFRecalcMode)
288 {
290
291 switch (aSyntaxPos)
292 {
293 case 0:
295 break;
296 case 1:
298 break;
299 case 2:
301 break;
302 }
303
304 ScRecalcOptions eOOXMLRecalc = static_cast<ScRecalcOptions>(nOOXMLRecalcMode);
305 ScRecalcOptions eODFRecalc = static_cast<ScRecalcOptions>(nODFRecalcMode);
306
307 aOpt.SetFormulaSyntax(eGram);
308 aOpt.SetUseEnglishFuncName(bEnglishFuncName);
309 aOpt.SetFormulaSepArg(aSep);
310 aOpt.SetFormulaSepArrayCol(aSepArrayCol);
311 aOpt.SetFormulaSepArrayRow(aSepArrayRow);
313 aOpt.SetOOXMLRecalcOptions(eOOXMLRecalc);
314 aOpt.SetODFRecalcOptions(eODFRecalc);
316
317 rCoreSet->Put( ScTpFormulaItem( std::move(aOpt) ) );
318 rCoreSet->Put( ScTpCalcItem( SID_SCDOCOPTIONS, maCurrentDocOptions ) );
319
320 bRet = true;
321 }
322 return bRet;
323}
324
326{
327 ScFormulaOptions aOpt;
328 if(const ScTpFormulaItem* pItem = rCoreSet->GetItemIfSet(SID_SCFORMULAOPTIONS, false))
329 aOpt = pItem->GetFormulaOptions();
330
331 // formula grammar.
333
334 switch (eGram)
335 {
336 case ::formula::FormulaGrammar::GRAM_NATIVE:
337 mxLbFormulaSyntax->set_active(0);
338 break;
339 case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1:
340 mxLbFormulaSyntax->set_active(1);
341 break;
342 case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1:
343 mxLbFormulaSyntax->set_active(2);
344 break;
345 default:
346 mxLbFormulaSyntax->set_active(0);
347 }
348
349 mxLbFormulaSyntax->save_value();
350 mxLbFormulaSyntax->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::Grammar::isReadOnly() );
351
352 ScRecalcOptions eOOXMLRecalc = aOpt.GetOOXMLRecalcOptions();
353 mxLbOOXMLRecalcOptions->set_active(static_cast<sal_uInt16>(eOOXMLRecalc));
354 mxLbOOXMLRecalcOptions->save_value();
355 mxLbOOXMLRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::isReadOnly() );
356
357 ScRecalcOptions eODFRecalc = aOpt.GetODFRecalcOptions();
358 mxLbODFRecalcOptions->set_active(static_cast<sal_uInt16>(eODFRecalc));
359 mxLbODFRecalcOptions->save_value();
360 mxLbODFRecalcOptions->set_sensitive( !officecfg::Office::Calc::Formula::Load::ODFRecalcMode::isReadOnly() );
361
362 // english function name.
363 mxCbEnglishFuncName->set_active( aOpt.GetUseEnglishFuncName() );
364 mxCbEnglishFuncName->save_state();
365 mxCbEnglishFuncName->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::EnglishFunctionName::isReadOnly() );
366
367 // Separators
368 OUString aSep = aOpt.GetFormulaSepArg();
369 OUString aSepArrayRow = aOpt.GetFormulaSepArrayRow();
370 OUString aSepArrayCol = aOpt.GetFormulaSepArrayCol();
371
372 if (IsValidSeparator(aSep, false) && IsValidSeparator(aSepArrayRow, true) && IsValidSeparator(aSepArrayCol, true))
373 {
374 // Each and all separators must be valid.
375 mxEdSepFuncArg->set_text(aSep);
376 mxEdSepArrayCol->set_text(aSepArrayCol);
377 mxEdSepArrayRow->set_text(aSepArrayRow);
378
379 mxEdSepFuncArg->save_value();
380 mxEdSepArrayCol->save_value();
381 mxEdSepArrayRow->save_value();
382 }
383 else
385
386 mxEdSepFuncArg->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() );
387 mxEdSepArrayCol->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() );
388 mxEdSepArrayRow->set_sensitive( !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
389 mxBtnSepReset->set_sensitive ( !officecfg::Office::Calc::Formula::Syntax::SeparatorArg::isReadOnly() &&
390 !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayCol::isReadOnly() &&
391 !officecfg::Office::Calc::Formula::Syntax::SeparatorArrayRow::isReadOnly() );
392
393 // detailed calc settings.
394 ScFormulaOptions aDefaults;
395
397 bool bDefault = aDefaults.GetCalcConfig() == maSavedConfig;
399
401
403}
404
406{
407 // What's this method for ?
408 return DeactivateRC::KeepPage;
409}
410
411/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScRecalcOptions
Definition: calcconfig.hxx:24
const OUString & getNumDecimalSep() const
bool GetWriteCalcConfig() const
const ScCalcConfig & GetConfig() const
bool IsWriteCalcConfig() const
Definition: docoptio.hxx:101
void SetWriteCalcConfig(bool bVal)
Definition: docoptio.hxx:100
void SetFormulaSepArrayRow(const OUString &rSep)
Definition: formulaopt.hxx:55
const OUString & GetFormulaSepArg() const
Definition: formulaopt.hxx:53
void SetUseEnglishFuncName(bool bVal)
Definition: formulaopt.hxx:46
void SetFormulaSepArrayCol(const OUString &rSep)
Definition: formulaopt.hxx:58
void SetFormulaSyntax(::formula::FormulaGrammar::Grammar eGram)
Definition: formulaopt.hxx:39
ScCalcConfig & GetCalcConfig()
Definition: formulaopt.hxx:42
void SetOOXMLRecalcOptions(ScRecalcOptions eOpt)
Definition: formulaopt.hxx:61
const OUString & GetFormulaSepArrayCol() const
Definition: formulaopt.hxx:59
void SetWriteCalcConfig(bool bVal)
Definition: formulaopt.hxx:49
bool GetUseEnglishFuncName() const
Definition: formulaopt.hxx:47
ScRecalcOptions GetOOXMLRecalcOptions() const
Definition: formulaopt.hxx:62
::formula::FormulaGrammar::Grammar GetFormulaSyntax() const
Definition: formulaopt.hxx:40
void SetCalcConfig(const ScCalcConfig &rConfig)
Definition: formulaopt.hxx:44
void SetFormulaSepArg(const OUString &rSep)
Definition: formulaopt.hxx:52
const OUString & GetFormulaSepArrayRow() const
Definition: formulaopt.hxx:56
static void GetDefaultFormulaSeparators(OUString &rSepArg, OUString &rSepArrayCol, OUString &rSepArrayRow)
Definition: formulaopt.cxx:50
ScRecalcOptions GetODFRecalcOptions() const
Definition: formulaopt.hxx:65
void SetODFRecalcOptions(ScRecalcOptions eOpt)
Definition: formulaopt.hxx:64
static SC_DLLPUBLIC const LocaleDataWrapper & getLocaleData()
Definition: global.cxx:1055
std::unique_ptr< weld::Entry > mxEdSepArrayCol
Definition: tpformula.hxx:77
static std::unique_ptr< SfxTabPage > Create(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet *rCoreSet)
Definition: tpformula.cxx:256
sal_Unicode mnDecSep
Definition: tpformula.hxx:67
std::unique_ptr< weld::ComboBox > mxLbFormulaSyntax
Definition: tpformula.hxx:69
std::unique_ptr< weld::RadioButton > mxBtnCustomCalcCustom
Definition: tpformula.hxx:73
ScCalcConfig maCurrentConfig
Definition: tpformula.hxx:62
bool IsValidSeparator(std::u16string_view aSep, bool bArray) const
Definition: tpformula.cxx:133
std::unique_ptr< weld::Button > mxBtnSepReset
Definition: tpformula.hxx:79
virtual ~ScTpFormulaOptions() override
Definition: tpformula.cxx:82
virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override
Definition: tpformula.cxx:405
ScTpFormulaOptions(weld::Container *pPage, weld::DialogController *pController, const SfxItemSet &rCoreSet)
Definition: tpformula.cxx:34
ScCalcConfig maSavedConfig
Definition: tpformula.hxx:61
void UpdateCustomCalcRadioButtons(bool bDefault)
Definition: tpformula.cxx:107
void ResetSeparators()
Definition: tpformula.cxx:86
std::unique_ptr< weld::ComboBox > mxLbODFRecalcOptions
Definition: tpformula.hxx:82
virtual bool FillItemSet(SfxItemSet *rCoreSet) override
Definition: tpformula.cxx:261
std::unique_ptr< weld::Button > mxBtnCustomCalcDetails
Definition: tpformula.hxx:74
void OnFocusSeparatorInput(weld::Entry *pEdit)
Definition: tpformula.cxx:95
ScDocOptions maCurrentDocOptions
Definition: tpformula.hxx:65
void LaunchCustomCalcSettings()
Definition: tpformula.cxx:123
std::unique_ptr< weld::Entry > mxEdSepFuncArg
Definition: tpformula.hxx:76
std::unique_ptr< weld::CheckButton > mxCbEnglishFuncName
Definition: tpformula.hxx:70
std::unique_ptr< weld::ComboBox > mxLbOOXMLRecalcOptions
Definition: tpformula.hxx:81
std::unique_ptr< weld::Entry > mxEdSepArrayRow
Definition: tpformula.hxx:78
ScDocOptions maSavedDocOptions
Definition: tpformula.hxx:64
virtual void Reset(const SfxItemSet *rCoreSet) override
Definition: tpformula.cxx:325
std::unique_ptr< weld::RadioButton > mxBtnCustomCalcDefault
Definition: tpformula.hxx:72
OUString maOldSepValue
Stores old separator value of currently focused separator edit box.
Definition: tpformula.hxx:59
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
weld::Window * GetFrameWeld() const
virtual short run()
virtual void select_region(int nStartPos, int nEndPos)=0
virtual OUString get_text() const=0
float u
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
DeactivateRC
IMPL_LINK(ScTpFormulaOptions, ButtonHdl, weld::Button &, rBtn, void)
Definition: tpformula.cxx:204
sal_uInt16 sal_Unicode
RET_OK