Diffstat (limited to 'noncore/apps/checkbook/kmolcalc.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/checkbook/kmolcalc.cpp | 235 |
1 files changed, 0 insertions, 235 deletions
diff --git a/noncore/apps/checkbook/kmolcalc.cpp b/noncore/apps/checkbook/kmolcalc.cpp deleted file mode 100644 index 50e1375..0000000 --- a/noncore/apps/checkbook/kmolcalc.cpp +++ b/dev/null | |||
@@ -1,235 +0,0 @@ | |||
1 | /* | ||
2 | * kmolcalc.cpp | ||
3 | * | ||
4 | * Copyright (C) 2000 Tomislav Gountchev <tomi@idiom.com> | ||
5 | * Copyright (C) 2002 Carsten Niehaus <cniehaus@handhelds.org> | ||
6 | */ | ||
7 | |||
8 | /** | ||
9 | * KMOLCALC is the calculation engine. It knows about a hashtable of user defined atomic | ||
10 | * weights and group definitions ELSTABLE, and the currently processed formula, stored | ||
11 | * as a list of elements and their coefficients, ELEMENTS. | ||
12 | */ | ||
13 | |||
14 | #include "kmolcalc.h" | ||
15 | #include <qdict.h> | ||
16 | #include <qdir.h> | ||
17 | #include <qfile.h> | ||
18 | #include <iostream.h> | ||
19 | |||
20 | |||
21 | /** | ||
22 | * Construct a new calculator object. | ||
23 | */ | ||
24 | KMolCalc::KMolCalc() { | ||
25 | elements = new ElementList; | ||
26 | elstable = NULL; | ||
27 | readElstable(); | ||
28 | } | ||
29 | |||
30 | KMolCalc::~KMolCalc() { | ||
31 | delete elements; | ||
32 | } | ||
33 | |||
34 | void KMolCalc::readElstable() { | ||
35 | weight = -1; // not calculated yet | ||
36 | if (elstable) delete elstable; | ||
37 | elstable = new QDict<SubUnit> (197, TRUE); | ||
38 | elstable->setAutoDelete(TRUE); | ||
39 | QStringList files;// = // KGlobal::dirs()->findAllResources("appdata", "kmolweights"); | ||
40 | mwfile = "/home/opie/opie/noncore/apps/oxigen/kmolweights"; | ||
41 | QFile f(mwfile); | ||
42 | QString* latest_f = &mwfile; | ||
43 | for (uint i=0; i<files.count(); i++) { | ||
44 | if (QFileInfo(QFile(files[i])).lastModified() > QFileInfo(QFile(*latest_f)).lastModified()) { | ||
45 | latest_f = &files[i]; | ||
46 | } | ||
47 | } | ||
48 | QFile lf(*latest_f); | ||
49 | if (f.exists()) readMwfile(f); | ||
50 | if (!f.exists()) { | ||
51 | readMwfile(lf); | ||
52 | writeElstable(); | ||
53 | } else if (QFileInfo(f).lastModified() < QFileInfo(lf).lastModified()) { | ||
54 | // announce | ||
55 | QMessageBox::information | ||
56 | (0, "Warning:", "Found new global Mw file.\nLocal definitions will be updated.", QMessageBox::Ok); | ||
57 | readMwfile(lf); | ||
58 | writeElstable(); | ||
59 | } | ||
60 | |||
61 | } | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Parse a string S and construct the ElementList this->ELEMENTS, representing the | ||
66 | * composition of S. Returns 0 if successful, or an error code (currently -1) if | ||
67 | * parsing failed. | ||
68 | * The elements is S must be valid element or group symbols, as stored in this->ELSTABLE. | ||
69 | * See help files for correct formula syntax. | ||
70 | */ | ||
71 | QString KMolCalc::readFormula(const QString& s) { | ||
72 | weight = -1; | ||
73 | if (elements) delete elements; | ||
74 | elements = new ElementList; | ||
75 | return KMolCalc::readGroup(s, elements); | ||
76 | } | ||
77 | |||
78 | // read a formula group recursively. Called by readFormula. | ||
79 | QString KMolCalc::readGroup(const QString& s, ElementList* els) { | ||
80 | if (s.isEmpty()) return QString ("Enter a formula."); //ERROR | ||
81 | int sl = s.length(); | ||
82 | int i = 0; | ||
83 | QString errors ("OK"); | ||
84 | bool ok = TRUE; | ||
85 | while (i < sl && ((s[i] <= '9' && s[i] >= '0') || s[i] == '.')) i++; | ||
86 | double prefix = (i == 0 ? 1 : s.left(i).toDouble(&ok)); | ||
87 | if (! ok || i == sl || prefix == 0) return QString ("Bad formula."); // ERROR | ||
88 | ElementList* elstemp = new ElementList; | ||
89 | while (i < sl) { | ||
90 | int j = i; | ||
91 | if (s[i] == '(') { | ||
92 | ElementList* inner = new ElementList; | ||
93 | int level = 1; // count levels of nested ( ). | ||
94 | while (1) { | ||
95 | if (i++ == sl) { | ||
96 | delete inner; | ||
97 | delete elstemp; | ||
98 | return QString ("Bad formula."); //ERROR | ||
99 | } | ||
100 | if (s[i] == '(') level++; | ||
101 | if (s[i] == ')') level--; | ||
102 | if (level == 0) break; | ||
103 | } | ||
104 | errors = KMolCalc::readGroup(s.mid(j+1, i-j-1), inner); | ||
105 | j = ++i; | ||
106 | while (i < sl && ((s[i] <= '9' && s[i] >= '0') || s[i] == '.')) i++; | ||
107 | double suffix = (i == j ? 1 : s.mid(j, i-j).toDouble(&ok)); | ||
108 | if (! ok || suffix == 0) { | ||
109 | delete inner; | ||
110 | delete elstemp; | ||
111 | return QString ("Bad formula."); // ERROR | ||
112 | } | ||
113 | inner->addTo(*elstemp, suffix); | ||
114 | delete inner; | ||
115 | inner = NULL; | ||
116 | } else if ((s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z')) { | ||
117 | while (++i < sl && ((s[i] >= 'a' && s[i] <= 'z') || s[i] == '*' || | ||
118 | s[i] == '\'')); | ||
119 | QString elname = s.mid(j, i-j); | ||
120 | j = i; | ||
121 | while (i < sl && ((s[i] <= '9' && s[i] >= '0') || s[i] == '.')) i++; | ||
122 | double suffix = (i == j ? 1 : s.mid(j, i-j).toDouble(&ok)); | ||
123 | if (! ok || suffix == 0) { | ||
124 | delete elstemp; | ||
125 | return QString ("Bad formula."); // ERROR | ||
126 | } | ||
127 | SubUnit* group = elstable->find(elname); | ||
128 | if (group == 0) { | ||
129 | delete elstemp; | ||
130 | return QString ("Undefined symbol: ") + elname; //ERROR | ||
131 | } | ||
132 | group->addTo(*elstemp, suffix); | ||
133 | } else if (s[i] == '+') { | ||
134 | if (elstemp->isEmpty()) { | ||
135 | delete elstemp; | ||
136 | return QString ("Bad formula."); //ERROR | ||
137 | } | ||
138 | elstemp->addTo(*els, prefix); | ||
139 | delete elstemp; | ||
140 | errors = KMolCalc::readGroup(s.mid(i+1, sl-i-1), els); | ||
141 | return errors; | ||
142 | } else { | ||
143 | delete elstemp; | ||
144 | return QString ("Bad formula."); //ERROR | ||
145 | } | ||
146 | } | ||
147 | elstemp->addTo(*els, prefix); | ||
148 | delete elstemp; | ||
149 | return errors; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Calculate and return the molecular weight of the current chemical formula. | ||
154 | */ | ||
155 | double KMolCalc::getWeight() { | ||
156 | if (weight == -1) weight = elements->getWeight(elstable); | ||
157 | return weight; | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * Return the elemental composition of the current formula, as a string of tab-separated | ||
162 | * element - percentage pairs, separated by newlines. | ||
163 | */ | ||
164 | QString KMolCalc::getEA() { | ||
165 | if (weight == -1) weight = elements->getWeight(elstable); | ||
166 | if (weight == -1) return QString("ERROR: Couldn't get Mw..."); // ERROR | ||
167 | return elements->getEA(elstable, weight); | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * Return the empirical formula of the current compound as a QString. | ||
172 | */ | ||
173 | QString KMolCalc::getEmpFormula() { | ||
174 | return elements->getEmpFormula(); | ||
175 | } | ||
176 | |||
177 | // Read the element definition file. | ||
178 | void KMolCalc::readMwfile(QFile& f) { | ||
179 | if (! f.open(IO_ReadOnly)) return; //ERROR | ||
180 | QTextStream fs (&f); | ||
181 | QString line; | ||
182 | while (! fs.eof()) { | ||
183 | line = fs.readLine(); | ||
184 | SubUnit* s = SubUnit::makeSubUnit(line); | ||
185 | elstable->replace(s->getName(), s); | ||
186 | } | ||
187 | f.close(); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Save the element definitions file. | ||
192 | */ | ||
193 | void KMolCalc::writeElstable() { | ||
194 | QFile f(mwfile); | ||
195 | if (! f.open(IO_WriteOnly)) return; //ERROR | ||
196 | QTextStream fs (&f); | ||
197 | QString line; | ||
198 | QDictIterator<SubUnit> it(*elstable); | ||
199 | while (it.current()) { | ||
200 | it.current()->writeOut(line); | ||
201 | fs << line << endl; | ||
202 | ++it; | ||
203 | } | ||
204 | f.close(); | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Remove a group or element definition from ELSTABLE. | ||
209 | */ | ||
210 | void KMolCalc::undefineGroup (const QString& name) { | ||
211 | elstable->remove (name); | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * Add a new element name - atomic weight record to the ELSTABLE hashtable. Assumes | ||
216 | * NAME has valid syntax. | ||
217 | |||
218 | */ | ||
219 | void KMolCalc::defineElement (const QString& name, double weight) { | ||
220 | Element* el = new Element(name, weight); | ||
221 | elstable->replace(name, el); | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * Add a new group definition to the ELSTABLE. Returns 0 if OK, -1 if parsing FORMULA | ||
226 | * fails. Assumes the syntax of grpname is correct. | ||
227 | */ | ||
228 | QString KMolCalc::defineGroup (const QString& grpname, const QString& formula) { | ||
229 | ElementList* els = new ElementList(grpname); | ||
230 | QString error = readGroup(formula, els); | ||
231 | if (error != "OK") return error; | ||
232 | if (els->contains(grpname)) return QString("Can't define a group recursively!\n"); | ||
233 | elstable->replace(grpname, els); | ||
234 | return QString("OK"); | ||
235 | } | ||