File indexing completed on 2024-05-12 15:28:05
0001 /*************************************************************************** 0002 File : XYDataReductionCurveDock.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 data reduction 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 "XYDataReductionCurveDock.h" 0031 #include "backend/core/AspectTreeModel.h" 0032 #include "backend/core/Project.h" 0033 #include "backend/worksheet/plots/cartesian/XYDataReductionCurve.h" 0034 #include "commonfrontend/widgets/TreeViewComboBox.h" 0035 0036 #include <QMenu> 0037 #include <QWidgetAction> 0038 #include <QStandardItemModel> 0039 #include <QStatusBar> 0040 #include <QProgressBar> 0041 0042 /*! 0043 \class XYDataReductionCurveDock 0044 \brief Provides a widget for editing the properties of the XYDataReductionCurves 0045 (2D-curves defined by an data reduction) currently selected in 0046 the project explorer. 0047 0048 If more then 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 XYDataReductionCurveDock::XYDataReductionCurveDock(QWidget* parent, QStatusBar* sb) : XYCurveDock(parent), statusBar(sb) { 0057 } 0058 0059 /*! 0060 * // Tab "General" 0061 */ 0062 void XYDataReductionCurveDock::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_GEOM_LINESIM_TYPE_COUNT; ++i) 0084 uiGeneralTab.cbType->addItem(i18n(nsl_geom_linesim_type_name[i])); 0085 uiGeneralTab.cbType->setItemData(nsl_geom_linesim_type_visvalingam_whyatt, i18n("This method is much slower than any other"), Qt::ToolTipRole); 0086 0087 uiGeneralTab.sbMin->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max()); 0088 uiGeneralTab.sbMax->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max()); 0089 uiGeneralTab.sbTolerance->setRange(0.0, std::numeric_limits<double>::max()); 0090 uiGeneralTab.sbTolerance2->setRange(0.0, std::numeric_limits<double>::max()); 0091 0092 uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build")); 0093 0094 auto* layout = new QHBoxLayout(ui.tabGeneral); 0095 layout->setMargin(0); 0096 layout->addWidget(generalTab); 0097 0098 //Slots 0099 connect(uiGeneralTab.chkVisible, &QCheckBox::clicked, this, &XYDataReductionCurveDock::visibilityChanged); 0100 connect(uiGeneralTab.cbDataSourceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYDataReductionCurveDock::dataSourceTypeChanged); 0101 connect(uiGeneralTab.cbAutoRange, &QCheckBox::clicked, this, &XYDataReductionCurveDock::autoRangeChanged); 0102 connect(uiGeneralTab.sbMin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYDataReductionCurveDock::xRangeMinChanged); 0103 connect(uiGeneralTab.sbMax, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYDataReductionCurveDock::xRangeMaxChanged); 0104 connect(uiGeneralTab.dateTimeEditMin, &QDateTimeEdit::dateTimeChanged, this, &XYDataReductionCurveDock::xRangeMinDateTimeChanged); 0105 connect(uiGeneralTab.dateTimeEditMax, &QDateTimeEdit::dateTimeChanged, this, &XYDataReductionCurveDock::xRangeMaxDateTimeChanged); 0106 connect(uiGeneralTab.chkAuto, &QCheckBox::clicked, this, &XYDataReductionCurveDock::autoToleranceChanged); 0107 connect(uiGeneralTab.sbTolerance, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYDataReductionCurveDock::toleranceChanged); 0108 connect(uiGeneralTab.chkAuto2, &QCheckBox::clicked, this, &XYDataReductionCurveDock::autoTolerance2Changed); 0109 connect(uiGeneralTab.sbTolerance2, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYDataReductionCurveDock::tolerance2Changed); 0110 connect(uiGeneralTab.pbRecalculate, &QPushButton::clicked, this, &XYDataReductionCurveDock::recalculateClicked); 0111 0112 connect(cbDataSourceCurve, &TreeViewComboBox::currentModelIndexChanged, this, &XYDataReductionCurveDock::dataSourceCurveChanged); 0113 connect(cbXDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYDataReductionCurveDock::xDataColumnChanged); 0114 connect(cbYDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYDataReductionCurveDock::yDataColumnChanged); 0115 } 0116 0117 void XYDataReductionCurveDock::initGeneralTab() { 0118 //if there are more then one curve in the list, disable the tab "general" 0119 if (m_curvesList.size() == 1) { 0120 uiGeneralTab.lName->setEnabled(true); 0121 uiGeneralTab.leName->setEnabled(true); 0122 uiGeneralTab.lComment->setEnabled(true); 0123 uiGeneralTab.leComment->setEnabled(true); 0124 0125 uiGeneralTab.leName->setText(m_curve->name()); 0126 uiGeneralTab.leComment->setText(m_curve->comment()); 0127 } else { 0128 uiGeneralTab.lName->setEnabled(false); 0129 uiGeneralTab.leName->setEnabled(false); 0130 uiGeneralTab.lComment->setEnabled(false); 0131 uiGeneralTab.leComment->setEnabled(false); 0132 0133 uiGeneralTab.leName->setText(QString()); 0134 uiGeneralTab.leComment->setText(QString()); 0135 } 0136 0137 //show the properties of the first curve 0138 m_dataReductionCurve = dynamic_cast<XYDataReductionCurve*>(m_curve); 0139 checkColumnAvailability(cbXDataColumn, m_dataReductionCurve->xDataColumn(), m_dataReductionCurve->xDataColumnPath()); 0140 checkColumnAvailability(cbYDataColumn, m_dataReductionCurve->yDataColumn(), m_dataReductionCurve->yDataColumnPath()); 0141 0142 //data source 0143 uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(m_dataReductionCurve->dataSourceType())); 0144 this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex()); 0145 XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_dataReductionCurve->dataSourceCurve()); 0146 XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_dataReductionCurve->xDataColumn()); 0147 XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_dataReductionCurve->yDataColumn()); 0148 0149 //range widgets 0150 const auto* plot = static_cast<const CartesianPlot*>(m_dataReductionCurve->parentAspect()); 0151 m_dateTimeRange = (plot->xRangeFormat() != CartesianPlot::RangeFormat::Numeric); 0152 if (!m_dateTimeRange) { 0153 uiGeneralTab.sbMin->setValue(m_dataReductionData.xRange.first()); 0154 uiGeneralTab.sbMax->setValue(m_dataReductionData.xRange.last()); 0155 } else { 0156 uiGeneralTab.dateTimeEditMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_dataReductionData.xRange.first()) ); 0157 uiGeneralTab.dateTimeEditMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_dataReductionData.xRange.last()) ); 0158 } 0159 0160 uiGeneralTab.lMin->setVisible(!m_dateTimeRange); 0161 uiGeneralTab.sbMin->setVisible(!m_dateTimeRange); 0162 uiGeneralTab.lMax->setVisible(!m_dateTimeRange); 0163 uiGeneralTab.sbMax->setVisible(!m_dateTimeRange); 0164 uiGeneralTab.lMinDateTime->setVisible(m_dateTimeRange); 0165 uiGeneralTab.dateTimeEditMin->setVisible(m_dateTimeRange); 0166 uiGeneralTab.lMaxDateTime->setVisible(m_dateTimeRange); 0167 uiGeneralTab.dateTimeEditMax->setVisible(m_dateTimeRange); 0168 0169 //auto range 0170 uiGeneralTab.cbAutoRange->setChecked(m_dataReductionData.autoRange); 0171 this->autoRangeChanged(); 0172 0173 // update list of selectable types 0174 xDataColumnChanged(cbXDataColumn->currentModelIndex()); 0175 0176 uiGeneralTab.cbType->setCurrentIndex(m_dataReductionData.type); 0177 this->typeChanged(m_dataReductionData.type); 0178 uiGeneralTab.chkAuto->setChecked(m_dataReductionData.autoTolerance); 0179 this->autoToleranceChanged(); 0180 uiGeneralTab.sbTolerance->setValue(m_dataReductionData.tolerance); 0181 this->toleranceChanged(m_dataReductionData.tolerance); 0182 uiGeneralTab.chkAuto2->setChecked(m_dataReductionData.autoTolerance2); 0183 this->autoTolerance2Changed(); 0184 uiGeneralTab.sbTolerance2->setValue(m_dataReductionData.tolerance2); 0185 this->tolerance2Changed(m_dataReductionData.tolerance2); 0186 0187 this->showDataReductionResult(); 0188 0189 //enable the "recalculate"-button if the source data was changed since the last dataReduction 0190 uiGeneralTab.pbRecalculate->setEnabled(m_dataReductionCurve->isSourceDataChangedSinceLastRecalc()); 0191 0192 uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); 0193 0194 //Slots 0195 connect(m_dataReductionCurve, &XYDataReductionCurve::aspectDescriptionChanged, this, &XYDataReductionCurveDock::curveDescriptionChanged); 0196 connect(m_dataReductionCurve, &XYDataReductionCurve::dataSourceTypeChanged, this, &XYDataReductionCurveDock::curveDataSourceTypeChanged); 0197 connect(m_dataReductionCurve, &XYDataReductionCurve::dataSourceCurveChanged, this, &XYDataReductionCurveDock::curveDataSourceCurveChanged); 0198 connect(m_dataReductionCurve, &XYDataReductionCurve::xDataColumnChanged, this, &XYDataReductionCurveDock::curveXDataColumnChanged); 0199 connect(m_dataReductionCurve, &XYDataReductionCurve::yDataColumnChanged, this, &XYDataReductionCurveDock::curveYDataColumnChanged); 0200 connect(m_dataReductionCurve, &XYDataReductionCurve::dataReductionDataChanged, this, &XYDataReductionCurveDock::curveDataReductionDataChanged); 0201 connect(m_dataReductionCurve, &XYDataReductionCurve::sourceDataChanged, this, &XYDataReductionCurveDock::enableRecalculate); 0202 connect(m_dataReductionCurve, QOverload<bool>::of(&XYCurve::visibilityChanged), this, &XYDataReductionCurveDock::curveVisibilityChanged); 0203 } 0204 0205 void XYDataReductionCurveDock::setModel() { 0206 QList<AspectType> list{AspectType::Folder, AspectType::Datapicker, AspectType::Worksheet, 0207 AspectType::CartesianPlot, AspectType::XYCurve, AspectType::XYAnalysisCurve}; 0208 cbDataSourceCurve->setTopLevelClasses(list); 0209 0210 QList<const AbstractAspect*> hiddenAspects; 0211 for (auto* curve : m_curvesList) 0212 hiddenAspects << curve; 0213 cbDataSourceCurve->setHiddenAspects(hiddenAspects); 0214 0215 list = {AspectType::Folder, AspectType::Workbook, AspectType::Datapicker, 0216 AspectType::DatapickerCurve, AspectType::Spreadsheet, AspectType::LiveDataSource, 0217 AspectType::Column, AspectType::Worksheet, AspectType::CartesianPlot, 0218 AspectType::XYFitCurve 0219 }; 0220 cbXDataColumn->setTopLevelClasses(list); 0221 cbYDataColumn->setTopLevelClasses(list); 0222 0223 cbDataSourceCurve->setModel(m_aspectTreeModel); 0224 cbXDataColumn->setModel(m_aspectTreeModel); 0225 cbYDataColumn->setModel(m_aspectTreeModel); 0226 0227 XYCurveDock::setModel(); 0228 } 0229 0230 /*! 0231 sets the curves. The properties of the curves in the list \c list can be edited in this widget. 0232 */ 0233 void XYDataReductionCurveDock::setCurves(QList<XYCurve*> list) { 0234 m_initializing = true; 0235 m_curvesList = list; 0236 m_curve = list.first(); 0237 m_aspect = m_curve; 0238 m_dataReductionCurve = dynamic_cast<XYDataReductionCurve*>(m_curve); 0239 m_aspectTreeModel = new AspectTreeModel(m_curve->project()); 0240 this->setModel(); 0241 m_dataReductionData = m_dataReductionCurve->dataReductionData(); 0242 0243 SET_NUMBER_LOCALE 0244 uiGeneralTab.sbMin->setLocale(numberLocale); 0245 uiGeneralTab.sbMax->setLocale(numberLocale); 0246 uiGeneralTab.sbTolerance->setLocale(numberLocale); 0247 uiGeneralTab.sbTolerance2->setLocale(numberLocale); 0248 0249 initGeneralTab(); 0250 initTabs(); 0251 m_initializing = false; 0252 0253 //hide the "skip gaps" option after the curves were set 0254 ui.lLineSkipGaps->hide(); 0255 ui.chkLineSkipGaps->hide(); 0256 } 0257 0258 //************************************************************* 0259 //**** SLOTs for changes triggered in XYFitCurveDock ***** 0260 //************************************************************* 0261 void XYDataReductionCurveDock::dataSourceTypeChanged(int index) { 0262 const auto type = (XYAnalysisCurve::DataSourceType)index; 0263 if (type == XYAnalysisCurve::DataSourceType::Spreadsheet) { 0264 uiGeneralTab.lDataSourceCurve->hide(); 0265 cbDataSourceCurve->hide(); 0266 uiGeneralTab.lXColumn->show(); 0267 cbXDataColumn->show(); 0268 uiGeneralTab.lYColumn->show(); 0269 cbYDataColumn->show(); 0270 } else { 0271 uiGeneralTab.lDataSourceCurve->show(); 0272 cbDataSourceCurve->show(); 0273 uiGeneralTab.lXColumn->hide(); 0274 cbXDataColumn->hide(); 0275 uiGeneralTab.lYColumn->hide(); 0276 cbYDataColumn->hide(); 0277 } 0278 0279 if (m_initializing) 0280 return; 0281 0282 for (auto* curve : m_curvesList) 0283 dynamic_cast<XYDataReductionCurve*>(curve)->setDataSourceType(type); 0284 } 0285 0286 void XYDataReductionCurveDock::dataSourceCurveChanged(const QModelIndex& index) { 0287 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0288 auto* dataSourceCurve = dynamic_cast<XYCurve*>(aspect); 0289 0290 // // disable deriv orders and accuracies that need more data points 0291 // this->updateSettings(dataSourceCurve->xColumn()); 0292 0293 if (m_initializing) 0294 return; 0295 0296 for (auto* curve : m_curvesList) 0297 dynamic_cast<XYDataReductionCurve*>(curve)->setDataSourceCurve(dataSourceCurve); 0298 } 0299 0300 void XYDataReductionCurveDock::xDataColumnChanged(const QModelIndex& index) { 0301 if (m_initializing) 0302 return; 0303 0304 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0305 auto* column = dynamic_cast<AbstractColumn*>(aspect); 0306 0307 for (auto* curve : m_curvesList) 0308 dynamic_cast<XYDataReductionCurve*>(curve)->setXDataColumn(column); 0309 0310 //TODO: this->updateSettings(column); ? 0311 if (column != nullptr && uiGeneralTab.cbAutoRange->isChecked()) { 0312 uiGeneralTab.sbMin->setValue(column->minimum()); 0313 uiGeneralTab.sbMax->setValue(column->maximum()); 0314 } 0315 0316 cbXDataColumn->useCurrentIndexText(true); 0317 cbXDataColumn->setInvalid(false); 0318 0319 updateTolerance(); 0320 updateTolerance2(); 0321 } 0322 0323 void XYDataReductionCurveDock::yDataColumnChanged(const QModelIndex& index) { 0324 if (m_initializing) 0325 return; 0326 0327 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0328 auto* column = dynamic_cast<AbstractColumn*>(aspect); 0329 0330 for (auto* curve : m_curvesList) 0331 dynamic_cast<XYDataReductionCurve*>(curve)->setYDataColumn(column); 0332 0333 cbYDataColumn->useCurrentIndexText(true); 0334 cbYDataColumn->setInvalid(false); 0335 0336 updateTolerance(); 0337 updateTolerance2(); 0338 } 0339 0340 void XYDataReductionCurveDock::updateTolerance() { 0341 const AbstractColumn* xDataColumn = nullptr; 0342 const AbstractColumn* yDataColumn = nullptr; 0343 if (m_dataReductionCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) { 0344 xDataColumn = m_dataReductionCurve->xDataColumn(); 0345 yDataColumn = m_dataReductionCurve->yDataColumn(); 0346 } else { 0347 if (m_dataReductionCurve->dataSourceCurve()) { 0348 xDataColumn = m_dataReductionCurve->dataSourceCurve()->xColumn(); 0349 yDataColumn = m_dataReductionCurve->dataSourceCurve()->yColumn(); 0350 } 0351 } 0352 0353 if (xDataColumn == nullptr || yDataColumn == nullptr) 0354 return; 0355 0356 //copy all valid data points for calculating tolerance to temporary vectors 0357 QVector<double> xdataVector; 0358 QVector<double> ydataVector; 0359 const double xmin = m_dataReductionData.xRange.first(); 0360 const double xmax = m_dataReductionData.xRange.last(); 0361 XYAnalysisCurve::copyData(xdataVector, ydataVector, xDataColumn, yDataColumn, xmin, xmax); 0362 0363 if (xdataVector.size() > 1) 0364 uiGeneralTab.cbType->setEnabled(true); 0365 else { 0366 uiGeneralTab.cbType->setEnabled(false); 0367 return; 0368 } 0369 DEBUG("automatic tolerance:"); 0370 DEBUG("clip_diag_perpoint =" << nsl_geom_linesim_clip_diag_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size())); 0371 DEBUG("clip_area_perpoint =" << nsl_geom_linesim_clip_area_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size())); 0372 DEBUG("avg_dist_perpoint =" << nsl_geom_linesim_avg_dist_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size())); 0373 0374 const auto type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); 0375 if (type == nsl_geom_linesim_type_raddist || type == nsl_geom_linesim_type_opheim) 0376 m_dataReductionData.tolerance = 10. * nsl_geom_linesim_clip_diag_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size()); 0377 else if (type == nsl_geom_linesim_type_visvalingam_whyatt) 0378 m_dataReductionData.tolerance = 0.1 * nsl_geom_linesim_clip_area_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size()); 0379 else if (type == nsl_geom_linesim_type_douglas_peucker_variant) 0380 m_dataReductionData.tolerance = xdataVector.size()/10.; // reduction to 10% 0381 else 0382 m_dataReductionData.tolerance = 2.*nsl_geom_linesim_avg_dist_perpoint(xdataVector.data(), ydataVector.data(), xdataVector.size()); 0383 //m_dataReductionData.tolerance = nsl_geom_linesim_clip_diag_perpoint(xdataVector.data(), ydataVector.data(), xdataVector.size()); 0384 uiGeneralTab.sbTolerance->setValue(m_dataReductionData.tolerance); 0385 } 0386 0387 void XYDataReductionCurveDock::updateTolerance2() { 0388 const auto type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); 0389 0390 if (type == nsl_geom_linesim_type_perpdist) 0391 uiGeneralTab.sbTolerance2->setValue(10); 0392 else if (type == nsl_geom_linesim_type_opheim) 0393 uiGeneralTab.sbTolerance2->setValue(5*uiGeneralTab.sbTolerance->value()); 0394 else if (type == nsl_geom_linesim_type_lang) 0395 uiGeneralTab.sbTolerance2->setValue(10); 0396 } 0397 0398 void XYDataReductionCurveDock::autoRangeChanged() { 0399 bool autoRange = uiGeneralTab.cbAutoRange->isChecked(); 0400 m_dataReductionData.autoRange = autoRange; 0401 0402 uiGeneralTab.lMin->setEnabled(!autoRange); 0403 uiGeneralTab.sbMin->setEnabled(!autoRange); 0404 uiGeneralTab.lMax->setEnabled(!autoRange); 0405 uiGeneralTab.sbMax->setEnabled(!autoRange); 0406 uiGeneralTab.lMinDateTime->setEnabled(!autoRange); 0407 uiGeneralTab.dateTimeEditMin->setEnabled(!autoRange); 0408 uiGeneralTab.lMaxDateTime->setEnabled(!autoRange); 0409 uiGeneralTab.dateTimeEditMax->setEnabled(!autoRange); 0410 0411 if (autoRange) { 0412 const AbstractColumn* xDataColumn = nullptr; 0413 if (m_dataReductionCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) 0414 xDataColumn = m_dataReductionCurve->xDataColumn(); 0415 else { 0416 if (m_dataReductionCurve->dataSourceCurve()) 0417 xDataColumn = m_dataReductionCurve->dataSourceCurve()->xColumn(); 0418 } 0419 0420 if (xDataColumn) { 0421 if (!m_dateTimeRange) { 0422 uiGeneralTab.sbMin->setValue(xDataColumn->minimum()); 0423 uiGeneralTab.sbMax->setValue(xDataColumn->maximum()); 0424 } else { 0425 uiGeneralTab.dateTimeEditMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xDataColumn->minimum())); 0426 uiGeneralTab.dateTimeEditMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xDataColumn->maximum())); 0427 } 0428 } 0429 } 0430 } 0431 0432 void XYDataReductionCurveDock::xRangeMinChanged(double value) { 0433 m_dataReductionData.xRange.first() = value; 0434 uiGeneralTab.pbRecalculate->setEnabled(true); 0435 } 0436 0437 void XYDataReductionCurveDock::xRangeMaxChanged(double value) { 0438 m_dataReductionData.xRange.last() = value; 0439 uiGeneralTab.pbRecalculate->setEnabled(true); 0440 } 0441 0442 void XYDataReductionCurveDock::xRangeMinDateTimeChanged(const QDateTime& dateTime) { 0443 if (m_initializing) 0444 return; 0445 0446 m_dataReductionData.xRange.first() = dateTime.toMSecsSinceEpoch(); 0447 uiGeneralTab.pbRecalculate->setEnabled(true); 0448 } 0449 0450 void XYDataReductionCurveDock::xRangeMaxDateTimeChanged(const QDateTime& dateTime) { 0451 if (m_initializing) 0452 return; 0453 0454 m_dataReductionData.xRange.last() = dateTime.toMSecsSinceEpoch(); 0455 uiGeneralTab.pbRecalculate->setEnabled(true); 0456 } 0457 0458 void XYDataReductionCurveDock::typeChanged(int index) { 0459 const auto type = (nsl_geom_linesim_type)index; 0460 m_dataReductionData.type = type; 0461 0462 switch (type) { 0463 case nsl_geom_linesim_type_douglas_peucker: 0464 case nsl_geom_linesim_type_raddist: 0465 case nsl_geom_linesim_type_interp: 0466 case nsl_geom_linesim_type_reumann_witkam: 0467 uiGeneralTab.lOption->setText(i18n("Tolerance (distance):")); 0468 uiGeneralTab.sbTolerance->setDecimals(6); 0469 uiGeneralTab.sbTolerance->setMinimum(0); 0470 uiGeneralTab.sbTolerance->setSingleStep(0.01); 0471 uiGeneralTab.lOption2->hide(); 0472 uiGeneralTab.chkAuto2->hide(); 0473 uiGeneralTab.sbTolerance2->hide(); 0474 if (uiGeneralTab.chkAuto->isChecked()) 0475 updateTolerance(); 0476 break; 0477 case nsl_geom_linesim_type_douglas_peucker_variant: 0478 uiGeneralTab.lOption->setText(i18n("Number of points:")); 0479 uiGeneralTab.sbTolerance->setDecimals(0); 0480 uiGeneralTab.sbTolerance->setMinimum(2); 0481 uiGeneralTab.sbTolerance->setSingleStep(1); 0482 uiGeneralTab.lOption2->hide(); 0483 uiGeneralTab.chkAuto2->hide(); 0484 uiGeneralTab.sbTolerance2->hide(); 0485 if (uiGeneralTab.chkAuto->isChecked()) 0486 updateTolerance(); 0487 break; 0488 case nsl_geom_linesim_type_nthpoint: 0489 uiGeneralTab.lOption->setText(i18n("Step size:")); 0490 uiGeneralTab.sbTolerance->setValue(10); 0491 uiGeneralTab.sbTolerance->setDecimals(0); 0492 uiGeneralTab.sbTolerance->setMinimum(1); 0493 uiGeneralTab.sbTolerance->setSingleStep(1); 0494 uiGeneralTab.lOption2->hide(); 0495 uiGeneralTab.chkAuto2->hide(); 0496 uiGeneralTab.sbTolerance2->hide(); 0497 break; 0498 case nsl_geom_linesim_type_perpdist: // repeat option 0499 uiGeneralTab.lOption->setText(i18n("Tolerance (distance):")); 0500 uiGeneralTab.sbTolerance->setDecimals(6); 0501 uiGeneralTab.sbTolerance->setMinimum(0); 0502 uiGeneralTab.sbTolerance->setSingleStep(0.01); 0503 uiGeneralTab.sbTolerance2->show(); 0504 uiGeneralTab.lOption2->show(); 0505 uiGeneralTab.chkAuto2->show(); 0506 uiGeneralTab.lOption2->setText(i18n("Repeats:")); 0507 uiGeneralTab.sbTolerance2->setDecimals(0); 0508 uiGeneralTab.sbTolerance2->setMinimum(1); 0509 uiGeneralTab.sbTolerance2->setSingleStep(1); 0510 if (uiGeneralTab.chkAuto->isChecked()) 0511 updateTolerance(); 0512 if (uiGeneralTab.chkAuto2->isChecked()) 0513 updateTolerance2(); 0514 break; 0515 case nsl_geom_linesim_type_visvalingam_whyatt: 0516 uiGeneralTab.lOption->setText(i18n("Tolerance (area):")); 0517 uiGeneralTab.sbTolerance->setDecimals(6); 0518 uiGeneralTab.sbTolerance->setMinimum(0); 0519 uiGeneralTab.sbTolerance->setSingleStep(0.01); 0520 uiGeneralTab.lOption2->hide(); 0521 uiGeneralTab.chkAuto2->hide(); 0522 uiGeneralTab.sbTolerance2->hide(); 0523 if (uiGeneralTab.chkAuto->isChecked()) 0524 updateTolerance(); 0525 break; 0526 case nsl_geom_linesim_type_opheim: // min/max tol options 0527 uiGeneralTab.lOption->setText(i18n("Minimum tolerance:")); 0528 uiGeneralTab.sbTolerance->setDecimals(6); 0529 uiGeneralTab.sbTolerance->setMinimum(0); 0530 uiGeneralTab.sbTolerance->setSingleStep(0.01); 0531 uiGeneralTab.lOption2->setText(i18n("Maximum tolerance:")); 0532 uiGeneralTab.lOption2->show(); 0533 uiGeneralTab.chkAuto2->show(); 0534 uiGeneralTab.sbTolerance2->show(); 0535 uiGeneralTab.sbTolerance2->setDecimals(6); 0536 uiGeneralTab.sbTolerance2->setMinimum(0); 0537 uiGeneralTab.sbTolerance2->setSingleStep(0.01); 0538 if (uiGeneralTab.chkAuto->isChecked()) 0539 updateTolerance(); 0540 if (uiGeneralTab.chkAuto2->isChecked()) 0541 updateTolerance2(); 0542 break; 0543 case nsl_geom_linesim_type_lang: // distance/region 0544 uiGeneralTab.lOption->setText(i18n("Tolerance (distance):")); 0545 uiGeneralTab.sbTolerance->setDecimals(6); 0546 uiGeneralTab.sbTolerance->setMinimum(0); 0547 uiGeneralTab.sbTolerance->setSingleStep(0.01); 0548 uiGeneralTab.lOption2->setText(i18n("Search region:")); 0549 uiGeneralTab.lOption2->show(); 0550 uiGeneralTab.chkAuto2->show(); 0551 uiGeneralTab.sbTolerance2->show(); 0552 uiGeneralTab.sbTolerance2->setDecimals(0); 0553 uiGeneralTab.sbTolerance2->setMinimum(1); 0554 uiGeneralTab.sbTolerance2->setSingleStep(1); 0555 if (uiGeneralTab.chkAuto->isChecked()) 0556 updateTolerance(); 0557 if (uiGeneralTab.chkAuto2->isChecked()) 0558 updateTolerance2(); 0559 break; 0560 } 0561 0562 uiGeneralTab.pbRecalculate->setEnabled(true); 0563 } 0564 0565 void XYDataReductionCurveDock::autoToleranceChanged() { 0566 const auto autoTolerance = (bool)uiGeneralTab.chkAuto->isChecked(); 0567 m_dataReductionData.autoTolerance = autoTolerance; 0568 0569 if (autoTolerance) { 0570 uiGeneralTab.sbTolerance->setEnabled(false); 0571 updateTolerance(); 0572 } else 0573 uiGeneralTab.sbTolerance->setEnabled(true); 0574 } 0575 0576 void XYDataReductionCurveDock::toleranceChanged(double value) { 0577 m_dataReductionData.tolerance = value; 0578 uiGeneralTab.pbRecalculate->setEnabled(true); 0579 } 0580 0581 void XYDataReductionCurveDock::autoTolerance2Changed() { 0582 const auto autoTolerance2 = (bool)uiGeneralTab.chkAuto2->isChecked(); 0583 m_dataReductionData.autoTolerance2 = autoTolerance2; 0584 0585 if (autoTolerance2) { 0586 uiGeneralTab.sbTolerance2->setEnabled(false); 0587 updateTolerance2(); 0588 } else 0589 uiGeneralTab.sbTolerance2->setEnabled(true); 0590 } 0591 0592 void XYDataReductionCurveDock::tolerance2Changed(double value) { 0593 m_dataReductionData.tolerance2 = value; 0594 uiGeneralTab.pbRecalculate->setEnabled(true); 0595 } 0596 0597 void XYDataReductionCurveDock::recalculateClicked() { 0598 //show a progress bar in the status bar 0599 auto* progressBar = new QProgressBar(); 0600 progressBar->setMinimum(0); 0601 progressBar->setMaximum(100); 0602 connect(m_curve, SIGNAL(completed(int)), progressBar, SLOT(setValue(int))); 0603 statusBar->clearMessage(); 0604 statusBar->addWidget(progressBar, 1); 0605 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 0606 0607 for (auto* curve : m_curvesList) 0608 dynamic_cast<XYDataReductionCurve*>(curve)->setDataReductionData(m_dataReductionData); 0609 0610 QApplication::restoreOverrideCursor(); 0611 statusBar->removeWidget(progressBar); 0612 0613 uiGeneralTab.pbRecalculate->setEnabled(false); 0614 emit info(i18n("Data reduction status: %1", m_dataReductionCurve->dataReductionResult().status)); 0615 } 0616 0617 void XYDataReductionCurveDock::enableRecalculate() const { 0618 if (m_initializing) 0619 return; 0620 0621 //no dataReductioning possible without the x- and y-data 0622 bool hasSourceData = false; 0623 if (m_dataReductionCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) { 0624 AbstractAspect* aspectX = static_cast<AbstractAspect*>(cbXDataColumn->currentModelIndex().internalPointer()); 0625 AbstractAspect* aspectY = static_cast<AbstractAspect*>(cbYDataColumn->currentModelIndex().internalPointer()); 0626 hasSourceData = (aspectX != nullptr && aspectY != nullptr); 0627 if (aspectX) { 0628 cbXDataColumn->useCurrentIndexText(true); 0629 cbXDataColumn->setInvalid(false); 0630 } 0631 if (aspectY) { 0632 cbYDataColumn->useCurrentIndexText(true); 0633 cbYDataColumn->setInvalid(false); 0634 } 0635 } else { 0636 hasSourceData = (m_dataReductionCurve->dataSourceCurve() != nullptr); 0637 } 0638 0639 uiGeneralTab.pbRecalculate->setEnabled(hasSourceData); 0640 } 0641 0642 /*! 0643 * show the result and details of the dataReduction 0644 */ 0645 void XYDataReductionCurveDock::showDataReductionResult() { 0646 const XYDataReductionCurve::DataReductionResult& dataReductionResult = m_dataReductionCurve->dataReductionResult(); 0647 if (!dataReductionResult.available) { 0648 uiGeneralTab.teResult->clear(); 0649 return; 0650 } 0651 0652 QString str = i18n("status: %1", dataReductionResult.status) + "<br>"; 0653 0654 if (!dataReductionResult.valid) { 0655 uiGeneralTab.teResult->setText(str); 0656 return; //result is not valid, there was an error which is shown in the status-string, nothing to show more. 0657 } 0658 0659 SET_NUMBER_LOCALE 0660 if (dataReductionResult.elapsedTime > 1000) 0661 str += i18n("calculation time: %1 s", numberLocale.toString(dataReductionResult.elapsedTime/1000)) + "<br>"; 0662 else 0663 str += i18n("calculation time: %1 ms", numberLocale.toString(dataReductionResult.elapsedTime)) + "<br>"; 0664 0665 str += "<br>"; 0666 0667 str += i18n("number of points: %1", numberLocale.toString(static_cast<qulonglong>(dataReductionResult.npoints))) + "<br>"; 0668 str += i18n("positional squared error: %1", numberLocale.toString(dataReductionResult.posError)) + "<br>"; 0669 str += i18n("area error: %1", numberLocale.toString(dataReductionResult.areaError)) + "<br>"; 0670 0671 uiGeneralTab.teResult->setText(str); 0672 } 0673 0674 //************************************************************* 0675 //*********** SLOTs for changes triggered in XYCurve ********** 0676 //************************************************************* 0677 //General-Tab 0678 void XYDataReductionCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { 0679 if (m_curve != aspect) 0680 return; 0681 0682 m_initializing = true; 0683 if (aspect->name() != uiGeneralTab.leName->text()) 0684 uiGeneralTab.leName->setText(aspect->name()); 0685 else if (aspect->comment() != uiGeneralTab.leComment->text()) 0686 uiGeneralTab.leComment->setText(aspect->comment()); 0687 m_initializing = false; 0688 } 0689 0690 void XYDataReductionCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) { 0691 m_initializing = true; 0692 uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(type)); 0693 m_initializing = false; 0694 } 0695 0696 void XYDataReductionCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) { 0697 m_initializing = true; 0698 XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve); 0699 m_initializing = false; 0700 } 0701 0702 void XYDataReductionCurveDock::curveXDataColumnChanged(const AbstractColumn* column) { 0703 m_initializing = true; 0704 XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column); 0705 m_initializing = false; 0706 } 0707 0708 void XYDataReductionCurveDock::curveYDataColumnChanged(const AbstractColumn* column) { 0709 m_initializing = true; 0710 XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column); 0711 m_initializing = false; 0712 } 0713 0714 void XYDataReductionCurveDock::curveDataReductionDataChanged(const XYDataReductionCurve::DataReductionData& dataReductionData) { 0715 m_initializing = true; 0716 m_dataReductionData = dataReductionData; 0717 //uiGeneralTab.cbType->setCurrentIndex(m_dataReductionData.type); 0718 //this->typeChanged(); 0719 0720 this->showDataReductionResult(); 0721 m_initializing = false; 0722 } 0723 0724 void XYDataReductionCurveDock::dataChanged() { 0725 this->enableRecalculate(); 0726 } 0727 0728 void XYDataReductionCurveDock::curveVisibilityChanged(bool on) { 0729 m_initializing = true; 0730 uiGeneralTab.chkVisible->setChecked(on); 0731 m_initializing = false; 0732 }