summaryrefslogtreecommitdiffstats
path: root/kmplot/kmplot/kminmax.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmplot/kmplot/kminmax.cpp')
-rw-r--r--kmplot/kmplot/kminmax.cpp435
1 files changed, 435 insertions, 0 deletions
diff --git a/kmplot/kmplot/kminmax.cpp b/kmplot/kmplot/kminmax.cpp
new file mode 100644
index 00000000..bf4e69a8
--- /dev/null
+++ b/kmplot/kmplot/kminmax.cpp
@@ -0,0 +1,435 @@
+/*
+* KmPlot - a math. function plotter for the KDE-Desktop
+*
+* Copyright (C) 2004 Fredrik Edemar
+* f_edemar@linux.se
+*
+* 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.
+*
+*/
+
+#include <kinputdialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+
+#include "kminmax.h"
+#include "xparser.h"
+
+KMinMax::KMinMax(View *v, QWidget *parent, const char *name)
+ : QMinMax(parent, name), m_view(v)
+{
+ m_mode=-1;
+ connect( cmdClose, SIGNAL( clicked() ), this, SLOT( close() ));
+ connect( cmdFind, SIGNAL( clicked() ), this, SLOT( cmdFind_clicked() ));
+ connect( cmdParameter, SIGNAL( clicked() ), this, SLOT( cmdParameter_clicked() ));
+ connect( list, SIGNAL( highlighted(QListBoxItem*) ), this, SLOT( list_highlighted(QListBoxItem*) ));
+ connect( list, SIGNAL( doubleClicked( QListBoxItem * ) ), this, SLOT( list_doubleClicked(QListBoxItem *) ));
+ parameter="";
+}
+
+
+void KMinMax::init(char m)
+{
+ if ( m_mode==m)
+ {
+ if ( m_mode == 2) //get y-value
+ max->setText("");
+ updateFunctions();
+ return;
+ }
+
+ m_mode = m;
+ if ( m_mode < 2) //find minimum point
+ {
+ max->setReadOnly(false);
+ QString range;
+ range.setNum(View::xmin);
+ min->setText( range);
+ range.setNum(View::xmax);
+ max->setText(range);
+ lblMin->setText(i18n("Search between the x-value:"));
+ lblMax->setText(i18n("and:"));
+ cmdFind->setText(i18n("&Find"));
+ QToolTip::add(min,i18n("Lower boundary of the plot range"));
+ QWhatsThis::add(min,i18n("Enter the lower boundary of the plot range. Expressions like 2*pi are allowed, too."));
+ QToolTip::add(max,i18n("Upper boundary of the plot range"));
+ QWhatsThis::add(max,i18n("Enter the upper boundary of the plot range. Expressions like 2*pi are allowed, too."));
+
+ if ( m_mode == 1) //find maximum point
+ {
+ setCaption(i18n("Find Maximum Point"));
+ QToolTip::add( cmdFind, i18n( "Search for the maximum point in the range you specified" ) );
+ QWhatsThis::add(cmdFind,i18n("Search for the highest y-value in the x-range you specified and show the result in a message box."));
+ }
+ else
+ {
+ setCaption(i18n("Find Minimum Point"));
+ QToolTip::add( cmdFind, i18n( "Search for the minimum point in the range you specified" ) );
+ QWhatsThis::add(cmdFind,i18n("Search for the lowest y-value in the x-range you specified and show the result in a message box."));
+ }
+ }
+ else if ( m_mode == 2) //get y-value
+ {
+ setCaption(i18n("Get y-Value"));
+ lblMin->setText(i18n("X:"));
+ lblMax->setText(i18n("Y:"));
+ max->setReadOnly(true);
+ min->setText("");
+ max->setText("");
+ QToolTip::add(min,i18n("Lower boundary of the plot range"));
+ QWhatsThis::add(min,i18n("Enter the lower boundary of the plot range. Expressions like 2*pi are allowed, too."));
+ QToolTip::add(max,i18n("No returned y-value yet"));
+ 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."));
+
+ cmdFind->setText(i18n("&Calculate"));
+ QToolTip::add( cmdFind, i18n( "Get the y-value from the x-value you typed" ) );
+ QWhatsThis::add(cmdFind,i18n("Get the y-value from the x-value you typed and show it in the y-value box."));
+
+ }
+ else if ( m_mode == 3) //area under a graph
+ {
+ max->setReadOnly(false);
+ QString range;
+ range.setNum(View::xmin);
+ min->setText( range);
+ range.setNum(View::xmax);
+ max->setText(range);
+ QToolTip::add(min,i18n("Lower boundary of the plot range"));
+ QWhatsThis::add(min,i18n("Enter the lower boundary of the plot range. Expressions like 2*pi are allowed, too."));
+ QToolTip::add(max,i18n("Upper boundary of the plot range"));
+ QWhatsThis::add(max,i18n("Enter the upper boundary of the plot range. Expressions like 2*pi are allowed, too."));
+
+ setCaption(i18n("Calculate Integral"));
+ lblMin->setText(i18n("Calculate the integral between the x-values:"));
+ lblMax->setText(i18n("and:"));
+ cmdFind->setText(i18n("&Calculate"));
+ QToolTip::add( cmdFind, i18n( "Calculate the integral between the x-values" ) );
+ QWhatsThis::add(cmdFind,i18n("Calculate the numeric integral between the x-values and draw the result as an area."));
+
+ }
+
+ min->setFocus();
+ updateFunctions();
+}
+
+void KMinMax::updateFunctions()
+{
+ QString const selected_item(list->currentText() );
+ list->clear();
+
+ for( QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin(); it != m_view->parser()->ufkt.end(); ++it)
+ {
+ if( it->fname[0] != 'x' && it->fname[0] != 'y' && it->fname[0] != 'r' && !it->fname.isEmpty())
+ {
+ if ( it->f_mode )
+ list->insertItem(it->fstr);
+
+ if ( it->f1_mode ) //1st derivative
+ {
+ QString function (it->fstr);
+ int i= function.find('(');
+ function.truncate(i);
+ function +="\'";
+ list->insertItem(function );
+ }
+ if ( it->f2_mode )//2nd derivative
+ {
+ QString function (it->fstr);
+ int i= function.find('(');
+ function.truncate(i);
+ function +="\'\'";
+ list->insertItem(function );
+ }
+ if ( it->integral_mode )//integral
+ {
+ QString function (it->fstr);
+ int i= function.find('(');
+ function.truncate(i);
+ function = function.upper();
+ list->insertItem(function );
+ }
+ }
+ }
+ list->sort();
+ if (list->count()==0) //empty list
+ cmdFind->setEnabled(false);
+ else
+ cmdFind->setEnabled(true);
+ selectItem();
+ QListBoxItem *found_item = list->findItem(selected_item,Qt::ExactMatch);
+ if ( found_item && m_view->csmode < 0)
+ list->setSelected(found_item,true);
+}
+
+void KMinMax::selectItem()
+{
+ cmdParameter->hide();
+ if ( m_view->csmode < 0)
+ return;
+ //kdDebug() << "cstype: " << (int)m_view->cstype << endl;
+ Ufkt *ufkt = &m_view->parser()->ufkt[m_view->parser()->ixValue(m_view->csmode)];
+ QString function = ufkt->fstr;
+ if ( m_view->cstype == 2)
+ {
+ int i= function.find('(');
+ function.truncate(i);
+ function +="\'\'";
+ }
+ else if ( m_view->cstype == 1)
+ {
+ int i= function.find('(');
+ function.truncate(i);
+ function +="\'";
+ }
+ //kdDebug() << "function: " << function << endl;
+ QListBoxItem *item = list->findItem(function,Qt::ExactMatch);
+ list->setSelected(item,true);
+
+ if ( !ufkt->parameters.isEmpty() )
+ parameter = ufkt->parameters[m_view->csparam].expression;
+}
+
+KMinMax::~KMinMax()
+{
+}
+
+void KMinMax::cmdFind_clicked()
+{
+ if ( list->currentItem() == -1)
+ {
+ KMessageBox::error(this, i18n("Please choose a function"));
+ return;
+ }
+ double dmin, dmax;
+ dmin = m_view->parser()->eval(min->text() );
+ if ( m_view->parser()->parserError()!=0 )
+ {
+ min->setFocus();
+ min->selectAll();
+ return;
+ }
+ if ( m_mode != 2)
+ {
+ dmax = m_view->parser()->eval(max->text() );
+ if ( m_view->parser()->parserError()!=0 )
+ {
+ max->setFocus();
+ max->selectAll();
+ return;
+ }
+ if ( dmin >= dmax)
+ {
+ KMessageBox::error(this,i18n("The minimum range value must be lower than the maximum range value"));
+ min->setFocus();
+ min->selectAll();
+ return;
+ }
+
+ if ( dmin<View::xmin || dmax>View::xmax )
+ {
+ KMessageBox::error(this,i18n("Please insert a minimum and maximum range between %1 and %2").arg(View::xmin).arg(View::xmax) );
+ min->setFocus();
+ min->selectAll();
+ return;
+ }
+ }
+
+
+ QString function( list->currentText() );
+ char p_mode = 0;
+ if ( function.contains('\'') == 1)
+ {
+ p_mode = 1;
+ int pos = function.find('\'');
+ function.remove(pos,1);
+ }
+ else if ( function.contains('\'') == 2)
+ {
+ p_mode = 2;
+ int pos = function.find('\'');
+ function.remove(pos,2);
+ }
+ else if ( function.at(0).category() == QChar::Letter_Uppercase)
+ {
+ p_mode = 3;
+ function.at(0) = function.at(0).lower();
+ }
+
+ QString fname, fstr;
+ Ufkt *ufkt = 0;
+ QString sec_function = function.section('(',0,0);
+
+ for( QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin(); it != m_view->parser()->ufkt.end(); ++it)
+ {
+ if ( it->fstr.section('(',0,0) == sec_function)
+ {
+ ufkt = it;
+ break;
+ }
+ }
+ if ( !ufkt)
+ {
+ KMessageBox::error(this,i18n("Function could not be found"));
+ return;
+ }
+
+ if ( ufkt->parameters.isEmpty() )
+ parameter = "0";
+ else if ( parameter.isEmpty())
+ {
+ KMessageBox::error(this,i18n("You must choose a parameter for that function"));
+ list_highlighted(list->selectedItem() );
+ return;
+ }
+
+
+ if ( m_mode == 0)
+ {
+ m_view->findMinMaxValue(ufkt,p_mode,true,dmin,dmax,parameter);
+ if ( !m_view->isCalculationStopped() )
+ KMessageBox::information(this,i18n("Minimum value:\nx: %1\ny: %2").arg(dmin).arg(dmax) );
+ }
+ else if ( m_mode == 1)
+ {
+ m_view->findMinMaxValue(ufkt,p_mode,false,dmin,dmax,parameter);
+ if ( !m_view->isCalculationStopped() )
+ KMessageBox::information(this,i18n("Maximum value:\nx: %1\ny: %2").arg(dmin).arg(dmax));
+ }
+ else if ( m_mode == 2)
+ {
+ m_view->getYValue(ufkt,p_mode,dmin,dmax,parameter);
+ if ( !m_view->isCalculationStopped() )
+ {
+ QString tmp;
+ tmp.setNum(dmax);
+ max->setText(tmp);
+ }
+ QToolTip::add(max,i18n("The returned y-value"));
+ 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"));
+ }
+ else if ( m_mode == 3)
+ {
+ double dmin_tmp = dmin;
+ m_view->areaUnderGraph(ufkt,p_mode,dmin,dmax,parameter, 0);
+ if ( !m_view->isCalculationStopped() )
+ {
+ m_view->setFocus();
+ m_view->update();
+ KMessageBox::information(this,i18n("The integral in the interval [%1, %2] is:\n%3").arg(dmin_tmp).arg(dmax).arg(dmin));
+ }
+ }
+
+ if ( m_view->isCalculationStopped() )
+ KMessageBox::error(this,i18n("The operation was cancelled by the user."));
+}
+void KMinMax::list_highlighted(QListBoxItem* item)
+{
+ if ( !item)
+ {
+ cmdParameter->hide();
+ return;
+ }
+ QString function( list->currentText() );
+ char p_mode = 0;
+ if ( function.contains('\'') == 1)
+ {
+ p_mode = 1;
+ int pos = function.find('\'');
+ function.remove(pos,1);
+ }
+ else if ( function.contains('\'') == 2)
+ {
+ p_mode = 2;
+ int pos = function.find('\'');
+ function.remove(pos,2);
+ }
+ else if ( function.at(0).category() == QChar::Letter_Uppercase)
+ {
+ p_mode = 3;
+ function.at(0) = function.at(0).lower();
+ }
+ QString const sec_function = function.section('(',0,0);
+ for(QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin(); it!=m_view->parser()->ufkt.end(); ++it)
+ {
+ if ( it->fstr.section('(',0,0) == sec_function)
+ {
+ if ( it->parameters.count() == 0)
+ cmdParameter->hide();
+ else
+ {
+ cmdParameter->show();
+ if (parameter.isEmpty() )
+ parameter = it->parameters.first().expression;
+ }
+ break;
+ }
+ }
+}
+void KMinMax::cmdParameter_clicked()
+{
+ QString function( list->currentText() );
+ char p_mode = 0;
+ if ( function.contains('\'') == 1)
+ {
+ p_mode = 1;
+ int pos = function.find('\'');
+ function.remove(pos,1);
+ }
+ else if ( function.contains('\'') == 2)
+ {
+ p_mode = 2;
+ int pos = function.find('\'');
+ function.remove(pos,2);
+ }
+ else if ( function.at(0).category() == QChar::Letter_Uppercase)
+ {
+ p_mode = 3;
+ function.at(0) = function.at(0).lower();
+ }
+
+ QString const sec_function = function.section('(',0,0);
+ for(QValueVector<Ufkt>::iterator it = m_view->parser()->ufkt.begin() ; it!=m_view->parser()->ufkt.end(); ++it)
+ {
+ if ( it->fstr.section('(',0,0) == sec_function)
+ {
+ QStringList str_parameters;
+ for ( QValueList<ParameterValueItem>::Iterator k = it->parameters.begin(); k != it->parameters.end(); ++k )
+ str_parameters.append( (*k).expression);
+ bool ok;
+ QStringList result = KInputDialog::getItemList( i18n("Choose Parameter"), i18n("Choose a parameter to use:"), str_parameters, QStringList(parameter),false,&ok,this );
+ if ( ok)
+ parameter = result.first();
+ break;
+ }
+ }
+}
+
+void KMinMax::list_doubleClicked(QListBoxItem *)
+{
+ if ( list->currentItem() == -1)
+ return;
+ else if( cmdParameter->isShown() )
+ cmdParameter_clicked();
+}
+#include "kminmax.moc"