File indexing completed on 2024-05-12 15:28:02
0001 /*************************************************************************** 0002 File : XYConvolutionCurveDock.cpp 0003 Project : LabPlot 0004 -------------------------------------------------------------------- 0005 Copyright : (C) 2018 Stefan Gerlach (stefan.gerlach@uni.kn) 0006 Description : widget for editing properties of convolution curves 0007 0008 ***************************************************************************/ 0009 0010 /*************************************************************************** 0011 * * 0012 * This program is free software; you can redistribute it and/or modify * 0013 * it under the terms of the GNU General Public License as published by * 0014 * the Free Software Foundation; either version 2 of the License, or * 0015 * (at your option) any later version. * 0016 * * 0017 * This program is distributed in the hope that it will be useful, * 0018 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0020 * GNU General Public License for more details. * 0021 * * 0022 * You should have received a copy of the GNU General Public License * 0023 * along with this program; if not, write to the Free Software * 0024 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0025 * Boston, MA 02110-1301 USA * 0026 * * 0027 ***************************************************************************/ 0028 0029 #include "XYConvolutionCurveDock.h" 0030 #include "backend/core/AspectTreeModel.h" 0031 #include "backend/core/Project.h" 0032 #include "backend/worksheet/plots/cartesian/XYConvolutionCurve.h" 0033 #include "commonfrontend/widgets/TreeViewComboBox.h" 0034 0035 #include <QMenu> 0036 #include <QWidgetAction> 0037 #include <QStandardItemModel> 0038 0039 extern "C" { 0040 #include "backend/nsl/nsl_conv.h" 0041 } 0042 0043 /*! 0044 \class XYConvolutionCurveDock 0045 \brief Provides a widget for editing the properties of the XYConvolutionCurves 0046 (2D-curves defined by a convolution) currently selected in 0047 the project explorer. 0048 0049 If more then one curves are set, the properties of the first column are shown. 0050 The changes of the properties are applied to all curves. 0051 The exclusions are the name, the comment and the datasets (columns) of 0052 the curves - these properties can only be changed if there is only one single curve. 0053 0054 \ingroup kdefrontend 0055 */ 0056 0057 XYConvolutionCurveDock::XYConvolutionCurveDock(QWidget* parent) : XYCurveDock(parent) { 0058 } 0059 0060 /*! 0061 * // Tab "General" 0062 */ 0063 void XYConvolutionCurveDock::setupGeneral() { 0064 DEBUG("XYConvolutionCurveDock::setupGeneral()"); 0065 QWidget* generalTab = new QWidget(ui.tabGeneral); 0066 uiGeneralTab.setupUi(generalTab); 0067 m_leName = uiGeneralTab.leName; 0068 m_leComment = uiGeneralTab.leComment; 0069 0070 auto* gridLayout = static_cast<QGridLayout*>(generalTab->layout()); 0071 gridLayout->setContentsMargins(2,2,2,2); 0072 gridLayout->setHorizontalSpacing(2); 0073 gridLayout->setVerticalSpacing(2); 0074 0075 uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet")); 0076 uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve")); 0077 0078 cbDataSourceCurve = new TreeViewComboBox(generalTab); 0079 gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 3); 0080 cbXDataColumn = new TreeViewComboBox(generalTab); 0081 gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 3); 0082 cbYDataColumn = new TreeViewComboBox(generalTab); 0083 gridLayout->addWidget(cbYDataColumn, 8, 2, 1, 3); 0084 cbY2DataColumn = new TreeViewComboBox(generalTab); 0085 gridLayout->addWidget(cbY2DataColumn, 9, 2, 1, 3); 0086 0087 for (int i = 0; i < NSL_CONV_KERNEL_COUNT; i++) 0088 uiGeneralTab.cbKernel->addItem(i18n(nsl_conv_kernel_name[i])); 0089 0090 uiGeneralTab.sbMin->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max()); 0091 uiGeneralTab.sbMax->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max()); 0092 0093 for (int i = 0; i < NSL_CONV_DIRECTION_COUNT; i++) 0094 uiGeneralTab.cbDirection->addItem(i18n(nsl_conv_direction_name[i])); 0095 for (int i = 0; i < NSL_CONV_TYPE_COUNT; i++) 0096 uiGeneralTab.cbType->addItem(i18n(nsl_conv_type_name[i])); 0097 // nsl_conv_method_type not exposed to user 0098 for (int i = 0; i < NSL_CONV_NORM_COUNT; i++) 0099 uiGeneralTab.cbNorm->addItem(i18n(nsl_conv_norm_name[i])); 0100 for (int i = 0; i < NSL_CONV_WRAP_COUNT; i++) 0101 uiGeneralTab.cbWrap->addItem(i18n(nsl_conv_wrap_name[i])); 0102 0103 uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build")); 0104 0105 auto* layout = new QHBoxLayout(ui.tabGeneral); 0106 layout->setMargin(0); 0107 layout->addWidget(generalTab); 0108 0109 DEBUG("XYConvolutionCurveDock::setupGeneral() DONE"); 0110 0111 //Slots 0112 connect(uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYConvolutionCurveDock::nameChanged ); 0113 connect(uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYConvolutionCurveDock::commentChanged ); 0114 connect(uiGeneralTab.chkVisible, &QCheckBox::clicked, this, &XYConvolutionCurveDock::visibilityChanged); 0115 connect(uiGeneralTab.cbDataSourceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYConvolutionCurveDock::dataSourceTypeChanged); 0116 connect(uiGeneralTab.sbSamplingInterval, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYConvolutionCurveDock::samplingIntervalChanged); 0117 connect(uiGeneralTab.cbKernel, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYConvolutionCurveDock::kernelChanged); 0118 connect(uiGeneralTab.sbKernelSize, QOverload<int>::of(&QSpinBox::valueChanged), this, &XYConvolutionCurveDock::kernelSizeChanged); 0119 connect(uiGeneralTab.cbAutoRange, &QCheckBox::clicked, this, &XYConvolutionCurveDock::autoRangeChanged); 0120 connect(uiGeneralTab.sbMin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYConvolutionCurveDock::xRangeMinChanged); 0121 connect(uiGeneralTab.sbMax, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYConvolutionCurveDock::xRangeMaxChanged); 0122 connect(uiGeneralTab.cbDirection, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYConvolutionCurveDock::directionChanged); 0123 connect(uiGeneralTab.cbType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYConvolutionCurveDock::typeChanged); 0124 connect(uiGeneralTab.cbNorm, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYConvolutionCurveDock::normChanged); 0125 connect(uiGeneralTab.cbWrap, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYConvolutionCurveDock::wrapChanged); 0126 connect(uiGeneralTab.pbRecalculate, &QPushButton::clicked, this, &XYConvolutionCurveDock::recalculateClicked); 0127 0128 connect(cbDataSourceCurve, &TreeViewComboBox::currentModelIndexChanged, this, &XYConvolutionCurveDock::dataSourceCurveChanged); 0129 connect(cbXDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYConvolutionCurveDock::xDataColumnChanged); 0130 connect(cbYDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYConvolutionCurveDock::yDataColumnChanged); 0131 connect(cbY2DataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYConvolutionCurveDock::y2DataColumnChanged); 0132 } 0133 0134 void XYConvolutionCurveDock::initGeneralTab() { 0135 DEBUG("XYConvolutionCurveDock::initGeneralTab()"); 0136 //if there are more then one curve in the list, disable the tab "general" 0137 if (m_curvesList.size() == 1) { 0138 uiGeneralTab.lName->setEnabled(true); 0139 uiGeneralTab.leName->setEnabled(true); 0140 uiGeneralTab.lComment->setEnabled(true); 0141 uiGeneralTab.leComment->setEnabled(true); 0142 0143 uiGeneralTab.leName->setText(m_curve->name()); 0144 uiGeneralTab.leComment->setText(m_curve->comment()); 0145 } else { 0146 uiGeneralTab.lName->setEnabled(false); 0147 uiGeneralTab.leName->setEnabled(false); 0148 uiGeneralTab.lComment->setEnabled(false); 0149 uiGeneralTab.leComment->setEnabled(false); 0150 0151 uiGeneralTab.leName->setText(QString()); 0152 uiGeneralTab.leComment->setText(QString()); 0153 } 0154 0155 auto* analysisCurve = dynamic_cast<XYAnalysisCurve*>(m_curve); 0156 checkColumnAvailability(cbXDataColumn, analysisCurve->xDataColumn(), analysisCurve->xDataColumnPath()); 0157 checkColumnAvailability(cbYDataColumn, analysisCurve->yDataColumn(), analysisCurve->yDataColumnPath()); 0158 checkColumnAvailability(cbY2DataColumn, analysisCurve->y2DataColumn(), analysisCurve->y2DataColumnPath()); 0159 0160 //show the properties of the first curve 0161 m_convolutionCurve = dynamic_cast<XYConvolutionCurve*>(m_curve); 0162 0163 // hide x-Range per default 0164 uiGeneralTab.lXRange->setEnabled(false); 0165 uiGeneralTab.cbAutoRange->setEnabled(false); 0166 0167 uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(m_convolutionCurve->dataSourceType())); 0168 this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex()); 0169 XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_convolutionCurve->dataSourceCurve()); 0170 XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_convolutionCurve->xDataColumn()); 0171 XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_convolutionCurve->yDataColumn()); 0172 XYCurveDock::setModelIndexFromAspect(cbY2DataColumn, m_convolutionCurve->y2DataColumn()); 0173 uiGeneralTab.sbSamplingInterval->setValue(m_convolutionData.samplingInterval); 0174 uiGeneralTab.cbKernel->setCurrentIndex(m_convolutionData.kernel); 0175 uiGeneralTab.sbKernelSize->setValue((int)m_convolutionData.kernelSize); 0176 uiGeneralTab.cbAutoRange->setChecked(m_convolutionData.autoRange); 0177 uiGeneralTab.sbMin->setValue(m_convolutionData.xRange.first()); 0178 uiGeneralTab.sbMax->setValue(m_convolutionData.xRange.last()); 0179 this->autoRangeChanged(); 0180 y2DataColumnChanged(cbY2DataColumn->currentModelIndex()); 0181 0182 // settings 0183 uiGeneralTab.cbDirection->setCurrentIndex(m_convolutionData.direction); 0184 uiGeneralTab.cbType->setCurrentIndex(m_convolutionData.type); 0185 //m_convolutionData.method not used 0186 uiGeneralTab.cbNorm->setCurrentIndex(m_convolutionData.normalize); 0187 uiGeneralTab.cbWrap->setCurrentIndex(m_convolutionData.wrap); 0188 0189 this->directionChanged(); 0190 0191 this->showConvolutionResult(); 0192 0193 uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); 0194 0195 //Slots 0196 connect(m_convolutionCurve, &XYConvolutionCurve::aspectDescriptionChanged, this, &XYConvolutionCurveDock::curveDescriptionChanged); 0197 connect(m_convolutionCurve, &XYConvolutionCurve::dataSourceTypeChanged, this, &XYConvolutionCurveDock::curveDataSourceTypeChanged); 0198 connect(m_convolutionCurve, &XYConvolutionCurve::dataSourceCurveChanged, this, &XYConvolutionCurveDock::curveDataSourceCurveChanged); 0199 connect(m_convolutionCurve, &XYConvolutionCurve::xDataColumnChanged, this, &XYConvolutionCurveDock::curveXDataColumnChanged); 0200 connect(m_convolutionCurve, &XYConvolutionCurve::yDataColumnChanged, this, &XYConvolutionCurveDock::curveYDataColumnChanged); 0201 connect(m_convolutionCurve, &XYConvolutionCurve::y2DataColumnChanged, this, &XYConvolutionCurveDock::curveY2DataColumnChanged); 0202 connect(m_convolutionCurve, &XYConvolutionCurve::convolutionDataChanged, this, &XYConvolutionCurveDock::curveConvolutionDataChanged); 0203 connect(m_convolutionCurve, &XYConvolutionCurve::sourceDataChanged, this, &XYConvolutionCurveDock::enableRecalculate); 0204 connect(m_convolutionCurve, QOverload<bool>::of(&XYCurve::visibilityChanged), this, &XYConvolutionCurveDock::curveVisibilityChanged); 0205 } 0206 0207 void XYConvolutionCurveDock::setModel() { 0208 DEBUG("XYConvolutionCurveDock::setModel()"); 0209 QList<AspectType> list{AspectType::Folder, AspectType::Datapicker, AspectType::Worksheet, 0210 AspectType::CartesianPlot, AspectType::XYCurve, AspectType::XYAnalysisCurve}; 0211 cbDataSourceCurve->setTopLevelClasses(list); 0212 0213 QList<const AbstractAspect*> hiddenAspects; 0214 for (auto* curve : m_curvesList) 0215 hiddenAspects << curve; 0216 cbDataSourceCurve->setHiddenAspects(hiddenAspects); 0217 0218 list = {AspectType::Folder, AspectType::Workbook, AspectType::Datapicker, AspectType::DatapickerCurve, 0219 AspectType::Spreadsheet, AspectType::LiveDataSource, AspectType::Column, 0220 AspectType::Worksheet, AspectType::CartesianPlot, AspectType::XYConvolution 0221 }; 0222 cbXDataColumn->setTopLevelClasses(list); 0223 cbYDataColumn->setTopLevelClasses(list); 0224 cbY2DataColumn->setTopLevelClasses(list); 0225 0226 cbDataSourceCurve->setModel(m_aspectTreeModel); 0227 cbXDataColumn->setModel(m_aspectTreeModel); 0228 cbYDataColumn->setModel(m_aspectTreeModel); 0229 cbY2DataColumn->setModel(m_aspectTreeModel); 0230 0231 XYCurveDock::setModel(); 0232 DEBUG("XYConvolutionCurveDock::setModel() DONE"); 0233 } 0234 0235 /*! 0236 sets the curves. The properties of the curves in the list \c list can be edited in this widget. 0237 */ 0238 void XYConvolutionCurveDock::setCurves(QList<XYCurve*> list) { 0239 m_initializing = true; 0240 m_curvesList = list; 0241 m_curve = list.first(); 0242 m_convolutionCurve = dynamic_cast<XYConvolutionCurve*>(m_curve); 0243 m_aspectTreeModel = new AspectTreeModel(m_curve->project()); 0244 this->setModel(); 0245 m_convolutionData = m_convolutionCurve->convolutionData(); 0246 0247 SET_NUMBER_LOCALE 0248 uiGeneralTab.sbSamplingInterval->setLocale(numberLocale); 0249 uiGeneralTab.sbMin->setLocale(numberLocale); 0250 uiGeneralTab.sbMax->setLocale(numberLocale); 0251 0252 initGeneralTab(); 0253 initTabs(); 0254 m_initializing = false; 0255 0256 //hide the "skip gaps" option after the curves were set 0257 ui.lLineSkipGaps->hide(); 0258 ui.chkLineSkipGaps->hide(); 0259 } 0260 0261 //************************************************************* 0262 //**** SLOTs for changes triggered in XYConvolutionCurveDock ** 0263 //************************************************************* 0264 void XYConvolutionCurveDock::dataSourceTypeChanged(int index) { 0265 auto type = (XYAnalysisCurve::DataSourceType)index; 0266 if (type == XYAnalysisCurve::DataSourceType::Spreadsheet) { 0267 uiGeneralTab.lDataSourceCurve->hide(); 0268 cbDataSourceCurve->hide(); 0269 uiGeneralTab.lXColumn->show(); 0270 cbXDataColumn->show(); 0271 uiGeneralTab.lYColumn->show(); 0272 cbYDataColumn->show(); 0273 uiGeneralTab.lY2Column->show(); 0274 cbY2DataColumn->show(); 0275 uiGeneralTab.lSamplingInterval->show(); 0276 uiGeneralTab.l2SamplingInterval->show(); 0277 uiGeneralTab.sbSamplingInterval->show(); 0278 uiGeneralTab.lKernel->setText(i18n("or Kernel/Size:")); 0279 } else { //xy-curve data source 0280 uiGeneralTab.lDataSourceCurve->show(); 0281 cbDataSourceCurve->show(); 0282 uiGeneralTab.lXColumn->hide(); 0283 cbXDataColumn->hide(); 0284 uiGeneralTab.lYColumn->hide(); 0285 cbYDataColumn->hide(); 0286 uiGeneralTab.lY2Column->hide(); 0287 cbY2DataColumn->hide(); 0288 uiGeneralTab.lSamplingInterval->hide(); 0289 uiGeneralTab.l2SamplingInterval->hide(); 0290 uiGeneralTab.sbSamplingInterval->hide(); 0291 uiGeneralTab.lKernel->setEnabled(true); 0292 uiGeneralTab.lKernel->setText(i18n("with Kernel/Size:")); 0293 uiGeneralTab.cbKernel->setEnabled(true); 0294 uiGeneralTab.sbKernelSize->setEnabled(true); 0295 } 0296 0297 if (m_initializing) 0298 return; 0299 0300 for (auto* curve : m_curvesList) 0301 dynamic_cast<XYConvolutionCurve*>(curve)->setDataSourceType(type); 0302 0303 enableRecalculate(); 0304 } 0305 0306 void XYConvolutionCurveDock::dataSourceCurveChanged(const QModelIndex& index) { 0307 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0308 auto* dataSourceCurve = dynamic_cast<XYCurve*>(aspect); 0309 0310 if (m_initializing) 0311 return; 0312 0313 for (auto* curve : m_curvesList) 0314 dynamic_cast<XYConvolutionCurve*>(curve)->setDataSourceCurve(dataSourceCurve); 0315 } 0316 0317 void XYConvolutionCurveDock::xDataColumnChanged(const QModelIndex& index) { 0318 DEBUG("XYConvolutionCurveDock::xDataColumnChanged()"); 0319 if (m_initializing) 0320 return; 0321 0322 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0323 auto* column = dynamic_cast<AbstractColumn*>(aspect); 0324 0325 for (auto* curve : m_curvesList) 0326 dynamic_cast<XYConvolutionCurve*>(curve)->setXDataColumn(column); 0327 0328 if (column != nullptr) { 0329 if (uiGeneralTab.cbAutoRange->isChecked()) { 0330 uiGeneralTab.sbMin->setValue(column->minimum()); 0331 uiGeneralTab.sbMax->setValue(column->maximum()); 0332 } 0333 } 0334 0335 cbXDataColumn->useCurrentIndexText(true); 0336 cbXDataColumn->setInvalid(false); 0337 } 0338 0339 void XYConvolutionCurveDock::yDataColumnChanged(const QModelIndex& index) { 0340 if (m_initializing) 0341 return; 0342 DEBUG("yDataColumnChanged()"); 0343 0344 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0345 auto* column = dynamic_cast<AbstractColumn*>(aspect); 0346 0347 for (auto* curve : m_curvesList) 0348 dynamic_cast<XYConvolutionCurve*>(curve)->setYDataColumn(column); 0349 0350 cbYDataColumn->useCurrentIndexText(true); 0351 cbYDataColumn->setInvalid(false); 0352 } 0353 0354 void XYConvolutionCurveDock::y2DataColumnChanged(const QModelIndex& index) { 0355 if (m_initializing) 0356 return; 0357 DEBUG("y2DataColumnChanged()"); 0358 0359 auto* aspect = static_cast<AbstractAspect*>(index.internalPointer()); 0360 auto* column = dynamic_cast<AbstractColumn*>(aspect); 0361 0362 for (auto* curve : m_curvesList) 0363 dynamic_cast<XYConvolutionCurve*>(curve)->setY2DataColumn(column); 0364 0365 cbY2DataColumn->useCurrentIndexText(true); 0366 cbY2DataColumn->setInvalid(false); 0367 } 0368 0369 void XYConvolutionCurveDock::samplingIntervalChanged() { 0370 double samplingInterval = uiGeneralTab.sbSamplingInterval->value(); 0371 m_convolutionData.samplingInterval = samplingInterval; 0372 0373 enableRecalculate(); 0374 } 0375 0376 void XYConvolutionCurveDock::kernelChanged() { 0377 auto kernel = (nsl_conv_kernel_type) uiGeneralTab.cbKernel->currentIndex(); 0378 m_convolutionData.kernel = kernel; 0379 0380 //TODO: change selectable sizes 0381 uiGeneralTab.sbKernelSize->setEnabled(true); 0382 switch (kernel) { 0383 case nsl_conv_kernel_avg: // all values allowed 0384 case nsl_conv_kernel_smooth_triangle: 0385 case nsl_conv_kernel_gaussian: 0386 case nsl_conv_kernel_lorentzian: 0387 uiGeneralTab.sbKernelSize->setMinimum(2); 0388 uiGeneralTab.sbKernelSize->setMaximum(999); 0389 uiGeneralTab.sbKernelSize->setSingleStep(1); 0390 uiGeneralTab.sbKernelSize->setValue(2); 0391 break; 0392 case nsl_conv_kernel_smooth_gaussian: 0393 uiGeneralTab.sbKernelSize->setMinimum(5); 0394 uiGeneralTab.sbKernelSize->setMaximum(9); 0395 uiGeneralTab.sbKernelSize->setSingleStep(2); 0396 uiGeneralTab.sbKernelSize->setValue(5); 0397 break; 0398 case nsl_conv_kernel_first_derivative: 0399 uiGeneralTab.sbKernelSize->setMinimum(2); 0400 uiGeneralTab.sbKernelSize->setValue(2); 0401 uiGeneralTab.sbKernelSize->setEnabled(false); 0402 break; 0403 case nsl_conv_kernel_smooth_first_derivative: 0404 uiGeneralTab.sbKernelSize->setMinimum(3); 0405 uiGeneralTab.sbKernelSize->setMaximum(999); 0406 uiGeneralTab.sbKernelSize->setSingleStep(2); 0407 uiGeneralTab.sbKernelSize->setValue(3); 0408 break; 0409 case nsl_conv_kernel_second_derivative: 0410 uiGeneralTab.sbKernelSize->setMinimum(3); 0411 uiGeneralTab.sbKernelSize->setValue(3); 0412 uiGeneralTab.sbKernelSize->setEnabled(false); 0413 break; 0414 case nsl_conv_kernel_third_derivative: 0415 uiGeneralTab.sbKernelSize->setMinimum(4); 0416 uiGeneralTab.sbKernelSize->setValue(4); 0417 uiGeneralTab.sbKernelSize->setEnabled(false); 0418 break; 0419 case nsl_conv_kernel_fourth_derivative: 0420 uiGeneralTab.sbKernelSize->setMinimum(5); 0421 uiGeneralTab.sbKernelSize->setValue(5); 0422 uiGeneralTab.sbKernelSize->setEnabled(false); 0423 break; 0424 } 0425 0426 enableRecalculate(); 0427 } 0428 0429 void XYConvolutionCurveDock::kernelSizeChanged() { 0430 size_t kernelSize = uiGeneralTab.sbKernelSize->value(); 0431 m_convolutionData.kernelSize = kernelSize; 0432 0433 enableRecalculate(); 0434 } 0435 0436 void XYConvolutionCurveDock::autoRangeChanged() { 0437 bool autoRange = uiGeneralTab.cbAutoRange->isChecked(); 0438 m_convolutionData.autoRange = autoRange; 0439 0440 if (autoRange) { 0441 uiGeneralTab.lMin->setEnabled(false); 0442 uiGeneralTab.sbMin->setEnabled(false); 0443 uiGeneralTab.lMax->setEnabled(false); 0444 uiGeneralTab.sbMax->setEnabled(false); 0445 0446 const AbstractColumn* xDataColumn = nullptr; 0447 if (m_convolutionCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) 0448 xDataColumn = m_convolutionCurve->xDataColumn(); 0449 else { 0450 if (m_convolutionCurve->dataSourceCurve()) 0451 xDataColumn = m_convolutionCurve->dataSourceCurve()->xColumn(); 0452 } 0453 0454 if (xDataColumn) { 0455 uiGeneralTab.sbMin->setValue(xDataColumn->minimum()); 0456 uiGeneralTab.sbMax->setValue(xDataColumn->maximum()); 0457 } 0458 } else { 0459 uiGeneralTab.lMin->setEnabled(true); 0460 uiGeneralTab.sbMin->setEnabled(true); 0461 uiGeneralTab.lMax->setEnabled(true); 0462 uiGeneralTab.sbMax->setEnabled(true); 0463 } 0464 0465 } 0466 void XYConvolutionCurveDock::xRangeMinChanged() { 0467 double xMin = uiGeneralTab.sbMin->value(); 0468 0469 m_convolutionData.xRange.first() = xMin; 0470 enableRecalculate(); 0471 } 0472 0473 void XYConvolutionCurveDock::xRangeMaxChanged() { 0474 double xMax = uiGeneralTab.sbMax->value(); 0475 0476 m_convolutionData.xRange.last() = xMax; 0477 enableRecalculate(); 0478 } 0479 0480 void XYConvolutionCurveDock::directionChanged() { 0481 DEBUG("XYConvolutionCurveDock::directionChanged()"); 0482 auto dir = (nsl_conv_direction_type) uiGeneralTab.cbDirection->currentIndex(); 0483 m_convolutionData.direction = dir; 0484 0485 // change name if still default 0486 if ( m_curve->name().compare(i18n("Convolution")) == 0 && dir == nsl_conv_direction_backward) { 0487 m_curve->setName(i18n("Deconvolution")); 0488 uiGeneralTab.leName->setText(m_curve->name()); 0489 } 0490 if (m_curve->name().compare(i18n("Deconvolution")) == 0 && dir == nsl_conv_direction_forward) { 0491 m_curve->setName(i18n("Convolution")); 0492 uiGeneralTab.leName->setText(m_curve->name()); 0493 } 0494 0495 enableRecalculate(); 0496 } 0497 0498 void XYConvolutionCurveDock::typeChanged() { 0499 auto type = (nsl_conv_type_type)uiGeneralTab.cbType->currentIndex(); 0500 m_convolutionData.type = type; 0501 0502 enableRecalculate(); 0503 } 0504 0505 void XYConvolutionCurveDock::normChanged() { 0506 auto norm = (nsl_conv_norm_type)uiGeneralTab.cbNorm->currentIndex(); 0507 m_convolutionData.normalize = norm; 0508 0509 enableRecalculate(); 0510 } 0511 0512 void XYConvolutionCurveDock::wrapChanged() { 0513 auto wrap = (nsl_conv_wrap_type)uiGeneralTab.cbWrap->currentIndex(); 0514 m_convolutionData.wrap = wrap; 0515 0516 enableRecalculate(); 0517 } 0518 0519 void XYConvolutionCurveDock::recalculateClicked() { 0520 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); 0521 0522 for (auto* curve : m_curvesList) 0523 dynamic_cast<XYConvolutionCurve*>(curve)->setConvolutionData(m_convolutionData); 0524 0525 uiGeneralTab.pbRecalculate->setEnabled(false); 0526 if (m_convolutionData.direction == nsl_conv_direction_forward) 0527 emit info(i18n("Convolution status: %1", m_convolutionCurve->convolutionResult().status)); 0528 else 0529 emit info(i18n("Deconvolution status: %1", m_convolutionCurve->convolutionResult().status)); 0530 QApplication::restoreOverrideCursor(); 0531 } 0532 0533 void XYConvolutionCurveDock::enableRecalculate() const { 0534 DEBUG("XYConvolutionCurveDock::enableRecalculate()"); 0535 if (m_initializing) 0536 return; 0537 0538 bool hasSourceData = false; 0539 //no convolution possible without the y-data 0540 if (m_convolutionCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) { 0541 AbstractAspect* aspectY = static_cast<AbstractAspect*>(cbYDataColumn->currentModelIndex().internalPointer()); 0542 hasSourceData = (aspectY != nullptr); 0543 if (aspectY) { 0544 cbYDataColumn->useCurrentIndexText(true); 0545 cbYDataColumn->setInvalid(false); 0546 } 0547 } else { 0548 hasSourceData = (m_convolutionCurve->dataSourceCurve() != nullptr); 0549 } 0550 0551 uiGeneralTab.pbRecalculate->setEnabled(hasSourceData); 0552 } 0553 0554 /*! 0555 * show the result and details of the convolution 0556 */ 0557 void XYConvolutionCurveDock::showConvolutionResult() { 0558 const XYConvolutionCurve::ConvolutionResult& convolutionResult = m_convolutionCurve->convolutionResult(); 0559 if (!convolutionResult.available) { 0560 uiGeneralTab.teResult->clear(); 0561 return; 0562 } 0563 0564 QString str = i18n("status: %1", convolutionResult.status) + "<br>"; 0565 0566 if (!convolutionResult.valid) { 0567 uiGeneralTab.teResult->setText(str); 0568 return; //result is not valid, there was an error which is shown in the status-string, nothing to show more. 0569 } 0570 0571 SET_NUMBER_LOCALE 0572 if (convolutionResult.elapsedTime > 1000) 0573 str += i18n("calculation time: %1 s", numberLocale.toString(convolutionResult.elapsedTime/1000)) + "<br>"; 0574 else 0575 str += i18n("calculation time: %1 ms", numberLocale.toString(convolutionResult.elapsedTime)) + "<br>"; 0576 0577 str += "<br><br>"; 0578 0579 uiGeneralTab.teResult->setText(str); 0580 0581 //enable the "recalculate"-button if the source data was changed since the last convolution 0582 uiGeneralTab.pbRecalculate->setEnabled(m_convolutionCurve->isSourceDataChangedSinceLastRecalc()); 0583 } 0584 0585 //************************************************************* 0586 //*********** SLOTs for changes triggered in XYCurve ********** 0587 //************************************************************* 0588 //General-Tab 0589 void XYConvolutionCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { 0590 if (m_curve != aspect) 0591 return; 0592 0593 m_initializing = true; 0594 if (aspect->name() != uiGeneralTab.leName->text()) 0595 uiGeneralTab.leName->setText(aspect->name()); 0596 else if (aspect->comment() != uiGeneralTab.leComment->text()) 0597 uiGeneralTab.leComment->setText(aspect->comment()); 0598 m_initializing = false; 0599 } 0600 0601 void XYConvolutionCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) { 0602 m_initializing = true; 0603 uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(type)); 0604 m_initializing = false; 0605 } 0606 0607 void XYConvolutionCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) { 0608 m_initializing = true; 0609 XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve); 0610 m_initializing = false; 0611 } 0612 0613 void XYConvolutionCurveDock::curveXDataColumnChanged(const AbstractColumn* column) { 0614 DEBUG("XYConvolutionCurveDock::curveXDataColumnChanged()"); 0615 m_initializing = true; 0616 XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column); 0617 if (column != nullptr) { 0618 DEBUG("X Column available"); 0619 uiGeneralTab.lXRange->setEnabled(true); 0620 uiGeneralTab.cbAutoRange->setEnabled(true); 0621 uiGeneralTab.lSamplingInterval->setEnabled(false); 0622 uiGeneralTab.l2SamplingInterval->setEnabled(false); 0623 uiGeneralTab.sbSamplingInterval->setEnabled(false); 0624 } else { 0625 DEBUG("X Column not available"); 0626 uiGeneralTab.lXRange->setEnabled(false); 0627 uiGeneralTab.cbAutoRange->setEnabled(false); 0628 uiGeneralTab.lSamplingInterval->setEnabled(true); 0629 uiGeneralTab.l2SamplingInterval->setEnabled(true); 0630 uiGeneralTab.sbSamplingInterval->setEnabled(true); 0631 } 0632 m_initializing = false; 0633 } 0634 0635 void XYConvolutionCurveDock::curveYDataColumnChanged(const AbstractColumn* column) { 0636 DEBUG("XYConvolutionCurveDock::curveYDataColumnChanged()"); 0637 m_initializing = true; 0638 XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column); 0639 m_initializing = false; 0640 } 0641 0642 void XYConvolutionCurveDock::curveY2DataColumnChanged(const AbstractColumn* column) { 0643 DEBUG("XYConvolutionCurveDock::curveY2DataColumnChanged()"); 0644 m_initializing = true; 0645 XYCurveDock::setModelIndexFromAspect(cbY2DataColumn, column); 0646 if (column != nullptr) { 0647 DEBUG("Y2 Column available"); 0648 uiGeneralTab.lKernel->setEnabled(false); 0649 uiGeneralTab.cbKernel->setEnabled(false); 0650 uiGeneralTab.sbKernelSize->setEnabled(false); 0651 } else { 0652 DEBUG("Y2 Column not available"); 0653 uiGeneralTab.lKernel->setEnabled(true); 0654 uiGeneralTab.cbKernel->setEnabled(true); 0655 uiGeneralTab.sbKernelSize->setEnabled(true); 0656 } 0657 m_initializing = false; 0658 } 0659 0660 void XYConvolutionCurveDock::curveConvolutionDataChanged(const XYConvolutionCurve::ConvolutionData& convolutionData) { 0661 m_initializing = true; 0662 m_convolutionData = convolutionData; 0663 this->directionChanged(); 0664 0665 this->showConvolutionResult(); 0666 m_initializing = false; 0667 } 0668 0669 void XYConvolutionCurveDock::dataChanged() { 0670 this->enableRecalculate(); 0671 } 0672 0673 void XYConvolutionCurveDock::curveVisibilityChanged(bool on) { 0674 m_initializing = true; 0675 uiGeneralTab.chkVisible->setChecked(on); 0676 m_initializing = false; 0677 }