moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kmplot / kmplot / kminmax.cpp
blob0edcd36529c9a01cc98b007e2fba22610d7865e0
1 /*
2 * KmPlot - a math. function plotter for the KDE-Desktop
4 * Copyright (C) 2004 Fredrik Edemar
5 * f_edemar@linux.se
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 #include <kinputdialog.h>
27 #include <klineedit.h>
28 #include <klocale.h>
29 #include <kmessagebox.h>
30 #include <kpushbutton.h>
31 #include <qlabel.h>
32 #include <qtooltip.h>
33 #include <qwhatsthis.h>
36 #include "kminmax.h"
37 #include "xparser.h"
39 KMinMax::KMinMax(View *v, QWidget *parent, const char *name)
40 : QMinMax(parent, name), m_view(v)
42 m_mode=-1;
43 connect( cmdClose, SIGNAL( clicked() ), this, SLOT( close() ));
44 connect( cmdFind, SIGNAL( clicked() ), this, SLOT( cmdFind_clicked() ));
45 connect( cmdParameter, SIGNAL( clicked() ), this, SLOT( cmdParameter_clicked() ));
46 connect( list, SIGNAL( highlighted(QListBoxItem*) ), this, SLOT( list_highlighted(QListBoxItem*) ));
47 connect( list, SIGNAL( doubleClicked( QListBoxItem * ) ), this, SLOT( list_doubleClicked(QListBoxItem *) ));
48 parameter="";
52 void KMinMax::init(char m)
54 if ( m_mode==m)
56 if ( m_mode == 2) //get y-value
57 max->setText("");
58 updateFunctions();
59 return;
62 m_mode = m;
63 if ( m_mode < 2) //find minimum point
65 max->setReadOnly(false);
66 QString range;
67 range.setNum(View::xmin);
68 min->setText( range);
69 range.setNum(View::xmax);
70 max->setText(range);
71 lblMin->setText(i18n("Search between the x-value:"));
72 lblMax->setText(i18n("and:"));
73 cmdFind->setText(i18n("&Find"));
74 QToolTip::add(min,i18n("lower boundary of the plot range"));
75 QWhatsThis::add(min,i18n("Enter the lower boundary of the plot range. Expressions like 2*pi are allowed, too."));
76 QToolTip::add(max,i18n("upper boundary of the plot range"));
77 QWhatsThis::add(max,i18n("Enter the upper boundary of the plot range. Expressions like 2*pi are allowed, too."));
79 if ( m_mode == 1) //find maximum point
81 setCaption(i18n("Find Maximum Point"));
82 QToolTip::add( cmdFind, i18n( "Search for the maximum point in the range you specified" ) );
83 QWhatsThis::add(cmdFind,i18n("Search for the highest y-value in the x-range you specified and show the result in a message box."));
85 else
87 setCaption(i18n("Find Minimum Point"));
88 QToolTip::add( cmdFind, i18n( "Search for the minimum point in the range you specified" ) );
89 QWhatsThis::add(cmdFind,i18n("Search for the lowest y-value in the x-range you specified and show the result in a message box."));
92 else if ( m_mode == 2) //get y-value
94 setCaption(i18n("Get y-Value"));
95 lblMin->setText(i18n("X:"));
96 lblMax->setText(i18n("Y:"));
97 max->setReadOnly(true);
98 min->setText("");
99 max->setText("");
100 QToolTip::add(min,i18n("lower boundary of the plot range"));
101 QWhatsThis::add(min,i18n("Enter the lower boundary of the plot range. Expressions like 2*pi are allowed, too."));
102 QToolTip::add(max,i18n("No returned y-value yet"));
103 QWhatsThis::add(max,i18n("Here you will see the y-value which you got from the x-value in the textbox above. To calculate the y-value, press the Calculate button."));
105 cmdFind->setText(i18n("&Calculate"));
106 QToolTip::add( cmdFind, i18n( "Get the y-value from the x-value you typed" ) );
107 QWhatsThis::add(cmdFind,i18n("Get the y-value from the x-value you typed and show it in the y-value box."));
110 else if ( m_mode == 3) //area under a graph
112 max->setReadOnly(false);
113 QString range;
114 range.setNum(View::xmin);
115 min->setText( range);
116 range.setNum(View::xmax);
117 max->setText(range);
118 QToolTip::add(min,i18n("lower boundary of the plot range"));
119 QWhatsThis::add(min,i18n("Enter the lower boundary of the plot range. Expressions like 2*pi are allowed, too."));
120 QToolTip::add(max,i18n("upper boundary of the plot range"));
121 QWhatsThis::add(max,i18n("Enter the upper boundary of the plot range. Expressions like 2*pi are allowed, too."));
123 setCaption(i18n("Area Under Graph"));
124 lblMin->setText(i18n("Draw the area between the x-values:"));
125 lblMax->setText(i18n("and:"));
126 cmdFind->setText(i18n("&Draw"));
127 QToolTip::add( cmdFind, i18n( "Draw the area between the function and the y-axis" ) );
128 QWhatsThis::add(cmdFind,i18n("Draw the area between the function and the y-axis and show the area in a message box."));
132 min->setFocus();
133 updateFunctions();
136 void KMinMax::updateFunctions()
138 QString const selected_item(list->currentText() );
139 list->clear();
141 for( QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin(); it != m_view->parser()->ufkt.end(); ++it)
143 if( it->fname[0] != 'x' && it->fname[0] != 'y' && it->fname[0] != 'r' && !it->fname.isEmpty())
145 if ( it->f_mode )
146 list->insertItem(it->fstr);
148 if ( it->f1_mode ) //1st derivative
150 QString function (it->fstr);
151 int i= function.find('(');
152 function.truncate(i);
153 function +="\'";
154 list->insertItem(function );
156 if ( it->f2_mode )//2nd derivative
158 QString function (it->fstr);
159 int i= function.find('(');
160 function.truncate(i);
161 function +="\'\'";
162 list->insertItem(function );
164 if ( it->integral_mode )//integral
166 QString function (it->fstr);
167 int i= function.find('(');
168 function.truncate(i);
169 function = function.upper();
170 list->insertItem(function );
174 list->sort();
175 if (list->count()==0) //empty list
176 cmdFind->setEnabled(false);
177 else
178 cmdFind->setEnabled(true);
179 selectItem();
180 QListBoxItem *found_item = list->findItem(selected_item,Qt::ExactMatch);
181 if ( found_item && m_view->csmode < 0)
182 list->setSelected(found_item,true);
185 void KMinMax::selectItem()
187 cmdParameter->hide();
188 if ( m_view->csmode < 0)
189 return;
190 //kdDebug() << "cstype: " << (int)m_view->cstype << endl;
191 Ufkt *ufkt = &m_view->parser()->ufkt[m_view->parser()->ixValue(m_view->csmode)];
192 QString function = ufkt->fstr;
193 if ( m_view->cstype == 2)
195 int i= function.find('(');
196 function.truncate(i);
197 function +="\'\'";
199 else if ( m_view->cstype == 1)
201 int i= function.find('(');
202 function.truncate(i);
203 function +="\'";
205 //kdDebug() << "function: " << function << endl;
206 QListBoxItem *item = list->findItem(function,Qt::ExactMatch);
207 list->setSelected(item,true);
209 if ( !ufkt->parameters.isEmpty() )
210 parameter = ufkt->parameters[m_view->csparam].expression;
213 KMinMax::~KMinMax()
217 void KMinMax::cmdFind_clicked()
219 if ( list->currentItem() == -1)
221 KMessageBox::error(this, i18n("Please choose a function"));
222 return;
224 double dmin, dmax;
225 dmin = m_view->parser()->eval(min->text() );
226 if ( m_view->parser()->parserError()!=0 )
228 min->setFocus();
229 min->selectAll();
230 return;
232 if ( m_mode != 2)
234 dmax = m_view->parser()->eval(max->text() );
235 if ( m_view->parser()->parserError()!=0 )
237 max->setFocus();
238 max->selectAll();
239 return;
241 if ( dmin >= dmax)
243 KMessageBox::error(this,i18n("The minimum range value must be lower than the maximum range value"));
244 min->setFocus();
245 min->selectAll();
246 return;
249 if ( dmin<View::xmin || dmax>View::xmax )
251 KMessageBox::error(this,i18n("Please insert a minimum and maximum range between %1 and %2").arg(View::xmin).arg(View::xmax) );
252 min->setFocus();
253 min->selectAll();
254 return;
259 QString function( list->currentText() );
260 char p_mode = 0;
261 if ( function.contains('\'') == 1)
263 p_mode = 1;
264 int pos = function.find('\'');
265 function.remove(pos,1);
267 else if ( function.contains('\'') == 2)
269 p_mode = 2;
270 int pos = function.find('\'');
271 function.remove(pos,2);
273 else if ( function.at(0).category() == QChar::Letter_Uppercase)
275 p_mode = 3;
276 function.at(0) = function.at(0).lower();
279 QString fname, fstr;
280 Ufkt *ufkt = 0;
281 QString sec_function = function.section('(',0,0);
283 for( QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin(); it != m_view->parser()->ufkt.end(); ++it)
285 if ( it->fstr.section('(',0,0) == sec_function)
287 ufkt = it;
288 break;
291 if ( !ufkt)
293 KMessageBox::error(this,i18n("Function could not be found"));
294 return;
297 if ( ufkt->parameters.isEmpty() )
298 parameter = "0";
299 else if ( parameter.isEmpty())
301 KMessageBox::error(this,i18n("You must choose a parameter for that function"));
302 list_highlighted(list->selectedItem() );
303 return;
307 if ( m_mode == 0)
309 m_view->findMinMaxValue(ufkt,p_mode,true,dmin,dmax,parameter);
310 if ( !m_view->isCalculationStopped() )
311 KMessageBox::information(this,i18n("Minimum value:\nx: %1\ny: %2").arg(dmin).arg(dmax) );
313 else if ( m_mode == 1)
315 m_view->findMinMaxValue(ufkt,p_mode,false,dmin,dmax,parameter);
316 if ( !m_view->isCalculationStopped() )
317 KMessageBox::information(this,i18n("Maximum value:\nx: %1\ny: %2").arg(dmin).arg(dmax));
319 else if ( m_mode == 2)
321 m_view->getYValue(ufkt,p_mode,dmin,dmax,parameter);
322 if ( !m_view->isCalculationStopped() )
324 QString tmp;
325 tmp.setNum(dmax);
326 max->setText(tmp);
328 QToolTip::add(max,i18n("The returned y-value"));
329 QWhatsThis::add(max,i18n("Here you see the result of the calculation: the returned y-value you got from the x-value in the textbox above"));
331 else if ( m_mode == 3)
333 double dmin_tmp = dmin;
334 m_view->areaUnderGraph(ufkt,p_mode,dmin,dmax,parameter, 0);
335 if ( !m_view->isCalculationStopped() )
337 m_view->setFocus();
338 m_view->update();
339 KMessageBox::information(this,i18n("The area between %1 and %2\nis: %3").arg(dmin_tmp).arg(dmax).arg(dmin));
343 if ( m_view->isCalculationStopped() )
344 KMessageBox::error(this,i18n("The operation was cancelled by the user."));
346 void KMinMax::list_highlighted(QListBoxItem* item)
348 if ( !item)
350 cmdParameter->hide();
351 return;
353 QString function( list->currentText() );
354 char p_mode = 0;
355 if ( function.contains('\'') == 1)
357 p_mode = 1;
358 int pos = function.find('\'');
359 function.remove(pos,1);
361 else if ( function.contains('\'') == 2)
363 p_mode = 2;
364 int pos = function.find('\'');
365 function.remove(pos,2);
367 else if ( function.at(0).category() == QChar::Letter_Uppercase)
369 p_mode = 3;
370 function.at(0) = function.at(0).lower();
372 QString const sec_function = function.section('(',0,0);
373 for(QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin(); it!=m_view->parser()->ufkt.end(); ++it)
375 if ( it->fstr.section('(',0,0) == sec_function)
377 if ( it->parameters.count() == 0)
378 cmdParameter->hide();
379 else
380 cmdParameter->show();
381 if (parameter.isEmpty() )
382 parameter = it->parameters.first().expression;
383 break;
387 void KMinMax::cmdParameter_clicked()
389 QString function( list->currentText() );
390 char p_mode = 0;
391 if ( function.contains('\'') == 1)
393 p_mode = 1;
394 int pos = function.find('\'');
395 function.remove(pos,1);
397 else if ( function.contains('\'') == 2)
399 p_mode = 2;
400 int pos = function.find('\'');
401 function.remove(pos,2);
403 else if ( function.at(0).category() == QChar::Letter_Uppercase)
405 p_mode = 3;
406 function.at(0) = function.at(0).lower();
409 QString const sec_function = function.section('(',0,0);
410 for(QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin() ; it!=m_view->parser()->ufkt.end(); ++it)
412 if ( it->fstr.section('(',0,0) == sec_function)
414 QStringList str_parameters;
415 for ( QValueList<ParameterValueItem>::Iterator k = it->parameters.begin(); k != it->parameters.end(); ++k )
416 str_parameters.append( (*k).expression);
417 bool ok;
418 QStringList result = KInputDialog::getItemList( i18n("Choose Parameter"), i18n("Choose a parameter to use:"), str_parameters, QStringList(parameter),false,&ok,this );
419 if ( ok)
420 parameter = result.first();
421 break;
426 void KMinMax::list_doubleClicked(QListBoxItem *)
428 if ( list->currentItem() == -1)
429 return;
430 else if( cmdParameter->isShown() )
431 cmdParameter_clicked();
433 #include "kminmax.moc"