cid#1607171 Data race condition
[LibreOffice.git] / sc / source / ui / StatisticsDialogs / FourierAnalysisDialog.cxx
blob94564358b9f0708646a1d142ac5ef0418ee859fe
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 */
11 #include <docsh.hxx>
12 #include <reffact.hxx>
13 #include <TableFillingAndNavigationTools.hxx>
14 #include <FourierAnalysisDialog.hxx>
15 #include <scresid.hxx>
16 #include <strings.hrc>
17 #include <o3tl/safeint.hxx>
19 ScFourierAnalysisDialog::ScFourierAnalysisDialog(SfxBindings* pSfxBindings,
20 SfxChildWindow* pChildWindow,
21 weld::Window* pParent, ScViewData& rViewData)
22 : ScStatisticsInputOutputDialog(pSfxBindings, pChildWindow, pParent, rViewData,
23 u"modules/scalc/ui/fourieranalysisdialog.ui"_ustr,
24 u"FourierAnalysisDialog"_ustr)
25 , maLabelAddr(ScAddress::INITIALIZE_INVALID)
26 , maActualInputRange(ScAddress::INITIALIZE_INVALID)
27 , mnLen(0)
28 , mfMinMag(0.0)
29 , mbUse3DAddresses(false)
30 , mbGroupedByColumn(true)
31 , mbWithLabels(false)
32 , mbInverse(false)
33 , mbPolar(false)
34 , mxWithLabelsCheckBox(m_xBuilder->weld_check_button(u"withlabels-check"_ustr))
35 , mxInverseCheckBox(m_xBuilder->weld_check_button(u"inverse-check"_ustr))
36 , mxPolarCheckBox(m_xBuilder->weld_check_button(u"polar-check"_ustr))
37 , mxMinMagnitudeField(m_xBuilder->weld_spin_button(u"minmagnitude-spin"_ustr))
38 , mxErrorMessage(m_xBuilder->weld_label(u"error-message"_ustr))
40 m_xDialog->set_title(ScResId(STR_FOURIER_ANALYSIS));
42 mxWithLabelsCheckBox->connect_toggled(LINK(this, ScFourierAnalysisDialog, CheckBoxHdl));
45 ScFourierAnalysisDialog::~ScFourierAnalysisDialog() {}
47 void ScFourierAnalysisDialog::Close()
49 DoClose(ScFourierAnalysisDialogWrapper::GetChildWindowId());
52 TranslateId ScFourierAnalysisDialog::GetUndoNameId() { return STR_FOURIER_ANALYSIS_UNDO_NAME; }
54 ScRange ScFourierAnalysisDialog::ApplyOutput(ScDocShell* pDocShell)
56 getOptions();
57 AddressWalkerWriter aOutput(mOutputAddress, pDocShell, mDocument,
58 formula::FormulaGrammar::mergeToGrammar(
59 formula::FormulaGrammar::GRAM_ENGLISH, mAddressDetails.eConv));
60 FormulaTemplate aTemplate(&mDocument);
61 aTemplate.autoReplaceUses3D(mbUse3DAddresses);
63 aOutput.writeBoldString(mbInverse ? ScResId(STR_INVERSE_FOURIER_TRANSFORM)
64 : ScResId(STR_FOURIER_TRANSFORM));
65 aOutput.newLine();
66 OUString aLabel;
67 getDataLabel(aLabel);
68 if (aLabel.startsWith("="))
69 aOutput.writeFormula(aLabel);
70 else
71 aOutput.writeString(aLabel);
73 aOutput.newLine();
74 // Components header
75 if (!mbPolar)
77 aOutput.writeString(ScResId(STR_REAL_PART));
78 aOutput.nextColumn();
79 aOutput.writeString(ScResId(STR_IMAGINARY_PART));
81 else
83 aOutput.writeString(ScResId(STR_MAGNITUDE_PART));
84 aOutput.nextColumn();
85 aOutput.writeString(ScResId(STR_PHASE_PART));
88 aOutput.newLine();
89 aTemplate.autoReplaceRange(u"%INPUTRANGE%"_ustr, maActualInputRange);
91 OUString aFormula;
92 genFormula(aFormula);
94 aTemplate.setTemplate(aFormula);
95 aOutput.writeMatrixFormula(aTemplate.getTemplate(), 2, mnLen);
97 return ScRange(aOutput.mMinimumAddress, aOutput.mMaximumAddress);
100 bool ScFourierAnalysisDialog::InputRangesValid()
102 if (!mInputRange.IsValid())
104 mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_INPUT_RANGE));
105 return false;
108 if (!mOutputAddress.IsValid())
110 mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_OUTPUT_ADDR));
111 return false;
114 mInputRange.PutInOrder();
116 mbGroupedByColumn = mGroupedBy == BY_COLUMN;
117 mbWithLabels = mxWithLabelsCheckBox->get_active();
119 mbUse3DAddresses = mInputRange.aStart.Tab() != mOutputAddress.Tab();
121 SCSIZE nRows = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
122 SCSIZE nCols = mInputRange.aEnd.Col() - mInputRange.aStart.Col() + 1;
124 SCSIZE nLen = mbGroupedByColumn ? nRows : nCols;
125 SCSIZE nComponents = mbGroupedByColumn ? nCols : nRows;
127 if (nComponents > 2)
129 OUString aMsg = mbGroupedByColumn ? ScResId(STR_MESSAGE_INVALID_NUMCOLS)
130 : ScResId(STR_MESSAGE_INVALID_NUMROWS);
131 mxErrorMessage->set_label(aMsg);
132 return false;
135 if (mbWithLabels && nLen < 2)
137 mxErrorMessage->set_label(ScResId(STR_MESSAGE_NODATA_IN_RANGE));
138 return false;
141 // Include space for writing the title, label and Real/Imaginary/Magnitude/Phase heading.
142 SCSIZE nLastOutputRow = mOutputAddress.Row() + nLen + 2;
143 if (mbWithLabels)
144 --nLastOutputRow;
146 if (nLastOutputRow > o3tl::make_unsigned(mDocument.MaxRow()))
148 mxErrorMessage->set_label(ScResId(STR_MESSAGE_OUTPUT_TOO_LONG));
149 return false;
152 ScAddress aActualStart(mInputRange.aStart);
154 if (mbWithLabels)
156 if (mbGroupedByColumn)
157 aActualStart.IncRow();
158 else
159 aActualStart.IncCol();
161 if (nComponents == 1)
162 maLabelAddr = mInputRange.aStart;
163 else
164 mbWithLabels = false;
166 mnLen = nLen - 1;
168 else
170 mnLen = nLen;
173 maActualInputRange = ScRange(aActualStart, mInputRange.aEnd);
174 mxErrorMessage->set_label(u""_ustr);
176 return true;
179 void ScFourierAnalysisDialog::getOptions()
181 mbInverse = mxInverseCheckBox->get_active();
182 mbPolar = mxPolarCheckBox->get_active();
184 sal_Int32 nDeciBels = static_cast<sal_Int32>(mxMinMagnitudeField->get_value());
185 if (nDeciBels <= -150)
186 mfMinMag = 0.0;
187 else
188 mfMinMag = pow(10.0, static_cast<double>(nDeciBels) / 10.0);
191 void ScFourierAnalysisDialog::getDataLabel(OUString& rLabel)
193 if (mbWithLabels)
195 rLabel = "="
196 + maLabelAddr.Format(mbUse3DAddresses ? ScRefFlags::ADDR_ABS_3D
197 : ScRefFlags::ADDR_ABS,
198 &mDocument, mAddressDetails);
200 return;
203 OUString aDataSrc(mInputRange.Format(
204 mDocument, mbUse3DAddresses ? ScRefFlags::RANGE_ABS_3D : ScRefFlags::RANGE_ABS,
205 mAddressDetails));
207 rLabel = ScResId(STR_INPUT_DATA_RANGE) + " : " + aDataSrc;
208 return;
211 void ScFourierAnalysisDialog::genFormula(OUString& rFormula)
213 static constexpr OUString aSep(u";"_ustr);
215 if (!mbPolar)
217 rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
218 + OUString::boolean(mbInverse) + ")";
219 return;
222 rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
223 + OUString::boolean(mbInverse) + ";true;" + OUString::number(mfMinMag) + ")";
226 IMPL_LINK_NOARG(ScFourierAnalysisDialog, CheckBoxHdl, weld::Toggleable&, void)
228 ValidateDialogInput();
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */