-rw-r--r-- | noncore/apps/oxygen/calcdlg.ui | 203 | ||||
-rw-r--r-- | noncore/apps/oxygen/calcdlgui.cpp | 2 | ||||
-rw-r--r-- | noncore/apps/oxygen/kmolcalc.cpp | 40 | ||||
-rw-r--r-- | noncore/apps/oxygen/kmolcalc.h | 5 |
4 files changed, 99 insertions, 151 deletions
diff --git a/noncore/apps/oxygen/calcdlg.ui b/noncore/apps/oxygen/calcdlg.ui index e0b19f9..5b0c53e 100644 --- a/noncore/apps/oxygen/calcdlg.ui +++ b/noncore/apps/oxygen/calcdlg.ui @@ -1,243 +1,230 @@ <!DOCTYPE UI><UI> <class>CalcDlg</class> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>CalcDlg</cstring> </property> <property stdset="1"> <name>geometry</name> <rect> <x>0</x> <y>0</y> - <width>218</width> - <height>274</height> + <width>275</width> + <height>357</height> </rect> </property> <property stdset="1"> <name>caption</name> <string>Network Time</string> </property> <property> <name>layoutMargin</name> </property> <property> <name>layoutSpacing</name> </property> <widget> <class>QTabWidget</class> <property stdset="1"> <name>name</name> <cstring>TabWidgetMain</cstring> </property> <property stdset="1"> <name>geometry</name> <rect> - <x>10</x> + <x>0</x> <y>0</y> - <width>200</width> - <height>260</height> + <width>270</width> + <height>350</height> </rect> </property> <property> <name>layoutMargin</name> </property> <property> <name>layoutSpacing</name> </property> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>tabMain</cstring> </property> <attribute> <name>title</name> <string>Molweight</string> </attribute> <widget> <class>QFrame</class> <property stdset="1"> <name>name</name> <cstring>FrameSystemTime</cstring> </property> <property stdset="1"> <name>geometry</name> <rect> - <x>2</x> - <y>2</y> - <width>180</width> - <height>220</height> + <x>0</x> + <y>0</y> + <width>260</width> + <height>320</height> </rect> </property> <property stdset="1"> <name>frameShape</name> <enum>StyledPanel</enum> </property> <property stdset="1"> <name>frameShadow</name> <enum>Raised</enum> </property> <widget> - <class>QLabel</class> - <property stdset="1"> - <name>name</name> - <cstring>TextLabel1_4</cstring> - </property> - <property stdset="1"> - <name>geometry</name> - <rect> - <x>1</x> - <y>1</y> - <width>298</width> - <height>16</height> - </rect> - </property> - <property stdset="1"> - <name>text</name> - <string>Formula:</string> - </property> - </widget> - <widget> <class>QLayoutWidget</class> <property stdset="1"> <name>name</name> <cstring>Layout7</cstring> </property> <property stdset="1"> <name>geometry</name> <rect> <x>0</x> - <y>50</y> - <width>175</width> - <height>30</height> + <y>0</y> + <width>260</width> + <height>320</height> </rect> </property> - <hbox> + <vbox> <property stdset="1"> <name>margin</name> <number>0</number> </property> <property stdset="1"> <name>spacing</name> <number>6</number> </property> <widget> - <class>QPushButton</class> + <class>QLabel</class> <property stdset="1"> <name>name</name> - <cstring>calculate</cstring> + <cstring>TextLabel1_4</cstring> </property> <property stdset="1"> <name>text</name> - <string>Calculate</string> + <string>Formula:</string> + </property> + </widget> + <widget> + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>formula</cstring> + </property> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout7</cstring> </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>calculate</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Calculate</string> + </property> + </widget> + <widget> + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>clear_fields</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Clear</string> + </property> + </widget> + </hbox> </widget> <widget> - <class>QPushButton</class> + <class>QLabel</class> <property stdset="1"> <name>name</name> - <cstring>clear_fields</cstring> + <cstring>TextLabel2_4</cstring> </property> <property stdset="1"> <name>text</name> - <string>Clear</string> + <string>Result:</string> </property> </widget> - </hbox> - </widget> - <widget> - <class>QLineEdit</class> - <property stdset="1"> - <name>name</name> - <cstring>formula</cstring> - </property> - <property stdset="1"> - <name>geometry</name> - <rect> - <x>0</x> - <y>20</y> - <width>170</width> - <height>22</height> - </rect> - </property> - </widget> - <widget> - <class>QMultiLineEdit</class> - <property stdset="1"> - <name>name</name> - <cstring>anal_display</cstring> - </property> - <property stdset="1"> - <name>geometry</name> - <rect> - <x>0</x> - <y>130</y> - <width>170</width> - <height>80</height> - </rect> - </property> - </widget> - <widget> - <class>QLineEdit</class> - <property stdset="1"> - <name>name</name> - <cstring>result</cstring> - </property> - <property stdset="1"> - <name>geometry</name> - <rect> - <x>0</x> - <y>100</y> - <width>170</width> - <height>22</height> - </rect> - </property> - </widget> - <widget> - <class>QLabel</class> - <property stdset="1"> - <name>name</name> - <cstring>TextLabel2_4</cstring> - </property> - <property stdset="1"> - <name>geometry</name> - <rect> - <x>1</x> - <y>86</y> - <width>298</width> - <height>16</height> - </rect> - </property> - <property stdset="1"> - <name>text</name> - <string>Result:</string> - </property> + <widget> + <class>QLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>result</cstring> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Elemental composition (%):</string> + </property> + </widget> + <widget> + <class>QMultiLineEdit</class> + <property stdset="1"> + <name>name</name> + <cstring>anal_display</cstring> + </property> + <property stdset="1"> + <name>readOnly</name> + <bool>true</bool> + </property> + </widget> + </vbox> </widget> </widget> </widget> <widget> <class>QWidget</class> <property stdset="1"> <name>name</name> <cstring>tabNtp</cstring> </property> <attribute> <name>title</name> <string>Nernst</string> </attribute> <grid> <property stdset="1"> <name>margin</name> <number>1</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> </grid> </widget> </widget> </widget> </UI> diff --git a/noncore/apps/oxygen/calcdlgui.cpp b/noncore/apps/oxygen/calcdlgui.cpp index e9b40d3..e40e2c7 100644 --- a/noncore/apps/oxygen/calcdlgui.cpp +++ b/noncore/apps/oxygen/calcdlgui.cpp @@ -1,55 +1,57 @@ /*************************************************************************** * * * 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. * * * **************************************************************************/ #include "oxygen.h" #include "calcdlgui.h" #include "kmolcalc.h" #include <qlineedit.h> #include <qmultilineedit.h> #include <qpushbutton.h> calcDlgUI::calcDlgUI() : CalcDlg() { + this->showMaximized(); kmolcalc = new KMolCalc; connect( calculate, SIGNAL( clicked() ), this, SLOT( calc() ) ); connect( clear_fields, SIGNAL( clicked() ), this, SLOT( clear() ) ); + result->setReadOnly( true ); } void calcDlgUI::calc() { QString compound( formula->text() ); if ( compound.isEmpty() ) { clear(); return; } QString errors( kmolcalc->readFormula( compound ) ); QString mw, ea; double weight = kmolcalc->getWeight(); if ( errors == "OK" ) { mw.setNum( weight ); ea = kmolcalc->getEmpFormula() + " :\n" + kmolcalc->getEA(); } else { mw = "???"; ea = tr( "ERROR: \n" ) + errors + "\n"; } result->setText( mw ); anal_display->setText( ea ); } /** * * Clear all text entry / result fields. * */ void calcDlgUI::clear() { formula->clear(); result->clear(); anal_display->clear(); } diff --git a/noncore/apps/oxygen/kmolcalc.cpp b/noncore/apps/oxygen/kmolcalc.cpp index 7257c4a..0ba52da 100644 --- a/noncore/apps/oxygen/kmolcalc.cpp +++ b/noncore/apps/oxygen/kmolcalc.cpp @@ -1,235 +1,199 @@ /* * kmolcalc.cpp * - * Copyright (C) 2000 Tomislav Gountchev <tomi@idiom.com> + * Copyright (C) 2000,2001 Tomislav Gountchev <tomi@idiom.com> * Copyright (C) 2002 Carsten Niehaus <cniehaus@handhelds.org> */ /** * KMOLCALC is the calculation engine. It knows about a hashtable of user defined atomic * weights and group definitions ELSTABLE, and the currently processed formula, stored * as a list of elements and their coefficients, ELEMENTS. */ #include "kmolcalc.h" #include <qdict.h> #include <qdir.h> #include <qfile.h> #include <iostream.h> /** * Construct a new calculator object. */ KMolCalc::KMolCalc() { elements = new ElementList; elstable = NULL; readElstable(); } KMolCalc::~KMolCalc() { delete elements; } void KMolCalc::readElstable() { weight = -1; // not calculated yet if (elstable) delete elstable; elstable = new QDict<SubUnit> (197, TRUE); elstable->setAutoDelete(TRUE); - QStringList files = "/home/opie/opie/noncore/apps/oxigen/kmolweights"; - mwfile = "/home/opie/opie/noncore/apps/oxigen/kmolweights"; + mwfile = "/home/opie/opie/noncore/apps/oxygen/kmolweights"; QFile f(mwfile); - QString* latest_f = &mwfile; - for (uint i=0; i<files.count(); i++) { - if (QFileInfo(QFile(files[i])).lastModified() > QFileInfo(QFile(*latest_f)).lastModified()) { - latest_f = &files[i]; - } - } - QFile lf(*latest_f); if (f.exists()) readMwfile(f); - if (!f.exists()) { - readMwfile(lf); - writeElstable(); - } else if (QFileInfo(f).lastModified() < QFileInfo(lf).lastModified()) { - // announce - QMessageBox::information - (0, "Warning:", "Found new global Mw file.\nLocal definitions will be updated.", QMessageBox::Ok); - readMwfile(lf); - writeElstable(); - } - } /** * Parse a string S and construct the ElementList this->ELEMENTS, representing the * composition of S. Returns 0 if successful, or an error code (currently -1) if * parsing failed. * The elements is S must be valid element or group symbols, as stored in this->ELSTABLE. * See help files for correct formula syntax. */ QString KMolCalc::readFormula(const QString& s) { weight = -1; if (elements) delete elements; elements = new ElementList; return KMolCalc::readGroup(s, elements); } // read a formula group recursively. Called by readFormula. QString KMolCalc::readGroup(const QString& s, ElementList* els) { if (s.isEmpty()) return QString ("Enter a formula."); //ERROR int sl = s.length(); int i = 0; QString errors ("OK"); bool ok = TRUE; while (i < sl && ((s[i] <= '9' && s[i] >= '0') || s[i] == '.')) i++; double prefix = (i == 0 ? 1 : s.left(i).toDouble(&ok)); if (! ok || i == sl || prefix == 0) return QString ("Bad formula."); // ERROR ElementList* elstemp = new ElementList; while (i < sl) { int j = i; if (s[i] == '(') { ElementList* inner = new ElementList; int level = 1; // count levels of nested ( ). while (1) { if (i++ == sl) { delete inner; delete elstemp; return QString ("Bad formula."); //ERROR } if (s[i] == '(') level++; if (s[i] == ')') level--; if (level == 0) break; } errors = KMolCalc::readGroup(s.mid(j+1, i-j-1), inner); j = ++i; while (i < sl && ((s[i] <= '9' && s[i] >= '0') || s[i] == '.')) i++; double suffix = (i == j ? 1 : s.mid(j, i-j).toDouble(&ok)); if (! ok || suffix == 0) { delete inner; delete elstemp; return QString ("Bad formula."); // ERROR } inner->addTo(*elstemp, suffix); delete inner; inner = NULL; } else if ((s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z')) { while (++i < sl && ((s[i] >= 'a' && s[i] <= 'z') || s[i] == '*' || s[i] == '\'')); QString elname = s.mid(j, i-j); j = i; while (i < sl && ((s[i] <= '9' && s[i] >= '0') || s[i] == '.')) i++; double suffix = (i == j ? 1 : s.mid(j, i-j).toDouble(&ok)); if (! ok || suffix == 0) { delete elstemp; return QString ("Bad formula."); // ERROR } SubUnit* group = elstable->find(elname); if (group == 0) { delete elstemp; return QString ("Undefined symbol: ") + elname; //ERROR } group->addTo(*elstemp, suffix); } else if (s[i] == '+') { if (elstemp->isEmpty()) { delete elstemp; return QString ("Bad formula."); //ERROR } elstemp->addTo(*els, prefix); delete elstemp; errors = KMolCalc::readGroup(s.mid(i+1, sl-i-1), els); return errors; } else { delete elstemp; return QString ("Bad formula."); //ERROR } } elstemp->addTo(*els, prefix); delete elstemp; return errors; } /** * Calculate and return the molecular weight of the current chemical formula. */ double KMolCalc::getWeight() { if (weight == -1) weight = elements->getWeight(elstable); return weight; } /** * Return the elemental composition of the current formula, as a string of tab-separated * element - percentage pairs, separated by newlines. */ QString KMolCalc::getEA() { if (weight == -1) weight = elements->getWeight(elstable); if (weight == -1) return QString("ERROR: Couldn't get Mw..."); // ERROR return elements->getEA(elstable, weight); } /** * Return the empirical formula of the current compound as a QString. */ QString KMolCalc::getEmpFormula() { return elements->getEmpFormula(); } // Read the element definition file. void KMolCalc::readMwfile(QFile& f) { if (! f.open(IO_ReadOnly)) return; //ERROR QTextStream fs (&f); QString line; while (! fs.eof()) { line = fs.readLine(); SubUnit* s = SubUnit::makeSubUnit(line); elstable->replace(s->getName(), s); } f.close(); } /** - * Save the element definitions file. - */ -void KMolCalc::writeElstable() { - QFile f(mwfile); - if (! f.open(IO_WriteOnly)) return; //ERROR - QTextStream fs (&f); - QString line; - QDictIterator<SubUnit> it(*elstable); - while (it.current()) { - it.current()->writeOut(line); - fs << line << endl; - ++it; - } - f.close(); -} - -/** * Remove a group or element definition from ELSTABLE. */ void KMolCalc::undefineGroup (const QString& name) { elstable->remove (name); } /** * Add a new element name - atomic weight record to the ELSTABLE hashtable. Assumes * NAME has valid syntax. */ void KMolCalc::defineElement (const QString& name, double weight) { Element* el = new Element(name, weight); elstable->replace(name, el); } /** * Add a new group definition to the ELSTABLE. Returns 0 if OK, -1 if parsing FORMULA * fails. Assumes the syntax of grpname is correct. */ QString KMolCalc::defineGroup (const QString& grpname, const QString& formula) { ElementList* els = new ElementList(grpname); QString error = readGroup(formula, els); if (error != "OK") return error; if (els->contains(grpname)) return QString("Can't define a group recursively!\n"); elstable->replace(grpname, els); return QString("OK"); } diff --git a/noncore/apps/oxygen/kmolcalc.h b/noncore/apps/oxygen/kmolcalc.h index c3e02f3..c589133 100644 --- a/noncore/apps/oxygen/kmolcalc.h +++ b/noncore/apps/oxygen/kmolcalc.h @@ -1,110 +1,105 @@ /* * kmolcalc.h * * Copyright (C) 2000 Tomislav Gountchev <tomi@idiom.com> */ #ifndef KMOLCALC_H #define KMOLCALC_H #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "kmolelements.h" #include <qdict.h> #include <qlist.h> #include <qstring.h> #include <qfile.h> #include <qfileinfo.h> #include <qmessagebox.h> #include <qtextstream.h> /** * KMOLCALC is the calculation engine. It knows about a hashtable of user defined atomic * weights and group definitions ELSTABLE, and the currently processed formula, stored * as a list of elements and their coefficients, ELEMENTS. */ class KMolCalc { public: KMolCalc(); ~KMolCalc(); /** * Parse a string S and construct the ElementList ELEMENTS, representing the composition * of S. Returns "OK" if successful, or an error message if parsing failed. * The elements is S must be valid element or group symbols, as stored in ELSTABLE. * See help files for correct formula syntax. */ QString readFormula(const QString& s); /** * Calculate and return the molecular weight of the current chemical formula. */ double getWeight(); /** * Return the elemental composition of the current formula, as a string of tab-separated * element - percentage pairs, separated by newlines. */ QString getEA(); /** * Return the empirical formula of the current compound as a QString. */ QString getEmpFormula(); /** * Add a new element name - atomic weight record to the ELSTABLE hashtable. * Assumes NAME has valid syntax. */ void defineElement(const QString& name, double weight); /** * Add a new group definition to the ELSTABLE. Returns "OK" if OK, error message * if parsing FORMULA fails. Assumes the syntax of NAME is correct. */ QString defineGroup(const QString& name, const QString& formula); /** * Remove a group or element definition from ELSTABLE. */ void undefineGroup(const QString& name); /** - * Save the element definitions file. - */ - void writeElstable(); - - /** * Read the element definitions file and construct ELSTABLE. */ void readElstable(); /** * The element dictionary. */ QDict<SubUnit>* elstable; QString mwfile; private: double weight; QString readGroup(const QString& s, ElementList* els); void readMwfile(QFile& f); ElementList* elements; }; #endif |