author | cniehaus <cniehaus> | 2002-09-15 14:02:04 (UTC) |
---|---|---|
committer | cniehaus <cniehaus> | 2002-09-15 14:02:04 (UTC) |
commit | ffb701b9a482ca30eda8901506c0c39ad8461e4c (patch) (side-by-side diff) | |
tree | 82fa34a6083a48c877f4a7b41c15672832095fbb /noncore/apps/checkbook/kmolcalc.cpp | |
parent | d01f8da912a2bed9de1943d174ec10dba505bf38 (diff) | |
download | opie-ffb701b9a482ca30eda8901506c0c39ad8461e4c.zip opie-ffb701b9a482ca30eda8901506c0c39ad8461e4c.tar.gz opie-ffb701b9a482ca30eda8901506c0c39ad8461e4c.tar.bz2 |
Ok, this is what I have so far. I know it is not really working thus it is
not in the toplevel-Makefile. I am putting as much work in it as possible.
Currently I am doing the kmol-port, after that the PSE-stuff.
Diffstat (limited to 'noncore/apps/checkbook/kmolcalc.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/checkbook/kmolcalc.cpp | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/noncore/apps/checkbook/kmolcalc.cpp b/noncore/apps/checkbook/kmolcalc.cpp new file mode 100644 index 0000000..e5ab736 --- a/dev/null +++ b/noncore/apps/checkbook/kmolcalc.cpp @@ -0,0 +1,233 @@ +/* + * kmolcalc.cpp + * + * Copyright (C) 2000 Tomislav Gountchev <tomi@idiom.com> + */ + +/** + * 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 <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;// = // KGlobal::dirs()->findAllResources("appdata", "kmolweights"); +// mwfile = locateLocal("data", "kmol")+"/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"); +} |