File indexing completed on 2024-05-12 15:28:17
0001 /*************************************************************************** 0002 File : FitOptionsWidget.cc 0003 Project : LabPlot 0004 Description : widget for editing advanced fit options 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2014-2020 Alexander Semke (alexander.semke@web.de) 0007 Copyright : (C) 2017-2018 Stefan Gerlach (stefan.gerlach@uni.kn) 0008 0009 ***************************************************************************/ 0010 0011 /*************************************************************************** 0012 * * 0013 * This program is free software; you can redistribute it and/or modify * 0014 * it under the terms of the GNU General Public License as published by * 0015 * the Free Software Foundation; either version 2 of the License, or * 0016 * (at your option) any later version. * 0017 * * 0018 * This program is distributed in the hope that it will be useful, * 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0021 * GNU General Public License for more details. * 0022 * * 0023 * You should have received a copy of the GNU General Public License * 0024 * along with this program; if not, write to the Free Software * 0025 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0026 * Boston, MA 02110-1301 USA * 0027 * * 0028 ***************************************************************************/ 0029 #include "FitOptionsWidget.h" 0030 #include "backend/worksheet/plots/cartesian/CartesianPlot.h" 0031 0032 /*! 0033 \class FitOptionsWidget 0034 \brief Widget for editing advanced fit options. 0035 0036 \ingroup kdefrontend 0037 */ 0038 FitOptionsWidget::FitOptionsWidget(QWidget* parent, XYFitCurve::FitData* fitData, XYFitCurve* fitCurve) : QWidget(parent), 0039 m_fitData(fitData), m_fitCurve(fitCurve) { 0040 ui.setupUi(this); 0041 ui.pbApply->setIcon(QIcon::fromTheme("dialog-ok-apply")); 0042 ui.pbCancel->setIcon(QIcon::fromTheme("dialog-cancel")); 0043 0044 //TODO: show "robust" option when robust fitting is possible 0045 // ui.cbRobust->addItem(i18n("on")); 0046 // ui.cbRobust->addItem(i18n("off")); 0047 ui.lRobust->setVisible(false); 0048 ui.cbRobust->setVisible(false); 0049 0050 ui.leMaxIterations->setValidator( new QIntValidator(ui.leMaxIterations) ); 0051 ui.leEps->setValidator( new QDoubleValidator(ui.leEps) ); 0052 ui.leEvaluatedPoints->setValidator( new QIntValidator(ui.leEvaluatedPoints) ); 0053 0054 SET_NUMBER_LOCALE 0055 ui.leMaxIterations->setText(numberLocale.toString(m_fitData->maxIterations)); 0056 ui.leEps->setText(numberLocale.toString(m_fitData->eps)); 0057 ui.leEvaluatedPoints->setText(numberLocale.toString(static_cast<qulonglong>(m_fitData->evaluatedPoints))); 0058 ui.sbConfidenceInterval->setLocale(numberLocale); 0059 0060 //range widgets 0061 const auto* plot = static_cast<const CartesianPlot*>(fitCurve->parentAspect()); 0062 m_dateTimeRange = (plot->xRangeFormat() != CartesianPlot::RangeFormat::Numeric); 0063 if (!m_dateTimeRange) { 0064 ui.leMin->setText(numberLocale.toString(m_fitData->fitRange.min())); 0065 ui.leMax->setText(numberLocale.toString(m_fitData->fitRange.max())); 0066 ui.leEvalMin->setText(numberLocale.toString(m_fitData->evalRange.min())); 0067 ui.leEvalMax->setText(numberLocale.toString(m_fitData->evalRange.max())); 0068 } else { 0069 ui.dateTimeEditMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->fitRange.min()) ); 0070 ui.dateTimeEditMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->fitRange.max()) ); 0071 ui.dateTimeEditEvalMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->evalRange.min()) ); 0072 ui.dateTimeEditEvalMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->evalRange.max()) ); 0073 } 0074 0075 ui.leMin->setVisible(!m_dateTimeRange); 0076 ui.leMax->setVisible(!m_dateTimeRange); 0077 ui.lXRange->setVisible(!m_dateTimeRange); 0078 ui.leEvalMin->setVisible(!m_dateTimeRange); 0079 ui.leEvalMax->setVisible(!m_dateTimeRange); 0080 ui.lEvalRange->setVisible(!m_dateTimeRange); 0081 ui.dateTimeEditMin->setVisible(m_dateTimeRange); 0082 ui.dateTimeEditMax->setVisible(m_dateTimeRange); 0083 ui.lXRangeDateTime->setVisible(m_dateTimeRange); 0084 ui.dateTimeEditEvalMin->setVisible(m_dateTimeRange); 0085 ui.dateTimeEditEvalMax->setVisible(m_dateTimeRange); 0086 ui.lEvalRangeDateTime->setVisible(m_dateTimeRange); 0087 0088 //auto range 0089 ui.cbAutoRange->setChecked(m_fitData->autoRange); 0090 ui.cbAutoEvalRange->setChecked(m_fitData->autoEvalRange); 0091 this->autoRangeChanged(); 0092 this->autoEvalRangeChanged(); 0093 0094 ui.cbUseDataErrors->setChecked(m_fitData->useDataErrors); 0095 ui.cbUseResults->setChecked(m_fitData->useResults); 0096 ui.cbPreview->setChecked(m_fitData->previewEnabled); 0097 ui.sbConfidenceInterval->setValue(m_fitData->confidenceInterval); 0098 0099 //SLOTS 0100 connect(ui.leEps, &QLineEdit::textChanged, this, &FitOptionsWidget::changed); 0101 connect(ui.leMaxIterations, &QLineEdit::textChanged, this, &FitOptionsWidget::changed); 0102 connect(ui.leEvaluatedPoints, &QLineEdit::textChanged, this, &FitOptionsWidget::changed); 0103 connect(ui.cbUseDataErrors, &QCheckBox::clicked, this, &FitOptionsWidget::changed); 0104 connect(ui.cbUseResults, &QCheckBox::clicked, this, &FitOptionsWidget::changed); 0105 connect(ui.cbPreview, &QCheckBox::clicked, this, &FitOptionsWidget::changed); 0106 connect(ui.sbConfidenceInterval, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &FitOptionsWidget::changed); 0107 connect(ui.pbApply, &QPushButton::clicked, this, &FitOptionsWidget::applyClicked); 0108 connect(ui.pbCancel, &QPushButton::clicked, this, &FitOptionsWidget::finished); 0109 connect(ui.cbAutoRange, &QCheckBox::clicked, this, &FitOptionsWidget::autoRangeChanged); 0110 connect(ui.cbAutoEvalRange, &QCheckBox::clicked, this, &FitOptionsWidget::autoEvalRangeChanged); 0111 connect(ui.leMin, &QLineEdit::textChanged, this, &FitOptionsWidget::fitRangeMinChanged); 0112 connect(ui.leMax, &QLineEdit::textChanged, this, &FitOptionsWidget::fitRangeMaxChanged); 0113 connect(ui.dateTimeEditMin, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::fitRangeMinDateTimeChanged); 0114 connect(ui.dateTimeEditMax, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::fitRangeMaxDateTimeChanged); 0115 connect(ui.leEvalMin, &QLineEdit::textChanged, this, &FitOptionsWidget::evalRangeMinChanged); 0116 connect(ui.leEvalMax, &QLineEdit::textChanged, this, &FitOptionsWidget::evalRangeMaxChanged); 0117 connect(ui.dateTimeEditEvalMin, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::evalRangeMinDateTimeChanged); 0118 connect(ui.dateTimeEditEvalMax, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::evalRangeMaxDateTimeChanged); 0119 } 0120 0121 void FitOptionsWidget::autoRangeChanged() { 0122 const bool autoRange = ui.cbAutoRange->isChecked(); 0123 m_fitData->autoRange = autoRange; 0124 0125 ui.leMin->setEnabled(!autoRange); 0126 ui.lXRange->setEnabled(!autoRange); 0127 ui.leMax->setEnabled(!autoRange); 0128 ui.dateTimeEditMin->setEnabled(!autoRange); 0129 ui.lXRange->setEnabled(!autoRange); 0130 ui.dateTimeEditMax->setEnabled(!autoRange); 0131 0132 if (autoRange) { 0133 const AbstractColumn* xDataColumn = nullptr; 0134 if (m_fitCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) 0135 xDataColumn = m_fitCurve->xDataColumn(); 0136 else { 0137 if (m_fitCurve->dataSourceCurve()) 0138 xDataColumn = m_fitCurve->dataSourceCurve()->xColumn(); 0139 } 0140 0141 if (xDataColumn) { 0142 const double xMin = xDataColumn->minimum(); 0143 const double xMax = xDataColumn->maximum(); 0144 m_fitData->fitRange.setRange(xMin, xMax); 0145 0146 SET_NUMBER_LOCALE 0147 if (!m_dateTimeRange) { 0148 ui.leMin->setText(numberLocale.toString(xMin)); 0149 ui.leMax->setText(numberLocale.toString(xMax)); 0150 } else { 0151 ui.dateTimeEditMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xMin)); 0152 ui.dateTimeEditMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xMax)); 0153 } 0154 } 0155 } 0156 } 0157 0158 void FitOptionsWidget::autoEvalRangeChanged() { 0159 const bool autoRange = ui.cbAutoEvalRange->isChecked(); 0160 m_fitData->autoEvalRange = autoRange; 0161 0162 ui.leEvalMin->setEnabled(!autoRange); 0163 ui.lEvalRange->setEnabled(!autoRange); 0164 ui.leEvalMax->setEnabled(!autoRange); 0165 ui.dateTimeEditEvalMin->setEnabled(!autoRange); 0166 ui.lEvalRange->setEnabled(!autoRange); 0167 ui.dateTimeEditEvalMax->setEnabled(!autoRange); 0168 0169 if (autoRange) { 0170 const AbstractColumn* xDataColumn = nullptr; 0171 if (m_fitCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) 0172 xDataColumn = m_fitCurve->xDataColumn(); 0173 else { 0174 if (m_fitCurve->dataSourceCurve()) 0175 xDataColumn = m_fitCurve->dataSourceCurve()->xColumn(); 0176 } 0177 0178 if (xDataColumn) { 0179 const double xMin = xDataColumn->minimum(); 0180 const double xMax = xDataColumn->maximum(); 0181 m_fitData->evalRange.setRange(xMin, xMax); 0182 0183 SET_NUMBER_LOCALE 0184 if (!m_dateTimeRange) { 0185 ui.leEvalMin->setText(numberLocale.toString(xMin)); 0186 ui.leEvalMax->setText(numberLocale.toString(xMax)); 0187 } else { 0188 ui.dateTimeEditEvalMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xMin)); 0189 ui.dateTimeEditEvalMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xMax)); 0190 } 0191 } 0192 } 0193 } 0194 0195 void FitOptionsWidget::fitRangeMinChanged() { 0196 SET_DOUBLE_FROM_LE(m_fitData->fitRange.min(), ui.leMin); 0197 changed(); 0198 } 0199 void FitOptionsWidget::fitRangeMaxChanged() { 0200 SET_DOUBLE_FROM_LE(m_fitData->fitRange.max(), ui.leMax); 0201 changed(); 0202 } 0203 0204 void FitOptionsWidget::fitRangeMinDateTimeChanged(const QDateTime& dateTime) { 0205 m_fitData->fitRange.setMin(dateTime.toMSecsSinceEpoch()); 0206 changed(); 0207 } 0208 0209 void FitOptionsWidget::fitRangeMaxDateTimeChanged(const QDateTime& dateTime) { 0210 m_fitData->fitRange.setMax(dateTime.toMSecsSinceEpoch()); 0211 changed(); 0212 } 0213 0214 void FitOptionsWidget::evalRangeMinChanged() { 0215 SET_DOUBLE_FROM_LE(m_fitData->evalRange.min(), ui.leEvalMin); 0216 changed(); 0217 } 0218 void FitOptionsWidget::evalRangeMaxChanged() { 0219 SET_DOUBLE_FROM_LE(m_fitData->evalRange.max(), ui.leEvalMax); 0220 changed(); 0221 } 0222 0223 void FitOptionsWidget::evalRangeMinDateTimeChanged(const QDateTime& dateTime) { 0224 m_fitData->evalRange.setMin(dateTime.toMSecsSinceEpoch()); 0225 changed(); 0226 } 0227 0228 void FitOptionsWidget::evalRangeMaxDateTimeChanged(const QDateTime& dateTime) { 0229 m_fitData->evalRange.setMax(dateTime.toMSecsSinceEpoch()); 0230 changed(); 0231 } 0232 0233 void FitOptionsWidget::applyClicked() { 0234 SET_INT_FROM_LE(m_fitData->maxIterations, ui.leMaxIterations); 0235 SET_DOUBLE_FROM_LE(m_fitData->eps, ui.leEps); 0236 SET_INT_FROM_LE(m_fitData->evaluatedPoints, ui.leEvaluatedPoints); 0237 0238 m_fitData->useDataErrors = ui.cbUseDataErrors->isChecked(); 0239 m_fitData->useResults = ui.cbUseResults->isChecked(); 0240 m_fitData->previewEnabled = ui.cbPreview->isChecked(); 0241 m_fitData->confidenceInterval = ui.sbConfidenceInterval->value(); 0242 0243 if (m_changed) 0244 emit optionsChanged(); 0245 0246 emit finished(); 0247 } 0248 0249 void FitOptionsWidget::changed() { 0250 m_changed = true; 0251 }