File indexing completed on 2024-05-12 15:28:10

0001 /***************************************************************************
0002     File             : XYSmoothCurveDock.cpp
0003     Project          : LabPlot
0004     --------------------------------------------------------------------
0005     Copyright        : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn)
0006     Copyright        : (C) 2017-2020 Alexander Semke (alexander.semke@web.de)
0007     Description      : widget for editing properties of smooth curves
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 
0030 #include "XYSmoothCurveDock.h"
0031 #include "backend/core/AspectTreeModel.h"
0032 #include "backend/core/Project.h"
0033 #include "backend/worksheet/plots/cartesian/XYSmoothCurve.h"
0034 #include "commonfrontend/widgets/TreeViewComboBox.h"
0035 
0036 #include <QStandardItemModel>
0037 
0038 /*!
0039   \class XYSmoothCurveDock
0040  \brief  Provides a widget for editing the properties of the XYSmoothCurves
0041         (2D-curves defined by an smooth) currently selected in
0042         the project explorer.
0043 
0044   If more then one curves are set, the properties of the first column are shown.
0045   The changes of the properties are applied to all curves.
0046   The exclusions are the name, the comment and the datasets (columns) of
0047   the curves  - these properties can only be changed if there is only one single curve.
0048 
0049   \ingroup kdefrontend
0050 */
0051 
0052 XYSmoothCurveDock::XYSmoothCurveDock(QWidget* parent) : XYCurveDock(parent) {
0053 }
0054 
0055 /*!
0056  *  // Tab "General"
0057  */
0058 void XYSmoothCurveDock::setupGeneral() {
0059     DEBUG("XYSmoothCurveDock::setupGeneral()");
0060 
0061     QWidget* generalTab = new QWidget(ui.tabGeneral);
0062     uiGeneralTab.setupUi(generalTab);
0063     m_leName = uiGeneralTab.leName;
0064     m_leComment = uiGeneralTab.leComment;
0065 
0066     auto* gridLayout = static_cast<QGridLayout*>(generalTab->layout());
0067     gridLayout->setContentsMargins(2,2,2,2);
0068     gridLayout->setHorizontalSpacing(2);
0069     gridLayout->setVerticalSpacing(2);
0070 
0071     uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet"));
0072     uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve"));
0073 
0074     cbDataSourceCurve = new TreeViewComboBox(generalTab);
0075     gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 3);
0076     cbXDataColumn = new TreeViewComboBox(generalTab);
0077     gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 3);
0078     cbYDataColumn = new TreeViewComboBox(generalTab);
0079     gridLayout->addWidget(cbYDataColumn, 7, 2, 1, 3);
0080 
0081     for (int i = 0; i < NSL_SMOOTH_TYPE_COUNT; i++)
0082         uiGeneralTab.cbType->addItem(i18n(nsl_smooth_type_name[i]));
0083 
0084     for (int i = 0; i < NSL_SMOOTH_WEIGHT_TYPE_COUNT; i++)
0085         uiGeneralTab.cbWeight->addItem(i18n(nsl_smooth_weight_type_name[i]));
0086 
0087     for (int i = 0; i < NSL_SMOOTH_PAD_MODE_COUNT; i++)
0088         uiGeneralTab.cbMode->addItem(i18n(nsl_smooth_pad_mode_name[i]));
0089 
0090     //TODO: use line edits
0091     uiGeneralTab.sbMin->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
0092     uiGeneralTab.sbMax->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
0093 
0094     uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build"));
0095 
0096     auto* layout = new QHBoxLayout(ui.tabGeneral);
0097     layout->setMargin(0);
0098     layout->addWidget(generalTab);
0099 
0100     //Slots
0101     connect(uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYSmoothCurveDock::nameChanged );
0102     connect(uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYSmoothCurveDock::commentChanged );
0103     connect(uiGeneralTab.chkVisible, &QCheckBox::clicked, this, &XYSmoothCurveDock::visibilityChanged);
0104     connect(uiGeneralTab.cbDataSourceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYSmoothCurveDock::dataSourceTypeChanged);
0105     connect(uiGeneralTab.cbAutoRange, &QCheckBox::clicked, this, &XYSmoothCurveDock::autoRangeChanged);
0106     connect(uiGeneralTab.sbMin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYSmoothCurveDock::xRangeMinChanged);
0107     connect(uiGeneralTab.sbMax, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYSmoothCurveDock::xRangeMaxChanged);
0108     connect(uiGeneralTab.dateTimeEditMin, &QDateTimeEdit::dateTimeChanged, this, &XYSmoothCurveDock::xRangeMinDateTimeChanged);
0109     connect(uiGeneralTab.dateTimeEditMax, &QDateTimeEdit::dateTimeChanged, this, &XYSmoothCurveDock::xRangeMaxDateTimeChanged);
0110     connect(uiGeneralTab.cbType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYSmoothCurveDock::typeChanged);
0111     //TODO: line edits?
0112     connect(uiGeneralTab.sbPoints, QOverload<int>::of(&QSpinBox::valueChanged), this, &XYSmoothCurveDock::pointsChanged);
0113     connect(uiGeneralTab.cbWeight, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYSmoothCurveDock::weightChanged);
0114     connect(uiGeneralTab.sbPercentile, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYSmoothCurveDock::percentileChanged);
0115     connect(uiGeneralTab.sbOrder, QOverload<int>::of(&QSpinBox::valueChanged), this, &XYSmoothCurveDock::orderChanged);
0116     connect(uiGeneralTab.cbMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYSmoothCurveDock::modeChanged);
0117     connect(uiGeneralTab.sbLeftValue, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYSmoothCurveDock::valueChanged);
0118     connect(uiGeneralTab.sbRightValue, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYSmoothCurveDock::valueChanged);
0119     connect(uiGeneralTab.pbRecalculate, &QPushButton::clicked, this, &XYSmoothCurveDock::recalculateClicked);
0120 
0121     connect(cbDataSourceCurve, &TreeViewComboBox::currentModelIndexChanged, this, &XYSmoothCurveDock::dataSourceCurveChanged);
0122     connect(cbXDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYSmoothCurveDock::xDataColumnChanged);
0123     connect(cbYDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYSmoothCurveDock::yDataColumnChanged);
0124 }
0125 
0126 void XYSmoothCurveDock::initGeneralTab() {
0127     DEBUG("XYSmoothCurveDock::initGeneralTab()");
0128 
0129     //if there are more then one curve in the list, disable the tab "general"
0130     if (m_curvesList.size() == 1) {
0131         uiGeneralTab.lName->setEnabled(true);
0132         uiGeneralTab.leName->setEnabled(true);
0133         uiGeneralTab.lComment->setEnabled(true);
0134         uiGeneralTab.leComment->setEnabled(true);
0135 
0136         uiGeneralTab.leName->setText(m_curve->name());
0137         uiGeneralTab.leComment->setText(m_curve->comment());
0138     } else {
0139         uiGeneralTab.lName->setEnabled(false);
0140         uiGeneralTab.leName->setEnabled(false);
0141         uiGeneralTab.lComment->setEnabled(false);
0142         uiGeneralTab.leComment->setEnabled(false);
0143 
0144         uiGeneralTab.leName->setText(QString());
0145         uiGeneralTab.leComment->setText(QString());
0146     }
0147 
0148     //show the properties of the first curve
0149     m_smoothCurve = static_cast<XYSmoothCurve*>(m_curve);
0150     checkColumnAvailability(cbXDataColumn, m_smoothCurve->xDataColumn(), m_smoothCurve->xDataColumnPath());
0151     checkColumnAvailability(cbYDataColumn, m_smoothCurve->yDataColumn(), m_smoothCurve->yDataColumnPath());
0152 
0153     //data source
0154     uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(m_smoothCurve->dataSourceType()));
0155     this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex());
0156     XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_smoothCurve->dataSourceCurve());
0157     XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_smoothCurve->xDataColumn());
0158     XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_smoothCurve->yDataColumn());
0159 
0160     //range widgets
0161     const auto* plot = static_cast<const CartesianPlot*>(m_smoothCurve->parentAspect());
0162     m_dateTimeRange = (plot->xRangeFormat() != CartesianPlot::RangeFormat::Numeric);
0163     if (!m_dateTimeRange) {
0164         uiGeneralTab.sbMin->setValue(m_smoothData.xRange.first());
0165         uiGeneralTab.sbMax->setValue(m_smoothData.xRange.last());
0166     } else {
0167         uiGeneralTab.dateTimeEditMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_smoothData.xRange.first()) );
0168         uiGeneralTab.dateTimeEditMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_smoothData.xRange.last()) );
0169     }
0170 
0171     uiGeneralTab.lMin->setVisible(!m_dateTimeRange);
0172     uiGeneralTab.sbMin->setVisible(!m_dateTimeRange);
0173     uiGeneralTab.lMax->setVisible(!m_dateTimeRange);
0174     uiGeneralTab.sbMax->setVisible(!m_dateTimeRange);
0175     uiGeneralTab.lMinDateTime->setVisible(m_dateTimeRange);
0176     uiGeneralTab.dateTimeEditMin->setVisible(m_dateTimeRange);
0177     uiGeneralTab.lMaxDateTime->setVisible(m_dateTimeRange);
0178     uiGeneralTab.dateTimeEditMax->setVisible(m_dateTimeRange);
0179 
0180     //auto range
0181     uiGeneralTab.cbAutoRange->setChecked(m_smoothData.autoRange);
0182     this->autoRangeChanged();
0183 
0184     // update list of selectable types
0185     xDataColumnChanged(cbXDataColumn->currentModelIndex());
0186 
0187     uiGeneralTab.cbType->setCurrentIndex(m_smoothData.type);
0188     typeChanged(uiGeneralTab.cbType->currentIndex());   // needed, when type does not change
0189     uiGeneralTab.sbPoints->setValue((int)m_smoothData.points);
0190     uiGeneralTab.cbWeight->setCurrentIndex(m_smoothData.weight);
0191     uiGeneralTab.sbPercentile->setValue(m_smoothData.percentile);
0192     uiGeneralTab.sbOrder->setValue((int)m_smoothData.order);
0193     uiGeneralTab.cbMode->setCurrentIndex(m_smoothData.mode);
0194     modeChanged(uiGeneralTab.cbMode->currentIndex());   // needed, when mode does not change
0195     uiGeneralTab.sbLeftValue->setValue(m_smoothData.lvalue);
0196     uiGeneralTab.sbRightValue->setValue(m_smoothData.rvalue);
0197     valueChanged();
0198     this->showSmoothResult();
0199 
0200     uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() );
0201 
0202     //Slots
0203     connect(m_smoothCurve, &XYSmoothCurve::aspectDescriptionChanged, this, &XYSmoothCurveDock::curveDescriptionChanged);
0204     connect(m_smoothCurve, &XYSmoothCurve::dataSourceTypeChanged, this, &XYSmoothCurveDock::curveDataSourceTypeChanged);
0205     connect(m_smoothCurve, &XYSmoothCurve::dataSourceCurveChanged, this, &XYSmoothCurveDock::curveDataSourceCurveChanged);
0206     connect(m_smoothCurve, &XYSmoothCurve::xDataColumnChanged, this, &XYSmoothCurveDock::curveXDataColumnChanged);
0207     connect(m_smoothCurve, &XYSmoothCurve::yDataColumnChanged, this, &XYSmoothCurveDock::curveYDataColumnChanged);
0208     connect(m_smoothCurve, &XYSmoothCurve::smoothDataChanged, this, &XYSmoothCurveDock::curveSmoothDataChanged);
0209     connect(m_smoothCurve, &XYSmoothCurve::sourceDataChanged, this, &XYSmoothCurveDock::enableRecalculate);
0210     connect(m_smoothCurve, QOverload<bool>::of(&XYCurve::visibilityChanged), this, &XYSmoothCurveDock::curveVisibilityChanged);
0211 }
0212 
0213 void XYSmoothCurveDock::setModel() {
0214     QList<AspectType> list{AspectType::Folder, AspectType::Datapicker, AspectType::Worksheet,
0215                             AspectType::CartesianPlot, AspectType::XYCurve, AspectType::XYAnalysisCurve};
0216     cbDataSourceCurve->setTopLevelClasses(list);
0217 
0218     QList<const AbstractAspect*> hiddenAspects;
0219     for (auto* curve : m_curvesList)
0220         hiddenAspects << curve;
0221     cbDataSourceCurve->setHiddenAspects(hiddenAspects);
0222 
0223     list = {AspectType::Folder, AspectType::Workbook, AspectType::Datapicker,
0224             AspectType::DatapickerCurve, AspectType::Spreadsheet, AspectType::LiveDataSource,
0225             AspectType::Column, AspectType::Worksheet, AspectType::CartesianPlot,
0226             AspectType::XYFitCurve, AspectType::CantorWorksheet
0227            };
0228     cbXDataColumn->setTopLevelClasses(list);
0229     cbYDataColumn->setTopLevelClasses(list);
0230 
0231     cbDataSourceCurve->setModel(m_aspectTreeModel);
0232     cbXDataColumn->setModel(m_aspectTreeModel);
0233     cbYDataColumn->setModel(m_aspectTreeModel);
0234 
0235     XYCurveDock::setModel();
0236 }
0237 
0238 /*!
0239   sets the curves. The properties of the curves in the list \c list can be edited in this widget.
0240 */
0241 void XYSmoothCurveDock::setCurves(QList<XYCurve*> list) {
0242     DEBUG("XYSmoothCurveDock::setCurves()");
0243 
0244     m_initializing = true;
0245     m_curvesList = list;
0246     m_curve = list.first();
0247     m_aspect = m_curve;
0248     m_smoothCurve = dynamic_cast<XYSmoothCurve*>(m_curve);
0249     m_aspectTreeModel = new AspectTreeModel(m_curve->project());
0250     this->setModel();
0251     m_smoothData = m_smoothCurve->smoothData();
0252 
0253     SET_NUMBER_LOCALE
0254     uiGeneralTab.sbMin->setLocale(numberLocale);
0255     uiGeneralTab.sbMax->setLocale(numberLocale);
0256     uiGeneralTab.sbPercentile->setLocale(numberLocale);
0257     uiGeneralTab.sbLeftValue->setLocale(numberLocale);
0258     uiGeneralTab.sbRightValue->setLocale(numberLocale);
0259 
0260     initGeneralTab();
0261     initTabs();
0262     m_initializing = false;
0263 
0264     //hide the "skip gaps" option after the curves were set
0265     ui.lLineSkipGaps->hide();
0266     ui.chkLineSkipGaps->hide();
0267 }
0268 
0269 //*************************************************************
0270 //**** SLOTs for changes triggered in XYFitCurveDock *****
0271 //*************************************************************
0272 void XYSmoothCurveDock::dataSourceTypeChanged(int index) {
0273     auto type = (XYAnalysisCurve::DataSourceType)index;
0274     if (type == XYAnalysisCurve::DataSourceType::Spreadsheet) {
0275         uiGeneralTab.lDataSourceCurve->hide();
0276         cbDataSourceCurve->hide();
0277         uiGeneralTab.lXColumn->show();
0278         cbXDataColumn->show();
0279         uiGeneralTab.lYColumn->show();
0280         cbYDataColumn->show();
0281     } else {
0282         uiGeneralTab.lDataSourceCurve->show();
0283         cbDataSourceCurve->show();
0284         uiGeneralTab.lXColumn->hide();
0285         cbXDataColumn->hide();
0286         uiGeneralTab.lYColumn->hide();
0287         cbYDataColumn->hide();
0288     }
0289 
0290     if (m_initializing)
0291         return;
0292 
0293     for (auto* curve : m_curvesList)
0294         dynamic_cast<XYSmoothCurve*>(curve)->setDataSourceType(type);
0295 }
0296 
0297 void XYSmoothCurveDock::dataSourceCurveChanged(const QModelIndex& index) {
0298     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
0299     auto* dataSourceCurve = dynamic_cast<XYCurve*>(aspect);
0300 
0301     if (m_initializing)
0302         return;
0303 
0304     for (auto* curve : m_curvesList)
0305         dynamic_cast<XYSmoothCurve*>(curve)->setDataSourceCurve(dataSourceCurve);
0306 }
0307 
0308 void XYSmoothCurveDock::xDataColumnChanged(const QModelIndex& index) {
0309     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
0310     auto* column = dynamic_cast<AbstractColumn*>(aspect);
0311 
0312     for (auto* curve : m_curvesList)
0313         dynamic_cast<XYSmoothCurve*>(curve)->setXDataColumn(column);
0314 
0315     // disable types that need more data points
0316     if (column != nullptr) {
0317         if (uiGeneralTab.cbAutoRange->isChecked()) {
0318             uiGeneralTab.sbMin->setValue(column->minimum());
0319             uiGeneralTab.sbMax->setValue(column->maximum());
0320         }
0321 
0322         unsigned int n = 0;
0323         for (int row = 0; row < column->rowCount(); row++) {
0324             if (column->isMasked(row))
0325                 continue;
0326 
0327             switch (column->columnMode()) {
0328             case AbstractColumn::ColumnMode::Numeric:
0329             case AbstractColumn::ColumnMode::Integer:
0330             case AbstractColumn::ColumnMode::BigInt:
0331                 if (!std::isnan(column->valueAt(row)))
0332                     n++;
0333                 break;
0334             case AbstractColumn::ColumnMode::DateTime:
0335             case AbstractColumn::ColumnMode::Month:
0336             case AbstractColumn::ColumnMode::Day:
0337                 n++;
0338                 break;
0339             case AbstractColumn::ColumnMode::Text:
0340                 break;
0341             }
0342         }
0343 
0344         DEBUG(" Set maximum points to " << n)
0345         // set maximum of sbPoints to number of columns
0346         uiGeneralTab.sbPoints->setMaximum((int)n);
0347     }
0348 
0349     cbXDataColumn->useCurrentIndexText(true);
0350     cbXDataColumn->setInvalid(false);
0351 }
0352 
0353 void XYSmoothCurveDock::yDataColumnChanged(const QModelIndex& index) {
0354     if (m_initializing)
0355         return;
0356 
0357     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
0358     auto* column = dynamic_cast<AbstractColumn*>(aspect);
0359 
0360     for (auto* curve : m_curvesList)
0361         dynamic_cast<XYSmoothCurve*>(curve)->setYDataColumn(column);
0362 
0363     cbYDataColumn->useCurrentIndexText(true);
0364     cbYDataColumn->setInvalid(false);
0365 }
0366 
0367 void XYSmoothCurveDock::autoRangeChanged() {
0368     bool autoRange = uiGeneralTab.cbAutoRange->isChecked();
0369     m_smoothData.autoRange = autoRange;
0370 
0371     uiGeneralTab.lMin->setEnabled(!autoRange);
0372     uiGeneralTab.sbMin->setEnabled(!autoRange);
0373     uiGeneralTab.lMax->setEnabled(!autoRange);
0374     uiGeneralTab.sbMax->setEnabled(!autoRange);
0375     uiGeneralTab.lMinDateTime->setEnabled(!autoRange);
0376     uiGeneralTab.dateTimeEditMin->setEnabled(!autoRange);
0377     uiGeneralTab.lMaxDateTime->setEnabled(!autoRange);
0378     uiGeneralTab.dateTimeEditMax->setEnabled(!autoRange);
0379 
0380     if (autoRange) {
0381         const AbstractColumn* xDataColumn = nullptr;
0382         if (m_smoothCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet)
0383             xDataColumn = m_smoothCurve->xDataColumn();
0384         else {
0385             if (m_smoothCurve->dataSourceCurve())
0386                 xDataColumn = m_smoothCurve->dataSourceCurve()->xColumn();
0387         }
0388 
0389         if (xDataColumn) {
0390             if (!m_dateTimeRange) {
0391                 uiGeneralTab.sbMin->setValue(xDataColumn->minimum());
0392                 uiGeneralTab.sbMax->setValue(xDataColumn->maximum());
0393             } else {
0394                 uiGeneralTab.dateTimeEditMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xDataColumn->minimum()));
0395                 uiGeneralTab.dateTimeEditMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xDataColumn->maximum()));
0396             }
0397         }
0398     }
0399 }
0400 
0401 void XYSmoothCurveDock::xRangeMinChanged(double value) {
0402     m_smoothData.xRange.first() = value;
0403     uiGeneralTab.pbRecalculate->setEnabled(true);
0404 }
0405 
0406 void XYSmoothCurveDock::xRangeMaxChanged(double value) {
0407     m_smoothData.xRange.last() = value;
0408     uiGeneralTab.pbRecalculate->setEnabled(true);
0409 }
0410 
0411 void XYSmoothCurveDock::xRangeMinDateTimeChanged(const QDateTime& dateTime) {
0412     if (m_initializing)
0413         return;
0414 
0415     m_smoothData.xRange.first() = dateTime.toMSecsSinceEpoch();
0416     uiGeneralTab.pbRecalculate->setEnabled(true);
0417 }
0418 
0419 void XYSmoothCurveDock::xRangeMaxDateTimeChanged(const QDateTime& dateTime) {
0420     if (m_initializing)
0421         return;
0422 
0423     m_smoothData.xRange.last() = dateTime.toMSecsSinceEpoch();
0424     uiGeneralTab.pbRecalculate->setEnabled(true);
0425 }
0426 
0427 void XYSmoothCurveDock::typeChanged(int index) {
0428     auto type = (nsl_smooth_type)index;
0429     m_smoothData.type = type;
0430 
0431     const auto* model = qobject_cast<const QStandardItemModel*>(uiGeneralTab.cbMode->model());
0432     QStandardItem* pad_interp_item = model->item(nsl_smooth_pad_interp);
0433     if (type == nsl_smooth_type_moving_average || type == nsl_smooth_type_moving_average_lagged) {
0434         uiGeneralTab.lWeight->show();
0435         uiGeneralTab.cbWeight->show();
0436         // disable interp pad model for MA and MAL
0437         pad_interp_item->setFlags(pad_interp_item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
0438     } else {
0439         uiGeneralTab.lWeight->hide();
0440         uiGeneralTab.cbWeight->hide();
0441         pad_interp_item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
0442     }
0443 
0444     if (type == nsl_smooth_type_moving_average_lagged) {
0445         uiGeneralTab.sbPoints->setSingleStep(1);
0446         uiGeneralTab.sbPoints->setMinimum(2);
0447         uiGeneralTab.lRightValue->hide();
0448         uiGeneralTab.sbRightValue->hide();
0449     } else {
0450         uiGeneralTab.sbPoints->setSingleStep(2);
0451         uiGeneralTab.sbPoints->setMinimum(3);
0452         if (m_smoothData.mode == nsl_smooth_pad_constant) {
0453             uiGeneralTab.lRightValue->show();
0454             uiGeneralTab.sbRightValue->show();
0455         }
0456     }
0457 
0458     if (type == nsl_smooth_type_percentile) {
0459         uiGeneralTab.lPercentile->show();
0460         uiGeneralTab.sbPercentile->show();
0461         // disable interp pad model for MA and MAL
0462         pad_interp_item->setFlags(pad_interp_item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
0463     } else {
0464         uiGeneralTab.lPercentile->hide();
0465         uiGeneralTab.sbPercentile->hide();
0466     }
0467 
0468     if (type == nsl_smooth_type_savitzky_golay) {
0469         uiGeneralTab.lOrder->show();
0470         uiGeneralTab.sbOrder->show();
0471     } else {
0472         uiGeneralTab.lOrder->hide();
0473         uiGeneralTab.sbOrder->hide();
0474     }
0475 
0476     enableRecalculate();
0477 }
0478 
0479 void XYSmoothCurveDock::pointsChanged(int value) {
0480     m_smoothData.points = (unsigned int)value;
0481     uiGeneralTab.sbOrder->setMaximum(value - 1); // set maximum order
0482     enableRecalculate();
0483 }
0484 
0485 void XYSmoothCurveDock::weightChanged(int index) {
0486     m_smoothData.weight = (nsl_smooth_weight_type)index;
0487     enableRecalculate();
0488 }
0489 
0490 void XYSmoothCurveDock::percentileChanged(double value) {
0491     m_smoothData.percentile = value;
0492     enableRecalculate();
0493 }
0494 
0495 void XYSmoothCurveDock::orderChanged(int value) {
0496     m_smoothData.order = (unsigned int)value;
0497     enableRecalculate();
0498 }
0499 
0500 void XYSmoothCurveDock::modeChanged(int index) {
0501     m_smoothData.mode = (nsl_smooth_pad_mode)index;
0502 
0503     if (m_smoothData.mode == nsl_smooth_pad_constant) {
0504         uiGeneralTab.lLeftValue->show();
0505         uiGeneralTab.sbLeftValue->show();
0506         if (m_smoothData.type == nsl_smooth_type_moving_average_lagged) {
0507             uiGeneralTab.lRightValue->hide();
0508             uiGeneralTab.sbRightValue->hide();
0509         } else {
0510             uiGeneralTab.lRightValue->show();
0511             uiGeneralTab.sbRightValue->show();
0512         }
0513     } else {
0514         uiGeneralTab.lLeftValue->hide();
0515         uiGeneralTab.sbLeftValue->hide();
0516         uiGeneralTab.lRightValue->hide();
0517         uiGeneralTab.sbRightValue->hide();
0518     }
0519 
0520     enableRecalculate();
0521 }
0522 
0523 void XYSmoothCurveDock::valueChanged() {
0524     m_smoothData.lvalue = uiGeneralTab.sbLeftValue->value();
0525     m_smoothData.rvalue = uiGeneralTab.sbRightValue->value();
0526 
0527     enableRecalculate();
0528 }
0529 
0530 void XYSmoothCurveDock::recalculateClicked() {
0531     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
0532 
0533     for (auto* curve : m_curvesList)
0534         dynamic_cast<XYSmoothCurve*>(curve)->setSmoothData(m_smoothData);
0535 
0536     uiGeneralTab.pbRecalculate->setEnabled(false);
0537     emit info(i18n("Smoothing status: %1", m_smoothCurve->smoothResult().status));
0538     QApplication::restoreOverrideCursor();
0539 }
0540 
0541 void XYSmoothCurveDock::enableRecalculate() const {
0542     if (m_initializing)
0543         return;
0544 
0545     //no smoothing possible without the x- and y-data
0546     bool hasSourceData = false;
0547     if (m_smoothCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) {
0548         AbstractAspect* aspectX = static_cast<AbstractAspect*>(cbXDataColumn->currentModelIndex().internalPointer());
0549         AbstractAspect* aspectY = static_cast<AbstractAspect*>(cbYDataColumn->currentModelIndex().internalPointer());
0550         hasSourceData = (aspectX != nullptr && aspectY != nullptr);
0551         if (aspectX) {
0552             cbXDataColumn->useCurrentIndexText(true);
0553             cbXDataColumn->setInvalid(false);
0554         }
0555         if (aspectY) {
0556             cbYDataColumn->useCurrentIndexText(true);
0557             cbYDataColumn->setInvalid(false);
0558         }
0559     } else {
0560          hasSourceData = (m_smoothCurve->dataSourceCurve() != nullptr);
0561     }
0562 
0563     uiGeneralTab.pbRecalculate->setEnabled(hasSourceData);
0564 }
0565 
0566 /*!
0567  * show the result and details of the smooth
0568  */
0569 void XYSmoothCurveDock::showSmoothResult() {
0570     const XYSmoothCurve::SmoothResult& smoothResult = m_smoothCurve->smoothResult();
0571     if (!smoothResult.available) {
0572         uiGeneralTab.teResult->clear();
0573         return;
0574     }
0575 
0576     //const XYSmoothCurve::SmoothData& smoothData = m_smoothCurve->smoothData();
0577     QString str = i18n("status: %1", smoothResult.status) + "<br>";
0578 
0579     if (!smoothResult.valid) {
0580         uiGeneralTab.teResult->setText(str);
0581         return; //result is not valid, there was an error which is shown in the status-string, nothing to show more.
0582     }
0583 
0584     SET_NUMBER_LOCALE
0585     if (smoothResult.elapsedTime>1000)
0586         str += i18n("calculation time: %1 s", numberLocale.toString(smoothResult.elapsedTime/1000)) + "<br>";
0587     else
0588         str += i18n("calculation time: %1 ms", numberLocale.toString(smoothResult.elapsedTime)) + "<br>";
0589 
0590     str += "<br><br>";
0591 
0592     uiGeneralTab.teResult->setText(str);
0593 
0594     //enable the "recalculate"-button if the source data was changed since the last smooth
0595     uiGeneralTab.pbRecalculate->setEnabled(m_smoothCurve->isSourceDataChangedSinceLastRecalc());
0596 }
0597 
0598 //*************************************************************
0599 //*********** SLOTs for changes triggered in XYCurve **********
0600 //*************************************************************
0601 //General-Tab
0602 void XYSmoothCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) {
0603     if (m_curve != aspect)
0604         return;
0605 
0606     m_initializing = true;
0607     if (aspect->name() != uiGeneralTab.leName->text())
0608         uiGeneralTab.leName->setText(aspect->name());
0609     else if (aspect->comment() != uiGeneralTab.leComment->text())
0610         uiGeneralTab.leComment->setText(aspect->comment());
0611     m_initializing = false;
0612 }
0613 
0614 void XYSmoothCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) {
0615     m_initializing = true;
0616     uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(type));
0617     m_initializing = false;
0618 }
0619 
0620 void XYSmoothCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) {
0621     m_initializing = true;
0622     XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve);
0623     m_initializing = false;
0624 }
0625 
0626 void XYSmoothCurveDock::curveXDataColumnChanged(const AbstractColumn* column) {
0627     m_initializing = true;
0628     XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column);
0629     m_initializing = false;
0630 }
0631 
0632 void XYSmoothCurveDock::curveYDataColumnChanged(const AbstractColumn* column) {
0633     m_initializing = true;
0634     XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column);
0635     m_initializing = false;
0636 }
0637 
0638 void XYSmoothCurveDock::curveSmoothDataChanged(const XYSmoothCurve::SmoothData& smoothData) {
0639     m_initializing = true;
0640     m_smoothData = smoothData;
0641     uiGeneralTab.cbType->setCurrentIndex(m_smoothData.type);
0642 
0643     this->showSmoothResult();
0644     m_initializing = false;
0645 }
0646 
0647 void XYSmoothCurveDock::dataChanged() {
0648     this->enableRecalculate();
0649 }
0650 
0651 void XYSmoothCurveDock::curveVisibilityChanged(bool on) {
0652     m_initializing = true;
0653     uiGeneralTab.chkVisible->setChecked(on);
0654     m_initializing = false;
0655 }