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 }