File indexing completed on 2024-04-14 14:08:50

0001 /*************************************************************************************
0002  *  Copyright (C) 2010-2014 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com> *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 #include "plotseditor.h"
0020 #include "ui_plotseditor.h"
0021 
0022 //Analitza includes
0023 #include <analitza/analyzer.h>
0024 #include <analitza/expression.h>
0025 #include <analitza/variables.h>
0026 #include <analitza/value.h>
0027 #include <analitzagui/expressionedit.h>
0028 #include <analitzagui/algebrahighlighter.h>
0029 #include <analitzagui/variablesmodel.h>
0030 #include <analitzaplot/functiongraph.h>
0031 #include <analitzaplot/planecurve.h>
0032 #include <analitzaplot/plotsmodel.h>
0033 #include <analitzaplot/spacecurve.h>
0034 #include <analitzaplot/surface.h>
0035 #include <analitzaplot/plotsfactory.h>
0036 
0037 //Qt includes
0038 #include <QStringListModel>
0039 #include <QPushButton>
0040 #include <qstyleditemdelegate.h>
0041 #include <QPainter>
0042 
0043 //KDE includes
0044 #include <KRandom>
0045 
0046 #include <cmath>
0047 
0048 //local includes
0049 #include "datastore.h"
0050 #include "spacesmodel.h"
0051 #include "spaceplotsproxymodel.h"
0052 #include "spaceitem.h"
0053 
0054 using namespace Analitza;
0055 
0056 PlotsEditor::PlotsEditor(QWidget * parent)
0057     : QDockWidget(parent), isEditing(false), plotnumber(1)
0058 {
0059     m_widget = new Ui::PlotsEditorWidget;
0060     m_widget->setupUi(this);
0061     setObjectName("adasdds");
0062 
0063     // random coloring of the plots
0064     m_widget->plotColor->setColor(randomFunctionColor());
0065 
0066     m_widget->focusPlot->setToolTip(i18n("check/uncheck to show/hide the Axes"));
0067     m_widget->focusPlot->setChecked(true);
0068 
0069     m_widget->editPlot->setToolTip(i18n("Click to edit the plot"));
0070     m_widget->removePlot->setToolTip(i18n("Click to remove the plot"));
0071 
0072     // no bounding by default
0073     m_widget->intervals->setChecked(false);
0074 
0075     connect(m_widget->fnameForGraphs, SIGNAL(currentIndexChanged(QString)), SLOT(setCurrentFunctionGraphs(QString)));
0076 
0077     m_widget->farrow->setText("=");
0078     m_widget->garrow->setText("=");
0079     m_widget->harrow->setText("=");
0080 
0081     connect(m_widget->builderDialogBox->button(QDialogButtonBox::Cancel), SIGNAL(pressed()), SLOT(showList()));
0082     connect(m_widget->editorDialogBox->button(QDialogButtonBox::Cancel), SIGNAL(pressed()), SLOT(cancelEditor()));
0083     connect(m_widget->editorDialogBox->button(QDialogButtonBox::Ok), SIGNAL(pressed()), SLOT(savePlot()));
0084 
0085     m_widget->builder->mapConnection(PlotsBuilder::CartesianGraphCurve, this, SLOT(buildCartesianGraphCurve()));
0086     m_widget->builder->mapConnection(PlotsBuilder::CartesianImplicitCurve, this, SLOT(buildCartesianImplicitCurve()));
0087     m_widget->builder->mapConnection(PlotsBuilder::CartesianParametricCurve2D, this, SLOT(buildCartesianParametricCurve2D()));
0088     m_widget->builder->mapConnection(PlotsBuilder::PolarGraphCurve, this, SLOT(buildPolarGraphCurve()));
0089     m_widget->builder->mapConnection(PlotsBuilder::CartesianParametricCurve3D, this, SLOT(buildCartesianParametricCurve3D()));
0090     m_widget->builder->mapConnection(PlotsBuilder::CartesianGraphSurface, this, SLOT(buildCartesianGraphSurface()));
0091     m_widget->builder->mapConnection(PlotsBuilder::CartesianImplicitSurface, this, SLOT(buildCartesianImplicitSurface()));
0092     m_widget->builder->mapConnection(PlotsBuilder::CartesianParametricSurface, this, SLOT(buildCartesianParametricSurface()));
0093     m_widget->builder->mapConnection(PlotsBuilder::CylindricalGraphSurface, this, SLOT(buildCylindricalGraphSurface()));
0094     m_widget->builder->mapConnection(PlotsBuilder::SphericalGraphSurface, this, SLOT(buildSphericalGraphSurface()));
0095 
0096     connect(m_widget->addPlots, SIGNAL(pressed()), SLOT(addPlots()));
0097     connect(m_widget->editPlot, SIGNAL(pressed()), SLOT(editPlot()));
0098     connect(m_widget->plotsView, SIGNAL(doubleClicked(QModelIndex)), SLOT(editPlot()));
0099     connect(m_widget->removePlot, SIGNAL(pressed()), SLOT(removePlot()));
0100     connect(m_widget->focusPlot,SIGNAL(stateChanged(int)),SLOT(showAxis(int)));
0101     connect(m_widget->plotnamecheck,SIGNAL(toggled(bool)),SLOT(plotnamecheckClicked(bool)));
0102 
0103     this->installEventFilter(this);
0104     m_widget->f->installEventFilter(this);
0105     plotnamecheckClicked(false);
0106 }
0107 
0108 bool PlotsEditor::eventFilter(QObject*, QEvent *event)
0109 {
0110     if(event->type() == QEvent::KeyPress)
0111     {
0112         QKeyEvent *key = static_cast<QKeyEvent *>(event);
0113         if(key->key() == Qt::Key_Enter || key->key() == Qt::Key_Return)
0114         {
0115             savePlot();
0116             m_widget->plotnamecheck->setChecked(false);
0117         }
0118     }
0119     return false;
0120 }
0121 
0122 PlotsEditor::~PlotsEditor()
0123 {
0124     delete m_widget;
0125 }
0126 
0127 void PlotsEditor::setDocument(DataStore* doc)
0128 {
0129     m_document  = doc;
0130     m_widget->plotsView->setModel(m_document->currentPlots());
0131     m_widget->plotsView->setSelectionModel(m_document->currentSelectionModel());
0132 }
0133 
0134 void PlotsEditor::setCurrentSpace(int spaceidx)
0135 {
0136     switch (m_document->spacesModel()->space(spaceidx)->dimension())
0137     {
0138     case Dim2D:
0139     {
0140         m_widget->builder->setupTypes(PlotsBuilder::CartesianGraphCurve |
0141                                       PlotsBuilder::CartesianImplicitCurve | PlotsBuilder::CartesianParametricCurve2D |
0142                                       PlotsBuilder::PolarGraphCurve);
0143         m_widget->styleWidget->hide();
0144         break;
0145     }
0146     case Dim3D:
0147     {
0148         m_widget->builder->setupTypes(PlotsBuilder::CartesianParametricCurve3D | PlotsBuilder::CartesianGraphSurface |
0149                                       PlotsBuilder::CartesianImplicitSurface | PlotsBuilder::CartesianParametricSurface | PlotsBuilder::CylindricalGraphSurface |
0150                                       PlotsBuilder::SphericalGraphSurface);
0151         m_widget->styleWidget->show();
0152         break;
0153     }
0154     default:
0155         break;
0156     }
0157 }
0158 
0159 void PlotsEditor::reset(bool clearBuilder)
0160 {
0161     //clear widgets
0162     m_widget->plotName->clear();
0163     m_widget->plotnamecheck->setChecked(false);
0164     m_widget->plotColor->setColor(randomFunctionColor());
0165 
0166     m_widget->f->clear();
0167     m_widget->g->clear();
0168     m_widget->h->clear();
0169     m_widget->minx->clear();
0170     m_widget->maxx->clear();
0171     m_widget->miny->clear();
0172     m_widget->maxy->clear();
0173     m_widget->minz->clear();
0174     m_widget->maxz->clear();
0175 
0176     //reset widgets
0177     m_widget->widgets->setCurrentIndex(0);
0178 
0179     if (clearBuilder)
0180         m_widget->builder->hideAllTypes();
0181 
0182     //focus
0183     m_widget->plotName->setFocus();
0184 }
0185 
0186 void PlotsEditor::showList()
0187 {
0188     m_widget->widgets->setCurrentIndex(0);
0189 }
0190 
0191 void PlotsEditor::showTypes()
0192 {
0193     m_widget->widgets->setCurrentIndex(1);
0194 }
0195 
0196 void PlotsEditor::showEditor()
0197 {
0198     /// clear actions
0199     m_widget->widgets->setCurrentIndex(2);
0200 
0201     /// force right focus
0202     // while editing the plot , it is very likely that user needs to change the expression.
0203     m_widget->f->setFocus();
0204 }
0205 
0206 void PlotsEditor::cancelEditor()
0207 {
0208     if (isEditing)
0209     {
0210         showList();
0211         isEditing = false;
0212         return;
0213     }
0214     if (m_cancelIsGoHome)
0215     {
0216         emit goHome();
0217         m_document->removeCurrentSpace();
0218     }
0219     else 
0220         showTypes();
0221 }
0222 
0223 void PlotsEditor::showAxis(int state)
0224 {
0225     if (state==0) {
0226         if(m_document->spacesModel()->space(m_document->currentSpace())->dimension()==Dim2D)
0227             emit updateGridcolor(QColor(255,255,255)); // Axis willnot be visible when the color will be white.
0228         else
0229             emit updateGridcolor(QColor(Qt::black));  // Axis willnot be visible when the color will be black.
0230     }
0231     else if (state==2) {
0232         if(m_document->spacesModel()->space(m_document->currentSpace())->dimension()==Dim2D)
0233             emit updateGridcolor(QColor(230,230,230)); // Axis will be visible when the color will be grey.
0234         else
0235             emit updateGridcolor(QColor(Qt::darkGray)); // Axis will be visible when the color will be darkGrey.
0236     }
0237 }
0238 
0239 void PlotsEditor::addPlots()
0240 {
0241     m_cancelIsGoHome = false;
0242     showTypes();
0243 }
0244 
0245 void PlotsEditor::editPlot(const QModelIndex &)
0246 {
0247     // comes when double clicked on the items in the list shown with checkbox.!
0248     isEditing = true;
0249 
0250     reset();
0251 
0252     // while editing the plot , it is very likely that user needs to change the expression.
0253     m_widget->f->setFocus();
0254 
0255     if (m_widget->plotsView->selectionModel()->hasSelection()) // may be the plotsview is different .!!!
0256     {
0257         QModelIndex index = m_widget->plotsView->selectionModel()->currentIndex();
0258         PlotItem* item = index.data(PlotsModel::PlotRole).value<PlotItem*>();
0259         
0260         m_widget->plotColor->setColor(item->color());
0261         m_widget->plotName->setText(item->name());
0262 
0263         if (dynamic_cast<PlaneCurve*>(item))
0264         {
0265             PlaneCurve *curve = dynamic_cast<PlaneCurve*>(item);
0266             
0267             if (Expression(curve->display()).isEquation()) // implicit
0268             {
0269                 m_widget->f->setExpression(Expression(curve->display()));
0270                 buildCartesianImplicitCurve();
0271 
0272                 if (curve->hasIntervals())
0273                 {
0274                     QPair<Analitza::Expression, Analitza::Expression> interval = curve->interval(curve->parameters().at(1), false);
0275                 
0276                     m_widget->miny->setExpression(interval.first);
0277                     m_widget->maxy->setExpression(interval.second);
0278                 }
0279             }
0280             else if (curve->expression().lambdaBody().isVector()) //vectorvalued
0281             {
0282                 m_widget->f->setExpression(curve->expression().lambdaBody().elementAt(0));
0283                 m_widget->g->setExpression(curve->expression().lambdaBody().elementAt(1));
0284 
0285                 buildCartesianParametricCurve2D();
0286             }
0287             else //graph
0288             {
0289                 m_widget->f->setExpression(curve->expression().lambdaBody());
0290 
0291                 if (curve->parameters().first() == "q") 
0292                 {
0293                     buildPolarGraphCurve();
0294                 }
0295                 else
0296                 {
0297                     buildCartesianGraphCurve();
0298 
0299                     if (curve->parameters().first() == "x")
0300                     {
0301                         m_currentVars = QStringList() << "x";
0302                         m_widget->fnameForGraphs->hide();
0303                         setupFuncName(1, "y", QStringList() << "x");
0304                         setupVarName(1, "x");
0305                         m_widget->fname->show();
0306                     }
0307                     else if (curve->parameters().first() == "y")
0308                     {
0309                         m_currentVars = QStringList() << "y";
0310                         m_widget->fnameForGraphs->hide();
0311                         setupFuncName(1, "x", QStringList() << "y");
0312                         setupVarName(1, "y");
0313                         m_widget->fname->show();
0314                     }
0315                 }
0316             }
0317 
0318             if (curve->hasIntervals())
0319             {
0320                 QPair<Analitza::Expression, Analitza::Expression> interval = curve->interval(curve->parameters().first(), false);
0321                 
0322                 m_widget->minx->setExpression(interval.first);
0323                 m_widget->maxx->setExpression(interval.second);
0324             }
0325         }
0326         else if (dynamic_cast<SpaceCurve*>(item))
0327         {
0328             SpaceCurve *curve = dynamic_cast<SpaceCurve*>(item);
0329 
0330             m_widget->f->setExpression(curve->expression().lambdaBody().elementAt(0));
0331             m_widget->g->setExpression(curve->expression().lambdaBody().elementAt(1));
0332             m_widget->h->setExpression(curve->expression().lambdaBody().elementAt(2));
0333 
0334             buildCartesianParametricCurve3D();
0335 
0336             
0337             if (curve->hasIntervals())
0338             {
0339                 QPair<Analitza::Expression, Analitza::Expression> interval = curve->interval(curve->parameters().first(), false);
0340                 
0341                 m_widget->minx->setExpression(interval.first);
0342                 m_widget->maxx->setExpression(interval.second);
0343             }
0344         }
0345         else if (dynamic_cast<Surface*>(item))
0346         {
0347             Surface *surface = dynamic_cast<Surface*>(item);
0348 
0349             if (Expression(surface->display()).isEquation()) // implicit
0350             {
0351                 m_widget->f->setExpression(Expression(surface->display()));
0352 
0353                 buildCartesianImplicitSurface();
0354 
0355                 if (surface->hasIntervals())
0356                 {
0357                     QPair<Analitza::Expression, Analitza::Expression> interval = surface->interval(surface->parameters().at(2), false);
0358                     
0359                     m_widget->minz->setExpression(interval.first);
0360                     m_widget->maxz->setExpression(interval.second);
0361                 }
0362             }
0363             else if (surface->expression().lambdaBody().isVector()) //vectorvalued
0364             {
0365                 m_widget->f->setExpression(surface->expression().lambdaBody().elementAt(0));
0366                 m_widget->g->setExpression(surface->expression().lambdaBody().elementAt(1));
0367                 m_widget->h->setExpression(surface->expression().lambdaBody().elementAt(2));
0368 
0369                 buildCartesianParametricSurface();
0370             }
0371             else //graph
0372             {
0373                 m_widget->f->setExpression(surface->expression().lambdaBody());
0374 
0375                 if (surface->parameters() == QStringList() << "r" << "p")
0376                     buildCylindricalGraphSurface();
0377                 else if (surface->parameters() == QStringList() << "t" << "p")
0378                     buildSphericalGraphSurface();
0379                 else
0380                 {
0381                     buildCartesianGraphSurface();
0382 
0383                     if (surface->parameters() == QStringList() << "x" << "y")
0384                     {
0385                         m_currentVars = QStringList() << "x" << "y";
0386                         m_widget->fnameForGraphs->hide();
0387                         setupFuncName(1, "z", QStringList() << "x" << "y");
0388                         setupVarName(1, "x");
0389                         setupVarName(2, "y");
0390                         m_widget->fname->show();
0391                     }
0392                     else if (surface->parameters() == QStringList() << "x" << "z")
0393                     {
0394                         m_currentVars = QStringList() << "x" << "z";
0395                         m_widget->fnameForGraphs->hide();
0396                         setupFuncName(1, "y", QStringList() << "x" << "z");
0397                         setupVarName(1, "x");
0398                         setupVarName(2, "z");
0399                         m_widget->fname->show();
0400                     }
0401                     else if (surface->parameters() == QStringList() << "y" << "z")
0402                     {
0403                         m_currentVars = QStringList() << "y" << "z";
0404                         m_widget->fnameForGraphs->hide();
0405                         setupFuncName(1, "x", QStringList() << "y" << "z");
0406                         setupVarName(1, "y");
0407                         setupVarName(2, "z");
0408                         m_widget->fname->show();
0409                     }
0410                 }
0411             }
0412 
0413             if (surface->hasIntervals())
0414             {
0415                 QPair<Analitza::Expression, Analitza::Expression> interval = surface->interval(surface->parameters().first(), false);
0416 
0417                 m_widget->minx->setExpression(interval.first);
0418                 m_widget->maxx->setExpression(interval.second);
0419 
0420                 interval = surface->interval(surface->parameters().at(1), false);
0421 
0422                 m_widget->miny->setExpression(interval.first);
0423                 m_widget->maxy->setExpression(interval.second);
0424             }
0425         }
0426     }
0427 }
0428 
0429 void PlotsEditor::buildCartesianGraphCurve(bool cancelIsGoHome)
0430 {
0431     if (!isEditing)
0432         reset();
0433 
0434     m_cancelIsGoHome = cancelIsGoHome;
0435 
0436     m_currentType = PlotsBuilder::CartesianGraphCurve;
0437 
0438     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newfunction").pixmap(16, 16));
0439 
0440     setupExpressionType(QStringList() << "x" << "y", QStringList() << "x");
0441 
0442     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0443     m_widget->maxx->setExpression(Analitza::Expression(Analitza::Cn(5)));
0444 }
0445 
0446 void PlotsEditor::buildCartesianImplicitCurve(bool cancelIsGoHome)
0447 {
0448     if (!isEditing)
0449         reset();
0450 
0451     m_cancelIsGoHome = cancelIsGoHome;
0452 
0453     m_currentType = PlotsBuilder::CartesianImplicitCurve;
0454 
0455     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newimplicit").pixmap(16, 16));
0456 
0457     setupExpressionType(QStringList(), QStringList() << "x" << "y", true);
0458 
0459     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0460     m_widget->maxx->setExpression(Analitza::Expression(Analitza::Cn(5)));
0461 
0462     m_widget->miny->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0463     m_widget->maxy->setExpression(Analitza::Expression(Analitza::Cn(5)));
0464 }
0465 
0466 void PlotsEditor::buildCartesianParametricCurve2D(bool cancelIsGoHome)
0467 {
0468     if (!isEditing)
0469         reset();
0470 
0471     m_cancelIsGoHome = cancelIsGoHome;
0472 
0473     m_currentType = PlotsBuilder::CartesianParametricCurve2D;
0474 
0475     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newparametric").pixmap(16, 16));
0476 
0477     setupExpressionType(QStringList() << "x" << "y", QStringList() << "t", false, true);
0478 
0479     m_widget->minx->setExpression(Analitza::Expression("-pi"));
0480     m_widget->maxx->setExpression(Analitza::Expression("pi"));
0481 }
0482 
0483 void PlotsEditor::buildPolarGraphCurve(bool cancelIsGoHome)
0484 {
0485     if (!isEditing)
0486         reset();
0487 
0488     m_cancelIsGoHome = cancelIsGoHome;
0489 
0490     m_currentType = PlotsBuilder::PolarGraphCurve;
0491 
0492     m_widget->plotIcon->setPixmap(QIcon::fromTheme("draw-spiral").pixmap(16, 16));
0493 
0494     setupExpressionType(QStringList()<<"q", QStringList() << "q");
0495 
0496     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(0)));
0497     m_widget->maxx->setExpression(Analitza::Expression("2*pi"));
0498 }
0499 
0500 //3D
0501 void PlotsEditor::buildCartesianParametricCurve3D(bool cancelIsGoHome)
0502 {
0503     if (!isEditing)
0504         reset();
0505 
0506     m_cancelIsGoHome = cancelIsGoHome;
0507 
0508     m_currentType = PlotsBuilder::CartesianParametricCurve3D;
0509 
0510     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newparametric3d").pixmap(16, 16));
0511 
0512     setupExpressionType(QStringList() << "x" << "y" << "z", QStringList() << "t", false, true);
0513 
0514     m_widget->minx->setExpression(Analitza::Expression("-pi"));
0515     m_widget->maxx->setExpression(Analitza::Expression("pi"));
0516 }
0517 
0518 void PlotsEditor::buildCartesianGraphSurface(bool cancelIsGoHome)
0519 {
0520     if (!isEditing)
0521         reset();
0522 
0523     m_cancelIsGoHome = cancelIsGoHome;
0524 
0525     m_currentType = PlotsBuilder::CartesianGraphSurface;
0526 
0527     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newfunction3d").pixmap(16, 16));
0528 
0529     setupExpressionType(QStringList() << "x,y" << "x,z" << "y,z", QStringList() << "x" << "y");
0530 
0531     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0532     m_widget->maxx->setExpression(Analitza::Expression(Analitza::Cn(5)));
0533 
0534     m_widget->miny->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0535     m_widget->maxy->setExpression(Analitza::Expression(Analitza::Cn(5)));
0536 }
0537 
0538 void PlotsEditor::buildCartesianImplicitSurface(bool cancelIsGoHome)
0539 {
0540     if (!isEditing)
0541         reset();
0542 
0543     m_cancelIsGoHome = cancelIsGoHome;
0544 
0545     m_currentType = PlotsBuilder::CartesianImplicitSurface;
0546 
0547     m_widget->plotIcon->setPixmap(QIcon::fromTheme("draw-square-inverted-corners").pixmap(16, 16));
0548 
0549     setupExpressionType(QStringList(), QStringList() << "x" << "y" << "z", true);
0550 
0551     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0552     m_widget->maxx->setExpression(Analitza::Expression(Analitza::Cn(5)));
0553 
0554     m_widget->miny->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0555     m_widget->maxy->setExpression(Analitza::Expression(Analitza::Cn(5)));
0556 
0557     m_widget->minz->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0558     m_widget->maxz->setExpression(Analitza::Expression(Analitza::Cn(5)));
0559 }
0560 
0561 void PlotsEditor::buildCartesianParametricSurface(bool cancelIsGoHome)
0562 {
0563     if (!isEditing)
0564         reset();
0565 
0566     m_cancelIsGoHome = cancelIsGoHome;
0567 
0568     m_currentType = PlotsBuilder::CartesianParametricSurface;
0569 
0570     m_widget->plotIcon->setPixmap(QIcon::fromTheme("draw-donut").pixmap(16, 16));
0571 
0572     setupExpressionType(QStringList() << "x" << "y" << "z", QStringList() << "u" << "v", false, true);
0573 
0574     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0575     m_widget->maxx->setExpression(Analitza::Expression(Analitza::Cn(5)));
0576 
0577     m_widget->miny->setExpression(Analitza::Expression(Analitza::Cn(-5)));
0578     m_widget->maxy->setExpression(Analitza::Expression(Analitza::Cn(5)));
0579 }
0580 
0581 void PlotsEditor::buildCylindricalGraphSurface(bool cancelIsGoHome)
0582 {
0583     if (!isEditing)
0584         reset();
0585 
0586     m_cancelIsGoHome = cancelIsGoHome;
0587 
0588     m_currentType = PlotsBuilder::CylindricalGraphSurface;
0589 
0590     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newcylindrical").pixmap(16, 16));
0591 
0592     setupExpressionType(QStringList() << "r,p", QStringList() << "r" << "p");
0593 
0594     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(0)));
0595     m_widget->maxx->setExpression(Analitza::Expression(Analitza::Cn(5)));
0596 
0597     m_widget->miny->setExpression(Analitza::Expression(Analitza::Cn(0)));
0598     m_widget->maxy->setExpression(Analitza::Expression("2*pi"));
0599 }
0600 
0601 void PlotsEditor::buildSphericalGraphSurface(bool cancelIsGoHome)
0602 {
0603     if (!isEditing)
0604         reset();
0605 
0606     m_cancelIsGoHome = cancelIsGoHome;
0607 
0608     m_currentType = PlotsBuilder::SphericalGraphSurface;
0609 
0610     m_widget->plotIcon->setPixmap(QIcon::fromTheme("newspherical").pixmap(16, 16));
0611 
0612     setupExpressionType(QStringList() << "t,p", QStringList() << "t" << "p");
0613 
0614     m_widget->minx->setExpression(Analitza::Expression(Analitza::Cn(0)));
0615     m_widget->maxx->setExpression(Analitza::Expression("2*pi"));
0616 
0617     m_widget->miny->setExpression(Analitza::Expression(Analitza::Cn(0)));
0618     m_widget->maxy->setExpression(Analitza::Expression("pi"));
0619 }
0620 
0621 void PlotsEditor::savePlot()
0622 {
0623     QStringList errors;
0624 
0625     QString name = m_widget->plotName->text();
0626 
0627     if (name.isEmpty())
0628         name = 'f'+QString::number(m_document->currentPlots()->rowCount()+1);
0629 
0630     switch (m_currentType)
0631     {
0632         case PlotsBuilder::CartesianGraphCurve:
0633         case PlotsBuilder::PolarGraphCurve:
0634         {
0635             PlotBuilder req = PlotsFactory::self()->requestPlot(Analitza::Expression(QString(m_currentVars.first()+"->"+m_widget->f->expression().toString())), Dim2D);
0636             if (req.canDraw())
0637             {
0638                 FunctionGraph *item =nullptr;
0639 
0640                 if (isEditing) 
0641                 {
0642                     //remove that first and then add the new one
0643                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0644                 }
0645 
0646                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0647                 if (m_widget->intervals->isChecked())
0648                 {
0649                     item->setInterval(item->parameters().first(), m_widget->minx->expression(), m_widget->maxx->expression());
0650                 }
0651                 else
0652                     item->clearIntervals();
0653 
0654                 m_document->plotsModel()->addPlot(item);
0655                 mapDataChanged();
0656             } 
0657             else
0658                 errors = req.errors();
0659 
0660             break;
0661         }
0662         case PlotsBuilder::CartesianGraphSurface:
0663         case PlotsBuilder::CylindricalGraphSurface:
0664         case PlotsBuilder::SphericalGraphSurface:
0665         {
0666             PlotBuilder req = PlotsFactory::self()->requestPlot(m_widget->f->expression(), Dim3D);
0667             qDebug() << "------------" << m_widget->f->text() << m_widget->f->expression().toString() << req.errors();
0668             
0669             if (req.canDraw()) 
0670             {
0671                 FunctionGraph *item = nullptr;
0672 
0673                 if (isEditing) {
0674                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0675 
0676                 }
0677 
0678                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0679                 
0680                 if (m_widget->intervals->isChecked())
0681                 {
0682                     item->setInterval(item->parameters().at(0), m_widget->minx->expression(), m_widget->maxx->expression());
0683                     item->setInterval(item->parameters().at(1), m_widget->miny->expression(), m_widget->maxy->expression());
0684                 }
0685                 else
0686                     item->clearIntervals();
0687                     
0688                 m_document->plotsModel()->addPlot(item);
0689                 mapDataChanged();
0690             } 
0691             else 
0692                 errors = req.errors();
0693 
0694             break;
0695         }
0696 
0697         case PlotsBuilder::CartesianImplicitCurve:
0698         {
0699             PlotBuilder req = PlotsFactory::self()->requestPlot(m_widget->f->expression(), Dim2D);
0700             
0701             if (req.canDraw() && m_widget->f->expression().isEquation()) 
0702             {
0703                 FunctionGraph *item = nullptr;
0704 
0705                 if (isEditing)
0706                 {
0707                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0708                 }
0709 
0710                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0711 
0712                 if (m_widget->intervals->isChecked())
0713                 {
0714                     item->setInterval(item->parameters().at(0), m_widget->minx->expression(), m_widget->maxx->expression());
0715                     item->setInterval(item->parameters().at(1), m_widget->miny->expression(), m_widget->maxy->expression());
0716                 }
0717                 else
0718                     item->clearIntervals();
0719 
0720                 m_document->plotsModel()->addPlot(item);
0721 
0722                 mapDataChanged();
0723             } 
0724             else
0725                 errors = req.errors();
0726 
0727             break;
0728         }
0729 
0730         case PlotsBuilder::CartesianImplicitSurface:
0731         {
0732             PlotBuilder req = PlotsFactory::self()->requestPlot(m_widget->f->expression(), Dim3D);
0733 
0734             if (req.canDraw() && m_widget->f->expression().isEquation())
0735             {
0736                 FunctionGraph *item = nullptr;
0737 
0738                 if (isEditing)
0739                 {
0740                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0741                 }
0742 
0743                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0744 
0745                 if (m_widget->intervals->isChecked())
0746                 {
0747                     item->setInterval(item->parameters().at(0), m_widget->minx->expression(), m_widget->maxx->expression());
0748                     item->setInterval(item->parameters().at(1), m_widget->miny->expression(), m_widget->maxy->expression());
0749                     item->setInterval(item->parameters().at(2), m_widget->minz->expression(), m_widget->maxz->expression());
0750                 }
0751                 else
0752                     item->clearIntervals();
0753 
0754                 m_document->plotsModel()->addPlot(item);
0755                 mapDataChanged();
0756             }
0757             else
0758                 errors = req.errors();
0759 
0760             break;
0761         }
0762 
0763         case PlotsBuilder::CartesianParametricCurve2D:
0764         {
0765             PlotBuilder req = PlotsFactory::self()->requestPlot(Analitza::Expression(QString(m_currentVars.first()+"->vector{"+m_widget->f->expression().toString()+", "+
0766                             m_widget->g->expression().toString()+"}")), Dim2D);
0767             
0768             if (req.canDraw()) 
0769             {
0770                 FunctionGraph *item = nullptr;
0771                 
0772                 if (isEditing) 
0773                 {
0774                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0775                 }
0776                 
0777                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0778                 
0779                 if (m_widget->intervals->isChecked())
0780                     item->setInterval(item->parameters().first(), m_widget->minx->expression(), m_widget->maxx->expression());
0781                 else
0782                     item->clearIntervals();
0783 
0784                 m_document->plotsModel()->addPlot(item);
0785                 mapDataChanged();
0786             }
0787             else
0788                 errors = req.errors();
0789 
0790             break;
0791         }
0792 
0793         case PlotsBuilder::CartesianParametricCurve3D:
0794         {
0795             PlotBuilder req = PlotsFactory::self()->requestPlot(Analitza::Expression(QString(m_currentVars.first()+"->vector{"+m_widget->f->expression().toString()+", "+m_widget->g->expression().toString()+", "+m_widget->h->expression().toString()+'}')), Dim3D);
0796             
0797             if (req.canDraw())
0798             {
0799                 FunctionGraph *item = nullptr;
0800                 
0801                 if (isEditing) {
0802                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0803                 }
0804                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0805 
0806                 if (m_widget->intervals->isChecked()) {
0807                     item->setInterval(item->parameters().first(), m_widget->minx->expression(), m_widget->maxx->expression());
0808                 }
0809                 else
0810                     item->clearIntervals();
0811 
0812 
0813                 m_document->plotsModel()->addPlot(item);
0814                 mapDataChanged();
0815             } 
0816             else
0817                 errors = req.errors();
0818 
0819             break;
0820         }
0821 
0822         case PlotsBuilder::CartesianParametricSurface:
0823         {
0824             PlotBuilder req = PlotsFactory::self()->requestPlot(Analitza::Expression(QString("("+m_currentVars.join(",")+")->vector{"+m_widget->f->expression().toString()+", "+m_widget->g->expression().toString()+", "+m_widget->h->expression().toString()+'}')), Dim3D);
0825             
0826             if (req.canDraw()) 
0827             {
0828                 FunctionGraph *item = nullptr;
0829                 if (isEditing) {
0830                     m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0831                 }
0832                 item = req.create(m_widget->plotColor->color(), m_widget->plotName->text());
0833 
0834                 if (m_widget->intervals->isChecked())
0835                 {
0836                     item->setInterval(item->parameters().at(0), m_widget->minx->expression(), m_widget->maxx->expression());
0837                     item->setInterval(item->parameters().at(1), m_widget->miny->expression(), m_widget->maxy->expression());
0838                 }
0839                 else
0840                     item->clearIntervals();
0841 
0842                 m_document->plotsModel()->addPlot(item);
0843                 mapDataChanged();
0844             } 
0845             else
0846                 errors = req.errors();
0847             
0848             break;
0849         }
0850         
0851         default:
0852             break;
0853     }
0854 
0855     if (errors.isEmpty())
0856     {
0857         isEditing = false;
0858         reset();
0859         showList();
0860     }
0861     else
0862     {
0863         emit sendStatus(errors.last(), 2000); //2 secs for the user
0864     }
0865 }
0866 
0867 void PlotsEditor::removePlot()
0868 {
0869     if (m_widget->plotsView->selectionModel()->hasSelection())
0870         m_document->unmapPlot(m_widget->plotsView->selectionModel()->currentIndex());
0871     emit mapDataChanged();
0872 }
0873 
0874 void PlotsEditor::setCurrentFunctionGraphs(const QString& txt)
0875 {
0876     m_currentFunctionGraphs = txt.split(',');
0877     m_currentVars = m_currentFunctionGraphs;
0878     for (int var = 1; var <=m_currentFunctionGraphs.size(); ++var)
0879         setupVarName(var, m_currentFunctionGraphs[var-1]);
0880 }
0881 
0882 void PlotsEditor::setupVarName(int var, const QString &vvalue)
0883 {
0884     switch (var)
0885     {
0886         case 1:
0887         {
0888             m_widget->x->setText("< "+vvalue+" <");
0889             break;
0890         }
0891         case 2:
0892         {
0893             m_widget->yinterval->show();
0894             m_widget->y->setText("< "+vvalue+" <");
0895             break;
0896         }
0897         case 3:
0898         {
0899             m_widget->zinterval->show();
0900             m_widget->z->setText("< "+vvalue+" <");
0901             break;
0902         }
0903     }
0904 }
0905 
0906 void PlotsEditor::setupFuncName(int var, const QString& vvalue, const QStringList& vars, bool withparenthesis)
0907 {
0908     QString mmlhelper = vvalue;
0909 
0910     if (withparenthesis)
0911         mmlhelper.append("(");
0912 
0913     foreach(const QString &v, vars)
0914     {
0915         mmlhelper.append(v);
0916 
0917         if (v != vars.last())
0918             mmlhelper.append(",");
0919     }
0920 
0921     if (withparenthesis)
0922         mmlhelper.append(")");
0923 
0924     switch (var)
0925     {
0926         case 1:
0927         {
0928             m_widget->fname->setText(mmlhelper);
0929             m_widget->gexpression->hide();
0930             m_widget->hexpression->hide();
0931             break;
0932         }
0933         case 2:
0934         {
0935             m_widget->gname->setText(mmlhelper);
0936             m_widget->gexpression->show();
0937             m_widget->hexpression->hide();
0938             break;
0939         }
0940         case 3:
0941         {
0942             m_widget->hname->setText(mmlhelper);
0943             m_widget->hexpression->show();
0944             break;
0945         }
0946     }
0947 }
0948 
0949 void PlotsEditor::setupExpressionType(const QStringList &fvalues, const QStringList &vvalues, bool isimplicit, bool isvectorValued)
0950 {
0951     //this vars track current type of plot (see saveslot)
0952     m_currentVars = vvalues;
0953     m_currentIsImplicit = isimplicit;
0954     m_currentIsVectorValued = isvectorValued;
0955     m_currentVectorSize = isvectorValued?fvalues.size():-1;
0956 
0957     m_widget->farrow->show();
0958 
0959     if (!isimplicit && !isvectorValued)
0960     {
0961         m_widget->fnameForGraphs->show();
0962         m_widget->fname->hide();
0963         m_widget->fnameForGraphs->clear();
0964         m_widget->fnameForGraphs->addItems(fvalues);
0965     } 
0966     else 
0967     {
0968         m_widget->fnameForGraphs->hide();
0969         m_widget->fname->show();
0970     }
0971 
0972     if (!isvectorValued || !isimplicit)
0973     {
0974         m_widget->gexpression->hide();
0975         m_widget->hexpression->hide();
0976 
0977         m_widget->yinterval->hide();
0978         m_widget->zinterval->hide();
0979     }
0980 
0981     if (isimplicit)
0982     {
0983         m_widget->fnameForGraphs->hide();
0984         m_widget->fname->hide();
0985         m_widget->farrow->hide();
0986     }
0987 
0988     for (int var = 1; var <=vvalues.size(); ++var)
0989         setupVarName(var, vvalues[var-1]);
0990 
0991     if (isvectorValued)
0992     {
0993         m_widget->fnameForGraphs->hide();
0994 
0995         m_widget->farrow->setText("=");
0996 
0997         for (int func = 1; func <= fvalues.size(); ++func)
0998         {
0999             setupFuncName(func, fvalues[func-1], vvalues);
1000         }
1001     }
1002     else
1003     {
1004         if (!isimplicit)
1005         {
1006             m_widget->farrow->setText("=");
1007         }
1008     }
1009     
1010     showEditor();
1011 }
1012 
1013 void PlotsEditor::plotnamecheckClicked(bool state)
1014 {
1015     if(state==true) {
1016         m_widget->plotIcon->show();
1017         m_widget->plotName->show();
1018         if(m_widget->plotName->text().isEmpty()) {
1019             m_widget->plotName->setText(i18n("plot %1",plotnumber));
1020             plotnumber++;
1021         }
1022     } else {
1023         m_widget->plotIcon->hide();
1024         m_widget->plotName->hide();
1025     }
1026 }
1027 
1028 #include "moc_plotseditor.cpp"