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

0001 /***************************************************************************
0002     File             : XYIntegrationCurveDock.cpp
0003     Project          : LabPlot
0004     --------------------------------------------------------------------
0005     Copyright        : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn)
0006     Description      : widget for editing properties of integration 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 "XYIntegrationCurveDock.h"
0030 #include "backend/core/AspectTreeModel.h"
0031 #include "backend/core/Project.h"
0032 #include "backend/worksheet/plots/cartesian/XYIntegrationCurve.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_int.h"
0041 }
0042 
0043 /*!
0044   \class XYIntegrationCurveDock
0045  \brief  Provides a widget for editing the properties of the XYIntegrationCurves
0046         (2D-curves defined by a integration) 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 XYIntegrationCurveDock::XYIntegrationCurveDock(QWidget* parent) : XYCurveDock(parent) {
0058 }
0059 
0060 /*!
0061  *  // Tab "General"
0062  */
0063 void XYIntegrationCurveDock::setupGeneral() {
0064     QWidget* generalTab = new QWidget(ui.tabGeneral);
0065     uiGeneralTab.setupUi(generalTab);
0066     m_leName = uiGeneralTab.leName;
0067     m_leComment = uiGeneralTab.leComment;
0068 
0069     auto* gridLayout = static_cast<QGridLayout*>(generalTab->layout());
0070     gridLayout->setContentsMargins(2,2,2,2);
0071     gridLayout->setHorizontalSpacing(2);
0072     gridLayout->setVerticalSpacing(2);
0073 
0074     uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet"));
0075     uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve"));
0076 
0077     cbDataSourceCurve = new TreeViewComboBox(generalTab);
0078     gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 3);
0079     cbXDataColumn = new TreeViewComboBox(generalTab);
0080     gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 3);
0081     cbYDataColumn = new TreeViewComboBox(generalTab);
0082     gridLayout->addWidget(cbYDataColumn, 7, 2, 1, 3);
0083 
0084     for (int i = 0; i < NSL_INT_NETHOD_COUNT; i++)
0085         uiGeneralTab.cbMethod->addItem(i18n(nsl_int_method_name[i]));
0086 
0087     //TODO: use line edits
0088     uiGeneralTab.sbMin->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
0089     uiGeneralTab.sbMax->setRange(-std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
0090 
0091     uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build"));
0092 
0093     auto* layout = new QHBoxLayout(ui.tabGeneral);
0094     layout->setMargin(0);
0095     layout->addWidget(generalTab);
0096 
0097     //Slots
0098     connect(uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYIntegrationCurveDock::nameChanged );
0099     connect(uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYIntegrationCurveDock::commentChanged );
0100     connect(uiGeneralTab.chkVisible, &QCheckBox::clicked, this, &XYIntegrationCurveDock::visibilityChanged);
0101     connect(uiGeneralTab.cbDataSourceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYIntegrationCurveDock::dataSourceTypeChanged);
0102     connect(uiGeneralTab.cbAutoRange, &QCheckBox::clicked, this, &XYIntegrationCurveDock::autoRangeChanged);
0103     connect(uiGeneralTab.sbMin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYIntegrationCurveDock::xRangeMinChanged);
0104     connect(uiGeneralTab.sbMax, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &XYIntegrationCurveDock::xRangeMaxChanged);
0105     connect(uiGeneralTab.dateTimeEditMin, &QDateTimeEdit::dateTimeChanged, this, &XYIntegrationCurveDock::xRangeMinDateTimeChanged);
0106     connect(uiGeneralTab.dateTimeEditMax, &QDateTimeEdit::dateTimeChanged, this, &XYIntegrationCurveDock::xRangeMaxDateTimeChanged);
0107     connect(uiGeneralTab.cbMethod, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYIntegrationCurveDock::methodChanged);
0108     connect(uiGeneralTab.cbAbsolute, &QCheckBox::clicked, this, &XYIntegrationCurveDock::absoluteChanged);
0109     connect(uiGeneralTab.pbRecalculate, &QPushButton::clicked, this, &XYIntegrationCurveDock::recalculateClicked);
0110 
0111     connect(cbDataSourceCurve, &TreeViewComboBox::currentModelIndexChanged, this, &XYIntegrationCurveDock::dataSourceCurveChanged);
0112     connect(cbXDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYIntegrationCurveDock::xDataColumnChanged);
0113     connect(cbYDataColumn, &TreeViewComboBox::currentModelIndexChanged, this, &XYIntegrationCurveDock::yDataColumnChanged);
0114 }
0115 
0116 void XYIntegrationCurveDock::initGeneralTab() {
0117     //if there are more then one curve in the list, disable the tab "general"
0118     if (m_curvesList.size() == 1) {
0119         uiGeneralTab.lName->setEnabled(true);
0120         uiGeneralTab.leName->setEnabled(true);
0121         uiGeneralTab.lComment->setEnabled(true);
0122         uiGeneralTab.leComment->setEnabled(true);
0123 
0124         uiGeneralTab.leName->setText(m_curve->name());
0125         uiGeneralTab.leComment->setText(m_curve->comment());
0126     } else {
0127         uiGeneralTab.lName->setEnabled(false);
0128         uiGeneralTab.leName->setEnabled(false);
0129         uiGeneralTab.lComment->setEnabled(false);
0130         uiGeneralTab.leComment->setEnabled(false);
0131 
0132         uiGeneralTab.leName->setText(QString());
0133         uiGeneralTab.leComment->setText(QString());
0134     }
0135 
0136     //show the properties of the first curve
0137     m_integrationCurve = static_cast<XYIntegrationCurve*>(m_curve);
0138     checkColumnAvailability(cbXDataColumn, m_integrationCurve->xDataColumn(), m_integrationCurve->xDataColumnPath());
0139     checkColumnAvailability(cbYDataColumn, m_integrationCurve->yDataColumn(), m_integrationCurve->yDataColumnPath());
0140 
0141     //data source
0142     uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(m_integrationCurve->dataSourceType()));
0143     this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex());
0144     XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_integrationCurve->dataSourceCurve());
0145     XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_integrationCurve->xDataColumn());
0146     XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_integrationCurve->yDataColumn());
0147 
0148     //range widgets
0149     const auto* plot = static_cast<const CartesianPlot*>(m_integrationCurve->parentAspect());
0150     m_dateTimeRange = (plot->xRangeFormat() != CartesianPlot::RangeFormat::Numeric);
0151     if (!m_dateTimeRange) {
0152         uiGeneralTab.sbMin->setValue(m_integrationData.xRange.first());
0153         uiGeneralTab.sbMax->setValue(m_integrationData.xRange.last());
0154     } else {
0155         uiGeneralTab.dateTimeEditMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_integrationData.xRange.first()) );
0156         uiGeneralTab.dateTimeEditMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_integrationData.xRange.last()) );
0157     }
0158 
0159     uiGeneralTab.lMin->setVisible(!m_dateTimeRange);
0160     uiGeneralTab.sbMin->setVisible(!m_dateTimeRange);
0161     uiGeneralTab.lMax->setVisible(!m_dateTimeRange);
0162     uiGeneralTab.sbMax->setVisible(!m_dateTimeRange);
0163     uiGeneralTab.lMinDateTime->setVisible(m_dateTimeRange);
0164     uiGeneralTab.dateTimeEditMin->setVisible(m_dateTimeRange);
0165     uiGeneralTab.lMaxDateTime->setVisible(m_dateTimeRange);
0166     uiGeneralTab.dateTimeEditMax->setVisible(m_dateTimeRange);
0167 
0168     //auto range
0169     uiGeneralTab.cbAutoRange->setChecked(m_integrationData.autoRange);
0170     this->autoRangeChanged();
0171 
0172     // update list of selectable types
0173     xDataColumnChanged(cbXDataColumn->currentModelIndex());
0174 
0175     uiGeneralTab.cbMethod->setCurrentIndex(m_integrationData.method);
0176     this->methodChanged(m_integrationData.method);
0177     uiGeneralTab.cbAbsolute->setChecked(m_integrationData.absolute);
0178     this->absoluteChanged();
0179 
0180     this->showIntegrationResult();
0181 
0182     uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() );
0183 
0184     //Slots
0185     connect(m_integrationCurve, &XYIntegrationCurve::aspectDescriptionChanged, this, &XYIntegrationCurveDock::curveDescriptionChanged);
0186     connect(m_integrationCurve, &XYIntegrationCurve::dataSourceTypeChanged, this, &XYIntegrationCurveDock::curveDataSourceTypeChanged);
0187     connect(m_integrationCurve, &XYIntegrationCurve::dataSourceCurveChanged, this, &XYIntegrationCurveDock::curveDataSourceCurveChanged);
0188     connect(m_integrationCurve, &XYIntegrationCurve::xDataColumnChanged, this, &XYIntegrationCurveDock::curveXDataColumnChanged);
0189     connect(m_integrationCurve, &XYIntegrationCurve::yDataColumnChanged, this, &XYIntegrationCurveDock::curveYDataColumnChanged);
0190     connect(m_integrationCurve, &XYIntegrationCurve::integrationDataChanged, this, &XYIntegrationCurveDock::curveIntegrationDataChanged);
0191     connect(m_integrationCurve, &XYIntegrationCurve::sourceDataChanged, this, &XYIntegrationCurveDock::enableRecalculate);
0192     connect(m_integrationCurve, QOverload<bool>::of(&XYCurve::visibilityChanged), this, &XYIntegrationCurveDock::curveVisibilityChanged);
0193 }
0194 
0195 void XYIntegrationCurveDock::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 XYIntegrationCurveDock::setCurves(QList<XYCurve*> list) {
0223     m_initializing = true;
0224     m_curvesList = list;
0225     m_curve = list.first();
0226     m_aspect = m_curve;
0227     m_integrationCurve = dynamic_cast<XYIntegrationCurve*>(m_curve);
0228     m_aspectTreeModel = new AspectTreeModel(m_curve->project());
0229     this->setModel();
0230     m_integrationData = m_integrationCurve->integrationData();
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 
0249 void XYIntegrationCurveDock::dataSourceTypeChanged(int index) {
0250     const auto type = (XYAnalysisCurve::DataSourceType)index;
0251     if (type == XYAnalysisCurve::DataSourceType::Spreadsheet) {
0252         uiGeneralTab.lDataSourceCurve->hide();
0253         cbDataSourceCurve->hide();
0254         uiGeneralTab.lXColumn->show();
0255         cbXDataColumn->show();
0256         uiGeneralTab.lYColumn->show();
0257         cbYDataColumn->show();
0258     } else {
0259         uiGeneralTab.lDataSourceCurve->show();
0260         cbDataSourceCurve->show();
0261         uiGeneralTab.lXColumn->hide();
0262         cbXDataColumn->hide();
0263         uiGeneralTab.lYColumn->hide();
0264         cbYDataColumn->hide();
0265     }
0266 
0267     if (m_initializing)
0268         return;
0269 
0270     for (auto* curve : m_curvesList)
0271         dynamic_cast<XYIntegrationCurve*>(curve)->setDataSourceType(type);
0272 }
0273 
0274 void XYIntegrationCurveDock::dataSourceCurveChanged(const QModelIndex& index) {
0275     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
0276     auto* dataSourceCurve = dynamic_cast<XYCurve*>(aspect);
0277 
0278     // disable integration orders and accuracies that need more data points
0279     this->updateSettings(dataSourceCurve->xColumn());
0280 
0281     if (m_initializing)
0282         return;
0283 
0284     for (auto* curve : m_curvesList)
0285         dynamic_cast<XYIntegrationCurve*>(curve)->setDataSourceCurve(dataSourceCurve);
0286 }
0287 
0288 void XYIntegrationCurveDock::xDataColumnChanged(const QModelIndex& index) {
0289     if (m_initializing)
0290         return;
0291 
0292     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
0293     auto* column = dynamic_cast<AbstractColumn*>(aspect);
0294 
0295     for (auto* curve : m_curvesList)
0296         dynamic_cast<XYIntegrationCurve*>(curve)->setXDataColumn(column);
0297 
0298     if (column != nullptr) {
0299         if (uiGeneralTab.cbAutoRange->isChecked()) {
0300             uiGeneralTab.sbMin->setValue(column->minimum());
0301             uiGeneralTab.sbMax->setValue(column->maximum());
0302         }
0303 
0304         // disable integration methods that need more data points
0305         this->updateSettings(column);
0306     }
0307 
0308     cbXDataColumn->useCurrentIndexText(true);
0309     cbXDataColumn->setInvalid(false);
0310 }
0311 
0312 /*!
0313  * disable deriv orders and accuracies that need more data points
0314  */
0315 void XYIntegrationCurveDock::updateSettings(const AbstractColumn* column) {
0316     if (!column)
0317         return;
0318 
0319     //TODO
0320 //  size_t n = 0;
0321 //  for (int row = 0; row < column->rowCount(); row++)
0322 //      if (!std::isnan(column->valueAt(row)) && !column->isMasked(row))
0323 //          n++;
0324 }
0325 void XYIntegrationCurveDock::yDataColumnChanged(const QModelIndex& index) {
0326     if (m_initializing)
0327         return;
0328 
0329     cbYDataColumn->hidePopup();
0330 
0331     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
0332     auto* column = dynamic_cast<AbstractColumn*>(aspect);
0333 
0334     for (auto* curve : m_curvesList)
0335         dynamic_cast<XYIntegrationCurve*>(curve)->setYDataColumn(column);
0336 
0337     cbYDataColumn->useCurrentIndexText(true);
0338     cbYDataColumn->setInvalid(false);
0339 }
0340 
0341 void XYIntegrationCurveDock::autoRangeChanged() {
0342     bool autoRange = uiGeneralTab.cbAutoRange->isChecked();
0343     m_integrationData.autoRange = autoRange;
0344 
0345     uiGeneralTab.lMin->setEnabled(!autoRange);
0346     uiGeneralTab.sbMin->setEnabled(!autoRange);
0347     uiGeneralTab.lMax->setEnabled(!autoRange);
0348     uiGeneralTab.sbMax->setEnabled(!autoRange);
0349     uiGeneralTab.lMinDateTime->setEnabled(!autoRange);
0350     uiGeneralTab.dateTimeEditMin->setEnabled(!autoRange);
0351     uiGeneralTab.lMaxDateTime->setEnabled(!autoRange);
0352     uiGeneralTab.dateTimeEditMax->setEnabled(!autoRange);
0353 
0354     if (autoRange) {
0355         const AbstractColumn* xDataColumn = nullptr;
0356         if (m_integrationCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet)
0357             xDataColumn = m_integrationCurve->xDataColumn();
0358         else {
0359             if (m_integrationCurve->dataSourceCurve())
0360                 xDataColumn = m_integrationCurve->dataSourceCurve()->xColumn();
0361         }
0362 
0363         if (xDataColumn) {
0364             if (!m_dateTimeRange) {
0365                 uiGeneralTab.sbMin->setValue(xDataColumn->minimum());
0366                 uiGeneralTab.sbMax->setValue(xDataColumn->maximum());
0367             } else {
0368                 uiGeneralTab.dateTimeEditMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xDataColumn->minimum()));
0369                 uiGeneralTab.dateTimeEditMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xDataColumn->maximum()));
0370             }
0371         }
0372     }
0373 }
0374 
0375 void XYIntegrationCurveDock::xRangeMinChanged(double value) {
0376     m_integrationData.xRange.first() = value;
0377     uiGeneralTab.pbRecalculate->setEnabled(true);
0378 }
0379 
0380 void XYIntegrationCurveDock::xRangeMaxChanged(double value) {
0381     m_integrationData.xRange.last() = value;
0382     uiGeneralTab.pbRecalculate->setEnabled(true);
0383 }
0384 
0385 void XYIntegrationCurveDock::xRangeMinDateTimeChanged(const QDateTime& dateTime) {
0386     if (m_initializing)
0387         return;
0388 
0389     m_integrationData.xRange.first() = dateTime.toMSecsSinceEpoch();
0390     uiGeneralTab.pbRecalculate->setEnabled(true);
0391 }
0392 
0393 void XYIntegrationCurveDock::xRangeMaxDateTimeChanged(const QDateTime& dateTime) {
0394     if (m_initializing)
0395         return;
0396 
0397     m_integrationData.xRange.last() = dateTime.toMSecsSinceEpoch();
0398     uiGeneralTab.pbRecalculate->setEnabled(true);
0399 }
0400 
0401 void XYIntegrationCurveDock::methodChanged(int index) {
0402     const auto method = (nsl_int_method_type)index;
0403     m_integrationData.method = method;
0404 
0405     // update absolute option
0406     switch (method) {
0407     case nsl_int_method_rectangle:
0408     case nsl_int_method_trapezoid:
0409         uiGeneralTab.cbAbsolute->setEnabled(true);
0410         break;
0411     case nsl_int_method_simpson:
0412     case nsl_int_method_simpson_3_8:
0413         uiGeneralTab.cbAbsolute->setChecked(false);
0414         uiGeneralTab.cbAbsolute->setEnabled(false);
0415     }
0416 
0417     uiGeneralTab.pbRecalculate->setEnabled(true);
0418 }
0419 
0420 void XYIntegrationCurveDock::absoluteChanged() {
0421     bool absolute = uiGeneralTab.cbAbsolute->isChecked();
0422     m_integrationData.absolute = absolute;
0423 
0424     uiGeneralTab.pbRecalculate->setEnabled(true);
0425 }
0426 
0427 void XYIntegrationCurveDock::recalculateClicked() {
0428     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
0429 
0430     for (auto* curve : m_curvesList)
0431         dynamic_cast<XYIntegrationCurve*>(curve)->setIntegrationData(m_integrationData);
0432 
0433     uiGeneralTab.pbRecalculate->setEnabled(false);
0434     emit info(i18n("Integration status: %1", m_integrationCurve->integrationResult().status));
0435     QApplication::restoreOverrideCursor();
0436 }
0437 
0438 void XYIntegrationCurveDock::enableRecalculate() const {
0439     if (m_initializing)
0440         return;
0441 
0442     //no integration possible without the x- and y-data
0443     bool hasSourceData = false;
0444     if (m_integrationCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet) {
0445         AbstractAspect* aspectX = static_cast<AbstractAspect*>(cbXDataColumn->currentModelIndex().internalPointer());
0446         AbstractAspect* aspectY = static_cast<AbstractAspect*>(cbYDataColumn->currentModelIndex().internalPointer());
0447         hasSourceData = (aspectX != nullptr && aspectY != nullptr);
0448         if (aspectX) {
0449             cbXDataColumn->useCurrentIndexText(true);
0450             cbXDataColumn->setInvalid(false);
0451         }
0452         if (aspectY) {
0453             cbYDataColumn->useCurrentIndexText(true);
0454             cbYDataColumn->setInvalid(false);
0455         }
0456     } else {
0457          hasSourceData = (m_integrationCurve->dataSourceCurve() != nullptr);
0458     }
0459 
0460     uiGeneralTab.pbRecalculate->setEnabled(hasSourceData);
0461 }
0462 
0463 /*!
0464  * show the result and details of the integration
0465  */
0466 void XYIntegrationCurveDock::showIntegrationResult() {
0467     const XYIntegrationCurve::IntegrationResult& integrationResult = m_integrationCurve->integrationResult();
0468     if (!integrationResult.available) {
0469         uiGeneralTab.teResult->clear();
0470         return;
0471     }
0472 
0473     QString str = i18n("status: %1", integrationResult.status) + "<br>";
0474 
0475     if (!integrationResult.valid) {
0476         uiGeneralTab.teResult->setText(str);
0477         return; //result is not valid, there was an error which is shown in the status-string, nothing to show more.
0478     }
0479 
0480     SET_NUMBER_LOCALE
0481     if (integrationResult.elapsedTime > 1000)
0482         str += i18n("calculation time: %1 s", numberLocale.toString(integrationResult.elapsedTime/1000)) + "<br>";
0483     else
0484         str += i18n("calculation time: %1 ms", numberLocale.toString(integrationResult.elapsedTime)) + "<br>";
0485 
0486     str += i18n("value: %1", numberLocale.toString(integrationResult.value)) + "<br>";
0487     str += "<br><br>";
0488 
0489     uiGeneralTab.teResult->setText(str);
0490 
0491     //enable the "recalculate"-button if the source data was changed since the last integration
0492     uiGeneralTab.pbRecalculate->setEnabled(m_integrationCurve->isSourceDataChangedSinceLastRecalc());
0493 }
0494 
0495 //*************************************************************
0496 //*********** SLOTs for changes triggered in XYCurve **********
0497 //*************************************************************
0498 //General-Tab
0499 void XYIntegrationCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) {
0500     if (m_curve != aspect)
0501         return;
0502 
0503     m_initializing = true;
0504     if (aspect->name() != uiGeneralTab.leName->text())
0505         uiGeneralTab.leName->setText(aspect->name());
0506     else if (aspect->comment() != uiGeneralTab.leComment->text())
0507         uiGeneralTab.leComment->setText(aspect->comment());
0508     m_initializing = false;
0509 }
0510 
0511 void XYIntegrationCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) {
0512     m_initializing = true;
0513     uiGeneralTab.cbDataSourceType->setCurrentIndex(static_cast<int>(type));
0514     m_initializing = false;
0515 }
0516 
0517 void XYIntegrationCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) {
0518     m_initializing = true;
0519     XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve);
0520     m_initializing = false;
0521 }
0522 
0523 void XYIntegrationCurveDock::curveXDataColumnChanged(const AbstractColumn* column) {
0524     m_initializing = true;
0525     XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column);
0526     m_initializing = false;
0527 }
0528 
0529 void XYIntegrationCurveDock::curveYDataColumnChanged(const AbstractColumn* column) {
0530     m_initializing = true;
0531     XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column);
0532     m_initializing = false;
0533 }
0534 
0535 void XYIntegrationCurveDock::curveIntegrationDataChanged(const XYIntegrationCurve::IntegrationData& integrationData) {
0536     m_initializing = true;
0537     m_integrationData = integrationData;
0538     uiGeneralTab.cbMethod->setCurrentIndex(m_integrationData.method);
0539     this->methodChanged(m_integrationData.method);
0540     uiGeneralTab.cbAbsolute->setChecked(m_integrationData.absolute);
0541     this->absoluteChanged();
0542 
0543     this->showIntegrationResult();
0544     m_initializing = false;
0545 }
0546 
0547 void XYIntegrationCurveDock::dataChanged() {
0548     this->enableRecalculate();
0549 }
0550 
0551 void XYIntegrationCurveDock::curveVisibilityChanged(bool on) {
0552     m_initializing = true;
0553     uiGeneralTab.chkVisible->setChecked(on);
0554     m_initializing = false;
0555 }