"Fossies" - the Fresh Open Source Software Archive

Member "labplot-2.8.2/src/kdefrontend/dockwidgets/XYEquationCurveDock.cpp" (24 Feb 2021, 15538 Bytes) of package /linux/privat/labplot-2.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "XYEquationCurveDock.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8.1_vs_2.8.2.

    1 /***************************************************************************
    2     File             : XYEquationCurveDock.cpp
    3     Project          : LabPlot
    4     --------------------------------------------------------------------
    5     Copyright        : (C) 2014-2021 Alexander Semke (alexander.semke@web.de)
    6     Description      : widget for editing properties of equation curves
    7 
    8  ***************************************************************************/
    9 
   10 /***************************************************************************
   11  *                                                                         *
   12  *  This program is free software; you can redistribute it and/or modify   *
   13  *  it under the terms of the GNU General Public License as published by   *
   14  *  the Free Software Foundation; either version 2 of the License, or      *
   15  *  (at your option) any later version.                                    *
   16  *                                                                         *
   17  *  This program is distributed in the hope that it will be useful,        *
   18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
   19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
   20  *  GNU General Public License for more details.                           *
   21  *                                                                         *
   22  *   You should have received a copy of the GNU General Public License     *
   23  *   along with this program; if not, write to the Free Software           *
   24  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
   25  *   Boston, MA  02110-1301  USA                                           *
   26  *                                                                         *
   27  ***************************************************************************/
   28 
   29 #include "XYEquationCurveDock.h"
   30 #include "backend/core/AspectTreeModel.h"
   31 #include "backend/core/Project.h"
   32 #include "backend/worksheet/plots/cartesian/XYEquationCurve.h"
   33 #include "backend/gsl/ExpressionParser.h"
   34 #include "kdefrontend/widgets/ConstantsWidget.h"
   35 #include "kdefrontend/widgets/FunctionsWidget.h"
   36 
   37 #include <QCompleter>
   38 #include <QKeyEvent>
   39 #include <QMenu>
   40 #include <QWidgetAction>
   41 
   42 #include <KLocalizedString>
   43 
   44 /*!
   45   \class XYEquationCurveDock
   46   \brief  Provides a widget for editing the properties of the XYEquationCurves
   47         (2D-curves defined by a mathematical equation) currently selected in
   48         the project explorer.
   49 
   50   If more then one curves are set, the properties of the first column are shown.
   51   The changes of the properties are applied to all curves.
   52   The exclusions are the name, the comment and the datasets (columns) of
   53   the curves  - these properties can only be changed if there is only one single curve.
   54 
   55   \ingroup kdefrontend
   56 */
   57 
   58 XYEquationCurveDock::XYEquationCurveDock(QWidget *parent): XYCurveDock(parent) {
   59     //remove the tab "Error bars"
   60     ui.tabWidget->removeTab(5);
   61 }
   62 
   63 /*!
   64  *  // Tab "General"
   65  */
   66 void XYEquationCurveDock::setupGeneral() {
   67     QWidget* generalTab = new QWidget(ui.tabGeneral);
   68     uiGeneralTab.setupUi(generalTab);
   69     m_leName = uiGeneralTab.leName;
   70     m_leComment = uiGeneralTab.leComment;
   71 
   72     auto* gridLayout = dynamic_cast<QGridLayout*>(generalTab->layout());
   73     if (gridLayout) {
   74         gridLayout->setContentsMargins(2, 2, 2, 2);
   75         gridLayout->setHorizontalSpacing(2);
   76         gridLayout->setVerticalSpacing(2);
   77     }
   78 
   79     auto* layout = new QHBoxLayout(ui.tabGeneral);
   80     layout->setMargin(0);
   81     layout->addWidget(generalTab);
   82 
   83     uiGeneralTab.tbConstants1->setIcon( QIcon::fromTheme("labplot-format-text-symbol") );
   84     uiGeneralTab.tbFunctions1->setIcon( QIcon::fromTheme("preferences-desktop-font") );
   85 
   86     uiGeneralTab.tbConstants2->setIcon( QIcon::fromTheme("labplot-format-text-symbol") );
   87     uiGeneralTab.tbFunctions2->setIcon( QIcon::fromTheme("preferences-desktop-font") );
   88 
   89     uiGeneralTab.cbType->addItem(i18n("Cartesian"));
   90     uiGeneralTab.cbType->addItem(i18n("Polar"));
   91     uiGeneralTab.cbType->addItem(i18n("Parametric"));
   92 //  uiGeneralTab.cbType->addItem(i18n("Implicit"));
   93 
   94     uiGeneralTab.pbRecalculate->setIcon(QIcon::fromTheme("run-build"));
   95 
   96     uiGeneralTab.teEquation2->setExpressionType(XYEquationCurve::EquationType::Parametric);
   97 
   98 //  uiGeneralTab.teEquation1->setMaximumHeight(uiGeneralTab.leName->sizeHint().height()*2);
   99 //  uiGeneralTab.teEquation2->setMaximumHeight(uiGeneralTab.leName->sizeHint().height()*2);
  100     uiGeneralTab.teMin->setMaximumHeight(uiGeneralTab.leName->sizeHint().height());
  101     uiGeneralTab.teMax->setMaximumHeight(uiGeneralTab.leName->sizeHint().height());
  102 
  103     //Slots
  104     connect(uiGeneralTab.leName, &QLineEdit::textChanged, this, &XYEquationCurveDock::nameChanged);
  105     connect(uiGeneralTab.leComment, &QLineEdit::textChanged, this, &XYEquationCurveDock::commentChanged);
  106     connect(uiGeneralTab.chkVisible, &QCheckBox::clicked, this, &XYEquationCurveDock::visibilityChanged);
  107 
  108     connect(uiGeneralTab.cbType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &XYEquationCurveDock::typeChanged);
  109     connect(uiGeneralTab.teEquation1, &ExpressionTextEdit::expressionChanged, this, &XYEquationCurveDock::enableRecalculate);
  110     connect(uiGeneralTab.teEquation2, &ExpressionTextEdit::expressionChanged, this, &XYEquationCurveDock::enableRecalculate);
  111     connect(uiGeneralTab.tbConstants1, &QToolButton::clicked, this, &XYEquationCurveDock::showConstants);
  112     connect(uiGeneralTab.tbFunctions1, &QToolButton::clicked, this, &XYEquationCurveDock::showFunctions);
  113     connect(uiGeneralTab.tbConstants2, &QToolButton::clicked, this, &XYEquationCurveDock::showConstants);
  114     connect(uiGeneralTab.tbFunctions2, &QToolButton::clicked, this, &XYEquationCurveDock::showFunctions);
  115     connect(uiGeneralTab.teMin, &ExpressionTextEdit::expressionChanged, this, &XYEquationCurveDock::enableRecalculate);
  116     connect(uiGeneralTab.teMax, &ExpressionTextEdit::expressionChanged, this, &XYEquationCurveDock::enableRecalculate);
  117     connect(uiGeneralTab.sbCount, QOverload<int>::of(&QSpinBox::valueChanged), this, &XYEquationCurveDock::enableRecalculate);
  118     connect(uiGeneralTab.pbRecalculate, &QPushButton::clicked, this, &XYEquationCurveDock::recalculateClicked);
  119 }
  120 
  121 /*!
  122   sets the curves. The properties of the curves in the list \c list can be edited in this widget.
  123 */
  124 void XYEquationCurveDock::setCurves(QList<XYCurve*> list) {
  125     m_initializing = true;
  126     m_curvesList = list;
  127     m_curve = list.first();
  128     m_aspect = list.first();
  129     m_equationCurve = dynamic_cast<XYEquationCurve*>(m_curve);
  130     Q_ASSERT(m_equationCurve);
  131     m_aspectTreeModel =  new AspectTreeModel(m_curve->project());
  132     XYCurveDock::setModel();
  133     initGeneralTab();
  134     initTabs();
  135     uiGeneralTab.pbRecalculate->setEnabled(false);
  136     m_initializing = false;
  137 }
  138 
  139 void XYEquationCurveDock::initGeneralTab() {
  140     //if there are more then one curve in the list, disable the tab "general"
  141     if (m_curvesList.size() == 1) {
  142         uiGeneralTab.lName->setEnabled(true);
  143         uiGeneralTab.leName->setEnabled(true);
  144         uiGeneralTab.lComment->setEnabled(true);
  145         uiGeneralTab.leComment->setEnabled(true);
  146 
  147         uiGeneralTab.leName->setText(m_curve->name());
  148         uiGeneralTab.leComment->setText(m_curve->comment());
  149     } else {
  150         uiGeneralTab.lName->setEnabled(false);
  151         uiGeneralTab.leName->setEnabled(false);
  152         uiGeneralTab.lComment->setEnabled(false);
  153         uiGeneralTab.leComment->setEnabled(false);
  154 
  155         uiGeneralTab.leName->setText(QString());
  156         uiGeneralTab.leComment->setText(QString());
  157     }
  158 
  159     //show the properties of the first curve
  160     const auto* equationCurve = dynamic_cast<const XYEquationCurve*>(m_curve);
  161     Q_ASSERT(equationCurve);
  162     const XYEquationCurve::EquationData& data = equationCurve->equationData();
  163     uiGeneralTab.cbType->setCurrentIndex(static_cast<int>(data.type));
  164     this->typeChanged(static_cast<int>(data.type));
  165     uiGeneralTab.teEquation1->setText(data.expression1);
  166     uiGeneralTab.teEquation2->setText(data.expression2);
  167     uiGeneralTab.teMin->setText(data.min);
  168     uiGeneralTab.teMax->setText(data.max);
  169     uiGeneralTab.sbCount->setValue(data.count);
  170 
  171     uiGeneralTab.chkVisible->setChecked( m_curve->isVisible() );
  172 
  173     //Slots
  174     connect(m_equationCurve, &XYEquationCurve::aspectDescriptionChanged,
  175             this, &XYEquationCurveDock::curveDescriptionChanged);
  176     connect(m_equationCurve, &XYEquationCurve::equationDataChanged,
  177             this, &XYEquationCurveDock::curveEquationDataChanged);
  178 }
  179 
  180 //*************************************************************
  181 //**** SLOTs for changes triggered in XYEquationCurveDock *****
  182 //*************************************************************
  183 void XYEquationCurveDock::typeChanged(int index) {
  184     const auto type{XYEquationCurve::EquationType(index)};
  185     if (type == XYEquationCurve::EquationType::Cartesian) {
  186         uiGeneralTab.lEquation1->setText("y=f(x)");
  187         uiGeneralTab.lEquation2->hide();
  188         uiGeneralTab.teEquation2->hide();
  189         uiGeneralTab.tbFunctions2->hide();
  190         uiGeneralTab.tbConstants2->hide();
  191         uiGeneralTab.lMin->show();
  192         uiGeneralTab.lMax->show();
  193         uiGeneralTab.teMin->show();
  194         uiGeneralTab.teMax->show();
  195         uiGeneralTab.lMin->setText(i18n("x, min"));
  196         uiGeneralTab.lMax->setText(i18n("x, max"));
  197     } else if (type == XYEquationCurve::EquationType::Polar) {
  198         uiGeneralTab.lEquation1->setText(QString::fromUtf8("r(φ)"));
  199         uiGeneralTab.lEquation2->hide();
  200         uiGeneralTab.teEquation2->hide();
  201         uiGeneralTab.tbFunctions2->hide();
  202         uiGeneralTab.tbConstants2->hide();
  203         uiGeneralTab.lMin->show();
  204         uiGeneralTab.lMax->show();
  205         uiGeneralTab.teMin->show();
  206         uiGeneralTab.teMax->show();
  207         uiGeneralTab.lMin->setText(i18n("φ, min"));
  208         uiGeneralTab.lMax->setText(i18n("φ, max"));
  209     } else if (type == XYEquationCurve::EquationType::Parametric) {
  210         uiGeneralTab.lEquation1->setText("x=f(t)");
  211         uiGeneralTab.lEquation2->setText("y=f(t)");
  212         uiGeneralTab.lEquation2->show();
  213         uiGeneralTab.teEquation2->show();
  214         uiGeneralTab.tbFunctions2->show();
  215         uiGeneralTab.tbConstants2->show();
  216         uiGeneralTab.lMin->show();
  217         uiGeneralTab.lMax->show();
  218         uiGeneralTab.teMin->show();
  219         uiGeneralTab.teMax->show();
  220         uiGeneralTab.lMin->setText(i18n("t, min"));
  221         uiGeneralTab.lMax->setText(i18n("t, max"));
  222     } else if (type == XYEquationCurve::EquationType::Implicit) {
  223         uiGeneralTab.lEquation1->setText("f(x,y)");
  224         uiGeneralTab.lEquation2->hide();
  225         uiGeneralTab.teEquation2->hide();
  226         uiGeneralTab.tbFunctions2->hide();
  227         uiGeneralTab.tbConstants2->hide();
  228         uiGeneralTab.lMin->hide();
  229         uiGeneralTab.lMax->hide();
  230         uiGeneralTab.teMin->hide();
  231         uiGeneralTab.teMax->hide();
  232     }
  233 
  234     uiGeneralTab.teEquation1->setExpressionType(type);
  235     this->enableRecalculate();
  236 }
  237 
  238 void XYEquationCurveDock::recalculateClicked() {
  239     XYEquationCurve::EquationData data;
  240     data.type = (XYEquationCurve::EquationType)uiGeneralTab.cbType->currentIndex();
  241     data.expression1 = uiGeneralTab.teEquation1->document()->toPlainText();
  242     data.expression2 = uiGeneralTab.teEquation2->document()->toPlainText();
  243     data.min = uiGeneralTab.teMin->document()->toPlainText();
  244     data.max = uiGeneralTab.teMax->document()->toPlainText();
  245     data.count = uiGeneralTab.sbCount->value();
  246 
  247     for (auto* curve : m_curvesList)
  248         static_cast<XYEquationCurve*>(curve)->setEquationData(data);
  249 
  250     uiGeneralTab.pbRecalculate->setEnabled(false);
  251 }
  252 
  253 void XYEquationCurveDock::showConstants() {
  254     QMenu menu;
  255     ConstantsWidget constants(&menu);
  256 
  257     if (QObject::sender() == uiGeneralTab.tbConstants1)
  258         connect(&constants, &ConstantsWidget::constantSelected, this, &XYEquationCurveDock::insertConstant1);
  259     else
  260         connect(&constants, &ConstantsWidget::constantSelected, this, &XYEquationCurveDock::insertConstant2);
  261 
  262     connect(&constants, &ConstantsWidget::constantSelected, &menu, &QMenu::close);
  263     connect(&constants, &ConstantsWidget::canceled, &menu, &QMenu::close);
  264 
  265     auto* widgetAction = new QWidgetAction(this);
  266     widgetAction->setDefaultWidget(&constants);
  267     menu.addAction(widgetAction);
  268 
  269     if (QObject::sender() == uiGeneralTab.tbConstants1) {
  270         QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbConstants1->width(),-menu.sizeHint().height());
  271         menu.exec(uiGeneralTab.tbConstants1->mapToGlobal(pos));
  272     } else {
  273         QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbConstants2->width(),-menu.sizeHint().height());
  274         menu.exec(uiGeneralTab.tbConstants2->mapToGlobal(pos));
  275     }
  276 }
  277 
  278 void XYEquationCurveDock::showFunctions() {
  279     QMenu menu;
  280     FunctionsWidget functions(&menu);
  281     if (QObject::sender() == uiGeneralTab.tbFunctions1)
  282         connect(&functions, &FunctionsWidget::functionSelected, this, &XYEquationCurveDock::insertFunction1);
  283     else
  284         connect(&functions, &FunctionsWidget::functionSelected, this, &XYEquationCurveDock::insertFunction2);
  285 
  286     connect(&functions, &FunctionsWidget::functionSelected, &menu, &QMenu::close);
  287     connect(&functions, &FunctionsWidget::canceled, &menu, &QMenu::close);
  288 
  289     auto* widgetAction = new QWidgetAction(this);
  290     widgetAction->setDefaultWidget(&functions);
  291     menu.addAction(widgetAction);
  292 
  293     if (QObject::sender() == uiGeneralTab.tbFunctions1) {
  294         QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbFunctions1->width(),-menu.sizeHint().height());
  295         menu.exec(uiGeneralTab.tbFunctions1->mapToGlobal(pos));
  296     } else {
  297         QPoint pos(-menu.sizeHint().width()+uiGeneralTab.tbFunctions2->width(),-menu.sizeHint().height());
  298         menu.exec(uiGeneralTab.tbFunctions2->mapToGlobal(pos));
  299     }
  300 }
  301 
  302 void XYEquationCurveDock::insertFunction1(const QString& functionName) {
  303     const auto type{XYEquationCurve::EquationType(uiGeneralTab.cbType->currentIndex())};
  304 
  305     uiGeneralTab.teEquation1->insertPlainText(functionName + ExpressionParser::functionArgumentString(functionName, type));
  306 }
  307 
  308 void XYEquationCurveDock::insertConstant1(const QString& constantsName) {
  309     uiGeneralTab.teEquation1->insertPlainText(constantsName);
  310 }
  311 
  312 void XYEquationCurveDock::insertFunction2(const QString& functionName) {
  313     uiGeneralTab.teEquation1->insertPlainText(functionName + ExpressionParser::functionArgumentString(functionName, XYEquationCurve::EquationType::Parametric));
  314 }
  315 
  316 void XYEquationCurveDock::insertConstant2(const QString& constantsName) {
  317     uiGeneralTab.teEquation2->insertPlainText(constantsName);
  318 }
  319 
  320 void XYEquationCurveDock::enableRecalculate() const {
  321     if (m_initializing)
  322         return;
  323 
  324     //check whether the formular expressions are correct
  325     bool valid = false;
  326     const auto type = XYEquationCurve::EquationType(uiGeneralTab.cbType->currentIndex());
  327     if (type != XYEquationCurve::EquationType::Parametric)
  328         valid = uiGeneralTab.teEquation1->isValid();
  329     else
  330         valid = (uiGeneralTab.teEquation1->isValid() && uiGeneralTab.teEquation2->isValid());
  331 
  332     valid = (valid && uiGeneralTab.teMin->isValid() && uiGeneralTab.teMax->isValid());
  333     uiGeneralTab.pbRecalculate->setEnabled(valid);
  334 }
  335 
  336 //*************************************************************
  337 //*********** SLOTs for changes triggered in XYCurve **********
  338 //*************************************************************
  339 //General-Tab
  340 void XYEquationCurveDock::curveDescriptionChanged(const AbstractAspect* aspect) {
  341     if (m_curve != aspect)
  342         return;
  343 
  344     const Lock lock(m_initializing);
  345     if (aspect->name() != uiGeneralTab.leName->text())
  346         uiGeneralTab.leName->setText(aspect->name());
  347     else if (aspect->comment() != uiGeneralTab.leComment->text())
  348         uiGeneralTab.leComment->setText(aspect->comment());
  349 }
  350 
  351 void XYEquationCurveDock::curveEquationDataChanged(const XYEquationCurve::EquationData& data) {
  352     const Lock lock(m_initializing);
  353     uiGeneralTab.cbType->setCurrentIndex(static_cast<int>(data.type));
  354     uiGeneralTab.teEquation1->setText(data.expression1);
  355     uiGeneralTab.teEquation2->setText(data.expression2);
  356     uiGeneralTab.teMin->setText(data.min);
  357     uiGeneralTab.teMax->setText(data.max);
  358     uiGeneralTab.sbCount->setValue(data.count);
  359 }