1
0
Fork 0
libreoffice/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

231 lines
7.1 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#include <docsh.hxx>
#include <reffact.hxx>
#include <TableFillingAndNavigationTools.hxx>
#include <FourierAnalysisDialog.hxx>
#include <scresid.hxx>
#include <strings.hrc>
#include <o3tl/safeint.hxx>
ScFourierAnalysisDialog::ScFourierAnalysisDialog(SfxBindings* pSfxBindings,
SfxChildWindow* pChildWindow,
weld::Window* pParent, ScViewData& rViewData)
: ScStatisticsInputOutputDialog(pSfxBindings, pChildWindow, pParent, rViewData,
u"modules/scalc/ui/fourieranalysisdialog.ui"_ustr,
u"FourierAnalysisDialog"_ustr)
, maLabelAddr(ScAddress::INITIALIZE_INVALID)
, maActualInputRange(ScAddress::INITIALIZE_INVALID)
, mnLen(0)
, mfMinMag(0.0)
, mbUse3DAddresses(false)
, mbGroupedByColumn(true)
, mbWithLabels(false)
, mbInverse(false)
, mbPolar(false)
, mxWithLabelsCheckBox(m_xBuilder->weld_check_button(u"withlabels-check"_ustr))
, mxInverseCheckBox(m_xBuilder->weld_check_button(u"inverse-check"_ustr))
, mxPolarCheckBox(m_xBuilder->weld_check_button(u"polar-check"_ustr))
, mxMinMagnitudeField(m_xBuilder->weld_spin_button(u"minmagnitude-spin"_ustr))
, mxErrorMessage(m_xBuilder->weld_label(u"error-message"_ustr))
{
m_xDialog->set_title(ScResId(STR_FOURIER_ANALYSIS));
mxWithLabelsCheckBox->connect_toggled(LINK(this, ScFourierAnalysisDialog, CheckBoxHdl));
}
ScFourierAnalysisDialog::~ScFourierAnalysisDialog() {}
void ScFourierAnalysisDialog::Close()
{
DoClose(ScFourierAnalysisDialogWrapper::GetChildWindowId());
}
TranslateId ScFourierAnalysisDialog::GetUndoNameId() { return STR_FOURIER_ANALYSIS_UNDO_NAME; }
ScRange ScFourierAnalysisDialog::ApplyOutput(ScDocShell* pDocShell)
{
getOptions();
AddressWalkerWriter aOutput(mOutputAddress, pDocShell, mDocument,
formula::FormulaGrammar::mergeToGrammar(
formula::FormulaGrammar::GRAM_ENGLISH, mAddressDetails.eConv));
FormulaTemplate aTemplate(&mDocument);
aTemplate.autoReplaceUses3D(mbUse3DAddresses);
aOutput.writeBoldString(mbInverse ? ScResId(STR_INVERSE_FOURIER_TRANSFORM)
: ScResId(STR_FOURIER_TRANSFORM));
aOutput.newLine();
OUString aLabel;
getDataLabel(aLabel);
if (aLabel.startsWith("="))
aOutput.writeFormula(aLabel);
else
aOutput.writeString(aLabel);
aOutput.newLine();
// Components header
if (!mbPolar)
{
aOutput.writeString(ScResId(STR_REAL_PART));
aOutput.nextColumn();
aOutput.writeString(ScResId(STR_IMAGINARY_PART));
}
else
{
aOutput.writeString(ScResId(STR_MAGNITUDE_PART));
aOutput.nextColumn();
aOutput.writeString(ScResId(STR_PHASE_PART));
}
aOutput.newLine();
aTemplate.autoReplaceRange(u"%INPUTRANGE%"_ustr, maActualInputRange);
OUString aFormula;
genFormula(aFormula);
aTemplate.setTemplate(aFormula);
aOutput.writeMatrixFormula(aTemplate.getTemplate(), 2, mnLen);
return ScRange(aOutput.mMinimumAddress, aOutput.mMaximumAddress);
}
bool ScFourierAnalysisDialog::InputRangesValid()
{
if (!mInputRange.IsValid())
{
mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_INPUT_RANGE));
return false;
}
if (!mOutputAddress.IsValid())
{
mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_OUTPUT_ADDR));
return false;
}
mInputRange.PutInOrder();
mbGroupedByColumn = mGroupedBy == BY_COLUMN;
mbWithLabels = mxWithLabelsCheckBox->get_active();
mbUse3DAddresses = mInputRange.aStart.Tab() != mOutputAddress.Tab();
SCSIZE nRows = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
SCSIZE nCols = mInputRange.aEnd.Col() - mInputRange.aStart.Col() + 1;
SCSIZE nLen = mbGroupedByColumn ? nRows : nCols;
SCSIZE nComponents = mbGroupedByColumn ? nCols : nRows;
if (nComponents > 2)
{
OUString aMsg = mbGroupedByColumn ? ScResId(STR_MESSAGE_INVALID_NUMCOLS)
: ScResId(STR_MESSAGE_INVALID_NUMROWS);
mxErrorMessage->set_label(aMsg);
return false;
}
if (mbWithLabels && nLen < 2)
{
mxErrorMessage->set_label(ScResId(STR_MESSAGE_NODATA_IN_RANGE));
return false;
}
// Include space for writing the title, label and Real/Imaginary/Magnitude/Phase heading.
SCSIZE nLastOutputRow = mOutputAddress.Row() + nLen + 2;
if (mbWithLabels)
--nLastOutputRow;
if (nLastOutputRow > o3tl::make_unsigned(mDocument.MaxRow()))
{
mxErrorMessage->set_label(ScResId(STR_MESSAGE_OUTPUT_TOO_LONG));
return false;
}
ScAddress aActualStart(mInputRange.aStart);
if (mbWithLabels)
{
if (mbGroupedByColumn)
aActualStart.IncRow();
else
aActualStart.IncCol();
if (nComponents == 1)
maLabelAddr = mInputRange.aStart;
else
mbWithLabels = false;
mnLen = nLen - 1;
}
else
{
mnLen = nLen;
}
maActualInputRange = ScRange(aActualStart, mInputRange.aEnd);
mxErrorMessage->set_label(u""_ustr);
return true;
}
void ScFourierAnalysisDialog::getOptions()
{
mbInverse = mxInverseCheckBox->get_active();
mbPolar = mxPolarCheckBox->get_active();
sal_Int32 nDeciBels = static_cast<sal_Int32>(mxMinMagnitudeField->get_value());
if (nDeciBels <= -150)
mfMinMag = 0.0;
else
mfMinMag = pow(10.0, static_cast<double>(nDeciBels) / 10.0);
}
void ScFourierAnalysisDialog::getDataLabel(OUString& rLabel)
{
if (mbWithLabels)
{
rLabel = "="
+ maLabelAddr.Format(mbUse3DAddresses ? ScRefFlags::ADDR_ABS_3D
: ScRefFlags::ADDR_ABS,
&mDocument, mAddressDetails);
return;
}
OUString aDataSrc(mInputRange.Format(
mDocument, mbUse3DAddresses ? ScRefFlags::RANGE_ABS_3D : ScRefFlags::RANGE_ABS,
mAddressDetails));
rLabel = ScResId(STR_INPUT_DATA_RANGE) + " : " + aDataSrc;
return;
}
void ScFourierAnalysisDialog::genFormula(OUString& rFormula)
{
static constexpr OUString aSep(u";"_ustr);
if (!mbPolar)
{
rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
+ OUString::boolean(mbInverse) + ")";
return;
}
rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
+ OUString::boolean(mbInverse) + ";true;" + OUString::number(mfMinMag) + ")";
}
IMPL_LINK_NOARG(ScFourierAnalysisDialog, CheckBoxHdl, weld::Toggleable&, void)
{
ValidateDialogInput();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */