moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kmplot / kmplot / editfunction.cpp
blobfc082f4dd7b6701359462c3c8bbf624093071803
1 /*
2 * KmPlot - a math. function plotter for the KDE-Desktop
4 * Copyright (C) 1998, 1999 Klaus-Dieter Möller
5 * 2000, 2002 kd.moeller@t-online.de
7 * This file is part of the KDE Project.
8 * KmPlot is part of the KDE-EDU Project.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 // Qt includes
27 #include <qcheckbox.h>
28 #include <qcombobox.h>
29 #include <qdialog.h>
30 #include <qframe.h>
31 #include <qlabel.h>
32 #include <qlayout.h>
33 #include <qradiobutton.h>
34 #include <qstringlist.h>
35 #include <qvbox.h>
38 // KDE includes
39 #include <kapplication.h>
40 #include <kcolorbutton.h>
41 #include <kiconloader.h>
42 #include <klineedit.h>
43 #include <klocale.h>
44 #include <kmessagebox.h>
45 #include <knuminput.h>
46 #include <kpushbutton.h>
48 #include <kdebug.h>
50 // local includes
51 #include "editfunction.h"
52 #include "editfunction.moc"
53 #include "View.h"
54 #include "editfunctionpage.h"
55 #include "editderivativespage.h"
56 #include "editintegralpage.h"
57 #include "kparametereditor.h"
59 EditFunction::EditFunction( XParser* parser, QWidget* parent, const char* name ) :
60 KDialogBase( IconList, "Caption", Help|Ok|Cancel, Ok, parent, name ), m_parser(parser)
62 QVBox *page0 = addVBoxPage( i18n("Function"), i18n( "Function" ), SmallIcon( "func", 32 ) );
63 editfunctionpage = new EditFunctionPage( page0 );
64 QVBox *page1 = addVBoxPage( i18n("Derivatives"), i18n( "Derivatives" ), SmallIcon( "deriv_func", 32 ) );
65 editderivativespage = new EditDerivativesPage( page1 );
66 QVBox *page2 = addVBoxPage( i18n("Integral"), i18n( "Integral" ), SmallIcon( "integral_func", 32 ) );
67 editintegralpage = new EditIntegralPage( page2 );
68 for( int number = 0; number < SLIDER_COUNT; number++ )
70 editfunctionpage->listOfSliders->insertItem( i18n( "Slider no. %1" ).arg( number +1) );
72 connect( editfunctionpage->cmdParameter, SIGNAL ( clicked() ), this, SLOT( cmdParameter_clicked() ) );
73 connect( editfunctionpage->useNoParameter, SIGNAL ( toggled(bool) ), this, SLOT( noParameter_toggled(bool) ) );
74 connect( editfunctionpage->customMinRange, SIGNAL ( toggled(bool) ), this, SLOT( customMinRange_toggled(bool) ) );
75 connect( editfunctionpage->customMaxRange, SIGNAL ( toggled(bool) ), this, SLOT( customMaxRange_toggled(bool) ) );
76 m_updatedfunction = 0;
79 void EditFunction::initDialog( int id )
81 m_id = id;
82 if( m_id == -1 ) clearWidgets(); //new function, so clear all values
83 else setWidgets();
84 editfunctionpage->equation->setFocus();
87 void EditFunction::clearWidgets()
89 // Clear the Function page
90 editfunctionpage->equation->clear();
91 editfunctionpage->hide->setChecked( false );
92 editfunctionpage->customMinRange->setChecked( false );
93 editfunctionpage->customMaxRange->setChecked( false );
94 editfunctionpage->min->clear();
95 editfunctionpage->max->clear();
96 editfunctionpage->lineWidth->setValue( m_parser->linewidth0 );
97 editfunctionpage->color->setColor( m_parser->defaultColor(m_parser->getNextIndex() ) );
99 // Clear the Derivatives page
100 editderivativespage->showDerivative1->setChecked( false );
101 editderivativespage->lineWidthDerivative1->setValue( editfunctionpage->lineWidth->value() );
102 editderivativespage->colorDerivative1->setColor( editfunctionpage->color->color() );
103 editderivativespage->showDerivative2->setChecked( false );
104 editderivativespage->lineWidthDerivative2->setValue( editfunctionpage->lineWidth->value() );
105 editderivativespage->colorDerivative2->setColor( editfunctionpage->color->color() );
107 // Clear the Integral page
108 editintegralpage->precision->setValue( Settings::stepWidth());
109 editintegralpage->color->setColor( editfunctionpage->color->color() );
110 editintegralpage->lineWidth->setValue(editfunctionpage->lineWidth->value());
114 void EditFunction::setWidgets()
116 Ufkt *ufkt = &m_parser->ufkt[ m_parser->ixValue(m_id) ];
117 editfunctionpage->equation->setText( ufkt->fstr );
118 editfunctionpage->hide->setChecked( !ufkt->f_mode);
119 editfunctionpage->lineWidth->setValue( ufkt->linewidth );
120 editfunctionpage->color->setColor( ufkt->color );
122 if (ufkt->usecustomxmin)
124 editfunctionpage->customMinRange->setChecked(true);
125 editfunctionpage->min->setText( ufkt->str_dmin );
127 else
128 editfunctionpage->customMinRange->setChecked(false);
129 if (ufkt->usecustomxmax)
131 editfunctionpage->customMaxRange->setChecked(true);
132 editfunctionpage->max->setText( ufkt->str_dmax );
134 else
135 editfunctionpage->customMaxRange->setChecked(false);
137 m_parameter = ufkt->parameters;
138 if( ufkt->use_slider == -1 )
139 if ( ufkt->parameters.isEmpty() )
140 editfunctionpage->useNoParameter->setChecked( true );
141 else
142 editfunctionpage->useList->setChecked( true );
143 else
145 editfunctionpage->useSlider->setChecked( true );
146 editfunctionpage->listOfSliders->setCurrentItem( ufkt->use_slider );
149 editderivativespage->showDerivative1->setChecked( ufkt->f1_mode );
150 editderivativespage->lineWidthDerivative1->setValue( ufkt->f1_linewidth );
151 editderivativespage->colorDerivative1->setColor( ufkt->f1_color );
152 editderivativespage->showDerivative2->setChecked( ufkt->f2_mode );
153 editderivativespage->lineWidthDerivative2->setValue( ufkt->f2_linewidth );
154 editderivativespage->colorDerivative2->setColor( ufkt->f2_color );
155 editintegralpage->precision->setValue( ufkt->integral_precision );
156 editintegralpage->lineWidth->setValue( ufkt->integral_linewidth );
157 editintegralpage->color->setColor( ufkt->integral_color );
159 if ( ufkt->integral_mode )
161 editintegralpage->showIntegral->setChecked( ufkt->integral_mode );
162 editintegralpage->customPrecision->setChecked( ufkt->integral_use_precision );
163 editintegralpage->txtInitX->setText(ufkt->str_startx);
164 editintegralpage->txtInitY->setText(ufkt->str_starty);
170 void EditFunction::accept()
172 QString f_str( editfunctionpage->equation->text() );
174 if ( m_id!=-1 )
175 m_parser->fixFunctionName(f_str, XParser::Function, m_id);
176 else
177 m_parser->fixFunctionName(f_str, XParser::Function);
178 if ( f_str.at(0)== 'x' || f_str.at(0)== 'y' || f_str.at(0)== 'r')
180 KMessageBox::error( this, i18n("You can only define plot functions in this dialog"));
181 return;
184 Ufkt tmp_ufkt; //all settings are saved here until we know that no errors have appeared
185 if( editfunctionpage->customMinRange->isChecked() )
187 tmp_ufkt.usecustomxmin = true;
188 tmp_ufkt.str_dmin = editfunctionpage->min->text();
189 tmp_ufkt.dmin = m_parser->eval( editfunctionpage->min->text() );
190 if (m_parser->parserError() != 0)
192 showPage(0);
193 editfunctionpage->min->setFocus();
194 editfunctionpage->min->selectAll();
195 return;
198 else
199 tmp_ufkt.usecustomxmin = false;
200 if( editfunctionpage->customMaxRange->isChecked() )
202 tmp_ufkt.usecustomxmax = true;
203 tmp_ufkt.str_dmax= editfunctionpage->max->text();
204 tmp_ufkt.dmax = m_parser->eval( editfunctionpage->max->text() );
205 if (m_parser->parserError() != 0)
207 showPage(0);
208 editfunctionpage->max->setFocus();
209 editfunctionpage->max->selectAll();
210 return;
213 else
214 tmp_ufkt.usecustomxmax = false;
216 if( tmp_ufkt.usecustomxmin && tmp_ufkt.usecustomxmax )
218 if ( tmp_ufkt.dmin >= tmp_ufkt.dmax)
220 KMessageBox::error(this,i18n("The minimum range value must be lower than the maximum range value"));
221 showPage(0);
222 editfunctionpage->min->setFocus();
223 editfunctionpage->min->selectAll();
224 return;
227 if ( tmp_ufkt.dmin<View::xmin || tmp_ufkt.dmax>View::xmax )
229 KMessageBox::error(this,i18n("Please insert a minimum and maximum range between %1 and %2").arg(View::xmin).arg(View::xmax) );
230 showPage(0);
231 editfunctionpage->min->setFocus();
232 editfunctionpage->min->selectAll();
233 return;
237 tmp_ufkt.linewidth = editfunctionpage->lineWidth->value();
238 tmp_ufkt.color = editfunctionpage->color->color().rgb();
240 if (editintegralpage->showIntegral->isChecked() )
242 double initx = m_parser->eval(editintegralpage->txtInitX->text());
243 tmp_ufkt.startx = initx;
244 tmp_ufkt.str_startx = editintegralpage->txtInitX->text();
245 if (m_parser->parserError(false) != 0)
247 KMessageBox::error(this,i18n("Please insert a valid x-value"));
248 showPage(2);
249 editintegralpage->txtInitX->setFocus();
250 editintegralpage->txtInitX->selectAll();
251 return;
254 double inity = m_parser->eval(editintegralpage->txtInitY->text());
255 tmp_ufkt.starty = inity;
256 tmp_ufkt.str_starty = editintegralpage->txtInitY->text();
257 if (m_parser->parserError(false) != 0)
259 KMessageBox::error(this,i18n("Please insert a valid y-value"));
260 showPage(2);
261 editintegralpage->txtInitY->setFocus();
262 editintegralpage->txtInitY->selectAll();
263 return;
265 tmp_ufkt.integral_mode = 1;
267 else
268 tmp_ufkt.integral_mode = 0;
270 tmp_ufkt.integral_color = editintegralpage->color->color().rgb();
271 tmp_ufkt.integral_use_precision = editintegralpage->customPrecision->isChecked();
272 tmp_ufkt.integral_precision = editintegralpage->precision->value();
273 tmp_ufkt.integral_linewidth = editintegralpage->lineWidth->value();
275 tmp_ufkt.f_mode = !editfunctionpage->hide->isChecked();
277 if( editfunctionpage->useSlider->isChecked() )
278 tmp_ufkt.use_slider = editfunctionpage->listOfSliders->currentItem(); //specify which slider that will be used
279 else
281 tmp_ufkt.use_slider = -1;
282 if ( editfunctionpage->useNoParameter->isChecked() || m_parameter.isEmpty() )
283 m_parameter.clear();
284 else
286 tmp_ufkt.parameters = m_parameter;
291 tmp_ufkt.f1_mode = editderivativespage->showDerivative1->isChecked();
292 tmp_ufkt.f1_linewidth = editderivativespage->lineWidthDerivative1->value();
293 tmp_ufkt.f1_color = editderivativespage->colorDerivative1->color().rgb();
295 tmp_ufkt.f2_mode = editderivativespage->showDerivative2->isChecked();
296 tmp_ufkt.f2_linewidth = editderivativespage->lineWidthDerivative2->value();
297 tmp_ufkt.f2_color = editderivativespage->colorDerivative2->color().rgb();
299 if ( f_str.contains('y') != 0 && ( tmp_ufkt.f_mode || tmp_ufkt.f1_mode || tmp_ufkt.f2_mode) )
301 KMessageBox::error( this, i18n( "Recursive function is only allowed when drawing integral graphs") );
302 return;
305 Ufkt *added_ufkt;
306 if( m_id != -1 ) //when editing a function:
308 int const ix = m_parser->ixValue(m_id);
309 if ( ix == -1) //The function could have been deleted
311 KMessageBox::error(this,i18n("Function could not be found"));
312 return;
314 added_ufkt = &m_parser->ufkt[ix];
315 QString const old_fstr = added_ufkt->fstr;
316 if(( (!m_parameter.isEmpty() && editfunctionpage->useList->isChecked() ) || editfunctionpage->useSlider->isChecked() ) && !functionHas2Arguments() )
317 fixFunctionArguments(f_str); //adding an extra argument for the parameter value
318 added_ufkt->fstr = f_str;
319 m_parser->reparse(added_ufkt); //reparse the funcion
320 if ( m_parser->parserError() != 0)
322 added_ufkt->fstr = old_fstr;
323 m_parser->reparse(added_ufkt);
324 raise();
325 showPage(0);
326 editfunctionpage->equation->setFocus();
327 editfunctionpage->equation->selectAll();
328 return;
331 else //creating a new function
333 if(( (!m_parameter.isEmpty() && editfunctionpage->useList->isChecked() ) || editfunctionpage->useSlider->isChecked() ) && !functionHas2Arguments() )
334 fixFunctionArguments(f_str); //adding an extra argument for the parameter value
335 int const id = m_parser->addfkt( f_str ); //create a new function otherwise
336 if( id == -1)
338 m_parser->parserError();
339 raise();
340 showPage(0);
341 editfunctionpage->equation->setFocus();
342 editfunctionpage->equation->selectAll();
343 return;
345 added_ufkt = &m_parser->ufkt.last();
347 //save all settings in the function now when we know no errors have appeared
348 added_ufkt->f_mode = tmp_ufkt.f_mode;
349 added_ufkt->f1_mode = tmp_ufkt.f1_mode;
350 added_ufkt->f2_mode = tmp_ufkt.f2_mode;
351 added_ufkt->integral_mode = tmp_ufkt.integral_mode;
352 added_ufkt->integral_use_precision = tmp_ufkt.integral_use_precision;
353 added_ufkt->linewidth = tmp_ufkt.linewidth;
354 added_ufkt->f1_linewidth = tmp_ufkt.f1_linewidth;
355 added_ufkt->f2_linewidth = tmp_ufkt.f2_linewidth;
356 added_ufkt->integral_linewidth = tmp_ufkt.integral_linewidth;
357 added_ufkt->str_dmin = tmp_ufkt.str_dmin;
358 added_ufkt->str_dmax = tmp_ufkt.str_dmax;
359 added_ufkt->dmin = tmp_ufkt.dmin;
360 added_ufkt->dmax = tmp_ufkt.dmax;
361 added_ufkt->str_startx = tmp_ufkt.str_startx;
362 added_ufkt->str_starty = tmp_ufkt.str_starty;
363 added_ufkt->oldx = tmp_ufkt.oldx;
364 added_ufkt->starty = tmp_ufkt.starty;
365 added_ufkt->startx = tmp_ufkt.startx;
366 added_ufkt->integral_precision = tmp_ufkt.integral_precision;
367 added_ufkt->color = tmp_ufkt.color;
368 added_ufkt->f1_color = tmp_ufkt.f1_color;
369 added_ufkt->f2_color = tmp_ufkt.f2_color;
370 added_ufkt->integral_color = tmp_ufkt.integral_color;
371 added_ufkt->parameters = tmp_ufkt.parameters;
372 added_ufkt->use_slider = tmp_ufkt.use_slider;
373 added_ufkt->usecustomxmin = tmp_ufkt.usecustomxmin;
374 added_ufkt->usecustomxmax = tmp_ufkt.usecustomxmax;
376 m_updatedfunction = added_ufkt;
378 // call inherited method
379 KDialogBase::accept();
382 Ufkt * EditFunction::functionItem()
384 return m_updatedfunction;
387 void EditFunction::slotHelp()
389 kapp->invokeHelp( "", "kmplot" );
392 bool EditFunction::functionHas2Arguments()
394 int const openBracket = editfunctionpage->equation->text().find( "(" );
395 int const closeBracket = editfunctionpage->equation->text().find( ")" );
396 return editfunctionpage->equation->text().mid( openBracket+1, closeBracket-openBracket-1 ).find( "," ) != -1;
398 void EditFunction::cmdParameter_clicked()
400 editfunctionpage->useList->setChecked(true);
401 KParameterEditor *dlg = new KParameterEditor(m_parser,&m_parameter);
402 dlg->show();
404 void EditFunction::noParameter_toggled(bool status)
406 if (status)
408 editfunctionpage->cmdParameter->setEnabled(false);
409 editfunctionpage->listOfSliders->setEnabled(false);
413 void EditFunction::customMinRange_toggled(bool status)
415 if (status)
416 editfunctionpage->min->setEnabled(true);
417 else
418 editfunctionpage->min->setEnabled(false);
421 void EditFunction::customMaxRange_toggled(bool status)
423 if (status)
424 editfunctionpage->max->setEnabled(true);
425 else
426 editfunctionpage->max->setEnabled(false);
429 void EditFunction::fixFunctionArguments(QString &f_str)
431 int const openBracket = f_str.find( "(" );
432 int const closeBracket = f_str.find( ")" );
433 char parameter_name;
434 if ( closeBracket-openBracket == 2) //the function atribute is only one character
436 char const function_name = f_str.at(openBracket+1).latin1();
437 parameter_name = 'a';
438 while ( parameter_name == function_name)
439 parameter_name++;
441 else
442 parameter_name = 'a';
443 f_str.insert(closeBracket,parameter_name);
444 f_str.insert(closeBracket,',');