-rw-r--r-- | noncore/tools/calc2/main/.cvsignore | 1 | ||||
-rw-r--r-- | noncore/tools/calc2/main/calc.cpp | 103 | ||||
-rw-r--r-- | noncore/tools/calc2/main/calc.h | 69 | ||||
-rw-r--r-- | noncore/tools/calc2/main/engine.cpp | 221 | ||||
-rw-r--r-- | noncore/tools/calc2/main/engine.h | 111 | ||||
-rw-r--r-- | noncore/tools/calc2/main/instruction.h | 69 | ||||
-rw-r--r-- | noncore/tools/calc2/main/main.cpp | 34 | ||||
-rw-r--r-- | noncore/tools/calc2/main/main.pro | 12 | ||||
-rw-r--r-- | noncore/tools/calc2/main/plugininterface.h | 45 | ||||
-rw-r--r-- | noncore/tools/calc2/main/stdinstructions.h | 125 |
10 files changed, 790 insertions, 0 deletions
diff --git a/noncore/tools/calc2/main/.cvsignore b/noncore/tools/calc2/main/.cvsignore new file mode 100644 index 0000000..6d678c6 --- a/dev/null +++ b/noncore/tools/calc2/main/.cvsignore @@ -0,0 +1 @@ +config.in diff --git a/noncore/tools/calc2/main/calc.cpp b/noncore/tools/calc2/main/calc.cpp new file mode 100644 index 0000000..8c50c2c --- a/dev/null +++ b/noncore/tools/calc2/main/calc.cpp @@ -0,0 +1,103 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include <qvaluelist.h> +#include <qpe/qpeapplication.h> +#include <qdir.h> +#include <qwidgetstack.h> + +#include "calc.h" +#include "plugininterface.h" + +calc::calc (QWidget * p, const char *n):QWidget (p, n) +{ + setCaption (tr ("Calculator")); + +// widgets + LCD = new QLCDNumber (this); + LCD->setMaximumSize (QSize (240, 30)); + LCD->setNumDigits(12); +LCD->setSegmentStyle(QLCDNumber::Filled); + pluginWidgetStack = new QWidgetStack (this); + +// layout widgets + calculatorLayout = new QVBoxLayout (this); + calculatorLayout->addWidget (LCD); + calculatorLayout->addWidget (pluginWidgetStack); + +// no formatting of display for now + connect (&engine, SIGNAL(display(double)), LCD, SLOT(display(double))); + connect (&engine, SIGNAL(display(const QString&)), LCD, SLOT(display(const QString&))); + connect (&engine, SIGNAL(setBinMode()), LCD, SLOT(setBinMode())); + connect (&engine, SIGNAL(setOctMode()), LCD, SLOT(setOctMode())); + connect (&engine, SIGNAL(setDecMode()), LCD, SLOT(setDecMode())); + connect (&engine, SIGNAL(setHexMode()), LCD, SLOT(setHexMode())); + +#ifndef NO_PLUGINS +// load plugins + QValueList < Plugin >::Iterator mit; + for (mit = pluginList.begin (); mit != pluginList.end (); ++mit) { + (*mit).interface->release (); + (*mit).library->unload (); + delete (*mit).library; + } + pluginList.clear (); + + QString path = QPEApplication::qpeDir() + "plugins/calculator"; + QDir dir (path, "lib*.so"); + QStringList list = dir.entryList (); + + QStringList::Iterator it; + for (it = list.begin (); it != list.end (); ++it) { + CalcInterface *iface = 0; + QLibrary *lib = new QLibrary (path + "/" + *it); + Plugin plugin; + plugin.pluginWidget = 0; + + if (lib->queryInterface (IID_Calc, (QUnknownInterface **) & iface) == + QS_OK) { + plugin.library = lib; + plugin.interface = iface; + plugin.pluginWidget = plugin.interface->getPlugin(&engine,pluginWidgetStack); + if (plugin.pluginWidget) + pluginWidgetStack->addWidget (plugin.pluginWidget, pluginList.count()); + pluginList.append (plugin); + } else { + delete lib; + } + } + setMode (1); +#else +// load simple interface +#endif +} + +calc::~calc () +{ +#ifndef NO_PLUGINS + QValueList < Plugin >::Iterator mit; + for (mit = pluginList.begin (); mit != pluginList.end (); ++mit) { + (*mit).interface->release (); + (*mit).library->unload (); + delete (*mit).library; + } +#endif +} + diff --git a/noncore/tools/calc2/main/calc.h b/noncore/tools/calc2/main/calc.h new file mode 100644 index 0000000..b52356d --- a/dev/null +++ b/noncore/tools/calc2/main/calc.h @@ -0,0 +1,69 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef CALC_H +#define CALC_H + +#ifdef QT_NO_COMPONENT +#define NO_PLUGINS +#endif + +#include <qlayout.h> +#include <qwidgetstack.h> + +#ifndef NO_PLUGINS +#include <qvaluelist.h> +#include <qpe/qlibrary.h> +#endif + +#include "engine.h" +#include "plugininterface.h" + +struct Plugin { +#ifndef NO_PLUGINS + QLibrary *library; +#endif + QWidget *pluginWidget; + CalcInterface *interface; + QString name; +}; + +class calc:public QWidget { + +Q_OBJECT +public: + calc (QWidget * p = 0, const char *n = 0); + ~calc (); + +private: +#ifndef NO_PLUGINS + void loadPlugins (); + QValueList < Plugin > pluginList; +#endif + QVBoxLayout *calculatorLayout; + QWidgetStack *pluginWidgetStack; + QLCDNumber *LCD; + Engine engine; + +public slots: + void setMode(int m){pluginWidgetStack->raiseWidget(m);}; +}; + +#endif diff --git a/noncore/tools/calc2/main/engine.cpp b/noncore/tools/calc2/main/engine.cpp new file mode 100644 index 0000000..74cd701 --- a/dev/null +++ b/noncore/tools/calc2/main/engine.cpp @@ -0,0 +1,221 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "engine.h" + +/* OPIE */ +#include <opie2/odebug.h> + +/* QT */ +#include <qstring.h> +#include <qlcdnumber.h> + +/* STD */ +#include <math.h> + +Data Engine::evalStack (Data num, bool inbrace = FALSE) +{ + if (state != sError) { + Instruction *i; + +// Pop the next op from the stack + while (!stack.isEmpty () && (braces || !inbrace)) { + i = stack.pop (); + +// Check this ops prec vs next ops prec + if (!stack.isEmpty ()) + if (i->precedence <= stack.top()->precedence) + i->acc = evalStack (i->acc, inbrace); + +// Evaluate this instruction + num = i->eval (num); + +// Error-check ( change this to work for all types ) + if (isnan (num.dbl) || isinf (num.dbl)) { + odebug << "bad result from operation" << oendl; + state = sError; + clearData(&num); + return num; + } + } + } + return num; +} + +// Plugins call this to request the stack be evaluated +void Engine::eval () +{ + num = evalStack (num); + if (state != sError) { + displayData(num); + state = sStart; + } +// if the user didnt close all their braces, its no big deal + braces = 0; +} + +void Engine::immediateInstruction (Instruction * i) +{ + if (state != sError) { + i->setRep(currentRep); + num = i->eval (num); + displayData(num); + state = sStart; + } +} + +void Engine::pushInstruction (Instruction * i) +{ + if (state != sError) { + i->setRep(currentRep); + i->acc = num; + stack.push (i); + state = sStart; + } +} + +void Engine::pushValue (char v) +{ + if (state == sAppend) { + bool ok = FALSE; + switch (currentRep) { + case rDouble: + displayString.append(v); + num.dbl=displayString.toDouble(&ok); + break; + case rFraction: + break; + default: + displayString.append(v); + num.i=displayString.toInt(&ok, calcBase()); + }; + if (!ok) { + state = sError; + odebug << "pushValue() - num->string conversion" << oendl; + } else { + const QString constString = displayString; + emit(display(constString)); + }; + + } else if (state == sStart) { + softReset(); + displayString.truncate(0); + state = sAppend; + pushValue (v); + } else if (state == sError) { + odebug << "in error state" << oendl; + return; + } +} + +void Engine::del () +{ + bool ok; + switch (currentRep) { + case rDouble: + displayString.truncate(displayString.length()); + num.dbl=displayString.toDouble(&ok); + break; + case rFraction: + odebug << "not available" << oendl; + break; + default: + displayString.truncate(displayString.length()); + num.i = displayString.toInt(&ok, calcBase()); + }; + + if (!ok) { + state = sError; + odebug << "del() - num->string conversion" << oendl; + } else { + const QString constString = displayString; + emit(display(constString)); + }; +} + +void Engine::displayData(Data d) { + switch (currentRep) { + case rDouble: + displayString.setNum(d.dbl); + break; + case rFraction: + odebug << "fractional display not yet impl" << oendl; + break; + default: + displayString.setNum(d.i, calcBase()); + break; + }; + const QString constString= displayString; + emit(display(constString)); +} + +// Returns the base when Rep is an integer type +int Engine::calcBase () { + switch (currentRep) { + case rBin: + return 2; + case rOct: + return 8; + case rDec: + return 10; + case rHex: + return 16; + default: + state = sError; + odebug << "Error - attempt to calc base for non-integer" << oendl; + return 10; + }; +} + +// Special instruction for internal use only +class iOpenBrace:public Instruction { + public: + iOpenBrace (Engine *e):Instruction (100) {engine = e;}; + ~iOpenBrace () {}; + + Data eval (Data num) { + engine->decBraces(); + return num; + }; + private: + Engine *engine; +}; + +void Engine::openBrace() { + pushInstruction(new iOpenBrace(this)); +} + +void Engine::closeBrace() { + braces++;evalStack(num,TRUE); +} + +// will need to show and hide display widgets +void Engine::setRepresentation(Representation r) { + currentRep = r; + clearData(&num); + clearData(&mem); + state = sStart; +} + +void Engine::clearData(Data *d) { + d->i = d->fraction.numerator = d->fraction.denominator = 0; + d->dbl = 0; +} + diff --git a/noncore/tools/calc2/main/engine.h b/noncore/tools/calc2/main/engine.h new file mode 100644 index 0000000..15c9aa1 --- a/dev/null +++ b/noncore/tools/calc2/main/engine.h @@ -0,0 +1,111 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef ENGINE_H +#define ENGINE_H + +#include <qwidget.h> +#include <qstack.h> // Instruction stack +#include <qstring.h> // Display +#include "instruction.h" + +// Possible states +enum State { + sStart, // start inputting a new number + sAppend, // continue inputting a number + sError +}; + +// State machine +class Engine:public QWidget { + +Q_OBJECT +public: + Engine (QWidget * parent = 0, const char *name = 0):QWidget (parent, name) { + hardReset(); + setRepresentation(rDec); + }; + + ~Engine () { }; + + void immediateInstruction (Instruction *); + void pushInstruction (Instruction *); + void eval (); + + void pushValue (char); + void del (); + + void openBrace (); + void closeBrace (); + + void softReset () { // clears the number being inputted + decimalPlaces = -1; + clearData(&num); + displayData(num); + state = sStart; + }; + void hardReset () { // a "real" reset of the stack + stack.clear (); + memClear(); + braces = 0; + softReset (); + }; + + void memSave () { + mem = num; + }; + void memRecall () { + num = mem; + state = sStart; + displayData(num); + }; + void memClear () { + clearData(&mem); + }; + + // rFraction will require a special display enabled here + void setRepresentation(Representation); + + // you dont want to call this + void decBraces(void){ braces--; }; + +private: + void displayData(Data d); + void clearData(Data *d); + int calcBase(); + Data evalStack (Data, bool); + Data num,mem; + State state; + QStack < Instruction > stack; + Representation currentRep; + int braces, decimalPlaces; // count of finishing 0's in num + QString displayString; // saves instatiating it over and over + +signals: + void display(const QString &); + void display(double); // could get rid of this and + // use a QLabel instead. + void setHexMode(); + void setBinMode(); + void setDecMode(); + void setOctMode(); +}; + +#endif diff --git a/noncore/tools/calc2/main/instruction.h b/noncore/tools/calc2/main/instruction.h new file mode 100644 index 0000000..6077bf0 --- a/dev/null +++ b/noncore/tools/calc2/main/instruction.h @@ -0,0 +1,69 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef INSTRUCTION_H +#define INSTRUCTION_H + +/* Internal representation of data +The first four types indicate an int, +that is, Data.i, and are incompatible +with the other two types. + +- Plugin is responsible for telling engine +which Rep to use at any given time +- Instructions from that plugin only +have to handle that representation +- Engine is responsible for error-checking +according to its current rep and display */ +enum Representation { + rBin, + rOct, + rDec, + rHex, + rDouble, + rFraction +}; + +// An atom of data +union Data { + int i; + double dbl; + struct Fraction { + int numerator, denominator; + } fraction; +}; + +// Instruction base class +class Instruction { +public: + Instruction (int p = 0) { + precedence = p; + }; + + virtual ~ Instruction () {}; + + virtual Data eval(Data) = 0; + void setRep(Representation r) { rep = r; }; + + Representation rep; + Data acc; + int precedence; +}; + +#endif diff --git a/noncore/tools/calc2/main/main.cpp b/noncore/tools/calc2/main/main.cpp new file mode 100644 index 0000000..ebfcc28 --- a/dev/null +++ b/noncore/tools/calc2/main/main.cpp @@ -0,0 +1,34 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#include <qpe/qpeapplication.h> +#include "calc.h" + +int main (int argc, char **argv) +{ + QPEApplication a (argc, argv); + + calc mw; + + QPEApplication::setInputMethodHint (&mw, QPEApplication::AlwaysOff); + mw.setCaption (calc::tr ("Calculator")); + a.showMainWidget (&mw); + + return a.exec (); +} diff --git a/noncore/tools/calc2/main/main.pro b/noncore/tools/calc2/main/main.pro new file mode 100644 index 0000000..e2eda1f --- a/dev/null +++ b/noncore/tools/calc2/main/main.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +CONFIG += qt +# Input +HEADERS += calc.h plugininterface.h instruction.h engine.h stdinstructions.h +SOURCES += calc.cpp main.cpp engine.cpp +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe -Wl,-export-dynamic +TARGET = calc2 +DESTDIR = $(OPIEDIR)/bin + +include( $(OPIEDIR)/include.pro ) diff --git a/noncore/tools/calc2/main/plugininterface.h b/noncore/tools/calc2/main/plugininterface.h new file mode 100644 index 0000000..df6db9d --- a/dev/null +++ b/noncore/tools/calc2/main/plugininterface.h @@ -0,0 +1,45 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef CALCINTERFACE_H +#define CALCINTERFACE_H + +#include <qnamespace.h> +#include <qstring.h> +#include <qlcdnumber.h> +#include <qpe/qcom.h> + +#include "engine.h" + +#ifndef QT_NO_COMPONENT +// {3CE88B66-B3FD-4580-9D04-77338A31A667} +#ifndef IID_Calc +#define IID_Calc QUuid( 0x3ce88b66, 0xb3fd, 0x4580, 0x9d, 0x04, 0x77, 0x33, 0x8a, 0x31, 0xa6, 0x67) +#endif +#endif + +class QWidget; +class QObject; + +struct CalcInterface:public QUnknownInterface { + virtual QWidget *getPlugin (Engine *e, QWidget * parent) = 0; +}; + +#endif diff --git a/noncore/tools/calc2/main/stdinstructions.h b/noncore/tools/calc2/main/stdinstructions.h new file mode 100644 index 0000000..a575968 --- a/dev/null +++ b/noncore/tools/calc2/main/stdinstructions.h @@ -0,0 +1,125 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef STDINSTRUCTION_H +#define STDINSTRUCTION_H + +#include <qpe/qmath.h> +#include "instruction.h" + +// Useful instructions for plugin writers +// If you use them, take note of their precedence +class iAdd:public Instruction { +public: + iAdd ():Instruction (10) { }; + ~iAdd () { }; + Data eval (Data num) { + Data result; + switch (rep) { + case rDouble: + result.dbl = acc.dbl + num.dbl; + break; + default: + result.i = acc.i + num.i; + }; + return result; + }; +}; +class iSub:public Instruction { +public: + iSub ():Instruction (10) { }; + ~iSub () { }; + Data eval (Data num) { + Data result; + switch (rep) { + case rDouble: + result.dbl = acc.dbl - num.dbl; + break; + default: + result.i = acc.i - num.i; + }; + return result; + }; +}; +class iMul:public Instruction { +public: + iMul ():Instruction (20) { }; + ~iMul () { }; + Data eval (Data num) { + Data result; + switch (rep) { + case rDouble: + result.dbl = acc.dbl * num.dbl; + break; + default: + result.i = acc.i * num.i; + }; + return result; + }; +}; +class iDiv:public Instruction { +public: + iDiv ():Instruction (20) { }; + ~iDiv () { }; + Data eval (Data num) { + Data result; + switch (rep) { + case rDouble: + result.dbl = acc.dbl / num.dbl; + break; + default: + result.i = acc.i / num.i; + }; + return result; + }; +}; + +// Immediate double instructions only +class iSin:public Instruction { +public: + iSin ():Instruction () { }; + ~iSin () { }; + Data eval (Data num) { + Data result; + result.dbl = qSin(num.dbl); + return result; + }; +}; +class iCos:public Instruction { +public: + iCos ():Instruction () { }; + ~iCos () { }; + Data eval (Data num) { + Data result; + result.dbl = qCos(num.dbl); + return result; + }; +}; +class iTan:public Instruction { +public: + iTan ():Instruction () { }; + ~iTan () {}; + Data eval (Data num) { + Data result; + result.dbl = qTan(num.dbl); + return result; + }; +}; +#endif |