Commit 3f749363 authored by David Saxton's avatar David Saxton

Added a quick and simple calculator. This replaces the "plot value" tool.

svn path=/trunk/KDE/kdeedu/kmplot/; revision=652005
parent 836b213d
......@@ -26,6 +26,7 @@ set(kmplotpart_PART_SRCS
parameteranimator.cpp
vector.cpp
kgradientdialog.cpp
calculator.cpp
)
qt4_add_dbus_adaptor( kmplotpart_PART_SRCS org.kde.kmplot.MainDlg.xml maindlg.h MainDlg)
......
/*
* KmPlot - a math. function plotter for the KDE-Desktop
*
* Copyright (C) 2007 David Saxton <david@bluehaze.org>
*
* 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 "calculator.h"
#include "equationedit.h"
#include "xparser.h"
#include <KLocale>
#include <QScrollBar>
#include <QTextEdit>
#include <QVBoxLayout>
//BEGIN class Calacultor
Calculator::Calculator( QWidget * parent )
: KDialog( parent )
{
setModal( false );
QWidget * widget = new QWidget( this );
setMainWidget( widget );
setCaption( i18n("Calculator") );
setButtons( Close );
QVBoxLayout *layout = new QVBoxLayout( widget );
layout->setMargin( 0 );
m_display = new QTextEdit( widget );
QSizePolicy displaySizePolicy = m_display->sizePolicy();
displaySizePolicy.setVerticalStretch( 10 );
displaySizePolicy.setVerticalPolicy( QSizePolicy::MinimumExpanding );
m_display->setSizePolicy( displaySizePolicy );
layout->addWidget( m_display );
m_input = new EquationEditor( 0 );
layout->addWidget( m_input->mainWidget() );
m_display->setReadOnly( true );
connect( m_input->edit(), SIGNAL(returnPressed()), this, SLOT(calculate()) );
resize( layout->minimumSize() );
}
Calculator::~Calculator()
{
m_input->deleteLater();
}
void Calculator::calculate()
{
Parser::Error error;
double value = XParser::self()->eval( m_input->text(), & error );
m_displayText += m_input->text();
if ( error == Parser::ParseSuccess )
m_displayText += " = <b>" + Parser::number( value ) + "</b><br>";
else
m_displayText += " = ? <font color=\"blue\">(" + Parser::errorString( error ) + ")</font>";
m_display->document()->setHtml( m_displayText );
m_display->verticalScrollBar()->setValue( m_display->verticalScrollBar()->maximum() );
m_input->edit()->selectAll();
}
//END class Calculator
#include "calculator.moc"
/*
* KmPlot - a math. function plotter for the KDE-Desktop
*
* Copyright (C) 2007 David Saxton <david@bluehaze.org>
*
* 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.
*
*/
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include <KDialog>
class EquationEditor;
class QTextEdit;
/**
* Mini-calculator for calculating values of functions, etc.
* @author David Saxton
*/
class Calculator : public KDialog
{
Q_OBJECT
public:
Calculator( QWidget *parent = 0 );
~Calculator();
protected Q_SLOTS:
/**
* The user hit enter from the input box.
*/
void calculate();
protected:
EquationEditor *m_input;
QTextEdit *m_display;
QString m_displayText;
};
#endif
......@@ -325,24 +325,24 @@ void EquationEdit::slotTextChanged( )
if ( m_replaceMap.isEmpty() )
{
// m_replaceMap[ '*' ] = QChar(0xd7);
m_replaceMap[ '*' ] = QChar(0x2219);
m_replaceMap[ '-' ] = MinusSymbol;
m_replaceMap[ '|' ] = AbsSymbol;
}
QTextCursor cursor;
cursor.beginEditBlock();
for ( CharMap::iterator i = m_replaceMap.begin(); i != m_replaceMap.end(); ++i )
{
int at = 0;
while ( !(cursor = doc->find( i.key(), at )).isNull() )
{
cursor.joinPreviousEditBlock();
at = cursor.position()+1;
cursor.deleteChar();
cursor.insertText( i.value() );
cursor.endEditBlock();
}
}
cursor.endEditBlock();
m_cleaningText = false;
//END tidy up mathematical characters
......@@ -604,6 +604,12 @@ QString EquationEditor::text() const
}
EquationEdit * EquationEditor::edit() const
{
return m_widget->edit;
}
void EquationEditor::insertFunction( const QString & function )
{
if ( m_widget->functionList->currentIndex() == 0 )
......
......@@ -194,6 +194,8 @@ class EquationEditor : public KDialog
*/
QString text() const;
EquationEdit *edit() const;
protected slots:
void insertFunction( const QString & text );
/**
......
......@@ -6,27 +6,45 @@
<x>0</x>
<y>0</y>
<width>517</width>
<height>299</height>
<height>182</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
......@@ -41,12 +59,21 @@
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="constantsButton" >
<property name="text" >
......@@ -89,10 +116,19 @@
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<property name="spacing" >
<number>0</number>
</property>
<property name="spacing" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
......@@ -110,18 +146,28 @@
</item>
<item>
<layout class="QGridLayout" >
<property name="margin" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<property name="spacing" >
<property name="horizontalSpacing" >
<number>6</number>
</property>
<property name="verticalSpacing" >
<number>6</number>
</property>
<item row="0" column="0" >
<widget class="QToolButton" name="toolButton_3" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -141,9 +187,7 @@
<item row="0" column="4" >
<widget class="QToolButton" name="toolButton_28" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -163,9 +207,7 @@
<item row="0" column="1" >
<widget class="QToolButton" name="toolButton_4" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -178,9 +220,7 @@
<item row="1" column="2" >
<widget class="QToolButton" name="toolButton_18" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -207,9 +247,7 @@
<item row="0" column="3" >
<widget class="QToolButton" name="toolButton_25" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -222,9 +260,7 @@
<item row="0" column="2" >
<widget class="QToolButton" name="toolButton_5" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -254,18 +290,28 @@
</item>
<item>
<layout class="QGridLayout" >
<property name="margin" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="spacing" >
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<property name="horizontalSpacing" >
<number>6</number>
</property>
<property name="verticalSpacing" >
<number>6</number>
</property>
<item row="1" column="1" >
<widget class="QToolButton" name="toolButton_2" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -299,9 +345,7 @@
<item row="0" column="3" >
<widget class="QToolButton" name="toolButton" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>3</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -314,9 +358,7 @@
<item row="1" column="0" >
<widget class="QToolButton" name="toolButton_13" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -336,9 +378,7 @@
<item row="0" column="2" >
<widget class="QToolButton" name="toolButton_11" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
......@@ -368,10 +408,22 @@
</item>
<item>
<layout class="QGridLayout" >
<property name="margin" >
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="spacing" >
<property name="bottomMargin" >
<number>0</number>
</property>
<property name="horizontalSpacing" >
<number>6</number>
</property>
<property name="verticalSpacing" >
<number>6</number>
</property>
<item row="1" column="4" >
......@@ -469,7 +521,7 @@
<property name="sizeHint" >
<size>
<width>465</width>
<height>171</height>
<height>0</height>
</size>
</property>
</spacer>
......@@ -477,20 +529,15 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>EquationEdit</class>
<extends>KLineEdit</extends>
<header>equationedit.h</header>
</customwidget>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
<class>EquationEdit</class>
<extends>KLineEdit</extends>
<header>equationedit.h</header>
</customwidget>
</customwidgets>
<resources/>
......
......@@ -46,12 +46,9 @@ FunctionTools::FunctionTools(QWidget *parent )
// Adjust margins
m_widget->layout()->setMargin( 0 );
for ( int i = 0; i < 2; ++ i )
m_widget->stack->widget( i )->layout()->setMargin( 0 );
init( CalculateY );
init( CalculateArea );
connect( m_widget->xValue, SIGNAL(textChanged(const QString &)), this, SLOT(xChanged()) );
connect( m_widget->min, SIGNAL(editingFinished()), this, SLOT(rangeEdited()) );
connect( m_widget->max, SIGNAL(editingFinished()), this, SLOT(rangeEdited()) );
connect( m_widget->list, SIGNAL(currentRowChanged(int)), this, SLOT(equationSelected(int)) );
......@@ -89,26 +86,11 @@ void FunctionTools::init( Mode m )
setCaption(i18n("Area Under Graph"));
break;
}
case CalculateY:
{
setCaption(i18n("Get y-Value"));
break;
}
}
if ( m_mode == CalculateY )
{
m_widget->xValue->setFocus();
m_widget->stack->setCurrentIndex( 0 );
}
else
{
m_widget->min->setText( XParser::self()->number( View::self()->m_xmin ) );
m_widget->max->setText( XParser::self()->number( View::self()->m_xmax ) );
m_widget->min->setFocus();
m_widget->stack->setCurrentIndex( 1 );
}
m_widget->min->setText( XParser::self()->number( View::self()->m_xmin ) );
m_widget->max->setText( XParser::self()->number( View::self()->m_xmax ) );
m_widget->min->setFocus();
updateEquationList();
setEquation( EquationPair( View::self()->m_currentPlot, 0 ) );
......@@ -121,13 +103,10 @@ void FunctionTools::updateEquationList()
m_widget->list->clear();
m_equations.clear();
// Can't e.g. calculate areas for parametric equations
bool onlyCartesianLike = (m_mode != CalculateY);
foreach ( Function * function, XParser::self()->m_ufkt )
{
if ( onlyCartesianLike && function->type() != Function::Cartesian && function->type() != Function::Differential )
if ( function->type() != Function::Cartesian && function->type() != Function::Differential )
continue;
QList<Plot> plots = function->plots();
......@@ -186,10 +165,6 @@ void FunctionTools::equationSelected( int equation )
findMaximum( current );
break;
case CalculateY:
calculateY( current );
break;
case CalculateArea:
calculateArea( current );
break;
......@@ -197,12 +172,6 @@ void FunctionTools::equationSelected( int equation )
}
void FunctionTools::xChanged()
{
calculateY( equation() );
}
void FunctionTools::rangeEdited()
{
switch ( m_mode )
......@@ -218,29 +187,10 @@ void FunctionTools::rangeEdited()
case CalculateArea:
calculateArea( equation() );
break;
case CalculateY:
return;
}
}
void FunctionTools::calculateY( const EquationPair & equation )
{
if ( !equation.first.function() )
return;
double result = View::self()->value( equation.first, equation.second, m_widget->xValue->value(), true );
Equation * eq = equation.first.function()->eq[ equation.second ];
m_widget->yResult->setText( QString( "%1(%2) = %3" )
.arg( eq->name() )
.arg( m_widget->xValue->text() )
.arg( XParser::self()->number( result ) ) );
}
void FunctionTools::findMinimum( const EquationPair & equation )
{
if ( !equation.first.function() )
......
......@@ -50,7 +50,6 @@ class FunctionTools : public KDialog
{
FindMinimum,
FindMaximum,
CalculateY,
CalculateArea
};
......@@ -78,10 +77,6 @@ class FunctionTools : public KDialog
* Called when the min or max range changes.
*/
void rangeEdited();
/**
* Called when the x value in the widget changes.
*/
void xChanged();
protected:
/**
......@@ -102,11 +97,6 @@ class FunctionTools : public KDialog
* Find the area under the graph