/* "calcqt.cpp" : Qtopia source code for "RPN calculator on Zaurus" * * This is a Qtopia program to realize "RPN caculator" on Sharp Zaurus, * which consists of header file "calcqt.h", main program code "calcqt.cpp" * (this file), and image file "calcqt.png". * Package file "calcqt_YYYY.MM.DD_arm.ipk" is also available. * The author, T. Nakatsuka, does not insist any right on this program, * i.e., free to re-distribute to any place with/without any modification. * The author acknowledges Hewlett-Packard Corp. for their intelligent * product of micro-calculators, which were borne in mind during designing, * and Trolltech for providing comprehensive environment of Qt/Qtopia. */ #include "calcqt.h" #include <qpe/qpeapplication.h> #include <qfont.h> #include <math.h> #define PI 3.141592653589793 #define EXP 2.718281828459045 #define PNGFILE "/opt/QtPalmtop/bin/calcqt.png" MainWin::MainWin( QWidget *parent, const char *name, WFlags f ) : QLabel( parent, name, f ) { QFont fnt("lcfont", 18, QFont::Bold); this->setFont(fnt); this->setGeometry(0, 0, 332, 412); keymap.load(PNGFILE); this->setPixmap(keymap); deg = new QRadioButton("Degree", this); deg->setGeometry(106, 6, 90, 30); deg->setBackgroundColor(QColor(255,255,255)); deg->setChecked(TRUE); rad = new QRadioButton("Radian", this); rad->setGeometry(216, 6, 90, 30); rad->setBackgroundColor(QColor(255,255,255)); rad->setChecked(FALSE); regT = new QLabel(this, "regT"); regT->setGeometry(46, 43, 270, 19); regT->setBackgroundColor(QColor(128,128,128)); regT->setText("0"); regZ = new QLabel(this, "regZ"); regZ->setGeometry(46, 69, 270, 19); regZ->setBackgroundColor(QColor(128,128,128)); regZ->setText("0"); regY = new QLabel(this, "regY"); regY->setGeometry(46, 95, 270, 19); regY->setBackgroundColor(QColor(128,128,128)); regY->setText("0"); regX = new QLabel(this, "regX"); regX->setGeometry(46, 121, 270, 19); regX->setBackgroundColor(QColor(255,255,255)); regX->setText("0"); connect(deg, SIGNAL(clicked()), this, SLOT(radio1event())); connect(rad, SIGNAL(clicked()), this, SLOT(radio2event())); xstr = "0"; x = 0.; y = 0.; z = 0.; t = 0.; r = 0.; tmp = 0.; key = 0; l = 1; lce = 0; kdeg = 1; } MainWin::~MainWin() { delete regX; delete regY; delete regZ; delete regT; delete rad; delete deg; } /* * key : Status for Register-X * = 0 : Register-X shall be cleared by New-Value entry * [after ENTER/CLR/CLX/STO operation] * = 1 : CHS input after key=0 * = 2 : Register-X shall be pushed (on stack) by New-Value entry * [after Arithmetic or SWAP/ROT operation, * or definite value entry by RCL/'pi'/'e'] * = 3 : CHS input after key=2 * =4-7: on the way of New-Value entry * [after Numeric input keys (0-9/./EEX)] * =4 : neither . nor EEX input yet * =5 : . already input but EEX not yet * =6 : EEX already input but no exponent digit yet * =7 : at least 1 exponent digit input already * = 9 : error detected (use CLR/CLX to reset) */ void MainWin::keyPressEvent( QKeyEvent *ke ) { int kc = ke->key(); if (key < 9) { switch (kc) { /* Only limited key inputs are supported */ case '0': num(0); break; /* '0'-'9' */ case '1': num(1); break; case '2': num(2); break; case '3': num(3); break; case '4': num(4); break; case '5': num(5); break; case '6': num(6); break; case '7': num(7); break; case '8': num(8); break; case '9': num(9); break; case '^': chs(); break; /* ^ for ch +/- */ case 'E': /* E(e) for Eex */ case 'e': if (key<6) eex(); break; case '.': if (key<5) dot(); break; /* decimal point */ case '*': y *= x; pop(); break; /* arithmetic *,/,+,- */ case '/': y /= x; pop(); break; case '+': y += x; pop(); break; case '-': if (key == 6) chs(); /* Only after Eex, '-' */ else { y -= x; pop(); } /* may be used to ch +/- */ break; case Key_Return: case Key_Enter: /* 'Enter' */ push(0); showx(); key=0; break; } } } void MainWin::mousePressEvent( QMouseEvent *me ) { int mx, my; mx = (me->x() + 44) / 60; my = (426 - me->y()) / 31; if (key == 9) { if (mx != 5) return; if ((my<4) || (my>5)) return; } switch (my) { case 1: switch (mx) { case 1: y += x; pop(); break; /* '+' */ case 2: num(0); break; /* '0' */ case 3: if (key<5) dot(); break; /* '.' */ case 4: if (key==3) push(1); else if (key>=2) push(0); /* 'PI' */ x = PI; if ((key==1) || (key==3)) x = -x; showx(); break; case 5: if (key==3) push(1); else if (key>=2) push(0); /* 'e' */ x = EXP; if ((key==1) || (key==3)) x = -x; showx(); break; } break; case 2: switch (mx) { case 1: y -= x; pop(); break; /* '-' */ case 2: num(1); break; /* '1' */ case 3: num(2); break; /* '2' */ case 4: num(3); break; /* '3' */ case 5: if (key==3) push(1); else if (key>=2) push(0); /* RCL */ x = r; if ((key==1) || (key==3)) x = -x; showx(); break; } break; case 3: switch (mx) { case 1: y *= x; pop(); break; /* '*' */ case 2: num(4); break; /* '4' */ case 3: num(5); break; /* '5' */ case 4: num(6); break; /* '6' */ case 5: r = x; showx(); key=0; break; /* STO */ } break; case 4: switch (mx) { case 1: y /= x; pop(); break; /* '/' */ case 2: num(7); break; /* '7' */ case 3: num(8); break; /* '8' */ case 4: num(9); break; /* '9' */ case 5: x = 0.; showx(); key=0; break; /* CLX */ } break; case 5: switch (mx) { case 1: case 2: push(0); showx(); key=0; break; /* Enter */ case 3: chs(); break; /* ch +/- */ case 4: if (key<6) eex(); break; /* Eex */ case 5: x = 0.; y = 0.; z = 0.; push(0); showx(); /* CLR */ r = 0.; key=0; break; } break; case 6: switch (mx) { case 1: y = pow(y, x); pop(); break; /* y**x */ case 2: x = 1./x; showx(); break; /* 1./x */ case 3: x = sqrt(x); showx(); break; /* sqrt */ case 4: tmp = x; x = y; y = tmp; showx(); /* swap */ regY->setText(QString::number(y,'g',15)); break; case 5: tmp = x; pop(); t = tmp; /* rot */ regT->setText(QString::number(t,'g',15)); break; } break; case 7: switch (mx) { case 1: x = exp(x); showx(); break; /* exp */ case 2: x = log(x); showx(); break; /* ln */ case 3: rad1(); x = sin(x); showx(); break; /* sin */ case 4: rad1(); x = cos(x); showx(); break; /* cos */ case 5: rad1(); x = tan(x); showx(); break; /* tan */ } break; case 8: switch (mx) { case 1: x = pow(10., x); showx(); break; /* 10**x */ case 2: x = log10(x); showx(); break; /* Log10 */ case 3: x = asin(x); rad0(); showx(); break; /* arcsin */ case 4: x = acos(x); rad0(); showx(); break; /* arccos */ case 5: x = atan(x); rad0(); showx(); break; /* arctan */ } break; } } void MainWin::radio1event() { deg->setChecked(TRUE); if (kdeg == 0) { kdeg = 1; rad->setChecked(FALSE); } } void MainWin::radio2event() { rad->setChecked(TRUE); if (kdeg != 0) { kdeg = 0; deg->setChecked(FALSE); } } void MainWin::showx() { if (isnan(x) || isinf(x)) error(); else { xstr.setNum(x,'g',15); l = xstr.length(); key=2; regX->setText(xstr); } } void MainWin::push(int k) { t = z; z = y; if (k==0) y = x; else y = -x; regY->setText(QString::number(y,'g',15)); regZ->setText(QString::number(z,'g',15)); regT->setText(QString::number(t,'g',15)); } void MainWin::pop() { x = y; y = z; z = t; showx(); regY->setText(QString::number(y,'g',15)); regZ->setText(QString::number(z,'g',15)); } void MainWin::rad0() { if (kdeg==1) x /= PI/180.; } void MainWin::rad1() { if (kdeg==1) x *= PI/180.; } void MainWin::num(int i) { if (key<4) { if (key==2) push(0); else if (key==3) push(1); if ((key==0) || (key==2)) { xstr = ""; l=0; } else { xstr = "-"; l=1; } key=4; } xstr.append(QString::number(i)); l++; if (key==6) key=7; x = xstr.toDouble(); regX->setText(xstr); } void MainWin::dot() { if (key<4) { if (key==2) push(0); else if (key==3) push(1); if ((key==1) || (key==3)) { xstr = "-0"; l=2; x = 0.; } else { xstr = "0"; l=1; x = 0.; } } xstr.append("."); l++; key=5; regX->setText(xstr); } void MainWin::eex() { if (key<4) { if (key==2) push(0); else if (key==3) push(1); xstr = ""; if ((key==1) || (key==3)) { xstr = "-1."; l=3; x = -1.; } else { xstr = "1."; l=2; x = 1.; } } xstr.append("E"); lce=l++; key=6; regX->setText(xstr); } void MainWin::chs() { if (key<6) { if ((key==0) || (key==2)) key++; if ((key==1) || (key==3)) key--; if (xstr.at(0) == '-') { xstr.remove(0,1); l--; } else { xstr.insert(0, "-"); l++; } x = -x; } else if (key==6) { if (xstr.at(lce) == 'E') { lce++; xstr.append("-"); l++; } else { xstr.remove(lce--,1); l--; } } else if (key==7) { if (xstr.at(lce) == 'E') { xstr.insert(++lce, "-"); l++; } else { xstr.remove(lce--,1); l--; } x = xstr.toDouble(); } regX->setText(xstr); } void MainWin::error() { regX->setText(" E R R O R !!"); x = 0.; key=9; } int main( int argc, char *argv[] ) { QPEApplication app(argc, argv); QWidget palmtop; palmtop.setCaption(" RPN calculator on Qtopia "); palmtop.setGeometry(0, 0, 332, 412); palmtop.setBackgroundColor(QColor(128,128,128)); MainWin win(&palmtop, "win", 0); app.setMainWidget(&palmtop); palmtop.show(); return app.exec(); }