summaryrefslogtreecommitdiffstats
path: root/kmplot/kmplot/editfunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmplot/kmplot/editfunction.cpp')
-rw-r--r--kmplot/kmplot/editfunction.cpp446
1 files changed, 446 insertions, 0 deletions
diff --git a/kmplot/kmplot/editfunction.cpp b/kmplot/kmplot/editfunction.cpp
new file mode 100644
index 00000000..60786d21
--- /dev/null
+++ b/kmplot/kmplot/editfunction.cpp
@@ -0,0 +1,446 @@
+/*
+* KmPlot - a math. function plotter for the KDE-Desktop
+*
+* Copyright (C) 1998, 1999 Klaus-Dieter Möller
+* 2000, 2002 kd.moeller@t-online.de
+*
+* This file is part of the KDE Project.
+* KmPlot is part of the KDE-EDU Project.
+*
+* 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.
+*
+*/
+
+// Qt includes
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qdialog.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qstringlist.h>
+#include <qvbox.h>
+
+
+// KDE includes
+#include <kapplication.h>
+#include <kcolorbutton.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kpushbutton.h>
+
+#include <kdebug.h>
+
+// local includes
+#include "editfunction.h"
+#include "editfunction.moc"
+#include "View.h"
+#include "editfunctionpage.h"
+#include "editderivativespage.h"
+#include "editintegralpage.h"
+#include "kparametereditor.h"
+
+EditFunction::EditFunction( XParser* parser, QWidget* parent, const char* name ) :
+ KDialogBase( IconList, "Caption", Help|Ok|Cancel, Ok, parent, name ), m_parser(parser)
+{
+ QVBox *page0 = addVBoxPage( i18n("Function"), i18n( "Function" ), SmallIcon( "func", 32 ) );
+ editfunctionpage = new EditFunctionPage( page0 );
+ QVBox *page1 = addVBoxPage( i18n("Derivatives"), i18n( "Derivatives" ), SmallIcon( "deriv_func", 32 ) );
+ editderivativespage = new EditDerivativesPage( page1 );
+ QVBox *page2 = addVBoxPage( i18n("Integral"), i18n( "Integral" ), SmallIcon( "integral_func", 32 ) );
+ editintegralpage = new EditIntegralPage( page2 );
+ for( int number = 0; number < SLIDER_COUNT; number++ )
+ {
+ editfunctionpage->listOfSliders->insertItem( i18n( "Slider No. %1" ).arg( number +1) );
+ }
+ connect( editfunctionpage->cmdParameter, SIGNAL ( clicked() ), this, SLOT( cmdParameter_clicked() ) );
+ connect( editfunctionpage->useNoParameter, SIGNAL ( toggled(bool) ), this, SLOT( noParameter_toggled(bool) ) );
+ connect( editfunctionpage->customMinRange, SIGNAL ( toggled(bool) ), this, SLOT( customMinRange_toggled(bool) ) );
+ connect( editfunctionpage->customMaxRange, SIGNAL ( toggled(bool) ), this, SLOT( customMaxRange_toggled(bool) ) );
+ m_updatedfunction = 0;
+}
+
+void EditFunction::initDialog( int id )
+{
+ m_id = id;
+ if( m_id == -1 ) clearWidgets(); //new function, so clear all values
+ else setWidgets();
+ editfunctionpage->equation->setFocus();
+}
+
+void EditFunction::clearWidgets()
+{
+ // Clear the Function page
+ editfunctionpage->equation->clear();
+ editfunctionpage->hide->setChecked( false );
+ editfunctionpage->customMinRange->setChecked( false );
+ editfunctionpage->customMaxRange->setChecked( false );
+ editfunctionpage->min->clear();
+ editfunctionpage->max->clear();
+ editfunctionpage->lineWidth->setValue( m_parser->linewidth0 );
+ editfunctionpage->color->setColor( m_parser->defaultColor(m_parser->getNextIndex() ) );
+
+ // Clear the Derivatives page
+ editderivativespage->showDerivative1->setChecked( false );
+ editderivativespage->lineWidthDerivative1->setValue( editfunctionpage->lineWidth->value() );
+ editderivativespage->colorDerivative1->setColor( editfunctionpage->color->color() );
+ editderivativespage->showDerivative2->setChecked( false );
+ editderivativespage->lineWidthDerivative2->setValue( editfunctionpage->lineWidth->value() );
+ editderivativespage->colorDerivative2->setColor( editfunctionpage->color->color() );
+
+ // Clear the Integral page
+ editintegralpage->precision->setValue( Settings::stepWidth());
+ editintegralpage->color->setColor( editfunctionpage->color->color() );
+ editintegralpage->lineWidth->setValue(editfunctionpage->lineWidth->value());
+
+}
+
+void EditFunction::setWidgets()
+{
+ Ufkt *ufkt = &m_parser->ufkt[ m_parser->ixValue(m_id) ];
+ editfunctionpage->equation->setText( ufkt->fstr );
+ editfunctionpage->hide->setChecked( !ufkt->f_mode);
+ editfunctionpage->lineWidth->setValue( ufkt->linewidth );
+ editfunctionpage->color->setColor( ufkt->color );
+
+ if (ufkt->usecustomxmin)
+ {
+ editfunctionpage->customMinRange->setChecked(true);
+ editfunctionpage->min->setText( ufkt->str_dmin );
+ }
+ else
+ editfunctionpage->customMinRange->setChecked(false);
+ if (ufkt->usecustomxmax)
+ {
+ editfunctionpage->customMaxRange->setChecked(true);
+ editfunctionpage->max->setText( ufkt->str_dmax );
+ }
+ else
+ editfunctionpage->customMaxRange->setChecked(false);
+
+ m_parameter = ufkt->parameters;
+ if( ufkt->use_slider == -1 )
+ if ( ufkt->parameters.isEmpty() )
+ editfunctionpage->useNoParameter->setChecked( true );
+ else
+ editfunctionpage->useList->setChecked( true );
+ else
+ {
+ editfunctionpage->useSlider->setChecked( true );
+ editfunctionpage->listOfSliders->setCurrentItem( ufkt->use_slider );
+ }
+
+ editderivativespage->showDerivative1->setChecked( ufkt->f1_mode );
+ editderivativespage->lineWidthDerivative1->setValue( ufkt->f1_linewidth );
+ editderivativespage->colorDerivative1->setColor( ufkt->f1_color );
+ editderivativespage->showDerivative2->setChecked( ufkt->f2_mode );
+ editderivativespage->lineWidthDerivative2->setValue( ufkt->f2_linewidth );
+ editderivativespage->colorDerivative2->setColor( ufkt->f2_color );
+ editintegralpage->precision->setValue( ufkt->integral_precision );
+ editintegralpage->lineWidth->setValue( ufkt->integral_linewidth );
+ editintegralpage->color->setColor( ufkt->integral_color );
+
+ if ( ufkt->integral_mode )
+ {
+ editintegralpage->showIntegral->setChecked( ufkt->integral_mode );
+ editintegralpage->customPrecision->setChecked( ufkt->integral_use_precision );
+ editintegralpage->txtInitX->setText(ufkt->str_startx);
+ editintegralpage->txtInitY->setText(ufkt->str_starty);
+
+ }
+
+}
+
+void EditFunction::accept()
+{
+ QString f_str( editfunctionpage->equation->text() );
+
+ if ( m_id!=-1 )
+ m_parser->fixFunctionName(f_str, XParser::Function, m_id);
+ else
+ m_parser->fixFunctionName(f_str, XParser::Function);
+ if ( f_str.at(0)== 'x' || f_str.at(0)== 'y' || f_str.at(0)== 'r')
+ {
+ KMessageBox::error( this, i18n("You can only define plot functions in this dialog"));
+ return;
+ }
+
+ Ufkt tmp_ufkt; //all settings are saved here until we know that no errors have appeared
+ if( editfunctionpage->customMinRange->isChecked() )
+ {
+ tmp_ufkt.usecustomxmin = true;
+ tmp_ufkt.str_dmin = editfunctionpage->min->text();
+ tmp_ufkt.dmin = m_parser->eval( editfunctionpage->min->text() );
+ if (m_parser->parserError() != 0)
+ {
+ showPage(0);
+ editfunctionpage->min->setFocus();
+ editfunctionpage->min->selectAll();
+ return;
+ }
+ }
+ else
+ tmp_ufkt.usecustomxmin = false;
+ if( editfunctionpage->customMaxRange->isChecked() )
+ {
+ tmp_ufkt.usecustomxmax = true;
+ tmp_ufkt.str_dmax= editfunctionpage->max->text();
+ tmp_ufkt.dmax = m_parser->eval( editfunctionpage->max->text() );
+ if (m_parser->parserError() != 0)
+ {
+ showPage(0);
+ editfunctionpage->max->setFocus();
+ editfunctionpage->max->selectAll();
+ return;
+ }
+ }
+ else
+ tmp_ufkt.usecustomxmax = false;
+
+ if( tmp_ufkt.usecustomxmin && tmp_ufkt.usecustomxmax )
+ {
+ if ( tmp_ufkt.dmin >= tmp_ufkt.dmax)
+ {
+ KMessageBox::error(this,i18n("The minimum range value must be lower than the maximum range value"));
+ showPage(0);
+ editfunctionpage->min->setFocus();
+ editfunctionpage->min->selectAll();
+ return;
+ }
+
+ if ( tmp_ufkt.dmin<View::xmin || tmp_ufkt.dmax>View::xmax )
+ {
+ KMessageBox::error(this,i18n("Please insert a minimum and maximum range between %1 and %2").arg(View::xmin).arg(View::xmax) );
+ showPage(0);
+ editfunctionpage->min->setFocus();
+ editfunctionpage->min->selectAll();
+ return;
+ }
+ }
+
+ tmp_ufkt.linewidth = editfunctionpage->lineWidth->value();
+ tmp_ufkt.color = editfunctionpage->color->color().rgb();
+
+ if (editintegralpage->showIntegral->isChecked() )
+ {
+ double initx = m_parser->eval(editintegralpage->txtInitX->text());
+ tmp_ufkt.startx = initx;
+ tmp_ufkt.str_startx = editintegralpage->txtInitX->text();
+ if (m_parser->parserError(false) != 0)
+ {
+ KMessageBox::error(this,i18n("Please insert a valid x-value"));
+ showPage(2);
+ editintegralpage->txtInitX->setFocus();
+ editintegralpage->txtInitX->selectAll();
+ return;
+ }
+
+ double inity = m_parser->eval(editintegralpage->txtInitY->text());
+ tmp_ufkt.starty = inity;
+ tmp_ufkt.str_starty = editintegralpage->txtInitY->text();
+ if (m_parser->parserError(false) != 0)
+ {
+ KMessageBox::error(this,i18n("Please insert a valid y-value"));
+ showPage(2);
+ editintegralpage->txtInitY->setFocus();
+ editintegralpage->txtInitY->selectAll();
+ return;
+ }
+ tmp_ufkt.integral_mode = 1;
+ }
+ else
+ tmp_ufkt.integral_mode = 0;
+
+ tmp_ufkt.integral_color = editintegralpage->color->color().rgb();
+ tmp_ufkt.integral_use_precision = editintegralpage->customPrecision->isChecked();
+ tmp_ufkt.integral_precision = editintegralpage->precision->value();
+ tmp_ufkt.integral_linewidth = editintegralpage->lineWidth->value();
+
+ tmp_ufkt.f_mode = !editfunctionpage->hide->isChecked();
+
+ if( editfunctionpage->useSlider->isChecked() )
+ tmp_ufkt.use_slider = editfunctionpage->listOfSliders->currentItem(); //specify which slider that will be used
+ else
+ {
+ tmp_ufkt.use_slider = -1;
+ if ( editfunctionpage->useNoParameter->isChecked() || m_parameter.isEmpty() )
+ m_parameter.clear();
+ else
+ {
+ tmp_ufkt.parameters = m_parameter;
+ }
+
+ }
+
+ tmp_ufkt.f1_mode = editderivativespage->showDerivative1->isChecked();
+ tmp_ufkt.f1_linewidth = editderivativespage->lineWidthDerivative1->value();
+ tmp_ufkt.f1_color = editderivativespage->colorDerivative1->color().rgb();
+
+ tmp_ufkt.f2_mode = editderivativespage->showDerivative2->isChecked();
+ tmp_ufkt.f2_linewidth = editderivativespage->lineWidthDerivative2->value();
+ tmp_ufkt.f2_color = editderivativespage->colorDerivative2->color().rgb();
+
+ if ( f_str.contains('y') != 0 && ( tmp_ufkt.f_mode || tmp_ufkt.f1_mode || tmp_ufkt.f2_mode) )
+ {
+ KMessageBox::error( this, i18n( "Recursive function is only allowed when drawing integral graphs") );
+ return;
+ }
+
+ Ufkt *added_ufkt;
+ if( m_id != -1 ) //when editing a function:
+ {
+ int const ix = m_parser->ixValue(m_id);
+ if ( ix == -1) //The function could have been deleted
+ {
+ KMessageBox::error(this,i18n("Function could not be found"));
+ return;
+ }
+ added_ufkt = &m_parser->ufkt[ix];
+ QString const old_fstr = added_ufkt->fstr;
+ if(( (!m_parameter.isEmpty() && editfunctionpage->useList->isChecked() ) || editfunctionpage->useSlider->isChecked() ) && !functionHas2Arguments() )
+ fixFunctionArguments(f_str); //adding an extra argument for the parameter value
+ added_ufkt->fstr = f_str;
+ m_parser->reparse(added_ufkt); //reparse the funcion
+ if ( m_parser->parserError() != 0)
+ {
+ added_ufkt->fstr = old_fstr;
+ m_parser->reparse(added_ufkt);
+ raise();
+ showPage(0);
+ editfunctionpage->equation->setFocus();
+ editfunctionpage->equation->selectAll();
+ return;
+ }
+ }
+ else //creating a new function
+ {
+ if(( (!m_parameter.isEmpty() && editfunctionpage->useList->isChecked() ) || editfunctionpage->useSlider->isChecked() ) && !functionHas2Arguments() )
+ fixFunctionArguments(f_str); //adding an extra argument for the parameter value
+ int const id = m_parser->addfkt( f_str ); //create a new function otherwise
+ if( id == -1)
+ {
+ m_parser->parserError();
+ raise();
+ showPage(0);
+ editfunctionpage->equation->setFocus();
+ editfunctionpage->equation->selectAll();
+ return;
+ }
+ added_ufkt = &m_parser->ufkt.last();
+ }
+ //save all settings in the function now when we know no errors have appeared
+ added_ufkt->f_mode = tmp_ufkt.f_mode;
+ added_ufkt->f1_mode = tmp_ufkt.f1_mode;
+ added_ufkt->f2_mode = tmp_ufkt.f2_mode;
+ added_ufkt->integral_mode = tmp_ufkt.integral_mode;
+ added_ufkt->integral_use_precision = tmp_ufkt.integral_use_precision;
+ added_ufkt->linewidth = tmp_ufkt.linewidth;
+ added_ufkt->f1_linewidth = tmp_ufkt.f1_linewidth;
+ added_ufkt->f2_linewidth = tmp_ufkt.f2_linewidth;
+ added_ufkt->integral_linewidth = tmp_ufkt.integral_linewidth;
+ added_ufkt->str_dmin = tmp_ufkt.str_dmin;
+ added_ufkt->str_dmax = tmp_ufkt.str_dmax;
+ added_ufkt->dmin = tmp_ufkt.dmin;
+ added_ufkt->dmax = tmp_ufkt.dmax;
+ added_ufkt->str_startx = tmp_ufkt.str_startx;
+ added_ufkt->str_starty = tmp_ufkt.str_starty;
+ added_ufkt->oldx = tmp_ufkt.oldx;
+ added_ufkt->starty = tmp_ufkt.starty;
+ added_ufkt->startx = tmp_ufkt.startx;
+ added_ufkt->integral_precision = tmp_ufkt.integral_precision;
+ added_ufkt->color = tmp_ufkt.color;
+ added_ufkt->f1_color = tmp_ufkt.f1_color;
+ added_ufkt->f2_color = tmp_ufkt.f2_color;
+ added_ufkt->integral_color = tmp_ufkt.integral_color;
+ added_ufkt->parameters = tmp_ufkt.parameters;
+ added_ufkt->use_slider = tmp_ufkt.use_slider;
+ added_ufkt->usecustomxmin = tmp_ufkt.usecustomxmin;
+ added_ufkt->usecustomxmax = tmp_ufkt.usecustomxmax;
+
+ m_updatedfunction = added_ufkt;
+
+ // call inherited method
+ KDialogBase::accept();
+}
+
+Ufkt * EditFunction::functionItem()
+{
+ return m_updatedfunction;
+}
+
+void EditFunction::slotHelp()
+{
+ kapp->invokeHelp( "", "kmplot" );
+}
+
+bool EditFunction::functionHas2Arguments()
+{
+ int const openBracket = editfunctionpage->equation->text().find( "(" );
+ int const closeBracket = editfunctionpage->equation->text().find( ")" );
+ return editfunctionpage->equation->text().mid( openBracket+1, closeBracket-openBracket-1 ).find( "," ) != -1;
+}
+void EditFunction::cmdParameter_clicked()
+{
+ editfunctionpage->useList->setChecked(true);
+ KParameterEditor *dlg = new KParameterEditor(m_parser,&m_parameter);
+ dlg->show();
+}
+void EditFunction::noParameter_toggled(bool status)
+{
+ if (status)
+ {
+ editfunctionpage->cmdParameter->setEnabled(false);
+ editfunctionpage->listOfSliders->setEnabled(false);
+ }
+}
+
+void EditFunction::customMinRange_toggled(bool status)
+{
+ if (status)
+ editfunctionpage->min->setEnabled(true);
+ else
+ editfunctionpage->min->setEnabled(false);
+}
+
+void EditFunction::customMaxRange_toggled(bool status)
+{
+ if (status)
+ editfunctionpage->max->setEnabled(true);
+ else
+ editfunctionpage->max->setEnabled(false);
+}
+
+void EditFunction::fixFunctionArguments(QString &f_str)
+{
+ int const openBracket = f_str.find( "(" );
+ int const closeBracket = f_str.find( ")" );
+ char parameter_name;
+ if ( closeBracket-openBracket == 2) //the function atribute is only one character
+ {
+ char const function_name = f_str.at(openBracket+1).latin1();
+ parameter_name = 'a';
+ while ( parameter_name == function_name)
+ parameter_name++;
+ }
+ else
+ parameter_name = 'a';
+ f_str.insert(closeBracket,parameter_name);
+ f_str.insert(closeBracket,',');
+}
+