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