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.
27 #include <qcheckbox.h>
28 #include <qcombobox.h>
33 #include <qradiobutton.h>
34 #include <qstringlist.h>
39 #include <kapplication.h>
40 #include <kcolorbutton.h>
41 #include <kiconloader.h>
42 #include <klineedit.h>
44 #include <kmessagebox.h>
45 #include <knuminput.h>
46 #include <kpushbutton.h>
51 #include "editfunction.h"
52 #include "editfunction.moc"
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
)
82 if( m_id
== -1 ) clearWidgets(); //new function, so clear all values
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
);
128 editfunctionpage
->customMinRange
->setChecked(false);
129 if (ufkt
->usecustomxmax
)
131 editfunctionpage
->customMaxRange
->setChecked(true);
132 editfunctionpage
->max
->setText( ufkt
->str_dmax
);
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 );
142 editfunctionpage
->useList
->setChecked( true );
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() );
175 m_parser
->fixFunctionName(f_str
, XParser::Function
, m_id
);
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"));
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)
193 editfunctionpage
->min
->setFocus();
194 editfunctionpage
->min
->selectAll();
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)
208 editfunctionpage
->max
->setFocus();
209 editfunctionpage
->max
->selectAll();
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"));
222 editfunctionpage
->min
->setFocus();
223 editfunctionpage
->min
->selectAll();
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
) );
231 editfunctionpage
->min
->setFocus();
232 editfunctionpage
->min
->selectAll();
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"));
249 editintegralpage
->txtInitX
->setFocus();
250 editintegralpage
->txtInitX
->selectAll();
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"));
261 editintegralpage
->txtInitY
->setFocus();
262 editintegralpage
->txtInitY
->selectAll();
265 tmp_ufkt
.integral_mode
= 1;
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
281 tmp_ufkt
.use_slider
= -1;
282 if ( editfunctionpage
->useNoParameter
->isChecked() || m_parameter
.isEmpty() )
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") );
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"));
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
);
326 editfunctionpage
->equation
->setFocus();
327 editfunctionpage
->equation
->selectAll();
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
338 m_parser
->parserError();
341 editfunctionpage
->equation
->setFocus();
342 editfunctionpage
->equation
->selectAll();
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
);
404 void EditFunction::noParameter_toggled(bool status
)
408 editfunctionpage
->cmdParameter
->setEnabled(false);
409 editfunctionpage
->listOfSliders
->setEnabled(false);
413 void EditFunction::customMinRange_toggled(bool status
)
416 editfunctionpage
->min
->setEnabled(true);
418 editfunctionpage
->min
->setEnabled(false);
421 void EditFunction::customMaxRange_toggled(bool status
)
424 editfunctionpage
->max
->setEnabled(true);
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( ")" );
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
)
442 parameter_name
= 'a';
443 f_str
.insert(closeBracket
,parameter_name
);
444 f_str
.insert(closeBracket
,',');