diff --git a/src/kdefrontend/dockwidgets/ColumnDock.cpp b/src/kdefrontend/dockwidgets/ColumnDock.cpp index abd8e0d10..a91a73cb6 100644 --- a/src/kdefrontend/dockwidgets/ColumnDock.cpp +++ b/src/kdefrontend/dockwidgets/ColumnDock.cpp @@ -1,423 +1,423 @@ /*************************************************************************** File : ColumnDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2011-2017 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2013-2017 by Stefan Gerlach (stefan.gerlach@uni.kn) Description : widget for column properties ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "ColumnDock.h" #include "backend/core/AbstractFilter.h" #include "backend/core/datatypes/SimpleCopyThroughFilter.h" #include "backend/core/datatypes/Double2StringFilter.h" #include "backend/core/datatypes/String2DoubleFilter.h" #include "backend/core/datatypes/DateTime2StringFilter.h" #include "backend/core/datatypes/String2DateTimeFilter.h" #include "backend/datasources/LiveDataSource.h" #include "backend/spreadsheet/Spreadsheet.h" #include /*! \class ColumnDock \brief Provides a widget for editing the properties of the spreadsheet columns currently selected in the project explorer. \ingroup kdefrontend */ ColumnDock::ColumnDock(QWidget* parent) : QWidget(parent), m_column(nullptr), m_initializing(false) { ui.setupUi(this); connect(ui.leName, &QLineEdit::textChanged, this, &ColumnDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &ColumnDock::commentChanged); connect(ui.cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); connect(ui.cbFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(formatChanged(int))); connect(ui.sbPrecision, SIGNAL(valueChanged(int)), this, SLOT(precisionChanged(int)) ); connect(ui.cbPlotDesignation, SIGNAL(currentIndexChanged(int)), this, SLOT(plotDesignationChanged(int))); retranslateUi(); } void ColumnDock::setColumns(QList list) { m_initializing = true; m_columnsList = list; m_column = list.first(); //check whether we have non-editable columns (e.g. columns for residuals calculated in XYFitCurve) bool nonEditable = false; for (auto* col: m_columnsList) { - Spreadsheet* s = dynamic_cast(col->parentAspect()); + const auto s = dynamic_cast(col->parentAspect()); if (s) { if (dynamic_cast(s)) { nonEditable = true; break; } } else { nonEditable = true; break; } } if (list.size() == 1) { //names and comments of non-editable columns in a file data source can be changed. if (!nonEditable && dynamic_cast(m_column->parentAspect()) != nullptr) { ui.leName->setEnabled(false); ui.leComment->setEnabled(false); } else { ui.leName->setEnabled(true); ui.leComment->setEnabled(true); } ui.leName->setText(m_column->name()); ui.leComment->setText(m_column->comment()); } else { ui.leName->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(""); ui.leComment->setText(""); } //show the properties of the first column AbstractColumn::ColumnMode columnMode = m_column->columnMode(); ui.cbType->setCurrentIndex(ui.cbType->findData((int)columnMode)); //disable widgets if we have at least one non-editable column ui.cbType->setEnabled(!nonEditable); ui.lFormat->setVisible(!nonEditable); ui.cbFormat->setVisible(!nonEditable); ui.lPrecision->setVisible(!nonEditable); ui.sbPrecision->setVisible(!nonEditable); ui.lPlotDesignation->setVisible(!nonEditable); ui.cbPlotDesignation->setVisible(!nonEditable); if (nonEditable) { m_initializing = false; return; } this->updateFormatWidgets(columnMode); switch(columnMode) { case AbstractColumn::Numeric: { - Double2StringFilter* filter = static_cast(m_column->outputFilter()); + auto filter = static_cast(m_column->outputFilter()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->numericFormat())); ui.sbPrecision->setValue(filter->numDigits()); break; } case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { - DateTime2StringFilter* filter = static_cast(m_column->outputFilter()); + auto filter = static_cast(m_column->outputFilter()); DEBUG(" set column format: " << filter->format().toStdString()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->format())); break; } case AbstractColumn::Integer: // nothing to set case AbstractColumn::Text: break; } ui.cbPlotDesignation->setCurrentIndex( int(m_column->plotDesignation()) ); // slots connect(m_column, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)),this, SLOT(columnDescriptionChanged(const AbstractAspect*))); connect(m_column->outputFilter(), SIGNAL(formatChanged()),this, SLOT(columnFormatChanged())); connect(m_column->outputFilter(), SIGNAL(digitsChanged()),this, SLOT(columnPrecisionChanged())); connect(m_column, SIGNAL(plotDesignationChanged(const AbstractColumn*)),this, SLOT(columnPlotDesignationChanged(const AbstractColumn*))); m_initializing = false; } /*! depending on the currently selected column type (column mode) updates the widgets for the column format, shows/hides the allowed widgets, fills the corresponding combobox with the possible entries. Called when the type (column mode) is changed. */ void ColumnDock::updateFormatWidgets(const AbstractColumn::ColumnMode columnMode) { ui.cbFormat->clear(); switch (columnMode) { case AbstractColumn::Numeric: ui.cbFormat->addItem(i18n("Decimal"), QVariant('f')); ui.cbFormat->addItem(i18n("Scientific (e)"), QVariant('e')); ui.cbFormat->addItem(i18n("Scientific (E)"), QVariant('E')); ui.cbFormat->addItem(i18n("Automatic (g)"), QVariant('g')); ui.cbFormat->addItem(i18n("Automatic (G)"), QVariant('G')); break; case AbstractColumn::Month: ui.cbFormat->addItem(i18n("Number without Leading Zero"), QVariant("M")); ui.cbFormat->addItem(i18n("Number with Leading Zero"), QVariant("MM")); ui.cbFormat->addItem(i18n("Abbreviated Month Name"), QVariant("MMM")); ui.cbFormat->addItem(i18n("Full Month Name"), QVariant("MMMM")); break; case AbstractColumn::Day: ui.cbFormat->addItem(i18n("Number without Leading Zero"), QVariant("d")); ui.cbFormat->addItem(i18n("Number with Leading Zero"), QVariant("dd")); ui.cbFormat->addItem(i18n("Abbreviated Day Name"), QVariant("ddd")); ui.cbFormat->addItem(i18n("Full Day Name"), QVariant("dddd")); break; case AbstractColumn::DateTime: for (const auto& s: AbstractColumn::dateTimeFormats()) ui.cbFormat->addItem(s, QVariant(s)); break; case AbstractColumn::Integer: case AbstractColumn::Text: break; } if (columnMode == AbstractColumn::Numeric) { ui.lPrecision->show(); ui.sbPrecision->show(); } else { ui.lPrecision->hide(); ui.sbPrecision->hide(); } if (columnMode == AbstractColumn::Text || columnMode == AbstractColumn::Integer) { ui.lFormat->hide(); ui.cbFormat->hide(); } else { ui.lFormat->show(); ui.cbFormat->show(); } if (columnMode == AbstractColumn::DateTime) { ui.cbFormat->setEditable(true); ui.cbFormat->setCurrentItem("yyyy-MM-dd hh:mm:ss.zzz"); } else { ui.cbFormat->setEditable(false); ui.cbFormat->setCurrentIndex(0); } } //************************************************************* //******** SLOTs for changes triggered in ColumnDock ********** //************************************************************* void ColumnDock::retranslateUi() { m_initializing = true; ui.cbType->clear(); ui.cbType->addItem(i18n("Numeric"), QVariant(int(AbstractColumn::Numeric))); ui.cbType->addItem(i18n("Integer"), QVariant(int(AbstractColumn::Integer))); ui.cbType->addItem(i18n("Text"), QVariant(int(AbstractColumn::Text))); ui.cbType->addItem(i18n("Month Names"), QVariant(int(AbstractColumn::Month))); ui.cbType->addItem(i18n("Day Names"), QVariant(int(AbstractColumn::Day))); ui.cbType->addItem(i18n("Date and Time"), QVariant(int(AbstractColumn::DateTime))); ui.cbPlotDesignation->clear(); ui.cbPlotDesignation->addItem(i18n("None")); ui.cbPlotDesignation->addItem(i18n("X")); ui.cbPlotDesignation->addItem(i18n("Y")); ui.cbPlotDesignation->addItem(i18n("Z")); ui.cbPlotDesignation->addItem(i18n("X-error")); ui.cbPlotDesignation->addItem(i18n("X-error -")); ui.cbPlotDesignation->addItem(i18n("X-error +")); ui.cbPlotDesignation->addItem(i18n("Y-error")); ui.cbPlotDesignation->addItem(i18n("Y-error -")); ui.cbPlotDesignation->addItem(i18n("Y-error +")); m_initializing = false; } void ColumnDock::nameChanged() { if (m_initializing) return; m_columnsList.first()->setName(ui.leName->text()); } void ColumnDock::commentChanged() { if (m_initializing) return; m_columnsList.first()->setComment(ui.leComment->text()); } /*! called when the type (column mode - numeric, text etc.) of the column was changed. */ void ColumnDock::typeChanged(int index) { DEBUG("ColumnDock::typeChanged()"); if (m_initializing) return; AbstractColumn::ColumnMode columnMode = (AbstractColumn::ColumnMode)ui.cbType->itemData(index).toInt(); int format_index = ui.cbFormat->currentIndex(); m_initializing = true; this->updateFormatWidgets(columnMode); m_initializing = false; switch(columnMode) { case AbstractColumn::Numeric: { int digits = ui.sbPrecision->value(); for (auto* col: m_columnsList) { col->beginMacro(i18n("%1: change column type", col->name())); col->setColumnMode(columnMode); - Double2StringFilter* filter = static_cast(col->outputFilter()); + auto filter = static_cast(col->outputFilter()); filter->setNumericFormat(ui.cbFormat->itemData(format_index).toChar().toLatin1()); filter->setNumDigits(digits); col->endMacro(); } break; } case AbstractColumn::Integer: case AbstractColumn::Text: for (auto* col: m_columnsList) col->setColumnMode(columnMode); break; case AbstractColumn::Month: case AbstractColumn::Day: for (auto* col: m_columnsList) { col->beginMacro(i18n("%1: change column type", col->name())); // the format is saved as item data QString format = ui.cbFormat->itemData(ui.cbFormat->currentIndex()).toString(); col->setColumnMode(columnMode); - DateTime2StringFilter* filter = static_cast(col->outputFilter()); + auto filter = static_cast(col->outputFilter()); filter->setFormat(format); col->endMacro(); } break; case AbstractColumn::DateTime: for (auto* col: m_columnsList) { col->beginMacro(i18n("%1: change column type", col->name())); // the format is the current text QString format = ui.cbFormat->currentText(); col->setColumnMode(columnMode); - DateTime2StringFilter* filter = static_cast(col->outputFilter()); + auto filter = static_cast(col->outputFilter()); filter->setFormat(format); col->endMacro(); } break; } DEBUG("ColumnDock::typeChanged() DONE"); } /*! called when the format for the current type (column mode) was changed. */ void ColumnDock::formatChanged(int index) { DEBUG("ColumnDock::formatChanged()"); if (m_initializing) return; AbstractColumn::ColumnMode mode = (AbstractColumn::ColumnMode)ui.cbType->itemData(ui.cbType->currentIndex()).toInt(); int format_index = index; switch(mode) { case AbstractColumn::Numeric: { for (auto* col: m_columnsList) { - Double2StringFilter* filter = static_cast(col->outputFilter()); + auto filter = static_cast(col->outputFilter()); filter->setNumericFormat(ui.cbFormat->itemData(format_index).toChar().toLatin1()); } break; } case AbstractColumn::Integer: case AbstractColumn::Text: break; case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { QString format = ui.cbFormat->itemData(ui.cbFormat->currentIndex()).toString(); for (auto* col: m_columnsList) { - DateTime2StringFilter* filter = static_cast(col->outputFilter()); + auto filter = static_cast(col->outputFilter()); filter->setFormat(format); } break; } } DEBUG("ColumnDock::formatChanged() DONE"); } void ColumnDock::precisionChanged(int digits) { if (m_initializing) return; for (auto* col: m_columnsList) { - Double2StringFilter* filter = static_cast(col->outputFilter()); + auto filter = static_cast(col->outputFilter()); filter->setNumDigits(digits); } } void ColumnDock::plotDesignationChanged(int index) { if (m_initializing) return; - AbstractColumn::PlotDesignation pd = AbstractColumn::PlotDesignation(index); + auto pd = AbstractColumn::PlotDesignation(index); for (auto* col: m_columnsList) col->setPlotDesignation(pd); } //************************************************************* //********* SLOTs for changes triggered in Column ************* //************************************************************* void ColumnDock::columnDescriptionChanged(const AbstractAspect* aspect) { if (m_column != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } void ColumnDock::columnFormatChanged() { DEBUG("ColumnDock::columnFormatChanged()"); m_initializing = true; AbstractColumn::ColumnMode columnMode = m_column->columnMode(); switch(columnMode) { case AbstractColumn::Numeric: { - Double2StringFilter* filter = static_cast(m_column->outputFilter()); + auto filter = static_cast(m_column->outputFilter()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->numericFormat())); break; } case AbstractColumn::Integer: case AbstractColumn::Text: break; case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { - DateTime2StringFilter* filter = static_cast(m_column->outputFilter()); + auto filter = static_cast(m_column->outputFilter()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->format())); break; } } m_initializing = false; } void ColumnDock::columnPrecisionChanged() { m_initializing = true; - Double2StringFilter* filter = static_cast(m_column->outputFilter()); + auto filter = static_cast(m_column->outputFilter()); ui.sbPrecision->setValue(filter->numDigits()); m_initializing = false; } void ColumnDock::columnPlotDesignationChanged(const AbstractColumn* col) { m_initializing = true; ui.cbPlotDesignation->setCurrentIndex( int(col->plotDesignation()) ); m_initializing = false; } diff --git a/src/kdefrontend/dockwidgets/CustomPointDock.cpp b/src/kdefrontend/dockwidgets/CustomPointDock.cpp index 893eb5b24..960946d4f 100644 --- a/src/kdefrontend/dockwidgets/CustomPointDock.cpp +++ b/src/kdefrontend/dockwidgets/CustomPointDock.cpp @@ -1,503 +1,503 @@ /*************************************************************************** File : CustomPointDock.cpp Project : LabPlot Description : widget for Datapicker-Point properties -------------------------------------------------------------------- Copyright : (C) 2015 Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "CustomPointDock.h" #include "backend/worksheet/Worksheet.h" #include "backend/worksheet/plots/cartesian/CustomPoint.h" #include "kdefrontend/TemplateHandler.h" #include "kdefrontend/GuiTools.h" #include #include #include #include #include CustomPointDock::CustomPointDock(QWidget *parent): QWidget(parent), m_point(nullptr) { ui.setupUi(this); //Validators ui.lePositionX->setValidator( new QDoubleValidator(ui.lePositionX) ); ui.lePositionY->setValidator( new QDoubleValidator(ui.lePositionY) ); //adjust layouts in the tabs - for (int i=0; icount(); ++i) { - QGridLayout* layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); + for (int i = 0; i < ui.tabWidget->count(); ++i) { + auto layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2,2,2,2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } //SLOTS //General connect(ui.leName, &QLineEdit::textChanged, this, &CustomPointDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &CustomPointDock::commentChanged); connect( ui.lePositionX, SIGNAL(returnPressed()), this, SLOT(positionXChanged()) ); connect( ui.lePositionY, SIGNAL(returnPressed()), this, SLOT(positionYChanged()) ); connect( ui.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); //Symbols connect( ui.cbSymbolStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolStyleChanged(int)) ); connect( ui.sbSymbolSize, SIGNAL(valueChanged(double)), this, SLOT(symbolSizeChanged(double)) ); connect( ui.sbSymbolRotation, SIGNAL(valueChanged(int)), this, SLOT(symbolRotationChanged(int)) ); connect( ui.sbSymbolOpacity, SIGNAL(valueChanged(int)), this, SLOT(symbolOpacityChanged(int)) ); connect( ui.cbSymbolFillingStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolFillingStyleChanged(int)) ); connect( ui.kcbSymbolFillingColor, SIGNAL(changed(QColor)), this, SLOT(symbolFillingColorChanged(QColor)) ); connect( ui.cbSymbolBorderStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolBorderStyleChanged(int)) ); connect( ui.kcbSymbolBorderColor, SIGNAL(changed(QColor)), this, SLOT(symbolBorderColorChanged(QColor)) ); connect( ui.sbSymbolBorderWidth, SIGNAL(valueChanged(double)), this, SLOT(symbolBorderWidthChanged(double)) ); //Template handler - TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::CustomPoint); + auto templateHandler = new TemplateHandler(this, TemplateHandler::CustomPoint); ui.verticalLayout->addWidget(templateHandler); connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), this, SLOT(loadConfigFromTemplate(KConfig&))); connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), this, SLOT(saveConfigAsTemplate(KConfig&))); connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); init(); } void CustomPointDock::init() { m_initializing = true; GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, Qt::black); QPainter pa; int iconSize = 20; QPixmap pm(iconSize, iconSize); QPen pen(Qt::SolidPattern, 0); ui.cbSymbolStyle->setIconSize(QSize(iconSize, iconSize)); QTransform trafo; trafo.scale(15, 15); for (int i=0; i<18; ++i) { - Symbol::Style style = (Symbol::Style)i; + auto style = (Symbol::Style)i; pm.fill(Qt::transparent); pa.begin(&pm); pa.setPen( pen ); pa.setRenderHint(QPainter::Antialiasing); pa.translate(iconSize/2,iconSize/2); pa.drawPath(trafo.map(Symbol::pathFromStyle(style))); pa.end(); ui.cbSymbolStyle->addItem(QIcon(pm), Symbol::nameFromStyle(style)); } GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, Qt::black); m_initializing = false; } void CustomPointDock::setPoints(QList list) { m_initializing=true; m_pointsList = list; m_point = list.first(); Q_ASSERT(m_point); //if there are more then one point in the list, disable the comment and name widgets in the tab "general" if (list.size()==1) { ui.lName->setEnabled(true); ui.leName->setEnabled(true); ui.lComment->setEnabled(true); ui.leComment->setEnabled(true); ui.leName->setText(m_point->name()); ui.leComment->setText(m_point->comment()); }else{ ui.lName->setEnabled(false); ui.leName->setEnabled(false); ui.lComment->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(""); ui.leComment->setText(""); } //show the properties of the first custom point this->load(); //SIGNALs/SLOTs // general connect(m_point, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)),this, SLOT(pointDescriptionChanged(const AbstractAspect*))); connect(m_point, SIGNAL(positionChanged(QPointF)), this, SLOT(pointPositionChanged(QPointF))); connect(m_point, SIGNAL(visibleChanged(bool)), this, SLOT(pointVisibilityChanged(bool))); //symbol connect(m_point, SIGNAL(symbolStyleChanged(Symbol::Style)), this, SLOT(pointSymbolStyleChanged(Symbol::Style))); connect(m_point, SIGNAL(symbolSizeChanged(qreal)), this, SLOT(pointSymbolSizeChanged(qreal))); connect(m_point, SIGNAL(symbolRotationAngleChanged(qreal)), this, SLOT(pointSymbolRotationAngleChanged(qreal))); connect(m_point, SIGNAL(symbolOpacityChanged(qreal)), this, SLOT(pointSymbolOpacityChanged(qreal))); connect(m_point, SIGNAL(symbolBrushChanged(QBrush)), this, SLOT(pointSymbolBrushChanged(QBrush))); connect(m_point, SIGNAL(symbolPenChanged(QPen)), this, SLOT(pointSymbolPenChanged(QPen))); } //********************************************************** //**** SLOTs for changes triggered in CustomPointDock ****** //********************************************************** //"General"-tab void CustomPointDock::nameChanged() { if (m_initializing) return; m_point->setName(ui.leName->text()); } void CustomPointDock::commentChanged() { if (m_initializing) return; m_point->setComment(ui.leComment->text()); } void CustomPointDock::positionXChanged() { if (m_initializing) return; QPointF pos = m_point->position(); float x = ui.lePositionX->text().toFloat(); pos.setX(x); for (auto* point : m_pointsList) point->setPosition(pos); } void CustomPointDock::positionYChanged() { if (m_initializing) return; QPointF pos = m_point->position(); float y = ui.lePositionY->text().toFloat(); pos.setY(y); for (auto* point : m_pointsList) point->setPosition(pos); } void CustomPointDock::visibilityChanged(bool state) { if (m_initializing) return; m_point->beginMacro(i18n("%1 CustomPoints: visibility changed", m_pointsList.count())); for (auto* point : m_pointsList) point->setVisible(state); m_point->endMacro(); } void CustomPointDock::symbolStyleChanged(int index) { - Symbol::Style style = Symbol::Style(index); + auto style = Symbol::Style(index); //enable/disable the filling options in the GUI depending on the currently selected points. - if (style!=Symbol::Line && style!=Symbol::Cross) { + if (style != Symbol::Line && style != Symbol::Cross) { ui.cbSymbolFillingStyle->setEnabled(true); bool noBrush = (Qt::BrushStyle(ui.cbSymbolFillingStyle->currentIndex())==Qt::NoBrush); ui.kcbSymbolFillingColor->setEnabled(!noBrush); } else { ui.kcbSymbolFillingColor->setEnabled(false); ui.cbSymbolFillingStyle->setEnabled(false); } bool noLine = (Qt::PenStyle(ui.cbSymbolBorderStyle->currentIndex())== Qt::NoPen); ui.kcbSymbolBorderColor->setEnabled(!noLine); ui.sbSymbolBorderWidth->setEnabled(!noLine); if (m_initializing) return; m_point->beginMacro(i18n("%1 CustomPoints: style changed", m_pointsList.count())); for (auto* point : m_pointsList) point->setSymbolStyle(style); m_point->endMacro(); } void CustomPointDock::symbolSizeChanged(double value) { if (m_initializing) return; m_point->beginMacro(i18n("%1 CustomPoints: size changed", m_pointsList.count())); for (auto* point : m_pointsList) point->setSymbolSize( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); m_point->endMacro(); } void CustomPointDock::symbolRotationChanged(int value) { if (m_initializing) return; m_point->beginMacro(i18n("%1 CustomPoints: rotation changed", m_pointsList.count())); for (auto* point : m_pointsList) point->setSymbolRotationAngle(value); m_point->endMacro(); } void CustomPointDock::symbolOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; m_point->beginMacro(i18n("%1 CustomPoints: opacity changed", m_pointsList.count())); for (auto* point : m_pointsList) point->setSymbolOpacity(opacity); m_point->endMacro(); } void CustomPointDock::symbolFillingStyleChanged(int index) { - Qt::BrushStyle brushStyle = Qt::BrushStyle(index); + auto brushStyle = Qt::BrushStyle(index); ui.kcbSymbolFillingColor->setEnabled(!(brushStyle==Qt::NoBrush)); if (m_initializing) return; QBrush brush; m_point->beginMacro(i18n("%1 CustomPoints: filling style changed", m_pointsList.count())); for (auto* point : m_pointsList) { brush = point->symbolBrush(); brush.setStyle(brushStyle); point->setSymbolBrush(brush); } m_point->endMacro(); } void CustomPointDock::symbolFillingColorChanged(const QColor& color) { if (m_initializing) return; QBrush brush; m_point->beginMacro(i18n("%1 CustomPoints: filling color changed", m_pointsList.count())); for (auto* point : m_pointsList) { brush = point->symbolBrush(); brush.setColor(color); point->setSymbolBrush(brush); } m_point->endMacro(); m_initializing = true; GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, color ); m_initializing = false; } void CustomPointDock::symbolBorderStyleChanged(int index) { - Qt::PenStyle penStyle=Qt::PenStyle(index); + auto penStyle = Qt::PenStyle(index); if ( penStyle == Qt::NoPen ) { ui.kcbSymbolBorderColor->setEnabled(false); ui.sbSymbolBorderWidth->setEnabled(false); } else { ui.kcbSymbolBorderColor->setEnabled(true); ui.sbSymbolBorderWidth->setEnabled(true); } if (m_initializing) return; QPen pen; m_point->beginMacro(i18n("%1 CustomPoints: border style changed", m_pointsList.count())); for (auto* point : m_pointsList) { pen = point->symbolPen(); pen.setStyle(penStyle); point->setSymbolPen(pen); } m_point->endMacro(); } void CustomPointDock::symbolBorderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; m_point->beginMacro(i18n("%1 CustomPoints: border color changed", m_pointsList.count())); for (auto* point : m_pointsList) { pen = point->symbolPen(); pen.setColor(color); point->setSymbolPen(pen); } m_point->endMacro(); m_initializing = true; GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, color); m_initializing = false; } void CustomPointDock::symbolBorderWidthChanged(double value) { if (m_initializing) return; QPen pen; m_point->beginMacro(i18n("%1 CustomPoints: border width changed", m_pointsList.count())); for (auto* point : m_pointsList) { pen = point->symbolPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); point->setSymbolPen(pen); } m_point->endMacro(); } //********************************************************* //**** SLOTs for changes triggered in CustomPoint ********* //********************************************************* //"General"-tab void CustomPointDock::pointDescriptionChanged(const AbstractAspect* aspect) { if (m_point != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) { ui.leName->setText(aspect->name()); } else if (aspect->comment() != ui.leComment->text()) { ui.leComment->setText(aspect->comment()); } m_initializing = false; } void CustomPointDock::pointPositionChanged(QPointF position) { m_initializing = true; ui.lePositionX->setText(QString::number(position.x())); ui.lePositionY->setText(QString::number(position.y())); m_initializing = false; } //"Symbol"-tab void CustomPointDock::pointSymbolStyleChanged(Symbol::Style style) { m_initializing = true; ui.cbSymbolStyle->setCurrentIndex((int)style); m_initializing = false; } void CustomPointDock::pointSymbolSizeChanged(qreal size) { m_initializing = true; ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(size, Worksheet::Point) ); m_initializing = false; } void CustomPointDock::pointSymbolRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbSymbolRotation->setValue(qRound(angle)); m_initializing = false; } void CustomPointDock::pointSymbolOpacityChanged(qreal opacity) { m_initializing = true; ui.sbSymbolOpacity->setValue( qRound(opacity*100.0) ); m_initializing = false; } void CustomPointDock::pointSymbolBrushChanged(const QBrush& brush) { m_initializing = true; ui.cbSymbolFillingStyle->setCurrentIndex((int) brush.style()); ui.kcbSymbolFillingColor->setColor(brush.color()); GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, brush.color()); m_initializing = false; } void CustomPointDock::pointSymbolPenChanged(const QPen& pen) { m_initializing = true; ui.cbSymbolBorderStyle->setCurrentIndex( (int) pen.style()); ui.kcbSymbolBorderColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, pen.color()); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Point)); m_initializing = false; } void CustomPointDock::pointVisibilityChanged(bool on) { m_initializing = true; ui.chkVisible->setChecked(on); m_initializing = false; } //********************************************************** //******************** SETTINGS **************************** //********************************************************** void CustomPointDock::load() { if (!m_point) return; m_initializing = true; ui.lePositionX->setText(QString::number(m_point->position().x())); ui.lePositionY->setText(QString::number(m_point->position().y())); ui.cbSymbolStyle->setCurrentIndex( (int)m_point->symbolStyle() ); ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(m_point->symbolSize(), Worksheet::Point) ); ui.sbSymbolRotation->setValue( m_point->symbolRotationAngle() ); ui.sbSymbolOpacity->setValue( qRound(m_point->symbolOpacity()*100.0) ); ui.cbSymbolFillingStyle->setCurrentIndex( (int) m_point->symbolBrush().style() ); ui.kcbSymbolFillingColor->setColor( m_point->symbolBrush().color() ); ui.cbSymbolBorderStyle->setCurrentIndex( (int) m_point->symbolPen().style() ); ui.kcbSymbolBorderColor->setColor( m_point->symbolPen().color() ); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_point->symbolPen().widthF(), Worksheet::Point) ); ui.chkVisible->setChecked( m_point->isVisible() ); m_initializing = false; } void CustomPointDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QDir::separator()); if (index!=-1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_pointsList.size(); if (size>1) m_point->beginMacro(i18n("%1 custom points: template \"%2\" loaded", size, name)); else m_point->beginMacro(i18n("%1: template \"%2\" loaded", m_point->name(), name)); this->loadConfig(config); m_point->endMacro(); } void CustomPointDock::loadConfig(KConfig& config) { KConfigGroup group = config.group( "CustomPoint" ); ui.cbSymbolStyle->setCurrentIndex( group.readEntry("SymbolStyle", (int)m_point->symbolStyle()) ); ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(group.readEntry("SymbolSize", m_point->symbolSize()), Worksheet::Point) ); ui.sbSymbolRotation->setValue( group.readEntry("SymbolRotation", m_point->symbolRotationAngle()) ); ui.sbSymbolOpacity->setValue( qRound(group.readEntry("SymbolOpacity", m_point->symbolOpacity())*100.0) ); ui.cbSymbolFillingStyle->setCurrentIndex( group.readEntry("SymbolFillingStyle", (int) m_point->symbolBrush().style()) ); ui.kcbSymbolFillingColor->setColor( group.readEntry("SymbolFillingColor", m_point->symbolBrush().color()) ); ui.cbSymbolBorderStyle->setCurrentIndex( group.readEntry("SymbolBorderStyle", (int) m_point->symbolPen().style()) ); ui.kcbSymbolBorderColor->setColor( group.readEntry("SymbolBorderColor", m_point->symbolPen().color()) ); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("SymbolBorderWidth",m_point->symbolPen().widthF()), Worksheet::Point) ); m_initializing=true; GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, ui.kcbSymbolFillingColor->color()); GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, ui.kcbSymbolBorderColor->color()); m_initializing=false; } void CustomPointDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "CustomPoint" ); group.writeEntry("SymbolStyle", ui.cbSymbolStyle->currentText()); group.writeEntry("SymbolSize", Worksheet::convertToSceneUnits(ui.sbSymbolSize->value(),Worksheet::Point)); group.writeEntry("SymbolRotation", ui.sbSymbolRotation->value()); group.writeEntry("SymbolOpacity", ui.sbSymbolOpacity->value()/100 ); group.writeEntry("SymbolFillingStyle", ui.cbSymbolFillingStyle->currentIndex()); group.writeEntry("SymbolFillingColor", ui.kcbSymbolFillingColor->color()); group.writeEntry("SymbolBorderStyle", ui.cbSymbolBorderStyle->currentIndex()); group.writeEntry("SymbolBorderColor", ui.kcbSymbolBorderColor->color()); group.writeEntry("SymbolBorderWidth", Worksheet::convertToSceneUnits(ui.sbSymbolBorderWidth->value(),Worksheet::Point)); config.sync(); } diff --git a/src/kdefrontend/dockwidgets/HistogramDock.cpp b/src/kdefrontend/dockwidgets/HistogramDock.cpp index a5ead47c3..c6f4a0adf 100644 --- a/src/kdefrontend/dockwidgets/HistogramDock.cpp +++ b/src/kdefrontend/dockwidgets/HistogramDock.cpp @@ -1,1732 +1,1731 @@ /*************************************************************************** File : HistogramDock.cpp Project : LabPlot Description : widget for Histogram properties -------------------------------------------------------------------- Copyright : (C) 2016 Anu Mittal (anu22mittal@gmail.com) Copyright : (C) 2018 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "HistogramDock.h" #include "backend/worksheet/plots/cartesian/Histogram.h" #include "backend/worksheet/Worksheet.h" #include "backend/worksheet/plots/cartesian/Symbol.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/column/Column.h" #include "backend/core/Project.h" #include "backend/core/datatypes/Double2StringFilter.h" #include "backend/core/datatypes/DateTime2StringFilter.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include "kdefrontend/TemplateHandler.h" #include "kdefrontend/GuiTools.h" #include #include #include #include #include #include #include #include #include #include /*! \class HistogramDock \brief Provides a widget for editing the properties of the Histograms (2D-curves) currently selected in the project explorer. If more than one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ HistogramDock::HistogramDock(QWidget* parent) : QWidget(parent), cbDataColumn(new TreeViewComboBox), m_curve(nullptr), m_aspectTreeModel(nullptr), m_initializing(false) { ui.setupUi(this); // Tab "General" - QGridLayout* gridLayout = qobject_cast(ui.tabGeneral->layout()); + auto gridLayout = qobject_cast(ui.tabGeneral->layout()); gridLayout->addWidget(cbDataColumn, 3, 2, 1, 1); //Tab "Values" gridLayout = qobject_cast(ui.tabValues->layout()); cbValuesColumn = new TreeViewComboBox(ui.tabValues); gridLayout->addWidget(cbValuesColumn, 2, 2, 1, 1); //Tab "Filling" ui.cbFillingColorStyle->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); ui.bFillingOpen->setIcon( QIcon::fromTheme("document-open") ); - QCompleter* completer = new QCompleter(this); + auto completer = new QCompleter(this); completer->setModel(new QDirModel); ui.leFillingFileName->setCompleter(completer); //adjust layouts in the tabs - for (int i=0; icount(); ++i){ - QGridLayout* layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); + for (int i = 0; i < ui.tabWidget->count(); ++i){ + auto layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2,2,2,2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } ui.leBinWidth->setValidator(new QDoubleValidator(ui.leBinWidth)); ui.leBinRangesMin->setValidator(new QDoubleValidator(ui.leBinRangesMin)); ui.leBinRangesMax->setValidator(new QDoubleValidator(ui.leBinRangesMax)); //Slots //General connect(ui.leName, &QLineEdit::textChanged, this, &HistogramDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &HistogramDock::commentChanged); connect( ui.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( cbDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(dataColumnChanged(QModelIndex)) ); connect( ui.cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)) ); connect( ui.cbOrientation, SIGNAL(currentIndexChanged(int)), this, SLOT(orientationChanged(int))); connect( ui.cbBinningMethod, SIGNAL(currentIndexChanged(int)), this, SLOT(binningMethodChanged(int)) ); connect(ui.sbBinCount, static_cast(&QSpinBox::valueChanged), this, &HistogramDock::binCountChanged); connect(ui.leBinWidth, &QLineEdit::textChanged, this, &HistogramDock::binWidthChanged); connect( ui.chkAutoBinRanges, &QCheckBox::stateChanged, this, &HistogramDock::autoBinRangesChanged ); connect( ui.leBinRangesMin, &QLineEdit::textChanged, this, &HistogramDock::binRangesMinChanged ); connect( ui.leBinRangesMax, &QLineEdit::textChanged, this, &HistogramDock::binRangesMaxChanged ); //Line connect(ui.cbLineType, static_cast(&QComboBox::currentIndexChanged), this, &HistogramDock::lineTypeChanged); connect(ui.cbLineStyle, static_cast(&QComboBox::currentIndexChanged), this, &HistogramDock::lineStyleChanged); connect(ui.kcbLineColor, &KColorButton::changed, this, &HistogramDock::lineColorChanged); connect(ui.sbLineWidth, static_cast(&QDoubleSpinBox::valueChanged), this, &HistogramDock::lineWidthChanged); connect(ui.sbLineOpacity, static_cast(&QSpinBox::valueChanged), this, &HistogramDock::lineOpacityChanged); //Symbol connect( ui.cbSymbolStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolsStyleChanged(int)) ); connect( ui.sbSymbolSize, SIGNAL(valueChanged(double)), this, SLOT(symbolsSizeChanged(double)) ); connect( ui.sbSymbolRotation, SIGNAL(valueChanged(int)), this, SLOT(symbolsRotationChanged(int)) ); connect( ui.sbSymbolOpacity, SIGNAL(valueChanged(int)), this, SLOT(symbolsOpacityChanged(int)) ); connect( ui.cbSymbolFillingStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolsFillingStyleChanged(int)) ); connect( ui.kcbSymbolFillingColor, SIGNAL(changed(QColor)), this, SLOT(symbolsFillingColorChanged(QColor)) ); connect( ui.cbSymbolBorderStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolsBorderStyleChanged(int)) ); connect( ui.kcbSymbolBorderColor, SIGNAL(changed(QColor)), this, SLOT(symbolsBorderColorChanged(QColor)) ); connect( ui.sbSymbolBorderWidth, SIGNAL(valueChanged(double)), this, SLOT(symbolsBorderWidthChanged(double)) ); //Values connect( ui.cbValuesType, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesTypeChanged(int)) ); connect( cbValuesColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(valuesColumnChanged(QModelIndex)) ); connect( ui.cbValuesPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesPositionChanged(int)) ); connect( ui.sbValuesDistance, SIGNAL(valueChanged(double)), this, SLOT(valuesDistanceChanged(double)) ); connect( ui.sbValuesRotation, SIGNAL(valueChanged(int)), this, SLOT(valuesRotationChanged(int)) ); connect( ui.sbValuesOpacity, SIGNAL(valueChanged(int)), this, SLOT(valuesOpacityChanged(int)) ); //TODO connect( ui.cbValuesFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesColumnFormatChanged(int)) ); connect( ui.leValuesPrefix, SIGNAL(returnPressed()), this, SLOT(valuesPrefixChanged()) ); connect( ui.leValuesSuffix, SIGNAL(returnPressed()), this, SLOT(valuesSuffixChanged()) ); connect( ui.kfrValuesFont, SIGNAL(fontSelected(QFont)), this, SLOT(valuesFontChanged(QFont)) ); connect( ui.kcbValuesColor, SIGNAL(changed(QColor)), this, SLOT(valuesColorChanged(QColor)) ); //Filling connect(ui.chkFillingEnabled, &QCheckBox::stateChanged, this, &HistogramDock::fillingEnabledChanged); connect( ui.cbFillingType, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingTypeChanged(int)) ); connect( ui.cbFillingColorStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingColorStyleChanged(int)) ); connect( ui.cbFillingImageStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingImageStyleChanged(int)) ); connect( ui.cbFillingBrushStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingBrushStyleChanged(int)) ); connect( ui.bFillingOpen, SIGNAL(clicked(bool)), this, SLOT(selectFile())); connect( ui.leFillingFileName, SIGNAL(returnPressed()), this, SLOT(fileNameChanged()) ); connect( ui.leFillingFileName, SIGNAL(textChanged(QString)), this, SLOT(fileNameChanged()) ); connect( ui.kcbFillingFirstColor, SIGNAL(changed(QColor)), this, SLOT(fillingFirstColorChanged(QColor)) ); connect( ui.kcbFillingSecondColor, SIGNAL(changed(QColor)), this, SLOT(fillingSecondColorChanged(QColor)) ); connect( ui.sbFillingOpacity, SIGNAL(valueChanged(int)), this, SLOT(fillingOpacityChanged(int)) ); //Error bars connect( ui.cbErrorType, SIGNAL(currentIndexChanged(int)), this, SLOT(errorTypeChanged(int)) ); connect( ui.cbErrorBarsType, SIGNAL(currentIndexChanged(int)), this, SLOT(errorBarsTypeChanged(int)) ); connect( ui.sbErrorBarsCapSize, SIGNAL(valueChanged(double)), this, SLOT(errorBarsCapSizeChanged(double)) ); connect( ui.cbErrorBarsStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(errorBarsStyleChanged(int)) ); connect( ui.kcbErrorBarsColor, SIGNAL(changed(QColor)), this, SLOT(errorBarsColorChanged(QColor)) ); connect( ui.sbErrorBarsWidth, SIGNAL(valueChanged(double)), this, SLOT(errorBarsWidthChanged(double)) ); connect( ui.sbErrorBarsOpacity, SIGNAL(valueChanged(int)), this, SLOT(errorBarsOpacityChanged(int)) ); //template handler - TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Histogram); + auto templateHandler = new TemplateHandler(this, TemplateHandler::Histogram); ui.verticalLayout->addWidget(templateHandler); templateHandler->show(); connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), this, SLOT(loadConfigFromTemplate(KConfig&))); connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), this, SLOT(saveConfigAsTemplate(KConfig&))); connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); retranslateUi(); init(); //TODO: activate the tab for error-bars again once the functionality is implemented ui.tabWidget->removeTab(5); } HistogramDock::~HistogramDock() { if (m_aspectTreeModel) delete m_aspectTreeModel; } void HistogramDock::init(){ //General //bins option ui.cbBinningMethod->addItem(i18n("By Number")); ui.cbBinningMethod->addItem(i18n("By Width")); ui.cbBinningMethod->addItem(i18n("Square-root")); ui.cbBinningMethod->addItem(i18n("Rice")); ui.cbBinningMethod->addItem(i18n("Sturges")); ui.cbBinningMethod->addItem(i18n("Doane")); ui.cbBinningMethod->addItem(i18n("Scott")); //histogram type ui.cbType->addItem(i18n("Ordinary Histogram")); ui.cbType->addItem(i18n("Cumulative Histogram")); // ui.cbType->addItem(i18n("AvgShifted Histogram")); //Orientation ui.cbOrientation->addItem(i18n("Vertical")); ui.cbOrientation->addItem(i18n("Horizontal")); //Line ui.cbLineType->addItem(i18n("None")); ui.cbLineType->addItem(i18n("Bars")); ui.cbLineType->addItem(i18n("Envelope")); ui.cbLineType->addItem(i18n("Drop Lines")); GuiTools::updatePenStyles(ui.cbLineStyle, Qt::black); //Symbols GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, Qt::black); QPainter pa; //TODO size of the icon depending on the actuall height of the combobox? int iconSize = 20; QPixmap pm(iconSize, iconSize); ui.cbSymbolStyle->setIconSize(QSize(iconSize, iconSize)); QTransform trafo; trafo.scale(15, 15); QPen pen(Qt::SolidPattern, 0); const QColor& color = (palette().color(QPalette::Base).lightness() < 128) ? Qt::white : Qt::black; pen.setColor(color); pa.setPen( pen ); ui.cbSymbolStyle->addItem(i18n("None")); for (int i = 1; i < 19; ++i) { //TODO: use enum count - Symbol::Style style = (Symbol::Style)i; + auto style = (Symbol::Style)i; pm.fill(Qt::transparent); pa.begin(&pm); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.translate(iconSize/2,iconSize/2); pa.drawPath(trafo.map(Symbol::pathFromStyle(style))); pa.end(); ui.cbSymbolStyle->addItem(QIcon(pm), Symbol::nameFromStyle(style)); } GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, Qt::black); m_initializing = false; //Values ui.cbValuesType->addItem(i18n("No Values")); ui.cbValuesType->addItem("Bin Entries Number"); ui.cbValuesType->addItem(i18n("Custom Column")); ui.cbValuesPosition->addItem(i18n("Above")); ui.cbValuesPosition->addItem(i18n("Below")); ui.cbValuesPosition->addItem(i18n("Left")); ui.cbValuesPosition->addItem(i18n("Right")); //Filling ui.cbFillingType->clear(); ui.cbFillingType->addItem(i18n("Color")); ui.cbFillingType->addItem(i18n("Image")); ui.cbFillingType->addItem(i18n("Pattern")); ui.cbFillingColorStyle->clear(); ui.cbFillingColorStyle->addItem(i18n("Single Color")); ui.cbFillingColorStyle->addItem(i18n("Horizontal Linear Gradient")); ui.cbFillingColorStyle->addItem(i18n("Vertical Linear Gradient")); ui.cbFillingColorStyle->addItem(i18n("Diagonal Linear Gradient (Start From Top Left)")); ui.cbFillingColorStyle->addItem(i18n("Diagonal Linear Gradient (Start From Bottom Left)")); ui.cbFillingColorStyle->addItem(i18n("Radial Gradient")); ui.cbFillingImageStyle->clear(); ui.cbFillingImageStyle->addItem(i18n("Scaled and Cropped")); ui.cbFillingImageStyle->addItem(i18n("Scaled")); ui.cbFillingImageStyle->addItem(i18n("Scaled, Keep Proportions")); ui.cbFillingImageStyle->addItem(i18n("Centered")); ui.cbFillingImageStyle->addItem(i18n("Tiled")); ui.cbFillingImageStyle->addItem(i18n("Center Tiled")); GuiTools::updateBrushStyles(ui.cbFillingBrushStyle, Qt::SolidPattern); //Error-bars pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.drawLine(3,10,17,10);//vert. line pa.drawLine(10,3,10,17);//hor. line pa.end(); ui.cbErrorBarsType->addItem(i18n("Bars")); ui.cbErrorBarsType->setItemIcon(0, pm); pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.setBrush(Qt::SolidPattern); pa.drawLine(3,10,17,10); //vert. line pa.drawLine(10,3,10,17); //hor. line pa.drawLine(7,3,13,3); //upper cap pa.drawLine(7,17,13,17); //bottom cap pa.drawLine(3,7,3,13); //left cap pa.drawLine(17,7,17,13); //right cap pa.end(); ui.cbErrorBarsType->addItem(i18n("Bars with Ends")); ui.cbErrorBarsType->setItemIcon(1, pm); ui.cbErrorType->addItem(i18n("No Errors")); GuiTools::updatePenStyles(ui.cbErrorBarsStyle, Qt::black); } void HistogramDock::setModel() { m_aspectTreeModel->enablePlottableColumnsOnly(true); m_aspectTreeModel->enableShowPlotDesignation(true); QList list; list << "Folder" << "Workbook" << "Datapicker" << "DatapickerCurve" << "Spreadsheet" << "FileDataSource" << "Column" << "Worksheet" << "CartesianPlot" << "XYFitCurve" << "CantorWorksheet"; cbDataColumn->setTopLevelClasses(list); cbValuesColumn->setTopLevelClasses(list); list.clear(); list << "Column"; m_aspectTreeModel->setSelectableAspects(list); cbDataColumn->setModel(m_aspectTreeModel); cbValuesColumn->setModel(m_aspectTreeModel); } void HistogramDock::setCurves(QList list){ m_initializing = true; m_curvesList = list; m_curve = list.first(); Q_ASSERT(m_curve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); setModel(); //if there are more then one curve in the list, disable the content in the tab "general" if (m_curvesList.size()==1){ ui.lName->setEnabled(true); ui.leName->setEnabled(true); ui.lComment->setEnabled(true); ui.leComment->setEnabled(true); ui.lXColumn->setEnabled(true); cbDataColumn->setEnabled(true); this->setModelIndexFromColumn(cbDataColumn, m_curve->dataColumn()); this->setModelIndexFromColumn(cbValuesColumn, m_curve->valuesColumn()); ui.leName->setText(m_curve->name()); ui.leComment->setText(m_curve->comment()); }else { ui.lName->setEnabled(false); ui.leName->setEnabled(false); ui.lComment->setEnabled(false); ui.leComment->setEnabled(false); ui.lXColumn->setEnabled(false); cbDataColumn->setEnabled(false); cbDataColumn->setCurrentModelIndex(QModelIndex()); cbValuesColumn->setCurrentModelIndex(QModelIndex()); ui.leName->setText(""); ui.leComment->setText(""); } //show the properties of the first curve ui.cbType->setCurrentIndex(m_curve->type()); ui.cbOrientation->setCurrentIndex(m_curve->orientation()); ui.cbBinningMethod->setCurrentIndex(m_curve->binningMethod()); ui.sbBinCount->setValue(m_curve->binCount()); ui.leBinWidth->setText(QString::number(m_curve->binWidth())); ui.chkAutoBinRanges->setChecked(m_curve->autoBinRanges()); ui.leBinRangesMin->setText( QString::number(m_curve->binRangesMin()) ); ui.leBinRangesMax->setText( QString::number(m_curve->binRangesMax()) ); ui.chkVisible->setChecked( m_curve->isVisible() ); KConfig config("", KConfig::SimpleConfig); loadConfig(config); //Slots //General-tab connect(m_curve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_curve, &Histogram::dataColumnChanged, this, &HistogramDock::curveDataColumnChanged); connect(m_curve, &Histogram::typeChanged, this, &HistogramDock::curveTypeChanged); connect(m_curve, &Histogram::orientationChanged, this, &HistogramDock::curveOrientationChanged); connect(m_curve, &Histogram::binningMethodChanged, this, &HistogramDock::curveBinningMethodChanged); connect(m_curve, &Histogram::binCountChanged, this, &HistogramDock::curveBinCountChanged); connect(m_curve, &Histogram::binWidthChanged, this, &HistogramDock::curveBinWidthChanged); connect(m_curve, &Histogram::autoBinRangesChanged, this, &HistogramDock::curveAutoBinRangesChanged); connect(m_curve, &Histogram::binRangesMinChanged, this, &HistogramDock::curveBinRangesMinChanged); connect(m_curve, &Histogram::binRangesMaxChanged, this, &HistogramDock::curveBinRangesMaxChanged); connect(m_curve, SIGNAL(visibilityChanged(bool)), this, SLOT(curveVisibilityChanged(bool))); //Line-tab connect(m_curve, SIGNAL(linePenChanged(QPen)), this, SLOT(curveLinePenChanged(QPen))); connect(m_curve, SIGNAL(lineOpacityChanged(qreal)), this, SLOT(curveLineOpacityChanged(qreal))); //Symbol-Tab connect(m_curve, SIGNAL(symbolsStyleChanged(Symbol::Style)), this, SLOT(curveSymbolsStyleChanged(Symbol::Style))); connect(m_curve, SIGNAL(symbolsSizeChanged(qreal)), this, SLOT(curveSymbolsSizeChanged(qreal))); connect(m_curve, SIGNAL(symbolsRotationAngleChanged(qreal)), this, SLOT(curveSymbolsRotationAngleChanged(qreal))); connect(m_curve, SIGNAL(symbolsOpacityChanged(qreal)), this, SLOT(curveSymbolsOpacityChanged(qreal))); connect(m_curve, SIGNAL(symbolsBrushChanged(QBrush)), this, SLOT(curveSymbolsBrushChanged(QBrush))); connect(m_curve, SIGNAL(symbolsPenChanged(QPen)), this, SLOT(curveSymbolsPenChanged(QPen))); //Values-Tab connect(m_curve, SIGNAL(valuesTypeChanged(Histogram::ValuesType)), this, SLOT(curveValuesTypeChanged(Histogram::ValuesType))); connect(m_curve, SIGNAL(valuesColumnChanged(const AbstractColumn*)), this, SLOT(curveValuesColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(valuesPositionChanged(Histogram::ValuesPosition)), this, SLOT(curveValuesPositionChanged(Histogram::ValuesPosition))); connect(m_curve, SIGNAL(valuesDistanceChanged(qreal)), this, SLOT(curveValuesDistanceChanged(qreal))); connect(m_curve, SIGNAL(valuesOpacityChanged(qreal)), this, SLOT(curveValuesOpacityChanged(qreal))); connect(m_curve, SIGNAL(valuesRotationAngleChanged(qreal)), this, SLOT(curveValuesRotationAngleChanged(qreal))); connect(m_curve, SIGNAL(valuesPrefixChanged(QString)), this, SLOT(curveValuesPrefixChanged(QString))); connect(m_curve, SIGNAL(valuesSuffixChanged(QString)), this, SLOT(curveValuesSuffixChanged(QString))); connect(m_curve, SIGNAL(valuesFontChanged(QFont)), this, SLOT(curveValuesFontChanged(QFont))); connect(m_curve, SIGNAL(valuesColorChanged(QColor)), this, SLOT(curveValuesColorChanged(QColor))); //Filling-Tab connect( m_curve, SIGNAL(fillingTypeChanged(PlotArea::BackgroundType)), this, SLOT(curveFillingTypeChanged(PlotArea::BackgroundType)) ); connect( m_curve, SIGNAL(fillingColorStyleChanged(PlotArea::BackgroundColorStyle)), this, SLOT(curveFillingColorStyleChanged(PlotArea::BackgroundColorStyle)) ); connect( m_curve, SIGNAL(fillingImageStyleChanged(PlotArea::BackgroundImageStyle)), this, SLOT(curveFillingImageStyleChanged(PlotArea::BackgroundImageStyle)) ); connect( m_curve, SIGNAL(fillingBrushStyleChanged(Qt::BrushStyle)), this, SLOT(curveFillingBrushStyleChanged(Qt::BrushStyle)) ); connect( m_curve, SIGNAL(fillingFirstColorChanged(QColor&)), this, SLOT(curveFillingFirstColorChanged(QColor&)) ); connect( m_curve, SIGNAL(fillingSecondColorChanged(QColor&)), this, SLOT(curveFillingSecondColorChanged(QColor&)) ); connect( m_curve, SIGNAL(fillingFileNameChanged(QString&)), this, SLOT(curveFillingFileNameChanged(QString&)) ); connect( m_curve, SIGNAL(fillingOpacityChanged(float)), this, SLOT(curveFillingOpacityChanged(float)) ); //"Error bars"-Tab connect(m_curve, SIGNAL(errorTypeChanged(Histogram::ErrorType)), this, SLOT(curveErrorTypeChanged(Histogram::ErrorType))); connect(m_curve, SIGNAL(errorBarsCapSizeChanged(qreal)), this, SLOT(curveErrorBarsCapSizeChanged(qreal))); connect(m_curve, SIGNAL(errorBarsTypeChanged(XYCurve::ErrorBarsType)), this, SLOT(curveErrorBarsTypeChanged(XYCurve::ErrorBarsType))); connect(m_curve, SIGNAL(errorBarsPenChanged(QPen)), this, SLOT(curveErrorBarsPenChanged(QPen))); connect(m_curve, SIGNAL(errorBarsOpacityChanged(qreal)), this, SLOT(curveErrorBarsOpacityChanged(qreal))); m_initializing=false; } void HistogramDock::setModelIndexFromColumn(TreeViewComboBox* cb, const AbstractColumn* column) { if (column) cb->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(column)); else cb->setCurrentModelIndex(QModelIndex()); } void HistogramDock::retranslateUi() { //TODO: // ui.lName->setText(i18n("Name")); // ui.lComment->setText(i18n("Comment")); // ui.chkVisible->setText(i18n("Visible")); // ui.lXColumn->setText(i18n("x-data")); // ui.lYColumn->setText(i18n("y-data")); //TODO updatePenStyles, updateBrushStyles for all comboboxes } //************************************************************* //**** SLOTs for changes triggered in HistogramDock ***** //************************************************************* // "General"-tab void HistogramDock::nameChanged() { if (m_initializing) return; m_curve->setName(ui.leName->text()); } void HistogramDock::commentChanged() { if (m_initializing) return; m_curve->setComment(ui.leComment->text()); } void HistogramDock::visibilityChanged(bool state){ if (m_initializing) return; for (auto* curve: m_curvesList) curve->setVisible(state); } void HistogramDock::typeChanged(int index) { if (m_initializing) return; - Histogram::HistogramType histogramType = Histogram::HistogramType(index); + auto histogramType = Histogram::HistogramType(index); for (auto* curve : m_curvesList) curve->setType(histogramType); } void HistogramDock::dataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); + auto aspect = static_cast(index.internalPointer()); AbstractColumn* column(nullptr); if (aspect) { column = dynamic_cast(aspect); Q_ASSERT(column); } for (auto* curve : m_curvesList) curve->setDataColumn(column); } void HistogramDock::orientationChanged(int index) { if (m_initializing) return; - Histogram::HistogramOrientation orientation = Histogram::HistogramOrientation(index); + auto orientation = Histogram::HistogramOrientation(index); for (auto* curve : m_curvesList) curve->setOrientation(orientation); } void HistogramDock::binningMethodChanged(int index) { - const Histogram::BinningMethod binningMethod = Histogram::BinningMethod(index); + const auto binningMethod = Histogram::BinningMethod(index); if (binningMethod == Histogram::ByNumber) { ui.lBinCount->show(); ui.sbBinCount->show(); ui.lBinWidth->hide(); ui.leBinWidth->hide(); } else if (binningMethod == Histogram::ByWidth) { ui.lBinCount->hide(); ui.sbBinCount->hide(); ui.lBinWidth->show(); ui.leBinWidth->show(); } else { ui.lBinCount->hide(); ui.sbBinCount->hide(); ui.lBinWidth->hide(); ui.leBinWidth->hide(); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setBinningMethod(binningMethod); } void HistogramDock::binCountChanged(int value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setBinCount(value); } void HistogramDock::binWidthChanged() { if (m_initializing) return; float width = ui.leBinWidth->text().toDouble(); for (auto* curve : m_curvesList) curve->setBinWidth(width); } void HistogramDock::autoBinRangesChanged(int state) { bool checked = (state==Qt::Checked); ui.leBinRangesMin->setEnabled(!checked); ui.leBinRangesMax->setEnabled(!checked); if (m_initializing) return; for (auto* hist : m_curvesList) hist->setAutoBinRanges(checked); } void HistogramDock::binRangesMinChanged(const QString& value) { if (m_initializing) return; const double min = value.toDouble(); for (auto* hist : m_curvesList) hist->setBinRangesMin(min); } void HistogramDock::binRangesMaxChanged(const QString& value) { if (m_initializing) return; const double max = value.toDouble(); for (auto* hist : m_curvesList) hist->setBinRangesMax(max); } //Line tab void HistogramDock::lineTypeChanged(int index) { - Histogram::LineType lineType = Histogram::LineType(index); + auto lineType = Histogram::LineType(index); if ( lineType == Histogram::NoLine) { ui.cbLineStyle->setEnabled(false); ui.kcbLineColor->setEnabled(false); ui.sbLineWidth->setEnabled(false); ui.sbLineOpacity->setEnabled(false); } else { ui.cbLineStyle->setEnabled(true); ui.kcbLineColor->setEnabled(true); ui.sbLineWidth->setEnabled(true); ui.sbLineOpacity->setEnabled(true); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setLineType(lineType); } void HistogramDock::lineStyleChanged(int index) { if (m_initializing) return; - Qt::PenStyle penStyle=Qt::PenStyle(index); + auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* curve : m_curvesList) { - pen=curve->linePen(); + pen = curve->linePen(); pen.setStyle(penStyle); curve->setLinePen(pen); } } void HistogramDock::lineColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->linePen(); + pen = curve->linePen(); pen.setColor(color); curve->setLinePen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbLineStyle, color); m_initializing = false; } void HistogramDock::lineWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->linePen(); + pen = curve->linePen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setLinePen(pen); } } void HistogramDock::lineOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setLineOpacity(opacity); } //"Symbol"-tab void HistogramDock::symbolsStyleChanged(int index) { - Symbol::Style style = Symbol::Style(index); + const auto style = Symbol::Style(index); if (style == Symbol::NoSymbols) { ui.sbSymbolSize->setEnabled(false); ui.sbSymbolRotation->setEnabled(false); ui.sbSymbolOpacity->setEnabled(false); ui.kcbSymbolFillingColor->setEnabled(false); ui.cbSymbolFillingStyle->setEnabled(false); ui.cbSymbolBorderStyle->setEnabled(false); ui.kcbSymbolBorderColor->setEnabled(false); ui.sbSymbolBorderWidth->setEnabled(false); } else { ui.sbSymbolSize->setEnabled(true); ui.sbSymbolRotation->setEnabled(true); ui.sbSymbolOpacity->setEnabled(true); //enable/disable the symbol filling options in the GUI depending on the currently selected symbol. - if (style!=Symbol::Line && style!=Symbol::Cross) { + if (style != Symbol::Line && style != Symbol::Cross) { ui.cbSymbolFillingStyle->setEnabled(true); bool noBrush = (Qt::BrushStyle(ui.cbSymbolFillingStyle->currentIndex()) == Qt::NoBrush); ui.kcbSymbolFillingColor->setEnabled(!noBrush); } else { ui.kcbSymbolFillingColor->setEnabled(false); ui.cbSymbolFillingStyle->setEnabled(false); } ui.cbSymbolBorderStyle->setEnabled(true); bool noLine = (Qt::PenStyle(ui.cbSymbolBorderStyle->currentIndex()) == Qt::NoPen); ui.kcbSymbolBorderColor->setEnabled(!noLine); ui.sbSymbolBorderWidth->setEnabled(!noLine); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setSymbolsStyle(style); } void HistogramDock::symbolsSizeChanged(double value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setSymbolsSize( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); } void HistogramDock::symbolsRotationChanged(int value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setSymbolsRotationAngle(value); } void HistogramDock::symbolsOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setSymbolsOpacity(opacity); } void HistogramDock::symbolsFillingStyleChanged(int index) { - Qt::BrushStyle brushStyle = Qt::BrushStyle(index); + auto brushStyle = Qt::BrushStyle(index); ui.kcbSymbolFillingColor->setEnabled(!(brushStyle == Qt::NoBrush)); if (m_initializing) return; QBrush brush; for (auto* curve : m_curvesList) { - brush=curve->symbolsBrush(); + brush = curve->symbolsBrush(); brush.setStyle(brushStyle); curve->setSymbolsBrush(brush); } } void HistogramDock::symbolsFillingColorChanged(const QColor& color) { if (m_initializing) return; QBrush brush; for (auto* curve : m_curvesList) { - brush=curve->symbolsBrush(); + brush = curve->symbolsBrush(); brush.setColor(color); curve->setSymbolsBrush(brush); } m_initializing = true; GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, color ); m_initializing = false; } void HistogramDock::symbolsBorderStyleChanged(int index) { - Qt::PenStyle penStyle=Qt::PenStyle(index); + auto penStyle = Qt::PenStyle(index); if ( penStyle == Qt::NoPen ) { ui.kcbSymbolBorderColor->setEnabled(false); ui.sbSymbolBorderWidth->setEnabled(false); } else { ui.kcbSymbolBorderColor->setEnabled(true); ui.sbSymbolBorderWidth->setEnabled(true); } if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->symbolsPen(); + pen = curve->symbolsPen(); pen.setStyle(penStyle); curve->setSymbolsPen(pen); } } void HistogramDock::symbolsBorderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { pen=curve->symbolsPen(); pen.setColor(color); curve->setSymbolsPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, color); m_initializing = false; } void HistogramDock::symbolsBorderWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { pen=curve->symbolsPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setSymbolsPen(pen); } } //Values tab /*! called when the type of the values (none, x, y, (x,y) etc.) was changed. */ void HistogramDock::valuesTypeChanged(int index) { - Histogram::ValuesType valuesType = Histogram::ValuesType(index); + auto valuesType = Histogram::ValuesType(index); if (valuesType == Histogram::NoValues){ //no values are to paint -> deactivate all the pertinent widgets ui.cbValuesPosition->setEnabled(false); ui.lValuesColumn->hide(); cbValuesColumn->hide(); ui.sbValuesDistance->setEnabled(false); ui.sbValuesRotation->setEnabled(false); ui.sbValuesOpacity->setEnabled(false); ui.cbValuesFormat->setEnabled(false); ui.cbValuesFormat->setEnabled(false); ui.sbValuesPrecision->setEnabled(false); ui.leValuesPrefix->setEnabled(false); ui.leValuesSuffix->setEnabled(false); ui.kfrValuesFont->setEnabled(false); ui.kcbValuesColor->setEnabled(false); } else { ui.cbValuesPosition->setEnabled(true); ui.sbValuesDistance->setEnabled(true); ui.sbValuesRotation->setEnabled(true); ui.sbValuesOpacity->setEnabled(true); ui.cbValuesFormat->setEnabled(true); ui.sbValuesPrecision->setEnabled(true); ui.leValuesPrefix->setEnabled(true); ui.leValuesSuffix->setEnabled(true); ui.kfrValuesFont->setEnabled(true); ui.kcbValuesColor->setEnabled(true); const Column* column; if (valuesType == Histogram::ValuesCustomColumn) { ui.lValuesColumn->show(); cbValuesColumn->show(); column= static_cast(cbValuesColumn->currentModelIndex().internalPointer()); } else { ui.lValuesColumn->hide(); cbValuesColumn->hide(); column = static_cast(m_curve->dataColumn()); } this->showValuesColumnFormat(column); } if (m_initializing) return; for (auto* curve: m_curvesList) curve->setValuesType(valuesType); } //TODO: very similar to ColumnDock void HistogramDock::showValuesColumnFormat(const Column* column){ if (!column){ // no valid column is available // -> hide all the format properties widgets (equivalent to showing the properties of the column mode "Text") this->updateValuesFormatWidgets(AbstractColumn::Text); }else{ AbstractColumn::ColumnMode columnMode = column->columnMode(); //update the format widgets for the new column mode this->updateValuesFormatWidgets(columnMode); //show the actual formatting properties switch(columnMode) { case AbstractColumn::Numeric:{ - Double2StringFilter * filter = static_cast(column->outputFilter()); + auto filter = static_cast(column->outputFilter()); ui.cbValuesFormat->setCurrentIndex(ui.cbValuesFormat->findData(filter->numericFormat())); ui.sbValuesPrecision->setValue(filter->numDigits()); break; } case AbstractColumn::Text: case AbstractColumn::Integer: break; case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { - DateTime2StringFilter * filter = static_cast(column->outputFilter()); + auto filter = static_cast(column->outputFilter()); ui.cbValuesFormat->setCurrentIndex(ui.cbValuesFormat->findData(filter->format())); break; } } } } //TODO: very similar to ColumnDock void HistogramDock::updateValuesFormatWidgets(const AbstractColumn::ColumnMode columnMode) { ui.cbValuesFormat->clear(); switch (columnMode) { case AbstractColumn::Numeric: ui.cbValuesFormat->addItem(i18n("Decimal"), QVariant('f')); ui.cbValuesFormat->addItem(i18n("Scientific (e)"), QVariant('e')); ui.cbValuesFormat->addItem(i18n("Scientific (E)"), QVariant('E')); ui.cbValuesFormat->addItem(i18n("Automatic (e)"), QVariant('g')); ui.cbValuesFormat->addItem(i18n("Automatic (E)"), QVariant('G')); break; case AbstractColumn::Integer: break; case AbstractColumn::Text: ui.cbValuesFormat->addItem(i18n("Text"), QVariant()); break; case AbstractColumn::Month: ui.cbValuesFormat->addItem(i18n("Number without Leading Zero"), QVariant("M")); ui.cbValuesFormat->addItem(i18n("Number with Leading Zero"), QVariant("MM")); ui.cbValuesFormat->addItem(i18n("Abbreviated Month Name"), QVariant("MMM")); ui.cbValuesFormat->addItem(i18n("Full Month Name"), QVariant("MMMM")); break; case AbstractColumn::Day: ui.cbValuesFormat->addItem(i18n("Number without Leading Zero"), QVariant("d")); ui.cbValuesFormat->addItem(i18n("Number with Leading Zero"), QVariant("dd")); ui.cbValuesFormat->addItem(i18n("Abbreviated Day Name"), QVariant("ddd")); ui.cbValuesFormat->addItem(i18n("Full Day Name"), QVariant("dddd")); break; case AbstractColumn::DateTime: for (const auto& s: AbstractColumn::dateFormats()) ui.cbValuesFormat->addItem(s, QVariant(s)); for (const auto& s: AbstractColumn::timeFormats()) ui.cbValuesFormat->addItem(s, QVariant(s)); for (const auto& s1: AbstractColumn::dateFormats()) for (const auto& s2: AbstractColumn::timeFormats()) ui.cbValuesFormat->addItem(s1 + ' ' + s2, QVariant(s1 + ' ' + s2)); break; } ui.cbValuesFormat->setCurrentIndex(0); if (columnMode == AbstractColumn::Numeric) { ui.lValuesPrecision->show(); ui.sbValuesPrecision->show(); } else { ui.lValuesPrecision->hide(); ui.sbValuesPrecision->hide(); } if (columnMode == AbstractColumn::Text) { ui.lValuesFormatTop->hide(); ui.lValuesFormat->hide(); ui.cbValuesFormat->hide(); } else { ui.lValuesFormatTop->show(); ui.lValuesFormat->show(); ui.cbValuesFormat->show(); ui.cbValuesFormat->setCurrentIndex(0); } if (columnMode == AbstractColumn::DateTime) { ui.cbValuesFormat->setEditable(true); } else { ui.cbValuesFormat->setEditable(false); } } /*! called when the custom column for the values was changed. */ void HistogramDock::valuesColumnChanged(const QModelIndex& index){ if (m_initializing) return; - Column* column = static_cast(index.internalPointer()); + auto column = static_cast(index.internalPointer()); this->showValuesColumnFormat(column); for (auto* curve: m_curvesList) { //TODO save also the format of the currently selected column for the values (precision etc.) curve->setValuesColumn(column); } } void HistogramDock::valuesPositionChanged(int index){ if (m_initializing) return; for (auto* curve : m_curvesList) curve->setValuesPosition(Histogram::ValuesPosition(index)); } void HistogramDock::valuesDistanceChanged(double value){ if (m_initializing) return; for (auto* curve: m_curvesList) curve->setValuesDistance( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); } void HistogramDock::valuesRotationChanged(int value){ if (m_initializing) return; for (auto* curve: m_curvesList) curve->setValuesRotationAngle(value); } void HistogramDock::valuesOpacityChanged(int value){ if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve: m_curvesList) curve->setValuesOpacity(opacity); } void HistogramDock::valuesPrefixChanged(){ if (m_initializing) return; QString prefix = ui.leValuesPrefix->text(); for (auto* curve: m_curvesList) curve->setValuesPrefix(prefix); } void HistogramDock::valuesSuffixChanged(){ if (m_initializing) return; QString suffix = ui.leValuesSuffix->text(); for (auto* curve: m_curvesList) curve->setValuesSuffix(suffix); } void HistogramDock::valuesFontChanged(const QFont& font){ if (m_initializing) return; QFont valuesFont = font; valuesFont.setPixelSize( Worksheet::convertToSceneUnits(font.pointSizeF(), Worksheet::Point) ); for (auto* curve: m_curvesList) curve->setValuesFont(valuesFont); } void HistogramDock::valuesColorChanged(const QColor& color){ if (m_initializing) return; for (auto* curve: m_curvesList) curve->setValuesColor(color); } //Filling-tab void HistogramDock::fillingEnabledChanged(int state) { ui.cbFillingType->setEnabled(state); ui.cbFillingColorStyle->setEnabled(state); ui.cbFillingBrushStyle->setEnabled(state); ui.cbFillingImageStyle->setEnabled(state); ui.kcbFillingFirstColor->setEnabled(state); ui.kcbFillingSecondColor->setEnabled(state); ui.leFillingFileName->setEnabled(state); ui.bFillingOpen->setEnabled(state); ui.sbFillingOpacity->setEnabled(state); if (m_initializing) return; for (auto* curve: m_curvesList) curve->setFillingEnabled(state); } void HistogramDock::fillingTypeChanged(int index){ - PlotArea::BackgroundType type = (PlotArea::BackgroundType)index; + auto type = (PlotArea::BackgroundType)index; if (type == PlotArea::Color){ ui.lFillingColorStyle->show(); ui.cbFillingColorStyle->show(); ui.lFillingImageStyle->hide(); ui.cbFillingImageStyle->hide(); ui.lFillingBrushStyle->hide(); ui.cbFillingBrushStyle->hide(); ui.lFillingFileName->hide(); ui.leFillingFileName->hide(); ui.bFillingOpen->hide(); ui.lFillingFirstColor->show(); ui.kcbFillingFirstColor->show(); - PlotArea::BackgroundColorStyle style = - (PlotArea::BackgroundColorStyle) ui.cbFillingColorStyle->currentIndex(); + auto style = (PlotArea::BackgroundColorStyle) ui.cbFillingColorStyle->currentIndex(); if (style == PlotArea::SingleColor){ ui.lFillingFirstColor->setText(i18n("Color:")); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); }else{ ui.lFillingFirstColor->setText(i18n("First color:")); ui.lFillingSecondColor->show(); ui.kcbFillingSecondColor->show(); } }else if(type == PlotArea::Image){ ui.lFillingColorStyle->hide(); ui.cbFillingColorStyle->hide(); ui.lFillingImageStyle->show(); ui.cbFillingImageStyle->show(); ui.lFillingBrushStyle->hide(); ui.cbFillingBrushStyle->hide(); ui.lFillingFileName->show(); ui.leFillingFileName->show(); ui.bFillingOpen->show(); ui.lFillingFirstColor->hide(); ui.kcbFillingFirstColor->hide(); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); }else if(type == PlotArea::Pattern) { ui.lFillingFirstColor->setText(i18n("Color:")); ui.lFillingColorStyle->hide(); ui.cbFillingColorStyle->hide(); ui.lFillingImageStyle->hide(); ui.cbFillingImageStyle->hide(); ui.lFillingBrushStyle->show(); ui.cbFillingBrushStyle->show(); ui.lFillingFileName->hide(); ui.leFillingFileName->hide(); ui.bFillingOpen->hide(); ui.lFillingFirstColor->show(); ui.kcbFillingFirstColor->show(); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); } if (m_initializing) return; for (auto* curve: m_curvesList) curve->setFillingType(type); } void HistogramDock::fillingColorStyleChanged(int index){ - PlotArea::BackgroundColorStyle style = (PlotArea::BackgroundColorStyle)index; + auto style = (PlotArea::BackgroundColorStyle)index; if (style == PlotArea::SingleColor){ ui.lFillingFirstColor->setText(i18n("Color:")); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); } else { ui.lFillingFirstColor->setText(i18n("First color:")); ui.lFillingSecondColor->show(); ui.kcbFillingSecondColor->show(); ui.lFillingBrushStyle->hide(); ui.cbFillingBrushStyle->hide(); } if (m_initializing) return; for (auto* curve: m_curvesList) curve->setFillingColorStyle(style); } void HistogramDock::fillingImageStyleChanged(int index){ if (m_initializing) return; - PlotArea::BackgroundImageStyle style = (PlotArea::BackgroundImageStyle)index; + auto style = (PlotArea::BackgroundImageStyle)index; for (auto* curve: m_curvesList) curve->setFillingImageStyle(style); } void HistogramDock::fillingBrushStyleChanged(int index){ if (m_initializing) return; - Qt::BrushStyle style = (Qt::BrushStyle)index; + auto style = (Qt::BrushStyle)index; for (auto* curve: m_curvesList) curve->setFillingBrushStyle(style); } void HistogramDock::fillingFirstColorChanged(const QColor& c){ if (m_initializing) return; for (auto* curve: m_curvesList) curve->setFillingFirstColor(c); } void HistogramDock::fillingSecondColorChanged(const QColor& c){ if (m_initializing) return; for (auto* curve: m_curvesList) curve->setFillingSecondColor(c); } //"Error bars"-Tab void HistogramDock::errorTypeChanged(int index) const { bool b = (index != 0); ui.lErrorData->setVisible(b); ui.lErrorFormat->setVisible(b); ui.lErrorBarsType->setVisible(b); ui.cbErrorBarsType->setVisible(b); ui.lErrorBarsStyle->setVisible(b); ui.cbErrorBarsStyle->setVisible(b); ui.lErrorBarsColor->setVisible(b); ui.kcbErrorBarsColor->setVisible(b); ui.lErrorBarsWidth->setVisible(b); ui.sbErrorBarsWidth->setVisible(b); ui.lErrorBarsOpacity->setVisible(b); ui.sbErrorBarsOpacity->setVisible(b); if (m_initializing) return; for (auto* curve : m_curvesList) curve->setErrorType(Histogram::ErrorType(index)); } void HistogramDock::errorBarsTypeChanged(int index) const { - XYCurve::ErrorBarsType type = XYCurve::ErrorBarsType(index); + auto type = XYCurve::ErrorBarsType(index); bool b = (type == XYCurve::ErrorBarsWithEnds); ui.lErrorBarsCapSize->setVisible(b); ui.sbErrorBarsCapSize->setVisible(b); if (m_initializing) return; for (auto* curve : m_curvesList) curve->setErrorBarsType(type); } void HistogramDock::errorBarsCapSizeChanged(double value) const { if (m_initializing) return; float size = Worksheet::convertToSceneUnits(value, Worksheet::Point); for (auto* curve : m_curvesList) curve->setErrorBarsCapSize(size); } void HistogramDock::errorBarsStyleChanged(int index) const { if (m_initializing) return; - Qt::PenStyle penStyle=Qt::PenStyle(index); + auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* curve : m_curvesList) { - pen=curve->errorBarsPen(); + pen = curve->errorBarsPen(); pen.setStyle(penStyle); curve->setErrorBarsPen(pen); } } void HistogramDock::errorBarsColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->errorBarsPen(); + pen = curve->errorBarsPen(); pen.setColor(color); curve->setErrorBarsPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbErrorBarsStyle, color); m_initializing = false; } void HistogramDock::errorBarsWidthChanged(double value) const { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->errorBarsPen(); + pen = curve->errorBarsPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setErrorBarsPen(pen); } } void HistogramDock::errorBarsOpacityChanged(int value) const { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setErrorBarsOpacity(opacity); } /*! opens a file dialog and lets the user select the image file. */ void HistogramDock::selectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "HistogramDock"); QString dir = conf.readEntry("LastImageDir", ""); QString formats; for (const QByteArray& format : QImageReader::supportedImageFormats()) { QString f = "*." + QString(format.constData()); formats.isEmpty() ? formats+=f : formats+=' '+f; } QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir, i18n("Images (%1)", formats)); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QDir::separator()); if (pos != -1) { QString newDir = path.left(pos); if (newDir!=dir) conf.writeEntry("LastImageDir", newDir); } ui.leFillingFileName->setText( path ); for (auto* curve: m_curvesList) curve->setFillingFileName(path); } void HistogramDock::fileNameChanged(){ if (m_initializing) return; QString fileName = ui.leFillingFileName->text(); for (auto* curve: m_curvesList) curve->setFillingFileName(fileName); } void HistogramDock::fillingOpacityChanged(int value){ if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve: m_curvesList) curve->setFillingOpacity(opacity); } //************************************************************* //*********** SLOTs for changes triggered in Histogram ******* //************************************************************* //General-Tab void HistogramDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } void HistogramDock::curveDataColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromColumn(cbDataColumn, column); m_initializing = false; } void HistogramDock::curveTypeChanged(Histogram::HistogramType type) { m_initializing = true; ui.cbType->setCurrentIndex((int)type); m_initializing = false; } void HistogramDock::curveOrientationChanged(Histogram::HistogramOrientation orientation) { m_initializing = true; ui.cbOrientation->setCurrentIndex((int)orientation); m_initializing = false; } void HistogramDock::curveBinningMethodChanged(Histogram::BinningMethod method) { m_initializing = true; ui.cbBinningMethod->setCurrentIndex((int)method); m_initializing = false; } void HistogramDock::curveBinCountChanged(int count) { m_initializing = true; ui.sbBinCount->setValue(count); m_initializing = false; } void HistogramDock::curveBinWidthChanged(float width) { m_initializing = true; ui.leBinWidth->setText(QString::number(width)); m_initializing = false; } void HistogramDock::curveAutoBinRangesChanged(bool value) { m_initializing = true; ui.chkAutoBinRanges->setChecked(value); m_initializing = false; } void HistogramDock::curveBinRangesMinChanged(double value) { m_initializing = true; ui.leBinRangesMin->setText( QString::number(value) ); m_initializing = false; } void HistogramDock::curveBinRangesMaxChanged(double value) { m_initializing = true; ui.leBinRangesMax->setText( QString::number(value) ); m_initializing = false; } //Line-Tab void HistogramDock::curveLineTypeChanged(Histogram::LineType type) { m_initializing = true; ui.cbLineType->setCurrentIndex((int)type); m_initializing = false; } void HistogramDock::curveLinePenChanged(const QPen& pen) { m_initializing = true; ui.cbLineStyle->setCurrentIndex( (int)pen.style()); ui.kcbLineColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbLineStyle, pen.color()); ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits( pen.widthF(), Worksheet::Point) ); m_initializing = false; } void HistogramDock::curveLineOpacityChanged(qreal opacity) { m_initializing = true; ui.sbLineOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } //Symbol-Tab void HistogramDock::curveSymbolsStyleChanged(Symbol::Style style) { m_initializing = true; ui.cbSymbolStyle->setCurrentIndex((int)style); m_initializing = false; } void HistogramDock::curveSymbolsSizeChanged(qreal size) { m_initializing = true; ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(size, Worksheet::Point) ); m_initializing = false; } void HistogramDock::curveSymbolsRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbSymbolRotation->setValue(angle); m_initializing = false; } void HistogramDock::curveSymbolsOpacityChanged(qreal opacity) { m_initializing = true; ui.sbSymbolOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } void HistogramDock::curveSymbolsBrushChanged(const QBrush& brush) { m_initializing = true; ui.cbSymbolFillingStyle->setCurrentIndex((int) brush.style()); ui.kcbSymbolFillingColor->setColor(brush.color()); GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, brush.color()); m_initializing = false; } void HistogramDock::curveSymbolsPenChanged(const QPen& pen) { m_initializing = true; ui.cbSymbolBorderStyle->setCurrentIndex( (int) pen.style()); ui.kcbSymbolBorderColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, pen.color()); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Point)); m_initializing = false; } //Values-Tab void HistogramDock::curveValuesTypeChanged(Histogram::ValuesType type) { m_initializing = true; ui.cbValuesType->setCurrentIndex((int) type); m_initializing = false; } void HistogramDock::curveValuesColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromColumn(cbValuesColumn, column); m_initializing = false; } void HistogramDock::curveValuesPositionChanged(Histogram::ValuesPosition position) { m_initializing = true; ui.cbValuesPosition->setCurrentIndex((int) position); m_initializing = false; } void HistogramDock::curveValuesDistanceChanged(qreal distance) { m_initializing = true; ui.sbValuesDistance->setValue( Worksheet::convertFromSceneUnits(distance, Worksheet::Point) ); m_initializing = false; } void HistogramDock::curveValuesRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbValuesRotation->setValue(angle); m_initializing = false; } void HistogramDock::curveValuesOpacityChanged(qreal opacity) { m_initializing = true; ui.sbValuesOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } void HistogramDock::curveValuesPrefixChanged(const QString& prefix) { m_initializing = true; ui.leValuesPrefix->setText(prefix); m_initializing = false; } void HistogramDock::curveValuesSuffixChanged(const QString& suffix) { m_initializing = true; ui.leValuesSuffix->setText(suffix); m_initializing = false; } void HistogramDock::curveValuesFontChanged(QFont font) { m_initializing = true; font.setPointSizeF( round(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Point)) ); ui.kfrValuesFont->setFont(font); m_initializing = false; } void HistogramDock::curveValuesColorChanged(QColor color) { m_initializing = true; ui.kcbValuesColor->setColor(color); m_initializing = false; } void HistogramDock::curveVisibilityChanged(bool on) { m_initializing = true; ui.chkVisible->setChecked(on); m_initializing = false; } //Filling void HistogramDock::curveFillingEnabledChanged(bool status) { m_initializing = true; ui.chkFillingEnabled->setChecked(status); m_initializing = false; } void HistogramDock::curveFillingTypeChanged(PlotArea::BackgroundType type){ m_initializing = true; ui.cbFillingType->setCurrentIndex(type); m_initializing = false; } void HistogramDock::curveFillingColorStyleChanged(PlotArea::BackgroundColorStyle style){ m_initializing = true; ui.cbFillingColorStyle->setCurrentIndex(style); m_initializing = false; } void HistogramDock::curveFillingImageStyleChanged(PlotArea::BackgroundImageStyle style){ m_initializing = true; ui.cbFillingImageStyle->setCurrentIndex(style); m_initializing = false; } void HistogramDock::curveFillingBrushStyleChanged(Qt::BrushStyle style){ m_initializing = true; ui.cbFillingBrushStyle->setCurrentIndex(style); m_initializing = false; } void HistogramDock::curveFillingFirstColorChanged(QColor& color){ m_initializing = true; ui.kcbFillingFirstColor->setColor(color); m_initializing = false; } void HistogramDock::curveFillingSecondColorChanged(QColor& color){ m_initializing = true; ui.kcbFillingSecondColor->setColor(color); m_initializing = false; } void HistogramDock::curveFillingFileNameChanged(QString& filename){ m_initializing = true; ui.leFillingFileName->setText(filename); m_initializing = false; } void HistogramDock::curveFillingOpacityChanged(float opacity){ m_initializing = true; ui.sbFillingOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } //"Error bars"-Tab void HistogramDock::curveErrorTypeChanged(Histogram::ErrorType type) { m_initializing = true; ui.cbErrorType->setCurrentIndex((int)type); m_initializing = false; } void HistogramDock::curveErrorBarsCapSizeChanged(qreal size) { m_initializing = true; ui.sbErrorBarsCapSize->setValue( Worksheet::convertFromSceneUnits(size, Worksheet::Point) ); m_initializing = false; } void HistogramDock::curveErrorBarsTypeChanged(XYCurve::ErrorBarsType type) { m_initializing = true; ui.cbErrorBarsType->setCurrentIndex((int)type); m_initializing = false; } void HistogramDock::curveErrorBarsPenChanged(const QPen& pen) { m_initializing = true; ui.cbErrorBarsStyle->setCurrentIndex( (int) pen.style()); ui.kcbErrorBarsColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbErrorBarsStyle, pen.color()); ui.sbErrorBarsWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(),Worksheet::Point) ); m_initializing = false; } void HistogramDock::curveErrorBarsOpacityChanged(qreal opacity) { m_initializing = true; ui.sbErrorBarsOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } //************************************************************* //************************* Settings ************************** //************************************************************* void HistogramDock::loadConfig(KConfig& config) { KConfigGroup group = config.group(QLatin1String("Histogram")); //General //we don't load/save the settings in the general-tab, since they are not style related. //It doesn't make sense to load/save them in the template. //This data is read in HistogramDock::setCurves(). //Line ui.cbLineType->setCurrentIndex( group.readEntry("LineType", (int) m_curve->lineType()) ); ui.cbLineStyle->setCurrentIndex( group.readEntry("LineStyle", (int) m_curve->linePen().style()) ); ui.kcbLineColor->setColor( group.readEntry("LineColor", m_curve->linePen().color()) ); ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LineWidth", m_curve->linePen().widthF()), Worksheet::Point) ); ui.sbLineOpacity->setValue( round(group.readEntry("LineOpacity", m_curve->lineOpacity())*100.0) ); //Symbols ui.cbSymbolStyle->setCurrentIndex( group.readEntry("SymbolStyle", (int)m_curve->symbolsStyle()) ); ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(group.readEntry("SymbolSize", m_curve->symbolsSize()), Worksheet::Point) ); ui.sbSymbolRotation->setValue( group.readEntry("SymbolRotation", m_curve->symbolsRotationAngle()) ); ui.sbSymbolOpacity->setValue( round(group.readEntry("SymbolOpacity", m_curve->symbolsOpacity())*100.0) ); ui.cbSymbolFillingStyle->setCurrentIndex( group.readEntry("SymbolFillingStyle", (int) m_curve->symbolsBrush().style()) ); ui.kcbSymbolFillingColor->setColor( group.readEntry("SymbolFillingColor", m_curve->symbolsBrush().color()) ); ui.cbSymbolBorderStyle->setCurrentIndex( group.readEntry("SymbolBorderStyle", (int) m_curve->symbolsPen().style()) ); ui.kcbSymbolBorderColor->setColor( group.readEntry("SymbolBorderColor", m_curve->symbolsPen().color()) ); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("SymbolBorderWidth",m_curve->symbolsPen().widthF()), Worksheet::Point) ); //Values ui.cbValuesType->setCurrentIndex( group.readEntry("ValuesType", (int) m_curve->valuesType()) ); ui.cbValuesPosition->setCurrentIndex( group.readEntry("ValuesPosition", (int) m_curve->valuesPosition()) ); ui.sbValuesDistance->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ValuesDistance", m_curve->valuesDistance()), Worksheet::Point) ); ui.sbValuesRotation->setValue( group.readEntry("ValuesRotation", m_curve->valuesRotationAngle()) ); ui.sbValuesOpacity->setValue( round(group.readEntry("ValuesOpacity",m_curve->valuesOpacity())*100.0) ); ui.leValuesPrefix->setText( group.readEntry("ValuesPrefix", m_curve->valuesPrefix()) ); ui.leValuesSuffix->setText( group.readEntry("ValuesSuffix", m_curve->valuesSuffix()) ); QFont valuesFont = m_curve->valuesFont(); valuesFont.setPointSizeF( round(Worksheet::convertFromSceneUnits(valuesFont.pixelSize(), Worksheet::Point)) ); ui.kfrValuesFont->setFont( group.readEntry("ValuesFont", valuesFont) ); ui.kcbValuesColor->setColor( group.readEntry("ValuesColor", m_curve->valuesColor()) ); //Filling ui.chkFillingEnabled->setChecked( group.readEntry("FillingEnabled", m_curve->fillingEnabled()) ); ui.cbFillingType->setCurrentIndex( group.readEntry("FillingType", (int) m_curve->fillingType()) ); ui.cbFillingColorStyle->setCurrentIndex( group.readEntry("FillingColorStyle", (int) m_curve->fillingColorStyle()) ); ui.cbFillingImageStyle->setCurrentIndex( group.readEntry("FillingImageStyle", (int) m_curve->fillingImageStyle()) ); ui.cbFillingBrushStyle->setCurrentIndex( group.readEntry("FillingBrushStyle", (int) m_curve->fillingBrushStyle()) ); ui.leFillingFileName->setText( group.readEntry("FillingFileName", m_curve->fillingFileName()) ); ui.kcbFillingFirstColor->setColor( group.readEntry("FillingFirstColor", m_curve->fillingFirstColor()) ); ui.kcbFillingSecondColor->setColor( group.readEntry("FillingSecondColor", m_curve->fillingSecondColor()) ); ui.sbFillingOpacity->setValue( round(group.readEntry("FillingOpacity", m_curve->fillingOpacity())*100.0) ); //Error bars ui.cbErrorType->setCurrentIndex( group.readEntry("ErrorType", (int) m_curve->errorType()) ); ui.cbErrorBarsType->setCurrentIndex( group.readEntry("ErrorBarsType", (int) m_curve->errorBarsType()) ); ui.sbErrorBarsCapSize->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ErrorBarsCapSize", m_curve->errorBarsCapSize()), Worksheet::Point) ); ui.cbErrorBarsStyle->setCurrentIndex( group.readEntry("ErrorBarsStyle", (int) m_curve->errorBarsPen().style()) ); ui.kcbErrorBarsColor->setColor( group.readEntry("ErrorBarsColor", m_curve->errorBarsPen().color()) ); ui.sbErrorBarsWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ErrorBarsWidth", m_curve->errorBarsPen().widthF()),Worksheet::Point) ); ui.sbErrorBarsOpacity->setValue( round(group.readEntry("ErrorBarsOpacity", m_curve->errorBarsOpacity())*100.0) ); } void HistogramDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QDir::separator()); if (index!=-1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_curvesList.size(); if (size>1) m_curve->beginMacro(i18n("%1 xy-curves: template \"%2\" loaded", size, name)); else m_curve->beginMacro(i18n("%1: template \"%2\" loaded", m_curve->name(), name)); this->loadConfig(config); m_curve->endMacro(); } void HistogramDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "Histogram" ); //Line group.writeEntry("LineType", ui.cbLineType->currentIndex()); group.writeEntry("LineStyle", ui.cbLineStyle->currentIndex()); group.writeEntry("LineColor", ui.kcbLineColor->color()); group.writeEntry("LineWidth", Worksheet::convertToSceneUnits(ui.sbLineWidth->value(),Worksheet::Point) ); group.writeEntry("LineOpacity", ui.sbLineOpacity->value()/100 ); //Values group.writeEntry("ValuesType", ui.cbValuesType->currentIndex()); group.writeEntry("ValuesPosition", ui.cbValuesPosition->currentIndex()); group.writeEntry("ValuesDistance", Worksheet::convertToSceneUnits(ui.sbValuesDistance->value(),Worksheet::Point)); group.writeEntry("ValuesRotation", ui.sbValuesRotation->value()); group.writeEntry("ValuesOpacity", ui.sbValuesOpacity->value()/100); group.writeEntry("ValuesPrefix", ui.leValuesPrefix->text()); group.writeEntry("ValuesSuffix", ui.leValuesSuffix->text()); group.writeEntry("ValuesFont", ui.kfrValuesFont->font()); group.writeEntry("ValuesColor", ui.kcbValuesColor->color()); //Filling group.writeEntry("FillingEnabled", ui.chkFillingEnabled->isChecked()); group.writeEntry("FillingType", ui.cbFillingType->currentIndex()); group.writeEntry("FillingColorStyle", ui.cbFillingColorStyle->currentIndex()); group.writeEntry("FillingImageStyle", ui.cbFillingImageStyle->currentIndex()); group.writeEntry("FillingBrushStyle", ui.cbFillingBrushStyle->currentIndex()); group.writeEntry("FillingFileName", ui.leFillingFileName->text()); group.writeEntry("FillingFirstColor", ui.kcbFillingFirstColor->color()); group.writeEntry("FillingSecondColor", ui.kcbFillingSecondColor->color()); group.writeEntry("FillingOpacity", ui.sbFillingOpacity->value()/100.0); config.sync(); } diff --git a/src/kdefrontend/dockwidgets/LiveDataDock.cpp b/src/kdefrontend/dockwidgets/LiveDataDock.cpp index 58114e766..86a81a964 100644 --- a/src/kdefrontend/dockwidgets/LiveDataDock.cpp +++ b/src/kdefrontend/dockwidgets/LiveDataDock.cpp @@ -1,1695 +1,1695 @@ /*************************************************************************** File : LiveDataDock.cpp Project : LabPlot Description : Dock widget for live data properties -------------------------------------------------------------------- Copyright : (C) 2017 by Fabian Kristof (fkristofszabolcs@gmail.com) Copyright : (C) 2018 by Kovacs Ferencz (kferike98@gmail.com) Copyright : (C) 2018 by Stefan Gerlach (stefan.gerlach@uni.kn) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "LiveDataDock.h" #include #include #include #include #include #include #ifdef HAVE_MQTT #include "kdefrontend/widgets/MQTTWillSettingsWidget.h" #include #include #include #endif LiveDataDock::LiveDataDock(QWidget* parent) : QWidget(parent), m_paused(false) #ifdef HAVE_MQTT , m_searching(true), m_searchTimer(new QTimer()), m_interpretMessage(true), m_previousMQTTClient(nullptr) #endif { ui.setupUi(this); ui.bUpdateNow->setIcon(QIcon::fromTheme(QLatin1String("view-refresh"))); connect(ui.bPausePlayReading, &QPushButton::clicked, this, &LiveDataDock::pauseContinueReading); connect(ui.bUpdateNow, &QPushButton::clicked, this, &LiveDataDock::updateNow); connect(ui.sbUpdateInterval, static_cast(&QSpinBox::valueChanged), this, &LiveDataDock::updateIntervalChanged); connect(ui.sbKeepNValues, static_cast(&QSpinBox::valueChanged), this, &LiveDataDock::keepNValuesChanged); connect(ui.sbSampleSize, static_cast(&QSpinBox::valueChanged), this, &LiveDataDock::sampleSizeChanged); connect(ui.cbUpdateType, static_cast(&QComboBox::currentIndexChanged), this, &LiveDataDock::updateTypeChanged); connect(ui.cbReadingType, static_cast(&QComboBox::currentIndexChanged), this, &LiveDataDock::readingTypeChanged); #ifdef HAVE_MQTT m_searchTimer->setInterval(10000); connect(this, &LiveDataDock::newTopic, this, &LiveDataDock::setTopicCompleter); connect(m_searchTimer, &QTimer::timeout, this, &LiveDataDock::topicTimeout); connect(ui.bSubscribe, &QPushButton::clicked, this, &LiveDataDock::addSubscription); connect(ui.bUnsubscribe, &QPushButton::clicked, this, &LiveDataDock::removeSubscription); connect(ui.bWillUpdateNow, &QPushButton::clicked, this, &LiveDataDock::willUpdateNow); connect(ui.leTopics, &QLineEdit::textChanged, this, &LiveDataDock::scrollToTopicTreeItem); connect(ui.leSubscriptions, &QLineEdit::textChanged, this, &LiveDataDock::scrollToSubsriptionTreeItem); connect(ui.bWillSettings, &QPushButton::clicked, this, &LiveDataDock::showWillSettings); ui.bSubscribe->setIcon(ui.bSubscribe->style()->standardIcon(QStyle::SP_ArrowRight)); ui.bSubscribe->setToolTip(i18n("Subscribe selected topics")); ui.bUnsubscribe->setIcon(ui.bUnsubscribe->style()->standardIcon(QStyle::SP_ArrowLeft)); ui.bUnsubscribe->setToolTip(i18n("Unsubscribe selected topics")); ui.bWillSettings->setToolTip(i18n("Manage MQTT connection's will settings")); ui.bWillSettings->setIcon(ui.bWillSettings->style()->standardIcon(QStyle::SP_FileDialogDetailedView)); #endif } LiveDataDock::~LiveDataDock() { #ifdef HAVE_MQTT delete m_searchTimer; QMapIterator clients(m_clients); while(clients.hasNext()) { clients.next(); delete clients.value(); } #endif } #ifdef HAVE_MQTT /*! * \brief Sets the MQTTClients of this dock widget * \param clients */ void LiveDataDock::setMQTTClients(const QList &clients) { m_liveDataSources.clear(); m_mqttClients.clear(); m_mqttClients = clients; const MQTTClient* const fmc = clients.at(0); ui.sbUpdateInterval->setValue(fmc->updateInterval()); ui.cbUpdateType->setCurrentIndex(static_cast(fmc->updateType())); ui.cbReadingType->setCurrentIndex(static_cast(fmc->readingType())); if (fmc->updateType() == MQTTClient::UpdateType::NewData) { ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); } if (fmc->isPaused()) { ui.bPausePlayReading->setText(i18n("Continue reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-record"))); } else { ui.bPausePlayReading->setText(i18n("Pause reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); } ui.sbKeepNValues->setValue(fmc->keepNValues()); ui.sbKeepNValues->setEnabled(true); if (fmc->readingType() == MQTTClient::ReadingType::TillEnd) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else ui.sbSampleSize->setValue(fmc->sampleSize()); // disable "whole file" option const QStandardItemModel* model = qobject_cast(ui.cbReadingType->model()); QStandardItem* item = model->item(LiveDataSource::ReadingType::WholeFile); item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); //show MQTT connected options ui.gbManageSubscriptions->show(); ui.bSubscribe->show(); ui.bUnsubscribe->show(); ui.twTopics->show(); ui.leTopics->show(); ui.lTopicSearch->show(); ui.twSubscriptions->show(); ui.lQoS->show(); ui.cbQoS->show(); ui.lWillSettings->show(); ui.bWillSettings->show(); //if there isn't a client with this hostname we instantiate a new one if(m_clients[fmc->clientHostName()] == nullptr) { m_clients[fmc->clientHostName()] = new QMqttClient(); connect(fmc, &MQTTClient::clientAboutToBeDeleted, this, &LiveDataDock::removeClient); connect(m_clients[fmc->clientHostName()], &QMqttClient::connected, this, &LiveDataDock::onMQTTConnect); connect(m_clients[fmc->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); m_clients[fmc->clientHostName()]->setHostname(fmc->clientHostName()); m_clients[fmc->clientHostName()]->setPort(fmc->clientPort()); if(fmc->MQTTUseAuthentication()) { m_clients[fmc->clientHostName()]->setUsername(fmc->clientUserName()); m_clients[fmc->clientHostName()]->setPassword(fmc->clientPassword()); } if(fmc->MQTTUseID()) { m_clients[fmc->clientHostName()]->setClientId(fmc->clientID()); } m_clients[fmc->clientHostName()]->connectToHost(); } if(m_previousMQTTClient == nullptr) { connect(fmc, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); //Fill the subscription tree(useful if the MQTTClient was loaded) QVector topics = fmc->topicNames(); for(int i = 0; i < topics.size(); ++i) { addTopicToTree(topics[i]); } fillSubscriptions(); } //if the previous MQTTClient's host name was different from the current one we have to disconnect some slots //and clear the tree widgets else if(m_previousMQTTClient->clientHostName() != fmc->clientHostName()) { disconnect(m_previousMQTTClient, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); disconnect(m_clients[m_previousMQTTClient->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); connect(m_clients[m_previousMQTTClient->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); disconnect(m_clients[fmc->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); ui.twTopics->clear(); //repopulating the tree widget with the already known topics of the client for(int i = 0; i < m_addedTopics[fmc->clientHostName()].size(); ++i) { addTopicToTree(m_addedTopics[fmc->clientHostName()].at(i)); } //fill subscriptions tree widget ui.twSubscriptions->clear(); fillSubscriptions(); connect(fmc, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); connect(m_clients[fmc->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); } if(fmc->willUpdateType() == MQTTClient::WillUpdateType::OnClick && fmc->MQTTWillUse()) ui.bWillUpdateNow->show(); m_previousMQTTClient = fmc; } #endif /*! * \brief Sets the live data sources of this dock widget * \param sources */ void LiveDataDock::setLiveDataSources(const QList& sources) { #ifdef HAVE_MQTT m_mqttClients.clear(); #endif m_liveDataSources = sources; const LiveDataSource* const fds = sources.at(0); const LiveDataSource::SourceType sourceType = fds->sourceType(); const LiveDataSource::ReadingType readingType = fds->readingType(); const LiveDataSource::UpdateType updateType = fds->updateType(); ui.sbUpdateInterval->setValue(fds->updateInterval()); ui.cbUpdateType->setCurrentIndex(static_cast(updateType)); ui.cbReadingType->setCurrentIndex(static_cast(readingType)); if (updateType == LiveDataSource::UpdateType::NewData) { ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); } if (fds->isPaused()) { ui.bPausePlayReading->setText(i18n("Continue Reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-record"))); } else { ui.bPausePlayReading->setText(i18n("Pause Reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); } ui.sbKeepNValues->setValue(fds->keepNValues()); // disable "whole file" when having no file (i.e. socket or port) - const QStandardItemModel* model = qobject_cast(ui.cbReadingType->model()); + auto model = qobject_cast(ui.cbReadingType->model()); QStandardItem* item = model->item(LiveDataSource::ReadingType::WholeFile); if (sourceType == LiveDataSource::SourceType::FileOrPipe) item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); else item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); if (sourceType == LiveDataSource::SourceType::NetworkTcpSocket || sourceType == LiveDataSource::SourceType::LocalSocket || sourceType == LiveDataSource::SourceType::SerialPort || readingType == LiveDataSource::ReadingType::TillEnd || readingType == LiveDataSource::ReadingType::WholeFile) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else { ui.sbSampleSize->setValue(fds->sampleSize()); } // disable "on new data"-option if not available model = qobject_cast(ui.cbUpdateType->model()); item = model->item(LiveDataSource::UpdateType::NewData); if (sourceType == LiveDataSource::SourceType::NetworkTcpSocket || sourceType == LiveDataSource::SourceType::NetworkUdpSocket || sourceType == LiveDataSource::SourceType::SerialPort) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); } else { item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); } ui.bWillSettings->hide(); ui.lWillSettings->hide(); ui.bWillUpdateNow->hide(); ui.bSubscribe->hide(); ui.bUnsubscribe->hide(); ui.twTopics->hide(); ui.leTopics->hide(); ui.lTopicSearch->hide(); ui.twSubscriptions->hide(); ui.gbManageSubscriptions->hide(); ui.lQoS->hide(); ui.cbQoS->hide(); } /*! * \brief Modifies the sample size of the live data sources or MQTTClient objects * \param sampleSize */ void LiveDataDock::sampleSizeChanged(int sampleSize) { if(!m_liveDataSources.isEmpty()) { for (auto* source : m_liveDataSources) source->setSampleSize(sampleSize); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { for (auto* client : m_mqttClients) client->setSampleSize(sampleSize); } #endif } /*! * \brief Updates the live data sources now */ void LiveDataDock::updateNow() { if(!m_liveDataSources.isEmpty()) { for (auto* source : m_liveDataSources) source->updateNow(); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { for (auto* client : m_mqttClients) client->updateNow(); } #endif } /*! * \brief LiveDataDock::updateTypeChanged * \param idx */ void LiveDataDock::updateTypeChanged(int idx) { if(!m_liveDataSources.isEmpty()) { DEBUG("LiveDataDock::updateTypeChanged()"); - const LiveDataSource::UpdateType type = static_cast(idx); + const auto type = static_cast(idx); switch (type) { case LiveDataSource::UpdateType::TimeInterval: ui.lUpdateInterval->show(); ui.sbUpdateInterval->show(); ui.lSampleSize->show(); ui.sbSampleSize->show(); for (auto* source: m_liveDataSources) { source->setUpdateType(type); source->setUpdateInterval(ui.sbUpdateInterval->value()); source->setFileWatched(false); } break; case LiveDataSource::UpdateType::NewData: ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); ui.lSampleSize->hide(); ui.sbSampleSize->hide(); for (auto* source: m_liveDataSources) { source->setFileWatched(true); source->setUpdateType(type); } } } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { DEBUG("LiveDataDock::updateTypeChanged()"); const MQTTClient::UpdateType type = static_cast(idx); if (type == MQTTClient::UpdateType::TimeInterval) { ui.lUpdateInterval->show(); ui.sbUpdateInterval->show(); for (auto* client : m_mqttClients) { client->setUpdateType(type); client->setUpdateInterval(ui.sbUpdateInterval->value()); } } else if (type == MQTTClient::UpdateType::NewData) { ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); for (auto* client : m_mqttClients) { client->setUpdateType(type); } } } #endif } /*! * \brief Handles the change of the reading type in the dock widget * \param idx */ void LiveDataDock::readingTypeChanged(int idx) { if(!m_liveDataSources.isEmpty()) { - const LiveDataSource::ReadingType type = static_cast(idx); + const auto type = static_cast(idx); const LiveDataSource* const fds = m_liveDataSources.at(0); const LiveDataSource::SourceType sourceType = fds->sourceType(); const LiveDataSource::UpdateType updateType = fds->updateType(); if (sourceType == LiveDataSource::SourceType::NetworkTcpSocket || sourceType == LiveDataSource::SourceType::LocalSocket || sourceType == LiveDataSource::SourceType::SerialPort || type == LiveDataSource::ReadingType::TillEnd || type == LiveDataSource::ReadingType::WholeFile || updateType == LiveDataSource::UpdateType::NewData) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else { ui.lSampleSize->show(); ui.sbSampleSize->show(); } for (auto* source : m_liveDataSources) source->setReadingType(type); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { MQTTClient::ReadingType type = static_cast(idx); if (type == MQTTClient::ReadingType::TillEnd) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else { ui.lSampleSize->show(); ui.sbSampleSize->show(); } for (auto* client : m_mqttClients) client->setReadingType(type); } #endif } /*! * \brief Modifies the update interval of the live data sources * \param updateInterval */ void LiveDataDock::updateIntervalChanged(int updateInterval) { if(!m_liveDataSources.isEmpty()) { for (auto* source : m_liveDataSources) source->setUpdateInterval(updateInterval); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { for (auto* client : m_mqttClients) client->setUpdateInterval(updateInterval); } #endif } /*! * \brief Modifies the number of samples to keep in each of the live data sources * \param keepNValues */ void LiveDataDock::keepNValuesChanged(const int keepNValues) { if(!m_liveDataSources.isEmpty()) { for (auto* source : m_liveDataSources) source->setKeepNValues(keepNValues); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { for (auto* client : m_mqttClients) client->setKeepNValues(keepNValues); } #endif } /*! * \brief Pauses the reading of the live data source */ void LiveDataDock::pauseReading() { if(!m_liveDataSources.isEmpty()) { for (auto* source: m_liveDataSources) source->pauseReading(); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { for (auto* client : m_mqttClients) client->pauseReading(); } #endif } /*! * \brief Continues the reading of the live data source */ void LiveDataDock::continueReading() { if(!m_liveDataSources.isEmpty()) { for (auto* source: m_liveDataSources) source->continueReading(); } #ifdef HAVE_MQTT else if (!m_mqttClients.isEmpty()) { for (auto* client : m_mqttClients) client->continueReading(); } #endif } /*! * \brief Handles the pausing/continuing of reading of the live data source */ void LiveDataDock::pauseContinueReading() { m_paused = !m_paused; if (m_paused) { pauseReading(); ui.bPausePlayReading->setText(i18n("Continue Reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-record"))); } else { continueReading(); ui.bPausePlayReading->setText(i18n("Pause Reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); } } #ifdef HAVE_MQTT /*! *\brief called when use will message checkbox's state is changed in the will settings widget, * Sets the mqttUseWill according to state for every client in m_mqttClients * * \param state the state of the checbox */ void LiveDataDock::useWillMessage(int state) { qDebug()<<"Use will message: " <setMQTTWillUse(true); if (m_mqttClients.first()->willUpdateType() == MQTTClient::WillUpdateType::OnClick) ui.bWillUpdateNow->show(); } else if (state == Qt::Unchecked) { for (auto* source: m_mqttClients) source->setMQTTWillUse(false); ui.bWillUpdateNow->hide(); } } /*! *\brief called when will message's QoS is changed in the will settings widget * sets the will QoS level for every client in m_mqttClients * * \param QoS the QoS level of the will message */ void LiveDataDock::willQoSChanged(int QoS) { for (auto* source: m_mqttClients) source->setWillQoS(QoS); } /*! *\brief called when will message's retain flag is changed in the will settings widget * sets the retain flag for the will message in every client in m_mqttClients * * \param state the state of the will retain chechbox */ void LiveDataDock::willRetainChanged(int state) { if(state == Qt::Checked) { for (auto* source: m_mqttClients) source->setWillRetain(true); } else if (state == Qt::Unchecked) { for (auto* source: m_mqttClients) source->setWillRetain(false); } } /*! *\brief called when will topic combobox's current item is changed in the will settings widget * sets the will topic for every client in m_mqttClients * * \param topic the current text of cbWillTopic */ void LiveDataDock::willTopicChanged(const QString& topic) { for (auto* source: m_mqttClients) { if(source->willTopic() != topic) source->clearLastMessage(); source->setWillTopic(topic); } } /*! *\brief called when the selected will message type is changed in the will settings widget * sets the will message type for every client in m_mqttClients * * \param type the selected will message type */ void LiveDataDock::willMessageTypeChanged(int type) { for (auto* source: m_mqttClients) source->setWillMessageType(static_cast (type)); } /*! *\brief called when the will own message is changed in the will settings widget * sets the will own message for every client in m_mqttClients * * \param message the will message given by the user */ void LiveDataDock::willOwnMessageChanged(const QString& message) { for (auto* source: m_mqttClients) source->setWillOwnMessage(message); } /*! *\brief called when the selected update type for the will message is changed in the will settings widget * sets the will update type for every client in m_mqttClients * * \param type the selected will update type */ void LiveDataDock::willUpdateTypeChanged(int updateType) { for (auto* source: m_mqttClients) source->setWillUpdateType(static_cast(updateType)); if(static_cast(updateType) == MQTTClient::WillUpdateType::TimePeriod) { ui.bWillUpdateNow->hide(); for (auto* source: m_mqttClients) { source->startWillTimer(); } } else if (static_cast(updateType) == MQTTClient::WillUpdateType::OnClick) { ui.bWillUpdateNow->show(); //if update type is on click we stop the will timer for (auto* source: m_mqttClients) source->stopWillTimer(); } } /*! *\brief called when the will update now button is pressed * updates the will message of every client in m_mqttClients */ void LiveDataDock::willUpdateNow() { for (auto* source: m_mqttClients) source->updateWillMessage(); } /*! *\brief called when the update interval for will message is changed in the will settings widget * sets the will update interval for every client in m_mqttClients, then starts the will timer for each one * * \param interval the new will update interval */ void LiveDataDock::willUpdateIntervalChanged(int interval) { for (auto* source: m_mqttClients) { source->setWillTimeInterval(interval); source->startWillTimer(); } } /*! *\brief called when the will statistics are changed in the will settings widget * adds or removes the statistic represented by the index from every client in m_mqttClients */ void LiveDataDock::statisticsChanged(int index) { bool useStatistic = m_mqttClients.first()->willStatistics()[index]; //if it's checked we add it if(!useStatistic) { if(index >= 0) { for (auto* source: m_mqttClients) source->addWillStatistics(static_cast(index) ); } } //otherwise remove it else { if(index >= 0){ for (auto* source: m_mqttClients) source->removeWillStatistics(static_cast(index) ); } } } /*! *\brief called when the client connects to the broker successfully, it subscribes to every topic (# wildcard) * in order to later list every available topic */ void LiveDataDock::onMQTTConnect() { QMqttTopicFilter globalFilter{"#"}; QMqttSubscription * subscription = m_clients[m_mqttClients.first()->clientHostName()]->subscribe(globalFilter, 1); if(!subscription) qDebug()<<"Couldn't make global subscription in LiveDataDock"; } /*! *\brief called when the client receives a message * if the message arrived from a new topic, the topic is put in twTopics */ void LiveDataDock::mqttMessageReceived(const QByteArray& message, const QMqttTopicName& topic) { Q_UNUSED(message) if(!m_addedTopics[m_mqttClients.first()->clientHostName()].contains(topic.name())) { m_addedTopics[m_mqttClients.first()->clientHostName()].push_back(topic.name()); addTopicToTree(topic.name()); } } /*! *\brief called when the subscribe button is pressed * subscribes to the topic represented by the current item of twTopics in every client from m_mqttClients */ void LiveDataDock::addSubscription() { QString name; QTreeWidgetItem *item = ui.twTopics->currentItem(); if(item != nullptr) { QTreeWidgetItem *tempItem = item; //determine the topic name that the current item represents name.prepend(item->text(0)); if(item->childCount() != 0) name.append("/#"); while(tempItem->parent() != nullptr) { tempItem = tempItem->parent(); name.prepend(tempItem->text(0) + '/'); } //check if the subscription already exists QList topLevelList = ui.twSubscriptions->findItems(name, Qt::MatchExactly); if(topLevelList.isEmpty() || topLevelList.first()->parent() != nullptr) { qDebug() << "LiveDataDock: start to add new subscription: " << name; bool foundSuperior = false; for(int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) { //if the new subscriptions contains an already existing one, we remove the inferior one if(checkTopicContains(name, ui.twSubscriptions->topLevelItem(i)->text(0)) && name != ui.twSubscriptions->topLevelItem(i)->text(0)) { ui.twSubscriptions->topLevelItem(i)->takeChildren(); ui.twSubscriptions->takeTopLevelItem(i); i--; continue; } //if there is a subscription containing the new one we set foundSuperior true if(checkTopicContains(ui.twSubscriptions->topLevelItem(i)->text(0), name) && name != ui.twSubscriptions->topLevelItem(i)->text(0)) { foundSuperior = true; qDebug()<<"Can't add "<topLevelItem(i)->text(0); break; } } //if there wasn't a superior subscription we can subscribe to the new topic if(!foundSuperior) { QStringList toplevelName; toplevelName.push_back(name); QTreeWidgetItem* newTopLevelItem = new QTreeWidgetItem(toplevelName); ui.twSubscriptions->addTopLevelItem(newTopLevelItem); if(name.endsWith('#')) { //adding every topic that the subscription contains to twSubscriptions addSubscriptionChildren(item, newTopLevelItem); } //subscribe in every MQTTClient for (auto* source: m_mqttClients) { source->addMQTTSubscription(name, ui.cbQoS->currentIndex()); } if(name.endsWith('#')) { //if an already existing subscription contains a topic that the new subscription also contains //we decompose the already existing subscription //by unsubscribing from its topics, that are present in the new subscription as well QStringList nameList = name.split('/', QString::SkipEmptyParts); QString root = nameList.first(); QVector children; for(int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) { if(ui.twSubscriptions->topLevelItem(i)->text(0).startsWith(root) && name != ui.twSubscriptions->topLevelItem(i)->text(0)) { children.clear(); //get the "leaf" children of the inspected subscription findSubscriptionLeafChildren(children, ui.twSubscriptions->topLevelItem(i)); for(int j = 0; j < children.size(); ++j) { if(checkTopicContains(name, children[j]->text(0))) { //if the new subscription contains a topic, we unsubscribe from it QTreeWidgetItem* unsubscribeItem = children[j]; while(unsubscribeItem->parent() != nullptr) { for(int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) { if(unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) { //add topic as subscription to every client for (auto* source: m_mqttClients) { source->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex()); } //also add it to twSubscriptions ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i)); i--; } else { //before we remove the topic, we reparent it to the new subscription //so no data is lost for (auto* source: m_mqttClients) { source->reparentTopic(unsubscribeItem->text(0), name); } } } unsubscribeItem = unsubscribeItem->parent(); } qDebug()<<"Remove: "<text(0); //Remove topic/subscription for (auto* source: m_mqttClients) { source->removeMQTTSubscription(unsubscribeItem->text(0)); } ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem)); } } } } } manageCommonLevelSubscriptions(); updateSubscriptionCompleter(); if(!ui.bWillSettings->isEnabled()) ui.bWillSettings->setEnabled(true); } else { QMessageBox::warning(this, "Warning", "You already subscribed to a topic containing this one"); } } else QMessageBox::warning(this, "Warning", "You already subscribed to this topic"); } else QMessageBox::warning(this, "Warning", "You didn't select any item from the Tree Widget"); } /*! *\brief called when the unsubscribe button is pressed * unsubscribes from the topic represented by the current item of twSubscription in every client from m_mqttClients */ void LiveDataDock::removeSubscription() { QTreeWidgetItem* unsubscribeItem = ui.twSubscriptions->currentItem(); if(unsubscribeItem != nullptr) { qDebug() << "LiveDataDock: unsubscribe from " << unsubscribeItem->text(0); //if it is a top level item, meaning a topic that we really subscribed to(not one that belongs to a subscription) //we can simply unsubscribe from it if(unsubscribeItem->parent() == nullptr) { for (auto* source: m_mqttClients) { source->removeMQTTSubscription(unsubscribeItem->text(0)); } ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem)); } //otherwise we remove the selected item, but subscribe to every other topic, that was contained by //the selected item's parent subscription(top level item of twSubscriptions) else{ while(unsubscribeItem->parent() != nullptr) { for(int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) { if(unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) { //add topic as subscription to every client for (auto* source: m_mqttClients) { source->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex()); } ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i)); i--; } } unsubscribeItem = unsubscribeItem->parent(); } //remove topic/subscription from every client for (auto* source: m_mqttClients) { source->removeMQTTSubscription(unsubscribeItem->text(0)); } ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem)); //check if any common topics were subscribed, if possible merge them manageCommonLevelSubscriptions(); } if(ui.twSubscriptions->topLevelItemCount() <= 0) ui.bWillSettings->setEnabled(false); updateSubscriptionCompleter(); } else QMessageBox::warning(this, "Warning", "You didn't select any item from the Tree Widget"); } /*! *\brief called when a new topic is added to the tree(twTopics) * appends the topic's root to the topicList if it isn't in the list already * then sets the completer for leTopics */ void LiveDataDock::setTopicCompleter(const QString& topicName) { if(!m_searching) { QStringList list = topicName.split('/', QString::SkipEmptyParts); QString topic; if(!list.isEmpty()) { topic = list.at(0); } else topic = topicName; if(!m_topicList[m_mqttClients.first()->clientHostName()].contains(topic)) { m_topicList[m_mqttClients.first()->clientHostName()].append(topic); m_topicCompleter = new QCompleter(m_topicList[m_mqttClients.first()->clientHostName()], this); m_topicCompleter->setCompletionMode(QCompleter::PopupCompletion); m_topicCompleter->setCaseSensitivity(Qt::CaseSensitive); ui.leTopics->setCompleter(m_topicCompleter); } } } /*! *\brief Updates the completer for leSubscriptions */ void LiveDataDock::updateSubscriptionCompleter() { QStringList subscriptionList; QVector subscriptions = m_mqttClients.first()->MQTTSubscriptions(); if(!subscriptions.isEmpty()) { for(int i = 0; i < subscriptions.size(); ++i) { subscriptionList.append(subscriptions[i]); } m_subscriptionCompleter = new QCompleter(subscriptionList, this); m_subscriptionCompleter->setCompletionMode(QCompleter::PopupCompletion); m_subscriptionCompleter->setCaseSensitivity(Qt::CaseSensitive); ui.leSubscriptions->setCompleter(m_subscriptionCompleter); } else { ui.leSubscriptions->setCompleter(nullptr); } } /*! *\brief called when 10 seconds passed since the last time the user searched for a certain root in twTopics * enables updating the completer for le */ void LiveDataDock::topicTimeout() { m_searching = false; m_searchTimer->stop(); } /*! *\brief called when a new the host name of the MQTTClients from m _mqttClients changes * or when the MQTTClients initialize their subscriptions * Fills twSubscriptions with the subscriptions of the MQTTClient */ void LiveDataDock::fillSubscriptions() { const MQTTClient* const fmc = m_mqttClients.at(0); ui.twSubscriptions->clear(); QVector subscriptions = fmc->MQTTSubscriptions(); for (int i = 0; i < subscriptions.count(); ++i) { QStringList name; name.append(subscriptions[i]); bool found = false; for(int j = 0; j < ui.twSubscriptions->topLevelItemCount(); ++j) { if(ui.twSubscriptions->topLevelItem(j)->text(0) == subscriptions[i]) { found = true; break; } } if(!found) { //Add the subscription to the tree widget QTreeWidgetItem* newItem = new QTreeWidgetItem(name); ui.twSubscriptions->addTopLevelItem(newItem); name.clear(); name = subscriptions[i].split('/', QString::SkipEmptyParts); //find the corresponding "root" item in twTopics QTreeWidgetItem* topic = nullptr; for(int j = 0; j < ui.twTopics->topLevelItemCount(); ++j) { if(ui.twTopics->topLevelItem(j)->text(0) == name[0]) { topic = ui.twTopics->topLevelItem(j); break; } } //restore the children of the subscription if(topic != nullptr && topic->childCount() > 0) { restoreSubscriptionChildren(topic, newItem, name, 1); } } } m_searching = false; } /*! *\brief Checks if a topic contains another one * * \param superior the name of a topic * \param inferior the name of a topic * \return true if superior is equal to or contains(if superior contains wildcards) inferior, * false otherwise */ bool LiveDataDock::checkTopicContains(const QString &superior, const QString &inferior) { if (superior == inferior) return true; else { if(superior.contains('/')) { QStringList superiorList = superior.split('/', QString::SkipEmptyParts); QStringList inferiorList = inferior.split('/', QString::SkipEmptyParts); //a longer topic can't contain a shorter one if(superiorList.size() > inferiorList.size()) return false; bool ok = true; for(int i = 0; i < superiorList.size(); ++i) { if(superiorList.at(i) != inferiorList.at(i)) { if((superiorList.at(i) != "+") && !(superiorList.at(i) == '#' && i == superiorList.size() - 1)) { //if the two topics differ, and the superior's current level isn't + or #(which can be only in the last position) //then superior can't contain inferior ok = false; break; } else if(i == superiorList.size() - 1 && (superiorList.at(i) == "+" && inferiorList.at(i) == '#') ) { //if the two topics differ at the last level //and the superior's current level is + while the inferior's is #(which can be only in the last position) //then superior can't contain inferior ok = false; break; } } } return ok; } return false; } } /*! *\brief called when leTopics' text is changed * if the rootName can be found in twTopics, then we scroll it to the top of the tree widget * * \param rootName the current text of leTopics */ void LiveDataDock::scrollToTopicTreeItem(const QString& rootName) { m_searching = true; m_searchTimer->start(); int topItemIdx = -1; for(int i = 0; i< ui.twTopics->topLevelItemCount(); ++i) if(ui.twTopics->topLevelItem(i)->text(0) == rootName) { topItemIdx = i; break; } if(topItemIdx >= 0) { ui.twTopics->scrollToItem(ui.twTopics->topLevelItem(topItemIdx), QAbstractItemView::ScrollHint::PositionAtTop); } } /*! *\brief called when leSubscriptions' text is changed * if the rootName can be found in twSubscriptions, then we scroll it to the top of the tree widget * * \param rootName the current text of leSubscriptions */ void LiveDataDock::scrollToSubsriptionTreeItem(const QString& rootName) { int topItemIdx = -1; for(int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) if(ui.twSubscriptions->topLevelItem(i)->text(0) == rootName) { topItemIdx = i; break; } if(topItemIdx >= 0) { ui.twSubscriptions->scrollToItem(ui.twSubscriptions->topLevelItem(topItemIdx), QAbstractItemView::ScrollHint::PositionAtTop); } } /*! *\brief Returns the "+" wildcard containing topic name, which includes the given topic names * * \param first the name of a topic * \param second the name of a topic * \return The name of the common topic, if it exists, otherwise "" */ QString LiveDataDock::checkCommonLevel(const QString& first, const QString& second) { QStringList firstList = first.split('/', QString::SkipEmptyParts); QStringList secondtList = second.split('/', QString::SkipEmptyParts); QString commonTopic = ""; if(!firstList.isEmpty()) { //the two topics have to be the same size and can't be identic if(firstList.size() == secondtList.size() && (first != second)) { //the index where they differ int differIndex = -1; for(int i = 0; i < firstList.size(); ++i) { if(firstList.at(i) != secondtList.at(i)) { differIndex = i; break; } } //they can differ at only one level bool differ = false; if(differIndex > 0 && differIndex < firstList.size() -1) { for(int j = differIndex +1; j < firstList.size(); ++j) { if(firstList.at(j) != secondtList.at(j)) { differ = true; break; } } } else differ = true; if(!differ) { for(int i = 0; i < firstList.size(); ++i) { if(i != differIndex) { commonTopic.append(firstList.at(i)); } else { //we put "+" wildcard at the level where they differ commonTopic.append('+'); } if(i != firstList.size() - 1) commonTopic.append('/'); } } } } qDebug() << "Common topic for " << first << " and "<childCount() > 0) { for(int i = 0; i < topic->childCount(); ++i) { QTreeWidgetItem* temp = topic->child(i); QString name; //if it has children, then we add it as a # wildcrad containing topic if(topic->child(i)->childCount() > 0) { name.append(temp->text(0) + "/#"); while(temp->parent() != nullptr) { temp = temp->parent(); name.prepend(temp->text(0) + '/'); } } //if not then we simply add the topic itself else { name.append(temp->text(0)); while(temp->parent() != nullptr) { temp = temp->parent(); name.prepend(temp->text(0) + '/'); } } QStringList nameList; nameList.append(name); QTreeWidgetItem* childItem = new QTreeWidgetItem(nameList); subscription->addChild(childItem); //we use the function recursively on the given item addSubscriptionChildren(topic->child(i), childItem); } } } /*! *\brief Restores the children of a top level item in twSubscriptions if it contains wildcards * * \param topic pointer to a top level item in twTopics which represents the root of the subscription topic * \param subscription pointer to a top level item in twSubscriptions, this is the item whose children will be restored * \param list QStringList containing the levels of the subscription topic * \param level the level's number which is being investigated */ void LiveDataDock::restoreSubscriptionChildren(QTreeWidgetItem * topic, QTreeWidgetItem * subscription, const QStringList& list, int level) { if(level < list.size()) { if((level < list.size() - 1) && (list[level] != "+") && (list[level] != '#')) { for(int i = 0; i < topic->childCount(); ++i) { //if the current level isn't + or # wildcard we recursively continue with the next level if(topic->child(i)->text(0) == list[level]) { restoreSubscriptionChildren(topic->child(i), subscription, list, level + 1); break; } } } else if (list[level] == "+") { for(int i = 0; i < topic->childCount(); ++i) { //determine the name of the topic, contained by the subscription QString name; name.append(topic->child(i)->text(0)); for(int j = level + 1; j < list.size(); ++j) { name.append('/' + list[j]); } QTreeWidgetItem* temp = topic->child(i); while(temp->parent() != nullptr) { temp = temp->parent(); name.prepend(temp->text(0) + '/'); } //Add the topic as child of the subscription QStringList nameList; nameList.append(name); QTreeWidgetItem* newItem = new QTreeWidgetItem(nameList); subscription->addChild(newItem); //Continue adding children recursively to the new item restoreSubscriptionChildren(topic->child(i), newItem, list, level + 1); } } else if (list[level] == '#') { //add the children of the # wildcard containing subscription addSubscriptionChildren(topic, subscription); } } } /*! *\brief Returns the index of level where the two topic names differ, if there is a common topic for them * * \param first the name of a topic * \param second the name of a topic * \return The index of the unequal level, if there is a common topic, otherwise -1 */ int LiveDataDock::commonLevelIndex(const QString& first, const QString& second) { QStringList firstList = first.split('/', QString::SkipEmptyParts); QStringList secondtList = second.split('/', QString::SkipEmptyParts); QString commonTopic = ""; int differIndex = -1; if(!firstList.isEmpty()) { //the two topics have to be the same size and can't be identic if(firstList.size() == secondtList.size() && (first != second)) { //the index where they differ for(int i = 0; i < firstList.size(); ++i) { if(firstList.at(i) != secondtList.at(i)) { differIndex = i; break; } } //they can differ at only one level bool differ = false; if(differIndex > 0) { for(int j = differIndex +1; j < firstList.size(); ++j) { if(firstList.at(j) != secondtList.at(j)) { differ = true; break; } } } else differ = true; if(!differ) { for(int i = 0; i < firstList.size(); ++i) { if(i != differIndex) commonTopic.append(firstList.at(i)); else commonTopic.append('+'); if(i != firstList.size() - 1) commonTopic.append('/'); } } } } //if there is a common topic we return the differIndex if(!commonTopic.isEmpty()) return differIndex; else return -1; } /*! *\brief Fills the children vector, with the root item's (twSubscriptions) leaf children (meaning no wildcard containing topics) * * \param children vector of TreeWidgetItem pointers * \param root pointer to a TreeWidgetItem of twSubscriptions */ void LiveDataDock::findSubscriptionLeafChildren(QVector& children, QTreeWidgetItem* root) { if(root->childCount() == 0) { children.push_back(root); } else { for(int i = 0; i < root->childCount(); ++i) { findSubscriptionLeafChildren(children, root->child(i)); } } } /*! *\brief Returns the amount of topics that the "+" wildcard will replace in the level position * * \param levelIdx the level currently being investigated * \param level the level where the new + wildcard will be placed * \param commonList the topic name split into levels * \param currentItem pointer to a TreeWidgetItem which represents the parent of the level * represented by levelIdx * \return returns the childCount, or -1 if some topics already represented by + wildcard have different * amount of children */ int LiveDataDock::checkCommonChildCount(int levelIdx, int level, QStringList& commonList, QTreeWidgetItem* currentItem) { //we recursively check the number of children, until we get to level-1 if(levelIdx < level - 1) { if(commonList[levelIdx] != "+") { for(int j = 0; j < currentItem->childCount(); ++j) { if(currentItem->child(j)->text(0) == commonList[levelIdx]) { //if the level isn't represented by + wildcard we simply return the amount of children of the corresponding item, recursively return checkCommonChildCount(levelIdx + 1, level, commonList, currentItem->child(j)); } } } else { int childCount = -1; bool ok = true; //otherwise we check if every + wildcard represented topic has the same number of children, recursively for(int j = 0; j < currentItem->childCount(); ++j) { int temp = checkCommonChildCount(levelIdx + 1, level, commonList, currentItem->child(j)); if((j > 0) && (temp != childCount)) { ok = false; break; } childCount = temp; } //if yes we return this number, otherwise -1 if(ok) return childCount; else return -1; } } else if (levelIdx == level - 1) { if(commonList[levelIdx] != "+") { for(int j = 0; j < currentItem->childCount(); ++j) { if(currentItem->child(j)->text(0) == commonList[levelIdx]) { //if the level isn't represented by + wildcard we simply return the amount of children of the corresponding item return currentItem->child(j)->childCount(); } } } else { int childCount = -1; bool ok = true; //otherwise we check if every + wildcard represented topic has the same number of children for(int j = 0; j < currentItem->childCount(); ++j) { if((j > 0) && (currentItem->child(j)->childCount() != childCount)) { ok = false; break; } childCount = currentItem->child(j)->childCount(); } //if yes we return this number, otherwise -1 if(ok) return childCount; else return -1; } } else if (level == 1 && levelIdx == 1) return currentItem->childCount(); return -1; } /*! *\brief We search in twSubscriptions for topics that can be represented using + wildcards, then merge them. * We do this until there are no topics to merge */ void LiveDataDock::manageCommonLevelSubscriptions() { bool foundEqual = false; do{ foundEqual = false; QMap> equalTopicsMap; QVector equalTopics; //compare the subscriptions present in the TreeWidget for(int i = 0; i < ui.twSubscriptions->topLevelItemCount() - 1; ++i) { for(int j = i + 1; j < ui.twSubscriptions->topLevelItemCount(); ++j) { QString commonTopic = checkCommonLevel(ui.twSubscriptions->topLevelItem(i)->text(0), ui.twSubscriptions->topLevelItem(j)->text(0)); //if there is a common topic for the 2 compared topics, we add them to the map (using the common topic as key) if(!commonTopic.isEmpty()) { if(!equalTopicsMap[commonTopic].contains(ui.twSubscriptions->topLevelItem(i)->text(0))) { equalTopicsMap[commonTopic].push_back(ui.twSubscriptions->topLevelItem(i)->text(0)); } if(!equalTopicsMap[commonTopic].contains(ui.twSubscriptions->topLevelItem(j)->text(0))) { equalTopicsMap[commonTopic].push_back(ui.twSubscriptions->topLevelItem(j)->text(0)); } } } } if(!equalTopicsMap.isEmpty()) { qDebug()<<"Manage equal topics"; QVector commonTopics; QMapIterator> topics(equalTopicsMap); //check for every map entry, if the found topics can be merged or not while(topics.hasNext()) { topics.next(); int level = commonLevelIndex(topics.value().last(), topics.value().first()); QStringList commonList = topics.value().first().split('/', QString::SkipEmptyParts); QTreeWidgetItem* currentItem = nullptr; //search the corresponding item to the common topics first level(root) for(int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) { if(ui.twTopics->topLevelItem(i)->text(0) == commonList.first()) { currentItem = ui.twTopics->topLevelItem(i); break; } } //calculate the number of topics the new + wildcard could replace int childCount = checkCommonChildCount(1, level, commonList, currentItem); if(childCount > 0) { //if the number of topics found and the calculated number of topics is equal, the topics can be merged if(topics.value().size() == childCount) { qDebug() << "Found common topic to manage: " << topics.key(); foundEqual = true; commonTopics.push_back(topics.key()); } } } if(foundEqual) { //if there are more common topics, the topics of which can be merged, we choose the one which has the lowest level new "+" wildcard int highestLevel = INT_MAX; int topicIdx = -1; for(int i = 0; i < commonTopics.size(); ++i) { int level = commonLevelIndex(equalTopicsMap[commonTopics[i]].first(), commonTopics[i]); if(level < highestLevel) { topicIdx = i; highestLevel = level; } } qDebug() << "Start to manage: " << commonTopics[topicIdx]; equalTopics.append(equalTopicsMap[commonTopics[topicIdx]]); //Add the common topic ("merging") QString commonTopic; commonTopic = checkCommonLevel(equalTopics.first(), equalTopics.last()); QStringList nameList; nameList.append(commonTopic); QTreeWidgetItem* newTopic = new QTreeWidgetItem(nameList); ui.twSubscriptions->addTopLevelItem(newTopic); //remove the "merged" topics for(int i = 0; i < equalTopics.size(); ++i) { for(int j = 0; j < ui.twSubscriptions->topLevelItemCount(); ++j){ if(ui.twSubscriptions->topLevelItem(j)->text(0) == equalTopics[i]) { newTopic->addChild(ui.twSubscriptions->takeTopLevelItem(j)); break; } } } //remove any subscription that the new subscription contains for(int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) { if(checkTopicContains(commonTopic, ui.twSubscriptions->topLevelItem(i)->text(0)) && commonTopic != ui.twSubscriptions->topLevelItem(i)->text(0) ) { ui.twSubscriptions->topLevelItem(i)->takeChildren(); ui.twSubscriptions->takeTopLevelItem(i); i--; } } //make the subscription on commonTopic in every MQTTClient from m_mqttClients for (auto* source: m_mqttClients) { source->addMQTTSubscription(commonTopic, ui.cbQoS->currentIndex()); } } } } while(foundEqual); } /*! *\brief Adds topicName to twTopics * * \param topicName the name of the topic, which will be added to the tree widget */ void LiveDataDock::addTopicToTree(const QString &topicName) { QStringList name; QChar sep = '/'; QString rootName; if(topicName.contains(sep)) { QStringList list = topicName.split(sep, QString::SkipEmptyParts); if(!list.isEmpty()) { rootName = list.at(0); name.append(list.at(0)); QTreeWidgetItem* currentItem; //check whether the first level of the topic can be found in twTopics int topItemIdx = -1; for(int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) { if(ui.twTopics->topLevelItem(i)->text(0) == list.at(0)) { topItemIdx = i; break; } } //if not we simply add every level of the topic to the tree if( topItemIdx < 0) { currentItem = new QTreeWidgetItem(name); ui.twTopics->addTopLevelItem(currentItem); for(int i = 1; i < list.size(); ++i) { name.clear(); name.append(list.at(i)); currentItem->addChild(new QTreeWidgetItem(name)); currentItem = currentItem->child(0); } } //otherwise we search for the first level that isn't part of the tree, //then add every level of the topic to the tree from that certain level else { currentItem = ui.twTopics->topLevelItem(topItemIdx); int listIdx = 1; for(; listIdx < list.size(); ++listIdx) { QTreeWidgetItem* childItem = nullptr; bool found = false; for(int j = 0; j < currentItem->childCount(); ++j) { childItem = currentItem->child(j); if(childItem->text(0) == list.at(listIdx)) { found = true; currentItem = childItem; break; } } if(!found) { //this is the level that isn't present in the tree break; } } //add every level to the tree starting with the first level that isn't part of the tree for(; listIdx < list.size(); ++listIdx) { name.clear(); name.append(list.at(listIdx)); currentItem->addChild(new QTreeWidgetItem(name)); currentItem = currentItem->child(currentItem->childCount() - 1); } } } } else { rootName = topicName; name.append(topicName); ui.twTopics->addTopLevelItem(new QTreeWidgetItem(name)); } //if a subscribed topic contains the new topic, we have to update twSubscriptions for(int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) { QStringList subscriptionName = ui.twSubscriptions->topLevelItem(i)->text(0).split('/', QString::SkipEmptyParts); if (rootName == subscriptionName[0]) { fillSubscriptions(); break; } } //signals that a newTopic was added, in order to fill the completer of leTopics //we have to pass the whole topic name, not just the root name, for testing purposes emit newTopic(topicName); } /*! *\brief called when a client receives a message, if the clients hostname isn't identic with the host name of MQTTClients * if the message arrived from a new topic, the topic is put in m_addedTopics */ void LiveDataDock::mqttMessageReceivedInBackground(const QByteArray& message, const QMqttTopicName& topic) { Q_UNUSED(message) if(!m_addedTopics[m_mqttClients.first()->clientHostName()].contains(topic.name())) { m_addedTopics[m_mqttClients.first()->clientHostName()].push_back(topic.name()); } } /*! *\brief called when an MQTTClient is about to be deleted * removes every data connected to the MQTTClient, and disconnects the corresponding client from m_clients * * \param name the host name of the MQTTClient that will be deleted */ void LiveDataDock::removeClient(const QString& name) { m_clients[name]->disconnectFromHost(); m_addedTopics.remove(name); m_topicList.remove(name); if(m_previousMQTTClient != nullptr && m_previousMQTTClient->clientHostName() == name) { disconnect(m_clients[m_previousMQTTClient->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); m_previousMQTTClient = nullptr; } if(m_mqttClients.first()->clientHostName() == name) { ui.twSubscriptions->clear(); ui.twTopics->clear(); m_mqttClients.clear(); } delete m_clients[name]; m_clients.remove(name); } /*! * \brief Used for testing the MQTT related features * \param topic */ bool LiveDataDock::testSubscribe(const QString& topic){ QStringList topicList = topic.split('/', QString::SkipEmptyParts); QTreeWidgetItem* currentItem = nullptr; for(int i = 0; i topLevelItemCount(); ++i) { if(ui.twTopics->topLevelItem(i)->text(0) == topicList[0]) { currentItem = ui.twTopics->topLevelItem(i); break; } } if (currentItem) { for(int i = 1 ; i < topicList.size(); ++i) { if(topicList[i] == '#') break; for(int j = 0; j < currentItem->childCount(); ++j) { if(currentItem->child(j)->text(0) == topicList[i]) { currentItem = currentItem->child(j); break; } else if (j == currentItem->childCount() - 1) return false; } } } else return false; ui.twTopics->setCurrentItem(currentItem); addSubscription(); return true; } /*! * \brief Used for testing the MQTT related features * \param topic */ bool LiveDataDock::testUnsubscribe(const QString& topic) { QTreeWidgetItem* currentItem = nullptr; for(int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) { if(checkTopicContains(ui.twSubscriptions->topLevelItem(i)->text(0), topic)) { currentItem = ui.twSubscriptions->topLevelItem(i); break; } } if(currentItem) { do { if(topic == currentItem->text(0)) { ui.twSubscriptions->setCurrentItem(currentItem); removeSubscription(); return true; } else { for(int i = 0; i < currentItem->childCount(); ++i) { qDebug()<child(i)->text(0)<<" "<child(i)->text(0), topic)) { currentItem = currentItem->child(i); break; } else if (i == currentItem->childCount() - 1) return false; } } } while(currentItem); } else return false; return false; } void LiveDataDock::showWillSettings() { QMenu menu; const MQTTClient* const fmc = m_mqttClients.at(0); QVector topics = fmc->topicNames(); MQTTWillSettingsWidget willSettings(&menu, fmc->willSettings(), topics); connect(&willSettings, &MQTTWillSettingsWidget::useChanged, this, &LiveDataDock::useWillMessage); connect(&willSettings, &MQTTWillSettingsWidget::messageTypeChanged, this, &LiveDataDock::willMessageTypeChanged); connect(&willSettings, &MQTTWillSettingsWidget::updateTypeChanged, this, &LiveDataDock::willUpdateTypeChanged); connect(&willSettings, &MQTTWillSettingsWidget::retainChanged, this, &LiveDataDock::willRetainChanged); connect(&willSettings, &MQTTWillSettingsWidget::intervalChanged, this, &LiveDataDock::willUpdateIntervalChanged); connect(&willSettings, &MQTTWillSettingsWidget::ownMessageChanged, this, &LiveDataDock::willOwnMessageChanged); connect(&willSettings, &MQTTWillSettingsWidget::topicChanged, this, &LiveDataDock::willTopicChanged); connect(&willSettings, &MQTTWillSettingsWidget::statisticsChanged, this, &LiveDataDock::statisticsChanged); connect(&willSettings, &MQTTWillSettingsWidget::QoSChanged, this, &LiveDataDock::willQoSChanged); connect(&willSettings, SIGNAL(canceled()), &menu, SLOT(close())); QWidgetAction* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&willSettings); menu.addAction(widgetAction); QPoint pos(ui.bWillSettings->sizeHint().width(),ui.bWillSettings->sizeHint().height()); menu.exec(ui.bWillSettings->mapToGlobal(pos)); } #endif diff --git a/src/kdefrontend/dockwidgets/MatrixDock.cpp b/src/kdefrontend/dockwidgets/MatrixDock.cpp index b3f08fd02..567b93afb 100644 --- a/src/kdefrontend/dockwidgets/MatrixDock.cpp +++ b/src/kdefrontend/dockwidgets/MatrixDock.cpp @@ -1,387 +1,387 @@ /*************************************************************************** File : MAtrixDock.cpp Project : LabPlot Description : widget for matrix properties -------------------------------------------------------------------- Copyright : (C) 2015 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "MatrixDock.h" #include "commonfrontend/matrix/MatrixView.h" #include "kdefrontend/TemplateHandler.h" #include #include #include /*! \class MatrixDock \brief Provides a widget for editing the properties of the matrices currently selected in the project explorer. \ingroup kdefrontend */ MatrixDock::MatrixDock(QWidget* parent): QWidget(parent), m_matrix(nullptr), m_initializing(false) { ui.setupUi(this); ui.cbFormat->addItem(i18n("Decimal"), QVariant('f')); ui.cbFormat->addItem(i18n("Scientific (e)"), QVariant('e')); ui.cbFormat->addItem(i18n("Scientific (E)"), QVariant('E')); ui.cbFormat->addItem(i18n("Automatic (g)"), QVariant('g')); ui.cbFormat->addItem(i18n("Automatic (G)"), QVariant('G')); ui.cbHeader->addItem(i18n("Rows and Columns")); ui.cbHeader->addItem(i18n("xy-Values")); ui.cbHeader->addItem(i18n("Rows, Columns and xy-Values")); //Validators ui.leXStart->setValidator( new QDoubleValidator(ui.leXStart) ); ui.leXEnd->setValidator( new QDoubleValidator(ui.leXEnd) ); ui.leYStart->setValidator( new QDoubleValidator(ui.leYStart) ); ui.leYEnd->setValidator( new QDoubleValidator(ui.leYEnd) ); connect(ui.leName, &QLineEdit::textChanged, this, &MatrixDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &MatrixDock::commentChanged); connect(ui.sbColumnCount, SIGNAL(valueChanged(int)), this, SLOT(columnCountChanged(int))); connect(ui.sbRowCount, SIGNAL(valueChanged(int)), this, SLOT(rowCountChanged(int))); connect(ui.leXStart, SIGNAL(returnPressed()), this, SLOT(xStartChanged())); connect(ui.leXEnd, SIGNAL(returnPressed()), this, SLOT(xEndChanged())); connect(ui.leYStart, SIGNAL(returnPressed()), this, SLOT(yStartChanged())); connect(ui.leYEnd, SIGNAL(returnPressed()), this, SLOT(yEndChanged())); connect(ui.cbFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(numericFormatChanged(int))); connect(ui.sbPrecision, SIGNAL(valueChanged(int)), this, SLOT(precisionChanged(int))); connect(ui.cbHeader, SIGNAL(currentIndexChanged(int)), this, SLOT(headerFormatChanged(int))); - TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Matrix); + auto templateHandler = new TemplateHandler(this, TemplateHandler::Matrix); ui.gridLayout->addWidget(templateHandler, 22, 0, 1, 4); templateHandler->show(); connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), this, SLOT(loadConfigFromTemplate(KConfig&))); connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), this, SLOT(saveConfigAsTemplate(KConfig&))); connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); } void MatrixDock::setMatrices(QList list){ m_initializing = true; m_matrixList = list; m_matrix = list.first(); if (list.size()==1){ ui.leName->setEnabled(true); ui.leComment->setEnabled(true); ui.leName->setText(m_matrix->name()); ui.leComment->setText(m_matrix->comment()); }else{ //disable the fields "Name" and "Comment" if there are more the one matrix ui.leName->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(""); ui.leComment->setText(""); } //show the properties of the first Matrix in the list, if there are >1 matrixs this->load(); // undo functions connect(m_matrix, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(matrixDescriptionChanged(const AbstractAspect*))); connect(m_matrix, SIGNAL(rowCountChanged(int)), this, SLOT(matrixRowCountChanged(int))); connect(m_matrix, SIGNAL(columnCountChanged(int)), this, SLOT(matrixColumnCountChanged(int))); connect(m_matrix, SIGNAL(xStartChanged(double)), this, SLOT(matrixXStartChanged(double))); connect(m_matrix, SIGNAL(xEndChanged(double)), this, SLOT(matrixXEndChanged(double))); connect(m_matrix, SIGNAL(yStartChanged(double)), this, SLOT(matrixYStartChanged(double))); connect(m_matrix, SIGNAL(yEndChanged(double)), this, SLOT(matrixYEndChanged(double))); connect(m_matrix, SIGNAL(numericFormatChanged(char)), this, SLOT(matrixNumericFormatChanged(char))); connect(m_matrix, SIGNAL(precisionChanged(int)), this, SLOT(matrixPrecisionChanged(int))); connect(m_matrix, SIGNAL(headerFormatChanged(Matrix::HeaderFormat)), this, SLOT(matrixHeaderFormatChanged(Matrix::HeaderFormat))); m_initializing = false; } //************************************************************* //****** SLOTs for changes triggered in MatrixDock ******* //************************************************************* void MatrixDock::nameChanged() { if (m_initializing) return; m_matrix->setName(ui.leName->text()); } void MatrixDock::commentChanged() { if (m_initializing) return; m_matrix->setComment(ui.leComment->text()); } //mapping to the logical coordinates void MatrixDock::xStartChanged() { if (m_initializing) return; QString str = ui.leXStart->text().trimmed(); if (str.isEmpty()) return; double value = str.toDouble(); for (auto* matrix : m_matrixList) matrix->setXStart(value); } void MatrixDock::xEndChanged() { if (m_initializing) return; QString str = ui.leXEnd->text().trimmed(); if (str.isEmpty()) return; double value = str.toDouble(); for (auto* matrix : m_matrixList) matrix->setXEnd(value); } void MatrixDock::yStartChanged() { if (m_initializing) return; QString str = ui.leYStart->text().trimmed(); if (str.isEmpty()) return; double value = str.toDouble(); for (auto* matrix : m_matrixList) matrix->setYStart(value); } void MatrixDock::yEndChanged() { if (m_initializing) return; QString str = ui.leYEnd->text().trimmed(); if (str.isEmpty()) return; double value = str.toDouble(); for (auto* matrix : m_matrixList) matrix->setYEnd(value); } //format void MatrixDock::numericFormatChanged(int index) { if (m_initializing) return; char format = ui.cbFormat->itemData(index).toChar().toLatin1(); for (auto* matrix : m_matrixList) matrix->setNumericFormat(format); } void MatrixDock::precisionChanged(int precision) { if (m_initializing) return; for (auto* matrix : m_matrixList) matrix->setPrecision(precision); } void MatrixDock::headerFormatChanged(int value) { if (m_initializing) return; - Matrix::HeaderFormat format = (Matrix::HeaderFormat)value; + auto format = (Matrix::HeaderFormat)value; for (auto* matrix : m_matrixList) matrix->setHeaderFormat(format); } void MatrixDock::rowCountChanged(int rows) { if (m_initializing) return; for (auto* matrix : m_matrixList) matrix->setRowCount(rows); } void MatrixDock::columnCountChanged(int columns) { if (m_initializing) return; for (auto* matrix : m_matrixList) matrix->setColumnCount(columns); } //************************************************************* //******** SLOTs for changes triggered in Matrix ********* //************************************************************* void MatrixDock::matrixDescriptionChanged(const AbstractAspect* aspect) { if (m_matrix != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } //matrix dimensions void MatrixDock::matrixRowCountChanged(int count) { m_initializing = true; ui.sbRowCount->setValue(count); m_initializing = false; } void MatrixDock::matrixColumnCountChanged(int count) { m_initializing = true; ui.sbColumnCount->setValue(count); m_initializing = false; } //mapping to the logical coordinates void MatrixDock::matrixXStartChanged(double value) { m_initializing = true; ui.leXStart->setText(QString::number(value)); m_initializing = false; } void MatrixDock::matrixXEndChanged(double value) { m_initializing = true; ui.leXEnd->setText(QString::number(value)); m_initializing = false; } void MatrixDock::matrixYStartChanged(double value) { m_initializing = true; ui.leYStart->setText(QString::number(value)); m_initializing = false; } void MatrixDock::matrixYEndChanged(double value) { m_initializing = true; ui.leYEnd->setText(QString::number(value)); m_initializing = false; } //format void MatrixDock::matrixNumericFormatChanged(char format) { m_initializing = true; int index = ui.cbFormat->findData((int)format); ui.cbFormat->setCurrentIndex(index); m_initializing = false; } void MatrixDock::matrixPrecisionChanged(int precision) { m_initializing = true; ui.sbPrecision->setValue(precision); m_initializing = false; } void MatrixDock::matrixHeaderFormatChanged(Matrix::HeaderFormat format) { m_initializing = true; ui.cbHeader->setCurrentIndex((int)format); m_initializing = false; } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void MatrixDock::load() { //matrix dimensions ui.sbRowCount->setValue(m_matrix->rowCount()); ui.sbColumnCount->setValue(m_matrix->columnCount()); //mapping to the logical coordinates ui.leXStart->setText(QString::number(m_matrix->xStart())); ui.leXEnd->setText(QString::number(m_matrix->xEnd())); ui.leYStart->setText(QString::number(m_matrix->yStart())); ui.leYEnd->setText(QString::number(m_matrix->yEnd())); //format ui.cbFormat->setCurrentIndex(ui.cbFormat->findData((int)m_matrix->numericFormat())); ui.sbPrecision->setValue(m_matrix->precision()); ui.cbHeader->setCurrentIndex(m_matrix->headerFormat()); } void MatrixDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; const int index = config.name().lastIndexOf(QDir::separator()); if (index != -1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); const int size = m_matrixList.size(); if (size>1) m_matrix->beginMacro(i18n("%1 matrices: template \"%2\" loaded", size, name)); else m_matrix->beginMacro(i18n("%1: template \"%2\" loaded", m_matrix->name(), name)); this->loadConfig(config); m_matrix->endMacro(); } /*! loads saved matrix properties from \c config. */ void MatrixDock::loadConfig(KConfig& config){ KConfigGroup group = config.group("Matrix"); //matrix dimensions ui.sbRowCount->setValue(group.readEntry("RowCount", m_matrix->rowCount())); ui.sbColumnCount->setValue(group.readEntry("ColumnCount", m_matrix->columnCount())); //mapping to the logical coordinates ui.leXStart->setText( QString::number(group.readEntry("XStart", m_matrix->xStart())) ); ui.leXEnd->setText( QString::number(group.readEntry("XEnd", m_matrix->xEnd())) ); ui.leYStart->setText( QString::number(group.readEntry("YStart", m_matrix->yStart())) ); ui.leYEnd->setText( QString::number(group.readEntry("YEnd", m_matrix->yEnd())) ); //format ui.cbFormat->setCurrentIndex( ui.cbFormat->findData(group.readEntry("NumericFormat", QString(m_matrix->numericFormat()))) ); ui.sbPrecision->setValue(group.readEntry("Precision", m_matrix->precision())); ui.cbHeader->setCurrentIndex(group.readEntry("HeaderFormat", (int)m_matrix->headerFormat())); } /*! saves matrix properties to \c config. */ void MatrixDock::saveConfigAsTemplate(KConfig& config){ KConfigGroup group = config.group("Matrix"); //matrix dimensions group.writeEntry("RowCount", ui.sbRowCount->value()); group.writeEntry("ColumnCount", ui.sbColumnCount->value()); //mapping to the logical coordinates group.writeEntry("XStart", ui.leXStart->text().toInt()); group.writeEntry("XEnd", ui.leXEnd->text().toInt()); group.writeEntry("YStart", ui.leYStart->text().toInt()); group.writeEntry("YEnd", ui.leYEnd->text().toInt()); //format group.writeEntry("NumericFormat", ui.cbFormat->itemData(ui.cbFormat->currentIndex())); group.writeEntry("Precision", ui.sbPrecision->value()); group.writeEntry("HeaderFormat", ui.cbHeader->currentIndex()); config.sync(); } diff --git a/src/kdefrontend/dockwidgets/ProjectDock.cpp b/src/kdefrontend/dockwidgets/ProjectDock.cpp index 92ab61843..0dffaa008 100644 --- a/src/kdefrontend/dockwidgets/ProjectDock.cpp +++ b/src/kdefrontend/dockwidgets/ProjectDock.cpp @@ -1,136 +1,136 @@ /*************************************************************************** File : ProjectDock.cpp Project : LabPlot Description : widget for project properties -------------------------------------------------------------------- Copyright : (C) 2012-2013 by Stefan Gerlach (stefan.gerlach@uni-konstanz.de) Copyright : (C) 2013 Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "ProjectDock.h" #include "backend/core/Project.h" #include "kdefrontend/TemplateHandler.h" #include /*! \class ProjectDock \brief Provides a widget for editing the properties of a project \ingroup kdefrontend */ ProjectDock::ProjectDock(QWidget *parent): QWidget(parent), m_project(nullptr), m_initializing(false) { ui.setupUi(this); // SLOTS connect(ui.leName, &QLineEdit::textChanged, this, &ProjectDock::titleChanged); connect(ui.leAuthor, &QLineEdit::textChanged, this, &ProjectDock::authorChanged); connect(ui.tbComment, &QTextBrowser::textChanged, this, &ProjectDock::commentChanged); - TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Worksheet); - ui.verticalLayout->addWidget(templateHandler, 0, 0); + auto templateHandler = new TemplateHandler(this, TemplateHandler::Worksheet); + ui.verticalLayout->addWidget(templateHandler, 0, nullptr); templateHandler->show(); connect(templateHandler, &TemplateHandler::loadConfigRequested, this, &ProjectDock::loadConfig); connect(templateHandler, &TemplateHandler::saveConfigRequested, this, &ProjectDock::saveConfig); this->retranslateUi(); } void ProjectDock::setProject(Project *project) { m_initializing=true; m_project = project; ui.leFileName->setText(project->fileName()); ui.lVersion->setText(project->version()); ui.lCreated->setText(project->creationTime().toString()); ui.lModified->setText(project->modificationTime().toString()); //show default properties of the project KConfig config("", KConfig::SimpleConfig); loadConfig(config); connect(m_project, &Project::aspectDescriptionChanged, this, &ProjectDock::projectDescriptionChanged); m_initializing = false; } //************************************************************ //****************** SLOTS ******************************** //************************************************************ void ProjectDock::retranslateUi(){ } void ProjectDock::titleChanged(const QString& title){ if (m_initializing) return; m_project->setName(title); } void ProjectDock::authorChanged(const QString& author){ if (m_initializing) return; m_project->setAuthor(author); } void ProjectDock::commentChanged(){ if (m_initializing) return; m_project->setComment(ui.tbComment->toPlainText()); } //************************************************************* //******** SLOTs for changes triggered in Project *********** //************************************************************* void ProjectDock::projectDescriptionChanged(const AbstractAspect* aspect) { if (m_project != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.tbComment->toPlainText()) ui.tbComment->setText(aspect->comment()); m_initializing = false; } //************************************************************* //************************* Settings ************************** //************************************************************* void ProjectDock::loadConfig(KConfig& config){ KConfigGroup group = config.group( "Project" ); ui.leName->setText( group.readEntry("Name", m_project->name()) ); ui.leAuthor->setText( group.readEntry("Author", m_project->author()) ); ui.tbComment->setText( group.readEntry("Comment", m_project->comment()) ); } void ProjectDock::saveConfig(KConfig& config){ KConfigGroup group = config.group( "Project" ); group.writeEntry("Name", ui.leName->text()); group.writeEntry("Author", ui.leAuthor->text()); group.writeEntry("Comment", ui.tbComment->toPlainText()); } diff --git a/src/kdefrontend/dockwidgets/SpreadsheetDock.cpp b/src/kdefrontend/dockwidgets/SpreadsheetDock.cpp index 4752fb371..388a52104 100644 --- a/src/kdefrontend/dockwidgets/SpreadsheetDock.cpp +++ b/src/kdefrontend/dockwidgets/SpreadsheetDock.cpp @@ -1,229 +1,229 @@ /*************************************************************************** File : SpreadsheetDock.cpp Project : LabPlot Description : widget for spreadsheet properties -------------------------------------------------------------------- Copyright : (C) 2010-2015 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2012-2013 by Stefan Gerlach (stefan.gerlach@uni-konstanz.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "SpreadsheetDock.h" #include "commonfrontend/spreadsheet/SpreadsheetView.h" #include "backend/spreadsheet/Spreadsheet.h" #include "kdefrontend/TemplateHandler.h" #include #include #include /*! \class SpreadsheetDock \brief Provides a widget for editing the properties of the spreadsheets currently selected in the project explorer. \ingroup kdefrontend */ SpreadsheetDock::SpreadsheetDock(QWidget* parent): QWidget(parent), m_spreadsheet(nullptr), m_initializing(false) { ui.setupUi(this); connect(ui.leName, &QLineEdit::textChanged, this, &SpreadsheetDock::nameChanged); connect(ui.teComment, &QTextEdit::textChanged, this, &SpreadsheetDock::commentChanged); connect(ui.sbColumnCount, static_cast(&QSpinBox::valueChanged), this, &SpreadsheetDock::columnCountChanged); connect(ui.sbRowCount, static_cast(&QSpinBox::valueChanged), this, &SpreadsheetDock::rowCountChanged); connect(ui.cbShowComments, &QCheckBox::stateChanged, this, &SpreadsheetDock::commentsShownChanged); - TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::Spreadsheet); + auto templateHandler = new TemplateHandler(this, TemplateHandler::Spreadsheet); ui.gridLayout->addWidget(templateHandler, 11, 0, 1, 4); templateHandler->show(); connect(templateHandler, &TemplateHandler::loadConfigRequested, this, &SpreadsheetDock::loadConfigFromTemplate); connect(templateHandler, &TemplateHandler::saveConfigRequested, this, &SpreadsheetDock::saveConfigAsTemplate); connect(templateHandler, &TemplateHandler::info, this, &SpreadsheetDock::info); } /*! set the current spreadsheet(s) */ void SpreadsheetDock::setSpreadsheets(QList list) { m_initializing = true; m_spreadsheetList = list; m_spreadsheet = list.first(); if (list.size() == 1) { ui.leName->setEnabled(true); ui.teComment->setEnabled(true); ui.leName->setText(m_spreadsheet->name()); ui.teComment->setText(m_spreadsheet->comment()); } else { //disable the fields "Name" and "Comment" if there are more then one spreadsheet ui.leName->setEnabled(false); ui.teComment->setEnabled(false); ui.leName->setText(""); ui.teComment->setText(""); } //show the properties of the first Spreadsheet in the list this->load(); // undo functions connect(m_spreadsheet, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(spreadsheetDescriptionChanged(const AbstractAspect*))); connect(m_spreadsheet, SIGNAL(rowCountChanged(int)),this, SLOT(spreadsheetRowCountChanged(int))); connect(m_spreadsheet, SIGNAL(columnCountChanged(int)),this, SLOT(spreadsheetColumnCountChanged(int))); //TODO: show comments m_initializing = false; } //************************************************************* //****** SLOTs for changes triggered in SpreadsheetDock ******* //************************************************************* void SpreadsheetDock::nameChanged() { if (m_initializing) return; m_spreadsheet->setName(ui.leName->text()); } void SpreadsheetDock::commentChanged() { if (m_initializing) return; m_spreadsheet->setComment(ui.teComment->document()->toPlainText()); } void SpreadsheetDock::rowCountChanged(int rows) { if (m_initializing) return; for (auto* spreadsheet: m_spreadsheetList) spreadsheet->setRowCount(rows); } void SpreadsheetDock::columnCountChanged(int columns) { if (m_initializing) return; for (auto* spreadsheet: m_spreadsheetList) spreadsheet->setColumnCount(columns); } /*! switches on/off the comment header in the views of the selected spreadsheets. */ void SpreadsheetDock::commentsShownChanged(int state) { if (m_initializing) return; for (auto* spreadsheet: m_spreadsheetList) qobject_cast(spreadsheet->view())->showComments(state); } //************************************************************* //******** SLOTs for changes triggered in Spreadsheet ********* //************************************************************* void SpreadsheetDock::spreadsheetDescriptionChanged(const AbstractAspect* aspect) { if (m_spreadsheet != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.teComment->toPlainText()) ui.teComment->document()->setPlainText(aspect->comment()); m_initializing = false; } void SpreadsheetDock::spreadsheetRowCountChanged(int count) { m_initializing = true; ui.sbRowCount->setValue(count); m_initializing = false; } void SpreadsheetDock::spreadsheetColumnCountChanged(int count) { m_initializing = true; ui.sbColumnCount->setValue(count); m_initializing = false; } void SpreadsheetDock::spreadsheetShowCommentsChanged(int checked) { m_initializing = true; ui.cbShowComments->setChecked(checked); m_initializing = false; } //************************************************************* //******************** SETTINGS ******************************* //************************************************************* void SpreadsheetDock::load() { ui.sbColumnCount->setValue(m_spreadsheet->columnCount()); ui.sbRowCount->setValue(m_spreadsheet->rowCount()); - SpreadsheetView* view = qobject_cast(m_spreadsheet->view()); + auto view = qobject_cast(m_spreadsheet->view()); ui.cbShowComments->setChecked(view->areCommentsShown()); } void SpreadsheetDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; - int index = config.name().lastIndexOf(QDir::separator()); + const int index = config.name().lastIndexOf(QDir::separator()); if (index != -1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); - int size = m_spreadsheetList.size(); - if (size>1) + const int size = m_spreadsheetList.size(); + if (size > 1) m_spreadsheet->beginMacro(i18n("%1 spreadsheets: template \"%2\" loaded", size, name)); else m_spreadsheet->beginMacro(i18n("%1: template \"%2\" loaded", m_spreadsheet->name(), name)); this->loadConfig(config); m_spreadsheet->endMacro(); } /*! loads saved spreadsheet properties from \c config. */ void SpreadsheetDock::loadConfig(KConfig& config) { KConfigGroup group = config.group( "Spreadsheet" ); ui.sbColumnCount->setValue(group.readEntry("ColumnCount", m_spreadsheet->columnCount())); ui.sbRowCount->setValue(group.readEntry("RowCount", m_spreadsheet->rowCount())); - SpreadsheetView* view = qobject_cast(m_spreadsheet->view()); + auto view = qobject_cast(m_spreadsheet->view()); ui.cbShowComments->setChecked(group.readEntry("ShowComments", view->areCommentsShown())); } /*! saves spreadsheet properties to \c config. */ void SpreadsheetDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "Spreadsheet" ); group.writeEntry("ColumnCount", ui.sbColumnCount->value()); group.writeEntry("RowCount", ui.sbRowCount->value()); group.writeEntry("ShowComments",ui.cbShowComments->isChecked()); config.sync(); } diff --git a/src/kdefrontend/dockwidgets/XYCurveDock.cpp b/src/kdefrontend/dockwidgets/XYCurveDock.cpp index 272ca2240..81d724ad3 100644 --- a/src/kdefrontend/dockwidgets/XYCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYCurveDock.cpp @@ -1,2255 +1,2254 @@ /*************************************************************************** File : XYCurveDock.cpp Project : LabPlot Description : widget for XYCurve properties -------------------------------------------------------------------- Copyright : (C) 2010-2018 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2012-2017 Stefan Gerlach (stefan.gerlach@uni-konstanz.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "XYCurveDock.h" #include "backend/worksheet/plots/cartesian/XYCurve.h" #include "backend/worksheet/Worksheet.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/column/Column.h" #include "backend/core/Project.h" #include "backend/core/datatypes/Double2StringFilter.h" #include "backend/core/datatypes/DateTime2StringFilter.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include "kdefrontend/TemplateHandler.h" #include "kdefrontend/GuiTools.h" #include #include #include #include #include #include #include #include #include #include /*! \class XYCurveDock \brief Provides a widget for editing the properties of the XYCurves (2D-curves) currently selected in the project explorer. If more than one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ XYCurveDock::XYCurveDock(QWidget* parent) : QWidget(parent), cbXColumn(nullptr), cbYColumn(nullptr), m_curve(nullptr), m_aspectTreeModel(nullptr) { ui.setupUi(this); //Tab "Values" - QGridLayout* gridLayout = qobject_cast(ui.tabValues->layout()); + auto gridLayout = qobject_cast(ui.tabValues->layout()); cbValuesColumn = new TreeViewComboBox(ui.tabValues); gridLayout->addWidget(cbValuesColumn, 2, 2, 1, 1); //Tab "Filling" ui.cbFillingColorStyle->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); ui.bFillingOpen->setIcon( QIcon::fromTheme("document-open") ); - QCompleter* completer = new QCompleter(this); + auto completer = new QCompleter(this); completer->setModel(new QDirModel); ui.leFillingFileName->setCompleter(completer); //Tab "Error bars" gridLayout = qobject_cast(ui.tabErrorBars->layout()); cbXErrorPlusColumn = new TreeViewComboBox(ui.tabErrorBars); gridLayout->addWidget(cbXErrorPlusColumn, 2, 2, 1, 1); cbXErrorMinusColumn = new TreeViewComboBox(ui.tabErrorBars); gridLayout->addWidget(cbXErrorMinusColumn, 3, 2, 1, 1); cbYErrorPlusColumn = new TreeViewComboBox(ui.tabErrorBars); gridLayout->addWidget(cbYErrorPlusColumn, 7, 2, 1, 1); cbYErrorMinusColumn = new TreeViewComboBox(ui.tabErrorBars); gridLayout->addWidget(cbYErrorMinusColumn, 8, 2, 1, 1); //adjust layouts in the tabs - for (int i=0; icount(); ++i) { - QGridLayout* layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); + for (int i = 0; i < ui.tabWidget->count(); ++i) { + auto layout = dynamic_cast(ui.tabWidget->widget(i)->layout()); if (!layout) continue; layout->setContentsMargins(2,2,2,2); layout->setHorizontalSpacing(2); layout->setVerticalSpacing(2); } //Slots //Lines connect( ui.cbLineType, SIGNAL(currentIndexChanged(int)), this, SLOT(lineTypeChanged(int)) ); connect( ui.sbLineInterpolationPointsCount, SIGNAL(valueChanged(int)), this, SLOT(lineInterpolationPointsCountChanged(int)) ); connect( ui.chkLineSkipGaps, SIGNAL(clicked(bool)), this, SLOT(lineSkipGapsChanged(bool)) ); connect( ui.chkLineIncreasingXOnly, &QCheckBox::clicked, this, &XYCurveDock::lineIncreasingXOnlyChanged ); connect( ui.cbLineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(lineStyleChanged(int)) ); connect( ui.kcbLineColor, SIGNAL(changed(QColor)), this, SLOT(lineColorChanged(QColor)) ); connect( ui.sbLineWidth, SIGNAL(valueChanged(double)), this, SLOT(lineWidthChanged(double)) ); connect( ui.sbLineOpacity, SIGNAL(valueChanged(int)), this, SLOT(lineOpacityChanged(int)) ); connect( ui.cbDropLineType, SIGNAL(currentIndexChanged(int)), this, SLOT(dropLineTypeChanged(int)) ); connect( ui.cbDropLineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(dropLineStyleChanged(int)) ); connect( ui.kcbDropLineColor, SIGNAL(changed(QColor)), this, SLOT(dropLineColorChanged(QColor)) ); connect( ui.sbDropLineWidth, SIGNAL(valueChanged(double)), this, SLOT(dropLineWidthChanged(double)) ); connect( ui.sbDropLineOpacity, SIGNAL(valueChanged(int)), this, SLOT(dropLineOpacityChanged(int)) ); //Symbol connect( ui.cbSymbolStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolsStyleChanged(int)) ); connect( ui.sbSymbolSize, SIGNAL(valueChanged(double)), this, SLOT(symbolsSizeChanged(double)) ); connect( ui.sbSymbolRotation, SIGNAL(valueChanged(int)), this, SLOT(symbolsRotationChanged(int)) ); connect( ui.sbSymbolOpacity, SIGNAL(valueChanged(int)), this, SLOT(symbolsOpacityChanged(int)) ); connect( ui.cbSymbolFillingStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolsFillingStyleChanged(int)) ); connect( ui.kcbSymbolFillingColor, SIGNAL(changed(QColor)), this, SLOT(symbolsFillingColorChanged(QColor)) ); connect( ui.cbSymbolBorderStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(symbolsBorderStyleChanged(int)) ); connect( ui.kcbSymbolBorderColor, SIGNAL(changed(QColor)), this, SLOT(symbolsBorderColorChanged(QColor)) ); connect( ui.sbSymbolBorderWidth, SIGNAL(valueChanged(double)), this, SLOT(symbolsBorderWidthChanged(double)) ); //Values connect( ui.cbValuesType, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesTypeChanged(int)) ); connect( cbValuesColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(valuesColumnChanged(QModelIndex)) ); connect( ui.cbValuesPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesPositionChanged(int)) ); connect( ui.sbValuesDistance, SIGNAL(valueChanged(double)), this, SLOT(valuesDistanceChanged(double)) ); connect( ui.sbValuesRotation, SIGNAL(valueChanged(int)), this, SLOT(valuesRotationChanged(int)) ); connect( ui.sbValuesOpacity, SIGNAL(valueChanged(int)), this, SLOT(valuesOpacityChanged(int)) ); //TODO connect( ui.cbValuesFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(valuesColumnFormatChanged(int)) ); connect( ui.leValuesPrefix, SIGNAL(returnPressed()), this, SLOT(valuesPrefixChanged()) ); connect( ui.leValuesSuffix, SIGNAL(returnPressed()), this, SLOT(valuesSuffixChanged()) ); connect( ui.kfrValuesFont, SIGNAL(fontSelected(QFont)), this, SLOT(valuesFontChanged(QFont)) ); connect( ui.kcbValuesColor, SIGNAL(changed(QColor)), this, SLOT(valuesColorChanged(QColor)) ); //Filling connect( ui.cbFillingPosition, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingPositionChanged(int)) ); connect( ui.cbFillingType, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingTypeChanged(int)) ); connect( ui.cbFillingColorStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingColorStyleChanged(int)) ); connect( ui.cbFillingImageStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingImageStyleChanged(int)) ); connect( ui.cbFillingBrushStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(fillingBrushStyleChanged(int)) ); connect(ui.bFillingOpen, SIGNAL(clicked(bool)), this, SLOT(selectFile())); connect( ui.leFillingFileName, SIGNAL(returnPressed()), this, SLOT(fileNameChanged()) ); connect( ui.leFillingFileName, SIGNAL(textChanged(QString)), this, SLOT(fileNameChanged()) ); connect( ui.kcbFillingFirstColor, SIGNAL(changed(QColor)), this, SLOT(fillingFirstColorChanged(QColor)) ); connect( ui.kcbFillingSecondColor, SIGNAL(changed(QColor)), this, SLOT(fillingSecondColorChanged(QColor)) ); connect( ui.sbFillingOpacity, SIGNAL(valueChanged(int)), this, SLOT(fillingOpacityChanged(int)) ); //Error bars connect( ui.cbXErrorType, SIGNAL(currentIndexChanged(int)), this, SLOT(xErrorTypeChanged(int)) ); connect( cbXErrorPlusColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xErrorPlusColumnChanged(QModelIndex)) ); connect( cbXErrorMinusColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xErrorMinusColumnChanged(QModelIndex)) ); connect( ui.cbYErrorType, SIGNAL(currentIndexChanged(int)), this, SLOT(yErrorTypeChanged(int)) ); connect( cbYErrorPlusColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yErrorPlusColumnChanged(QModelIndex)) ); connect( cbYErrorMinusColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yErrorMinusColumnChanged(QModelIndex)) ); connect( ui.cbErrorBarsType, SIGNAL(currentIndexChanged(int)), this, SLOT(errorBarsTypeChanged(int)) ); connect( ui.sbErrorBarsCapSize, SIGNAL(valueChanged(double)), this, SLOT(errorBarsCapSizeChanged(double)) ); connect( ui.cbErrorBarsStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(errorBarsStyleChanged(int)) ); connect( ui.kcbErrorBarsColor, SIGNAL(changed(QColor)), this, SLOT(errorBarsColorChanged(QColor)) ); connect( ui.sbErrorBarsWidth, SIGNAL(valueChanged(double)), this, SLOT(errorBarsWidthChanged(double)) ); connect( ui.sbErrorBarsOpacity, SIGNAL(valueChanged(int)), this, SLOT(errorBarsOpacityChanged(int)) ); //template handler - TemplateHandler* templateHandler = new TemplateHandler(this, TemplateHandler::XYCurve); + auto templateHandler = new TemplateHandler(this, TemplateHandler::XYCurve); ui.verticalLayout->addWidget(templateHandler); templateHandler->show(); connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), this, SLOT(loadConfigFromTemplate(KConfig&))); connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), this, SLOT(saveConfigAsTemplate(KConfig&))); connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString))); retranslateUi(); init(); } XYCurveDock::~XYCurveDock() { if (m_aspectTreeModel) delete m_aspectTreeModel; } void XYCurveDock::setupGeneral() { QWidget* generalTab = new QWidget(ui.tabGeneral); uiGeneralTab.setupUi(generalTab); - QHBoxLayout* layout = new QHBoxLayout(ui.tabGeneral); + auto layout = new QHBoxLayout(ui.tabGeneral); layout->setMargin(0); layout->addWidget(generalTab); // Tab "General" - QGridLayout* gridLayout = qobject_cast(generalTab->layout()); + auto gridLayout = qobject_cast(generalTab->layout()); cbXColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbXColumn, 2, 2, 1, 1); cbYColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbYColumn, 3, 2, 1, 1); //General connect(uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYCurveDock::nameChanged); connect(uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYCurveDock::commentChanged); - connect( uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); - connect( cbXColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xColumnChanged(QModelIndex)) ); - connect( cbYColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yColumnChanged(QModelIndex)) ); + connect(uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool))); + connect(cbXColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xColumnChanged(QModelIndex))); + connect(cbYColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yColumnChanged(QModelIndex))); } void XYCurveDock::init() { m_initializing = true; //Line ui.cbLineType->addItem(i18n("None")); ui.cbLineType->addItem(i18n("Line")); ui.cbLineType->addItem(i18n("Horiz. Start")); ui.cbLineType->addItem(i18n("Vert. Start")); ui.cbLineType->addItem(i18n("Horiz. Midpoint")); ui.cbLineType->addItem(i18n("Vert. Midpoint")); ui.cbLineType->addItem(i18n("2-segments")); ui.cbLineType->addItem(i18n("3-segments")); ui.cbLineType->addItem(i18n("Cubic Spline (Natural)")); ui.cbLineType->addItem(i18n("Cubic Spline (Periodic)")); ui.cbLineType->addItem(i18n("Akima-spline (Natural)")); ui.cbLineType->addItem(i18n("Akima-spline (Periodic)")); QPainter pa; //TODO size of the icon depending on the actual height of the combobox? int iconSize = 20; QPixmap pm(iconSize, iconSize); ui.cbLineType->setIconSize(QSize(iconSize, iconSize)); QPen pen(Qt::SolidPattern, 0); const QColor& color = (palette().color(QPalette::Base).lightness() < 128) ? Qt::white : Qt::black; pen.setColor(color); pa.setPen( pen ); //no line pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.end(); ui.cbLineType->setItemIcon(0, pm); //line pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,17,17); pa.end(); ui.cbLineType->setItemIcon(1, pm); pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,17,3); pa.drawLine(17,3,17,17); pa.end(); ui.cbLineType->setItemIcon(2, pm); pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,3,17); pa.drawLine(3,17,17,17); pa.end(); ui.cbLineType->setItemIcon(3, pm); //horizontal midpoint pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,10,3); pa.drawLine(10,3,10,17); pa.drawLine(10,17,17,17); pa.end(); ui.cbLineType->setItemIcon(4, pm); //vertical midpoint pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,3,10); pa.drawLine(3,10,17,10); pa.drawLine(17,10,17,17); pa.end(); ui.cbLineType->setItemIcon(5, pm); //2-segments pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 8,8,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,10,10); pa.end(); ui.cbLineType->setItemIcon(6, pm); //3-segments pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 8,8,4,4); pa.drawEllipse( 15,15,4,4); pa.drawLine(3,3,17,17); pa.end(); ui.cbLineType->setItemIcon(7, pm); //natural spline pm.fill(Qt::transparent); pa.begin( &pm ); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.drawEllipse( 1,1,4,4); pa.drawEllipse( 15,15,4,4); pa.rotate(45); pa.drawArc(2*sqrt(2),-4,17*sqrt(2),20,30*16,120*16); pa.end(); ui.cbLineType->setItemIcon(8, pm); ui.cbLineType->setItemIcon(9, pm); ui.cbLineType->setItemIcon(10, pm); ui.cbLineType->setItemIcon(11, pm); GuiTools::updatePenStyles(ui.cbLineStyle, Qt::black); //Drop lines ui.cbDropLineType->addItem(i18n("No Drop Lines")); ui.cbDropLineType->addItem(i18n("Drop Lines, X")); ui.cbDropLineType->addItem(i18n("Drop Lines, Y")); ui.cbDropLineType->addItem(i18n("Drop Lines, XY")); ui.cbDropLineType->addItem(i18n("Drop Lines, X, Zero Baseline")); ui.cbDropLineType->addItem(i18n("Drop Lines, X, Min Baseline")); ui.cbDropLineType->addItem(i18n("Drop Lines, X, Max Baseline")); GuiTools::updatePenStyles(ui.cbDropLineStyle, Qt::black); //Symbols GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, Qt::black); ui.cbSymbolStyle->setIconSize(QSize(iconSize, iconSize)); QTransform trafo; trafo.scale(15, 15); ui.cbSymbolStyle->addItem(i18n("None")); for (int i = 1; i < 19; ++i) { //TODO: use enum count - Symbol::Style style = (Symbol::Style)i; + const auto style = (Symbol::Style)i; pm.fill(Qt::transparent); pa.begin(&pm); pa.setPen(pen); pa.setRenderHint(QPainter::Antialiasing); pa.translate(iconSize/2,iconSize/2); pa.drawPath(trafo.map(Symbol::pathFromStyle(style))); pa.end(); - ui.cbSymbolStyle->addItem(QIcon(pm), Symbol::nameFromStyle(style)); + ui.cbSymbolStyle->addItem(QIcon(pm), Symbol::nameFromStyle(style)); } GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, Qt::black); m_initializing = false; //Values ui.cbValuesType->addItem(i18n("No Values")); ui.cbValuesType->addItem("x"); ui.cbValuesType->addItem("y"); ui.cbValuesType->addItem("x, y"); ui.cbValuesType->addItem("(x, y)"); ui.cbValuesType->addItem(i18n("Custom Column")); ui.cbValuesPosition->addItem(i18n("Above")); ui.cbValuesPosition->addItem(i18n("Below")); ui.cbValuesPosition->addItem(i18n("Left")); ui.cbValuesPosition->addItem(i18n("Right")); //Filling ui.cbFillingPosition->clear(); ui.cbFillingPosition->addItem(i18n("None")); ui.cbFillingPosition->addItem(i18n("Above")); ui.cbFillingPosition->addItem(i18n("Below")); ui.cbFillingPosition->addItem(i18n("Zero Baseline")); ui.cbFillingPosition->addItem(i18n("Left")); ui.cbFillingPosition->addItem(i18n("Right")); ui.cbFillingType->clear(); ui.cbFillingType->addItem(i18n("Color")); ui.cbFillingType->addItem(i18n("Image")); ui.cbFillingType->addItem(i18n("Pattern")); ui.cbFillingColorStyle->clear(); ui.cbFillingColorStyle->addItem(i18n("Single Color")); ui.cbFillingColorStyle->addItem(i18n("Horizontal Gradient")); ui.cbFillingColorStyle->addItem(i18n("Vertical Gradient")); ui.cbFillingColorStyle->addItem(i18n("Diag. Gradient (From Top Left)")); ui.cbFillingColorStyle->addItem(i18n("Diag. Gradient (From Bottom Left)")); ui.cbFillingColorStyle->addItem(i18n("Radial Gradient")); ui.cbFillingImageStyle->clear(); ui.cbFillingImageStyle->addItem(i18n("Scaled and Cropped")); ui.cbFillingImageStyle->addItem(i18n("Scaled")); ui.cbFillingImageStyle->addItem(i18n("Scaled, Keep Proportions")); ui.cbFillingImageStyle->addItem(i18n("Centered")); ui.cbFillingImageStyle->addItem(i18n("Tiled")); ui.cbFillingImageStyle->addItem(i18n("Center Tiled")); GuiTools::updateBrushStyles(ui.cbFillingBrushStyle, Qt::SolidPattern); //Error-bars pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.drawLine(3,10,17,10);//vert. line pa.drawLine(10,3,10,17);//hor. line pa.end(); ui.cbErrorBarsType->addItem(i18n("Bars")); ui.cbErrorBarsType->setItemIcon(0, pm); pm.fill(Qt::transparent); pa.begin( &pm ); pa.setRenderHint(QPainter::Antialiasing); pa.setBrush(Qt::SolidPattern); pa.drawLine(3,10,17,10); //vert. line pa.drawLine(10,3,10,17); //hor. line pa.drawLine(7,3,13,3); //upper cap pa.drawLine(7,17,13,17); //bottom cap pa.drawLine(3,7,3,13); //left cap pa.drawLine(17,7,17,13); //right cap pa.end(); ui.cbErrorBarsType->addItem(i18n("Bars with Ends")); ui.cbErrorBarsType->setItemIcon(1, pm); ui.cbXErrorType->addItem(i18n("No")); ui.cbXErrorType->addItem(i18n("Symmetric")); ui.cbXErrorType->addItem(i18n("Asymmetric")); ui.cbYErrorType->addItem(i18n("No")); ui.cbYErrorType->addItem(i18n("Symmetric")); ui.cbYErrorType->addItem(i18n("Asymmetric")); GuiTools::updatePenStyles(ui.cbErrorBarsStyle, Qt::black); } void XYCurveDock::setModel() { m_aspectTreeModel->enablePlottableColumnsOnly(true); m_aspectTreeModel->enableShowPlotDesignation(true); QList list; list << "Folder" << "Workbook" << "Datapicker" << "DatapickerCurve" << "Spreadsheet" << "FileDataSource" << "Column" << "Worksheet" << "CartesianPlot" << "XYFitCurve" << "CantorWorksheet"; if (cbXColumn) { cbXColumn->setTopLevelClasses(list); cbYColumn->setTopLevelClasses(list); } cbValuesColumn->setTopLevelClasses(list); cbXErrorMinusColumn->setTopLevelClasses(list); cbXErrorPlusColumn->setTopLevelClasses(list); cbYErrorMinusColumn->setTopLevelClasses(list); cbYErrorPlusColumn->setTopLevelClasses(list); list.clear(); list << "Column" << "XYCurve"; m_aspectTreeModel->setSelectableAspects(list); if (cbXColumn) { cbXColumn->setModel(m_aspectTreeModel); cbYColumn->setModel(m_aspectTreeModel); } cbValuesColumn->setModel(m_aspectTreeModel); cbXErrorMinusColumn->setModel(m_aspectTreeModel); cbXErrorPlusColumn->setModel(m_aspectTreeModel); cbYErrorMinusColumn->setModel(m_aspectTreeModel); cbYErrorPlusColumn->setModel(m_aspectTreeModel); } /*! sets the curves. The properties of the curves in the list \c list can be edited in this widget. */ void XYCurveDock::setCurves(QList list) { m_initializing = true; m_curvesList = list; m_curve = list.first(); Q_ASSERT(m_curve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); setModel(); initGeneralTab(); initTabs(); m_initializing = false; } void XYCurveDock::initGeneralTab() { DEBUG("XYCurveDock::initGeneralTab()"); //if there are more than one curve in the list, disable the content in the tab "general" if (m_curvesList.size() == 1) { uiGeneralTab.lName->setEnabled(true); uiGeneralTab.leName->setEnabled(true); uiGeneralTab.lComment->setEnabled(true); uiGeneralTab.leComment->setEnabled(true); uiGeneralTab.lXColumn->setEnabled(true); cbXColumn->setEnabled(true); uiGeneralTab.lYColumn->setEnabled(true); cbYColumn->setEnabled(true); DEBUG("setModelIndexFromAspect()"); this->setModelIndexFromAspect(cbXColumn, m_curve->xColumn()); this->setModelIndexFromAspect(cbYColumn, m_curve->yColumn()); uiGeneralTab.leName->setText(m_curve->name()); uiGeneralTab.leComment->setText(m_curve->comment()); } else { uiGeneralTab.lName->setEnabled(false); uiGeneralTab.leName->setEnabled(false); uiGeneralTab.lComment->setEnabled(false); uiGeneralTab.leComment->setEnabled(false); uiGeneralTab.lXColumn->setEnabled(false); cbXColumn->setEnabled(false); uiGeneralTab.lYColumn->setEnabled(false); cbYColumn->setEnabled(false); cbXColumn->setCurrentModelIndex(QModelIndex()); cbYColumn->setCurrentModelIndex(QModelIndex()); uiGeneralTab.leName->setText(""); uiGeneralTab.leComment->setText(""); } //show the properties of the first curve uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); //Slots connect(m_curve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)),this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_curve, SIGNAL(xColumnChanged(const AbstractColumn*)), this, SLOT(curveXColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(yColumnChanged(const AbstractColumn*)), this, SLOT(curveYColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(visibilityChanged(bool)), this, SLOT(curveVisibilityChanged(bool))); DEBUG("XYCurveDock::initGeneralTab() DONE"); } void XYCurveDock::initTabs() { //if there are more than one curve in the list, disable the tab "general" if (m_curvesList.size() == 1) { this->setModelIndexFromAspect(cbValuesColumn, m_curve->valuesColumn()); this->setModelIndexFromAspect(cbXErrorPlusColumn, m_curve->xErrorPlusColumn()); this->setModelIndexFromAspect(cbXErrorMinusColumn, m_curve->xErrorMinusColumn()); this->setModelIndexFromAspect(cbYErrorPlusColumn, m_curve->yErrorPlusColumn()); this->setModelIndexFromAspect(cbYErrorMinusColumn, m_curve->yErrorMinusColumn()); } else { cbValuesColumn->setCurrentModelIndex(QModelIndex()); cbXErrorPlusColumn->setCurrentModelIndex(QModelIndex()); cbXErrorMinusColumn->setCurrentModelIndex(QModelIndex()); cbYErrorPlusColumn->setCurrentModelIndex(QModelIndex()); cbYErrorMinusColumn->setCurrentModelIndex(QModelIndex()); } //show the properties of the first curve load(); //Slots //Line-Tab connect(m_curve, SIGNAL(lineTypeChanged(XYCurve::LineType)), this, SLOT(curveLineTypeChanged(XYCurve::LineType))); connect(m_curve, SIGNAL(lineSkipGapsChanged(bool)), this, SLOT(curveLineSkipGapsChanged(bool))); connect(m_curve, &XYCurve::lineIncreasingXOnlyChanged, this, &XYCurveDock::curveLineIncreasingXOnlyChanged); connect(m_curve, SIGNAL(lineInterpolationPointsCountChanged(int)), this, SLOT(curveLineInterpolationPointsCountChanged(int))); connect(m_curve, SIGNAL(linePenChanged(QPen)), this, SLOT(curveLinePenChanged(QPen))); connect(m_curve, SIGNAL(lineOpacityChanged(qreal)), this, SLOT(curveLineOpacityChanged(qreal))); connect(m_curve, SIGNAL(dropLineTypeChanged(XYCurve::DropLineType)), this, SLOT(curveDropLineTypeChanged(XYCurve::DropLineType))); connect(m_curve, SIGNAL(dropLinePenChanged(QPen)), this, SLOT(curveDropLinePenChanged(QPen))); connect(m_curve, SIGNAL(dropLineOpacityChanged(qreal)), this, SLOT(curveDropLineOpacityChanged(qreal))); //Symbol-Tab connect(m_curve, SIGNAL(symbolsStyleChanged(Symbol::Style)), this, SLOT(curveSymbolsStyleChanged(Symbol::Style))); connect(m_curve, SIGNAL(symbolsSizeChanged(qreal)), this, SLOT(curveSymbolsSizeChanged(qreal))); connect(m_curve, SIGNAL(symbolsRotationAngleChanged(qreal)), this, SLOT(curveSymbolsRotationAngleChanged(qreal))); connect(m_curve, SIGNAL(symbolsOpacityChanged(qreal)), this, SLOT(curveSymbolsOpacityChanged(qreal))); connect(m_curve, SIGNAL(symbolsBrushChanged(QBrush)), this, SLOT(curveSymbolsBrushChanged(QBrush))); connect(m_curve, SIGNAL(symbolsPenChanged(QPen)), this, SLOT(curveSymbolsPenChanged(QPen))); //Values-Tab connect(m_curve, SIGNAL(valuesTypeChanged(XYCurve::ValuesType)), this, SLOT(curveValuesTypeChanged(XYCurve::ValuesType))); connect(m_curve, SIGNAL(valuesColumnChanged(const AbstractColumn*)), this, SLOT(curveValuesColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(valuesPositionChanged(XYCurve::ValuesPosition)), this, SLOT(curveValuesPositionChanged(XYCurve::ValuesPosition))); connect(m_curve, SIGNAL(valuesDistanceChanged(qreal)), this, SLOT(curveValuesDistanceChanged(qreal))); connect(m_curve, SIGNAL(valuesOpacityChanged(qreal)), this, SLOT(curveValuesOpacityChanged(qreal))); connect(m_curve, SIGNAL(valuesRotationAngleChanged(qreal)), this, SLOT(curveValuesRotationAngleChanged(qreal))); connect(m_curve, SIGNAL(valuesPrefixChanged(QString)), this, SLOT(curveValuesPrefixChanged(QString))); connect(m_curve, SIGNAL(valuesSuffixChanged(QString)), this, SLOT(curveValuesSuffixChanged(QString))); connect(m_curve, SIGNAL(valuesFontChanged(QFont)), this, SLOT(curveValuesFontChanged(QFont))); connect(m_curve, SIGNAL(valuesColorChanged(QColor)), this, SLOT(curveValuesColorChanged(QColor))); //Filling-Tab connect( m_curve, SIGNAL(fillingPositionChanged(XYCurve::FillingPosition)), this, SLOT(curveFillingPositionChanged(XYCurve::FillingPosition)) ); connect( m_curve, SIGNAL(fillingTypeChanged(PlotArea::BackgroundType)), this, SLOT(curveFillingTypeChanged(PlotArea::BackgroundType)) ); connect( m_curve, SIGNAL(fillingColorStyleChanged(PlotArea::BackgroundColorStyle)), this, SLOT(curveFillingColorStyleChanged(PlotArea::BackgroundColorStyle)) ); connect( m_curve, SIGNAL(fillingImageStyleChanged(PlotArea::BackgroundImageStyle)), this, SLOT(curveFillingImageStyleChanged(PlotArea::BackgroundImageStyle)) ); connect( m_curve, SIGNAL(fillingBrushStyleChanged(Qt::BrushStyle)), this, SLOT(curveFillingBrushStyleChanged(Qt::BrushStyle)) ); connect( m_curve, SIGNAL(fillingFirstColorChanged(QColor&)), this, SLOT(curveFillingFirstColorChanged(QColor&)) ); connect( m_curve, SIGNAL(fillingSecondColorChanged(QColor&)), this, SLOT(curveFillingSecondColorChanged(QColor&)) ); connect( m_curve, SIGNAL(fillingFileNameChanged(QString&)), this, SLOT(curveFillingFileNameChanged(QString&)) ); connect( m_curve, SIGNAL(fillingOpacityChanged(float)), this, SLOT(curveFillingOpacityChanged(float)) ); //"Error bars"-Tab connect(m_curve, SIGNAL(xErrorTypeChanged(XYCurve::ErrorType)), this, SLOT(curveXErrorTypeChanged(XYCurve::ErrorType))); connect(m_curve, SIGNAL(xErrorPlusColumnChanged(const AbstractColumn*)), this, SLOT(curveXErrorPlusColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(xErrorMinusColumnChanged(const AbstractColumn*)), this, SLOT(curveXErrorMinusColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(yErrorTypeChanged(XYCurve::ErrorType)), this, SLOT(curveYErrorTypeChanged(XYCurve::ErrorType))); connect(m_curve, SIGNAL(yErrorPlusColumnChanged(const AbstractColumn*)), this, SLOT(curveYErrorPlusColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(yErrorMinusColumnChanged(const AbstractColumn*)), this, SLOT(curveYErrorMinusColumnChanged(const AbstractColumn*))); connect(m_curve, SIGNAL(errorBarsCapSizeChanged(qreal)), this, SLOT(curveErrorBarsCapSizeChanged(qreal))); connect(m_curve, SIGNAL(errorBarsTypeChanged(XYCurve::ErrorBarsType)), this, SLOT(curveErrorBarsTypeChanged(XYCurve::ErrorBarsType))); connect(m_curve, SIGNAL(errorBarsPenChanged(QPen)), this, SLOT(curveErrorBarsPenChanged(QPen))); connect(m_curve, SIGNAL(errorBarsOpacityChanged(qreal)), this, SLOT(curveErrorBarsOpacityChanged(qreal))); } /*! depending on the currently selected values column type (column mode) updates the widgets for the values column format, shows/hides the allowed widgets, fills the corresponding combobox with the possible entries. Called when the values column was changed. synchronize this function with ColumnDock::updateFormat. */ void XYCurveDock::updateValuesFormatWidgets(const AbstractColumn::ColumnMode columnMode) { ui.cbValuesFormat->clear(); switch (columnMode) { case AbstractColumn::Numeric: ui.cbValuesFormat->addItem(i18n("Decimal"), QVariant('f')); ui.cbValuesFormat->addItem(i18n("Scientific (e)"), QVariant('e')); ui.cbValuesFormat->addItem(i18n("Scientific (E)"), QVariant('E')); ui.cbValuesFormat->addItem(i18n("Automatic (e)"), QVariant('g')); ui.cbValuesFormat->addItem(i18n("Automatic (E)"), QVariant('G')); break; case AbstractColumn::Integer: break; case AbstractColumn::Text: ui.cbValuesFormat->addItem(i18n("Text"), QVariant()); break; case AbstractColumn::Month: ui.cbValuesFormat->addItem(i18n("Number without Leading Zero"), QVariant("M")); ui.cbValuesFormat->addItem(i18n("Number with Leading Zero"), QVariant("MM")); ui.cbValuesFormat->addItem(i18n("Abbreviated Month Name"), QVariant("MMM")); ui.cbValuesFormat->addItem(i18n("Full Month Name"), QVariant("MMMM")); break; case AbstractColumn::Day: ui.cbValuesFormat->addItem(i18n("Number without Leading Zero"), QVariant("d")); ui.cbValuesFormat->addItem(i18n("Number with Leading Zero"), QVariant("dd")); ui.cbValuesFormat->addItem(i18n("Abbreviated Day Name"), QVariant("ddd")); ui.cbValuesFormat->addItem(i18n("Full Day Name"), QVariant("dddd")); break; case AbstractColumn::DateTime: { for (const auto& s: AbstractColumn::dateFormats()) ui.cbValuesFormat->addItem(s, QVariant(s)); for (const auto& s: AbstractColumn::timeFormats()) ui.cbValuesFormat->addItem(s, QVariant(s)); for (const auto& s1: AbstractColumn::dateFormats()) { for (const auto& s2: AbstractColumn::timeFormats()) ui.cbValuesFormat->addItem(s1 + ' ' + s2, QVariant(s1 + ' ' + s2)); } break; } } if (columnMode == AbstractColumn::Numeric) { ui.lValuesPrecision->show(); ui.sbValuesPrecision->show(); } else { ui.lValuesPrecision->hide(); ui.sbValuesPrecision->hide(); } if (columnMode == AbstractColumn::Text) { ui.lValuesFormatTop->hide(); ui.lValuesFormat->hide(); ui.cbValuesFormat->hide(); } else { ui.lValuesFormatTop->show(); ui.lValuesFormat->show(); ui.cbValuesFormat->show(); } if (columnMode == AbstractColumn::DateTime) { ui.cbValuesFormat->setCurrentItem("yyyy-MM-dd hh:mm:ss.zzz"); ui.cbValuesFormat->setEditable(true); } else { ui.cbValuesFormat->setCurrentIndex(0); ui.cbValuesFormat->setEditable(false); } } /*! shows the formatting properties of the column \c column. Called, when a new column for the values was selected - either by changing the type of the values (none, x, y, etc.) or by selecting a new custom column for the values. */ void XYCurveDock::showValuesColumnFormat(const Column* column) { if (!column) { // no valid column is available // -> hide all the format properties widgets (equivalent to showing the properties of the column mode "Text") this->updateValuesFormatWidgets(AbstractColumn::Text); } else { AbstractColumn::ColumnMode columnMode = column->columnMode(); //update the format widgets for the new column mode this->updateValuesFormatWidgets(columnMode); //show the actual formatting properties switch (columnMode) { case AbstractColumn::Numeric: { - Double2StringFilter* filter = static_cast(column->outputFilter()); + const auto filter = static_cast(column->outputFilter()); ui.cbValuesFormat->setCurrentIndex(ui.cbValuesFormat->findData(filter->numericFormat())); ui.sbValuesPrecision->setValue(filter->numDigits()); break; } case AbstractColumn::Integer: case AbstractColumn::Text: break; case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { - DateTime2StringFilter* filter = static_cast(column->outputFilter()); + const auto filter = static_cast(column->outputFilter()); DEBUG(" column values format = " << filter->format().toStdString()); ui.cbValuesFormat->setCurrentIndex(ui.cbValuesFormat->findData(filter->format())); break; } } } } void XYCurveDock::setModelIndexFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect) { DEBUG("XYCurveDock::setModelIndexFromAspect()"); if (aspect) cb->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(aspect)); else cb->setCurrentModelIndex(QModelIndex()); } //************************************************************* //********** SLOTs for changes triggered in XYCurveDock ******** //************************************************************* void XYCurveDock::retranslateUi() { ui.lLineIncreasingXOnly->setToolTip(i18n("Connect data points only for strictly increasing values of X")); ui.chkLineIncreasingXOnly->setToolTip(i18n("Connect data points only for strictly increasing values of X")); //TODO: // uiGeneralTab.lName->setText(i18n("Name")); // uiGeneralTab.lComment->setText(i18n("Comment")); // uiGeneralTab.chkVisible->setText(i18n("Visible")); // uiGeneralTab.lXColumn->setText(i18n("x-data")); // uiGeneralTab.lYColumn->setText(i18n("y-data")); //TODO updatePenStyles, updateBrushStyles for all comboboxes } // "General"-tab void XYCurveDock::nameChanged() { if (m_initializing) return; m_curve->setName(uiGeneralTab.leName->text()); } void XYCurveDock::commentChanged() { if (m_initializing) return; m_curve->setComment(uiGeneralTab.leComment->text()); } void XYCurveDock::xColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); + auto aspect = static_cast(index.internalPointer()); AbstractColumn* column = nullptr; if (aspect) { column = dynamic_cast(aspect); Q_ASSERT(column); } for (auto* curve : m_curvesList) curve->setXColumn(column); } void XYCurveDock::yColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); + auto aspect = static_cast(index.internalPointer()); AbstractColumn* column = nullptr; if (aspect) { column = dynamic_cast(aspect); Q_ASSERT(column); } for (auto* curve : m_curvesList) curve->setYColumn(column); } void XYCurveDock::visibilityChanged(bool state) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setVisible(state); } // "Line"-tab void XYCurveDock::lineTypeChanged(int index) { - XYCurve::LineType lineType = XYCurve::LineType(index); + const auto lineType = XYCurve::LineType(index); if ( lineType == XYCurve::NoLine) { ui.chkLineSkipGaps->setEnabled(false); ui.cbLineStyle->setEnabled(false); ui.kcbLineColor->setEnabled(false); ui.sbLineWidth->setEnabled(false); ui.sbLineOpacity->setEnabled(false); ui.lLineInterpolationPointsCount->hide(); ui.sbLineInterpolationPointsCount->hide(); } else { ui.chkLineSkipGaps->setEnabled(true); ui.cbLineStyle->setEnabled(true); ui.kcbLineColor->setEnabled(true); ui.sbLineWidth->setEnabled(true); ui.sbLineOpacity->setEnabled(true); if (lineType == XYCurve::SplineCubicNatural || lineType == XYCurve::SplineCubicPeriodic || lineType == XYCurve::SplineAkimaNatural || lineType == XYCurve::SplineAkimaPeriodic) { ui.lLineInterpolationPointsCount->show(); ui.sbLineInterpolationPointsCount->show(); ui.lLineSkipGaps->hide(); ui.chkLineSkipGaps->hide(); } else { ui.lLineInterpolationPointsCount->hide(); ui.sbLineInterpolationPointsCount->hide(); ui.lLineSkipGaps->show(); ui.chkLineSkipGaps->show(); } } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setLineType(lineType); } void XYCurveDock::lineSkipGapsChanged(bool skip) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setLineSkipGaps(skip); } void XYCurveDock::lineIncreasingXOnlyChanged(bool incr) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setLineIncreasingXOnly(incr); } void XYCurveDock::lineInterpolationPointsCountChanged(int count) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setLineInterpolationPointsCount(count); } void XYCurveDock::lineStyleChanged(int index) { if (m_initializing) return; - Qt::PenStyle penStyle=Qt::PenStyle(index); + const auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* curve : m_curvesList) { - pen=curve->linePen(); + pen = curve->linePen(); pen.setStyle(penStyle); curve->setLinePen(pen); } } void XYCurveDock::lineColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->linePen(); + pen = curve->linePen(); pen.setColor(color); curve->setLinePen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbLineStyle, color); m_initializing = false; } void XYCurveDock::lineWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->linePen(); + pen = curve->linePen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setLinePen(pen); } } void XYCurveDock::lineOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setLineOpacity(opacity); } void XYCurveDock::dropLineTypeChanged(int index) { - XYCurve::DropLineType dropLineType = XYCurve::DropLineType(index); + const auto dropLineType = XYCurve::DropLineType(index); if ( dropLineType == XYCurve::NoDropLine) { ui.cbDropLineStyle->setEnabled(false); ui.kcbDropLineColor->setEnabled(false); ui.sbDropLineWidth->setEnabled(false); ui.sbDropLineOpacity->setEnabled(false); } else { ui.cbDropLineStyle->setEnabled(true); ui.kcbDropLineColor->setEnabled(true); ui.sbDropLineWidth->setEnabled(true); ui.sbDropLineOpacity->setEnabled(true); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setDropLineType(dropLineType); } void XYCurveDock::dropLineStyleChanged(int index) { if (m_initializing) return; - Qt::PenStyle penStyle=Qt::PenStyle(index); + auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* curve : m_curvesList) { - pen=curve->dropLinePen(); + pen = curve->dropLinePen(); pen.setStyle(penStyle); curve->setDropLinePen(pen); } } void XYCurveDock::dropLineColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->dropLinePen(); + pen = curve->dropLinePen(); pen.setColor(color); curve->setDropLinePen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbDropLineStyle, color); m_initializing = false; } void XYCurveDock::dropLineWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->dropLinePen(); + pen = curve->dropLinePen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setDropLinePen(pen); } } void XYCurveDock::dropLineOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setDropLineOpacity(opacity); } //"Symbol"-tab void XYCurveDock::symbolsStyleChanged(int index) { - Symbol::Style style = Symbol::Style(index); + const auto style = Symbol::Style(index); if (style == Symbol::NoSymbols) { ui.sbSymbolSize->setEnabled(false); ui.sbSymbolRotation->setEnabled(false); ui.sbSymbolOpacity->setEnabled(false); ui.kcbSymbolFillingColor->setEnabled(false); ui.cbSymbolFillingStyle->setEnabled(false); ui.cbSymbolBorderStyle->setEnabled(false); ui.kcbSymbolBorderColor->setEnabled(false); ui.sbSymbolBorderWidth->setEnabled(false); } else { ui.sbSymbolSize->setEnabled(true); ui.sbSymbolRotation->setEnabled(true); ui.sbSymbolOpacity->setEnabled(true); //enable/disable the symbol filling options in the GUI depending on the currently selected symbol. - if (style!=Symbol::Line && style!=Symbol::Cross) { + if (style != Symbol::Line && style != Symbol::Cross) { ui.cbSymbolFillingStyle->setEnabled(true); bool noBrush = (Qt::BrushStyle(ui.cbSymbolFillingStyle->currentIndex()) == Qt::NoBrush); ui.kcbSymbolFillingColor->setEnabled(!noBrush); } else { ui.kcbSymbolFillingColor->setEnabled(false); ui.cbSymbolFillingStyle->setEnabled(false); } ui.cbSymbolBorderStyle->setEnabled(true); bool noLine = (Qt::PenStyle(ui.cbSymbolBorderStyle->currentIndex()) == Qt::NoPen); ui.kcbSymbolBorderColor->setEnabled(!noLine); ui.sbSymbolBorderWidth->setEnabled(!noLine); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setSymbolsStyle(style); } void XYCurveDock::symbolsSizeChanged(double value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setSymbolsSize( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); } void XYCurveDock::symbolsRotationChanged(int value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setSymbolsRotationAngle(value); } void XYCurveDock::symbolsOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setSymbolsOpacity(opacity); } void XYCurveDock::symbolsFillingStyleChanged(int index) { - Qt::BrushStyle brushStyle = Qt::BrushStyle(index); + const auto brushStyle = Qt::BrushStyle(index); ui.kcbSymbolFillingColor->setEnabled(!(brushStyle == Qt::NoBrush)); if (m_initializing) return; QBrush brush; for (auto* curve : m_curvesList) { - brush=curve->symbolsBrush(); + brush = curve->symbolsBrush(); brush.setStyle(brushStyle); curve->setSymbolsBrush(brush); } } void XYCurveDock::symbolsFillingColorChanged(const QColor& color) { if (m_initializing) return; QBrush brush; for (auto* curve : m_curvesList) { - brush=curve->symbolsBrush(); + brush = curve->symbolsBrush(); brush.setColor(color); curve->setSymbolsBrush(brush); } m_initializing = true; GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, color ); m_initializing = false; } void XYCurveDock::symbolsBorderStyleChanged(int index) { - Qt::PenStyle penStyle=Qt::PenStyle(index); + const auto penStyle = Qt::PenStyle(index); if ( penStyle == Qt::NoPen ) { ui.kcbSymbolBorderColor->setEnabled(false); ui.sbSymbolBorderWidth->setEnabled(false); } else { ui.kcbSymbolBorderColor->setEnabled(true); ui.sbSymbolBorderWidth->setEnabled(true); } if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->symbolsPen(); + pen = curve->symbolsPen(); pen.setStyle(penStyle); curve->setSymbolsPen(pen); } } void XYCurveDock::symbolsBorderColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->symbolsPen(); + pen = curve->symbolsPen(); pen.setColor(color); curve->setSymbolsPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, color); m_initializing = false; } void XYCurveDock::symbolsBorderWidthChanged(double value) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->symbolsPen(); + pen = curve->symbolsPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setSymbolsPen(pen); } } //Values-tab /*! called when the type of the values (none, x, y, (x,y) etc.) was changed. */ void XYCurveDock::valuesTypeChanged(int index) { - XYCurve::ValuesType valuesType = XYCurve::ValuesType(index); + const auto valuesType = XYCurve::ValuesType(index); if (valuesType == XYCurve::NoValues) { //no values are to paint -> deactivate all the pertinent widgets ui.cbValuesPosition->setEnabled(false); ui.lValuesColumn->hide(); cbValuesColumn->hide(); ui.sbValuesDistance->setEnabled(false); ui.sbValuesRotation->setEnabled(false); ui.sbValuesOpacity->setEnabled(false); ui.cbValuesFormat->setEnabled(false); ui.cbValuesFormat->setEnabled(false); ui.sbValuesPrecision->setEnabled(false); ui.leValuesPrefix->setEnabled(false); ui.leValuesSuffix->setEnabled(false); ui.kfrValuesFont->setEnabled(false); ui.kcbValuesColor->setEnabled(false); } else { ui.cbValuesPosition->setEnabled(true); ui.sbValuesDistance->setEnabled(true); ui.sbValuesRotation->setEnabled(true); ui.sbValuesOpacity->setEnabled(true); ui.cbValuesFormat->setEnabled(true); ui.sbValuesPrecision->setEnabled(true); ui.leValuesPrefix->setEnabled(true); ui.leValuesSuffix->setEnabled(true); ui.kfrValuesFont->setEnabled(true); ui.kcbValuesColor->setEnabled(true); const Column* column; if (valuesType == XYCurve::ValuesCustomColumn) { ui.lValuesColumn->show(); cbValuesColumn->show(); column= static_cast(cbValuesColumn->currentModelIndex().internalPointer()); } else { ui.lValuesColumn->hide(); cbValuesColumn->hide(); if (valuesType == XYCurve::ValuesY) column = static_cast(m_curve->yColumn()); else column = static_cast(m_curve->xColumn()); } this->showValuesColumnFormat(column); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setValuesType(valuesType); } /*! called when the custom column for the values was changed. */ void XYCurveDock::valuesColumnChanged(const QModelIndex& index) { if (m_initializing) return; - Column* column= static_cast(index.internalPointer()); + auto column = static_cast(index.internalPointer()); this->showValuesColumnFormat(column); for (auto* curve : m_curvesList) { //TODO save also the format of the currently selected column for the values (precision etc.) curve->setValuesColumn(column); } } void XYCurveDock::valuesPositionChanged(int index) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setValuesPosition(XYCurve::ValuesPosition(index)); } void XYCurveDock::valuesDistanceChanged(double value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setValuesDistance( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); } void XYCurveDock::valuesRotationChanged(int value) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setValuesRotationAngle(value); } void XYCurveDock::valuesOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setValuesOpacity(opacity); } void XYCurveDock::valuesPrefixChanged() { if (m_initializing) return; QString prefix = ui.leValuesPrefix->text(); for (auto* curve : m_curvesList) curve->setValuesPrefix(prefix); } void XYCurveDock::valuesSuffixChanged() { if (m_initializing) return; QString suffix = ui.leValuesSuffix->text(); for (auto* curve : m_curvesList) curve->setValuesSuffix(suffix); } void XYCurveDock::valuesFontChanged(const QFont& font) { if (m_initializing) return; QFont valuesFont = font; valuesFont.setPixelSize( Worksheet::convertToSceneUnits(font.pointSizeF(), Worksheet::Point) ); for (auto* curve : m_curvesList) curve->setValuesFont(valuesFont); } void XYCurveDock::valuesColorChanged(const QColor& color) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setValuesColor(color); } //Filling-tab void XYCurveDock::fillingPositionChanged(int index) { - XYCurve::FillingPosition fillingPosition = XYCurve::FillingPosition(index); + const auto fillingPosition = XYCurve::FillingPosition(index); bool b = (fillingPosition != XYCurve::NoFilling); ui.cbFillingType->setEnabled(b); ui.cbFillingColorStyle->setEnabled(b); ui.cbFillingBrushStyle->setEnabled(b); ui.cbFillingImageStyle->setEnabled(b); ui.kcbFillingFirstColor->setEnabled(b); ui.kcbFillingSecondColor->setEnabled(b); ui.leFillingFileName->setEnabled(b); ui.bFillingOpen->setEnabled(b); ui.sbFillingOpacity->setEnabled(b); if (m_initializing) return; for (auto* curve : m_curvesList) curve->setFillingPosition(fillingPosition); } void XYCurveDock::fillingTypeChanged(int index) { - PlotArea::BackgroundType type = (PlotArea::BackgroundType)index; + const auto type = (PlotArea::BackgroundType)index; if (type == PlotArea::Color) { ui.lFillingColorStyle->show(); ui.cbFillingColorStyle->show(); ui.lFillingImageStyle->hide(); ui.cbFillingImageStyle->hide(); ui.lFillingBrushStyle->hide(); ui.cbFillingBrushStyle->hide(); ui.lFillingFileName->hide(); ui.leFillingFileName->hide(); ui.bFillingOpen->hide(); ui.lFillingFirstColor->show(); ui.kcbFillingFirstColor->show(); - PlotArea::BackgroundColorStyle style = - (PlotArea::BackgroundColorStyle) ui.cbFillingColorStyle->currentIndex(); + auto style = (PlotArea::BackgroundColorStyle) ui.cbFillingColorStyle->currentIndex(); if (style == PlotArea::SingleColor) { ui.lFillingFirstColor->setText(i18n("Color:")); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); } else { ui.lFillingFirstColor->setText(i18n("First color:")); ui.lFillingSecondColor->show(); ui.kcbFillingSecondColor->show(); } } else if (type == PlotArea::Image) { ui.lFillingColorStyle->hide(); ui.cbFillingColorStyle->hide(); ui.lFillingImageStyle->show(); ui.cbFillingImageStyle->show(); ui.lFillingBrushStyle->hide(); ui.cbFillingBrushStyle->hide(); ui.lFillingFileName->show(); ui.leFillingFileName->show(); ui.bFillingOpen->show(); ui.lFillingFirstColor->hide(); ui.kcbFillingFirstColor->hide(); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); } else if (type == PlotArea::Pattern) { ui.lFillingFirstColor->setText(i18n("Color:")); ui.lFillingColorStyle->hide(); ui.cbFillingColorStyle->hide(); ui.lFillingImageStyle->hide(); ui.cbFillingImageStyle->hide(); ui.lFillingBrushStyle->show(); ui.cbFillingBrushStyle->show(); ui.lFillingFileName->hide(); ui.leFillingFileName->hide(); ui.bFillingOpen->hide(); ui.lFillingFirstColor->show(); ui.kcbFillingFirstColor->show(); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setFillingType(type); } void XYCurveDock::fillingColorStyleChanged(int index) { - PlotArea::BackgroundColorStyle style = (PlotArea::BackgroundColorStyle)index; + const auto style = (PlotArea::BackgroundColorStyle)index; if (style == PlotArea::SingleColor) { ui.lFillingFirstColor->setText(i18n("Color:")); ui.lFillingSecondColor->hide(); ui.kcbFillingSecondColor->hide(); } else { ui.lFillingFirstColor->setText(i18n("First color:")); ui.lFillingSecondColor->show(); ui.kcbFillingSecondColor->show(); ui.lFillingBrushStyle->hide(); ui.cbFillingBrushStyle->hide(); } if (m_initializing) return; for (auto* curve : m_curvesList) curve->setFillingColorStyle(style); } void XYCurveDock::fillingImageStyleChanged(int index) { if (m_initializing) return; - PlotArea::BackgroundImageStyle style = (PlotArea::BackgroundImageStyle)index; + auto style = (PlotArea::BackgroundImageStyle)index; for (auto* curve : m_curvesList) curve->setFillingImageStyle(style); } void XYCurveDock::fillingBrushStyleChanged(int index) { if (m_initializing) return; - Qt::BrushStyle style = (Qt::BrushStyle)index; + auto style = (Qt::BrushStyle)index; for (auto* curve : m_curvesList) curve->setFillingBrushStyle(style); } void XYCurveDock::fillingFirstColorChanged(const QColor& c) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setFillingFirstColor(c); m_initializing = true; GuiTools::updateBrushStyles(ui.cbFillingBrushStyle, c); m_initializing = false; } void XYCurveDock::fillingSecondColorChanged(const QColor& c) { if (m_initializing) return; for (auto* curve : m_curvesList) curve->setFillingSecondColor(c); } /*! opens a file dialog and lets the user select the image file. */ void XYCurveDock::selectFile() { KConfigGroup conf(KSharedConfig::openConfig(), "XYCurveDock"); QString dir = conf.readEntry("LastImageDir", ""); QString formats; for (const QByteArray& format : QImageReader::supportedImageFormats()) { QString f = "*." + QString(format.constData()); formats.isEmpty() ? formats+=f : formats+=' '+f; } QString path = QFileDialog::getOpenFileName(this, i18n("Select the image file"), dir, i18n("Images (%1)", formats)); if (path.isEmpty()) return; //cancel was clicked in the file-dialog int pos = path.lastIndexOf(QDir::separator()); if (pos!=-1) { QString newDir = path.left(pos); if (newDir!=dir) conf.writeEntry("LastImageDir", newDir); } ui.leFillingFileName->setText( path ); for (auto* curve : m_curvesList) curve->setFillingFileName(path); } void XYCurveDock::fileNameChanged() { if (m_initializing) return; QString fileName = ui.leFillingFileName->text(); for (auto* curve : m_curvesList) curve->setFillingFileName(fileName); } void XYCurveDock::fillingOpacityChanged(int value) { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setFillingOpacity(opacity); } //"Error bars"-Tab void XYCurveDock::xErrorTypeChanged(int index) const { if (index == 0) { //no error ui.lXErrorDataPlus->setVisible(false); cbXErrorPlusColumn->setVisible(false); ui.lXErrorDataMinus->setVisible(false); cbXErrorMinusColumn->setVisible(false); } else if (index == 1) { //symmetric error ui.lXErrorDataPlus->setVisible(true); cbXErrorPlusColumn->setVisible(true); ui.lXErrorDataMinus->setVisible(false); cbXErrorMinusColumn->setVisible(false); ui.lXErrorDataPlus->setText(i18n("Data, +-")); } else if (index == 2) { //asymmetric error ui.lXErrorDataPlus->setVisible(true); cbXErrorPlusColumn->setVisible(true); ui.lXErrorDataMinus->setVisible(true); cbXErrorMinusColumn->setVisible(true); ui.lXErrorDataPlus->setText(i18n("Data, +")); } bool b = (index!=0 || ui.cbYErrorType->currentIndex()!=0); ui.lErrorFormat->setVisible(b); ui.lErrorBarsType->setVisible(b); ui.cbErrorBarsType->setVisible(b); ui.lErrorBarsStyle->setVisible(b); ui.cbErrorBarsStyle->setVisible(b); ui.lErrorBarsColor->setVisible(b); ui.kcbErrorBarsColor->setVisible(b); ui.lErrorBarsWidth->setVisible(b); ui.sbErrorBarsWidth->setVisible(b); ui.lErrorBarsOpacity->setVisible(b); ui.sbErrorBarsOpacity->setVisible(b); if (m_initializing) return; for (auto* curve : m_curvesList) curve->setXErrorType(XYCurve::ErrorType(index)); } void XYCurveDock::xErrorPlusColumnChanged(const QModelIndex& index) const { Q_UNUSED(index); if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); Q_ASSERT(column); for (auto* curve : m_curvesList) curve->setXErrorPlusColumn(column); } void XYCurveDock::xErrorMinusColumnChanged(const QModelIndex& index) const { Q_UNUSED(index); if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); Q_ASSERT(column); for (auto* curve : m_curvesList) curve->setXErrorMinusColumn(column); } void XYCurveDock::yErrorTypeChanged(int index) const { if (index == 0) { //no error ui.lYErrorDataPlus->setVisible(false); cbYErrorPlusColumn->setVisible(false); ui.lYErrorDataMinus->setVisible(false); cbYErrorMinusColumn->setVisible(false); } else if (index == 1) { //symmetric error ui.lYErrorDataPlus->setVisible(true); cbYErrorPlusColumn->setVisible(true); ui.lYErrorDataMinus->setVisible(false); cbYErrorMinusColumn->setVisible(false); ui.lYErrorDataPlus->setText(i18n("Data, +-")); } else if (index == 2) { //asymmetric error ui.lYErrorDataPlus->setVisible(true); cbYErrorPlusColumn->setVisible(true); ui.lYErrorDataMinus->setVisible(true); cbYErrorMinusColumn->setVisible(true); ui.lYErrorDataPlus->setText(i18n("Data, +")); } bool b = (index!=0 || ui.cbXErrorType->currentIndex()!=0); ui.lErrorFormat->setVisible(b); ui.lErrorBarsType->setVisible(b); ui.cbErrorBarsType->setVisible(b); ui.lErrorBarsStyle->setVisible(b); ui.cbErrorBarsStyle->setVisible(b); ui.lErrorBarsColor->setVisible(b); ui.kcbErrorBarsColor->setVisible(b); ui.lErrorBarsWidth->setVisible(b); ui.sbErrorBarsWidth->setVisible(b); ui.lErrorBarsOpacity->setVisible(b); ui.sbErrorBarsOpacity->setVisible(b); if (m_initializing) return; for (auto* curve : m_curvesList) curve->setYErrorType(XYCurve::ErrorType(index)); } void XYCurveDock::yErrorPlusColumnChanged(const QModelIndex& index) const { Q_UNUSED(index); if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); Q_ASSERT(column); for (auto* curve : m_curvesList) curve->setYErrorPlusColumn(column); } void XYCurveDock::yErrorMinusColumnChanged(const QModelIndex& index) const { Q_UNUSED(index); if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); Q_ASSERT(column); for (auto* curve : m_curvesList) curve->setYErrorMinusColumn(column); } void XYCurveDock::errorBarsTypeChanged(int index) const { - XYCurve::ErrorBarsType type = XYCurve::ErrorBarsType(index); + auto type = XYCurve::ErrorBarsType(index); bool b = (type == XYCurve::ErrorBarsWithEnds); ui.lErrorBarsCapSize->setVisible(b); ui.sbErrorBarsCapSize->setVisible(b); if (m_initializing) return; for (auto* curve : m_curvesList) curve->setErrorBarsType(type); } void XYCurveDock::errorBarsCapSizeChanged(double value) const { if (m_initializing) return; float size = Worksheet::convertToSceneUnits(value, Worksheet::Point); for (auto* curve : m_curvesList) curve->setErrorBarsCapSize(size); } void XYCurveDock::errorBarsStyleChanged(int index) const { if (m_initializing) return; - Qt::PenStyle penStyle=Qt::PenStyle(index); + auto penStyle = Qt::PenStyle(index); QPen pen; for (auto* curve : m_curvesList) { - pen=curve->errorBarsPen(); + pen = curve->errorBarsPen(); pen.setStyle(penStyle); curve->setErrorBarsPen(pen); } } void XYCurveDock::errorBarsColorChanged(const QColor& color) { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->errorBarsPen(); + pen = curve->errorBarsPen(); pen.setColor(color); curve->setErrorBarsPen(pen); } m_initializing = true; GuiTools::updatePenStyles(ui.cbErrorBarsStyle, color); m_initializing = false; } void XYCurveDock::errorBarsWidthChanged(double value) const { if (m_initializing) return; QPen pen; for (auto* curve : m_curvesList) { - pen=curve->errorBarsPen(); + pen = curve->errorBarsPen(); pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Point) ); curve->setErrorBarsPen(pen); } } void XYCurveDock::errorBarsOpacityChanged(int value) const { if (m_initializing) return; qreal opacity = (float)value/100.; for (auto* curve : m_curvesList) curve->setErrorBarsOpacity(opacity); } //************************************************************* //*********** SLOTs for changes triggered in XYCurve ********** //************************************************************* //General-Tab void XYCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != uiGeneralTab.leName->text()) uiGeneralTab.leName->setText(aspect->name()); else if (aspect->comment() != uiGeneralTab.leComment->text()) uiGeneralTab.leComment->setText(aspect->comment()); m_initializing = false; } void XYCurveDock::curveXColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbXColumn, column); m_initializing = false; } void XYCurveDock::curveYColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbYColumn, column); m_initializing = false; } void XYCurveDock::curveVisibilityChanged(bool on) { m_initializing = true; uiGeneralTab.chkVisible->setChecked(on); m_initializing = false; } //Line-Tab void XYCurveDock::curveLineTypeChanged(XYCurve::LineType type) { m_initializing = true; ui.cbLineType->setCurrentIndex( (int) type); m_initializing = false; } void XYCurveDock::curveLineSkipGapsChanged(bool skip) { m_initializing = true; ui.chkLineSkipGaps->setChecked(skip); m_initializing = false; } void XYCurveDock::curveLineIncreasingXOnlyChanged(bool incr) { m_initializing = true; ui.chkLineIncreasingXOnly->setChecked(incr); m_initializing = false; } void XYCurveDock::curveLineInterpolationPointsCountChanged(int count) { m_initializing = true; ui.sbLineInterpolationPointsCount->setValue(count); m_initializing = false; } void XYCurveDock::curveLinePenChanged(const QPen& pen) { m_initializing = true; ui.cbLineStyle->setCurrentIndex( (int)pen.style()); ui.kcbLineColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbLineStyle, pen.color()); ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits( pen.widthF(), Worksheet::Point) ); m_initializing = false; } void XYCurveDock::curveLineOpacityChanged(qreal opacity) { m_initializing = true; ui.sbLineOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } void XYCurveDock::curveDropLineTypeChanged(XYCurve::DropLineType type) { m_initializing = true; ui.cbDropLineType->setCurrentIndex( (int)type ); m_initializing = false; } void XYCurveDock::curveDropLinePenChanged(const QPen& pen) { m_initializing = true; ui.cbDropLineStyle->setCurrentIndex( (int) pen.style()); ui.kcbDropLineColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbDropLineStyle, pen.color()); ui.sbDropLineWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(),Worksheet::Point) ); m_initializing = false; } void XYCurveDock::curveDropLineOpacityChanged(qreal opacity) { m_initializing = true; ui.sbDropLineOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } //Symbol-Tab void XYCurveDock::curveSymbolsStyleChanged(Symbol::Style style) { m_initializing = true; ui.cbSymbolStyle->setCurrentIndex((int)style); m_initializing = false; } void XYCurveDock::curveSymbolsSizeChanged(qreal size) { m_initializing = true; ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(size, Worksheet::Point) ); m_initializing = false; } void XYCurveDock::curveSymbolsRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbSymbolRotation->setValue(angle); m_initializing = false; } void XYCurveDock::curveSymbolsOpacityChanged(qreal opacity) { m_initializing = true; ui.sbSymbolOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } void XYCurveDock::curveSymbolsBrushChanged(const QBrush& brush) { m_initializing = true; ui.cbSymbolFillingStyle->setCurrentIndex((int) brush.style()); ui.kcbSymbolFillingColor->setColor(brush.color()); GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, brush.color()); m_initializing = false; } void XYCurveDock::curveSymbolsPenChanged(const QPen& pen) { m_initializing = true; ui.cbSymbolBorderStyle->setCurrentIndex( (int) pen.style()); ui.kcbSymbolBorderColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, pen.color()); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Point)); m_initializing = false; } //Values-Tab void XYCurveDock::curveValuesTypeChanged(XYCurve::ValuesType type) { m_initializing = true; ui.cbValuesType->setCurrentIndex((int) type); m_initializing = false; } void XYCurveDock::curveValuesColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbValuesColumn, column); m_initializing = false; } void XYCurveDock::curveValuesPositionChanged(XYCurve::ValuesPosition position) { m_initializing = true; ui.cbValuesPosition->setCurrentIndex((int) position); m_initializing = false; } void XYCurveDock::curveValuesDistanceChanged(qreal distance) { m_initializing = true; ui.sbValuesDistance->setValue( Worksheet::convertFromSceneUnits(distance, Worksheet::Point) ); m_initializing = false; } void XYCurveDock::curveValuesRotationAngleChanged(qreal angle) { m_initializing = true; ui.sbValuesRotation->setValue(angle); m_initializing = false; } void XYCurveDock::curveValuesOpacityChanged(qreal opacity) { m_initializing = true; ui.sbValuesOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } void XYCurveDock::curveValuesPrefixChanged(const QString& prefix) { m_initializing = true; ui.leValuesPrefix->setText(prefix); m_initializing = false; } void XYCurveDock::curveValuesSuffixChanged(const QString& suffix) { m_initializing = true; ui.leValuesSuffix->setText(suffix); m_initializing = false; } void XYCurveDock::curveValuesFontChanged(QFont font) { m_initializing = true; font.setPointSizeF( round(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Point)) ); ui.kfrValuesFont->setFont(font); m_initializing = false; } void XYCurveDock::curveValuesColorChanged(QColor color) { m_initializing = true; ui.kcbValuesColor->setColor(color); m_initializing = false; } //Filling void XYCurveDock::curveFillingPositionChanged(XYCurve::FillingPosition position) { m_initializing = true; ui.cbFillingPosition->setCurrentIndex((int)position); m_initializing = false; } void XYCurveDock::curveFillingTypeChanged(PlotArea::BackgroundType type) { m_initializing = true; ui.cbFillingType->setCurrentIndex(type); m_initializing = false; } void XYCurveDock::curveFillingColorStyleChanged(PlotArea::BackgroundColorStyle style) { m_initializing = true; ui.cbFillingColorStyle->setCurrentIndex(style); m_initializing = false; } void XYCurveDock::curveFillingImageStyleChanged(PlotArea::BackgroundImageStyle style) { m_initializing = true; ui.cbFillingImageStyle->setCurrentIndex(style); m_initializing = false; } void XYCurveDock::curveFillingBrushStyleChanged(Qt::BrushStyle style) { m_initializing = true; ui.cbFillingBrushStyle->setCurrentIndex(style); m_initializing = false; } void XYCurveDock::curveFillingFirstColorChanged(QColor& color) { m_initializing = true; ui.kcbFillingFirstColor->setColor(color); GuiTools::updateBrushStyles(ui.cbFillingBrushStyle, color); m_initializing = false; } void XYCurveDock::curveFillingSecondColorChanged(QColor& color) { m_initializing = true; ui.kcbFillingSecondColor->setColor(color); m_initializing = false; } void XYCurveDock::curveFillingFileNameChanged(QString& filename) { m_initializing = true; ui.leFillingFileName->setText(filename); m_initializing = false; } void XYCurveDock::curveFillingOpacityChanged(float opacity) { m_initializing = true; ui.sbFillingOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } //"Error bars"-Tab void XYCurveDock::curveXErrorTypeChanged(XYCurve::ErrorType type) { m_initializing = true; ui.cbXErrorType->setCurrentIndex((int) type); m_initializing = false; } void XYCurveDock::curveXErrorPlusColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbXErrorPlusColumn, column); m_initializing = false; } void XYCurveDock::curveXErrorMinusColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbXErrorMinusColumn, column); m_initializing = false; } void XYCurveDock::curveYErrorTypeChanged(XYCurve::ErrorType type) { m_initializing = true; ui.cbYErrorType->setCurrentIndex((int) type); m_initializing = false; } void XYCurveDock::curveYErrorPlusColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbYErrorPlusColumn, column); m_initializing = false; } void XYCurveDock::curveYErrorMinusColumnChanged(const AbstractColumn* column) { m_initializing = true; this->setModelIndexFromAspect(cbYErrorMinusColumn, column); m_initializing = false; } void XYCurveDock::curveErrorBarsCapSizeChanged(qreal size) { m_initializing = true; ui.sbErrorBarsCapSize->setValue( Worksheet::convertFromSceneUnits(size, Worksheet::Point) ); m_initializing = false; } void XYCurveDock::curveErrorBarsTypeChanged(XYCurve::ErrorBarsType type) { m_initializing = true; ui.cbErrorBarsType->setCurrentIndex( (int) type); m_initializing = false; } void XYCurveDock::curveErrorBarsPenChanged(const QPen& pen) { m_initializing = true; ui.cbErrorBarsStyle->setCurrentIndex( (int) pen.style()); ui.kcbErrorBarsColor->setColor( pen.color()); GuiTools::updatePenStyles(ui.cbErrorBarsStyle, pen.color()); ui.sbErrorBarsWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(),Worksheet::Point) ); m_initializing = false; } void XYCurveDock::curveErrorBarsOpacityChanged(qreal opacity) { m_initializing = true; ui.sbErrorBarsOpacity->setValue( round(opacity*100.0) ); m_initializing = false; } //************************************************************* //************************* Settings ************************** //************************************************************* void XYCurveDock::load() { //General //This data is read in XYCurveDock::setCurves(). //Line ui.cbLineType->setCurrentIndex( (int) m_curve->lineType() ); ui.chkLineSkipGaps->setChecked( m_curve->lineSkipGaps() ); ui.sbLineInterpolationPointsCount->setValue( m_curve->lineInterpolationPointsCount() ); ui.cbLineStyle->setCurrentIndex( (int) m_curve->linePen().style() ); ui.kcbLineColor->setColor( m_curve->linePen().color() ); ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits(m_curve->linePen().widthF(), Worksheet::Point) ); ui.sbLineOpacity->setValue( round(m_curve->lineOpacity()*100.0) ); //Drop lines ui.cbDropLineType->setCurrentIndex( (int) m_curve->dropLineType() ); ui.cbDropLineStyle->setCurrentIndex( (int) m_curve->dropLinePen().style() ); ui.kcbDropLineColor->setColor( m_curve->dropLinePen().color() ); ui.sbDropLineWidth->setValue( Worksheet::convertFromSceneUnits(m_curve->dropLinePen().widthF(),Worksheet::Point) ); ui.sbDropLineOpacity->setValue( round(m_curve->dropLineOpacity()*100.0) ); //Symbols ui.cbSymbolStyle->setCurrentIndex( (int)m_curve->symbolsStyle() ); ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(m_curve->symbolsSize(), Worksheet::Point) ); ui.sbSymbolRotation->setValue( m_curve->symbolsRotationAngle() ); ui.sbSymbolOpacity->setValue( round(m_curve->symbolsOpacity()*100.0) ); ui.cbSymbolFillingStyle->setCurrentIndex( (int) m_curve->symbolsBrush().style() ); ui.kcbSymbolFillingColor->setColor( m_curve->symbolsBrush().color() ); ui.cbSymbolBorderStyle->setCurrentIndex( (int) m_curve->symbolsPen().style() ); ui.kcbSymbolBorderColor->setColor( m_curve->symbolsPen().color() ); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_curve->symbolsPen().widthF(), Worksheet::Point) ); //Values ui.cbValuesType->setCurrentIndex( (int) m_curve->valuesType() ); ui.cbValuesPosition->setCurrentIndex( (int) m_curve->valuesPosition() ); ui.sbValuesDistance->setValue( Worksheet::convertFromSceneUnits(m_curve->valuesDistance(), Worksheet::Point) ); ui.sbValuesRotation->setValue( m_curve->valuesRotationAngle() ); ui.sbValuesOpacity->setValue( round(m_curve->valuesOpacity()*100.0) ); ui.leValuesPrefix->setText( m_curve->valuesPrefix() ); ui.leValuesSuffix->setText( m_curve->valuesSuffix() ); QFont valuesFont = m_curve->valuesFont(); valuesFont.setPointSizeF( round(Worksheet::convertFromSceneUnits(valuesFont.pixelSize(), Worksheet::Point)) ); ui.kfrValuesFont->setFont(valuesFont); ui.kcbValuesColor->setColor( m_curve->valuesColor() ); //Filling ui.cbFillingPosition->setCurrentIndex( (int) m_curve->fillingPosition() ); ui.cbFillingType->setCurrentIndex( (int)m_curve->fillingType() ); ui.cbFillingColorStyle->setCurrentIndex( (int) m_curve->fillingColorStyle() ); ui.cbFillingImageStyle->setCurrentIndex( (int) m_curve->fillingImageStyle() ); ui.cbFillingBrushStyle->setCurrentIndex( (int) m_curve->fillingBrushStyle() ); ui.leFillingFileName->setText( m_curve->fillingFileName() ); ui.kcbFillingFirstColor->setColor( m_curve->fillingFirstColor() ); ui.kcbFillingSecondColor->setColor( m_curve->fillingSecondColor() ); ui.sbFillingOpacity->setValue( round(m_curve->fillingOpacity()*100.0) ); //Error bars ui.cbXErrorType->setCurrentIndex( (int) m_curve->xErrorType() ); ui.cbYErrorType->setCurrentIndex( (int) m_curve->yErrorType() ); ui.cbErrorBarsType->setCurrentIndex( (int) m_curve->errorBarsType() ); ui.sbErrorBarsCapSize->setValue( Worksheet::convertFromSceneUnits(m_curve->errorBarsCapSize(), Worksheet::Point) ); ui.cbErrorBarsStyle->setCurrentIndex( (int) m_curve->errorBarsPen().style() ); ui.kcbErrorBarsColor->setColor( m_curve->errorBarsPen().color() ); ui.sbErrorBarsWidth->setValue( Worksheet::convertFromSceneUnits(m_curve->errorBarsPen().widthF(),Worksheet::Point) ); ui.sbErrorBarsOpacity->setValue( round(m_curve->errorBarsOpacity()*100.0) ); m_initializing=true; GuiTools::updatePenStyles(ui.cbLineStyle, ui.kcbLineColor->color()); GuiTools::updatePenStyles(ui.cbDropLineStyle, ui.kcbDropLineColor->color()); GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, ui.kcbSymbolFillingColor->color()); GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, ui.kcbSymbolBorderColor->color()); GuiTools::updatePenStyles(ui.cbErrorBarsStyle, ui.kcbErrorBarsColor->color()); m_initializing=false; } void XYCurveDock::loadConfigFromTemplate(KConfig& config) { //extract the name of the template from the file name QString name; int index = config.name().lastIndexOf(QDir::separator()); if (index!=-1) name = config.name().right(config.name().size() - index - 1); else name = config.name(); int size = m_curvesList.size(); if (size>1) m_curve->beginMacro(i18n("%1 xy-curves: template \"%2\" loaded", size, name)); else m_curve->beginMacro(i18n("%1: template \"%2\" loaded", m_curve->name(), name)); this->loadConfig(config); m_curve->endMacro(); } void XYCurveDock::loadConfig(KConfig& config) { KConfigGroup group = config.group( "XYCurve" ); //General //we don't load/save the settings in the general-tab, since they are not style related. //It doesn't make sense to load/save them in the template. //This data is read in XYCurveDock::setCurves(). //Line ui.cbLineType->setCurrentIndex( group.readEntry("LineType", (int) m_curve->lineType()) ); ui.chkLineSkipGaps->setChecked( group.readEntry("LineSkipGaps", m_curve->lineSkipGaps()) ); ui.sbLineInterpolationPointsCount->setValue( group.readEntry("LineInterpolationPointsCount", m_curve->lineInterpolationPointsCount()) ); ui.cbLineStyle->setCurrentIndex( group.readEntry("LineStyle", (int) m_curve->linePen().style()) ); ui.kcbLineColor->setColor( group.readEntry("LineColor", m_curve->linePen().color()) ); ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LineWidth", m_curve->linePen().widthF()), Worksheet::Point) ); ui.sbLineOpacity->setValue( round(group.readEntry("LineOpacity", m_curve->lineOpacity())*100.0) ); //Drop lines ui.cbDropLineType->setCurrentIndex( group.readEntry("DropLineType", (int) m_curve->dropLineType()) ); ui.cbDropLineStyle->setCurrentIndex( group.readEntry("DropLineStyle", (int) m_curve->dropLinePen().style()) ); ui.kcbDropLineColor->setColor( group.readEntry("DropLineColor", m_curve->dropLinePen().color()) ); ui.sbDropLineWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("DropLineWidth", m_curve->dropLinePen().widthF()),Worksheet::Point) ); ui.sbDropLineOpacity->setValue( round(group.readEntry("DropLineOpacity", m_curve->dropLineOpacity())*100.0) ); //Symbols ui.cbSymbolStyle->setCurrentIndex( group.readEntry("SymbolStyle", (int)m_curve->symbolsStyle()) ); ui.sbSymbolSize->setValue( Worksheet::convertFromSceneUnits(group.readEntry("SymbolSize", m_curve->symbolsSize()), Worksheet::Point) ); ui.sbSymbolRotation->setValue( group.readEntry("SymbolRotation", m_curve->symbolsRotationAngle()) ); ui.sbSymbolOpacity->setValue( round(group.readEntry("SymbolOpacity", m_curve->symbolsOpacity())*100.0) ); ui.cbSymbolFillingStyle->setCurrentIndex( group.readEntry("SymbolFillingStyle", (int) m_curve->symbolsBrush().style()) ); ui.kcbSymbolFillingColor->setColor( group.readEntry("SymbolFillingColor", m_curve->symbolsBrush().color()) ); ui.cbSymbolBorderStyle->setCurrentIndex( group.readEntry("SymbolBorderStyle", (int) m_curve->symbolsPen().style()) ); ui.kcbSymbolBorderColor->setColor( group.readEntry("SymbolBorderColor", m_curve->symbolsPen().color()) ); ui.sbSymbolBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("SymbolBorderWidth",m_curve->symbolsPen().widthF()), Worksheet::Point) ); //Values ui.cbValuesType->setCurrentIndex( group.readEntry("ValuesType", (int) m_curve->valuesType()) ); ui.cbValuesPosition->setCurrentIndex( group.readEntry("ValuesPosition", (int) m_curve->valuesPosition()) ); ui.sbValuesDistance->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ValuesDistance", m_curve->valuesDistance()), Worksheet::Point) ); ui.sbValuesRotation->setValue( group.readEntry("ValuesRotation", m_curve->valuesRotationAngle()) ); ui.sbValuesOpacity->setValue( round(group.readEntry("ValuesOpacity",m_curve->valuesOpacity())*100.0) ); ui.leValuesPrefix->setText( group.readEntry("ValuesPrefix", m_curve->valuesPrefix()) ); ui.leValuesSuffix->setText( group.readEntry("ValuesSuffix", m_curve->valuesSuffix()) ); QFont valuesFont = m_curve->valuesFont(); valuesFont.setPointSizeF( round(Worksheet::convertFromSceneUnits(valuesFont.pixelSize(), Worksheet::Point)) ); ui.kfrValuesFont->setFont( group.readEntry("ValuesFont", valuesFont) ); ui.kcbValuesColor->setColor( group.readEntry("ValuesColor", m_curve->valuesColor()) ); //Filling ui.cbFillingPosition->setCurrentIndex( group.readEntry("FillingPosition", (int) m_curve->fillingPosition()) ); ui.cbFillingType->setCurrentIndex( group.readEntry("FillingType", (int) m_curve->fillingType()) ); ui.cbFillingColorStyle->setCurrentIndex( group.readEntry("FillingColorStyle", (int) m_curve->fillingColorStyle()) ); ui.cbFillingImageStyle->setCurrentIndex( group.readEntry("FillingImageStyle", (int) m_curve->fillingImageStyle()) ); ui.cbFillingBrushStyle->setCurrentIndex( group.readEntry("FillingBrushStyle", (int) m_curve->fillingBrushStyle()) ); ui.leFillingFileName->setText( group.readEntry("FillingFileName", m_curve->fillingFileName()) ); ui.kcbFillingFirstColor->setColor( group.readEntry("FillingFirstColor", m_curve->fillingFirstColor()) ); ui.kcbFillingSecondColor->setColor( group.readEntry("FillingSecondColor", m_curve->fillingSecondColor()) ); ui.sbFillingOpacity->setValue( round(group.readEntry("FillingOpacity", m_curve->fillingOpacity())*100.0) ); //Error bars ui.cbXErrorType->setCurrentIndex( group.readEntry("XErrorType", (int) m_curve->xErrorType()) ); ui.cbYErrorType->setCurrentIndex( group.readEntry("YErrorType", (int) m_curve->yErrorType()) ); ui.cbErrorBarsType->setCurrentIndex( group.readEntry("ErrorBarsType", (int) m_curve->errorBarsType()) ); ui.sbErrorBarsCapSize->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ErrorBarsCapSize", m_curve->errorBarsCapSize()), Worksheet::Point) ); ui.cbErrorBarsStyle->setCurrentIndex( group.readEntry("ErrorBarsStyle", (int) m_curve->errorBarsPen().style()) ); ui.kcbErrorBarsColor->setColor( group.readEntry("ErrorBarsColor", m_curve->errorBarsPen().color()) ); ui.sbErrorBarsWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ErrorBarsWidth", m_curve->errorBarsPen().widthF()),Worksheet::Point) ); ui.sbErrorBarsOpacity->setValue( round(group.readEntry("ErrorBarsOpacity", m_curve->errorBarsOpacity())*100.0) ); m_initializing=true; GuiTools::updatePenStyles(ui.cbLineStyle, ui.kcbLineColor->color()); GuiTools::updatePenStyles(ui.cbDropLineStyle, ui.kcbDropLineColor->color()); GuiTools::updateBrushStyles(ui.cbSymbolFillingStyle, ui.kcbSymbolFillingColor->color()); GuiTools::updatePenStyles(ui.cbSymbolBorderStyle, ui.kcbSymbolBorderColor->color()); GuiTools::updatePenStyles(ui.cbErrorBarsStyle, ui.kcbErrorBarsColor->color()); GuiTools::updateBrushStyles(ui.cbFillingBrushStyle, ui.kcbFillingFirstColor->color()); m_initializing=false; } void XYCurveDock::saveConfigAsTemplate(KConfig& config) { KConfigGroup group = config.group( "XYCurve" ); //General //we don't load/save the settings in the general-tab, since they are not style related. //It doesn't make sense to load/save them in the template. group.writeEntry("LineType", ui.cbLineType->currentIndex()); group.writeEntry("LineSkipGaps", ui.chkLineSkipGaps->isChecked()); group.writeEntry("LineInterpolationPointsCount", ui.sbLineInterpolationPointsCount->value() ); group.writeEntry("LineStyle", ui.cbLineStyle->currentIndex()); group.writeEntry("LineColor", ui.kcbLineColor->color()); group.writeEntry("LineWidth", Worksheet::convertToSceneUnits(ui.sbLineWidth->value(),Worksheet::Point) ); group.writeEntry("LineOpacity", ui.sbLineOpacity->value()/100 ); //Drop Line group.writeEntry("DropLineType", ui.cbDropLineType->currentIndex()); group.writeEntry("DropLineStyle", ui.cbDropLineStyle->currentIndex()); group.writeEntry("DropLineColor", ui.kcbDropLineColor->color()); group.writeEntry("DropLineWidth", Worksheet::convertToSceneUnits(ui.sbDropLineWidth->value(),Worksheet::Point) ); group.writeEntry("DropLineOpacity", ui.sbDropLineOpacity->value()/100 ); //Symbol (TODO: character) group.writeEntry("SymbolStyle", ui.cbSymbolStyle->currentIndex()); group.writeEntry("SymbolSize", Worksheet::convertToSceneUnits(ui.sbSymbolSize->value(),Worksheet::Point)); group.writeEntry("SymbolRotation", ui.sbSymbolRotation->value()); group.writeEntry("SymbolOpacity", ui.sbSymbolOpacity->value()/100 ); group.writeEntry("SymbolFillingStyle", ui.cbSymbolFillingStyle->currentIndex()); group.writeEntry("SymbolFillingColor", ui.kcbSymbolFillingColor->color()); group.writeEntry("SymbolBorderStyle", ui.cbSymbolBorderStyle->currentIndex()); group.writeEntry("SymbolBorderColor", ui.kcbSymbolBorderColor->color()); group.writeEntry("SymbolBorderWidth", Worksheet::convertToSceneUnits(ui.sbSymbolBorderWidth->value(),Worksheet::Point)); //Values group.writeEntry("ValuesType", ui.cbValuesType->currentIndex()); group.writeEntry("ValuesPosition", ui.cbValuesPosition->currentIndex()); group.writeEntry("ValuesDistance", Worksheet::convertToSceneUnits(ui.sbValuesDistance->value(),Worksheet::Point)); group.writeEntry("ValuesRotation", ui.sbValuesRotation->value()); group.writeEntry("ValuesOpacity", ui.sbValuesOpacity->value()/100); group.writeEntry("ValuesPrefix", ui.leValuesPrefix->text()); group.writeEntry("ValuesSuffix", ui.leValuesSuffix->text()); group.writeEntry("ValuesFont", ui.kfrValuesFont->font()); group.writeEntry("ValuesColor", ui.kcbValuesColor->color()); //Filling group.writeEntry("FillingPosition", ui.cbFillingPosition->currentIndex()); group.writeEntry("FillingType", ui.cbFillingType->currentIndex()); group.writeEntry("FillingColorStyle", ui.cbFillingColorStyle->currentIndex()); group.writeEntry("FillingImageStyle", ui.cbFillingImageStyle->currentIndex()); group.writeEntry("FillingBrushStyle", ui.cbFillingBrushStyle->currentIndex()); group.writeEntry("FillingFileName", ui.leFillingFileName->text()); group.writeEntry("FillingFirstColor", ui.kcbFillingFirstColor->color()); group.writeEntry("FillingSecondColor", ui.kcbFillingSecondColor->color()); group.writeEntry("FillingOpacity", ui.sbFillingOpacity->value()/100.0); //Error bars group.writeEntry("XErrorType", ui.cbXErrorType->currentIndex()); group.writeEntry("YErrorType", ui.cbYErrorType->currentIndex()); group.writeEntry("ErrorBarsType", ui.cbErrorBarsType->currentIndex()); group.writeEntry("ErrorBarsCapSize", Worksheet::convertToSceneUnits(ui.sbErrorBarsCapSize->value(),Worksheet::Point) ); group.writeEntry("ErrorBarsStyle", ui.cbErrorBarsStyle->currentIndex()); group.writeEntry("ErrorBarsColor", ui.kcbErrorBarsColor->color()); group.writeEntry("ErrorBarsWidth", Worksheet::convertToSceneUnits(ui.sbErrorBarsWidth->value(),Worksheet::Point) ); group.writeEntry("ErrorBarsOpacity", ui.sbErrorBarsOpacity->value()/100 ); config.sync(); } diff --git a/src/kdefrontend/dockwidgets/XYDataReductionCurveDock.cpp b/src/kdefrontend/dockwidgets/XYDataReductionCurveDock.cpp index af45a6204..f8bf1c613 100644 --- a/src/kdefrontend/dockwidgets/XYDataReductionCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYDataReductionCurveDock.cpp @@ -1,698 +1,698 @@ /*************************************************************************** File : XYDataReductionCurveDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn) Copyright : (C) 2017 Alexander Semke (alexander.semke@web.de) Description : widget for editing properties of data reduction curves ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "XYDataReductionCurveDock.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/worksheet/plots/cartesian/XYDataReductionCurve.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include #include #include #include #include /*! \class XYDataReductionCurveDock \brief Provides a widget for editing the properties of the XYDataReductionCurves (2D-curves defined by an data reduction) currently selected in the project explorer. If more then one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ XYDataReductionCurveDock::XYDataReductionCurveDock(QWidget* parent, QStatusBar* sb) : XYCurveDock(parent), statusBar(sb), cbDataSourceCurve(nullptr), cbXDataColumn(nullptr), cbYDataColumn(nullptr), m_dataReductionCurve(nullptr) { //hide the line connection type ui.cbLineType->setDisabled(true); //remove the tab "Error bars" ui.tabWidget->removeTab(5); } /*! * // Tab "General" */ void XYDataReductionCurveDock::setupGeneral() { QWidget* generalTab = new QWidget(ui.tabGeneral); uiGeneralTab.setupUi(generalTab); - QGridLayout* gridLayout = dynamic_cast(generalTab->layout()); + auto gridLayout = dynamic_cast(generalTab->layout()); if (gridLayout) { gridLayout->setContentsMargins(2,2,2,2); gridLayout->setHorizontalSpacing(2); gridLayout->setVerticalSpacing(2); } uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet")); uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve")); cbDataSourceCurve = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 3); cbXDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 3); cbYDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbYDataColumn, 7, 2, 1, 3); for (int i=0; i < NSL_GEOM_LINESIM_TYPE_COUNT; ++i) uiGeneralTab.cbType->addItem(i18n(nsl_geom_linesim_type_name[i])); uiGeneralTab.cbType->setItemData(nsl_geom_linesim_type_visvalingam_whyatt, i18n("This method is much slower than any other"), Qt::ToolTipRole); uiGeneralTab.sbMin->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.sbMax->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.sbTolerance->setRange(0.0, std::numeric_limits::max()); uiGeneralTab.sbTolerance2->setRange(0.0, std::numeric_limits::max()); uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build")); - QHBoxLayout* layout = new QHBoxLayout(ui.tabGeneral); + auto layout = new QHBoxLayout(ui.tabGeneral); layout->setMargin(0); layout->addWidget(generalTab); //Slots connect( uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYDataReductionCurveDock::nameChanged ); connect( uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYDataReductionCurveDock::commentChanged ); connect( uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( uiGeneralTab.cbDataSourceType, SIGNAL(currentIndexChanged(int)), this, SLOT(dataSourceTypeChanged(int)) ); connect( uiGeneralTab.cbAutoRange, SIGNAL(clicked(bool)), this, SLOT(autoRangeChanged()) ); connect( uiGeneralTab.sbMin, SIGNAL(valueChanged(double)), this, SLOT(xRangeMinChanged()) ); connect( uiGeneralTab.sbMax, SIGNAL(valueChanged(double)), this, SLOT(xRangeMaxChanged()) ); connect( uiGeneralTab.cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged()) ); connect( uiGeneralTab.chkAuto, SIGNAL(clicked(bool)), this, SLOT(autoToleranceChanged()) ); connect( uiGeneralTab.sbTolerance, SIGNAL(valueChanged(double)), this, SLOT(toleranceChanged()) ); connect( uiGeneralTab.chkAuto2, SIGNAL(clicked(bool)), this, SLOT(autoTolerance2Changed()) ); connect( uiGeneralTab.sbTolerance2, SIGNAL(valueChanged(double)), this, SLOT(tolerance2Changed()) ); connect( uiGeneralTab.pbRecalculate, SIGNAL(clicked()), this, SLOT(recalculateClicked()) ); connect( cbDataSourceCurve, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(dataSourceCurveChanged(QModelIndex)) ); connect( cbXDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xDataColumnChanged(QModelIndex)) ); connect( cbYDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yDataColumnChanged(QModelIndex)) ); } void XYDataReductionCurveDock::initGeneralTab() { //if there are more then one curve in the list, disable the tab "general" if (m_curvesList.size() == 1) { uiGeneralTab.lName->setEnabled(true); uiGeneralTab.leName->setEnabled(true); uiGeneralTab.lComment->setEnabled(true); uiGeneralTab.leComment->setEnabled(true); uiGeneralTab.leName->setText(m_curve->name()); uiGeneralTab.leComment->setText(m_curve->comment()); } else { uiGeneralTab.lName->setEnabled(false); uiGeneralTab.leName->setEnabled(false); uiGeneralTab.lComment->setEnabled(false); uiGeneralTab.leComment->setEnabled(false); uiGeneralTab.leName->setText(""); uiGeneralTab.leComment->setText(""); } //show the properties of the first curve m_dataReductionCurve = dynamic_cast(m_curve); uiGeneralTab.cbDataSourceType->setCurrentIndex(m_dataReductionCurve->dataSourceType()); this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex()); XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_dataReductionCurve->dataSourceCurve()); XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_dataReductionCurve->xDataColumn()); XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_dataReductionCurve->yDataColumn()); uiGeneralTab.cbAutoRange->setChecked(m_dataReductionData.autoRange); uiGeneralTab.sbMin->setValue(m_dataReductionData.xRange.first()); uiGeneralTab.sbMax->setValue(m_dataReductionData.xRange.last()); this->autoRangeChanged(); // update list of selectable types xDataColumnChanged(cbXDataColumn->currentModelIndex()); uiGeneralTab.cbType->setCurrentIndex(m_dataReductionData.type); this->typeChanged(); uiGeneralTab.chkAuto->setChecked(m_dataReductionData.autoTolerance); this->autoToleranceChanged(); uiGeneralTab.sbTolerance->setValue(m_dataReductionData.tolerance); this->toleranceChanged(); uiGeneralTab.chkAuto2->setChecked(m_dataReductionData.autoTolerance2); this->autoTolerance2Changed(); uiGeneralTab.sbTolerance2->setValue(m_dataReductionData.tolerance2); this->tolerance2Changed(); this->showDataReductionResult(); //enable the "recalculate"-button if the source data was changed since the last dataReduction uiGeneralTab.pbRecalculate->setEnabled(m_dataReductionCurve->isSourceDataChangedSinceLastRecalc()); uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); //Slots connect(m_dataReductionCurve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_dataReductionCurve, SIGNAL(dataSourceTypeChanged(XYAnalysisCurve::DataSourceType)), this, SLOT(curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType))); connect(m_dataReductionCurve, SIGNAL(dataSourceCurveChanged(const XYCurve*)), this, SLOT(curveDataSourceCurveChanged(const XYCurve*))); connect(m_dataReductionCurve, SIGNAL(xDataColumnChanged(const AbstractColumn*)), this, SLOT(curveXDataColumnChanged(const AbstractColumn*))); connect(m_dataReductionCurve, SIGNAL(yDataColumnChanged(const AbstractColumn*)), this, SLOT(curveYDataColumnChanged(const AbstractColumn*))); connect(m_dataReductionCurve, SIGNAL(dataReductionDataChanged(XYDataReductionCurve::DataReductionData)), this, SLOT(curveDataReductionDataChanged(XYDataReductionCurve::DataReductionData))); connect(m_dataReductionCurve, SIGNAL(sourceDataChanged()), this, SLOT(enableRecalculate())); } void XYDataReductionCurveDock::setModel() { QList list; list<<"Folder"<<"Datapicker"<<"Worksheet"<<"CartesianPlot"<<"XYCurve"; cbDataSourceCurve->setTopLevelClasses(list); QList hiddenAspects; for (auto* curve : m_curvesList) hiddenAspects << curve; cbDataSourceCurve->setHiddenAspects(hiddenAspects); list.clear(); list<<"Folder"<<"Workbook"<<"Datapicker"<<"DatapickerCurve"<<"Spreadsheet" <<"FileDataSource"<<"Column"<<"Worksheet"<<"CartesianPlot"<<"XYFitCurve"; cbXDataColumn->setTopLevelClasses(list); cbYDataColumn->setTopLevelClasses(list); cbDataSourceCurve->setModel(m_aspectTreeModel); cbXDataColumn->setModel(m_aspectTreeModel); cbYDataColumn->setModel(m_aspectTreeModel); XYCurveDock::setModel(); } /*! sets the curves. The properties of the curves in the list \c list can be edited in this widget. */ void XYDataReductionCurveDock::setCurves(QList list) { m_initializing=true; m_curvesList=list; m_curve=list.first(); m_dataReductionCurve = dynamic_cast(m_curve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); this->setModel(); m_dataReductionData = m_dataReductionCurve->dataReductionData(); initGeneralTab(); initTabs(); m_initializing=false; //hide the "skip gaps" option after the curves were set ui.lLineSkipGaps->hide(); ui.chkLineSkipGaps->hide(); } //************************************************************* //**** SLOTs for changes triggered in XYFitCurveDock ***** //************************************************************* void XYDataReductionCurveDock::nameChanged() { if (m_initializing) return; m_curve->setName(uiGeneralTab.leName->text()); } void XYDataReductionCurveDock::commentChanged() { if (m_initializing) return; m_curve->setComment(uiGeneralTab.leComment->text()); } void XYDataReductionCurveDock::dataSourceTypeChanged(int index) { - XYAnalysisCurve::DataSourceType type = (XYAnalysisCurve::DataSourceType)index; + const auto type = (XYAnalysisCurve::DataSourceType)index; if (type == XYAnalysisCurve::DataSourceSpreadsheet) { uiGeneralTab.lDataSourceCurve->hide(); cbDataSourceCurve->hide(); uiGeneralTab.lXColumn->show(); cbXDataColumn->show(); uiGeneralTab.lYColumn->show(); cbYDataColumn->show(); } else { uiGeneralTab.lDataSourceCurve->show(); cbDataSourceCurve->show(); uiGeneralTab.lXColumn->hide(); cbXDataColumn->hide(); uiGeneralTab.lYColumn->hide(); cbYDataColumn->hide(); } if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataSourceType(type); } void XYDataReductionCurveDock::dataSourceCurveChanged(const QModelIndex& index) { - AbstractAspect* aspect = static_cast(index.internalPointer()); - XYCurve* dataSourceCurve = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto dataSourceCurve = dynamic_cast(aspect); // // disable deriv orders and accuracies that need more data points // this->updateSettings(dataSourceCurve->xColumn()); if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataSourceCurve(dataSourceCurve); } void XYDataReductionCurveDock::xDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); for (auto* curve : m_curvesList) dynamic_cast(curve)->setXDataColumn(column); //TODO: this->updateSettings(column); ? if (column != nullptr && uiGeneralTab.cbAutoRange->isChecked()) { uiGeneralTab.sbMin->setValue(column->minimum()); uiGeneralTab.sbMax->setValue(column->maximum()); } updateTolerance(); updateTolerance2(); } void XYDataReductionCurveDock::yDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); for (auto* curve : m_curvesList) dynamic_cast(curve)->setYDataColumn(column); updateTolerance(); updateTolerance2(); } void XYDataReductionCurveDock::updateTolerance() { const AbstractColumn* xDataColumn = nullptr; const AbstractColumn* yDataColumn = nullptr; if (m_dataReductionCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) { xDataColumn = m_dataReductionCurve->xDataColumn(); yDataColumn = m_dataReductionCurve->yDataColumn(); } else { if (m_dataReductionCurve->dataSourceCurve()) { xDataColumn = m_dataReductionCurve->dataSourceCurve()->xColumn(); yDataColumn = m_dataReductionCurve->dataSourceCurve()->yColumn(); } } if(xDataColumn == nullptr || yDataColumn == nullptr) return; //copy all valid data points for calculating tolerance to temporary vectors QVector xdataVector; QVector ydataVector; const double xmin = m_dataReductionData.xRange.first(); const double xmax = m_dataReductionData.xRange.last(); for (int row=0; rowrowCount(); ++row) { //only copy those data where _all_ values (for x and y, if given) are valid if (!std::isnan(xDataColumn->valueAt(row)) && !std::isnan(yDataColumn->valueAt(row)) && !xDataColumn->isMasked(row) && !yDataColumn->isMasked(row)) { // only when inside given range if (xDataColumn->valueAt(row) >= xmin && xDataColumn->valueAt(row) <= xmax) { xdataVector.append(xDataColumn->valueAt(row)); ydataVector.append(yDataColumn->valueAt(row)); } } } if(xdataVector.size() > 1) uiGeneralTab.cbType->setEnabled(true); else { uiGeneralTab.cbType->setEnabled(false); return; } DEBUG("automatic tolerance:"); DEBUG("clip_diag_perpoint =" << nsl_geom_linesim_clip_diag_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size())); DEBUG("clip_area_perpoint =" << nsl_geom_linesim_clip_area_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size())); DEBUG("avg_dist_perpoint =" << nsl_geom_linesim_avg_dist_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size())); - nsl_geom_linesim_type type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); + const auto type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); if (type == nsl_geom_linesim_type_raddist || type == nsl_geom_linesim_type_opheim) m_dataReductionData.tolerance = 10. * nsl_geom_linesim_clip_diag_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size()); else if (type == nsl_geom_linesim_type_visvalingam_whyatt) m_dataReductionData.tolerance = 0.1 * nsl_geom_linesim_clip_area_perpoint(xdataVector.data(), ydataVector.data(), (size_t)xdataVector.size()); else if (type == nsl_geom_linesim_type_douglas_peucker_variant) m_dataReductionData.tolerance = xdataVector.size()/10.; // reduction to 10% else m_dataReductionData.tolerance = 2.*nsl_geom_linesim_avg_dist_perpoint(xdataVector.data(), ydataVector.data(), xdataVector.size()); //m_dataReductionData.tolerance = nsl_geom_linesim_clip_diag_perpoint(xdataVector.data(), ydataVector.data(), xdataVector.size()); uiGeneralTab.sbTolerance->setValue(m_dataReductionData.tolerance); } void XYDataReductionCurveDock::updateTolerance2() { - nsl_geom_linesim_type type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); + const auto type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); if (type == nsl_geom_linesim_type_perpdist) uiGeneralTab.sbTolerance2->setValue(10); else if (type == nsl_geom_linesim_type_opheim) uiGeneralTab.sbTolerance2->setValue(5*uiGeneralTab.sbTolerance->value()); else if (type == nsl_geom_linesim_type_lang) uiGeneralTab.sbTolerance2->setValue(10); } void XYDataReductionCurveDock::autoRangeChanged() { bool autoRange = uiGeneralTab.cbAutoRange->isChecked(); m_dataReductionData.autoRange = autoRange; if (autoRange) { uiGeneralTab.lMin->setEnabled(false); uiGeneralTab.sbMin->setEnabled(false); uiGeneralTab.lMax->setEnabled(false); uiGeneralTab.sbMax->setEnabled(false); const AbstractColumn* xDataColumn = nullptr; if (m_dataReductionCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) xDataColumn = m_dataReductionCurve->xDataColumn(); else { if (m_dataReductionCurve->dataSourceCurve()) xDataColumn = m_dataReductionCurve->dataSourceCurve()->xColumn(); } if (xDataColumn) { uiGeneralTab.sbMin->setValue(xDataColumn->minimum()); uiGeneralTab.sbMax->setValue(xDataColumn->maximum()); } } else { uiGeneralTab.lMin->setEnabled(true); uiGeneralTab.sbMin->setEnabled(true); uiGeneralTab.lMax->setEnabled(true); uiGeneralTab.sbMax->setEnabled(true); } } void XYDataReductionCurveDock::xRangeMinChanged() { double xMin = uiGeneralTab.sbMin->value(); m_dataReductionData.xRange.first() = xMin; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDataReductionCurveDock::xRangeMaxChanged() { double xMax = uiGeneralTab.sbMax->value(); m_dataReductionData.xRange.last() = xMax; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDataReductionCurveDock::typeChanged() { - nsl_geom_linesim_type type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); + const auto type = (nsl_geom_linesim_type)uiGeneralTab.cbType->currentIndex(); m_dataReductionData.type = type; switch (type) { case nsl_geom_linesim_type_douglas_peucker: case nsl_geom_linesim_type_raddist: case nsl_geom_linesim_type_interp: case nsl_geom_linesim_type_reumann_witkam: uiGeneralTab.lOption->setText(i18n("Tolerance (distance):")); uiGeneralTab.sbTolerance->setDecimals(6); uiGeneralTab.sbTolerance->setMinimum(0); uiGeneralTab.sbTolerance->setSingleStep(0.01); uiGeneralTab.lOption2->hide(); uiGeneralTab.chkAuto2->hide(); uiGeneralTab.sbTolerance2->hide(); if (uiGeneralTab.chkAuto->isChecked()) updateTolerance(); break; case nsl_geom_linesim_type_douglas_peucker_variant: uiGeneralTab.lOption->setText(i18n("Number of points:")); uiGeneralTab.sbTolerance->setDecimals(0); uiGeneralTab.sbTolerance->setMinimum(2); uiGeneralTab.sbTolerance->setSingleStep(1); uiGeneralTab.lOption2->hide(); uiGeneralTab.chkAuto2->hide(); uiGeneralTab.sbTolerance2->hide(); if (uiGeneralTab.chkAuto->isChecked()) updateTolerance(); break; case nsl_geom_linesim_type_nthpoint: uiGeneralTab.lOption->setText(i18n("Step size:")); uiGeneralTab.sbTolerance->setValue(10); uiGeneralTab.sbTolerance->setDecimals(0); uiGeneralTab.sbTolerance->setMinimum(1); uiGeneralTab.sbTolerance->setSingleStep(1); uiGeneralTab.lOption2->hide(); uiGeneralTab.chkAuto2->hide(); uiGeneralTab.sbTolerance2->hide(); break; case nsl_geom_linesim_type_perpdist: // repeat option uiGeneralTab.lOption->setText(i18n("Tolerance (distance):")); uiGeneralTab.sbTolerance->setDecimals(6); uiGeneralTab.sbTolerance->setMinimum(0); uiGeneralTab.sbTolerance->setSingleStep(0.01); uiGeneralTab.sbTolerance2->show(); uiGeneralTab.lOption2->show(); uiGeneralTab.chkAuto2->show(); uiGeneralTab.lOption2->setText(i18n("Repeats:")); uiGeneralTab.sbTolerance2->setDecimals(0); uiGeneralTab.sbTolerance2->setMinimum(1); uiGeneralTab.sbTolerance2->setSingleStep(1); if (uiGeneralTab.chkAuto->isChecked()) updateTolerance(); if (uiGeneralTab.chkAuto2->isChecked()) updateTolerance2(); break; case nsl_geom_linesim_type_visvalingam_whyatt: uiGeneralTab.lOption->setText(i18n("Tolerance (area):")); uiGeneralTab.sbTolerance->setDecimals(6); uiGeneralTab.sbTolerance->setMinimum(0); uiGeneralTab.sbTolerance->setSingleStep(0.01); uiGeneralTab.lOption2->hide(); uiGeneralTab.chkAuto2->hide(); uiGeneralTab.sbTolerance2->hide(); if (uiGeneralTab.chkAuto->isChecked()) updateTolerance(); break; case nsl_geom_linesim_type_opheim: // min/max tol options uiGeneralTab.lOption->setText(i18n("Minimum tolerance:")); uiGeneralTab.sbTolerance->setDecimals(6); uiGeneralTab.sbTolerance->setMinimum(0); uiGeneralTab.sbTolerance->setSingleStep(0.01); uiGeneralTab.lOption2->setText(i18n("Maximum tolerance:")); uiGeneralTab.lOption2->show(); uiGeneralTab.chkAuto2->show(); uiGeneralTab.sbTolerance2->show(); uiGeneralTab.sbTolerance2->setDecimals(6); uiGeneralTab.sbTolerance2->setMinimum(0); uiGeneralTab.sbTolerance2->setSingleStep(0.01); if (uiGeneralTab.chkAuto->isChecked()) updateTolerance(); if (uiGeneralTab.chkAuto2->isChecked()) updateTolerance2(); break; case nsl_geom_linesim_type_lang: // distance/region uiGeneralTab.lOption->setText(i18n("Tolerance (distance):")); uiGeneralTab.sbTolerance->setDecimals(6); uiGeneralTab.sbTolerance->setMinimum(0); uiGeneralTab.sbTolerance->setSingleStep(0.01); uiGeneralTab.lOption2->setText(i18n("Search region:")); uiGeneralTab.lOption2->show(); uiGeneralTab.chkAuto2->show(); uiGeneralTab.sbTolerance2->show(); uiGeneralTab.sbTolerance2->setDecimals(0); uiGeneralTab.sbTolerance2->setMinimum(1); uiGeneralTab.sbTolerance2->setSingleStep(1); if (uiGeneralTab.chkAuto->isChecked()) updateTolerance(); if (uiGeneralTab.chkAuto2->isChecked()) updateTolerance2(); break; } uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDataReductionCurveDock::autoToleranceChanged() { - bool autoTolerance = (bool)uiGeneralTab.chkAuto->isChecked(); + const auto autoTolerance = (bool)uiGeneralTab.chkAuto->isChecked(); m_dataReductionData.autoTolerance = autoTolerance; if (autoTolerance) { uiGeneralTab.sbTolerance->setEnabled(false); updateTolerance(); } else uiGeneralTab.sbTolerance->setEnabled(true); } void XYDataReductionCurveDock::toleranceChanged() { m_dataReductionData.tolerance = uiGeneralTab.sbTolerance->value(); uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDataReductionCurveDock::autoTolerance2Changed() { - bool autoTolerance2 = (bool)uiGeneralTab.chkAuto2->isChecked(); + const auto autoTolerance2 = (bool)uiGeneralTab.chkAuto2->isChecked(); m_dataReductionData.autoTolerance2 = autoTolerance2; if (autoTolerance2) { uiGeneralTab.sbTolerance2->setEnabled(false); updateTolerance2(); } else uiGeneralTab.sbTolerance2->setEnabled(true); } void XYDataReductionCurveDock::tolerance2Changed() { m_dataReductionData.tolerance2 = uiGeneralTab.sbTolerance2->value(); uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDataReductionCurveDock::recalculateClicked() { //show a progress bar in the status bar - QProgressBar* progressBar = new QProgressBar(); + auto progressBar = new QProgressBar(); progressBar->setMinimum(0); progressBar->setMaximum(100); connect(m_curve, SIGNAL(completed(int)), progressBar, SLOT(setValue(int))); statusBar->clearMessage(); statusBar->addWidget(progressBar, 1); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataReductionData(m_dataReductionData); QApplication::restoreOverrideCursor(); statusBar->removeWidget(progressBar); uiGeneralTab.pbRecalculate->setEnabled(false); emit info(i18n("Data reduction status: %1", m_dataReductionCurve->dataReductionResult().status)); } void XYDataReductionCurveDock::enableRecalculate() const { if (m_initializing) return; //no dataReductioning possible without the x- and y-data bool hasSourceData = false; if (m_dataReductionCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) { AbstractAspect* aspectX = static_cast(cbXDataColumn->currentModelIndex().internalPointer()); AbstractAspect* aspectY = static_cast(cbYDataColumn->currentModelIndex().internalPointer()); hasSourceData = (aspectX!=nullptr && aspectY!=nullptr); } else { hasSourceData = (m_dataReductionCurve->dataSourceCurve() != nullptr); } uiGeneralTab.pbRecalculate->setEnabled(hasSourceData); } /*! * show the result and details of the dataReduction */ void XYDataReductionCurveDock::showDataReductionResult() { const XYDataReductionCurve::DataReductionResult& dataReductionResult = m_dataReductionCurve->dataReductionResult(); if (!dataReductionResult.available) { uiGeneralTab.teResult->clear(); return; } QString str = i18n("status: %1", dataReductionResult.status) + "
"; if (!dataReductionResult.valid) { uiGeneralTab.teResult->setText(str); return; //result is not valid, there was an error which is shown in the status-string, nothing to show more. } if (dataReductionResult.elapsedTime>1000) str += i18n("calculation time: %1 s", QString::number(dataReductionResult.elapsedTime/1000)) + "
"; else str += i18n("calculation time: %1 ms", QString::number(dataReductionResult.elapsedTime)) + "
"; str += "
"; str += i18n("number of points: %1", QString::number(dataReductionResult.npoints)) + "
"; str += i18n("positional squared error: %1", QString::number(dataReductionResult.posError)) + "
"; str += i18n("area error: %1", QString::number(dataReductionResult.areaError)) + "
"; uiGeneralTab.teResult->setText(str); } //************************************************************* //*********** SLOTs for changes triggered in XYCurve ********** //************************************************************* //General-Tab void XYDataReductionCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != uiGeneralTab.leName->text()) uiGeneralTab.leName->setText(aspect->name()); else if (aspect->comment() != uiGeneralTab.leComment->text()) uiGeneralTab.leComment->setText(aspect->comment()); m_initializing = false; } void XYDataReductionCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) { m_initializing = true; uiGeneralTab.cbDataSourceType->setCurrentIndex(type); m_initializing = false; } void XYDataReductionCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve); m_initializing = false; } void XYDataReductionCurveDock::curveXDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column); m_initializing = false; } void XYDataReductionCurveDock::curveYDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column); m_initializing = false; } void XYDataReductionCurveDock::curveDataReductionDataChanged(const XYDataReductionCurve::DataReductionData& dataReductionData) { m_initializing = true; m_dataReductionData = dataReductionData; //uiGeneralTab.cbType->setCurrentIndex(m_dataReductionData.type); //this->typeChanged(); this->showDataReductionResult(); m_initializing = false; } void XYDataReductionCurveDock::dataChanged() { this->enableRecalculate(); } diff --git a/src/kdefrontend/dockwidgets/XYDifferentiationCurveDock.cpp b/src/kdefrontend/dockwidgets/XYDifferentiationCurveDock.cpp index ed13bbe73..25a9e17fa 100644 --- a/src/kdefrontend/dockwidgets/XYDifferentiationCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYDifferentiationCurveDock.cpp @@ -1,589 +1,589 @@ /*************************************************************************** File : XYDifferentiationCurveDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn) Copyright : (C) 2017 Alexander Semke (alexander.semke@web.de) Description : widget for editing properties of differentiation curves ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "XYDifferentiationCurveDock.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/worksheet/plots/cartesian/XYDifferentiationCurve.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include extern "C" { #include "backend/nsl/nsl_diff.h" } /*! \class XYDifferentiationCurveDock \brief Provides a widget for editing the properties of the XYDifferentiationCurves (2D-curves defined by a differentiation) currently selected in the project explorer. If more than one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ XYDifferentiationCurveDock::XYDifferentiationCurveDock(QWidget* parent) : XYCurveDock(parent), cbDataSourceCurve(nullptr), cbXDataColumn(nullptr), cbYDataColumn(nullptr), m_differentiationCurve(nullptr) { //hide the line connection type ui.cbLineType->setDisabled(true); //remove the tab "Error bars" ui.tabWidget->removeTab(5); } /*! * // Tab "General" */ void XYDifferentiationCurveDock::setupGeneral() { QWidget* generalTab = new QWidget(ui.tabGeneral); uiGeneralTab.setupUi(generalTab); - QGridLayout* gridLayout = dynamic_cast(generalTab->layout()); + auto gridLayout = dynamic_cast(generalTab->layout()); if (gridLayout) { gridLayout->setContentsMargins(2,2,2,2); gridLayout->setHorizontalSpacing(2); gridLayout->setVerticalSpacing(2); } uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet")); uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve")); cbDataSourceCurve = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 3); cbXDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 3); cbYDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbYDataColumn, 7, 2, 1, 3); for (int i=0; i < NSL_DIFF_DERIV_ORDER_COUNT; ++i) uiGeneralTab.cbDerivOrder->addItem(i18n(nsl_diff_deriv_order_name[i])); uiGeneralTab.sbMin->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.sbMax->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.pbRecalculate->setIcon( QIcon::fromTheme("run-build") ); - QHBoxLayout* layout = new QHBoxLayout(ui.tabGeneral); + auto layout = new QHBoxLayout(ui.tabGeneral); layout->setMargin(0); layout->addWidget(generalTab); //Slots connect( uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYDifferentiationCurveDock::nameChanged ); connect( uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYDifferentiationCurveDock::commentChanged ); connect( uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( uiGeneralTab.cbDataSourceType, SIGNAL(currentIndexChanged(int)), this, SLOT(dataSourceTypeChanged(int)) ); connect( uiGeneralTab.cbAutoRange, SIGNAL(clicked(bool)), this, SLOT(autoRangeChanged()) ); connect( uiGeneralTab.sbMin, SIGNAL(valueChanged(double)), this, SLOT(xRangeMinChanged()) ); connect( uiGeneralTab.sbMax, SIGNAL(valueChanged(double)), this, SLOT(xRangeMaxChanged()) ); connect( uiGeneralTab.cbDerivOrder, SIGNAL(currentIndexChanged(int)), this, SLOT(derivOrderChanged()) ); connect( uiGeneralTab.sbAccOrder, SIGNAL(valueChanged(int)), this, SLOT(accOrderChanged()) ); connect( uiGeneralTab.pbRecalculate, SIGNAL(clicked()), this, SLOT(recalculateClicked()) ); connect( cbDataSourceCurve, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(dataSourceCurveChanged(QModelIndex)) ); connect( cbXDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xDataColumnChanged(QModelIndex)) ); connect( cbYDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yDataColumnChanged(QModelIndex)) ); } void XYDifferentiationCurveDock::initGeneralTab() { //if there are more than one curve in the list, disable the tab "general" if (m_curvesList.size()==1) { uiGeneralTab.lName->setEnabled(true); uiGeneralTab.leName->setEnabled(true); uiGeneralTab.lComment->setEnabled(true); uiGeneralTab.leComment->setEnabled(true); uiGeneralTab.leName->setText(m_curve->name()); uiGeneralTab.leComment->setText(m_curve->comment()); }else { uiGeneralTab.lName->setEnabled(false); uiGeneralTab.leName->setEnabled(false); uiGeneralTab.lComment->setEnabled(false); uiGeneralTab.leComment->setEnabled(false); uiGeneralTab.leName->setText(""); uiGeneralTab.leComment->setText(""); } //show the properties of the first curve m_differentiationCurve = dynamic_cast(m_curve); uiGeneralTab.cbDataSourceType->setCurrentIndex(m_differentiationCurve->dataSourceType()); this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex()); XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_differentiationCurve->dataSourceCurve()); XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_differentiationCurve->xDataColumn()); XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_differentiationCurve->yDataColumn()); uiGeneralTab.cbAutoRange->setChecked(m_differentiationData.autoRange); uiGeneralTab.sbMin->setValue(m_differentiationData.xRange.first()); uiGeneralTab.sbMax->setValue(m_differentiationData.xRange.last()); this->autoRangeChanged(); // update list of selectable types xDataColumnChanged(cbXDataColumn->currentModelIndex()); uiGeneralTab.cbDerivOrder->setCurrentIndex(m_differentiationData.derivOrder); this->derivOrderChanged(); uiGeneralTab.sbAccOrder->setValue(m_differentiationData.accOrder); this->accOrderChanged(); this->showDifferentiationResult(); uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); //Slots connect(m_differentiationCurve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_differentiationCurve, SIGNAL(dataSourceTypeChanged(XYAnalysisCurve::DataSourceType)), this, SLOT(curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType))); connect(m_differentiationCurve, SIGNAL(dataSourceCurveChanged(const XYCurve*)), this, SLOT(curveDataSourceCurveChanged(const XYCurve*))); connect(m_differentiationCurve, SIGNAL(xDataColumnChanged(const AbstractColumn*)), this, SLOT(curveXDataColumnChanged(const AbstractColumn*))); connect(m_differentiationCurve, SIGNAL(yDataColumnChanged(const AbstractColumn*)), this, SLOT(curveYDataColumnChanged(const AbstractColumn*))); connect(m_differentiationCurve, SIGNAL(differentiationDataChanged(XYDifferentiationCurve::DifferentiationData)), this, SLOT(curveDifferentiationDataChanged(XYDifferentiationCurve::DifferentiationData))); connect(m_differentiationCurve, SIGNAL(sourceDataChanged()), this, SLOT(enableRecalculate())); } void XYDifferentiationCurveDock::setModel() { QList list; list<<"Folder"<<"Datapicker"<<"Worksheet"<<"CartesianPlot"<<"XYCurve"; cbDataSourceCurve->setTopLevelClasses(list); QList hiddenAspects; for (auto curve : m_curvesList) hiddenAspects << curve; cbDataSourceCurve->setHiddenAspects(hiddenAspects); list.clear(); list<<"Folder"<<"Workbook"<<"Datapicker"<<"DatapickerCurve"<<"Spreadsheet" <<"FileDataSource"<<"Column"<<"Worksheet"<<"CartesianPlot"<<"XYFitCurve"; cbXDataColumn->setTopLevelClasses(list); cbYDataColumn->setTopLevelClasses(list); cbDataSourceCurve->setModel(m_aspectTreeModel); cbXDataColumn->setModel(m_aspectTreeModel); cbYDataColumn->setModel(m_aspectTreeModel); XYCurveDock::setModel(); } /*! sets the curves. The properties of the curves in the list \c list can be edited in this widget. */ void XYDifferentiationCurveDock::setCurves(QList list) { m_initializing = true; m_curvesList = list; m_curve = list.first(); m_differentiationCurve = dynamic_cast(m_curve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); this->setModel(); m_differentiationData = m_differentiationCurve->differentiationData(); initGeneralTab(); initTabs(); m_initializing = false; //hide the "skip gaps" option after the curves were set ui.lLineSkipGaps->hide(); ui.chkLineSkipGaps->hide(); } //************************************************************* //**** SLOTs for changes triggered in XYFitCurveDock ***** //************************************************************* void XYDifferentiationCurveDock::nameChanged() { if (m_initializing) return; m_curve->setName(uiGeneralTab.leName->text()); } void XYDifferentiationCurveDock::commentChanged() { if (m_initializing) return; m_curve->setComment(uiGeneralTab.leComment->text()); } void XYDifferentiationCurveDock::dataSourceTypeChanged(int index) { - XYAnalysisCurve::DataSourceType type = (XYAnalysisCurve::DataSourceType)index; + const auto type = (XYAnalysisCurve::DataSourceType)index; if (type == XYAnalysisCurve::DataSourceSpreadsheet) { uiGeneralTab.lDataSourceCurve->hide(); cbDataSourceCurve->hide(); uiGeneralTab.lXColumn->show(); cbXDataColumn->show(); uiGeneralTab.lYColumn->show(); cbYDataColumn->show(); } else { uiGeneralTab.lDataSourceCurve->show(); cbDataSourceCurve->show(); uiGeneralTab.lXColumn->hide(); cbXDataColumn->hide(); uiGeneralTab.lYColumn->hide(); cbYDataColumn->hide(); } if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataSourceType(type); } void XYDifferentiationCurveDock::dataSourceCurveChanged(const QModelIndex& index) { - AbstractAspect* aspect = static_cast(index.internalPointer()); - XYCurve* dataSourceCurve = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto dataSourceCurve = dynamic_cast(aspect); // disable deriv orders and accuracies that need more data points this->updateSettings(dataSourceCurve->xColumn()); if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataSourceCurve(dataSourceCurve); } void XYDifferentiationCurveDock::xDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); // disable deriv orders and accuracies that need more data points this->updateSettings(column); if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setXDataColumn(column); } void XYDifferentiationCurveDock::yDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); for (auto* curve : m_curvesList) dynamic_cast(curve)->setYDataColumn(column); } /*! * disable deriv orders and accuracies that need more data points */ void XYDifferentiationCurveDock::updateSettings(const AbstractColumn* column) { if (!column) return; if (uiGeneralTab.cbAutoRange->isChecked()) { uiGeneralTab.sbMin->setValue(column->minimum()); uiGeneralTab.sbMax->setValue(column->maximum()); } size_t n=0; for (int row=0; row < column->rowCount(); ++row) if (!std::isnan(column->valueAt(row)) && !column->isMasked(row)) n++; - const QStandardItemModel* model = qobject_cast(uiGeneralTab.cbDerivOrder->model()); + const auto model = qobject_cast(uiGeneralTab.cbDerivOrder->model()); QStandardItem* item = model->item(nsl_diff_deriv_order_first); if (n < 3) item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); else { item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); if (n < 5) uiGeneralTab.sbAccOrder->setMinimum(2); } item = model->item(nsl_diff_deriv_order_second); if (n < 3) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbDerivOrder->currentIndex() == nsl_diff_deriv_order_second) uiGeneralTab.cbDerivOrder->setCurrentIndex(nsl_diff_deriv_order_first); } else { item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); if (n < 4) uiGeneralTab.sbAccOrder->setMinimum(1); else if (n < 5) uiGeneralTab.sbAccOrder->setMinimum(2); } item = model->item(nsl_diff_deriv_order_third); if (n < 5) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbDerivOrder->currentIndex() == nsl_diff_deriv_order_third) uiGeneralTab.cbDerivOrder->setCurrentIndex(nsl_diff_deriv_order_first); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = model->item(nsl_diff_deriv_order_fourth); if (n < 5) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbDerivOrder->currentIndex() == nsl_diff_deriv_order_fourth) uiGeneralTab.cbDerivOrder->setCurrentIndex(nsl_diff_deriv_order_first); } else { item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); if (n < 7) uiGeneralTab.sbAccOrder->setMinimum(1); } item = model->item(nsl_diff_deriv_order_fifth); if (n < 7) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbDerivOrder->currentIndex() == nsl_diff_deriv_order_fifth) uiGeneralTab.cbDerivOrder->setCurrentIndex(nsl_diff_deriv_order_first); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = model->item(nsl_diff_deriv_order_sixth); if (n < 7) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbDerivOrder->currentIndex() == nsl_diff_deriv_order_sixth) uiGeneralTab.cbDerivOrder->setCurrentIndex(nsl_diff_deriv_order_first); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); } void XYDifferentiationCurveDock::autoRangeChanged() { bool autoRange = uiGeneralTab.cbAutoRange->isChecked(); m_differentiationData.autoRange = autoRange; if (autoRange) { uiGeneralTab.lMin->setEnabled(false); uiGeneralTab.sbMin->setEnabled(false); uiGeneralTab.lMax->setEnabled(false); uiGeneralTab.sbMax->setEnabled(false); const AbstractColumn* xDataColumn = nullptr; if (m_differentiationCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) xDataColumn = m_differentiationCurve->xDataColumn(); else { if (m_differentiationCurve->dataSourceCurve()) xDataColumn = m_differentiationCurve->dataSourceCurve()->xColumn(); } if (xDataColumn) { uiGeneralTab.sbMin->setValue(xDataColumn->minimum()); uiGeneralTab.sbMax->setValue(xDataColumn->maximum()); } } else { uiGeneralTab.lMin->setEnabled(true); uiGeneralTab.sbMin->setEnabled(true); uiGeneralTab.lMax->setEnabled(true); uiGeneralTab.sbMax->setEnabled(true); } } void XYDifferentiationCurveDock::xRangeMinChanged() { double xMin = uiGeneralTab.sbMin->value(); m_differentiationData.xRange.first() = xMin; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDifferentiationCurveDock::xRangeMaxChanged() { double xMax = uiGeneralTab.sbMax->value(); m_differentiationData.xRange.last() = xMax; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDifferentiationCurveDock::derivOrderChanged() { - const nsl_diff_deriv_order_type derivOrder = (nsl_diff_deriv_order_type)uiGeneralTab.cbDerivOrder->currentIndex(); + const auto derivOrder = (nsl_diff_deriv_order_type)uiGeneralTab.cbDerivOrder->currentIndex(); m_differentiationData.derivOrder = derivOrder; // update avail. accuracies switch (derivOrder) { case nsl_diff_deriv_order_first: uiGeneralTab.sbAccOrder->setMinimum(2); uiGeneralTab.sbAccOrder->setMaximum(4); uiGeneralTab.sbAccOrder->setSingleStep(2); uiGeneralTab.sbAccOrder->setValue(4); break; case nsl_diff_deriv_order_second: uiGeneralTab.sbAccOrder->setMinimum(1); uiGeneralTab.sbAccOrder->setMaximum(3); uiGeneralTab.sbAccOrder->setSingleStep(1); uiGeneralTab.sbAccOrder->setValue(3); break; case nsl_diff_deriv_order_third: uiGeneralTab.sbAccOrder->setMinimum(2); uiGeneralTab.sbAccOrder->setMaximum(2); break; case nsl_diff_deriv_order_fourth: uiGeneralTab.sbAccOrder->setMinimum(1); uiGeneralTab.sbAccOrder->setMaximum(3); uiGeneralTab.sbAccOrder->setSingleStep(2); uiGeneralTab.sbAccOrder->setValue(3); break; case nsl_diff_deriv_order_fifth: uiGeneralTab.sbAccOrder->setMinimum(2); uiGeneralTab.sbAccOrder->setMaximum(2); break; case nsl_diff_deriv_order_sixth: uiGeneralTab.sbAccOrder->setMinimum(1); uiGeneralTab.sbAccOrder->setMaximum(1); break; } uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDifferentiationCurveDock::accOrderChanged() { - int accOrder = (int)uiGeneralTab.sbAccOrder->value(); + const auto accOrder = (int)uiGeneralTab.sbAccOrder->value(); m_differentiationData.accOrder = accOrder; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYDifferentiationCurveDock::recalculateClicked() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); for (auto* curve : m_curvesList) if (curve != nullptr) dynamic_cast(curve)->setDifferentiationData(m_differentiationData); uiGeneralTab.pbRecalculate->setEnabled(false); emit info(i18n("Differentiation status: %1", m_differentiationCurve->differentiationResult().status)); QApplication::restoreOverrideCursor(); } void XYDifferentiationCurveDock::enableRecalculate() const { if (m_initializing) return; //no differentiation possible without the x- and y-data bool hasSourceData = false; if (m_differentiationCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) { AbstractAspect* aspectX = static_cast(cbXDataColumn->currentModelIndex().internalPointer()); AbstractAspect* aspectY = static_cast(cbYDataColumn->currentModelIndex().internalPointer()); hasSourceData = (aspectX!=nullptr && aspectY!=nullptr); } else { hasSourceData = (m_differentiationCurve->dataSourceCurve() != nullptr); } uiGeneralTab.pbRecalculate->setEnabled(hasSourceData); } /*! * show the result and details of the differentiation */ void XYDifferentiationCurveDock::showDifferentiationResult() { const XYDifferentiationCurve::DifferentiationResult& differentiationResult = m_differentiationCurve->differentiationResult(); if (!differentiationResult.available) { uiGeneralTab.teResult->clear(); return; } QString str = i18n("status: %1", differentiationResult.status) + "
"; if (!differentiationResult.valid) { uiGeneralTab.teResult->setText(str); return; //result is not valid, there was an error which is shown in the status-string, nothing to show more. } if (differentiationResult.elapsedTime>1000) str += i18n("calculation time: %1 s", QString::number(differentiationResult.elapsedTime/1000)) + "
"; else str += i18n("calculation time: %1 ms", QString::number(differentiationResult.elapsedTime)) + "
"; str += "

"; uiGeneralTab.teResult->setText(str); //enable the "recalculate"-button if the source data was changed since the last differentiation uiGeneralTab.pbRecalculate->setEnabled(m_differentiationCurve->isSourceDataChangedSinceLastRecalc()); } //************************************************************* //*** SLOTs for changes triggered in XYDifferentiationCurve *** //************************************************************* //General-Tab void XYDifferentiationCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != uiGeneralTab.leName->text()) uiGeneralTab.leName->setText(aspect->name()); else if (aspect->comment() != uiGeneralTab.leComment->text()) uiGeneralTab.leComment->setText(aspect->comment()); m_initializing = false; } void XYDifferentiationCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) { m_initializing = true; uiGeneralTab.cbDataSourceType->setCurrentIndex(type); m_initializing = false; } void XYDifferentiationCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve); m_initializing = false; } void XYDifferentiationCurveDock::curveXDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column); m_initializing = false; } void XYDifferentiationCurveDock::curveYDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column); m_initializing = false; } void XYDifferentiationCurveDock::curveDifferentiationDataChanged(const XYDifferentiationCurve::DifferentiationData& differentiationData) { m_initializing = true; m_differentiationData = differentiationData; uiGeneralTab.cbDerivOrder->setCurrentIndex(m_differentiationData.derivOrder); this->derivOrderChanged(); uiGeneralTab.sbAccOrder->setValue(m_differentiationData.accOrder); this->accOrderChanged(); this->showDifferentiationResult(); m_initializing = false; } void XYDifferentiationCurveDock::dataChanged() { this->enableRecalculate(); } diff --git a/src/kdefrontend/dockwidgets/XYEquationCurveDock.cpp b/src/kdefrontend/dockwidgets/XYEquationCurveDock.cpp index e758e0543..606bb5ceb 100644 --- a/src/kdefrontend/dockwidgets/XYEquationCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYEquationCurveDock.cpp @@ -1,378 +1,378 @@ /*************************************************************************** File : XYEquationCurveDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2014 Alexander Semke (alexander.semke@web.de) Description : widget for editing properties of equation curves ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "XYEquationCurveDock.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/worksheet/plots/cartesian/XYEquationCurve.h" #include "backend/gsl/ExpressionParser.h" #include "kdefrontend/widgets/ConstantsWidget.h" #include "kdefrontend/widgets/FunctionsWidget.h" #include #include #include #include #include /*! \class XYEquationCurveDock \brief Provides a widget for editing the properties of the XYEquationCurves (2D-curves defined by a mathematical equation) currently selected in the project explorer. If more then one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ XYEquationCurveDock::XYEquationCurveDock(QWidget *parent): XYCurveDock(parent), m_equationCurve(nullptr) { //remove the tab "Error bars" ui.tabWidget->removeTab(5); } /*! * // Tab "General" */ void XYEquationCurveDock::setupGeneral() { QWidget* generalTab = new QWidget(ui.tabGeneral); uiGeneralTab.setupUi(generalTab); - QGridLayout* gridLayout = dynamic_cast(generalTab->layout()); - if (gridLayout ) { + auto gridLayout = dynamic_cast(generalTab->layout()); + if (gridLayout) { gridLayout->setContentsMargins(2,2,2,2); gridLayout->setHorizontalSpacing(2); gridLayout->setVerticalSpacing(2); } - QHBoxLayout* layout = new QHBoxLayout(ui.tabGeneral); + auto layout = new QHBoxLayout(ui.tabGeneral); layout->setMargin(0); layout->addWidget(generalTab); uiGeneralTab.tbConstants1->setIcon( QIcon::fromTheme("labplot-format-text-symbol") ); uiGeneralTab.tbFunctions1->setIcon( QIcon::fromTheme("preferences-desktop-font") ); uiGeneralTab.tbConstants2->setIcon( QIcon::fromTheme("labplot-format-text-symbol") ); uiGeneralTab.tbFunctions2->setIcon( QIcon::fromTheme("preferences-desktop-font") ); uiGeneralTab.cbType->addItem(i18n("Cartesian")); uiGeneralTab.cbType->addItem(i18n("Polar")); uiGeneralTab.cbType->addItem(i18n("Parametric")); // uiGeneralTab.cbType->addItem(i18n("Implicit")); uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build")); uiGeneralTab.teEquation2->setExpressionType(XYEquationCurve::Parametric); uiGeneralTab.teEquation1->setMaximumHeight(uiGeneralTab.leName->sizeHint().height()*2); uiGeneralTab.teEquation2->setMaximumHeight(uiGeneralTab.leName->sizeHint().height()*2); uiGeneralTab.teMin->setMaximumHeight(uiGeneralTab.leName->sizeHint().height()); uiGeneralTab.teMax->setMaximumHeight(uiGeneralTab.leName->sizeHint().height()); //Slots connect( uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYEquationCurveDock::nameChanged ); connect( uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYEquationCurveDock::commentChanged ); connect( uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( uiGeneralTab.cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int)) ); connect( uiGeneralTab.teEquation1, SIGNAL(expressionChanged()), this, SLOT(enableRecalculate()) ); connect( uiGeneralTab.teEquation2, SIGNAL(expressionChanged()), this, SLOT(enableRecalculate()) ); connect( uiGeneralTab.tbConstants1, SIGNAL(clicked()), this, SLOT(showConstants()) ); connect( uiGeneralTab.tbFunctions1, SIGNAL(clicked()), this, SLOT(showFunctions()) ); connect( uiGeneralTab.tbConstants2, SIGNAL(clicked()), this, SLOT(showConstants()) ); connect( uiGeneralTab.tbFunctions2, SIGNAL(clicked()), this, SLOT(showFunctions()) ); connect( uiGeneralTab.teMin, SIGNAL(expressionChanged()), this, SLOT(enableRecalculate()) ); connect( uiGeneralTab.teMax, SIGNAL(expressionChanged()), this, SLOT(enableRecalculate()) ); connect( uiGeneralTab.sbCount, SIGNAL(valueChanged(int)), this, SLOT(enableRecalculate()) ); connect( uiGeneralTab.pbRecalculate, SIGNAL(clicked()), this, SLOT(recalculateClicked()) ); } /*! sets the curves. The properties of the curves in the list \c list can be edited in this widget. */ void XYEquationCurveDock::setCurves(QList list) { m_initializing=true; m_curvesList=list; m_curve=list.first(); m_equationCurve = dynamic_cast(m_curve); Q_ASSERT(m_equationCurve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); XYCurveDock::setModel(); initGeneralTab(); initTabs(); uiGeneralTab.pbRecalculate->setEnabled(false); m_initializing=false; } void XYEquationCurveDock::initGeneralTab() { //if there are more then one curve in the list, disable the tab "general" if (m_curvesList.size()==1){ uiGeneralTab.lName->setEnabled(true); uiGeneralTab.leName->setEnabled(true); uiGeneralTab.lComment->setEnabled(true); uiGeneralTab.leComment->setEnabled(true); uiGeneralTab.leName->setText(m_curve->name()); uiGeneralTab.leComment->setText(m_curve->comment()); }else { uiGeneralTab.lName->setEnabled(false); uiGeneralTab.leName->setEnabled(false); uiGeneralTab.lComment->setEnabled(false); uiGeneralTab.leComment->setEnabled(false); uiGeneralTab.leName->setText(""); uiGeneralTab.leComment->setText(""); } //show the properties of the first curve - const XYEquationCurve* equationCurve = dynamic_cast(m_curve); + const auto equationCurve = dynamic_cast(m_curve); Q_ASSERT(equationCurve); const XYEquationCurve::EquationData& data = equationCurve->equationData(); uiGeneralTab.cbType->setCurrentIndex(data.type); this->typeChanged(data.type); uiGeneralTab.teEquation1->setText(data.expression1); uiGeneralTab.teEquation2->setText(data.expression2); uiGeneralTab.teMin->setText(data.min); uiGeneralTab.teMax->setText(data.max); uiGeneralTab.sbCount->setValue(data.count); uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); //Slots connect(m_equationCurve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_equationCurve, SIGNAL(equationDataChanged(XYEquationCurve::EquationData)), this, SLOT(curveEquationDataChanged(XYEquationCurve::EquationData))); } //************************************************************* //**** SLOTs for changes triggered in XYEquationCurveDock ***** //************************************************************* void XYEquationCurveDock::nameChanged(){ if (m_initializing) return; m_curve->setName(uiGeneralTab.leName->text()); } void XYEquationCurveDock::commentChanged(){ if (m_initializing) return; m_curve->setComment(uiGeneralTab.leComment->text()); } void XYEquationCurveDock::typeChanged(int index) { - XYEquationCurve::EquationType type = XYEquationCurve::EquationType(index); - if (type==XYEquationCurve::Cartesian) { + const auto type = XYEquationCurve::EquationType(index); + if (type == XYEquationCurve::Cartesian) { uiGeneralTab.lEquation1->setText("y=f(x)"); uiGeneralTab.lEquation2->hide(); uiGeneralTab.teEquation2->hide(); uiGeneralTab.tbFunctions2->hide(); uiGeneralTab.tbConstants2->hide(); uiGeneralTab.lMin->show(); uiGeneralTab.lMax->show(); uiGeneralTab.teMin->show(); uiGeneralTab.teMax->show(); uiGeneralTab.lMin->setText(i18n("x, min")); uiGeneralTab.lMax->setText(i18n("x, max")); - } else if (type==XYEquationCurve::Polar) { + } else if (type == XYEquationCurve::Polar) { uiGeneralTab.lEquation1->setText(QString::fromUtf8("r(φ)")); uiGeneralTab.lEquation2->hide(); uiGeneralTab.teEquation2->hide(); uiGeneralTab.tbFunctions2->hide(); uiGeneralTab.tbConstants2->hide(); uiGeneralTab.lMin->show(); uiGeneralTab.lMax->show(); uiGeneralTab.teMin->show(); uiGeneralTab.teMax->show(); uiGeneralTab.lMin->setText(i18n("φ, min")); uiGeneralTab.lMax->setText(i18n("φ, max")); - } else if (type==XYEquationCurve::Parametric) { + } else if (type == XYEquationCurve::Parametric) { uiGeneralTab.lEquation1->setText("x=f(t)"); uiGeneralTab.lEquation2->setText("y=f(t)"); uiGeneralTab.lEquation2->show(); uiGeneralTab.teEquation2->show(); uiGeneralTab.tbFunctions2->show(); uiGeneralTab.tbConstants2->show(); uiGeneralTab.lMin->show(); uiGeneralTab.lMax->show(); uiGeneralTab.teMin->show(); uiGeneralTab.teMax->show(); uiGeneralTab.lMin->setText(i18n("t, min")); uiGeneralTab.lMax->setText(i18n("t, max")); - } else if (type==XYEquationCurve::Implicit) { + } else if (type == XYEquationCurve::Implicit) { uiGeneralTab.lEquation1->setText("f(x,y)"); uiGeneralTab.lEquation2->hide(); uiGeneralTab.teEquation2->hide(); uiGeneralTab.tbFunctions2->hide(); uiGeneralTab.tbConstants2->hide(); uiGeneralTab.lMin->hide(); uiGeneralTab.lMax->hide(); uiGeneralTab.teMin->hide(); uiGeneralTab.teMax->hide(); } uiGeneralTab.teEquation1->setExpressionType(type); this->enableRecalculate(); } void XYEquationCurveDock::recalculateClicked() { XYEquationCurve::EquationData data; data.type = (XYEquationCurve::EquationType)uiGeneralTab.cbType->currentIndex(); data.expression1 = uiGeneralTab.teEquation1->document()->toPlainText(); data.expression2 = uiGeneralTab.teEquation2->document()->toPlainText(); data.min = uiGeneralTab.teMin->document()->toPlainText(); data.max = uiGeneralTab.teMax->document()->toPlainText(); data.count = uiGeneralTab.sbCount->value(); for (auto* curve : m_curvesList) dynamic_cast(curve)->setEquationData(data); uiGeneralTab.pbRecalculate->setEnabled(false); } void XYEquationCurveDock::showConstants() { QMenu menu; ConstantsWidget constants(&menu); - if (QObject::sender()==uiGeneralTab.tbConstants1) + if (QObject::sender() == uiGeneralTab.tbConstants1) connect(&constants, SIGNAL(constantSelected(QString)), this, SLOT(insertConstant1(QString))); else connect(&constants, SIGNAL(constantSelected(QString)), this, SLOT(insertConstant2(QString))); connect(&constants, SIGNAL(constantSelected(QString)), &menu, SLOT(close())); connect(&constants, SIGNAL(canceled()), &menu, SLOT(close())); - QWidgetAction* widgetAction = new QWidgetAction(this); + auto widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&constants); menu.addAction(widgetAction); - if (QObject::sender()==uiGeneralTab.tbConstants1) { + if (QObject::sender() == uiGeneralTab.tbConstants1) { QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbConstants1->width(),-menu.sizeHint().height()); menu.exec(uiGeneralTab.tbConstants1->mapToGlobal(pos)); } else { QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbConstants2->width(),-menu.sizeHint().height()); menu.exec(uiGeneralTab.tbConstants2->mapToGlobal(pos)); } } void XYEquationCurveDock::showFunctions() { QMenu menu; FunctionsWidget functions(&menu); - if (QObject::sender()==uiGeneralTab.tbFunctions1) + if (QObject::sender() == uiGeneralTab.tbFunctions1) connect(&functions, SIGNAL(functionSelected(QString)), this, SLOT(insertFunction1(QString))); else connect(&functions, SIGNAL(functionSelected(QString)), this, SLOT(insertFunction2(QString))); connect(&functions, SIGNAL(functionSelected(QString)), &menu, SLOT(close())); connect(&functions, SIGNAL(canceled()), &menu, SLOT(close())); - QWidgetAction* widgetAction = new QWidgetAction(this); + auto widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&functions); menu.addAction(widgetAction); - if (QObject::sender()==uiGeneralTab.tbFunctions1) { + if (QObject::sender() == uiGeneralTab.tbFunctions1) { QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbFunctions1->width(),-menu.sizeHint().height()); menu.exec(uiGeneralTab.tbFunctions1->mapToGlobal(pos)); } else { QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbFunctions2->width(),-menu.sizeHint().height()); menu.exec(uiGeneralTab.tbFunctions2->mapToGlobal(pos)); } } void XYEquationCurveDock::insertFunction1(const QString& str) { //TODO: not all functions have only one argument - XYEquationCurve::EquationType type = XYEquationCurve::EquationType(uiGeneralTab.cbType->currentIndex()); - if (type==XYEquationCurve::Cartesian) + const auto type = XYEquationCurve::EquationType(uiGeneralTab.cbType->currentIndex()); + if (type == XYEquationCurve::Cartesian) uiGeneralTab.teEquation1->insertPlainText(str + "(x)"); - else if (type==XYEquationCurve::Polar) + else if (type == XYEquationCurve::Polar) uiGeneralTab.teEquation1->insertPlainText(str + "(phi)"); - else if (type==XYEquationCurve::Parametric) + else if (type == XYEquationCurve::Parametric) uiGeneralTab.teEquation1->insertPlainText(str + "(t)"); } void XYEquationCurveDock::insertConstant1(const QString& str) { uiGeneralTab.teEquation1->insertPlainText(str); } void XYEquationCurveDock::insertFunction2(const QString& str) { //TODO: not all functions have only one argument uiGeneralTab.teEquation2->insertPlainText(str + "(t)"); } void XYEquationCurveDock::insertConstant2(const QString& str) { uiGeneralTab.teEquation2->insertPlainText(str); } void XYEquationCurveDock::enableRecalculate() const { if (m_initializing) return; //check whether the formular expressions are correct bool valid = false; - XYEquationCurve::EquationType type = XYEquationCurve::EquationType(uiGeneralTab.cbType->currentIndex()); - if (type!=XYEquationCurve::Parametric) + const auto type = XYEquationCurve::EquationType(uiGeneralTab.cbType->currentIndex()); + if (type != XYEquationCurve::Parametric) valid = uiGeneralTab.teEquation1->isValid(); else valid = (uiGeneralTab.teEquation1->isValid() && uiGeneralTab.teEquation2->isValid()); valid = (valid && uiGeneralTab.teMin->isValid() && uiGeneralTab.teMax->isValid()); uiGeneralTab.pbRecalculate->setEnabled(valid); } //************************************************************* //*********** SLOTs for changes triggered in XYCurve ********** //************************************************************* //General-Tab void XYEquationCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != uiGeneralTab.leName->text()) { uiGeneralTab.leName->setText(aspect->name()); } else if (aspect->comment() != uiGeneralTab.leComment->text()) { uiGeneralTab.leComment->setText(aspect->comment()); } m_initializing = false; } void XYEquationCurveDock::curveEquationDataChanged(const XYEquationCurve::EquationData& data) { m_initializing = true; uiGeneralTab.cbType->setCurrentIndex(data.type); uiGeneralTab.teEquation1->setText(data.expression1); uiGeneralTab.teEquation2->setText(data.expression2); uiGeneralTab.teMin->setText(data.min); uiGeneralTab.teMax->setText(data.max); uiGeneralTab.sbCount->setValue(data.count); m_initializing = false; } diff --git a/src/kdefrontend/dockwidgets/XYIntegrationCurveDock.cpp b/src/kdefrontend/dockwidgets/XYIntegrationCurveDock.cpp index 9f41e3f33..5f0d86929 100644 --- a/src/kdefrontend/dockwidgets/XYIntegrationCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYIntegrationCurveDock.cpp @@ -1,504 +1,504 @@ /*************************************************************************** File : XYIntegrationCurveDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn) Description : widget for editing properties of integration curves ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "XYIntegrationCurveDock.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/worksheet/plots/cartesian/XYIntegrationCurve.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include #include #include extern "C" { #include "backend/nsl/nsl_int.h" } /*! \class XYIntegrationCurveDock \brief Provides a widget for editing the properties of the XYIntegrationCurves (2D-curves defined by a integration) currently selected in the project explorer. If more then one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ XYIntegrationCurveDock::XYIntegrationCurveDock(QWidget* parent) : XYCurveDock(parent), cbDataSourceCurve(nullptr), cbXDataColumn(nullptr), cbYDataColumn(nullptr), m_integrationCurve(nullptr) { //hide the line connection type ui.cbLineType->setDisabled(true); //remove the tab "Error bars" ui.tabWidget->removeTab(5); } /*! * // Tab "General" */ void XYIntegrationCurveDock::setupGeneral() { QWidget* generalTab = new QWidget(ui.tabGeneral); uiGeneralTab.setupUi(generalTab); - QGridLayout* gridLayout = dynamic_cast(generalTab->layout()); + auto gridLayout = dynamic_cast(generalTab->layout()); if (gridLayout) { gridLayout->setContentsMargins(2,2,2,2); gridLayout->setHorizontalSpacing(2); gridLayout->setVerticalSpacing(2); } uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet")); uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve")); cbDataSourceCurve = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 3); cbXDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 3); cbYDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbYDataColumn, 7, 2, 1, 3); - for (int i=0; i < NSL_INT_NETHOD_COUNT; i++) + for (int i = 0; i < NSL_INT_NETHOD_COUNT; i++) uiGeneralTab.cbMethod->addItem(i18n(nsl_int_method_name[i])); uiGeneralTab.sbMin->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.sbMax->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build")); - QHBoxLayout* layout = new QHBoxLayout(ui.tabGeneral); + auto layout = new QHBoxLayout(ui.tabGeneral); layout->setMargin(0); layout->addWidget(generalTab); //Slots connect( uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYIntegrationCurveDock::nameChanged ); connect( uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYIntegrationCurveDock::commentChanged ); connect( uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( uiGeneralTab.cbDataSourceType, SIGNAL(currentIndexChanged(int)), this, SLOT(dataSourceTypeChanged(int)) ); connect( uiGeneralTab.cbAutoRange, SIGNAL(clicked(bool)), this, SLOT(autoRangeChanged()) ); connect( uiGeneralTab.sbMin, SIGNAL(valueChanged(double)), this, SLOT(xRangeMinChanged()) ); connect( uiGeneralTab.sbMax, SIGNAL(valueChanged(double)), this, SLOT(xRangeMaxChanged()) ); connect( uiGeneralTab.cbMethod, SIGNAL(currentIndexChanged(int)), this, SLOT(methodChanged()) ); connect( uiGeneralTab.cbAbsolute, SIGNAL(clicked(bool)), this, SLOT(absoluteChanged()) ); connect( uiGeneralTab.pbRecalculate, SIGNAL(clicked()), this, SLOT(recalculateClicked()) ); connect( cbDataSourceCurve, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(dataSourceCurveChanged(QModelIndex)) ); connect( cbXDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xDataColumnChanged(QModelIndex)) ); connect( cbYDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yDataColumnChanged(QModelIndex)) ); } void XYIntegrationCurveDock::initGeneralTab() { //if there are more then one curve in the list, disable the tab "general" if (m_curvesList.size()==1) { uiGeneralTab.lName->setEnabled(true); uiGeneralTab.leName->setEnabled(true); uiGeneralTab.lComment->setEnabled(true); uiGeneralTab.leComment->setEnabled(true); uiGeneralTab.leName->setText(m_curve->name()); uiGeneralTab.leComment->setText(m_curve->comment()); }else { uiGeneralTab.lName->setEnabled(false); uiGeneralTab.leName->setEnabled(false); uiGeneralTab.lComment->setEnabled(false); uiGeneralTab.leComment->setEnabled(false); uiGeneralTab.leName->setText(""); uiGeneralTab.leComment->setText(""); } //show the properties of the first curve m_integrationCurve = dynamic_cast(m_curve); uiGeneralTab.cbDataSourceType->setCurrentIndex(m_integrationCurve->dataSourceType()); this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex()); XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_integrationCurve->dataSourceCurve()); XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_integrationCurve->xDataColumn()); XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_integrationCurve->yDataColumn()); uiGeneralTab.cbAutoRange->setChecked(m_integrationData.autoRange); uiGeneralTab.sbMin->setValue(m_integrationData.xRange.first()); uiGeneralTab.sbMax->setValue(m_integrationData.xRange.last()); this->autoRangeChanged(); // update list of selectable types xDataColumnChanged(cbXDataColumn->currentModelIndex()); uiGeneralTab.cbMethod->setCurrentIndex(m_integrationData.method); this->methodChanged(); uiGeneralTab.cbAbsolute->setChecked(m_integrationData.absolute); this->absoluteChanged(); this->showIntegrationResult(); uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); //Slots connect(m_integrationCurve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_integrationCurve, SIGNAL(dataSourceTypeChanged(XYAnalysisCurve::DataSourceType)), this, SLOT(curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType))); connect(m_integrationCurve, SIGNAL(dataSourceCurveChanged(const XYCurve*)), this, SLOT(curveDataSourceCurveChanged(const XYCurve*))); connect(m_integrationCurve, SIGNAL(xDataColumnChanged(const AbstractColumn*)), this, SLOT(curveXDataColumnChanged(const AbstractColumn*))); connect(m_integrationCurve, SIGNAL(yDataColumnChanged(const AbstractColumn*)), this, SLOT(curveYDataColumnChanged(const AbstractColumn*))); connect(m_integrationCurve, SIGNAL(integrationDataChanged(XYIntegrationCurve::IntegrationData)), this, SLOT(curveIntegrationDataChanged(XYIntegrationCurve::IntegrationData))); connect(m_integrationCurve, SIGNAL(sourceDataChanged()), this, SLOT(enableRecalculate())); } void XYIntegrationCurveDock::setModel() { QList list; list<<"Folder"<<"Datapicker"<<"Worksheet"<<"CartesianPlot"<<"XYCurve"; cbDataSourceCurve->setTopLevelClasses(list); QList hiddenAspects; for (auto* curve : m_curvesList) hiddenAspects << curve; cbDataSourceCurve->setHiddenAspects(hiddenAspects); list.clear(); list<<"Folder"<<"Workbook"<<"Datapicker"<<"DatapickerCurve"<<"Spreadsheet" <<"FileDataSource"<<"Column"<<"Worksheet"<<"CartesianPlot"<<"XYFitCurve"; cbXDataColumn->setTopLevelClasses(list); cbYDataColumn->setTopLevelClasses(list); cbDataSourceCurve->setModel(m_aspectTreeModel); cbXDataColumn->setModel(m_aspectTreeModel); cbYDataColumn->setModel(m_aspectTreeModel); XYCurveDock::setModel(); } /*! sets the curves. The properties of the curves in the list \c list can be edited in this widget. */ void XYIntegrationCurveDock::setCurves(QList list) { m_initializing=true; m_curvesList=list; m_curve=list.first(); m_integrationCurve = dynamic_cast(m_curve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); this->setModel(); m_integrationData = m_integrationCurve->integrationData(); initGeneralTab(); initTabs(); m_initializing=false; //hide the "skip gaps" option after the curves were set ui.lLineSkipGaps->hide(); ui.chkLineSkipGaps->hide(); } //************************************************************* //**** SLOTs for changes triggered in XYFitCurveDock ***** //************************************************************* void XYIntegrationCurveDock::nameChanged() { if (m_initializing) return; m_curve->setName(uiGeneralTab.leName->text()); } void XYIntegrationCurveDock::commentChanged() { if (m_initializing) return; m_curve->setComment(uiGeneralTab.leComment->text()); } void XYIntegrationCurveDock::dataSourceTypeChanged(int index) { - XYAnalysisCurve::DataSourceType type = (XYAnalysisCurve::DataSourceType)index; + const auto type = (XYAnalysisCurve::DataSourceType)index; if (type == XYAnalysisCurve::DataSourceSpreadsheet) { uiGeneralTab.lDataSourceCurve->hide(); cbDataSourceCurve->hide(); uiGeneralTab.lXColumn->show(); cbXDataColumn->show(); uiGeneralTab.lYColumn->show(); cbYDataColumn->show(); } else { uiGeneralTab.lDataSourceCurve->show(); cbDataSourceCurve->show(); uiGeneralTab.lXColumn->hide(); cbXDataColumn->hide(); uiGeneralTab.lYColumn->hide(); cbYDataColumn->hide(); } if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataSourceType(type); } void XYIntegrationCurveDock::dataSourceCurveChanged(const QModelIndex& index) { - AbstractAspect* aspect = static_cast(index.internalPointer()); - XYCurve* dataSourceCurve = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto dataSourceCurve = dynamic_cast(aspect); // disable integration orders and accuracies that need more data points this->updateSettings(dataSourceCurve->xColumn()); if (m_initializing) return; for (auto* curve : m_curvesList) dynamic_cast(curve)->setDataSourceCurve(dataSourceCurve); } void XYIntegrationCurveDock::xDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); for (auto* curve : m_curvesList) dynamic_cast(curve)->setXDataColumn(column); if (column != nullptr) { if (uiGeneralTab.cbAutoRange->isChecked()) { uiGeneralTab.sbMin->setValue(column->minimum()); uiGeneralTab.sbMax->setValue(column->maximum()); } // disable integration methods that need more data points this->updateSettings(column); } } /*! * disable deriv orders and accuracies that need more data points */ void XYIntegrationCurveDock::updateSettings(const AbstractColumn* column) { if (!column) return; //TODO // size_t n=0; // for (int row=0; row < column->rowCount(); row++) // if (!std::isnan(column->valueAt(row)) && !column->isMasked(row)) // n++; } void XYIntegrationCurveDock::yDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); - AbstractColumn* column = dynamic_cast(aspect); + auto aspect = static_cast(index.internalPointer()); + auto column = dynamic_cast(aspect); for (auto* curve : m_curvesList) dynamic_cast(curve)->setYDataColumn(column); } void XYIntegrationCurveDock::autoRangeChanged() { bool autoRange = uiGeneralTab.cbAutoRange->isChecked(); m_integrationData.autoRange = autoRange; if (autoRange) { uiGeneralTab.lMin->setEnabled(false); uiGeneralTab.sbMin->setEnabled(false); uiGeneralTab.lMax->setEnabled(false); uiGeneralTab.sbMax->setEnabled(false); const AbstractColumn* xDataColumn = nullptr; if (m_integrationCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) xDataColumn = m_integrationCurve->xDataColumn(); else { if (m_integrationCurve->dataSourceCurve()) xDataColumn = m_integrationCurve->dataSourceCurve()->xColumn(); } if (xDataColumn) { uiGeneralTab.sbMin->setValue(xDataColumn->minimum()); uiGeneralTab.sbMax->setValue(xDataColumn->maximum()); } } else { uiGeneralTab.lMin->setEnabled(true); uiGeneralTab.sbMin->setEnabled(true); uiGeneralTab.lMax->setEnabled(true); uiGeneralTab.sbMax->setEnabled(true); } } void XYIntegrationCurveDock::xRangeMinChanged() { double xMin = uiGeneralTab.sbMin->value(); m_integrationData.xRange.first() = xMin; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYIntegrationCurveDock::xRangeMaxChanged() { double xMax = uiGeneralTab.sbMax->value(); m_integrationData.xRange.last() = xMax; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYIntegrationCurveDock::methodChanged() { - nsl_int_method_type method = (nsl_int_method_type)uiGeneralTab.cbMethod->currentIndex(); + const auto method = (nsl_int_method_type)uiGeneralTab.cbMethod->currentIndex(); m_integrationData.method = method; // update absolute option switch (method) { case nsl_int_method_rectangle: case nsl_int_method_trapezoid: uiGeneralTab.cbAbsolute->setEnabled(true); break; case nsl_int_method_simpson: case nsl_int_method_simpson_3_8: uiGeneralTab.cbAbsolute->setChecked(false); uiGeneralTab.cbAbsolute->setEnabled(false); } uiGeneralTab.pbRecalculate->setEnabled(true); } void XYIntegrationCurveDock::absoluteChanged() { bool absolute = uiGeneralTab.cbAbsolute->isChecked(); m_integrationData.absolute = absolute; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYIntegrationCurveDock::recalculateClicked() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); for (auto* curve : m_curvesList) dynamic_cast(curve)->setIntegrationData(m_integrationData); uiGeneralTab.pbRecalculate->setEnabled(false); emit info(i18n("Integration status: %1", m_integrationCurve->integrationResult().status)); QApplication::restoreOverrideCursor(); } void XYIntegrationCurveDock::enableRecalculate() const { if (m_initializing) return; //no integration possible without the x- and y-data bool hasSourceData = false; if (m_integrationCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) { AbstractAspect* aspectX = static_cast(cbXDataColumn->currentModelIndex().internalPointer()); AbstractAspect* aspectY = static_cast(cbYDataColumn->currentModelIndex().internalPointer()); hasSourceData = (aspectX!=nullptr && aspectY!=nullptr); } else { hasSourceData = (m_integrationCurve->dataSourceCurve() != nullptr); } uiGeneralTab.pbRecalculate->setEnabled(hasSourceData); } /*! * show the result and details of the integration */ void XYIntegrationCurveDock::showIntegrationResult() { const XYIntegrationCurve::IntegrationResult& integrationResult = m_integrationCurve->integrationResult(); if (!integrationResult.available) { uiGeneralTab.teResult->clear(); return; } QString str = i18n("status: %1", integrationResult.status) + "
"; if (!integrationResult.valid) { uiGeneralTab.teResult->setText(str); return; //result is not valid, there was an error which is shown in the status-string, nothing to show more. } if (integrationResult.elapsedTime>1000) str += i18n("calculation time: %1 s", QString::number(integrationResult.elapsedTime/1000)) + "
"; else str += i18n("calculation time: %1 ms", QString::number(integrationResult.elapsedTime)) + "
"; str += i18n("value: %1", QString::number(integrationResult.value)) + "
"; str += "

"; uiGeneralTab.teResult->setText(str); //enable the "recalculate"-button if the source data was changed since the last integration uiGeneralTab.pbRecalculate->setEnabled(m_integrationCurve->isSourceDataChangedSinceLastRecalc()); } //************************************************************* //*********** SLOTs for changes triggered in XYCurve ********** //************************************************************* //General-Tab void XYIntegrationCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != uiGeneralTab.leName->text()) uiGeneralTab.leName->setText(aspect->name()); else if (aspect->comment() != uiGeneralTab.leComment->text()) uiGeneralTab.leComment->setText(aspect->comment()); m_initializing = false; } void XYIntegrationCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) { m_initializing = true; uiGeneralTab.cbDataSourceType->setCurrentIndex(type); m_initializing = false; } void XYIntegrationCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve); m_initializing = false; } void XYIntegrationCurveDock::curveXDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column); m_initializing = false; } void XYIntegrationCurveDock::curveYDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column); m_initializing = false; } void XYIntegrationCurveDock::curveIntegrationDataChanged(const XYIntegrationCurve::IntegrationData& integrationData) { m_initializing = true; m_integrationData = integrationData; uiGeneralTab.cbMethod->setCurrentIndex(m_integrationData.method); this->methodChanged(); uiGeneralTab.cbAbsolute->setChecked(m_integrationData.absolute); this->absoluteChanged(); this->showIntegrationResult(); m_initializing = false; } void XYIntegrationCurveDock::dataChanged() { this->enableRecalculate(); } diff --git a/src/kdefrontend/dockwidgets/XYInterpolationCurveDock.cpp b/src/kdefrontend/dockwidgets/XYInterpolationCurveDock.cpp index 40e71b014..1f0265e9c 100644 --- a/src/kdefrontend/dockwidgets/XYInterpolationCurveDock.cpp +++ b/src/kdefrontend/dockwidgets/XYInterpolationCurveDock.cpp @@ -1,735 +1,735 @@ /*************************************************************************** File : XYInterpolationCurveDock.cpp Project : LabPlot -------------------------------------------------------------------- Copyright : (C) 2016 Stefan Gerlach (stefan.gerlach@uni.kn) Copyright : (C) 20016-2017 Alexander Semke (alexander.semke@web.de) Description : widget for editing properties of interpolation curves ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "XYInterpolationCurveDock.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/worksheet/plots/cartesian/XYInterpolationCurve.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include #include #include extern "C" { #include // gsl_interp types } #include // isnan /*! \class XYInterpolationCurveDock \brief Provides a widget for editing the properties of the XYInterpolationCurves (2D-curves defined by an interpolation) currently selected in the project explorer. If more then one curves are set, the properties of the first column are shown. The changes of the properties are applied to all curves. The exclusions are the name, the comment and the datasets (columns) of the curves - these properties can only be changed if there is only one single curve. \ingroup kdefrontend */ XYInterpolationCurveDock::XYInterpolationCurveDock(QWidget* parent): XYCurveDock(parent), cbDataSourceCurve(nullptr), cbXDataColumn(nullptr), cbYDataColumn(nullptr), m_interpolationCurve(nullptr), dataPoints(0) { //hide the line connection type ui.cbLineType->setDisabled(true); //remove the tab "Error bars" ui.tabWidget->removeTab(5); } /*! * // Tab "General" */ void XYInterpolationCurveDock::setupGeneral() { QWidget* generalTab = new QWidget(ui.tabGeneral); uiGeneralTab.setupUi(generalTab); - QGridLayout* gridLayout = dynamic_cast(generalTab->layout()); + auto gridLayout = dynamic_cast(generalTab->layout()); if (gridLayout) { gridLayout->setContentsMargins(2,2,2,2); gridLayout->setHorizontalSpacing(2); gridLayout->setVerticalSpacing(2); } uiGeneralTab.cbDataSourceType->addItem(i18n("Spreadsheet")); uiGeneralTab.cbDataSourceType->addItem(i18n("XY-Curve")); cbDataSourceCurve = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbDataSourceCurve, 5, 2, 1, 2); cbXDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbXDataColumn, 6, 2, 1, 2); cbYDataColumn = new TreeViewComboBox(generalTab); gridLayout->addWidget(cbYDataColumn, 7, 2, 1, 2); for (int i=0; i < NSL_INTERP_TYPE_COUNT; i++) uiGeneralTab.cbType->addItem(i18n(nsl_interp_type_name[i])); #if GSL_MAJOR_VERSION < 2 // disable Steffen spline item const QStandardItemModel* model = qobject_cast(uiGeneralTab.cbType->model()); QStandardItem* item = model->item(nsl_interp_type_steffen); item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); #endif for (int i=0; i < NSL_INTERP_PCH_VARIANT_COUNT; i++) uiGeneralTab.cbVariant->addItem(i18n(nsl_interp_pch_variant_name[i])); for (int i=0; i < NSL_INTERP_EVALUATE_COUNT; i++) uiGeneralTab.cbEval->addItem(i18n(nsl_interp_evaluate_name[i])); uiGeneralTab.cbPointsMode->addItem(i18n("Auto (5x data points)")); uiGeneralTab.cbPointsMode->addItem(i18n("Multiple of data points")); uiGeneralTab.cbPointsMode->addItem(i18n("Custom")); uiGeneralTab.sbMin->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.sbMax->setRange(-std::numeric_limits::max(), std::numeric_limits::max()); uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build")); - QHBoxLayout* layout = new QHBoxLayout(ui.tabGeneral); + auto layout = new QHBoxLayout(ui.tabGeneral); layout->setMargin(0); layout->addWidget(generalTab); //Slots connect( uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYInterpolationCurveDock::nameChanged ); connect( uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYInterpolationCurveDock::commentChanged ); connect( uiGeneralTab.chkVisible, SIGNAL(clicked(bool)), this, SLOT(visibilityChanged(bool)) ); connect( uiGeneralTab.cbDataSourceType, SIGNAL(currentIndexChanged(int)), this, SLOT(dataSourceTypeChanged(int)) ); connect( uiGeneralTab.cbAutoRange, SIGNAL(clicked(bool)), this, SLOT(autoRangeChanged()) ); connect( uiGeneralTab.sbMin, SIGNAL(valueChanged(double)), this, SLOT(xRangeMinChanged()) ); connect( uiGeneralTab.sbMax, SIGNAL(valueChanged(double)), this, SLOT(xRangeMaxChanged()) ); connect( uiGeneralTab.cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged()) ); connect( uiGeneralTab.cbVariant, SIGNAL(currentIndexChanged(int)), this, SLOT(variantChanged()) ); connect( uiGeneralTab.sbTension, SIGNAL(valueChanged(double)), this, SLOT(tensionChanged()) ); connect( uiGeneralTab.sbContinuity, SIGNAL(valueChanged(double)), this, SLOT(continuityChanged()) ); connect( uiGeneralTab.sbBias, SIGNAL(valueChanged(double)), this, SLOT(biasChanged()) ); connect( uiGeneralTab.cbEval, SIGNAL(currentIndexChanged(int)), this, SLOT(evaluateChanged()) ); connect( uiGeneralTab.sbPoints, SIGNAL(valueChanged(double)), this, SLOT(numberOfPointsChanged()) ); connect( uiGeneralTab.cbPointsMode, SIGNAL(currentIndexChanged(int)), this, SLOT(pointsModeChanged()) ); connect( uiGeneralTab.pbRecalculate, SIGNAL(clicked()), this, SLOT(recalculateClicked()) ); connect( cbDataSourceCurve, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(dataSourceCurveChanged(QModelIndex)) ); connect( cbXDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(xDataColumnChanged(QModelIndex)) ); connect( cbYDataColumn, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(yDataColumnChanged(QModelIndex)) ); } void XYInterpolationCurveDock::initGeneralTab() { //if there are more then one curve in the list, disable the tab "general" if (m_curvesList.size()==1) { uiGeneralTab.lName->setEnabled(true); uiGeneralTab.leName->setEnabled(true); uiGeneralTab.lComment->setEnabled(true); uiGeneralTab.leComment->setEnabled(true); uiGeneralTab.leName->setText(m_curve->name()); uiGeneralTab.leComment->setText(m_curve->comment()); }else { uiGeneralTab.lName->setEnabled(false); uiGeneralTab.leName->setEnabled(false); uiGeneralTab.lComment->setEnabled(false); uiGeneralTab.leComment->setEnabled(false); uiGeneralTab.leName->setText(""); uiGeneralTab.leComment->setText(""); } //show the properties of the first curve m_interpolationCurve = dynamic_cast(m_curve); Q_ASSERT(m_interpolationCurve); uiGeneralTab.cbDataSourceType->setCurrentIndex(m_interpolationCurve->dataSourceType()); this->dataSourceTypeChanged(uiGeneralTab.cbDataSourceType->currentIndex()); XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, m_interpolationCurve->dataSourceCurve()); XYCurveDock::setModelIndexFromAspect(cbXDataColumn, m_interpolationCurve->xDataColumn()); XYCurveDock::setModelIndexFromAspect(cbYDataColumn, m_interpolationCurve->yDataColumn()); uiGeneralTab.cbAutoRange->setChecked(m_interpolationData.autoRange); uiGeneralTab.sbMin->setValue(m_interpolationData.xRange.first()); uiGeneralTab.sbMax->setValue(m_interpolationData.xRange.last()); this->autoRangeChanged(); // update list of selectable types xDataColumnChanged(cbXDataColumn->currentModelIndex()); uiGeneralTab.cbType->setCurrentIndex(m_interpolationData.type); this->typeChanged(); uiGeneralTab.cbVariant->setCurrentIndex(m_interpolationData.variant); this->variantChanged(); uiGeneralTab.sbTension->setValue(m_interpolationData.tension); uiGeneralTab.sbContinuity->setValue(m_interpolationData.continuity); uiGeneralTab.sbBias->setValue(m_interpolationData.bias); uiGeneralTab.cbEval->setCurrentIndex(m_interpolationData.evaluate); if (m_interpolationData.pointsMode == XYInterpolationCurve::Multiple) uiGeneralTab.sbPoints->setValue(m_interpolationData.npoints/5.); else uiGeneralTab.sbPoints->setValue(m_interpolationData.npoints); uiGeneralTab.cbPointsMode->setCurrentIndex(m_interpolationData.pointsMode); this->showInterpolationResult(); uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() ); //Slots connect(m_interpolationCurve, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(curveDescriptionChanged(const AbstractAspect*))); connect(m_interpolationCurve, SIGNAL(dataSourceTypeChanged(XYAnalysisCurve::DataSourceType)), this, SLOT(curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType))); connect(m_interpolationCurve, SIGNAL(dataSourceCurveChanged(const XYCurve*)), this, SLOT(curveDataSourceCurveChanged(const XYCurve*))); connect(m_interpolationCurve, SIGNAL(xDataColumnChanged(const AbstractColumn*)), this, SLOT(curveXDataColumnChanged(const AbstractColumn*))); connect(m_interpolationCurve, SIGNAL(yDataColumnChanged(const AbstractColumn*)), this, SLOT(curveYDataColumnChanged(const AbstractColumn*))); connect(m_interpolationCurve, SIGNAL(interpolationDataChanged(XYInterpolationCurve::InterpolationData)), this, SLOT(curveInterpolationDataChanged(XYInterpolationCurve::InterpolationData))); connect(m_interpolationCurve, SIGNAL(sourceDataChanged()), this, SLOT(enableRecalculate())); } void XYInterpolationCurveDock::setModel() { QList list; list<<"Folder"<<"Datapicker"<<"Worksheet"<<"CartesianPlot"<<"XYCurve"; cbDataSourceCurve->setTopLevelClasses(list); QList hiddenAspects; for(XYCurve* curve: m_curvesList) hiddenAspects << curve; cbDataSourceCurve->setHiddenAspects(hiddenAspects); list.clear(); list<<"Folder"<<"Workbook"<<"Datapicker"<<"DatapickerCurve"<<"Spreadsheet" <<"FileDataSource"<<"Column"<<"Worksheet"<<"CartesianPlot"<<"XYFitCurve"<<"CantorWorksheet"; cbXDataColumn->setTopLevelClasses(list); cbYDataColumn->setTopLevelClasses(list); cbXDataColumn->setModel(m_aspectTreeModel); cbYDataColumn->setModel(m_aspectTreeModel); XYCurveDock::setModel(); } /*! sets the curves. The properties of the curves in the list \c list can be edited in this widget. */ void XYInterpolationCurveDock::setCurves(QList list) { m_initializing=true; m_curvesList=list; m_curve=list.first(); m_interpolationCurve = dynamic_cast(m_curve); Q_ASSERT(m_interpolationCurve); m_aspectTreeModel = new AspectTreeModel(m_curve->project()); this->setModel(); m_interpolationData = m_interpolationCurve->interpolationData(); initGeneralTab(); initTabs(); m_initializing=false; //hide the "skip gaps" option after the curves were set ui.lLineSkipGaps->hide(); ui.chkLineSkipGaps->hide(); } //************************************************************* //**** SLOTs for changes triggered in XYFitCurveDock ***** //************************************************************* void XYInterpolationCurveDock::nameChanged() { if (m_initializing) return; m_curve->setName(uiGeneralTab.leName->text()); } void XYInterpolationCurveDock::commentChanged() { if (m_initializing) return; m_curve->setComment(uiGeneralTab.leComment->text()); } void XYInterpolationCurveDock::dataSourceTypeChanged(int index) { - XYAnalysisCurve::DataSourceType type = (XYAnalysisCurve::DataSourceType)index; + const auto type = (XYAnalysisCurve::DataSourceType)index; if (type == XYAnalysisCurve::DataSourceSpreadsheet) { uiGeneralTab.lDataSourceCurve->hide(); cbDataSourceCurve->hide(); uiGeneralTab.lXColumn->show(); cbXDataColumn->show(); uiGeneralTab.lYColumn->show(); cbYDataColumn->show(); } else { uiGeneralTab.lDataSourceCurve->show(); cbDataSourceCurve->show(); uiGeneralTab.lXColumn->hide(); cbXDataColumn->hide(); uiGeneralTab.lYColumn->hide(); cbYDataColumn->hide(); } if (m_initializing) return; for(XYCurve* curve: m_curvesList) dynamic_cast(curve)->setDataSourceType(type); } void XYInterpolationCurveDock::dataSourceCurveChanged(const QModelIndex& index) { - AbstractAspect* aspect = static_cast(index.internalPointer()); + auto aspect = static_cast(index.internalPointer()); XYCurve* dataSourceCurve = nullptr; if (aspect) { dataSourceCurve = dynamic_cast(aspect); Q_ASSERT(dataSourceCurve); } // disable types that need more data points this->updateSettings(dataSourceCurve->xColumn()); if (m_initializing) return; for(XYCurve* curve: m_curvesList) dynamic_cast(curve)->setDataSourceCurve(dataSourceCurve); } void XYInterpolationCurveDock::xDataColumnChanged(const QModelIndex& index) { - AbstractAspect* aspect = static_cast(index.internalPointer()); + auto aspect = static_cast(index.internalPointer()); AbstractColumn* column = nullptr; if (aspect) { column = dynamic_cast(aspect); Q_ASSERT(column); } this->updateSettings(column); if (m_initializing) return; for(XYCurve* curve: m_curvesList) dynamic_cast(curve)->setXDataColumn(column); } void XYInterpolationCurveDock::updateSettings(const AbstractColumn* column) { if (!column) return; // disable types that need more data points if (uiGeneralTab.cbAutoRange->isChecked()) { uiGeneralTab.sbMin->setValue(column->minimum()); uiGeneralTab.sbMax->setValue(column->maximum()); } - unsigned int n=0; - for (int row=0; row < column->rowCount(); row++) + unsigned int n = 0; + for (int row = 0; row < column->rowCount(); row++) if (!std::isnan(column->valueAt(row)) && !column->isMasked(row)) n++; dataPoints = n; if(m_interpolationData.pointsMode == XYInterpolationCurve::Auto) pointsModeChanged(); - const QStandardItemModel* model = qobject_cast(uiGeneralTab.cbType->model()); + const auto model = qobject_cast(uiGeneralTab.cbType->model()); QStandardItem* item = model->item(nsl_interp_type_polynomial); if (dataPoints < gsl_interp_type_min_size(gsl_interp_polynomial) || dataPoints > 100) { // not good for many points item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbType->currentIndex() == nsl_interp_type_polynomial) uiGeneralTab.cbType->setCurrentIndex(0); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = model->item(nsl_interp_type_cspline); if (dataPoints < gsl_interp_type_min_size(gsl_interp_cspline)) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbType->currentIndex() == nsl_interp_type_cspline) uiGeneralTab.cbType->setCurrentIndex(0); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = model->item(nsl_interp_type_cspline_periodic); if (dataPoints < gsl_interp_type_min_size(gsl_interp_cspline_periodic)) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbType->currentIndex() == nsl_interp_type_cspline_periodic) uiGeneralTab.cbType->setCurrentIndex(0); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = model->item(nsl_interp_type_akima); if (dataPoints < gsl_interp_type_min_size(gsl_interp_akima)) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbType->currentIndex() == nsl_interp_type_akima) uiGeneralTab.cbType->setCurrentIndex(0); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); item = model->item(nsl_interp_type_akima_periodic); if (dataPoints < gsl_interp_type_min_size(gsl_interp_akima_periodic)) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbType->currentIndex() == nsl_interp_type_akima_periodic) uiGeneralTab.cbType->setCurrentIndex(0); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); #if GSL_MAJOR_VERSION >= 2 item = model->item(nsl_interp_type_steffen); if (dataPoints < gsl_interp_type_min_size(gsl_interp_steffen)) { item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled)); if (uiGeneralTab.cbType->currentIndex() == nsl_interp_type_steffen) uiGeneralTab.cbType->setCurrentIndex(0); } else item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); #endif // own types work with 2 or more data points } void XYInterpolationCurveDock::yDataColumnChanged(const QModelIndex& index) { if (m_initializing) return; - AbstractAspect* aspect = static_cast(index.internalPointer()); + auto aspect = static_cast(index.internalPointer()); AbstractColumn* column = nullptr; if (aspect) { column = dynamic_cast(aspect); Q_ASSERT(column); } for(XYCurve* curve: m_curvesList) dynamic_cast(curve)->setYDataColumn(column); } void XYInterpolationCurveDock::autoRangeChanged() { bool autoRange = uiGeneralTab.cbAutoRange->isChecked(); m_interpolationData.autoRange = autoRange; if (autoRange) { uiGeneralTab.lMin->setEnabled(false); uiGeneralTab.sbMin->setEnabled(false); uiGeneralTab.lMax->setEnabled(false); uiGeneralTab.sbMax->setEnabled(false); const AbstractColumn* xDataColumn = nullptr; if (m_interpolationCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) xDataColumn = m_interpolationCurve->xDataColumn(); else { if (m_interpolationCurve->dataSourceCurve()) xDataColumn = m_interpolationCurve->dataSourceCurve()->xColumn(); } if (xDataColumn) { uiGeneralTab.sbMin->setValue(xDataColumn->minimum()); uiGeneralTab.sbMax->setValue(xDataColumn->maximum()); } } else { uiGeneralTab.lMin->setEnabled(true); uiGeneralTab.sbMin->setEnabled(true); uiGeneralTab.lMax->setEnabled(true); uiGeneralTab.sbMax->setEnabled(true); } } void XYInterpolationCurveDock::xRangeMinChanged() { double xMin = uiGeneralTab.sbMin->value(); m_interpolationData.xRange.first() = xMin; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::xRangeMaxChanged() { double xMax = uiGeneralTab.sbMax->value(); m_interpolationData.xRange.last() = xMax; uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::typeChanged() { - nsl_interp_type type = (nsl_interp_type)uiGeneralTab.cbType->currentIndex(); + const auto type = (nsl_interp_type)uiGeneralTab.cbType->currentIndex(); m_interpolationData.type = type; switch (type) { case nsl_interp_type_pch: uiGeneralTab.lVariant->show(); uiGeneralTab.cbVariant->show(); break; case nsl_interp_type_linear: case nsl_interp_type_polynomial: case nsl_interp_type_cspline: case nsl_interp_type_cspline_periodic: case nsl_interp_type_akima: case nsl_interp_type_akima_periodic: case nsl_interp_type_steffen: case nsl_interp_type_cosine: case nsl_interp_type_exponential: case nsl_interp_type_rational: uiGeneralTab.lVariant->hide(); uiGeneralTab.cbVariant->hide(); uiGeneralTab.cbVariant->setCurrentIndex(nsl_interp_pch_variant_finite_difference); uiGeneralTab.lParameter->hide(); uiGeneralTab.lTension->hide(); uiGeneralTab.sbTension->hide(); uiGeneralTab.lContinuity->hide(); uiGeneralTab.sbContinuity->hide(); uiGeneralTab.lBias->hide(); uiGeneralTab.sbBias->hide(); } uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::variantChanged() { - nsl_interp_pch_variant variant = (nsl_interp_pch_variant)uiGeneralTab.cbVariant->currentIndex(); + const auto variant = (nsl_interp_pch_variant)uiGeneralTab.cbVariant->currentIndex(); m_interpolationData.variant = variant; switch (variant) { case nsl_interp_pch_variant_finite_difference: uiGeneralTab.lParameter->hide(); uiGeneralTab.lTension->hide(); uiGeneralTab.sbTension->hide(); uiGeneralTab.lContinuity->hide(); uiGeneralTab.sbContinuity->hide(); uiGeneralTab.lBias->hide(); uiGeneralTab.sbBias->hide(); break; case nsl_interp_pch_variant_catmull_rom: uiGeneralTab.lParameter->show(); uiGeneralTab.lTension->show(); uiGeneralTab.sbTension->show(); uiGeneralTab.sbTension->setEnabled(false); uiGeneralTab.sbTension->setValue(0.0); uiGeneralTab.lContinuity->hide(); uiGeneralTab.sbContinuity->hide(); uiGeneralTab.lBias->hide(); uiGeneralTab.sbBias->hide(); break; case nsl_interp_pch_variant_cardinal: uiGeneralTab.lParameter->show(); uiGeneralTab.lTension->show(); uiGeneralTab.sbTension->show(); uiGeneralTab.sbTension->setEnabled(true); uiGeneralTab.lContinuity->hide(); uiGeneralTab.sbContinuity->hide(); uiGeneralTab.lBias->hide(); uiGeneralTab.sbBias->hide(); break; case nsl_interp_pch_variant_kochanek_bartels: uiGeneralTab.lParameter->show(); uiGeneralTab.lTension->show(); uiGeneralTab.sbTension->show(); uiGeneralTab.sbTension->setEnabled(true); uiGeneralTab.lContinuity->show(); uiGeneralTab.sbContinuity->show(); uiGeneralTab.lBias->show(); uiGeneralTab.sbBias->show(); break; } uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::tensionChanged() { m_interpolationData.tension = uiGeneralTab.sbTension->value(); uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::continuityChanged() { m_interpolationData.continuity = uiGeneralTab.sbContinuity->value(); uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::biasChanged() { m_interpolationData.bias = uiGeneralTab.sbBias->value(); uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::evaluateChanged() { m_interpolationData.evaluate = (nsl_interp_evaluate)uiGeneralTab.cbEval->currentIndex(); uiGeneralTab.pbRecalculate->setEnabled(true); } void XYInterpolationCurveDock::pointsModeChanged() { - XYInterpolationCurve::PointsMode mode = (XYInterpolationCurve::PointsMode)uiGeneralTab.cbPointsMode->currentIndex(); + const auto mode = (XYInterpolationCurve::PointsMode)uiGeneralTab.cbPointsMode->currentIndex(); switch (mode) { case XYInterpolationCurve::Auto: uiGeneralTab.sbPoints->setEnabled(false); uiGeneralTab.sbPoints->setDecimals(0); uiGeneralTab.sbPoints->setSingleStep(1.0); uiGeneralTab.sbPoints->setValue(5*dataPoints); break; case XYInterpolationCurve::Multiple: uiGeneralTab.sbPoints->setEnabled(true); if(m_interpolationData.pointsMode != XYInterpolationCurve::Multiple && dataPoints > 0) { uiGeneralTab.sbPoints->setDecimals(2); uiGeneralTab.sbPoints->setValue(uiGeneralTab.sbPoints->value()/(double)dataPoints); uiGeneralTab.sbPoints->setSingleStep(0.01); } break; case XYInterpolationCurve::Custom: uiGeneralTab.sbPoints->setEnabled(true); if(m_interpolationData.pointsMode == XYInterpolationCurve::Multiple) { uiGeneralTab.sbPoints->setDecimals(0); uiGeneralTab.sbPoints->setSingleStep(1.0); uiGeneralTab.sbPoints->setValue(uiGeneralTab.sbPoints->value()*dataPoints); } break; } m_interpolationData.pointsMode = mode; } void XYInterpolationCurveDock::numberOfPointsChanged() { if(uiGeneralTab.cbPointsMode->currentIndex() == XYInterpolationCurve::Multiple) m_interpolationData.npoints = uiGeneralTab.sbPoints->value()*dataPoints; else m_interpolationData.npoints = uiGeneralTab.sbPoints->value(); // warn if points is smaller than data points QPalette palette = uiGeneralTab.sbPoints->palette(); if(m_interpolationData.npoints < dataPoints) palette.setColor(QPalette::Text, Qt::red); else palette.setColor(QPalette::Text, Qt::black); uiGeneralTab.sbPoints->setPalette(palette); enableRecalculate(); } void XYInterpolationCurveDock::recalculateClicked() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); for(XYCurve* curve: m_curvesList) dynamic_cast(curve)->setInterpolationData(m_interpolationData); uiGeneralTab.pbRecalculate->setEnabled(false); emit info(i18n("Interpolation status: %1", m_interpolationCurve->interpolationResult().status)); QApplication::restoreOverrideCursor(); } void XYInterpolationCurveDock::enableRecalculate() const { if (m_initializing) return; //no interpolation possible without the x- and y-data bool hasSourceData = false; if (m_interpolationCurve->dataSourceType() == XYAnalysisCurve::DataSourceSpreadsheet) { AbstractAspect* aspectX = static_cast(cbXDataColumn->currentModelIndex().internalPointer()); AbstractAspect* aspectY = static_cast(cbYDataColumn->currentModelIndex().internalPointer()); hasSourceData = (aspectX!=nullptr && aspectY!=nullptr); } else { hasSourceData = (m_interpolationCurve->dataSourceCurve() != nullptr); } uiGeneralTab.pbRecalculate->setEnabled(hasSourceData); } /*! * show the result and details of the interpolation */ void XYInterpolationCurveDock::showInterpolationResult() { const XYInterpolationCurve::InterpolationResult& interpolationResult = m_interpolationCurve->interpolationResult(); if (!interpolationResult.available) { uiGeneralTab.teResult->clear(); return; } QString str = i18n("status: %1", interpolationResult.status) + "
"; if (!interpolationResult.valid) { uiGeneralTab.teResult->setText(str); return; //result is not valid, there was an error which is shown in the status-string, nothing to show more. } if (interpolationResult.elapsedTime>1000) str += i18n("calculation time: %1 s", QString::number(interpolationResult.elapsedTime/1000)) + "
"; else str += i18n("calculation time: %1 ms", QString::number(interpolationResult.elapsedTime)) + "
"; str += "

"; uiGeneralTab.teResult->setText(str); //enable the "recalculate"-button if the source data was changed since the last interpolation uiGeneralTab.pbRecalculate->setEnabled(m_interpolationCurve->isSourceDataChangedSinceLastRecalc()); } //************************************************************* //*********** SLOTs for changes triggered in XYCurve ********** //************************************************************* //General-Tab void XYInterpolationCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) { if (m_curve != aspect) return; m_initializing = true; if (aspect->name() != uiGeneralTab.leName->text()) { uiGeneralTab.leName->setText(aspect->name()); } else if (aspect->comment() != uiGeneralTab.leComment->text()) { uiGeneralTab.leComment->setText(aspect->comment()); } m_initializing = false; } void XYInterpolationCurveDock::curveDataSourceTypeChanged(XYAnalysisCurve::DataSourceType type) { m_initializing = true; uiGeneralTab.cbDataSourceType->setCurrentIndex(type); m_initializing = false; } void XYInterpolationCurveDock::curveDataSourceCurveChanged(const XYCurve* curve) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbDataSourceCurve, curve); m_initializing = false; } void XYInterpolationCurveDock::curveXDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbXDataColumn, column); m_initializing = false; } void XYInterpolationCurveDock::curveYDataColumnChanged(const AbstractColumn* column) { m_initializing = true; XYCurveDock::setModelIndexFromAspect(cbYDataColumn, column); m_initializing = false; } void XYInterpolationCurveDock::curveInterpolationDataChanged(const XYInterpolationCurve::InterpolationData& data) { m_initializing = true; m_interpolationData = data; uiGeneralTab.cbType->setCurrentIndex(m_interpolationData.type); this->typeChanged(); this->showInterpolationResult(); m_initializing = false; } void XYInterpolationCurveDock::dataChanged() { this->enableRecalculate(); }