File indexing completed on 2023-09-24 03:52:09
0001 /* 0002 SPDX-FileCopyrightText: 2003-2005, 2006 Carsten Niehaus <cniehaus@kde.org> 0003 SPDX-FileCopyrightText: 2005 Inge Wallin <inge@lysator.liu.se> 0004 SPDX-FileCopyrightText: 2009 Kashyap. R. Puranik <kashthealien@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "molcalcwidget.h" 0010 0011 // libscience 0012 #include <element.h> 0013 0014 #include "kalziumdataobject.h" 0015 #include "kalziumutils.h" 0016 #include "prefs.h" 0017 #include "search.h" 0018 0019 #include "kalzium_debug.h" 0020 #include <QFile> 0021 #include <QKeyEvent> 0022 #include <QLineEdit> 0023 #include <QPushButton> 0024 #include <QStandardPaths> 0025 #include <QTimer> 0026 0027 #include <KLocalizedString> 0028 0029 MolcalcWidget::MolcalcWidget(QWidget *parent) 0030 : QWidget(parent) 0031 { 0032 m_parser = new MoleculeParser(KalziumDataObject::instance()->ElementList); 0033 0034 m_timer = new QTimer(this); 0035 m_timer->setSingleShot(true); 0036 0037 ui.setupUi(this); 0038 0039 connect(ui.calcButton, &QAbstractButton::clicked, this, &MolcalcWidget::slotCalculate); 0040 connect(ui.formulaEdit, &QLineEdit::returnPressed, this, &MolcalcWidget::slotCalculate); 0041 connect(m_timer, &QTimer::timeout, this, &MolcalcWidget::slotCalculate); 0042 0043 ui.formulaEdit->setClearButtonEnabled(true); 0044 0045 clear(); 0046 if (!Prefs::addAlias()) { 0047 hideExtra(); 0048 ui.details->show(); 0049 } 0050 if (!Prefs::alias()) { 0051 ui.details->hide(); 0052 } 0053 0054 if (Prefs::addAlias()) { 0055 connect(ui.alias, &QAbstractButton::clicked, this, &MolcalcWidget::addAlias); 0056 QString shortForm, fullForm; // short form (symbol) and full form (expansion) 0057 QList<QString> shortList, fullList; // Used to store the short and full forms 0058 int i = 0; // loop counter 0059 0060 // Search in User defined aliases. 0061 QString fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("libkdeedu/data/symbols2.csv")); 0062 QFile file(fileName); 0063 0064 // Check file validity 0065 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0066 qCDebug(KALZIUM_LOG) << fileName << " opened"; 0067 QTextStream in(&file); 0068 // Get all shortForms and fullForms in the file. 0069 // eg the short form and full form extracted from ("Me","CH3") 0070 // are (Me) and (CH3) respectively 0071 while (!in.atEnd()) { 0072 QString line = in.readLine(); 0073 shortForm = line.section(',', 0, 0); 0074 shortForm.remove(QChar('\"')); 0075 fullForm = line.section(',', 1, 1); 0076 fullForm.remove(QChar('\"')); 0077 shortList << shortForm; 0078 fullList << fullForm; 0079 } 0080 0081 int length = shortList.length(); 0082 ui.user_defined->setRowCount(length); 0083 // Put all the aliases on to the table in the user interface 0084 for (i = 0; i < length; ++i) { 0085 shortForm = shortList.takeFirst(); 0086 fullForm = fullList.takeFirst(); 0087 ui.user_defined->setItem((int)i, 0, new QTableWidgetItem(i18n("%1", shortForm + " : " + fullForm))); 0088 } 0089 } else { 0090 qCDebug(KALZIUM_LOG) << fileName << " could not be opened!"; 0091 } 0092 0093 // Find the system defined aliases 0094 // Open the file 0095 fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("libkdeedu/data/symbols.csv")); 0096 QFile file2(fileName); 0097 shortList.clear(); 0098 fullList.clear(); 0099 0100 // Check file validity 0101 if (!(!file2.open(QIODevice::ReadOnly | QIODevice::Text))) { 0102 qCDebug(KALZIUM_LOG) << fileName << " opened"; 0103 QTextStream in(&file2); 0104 0105 // Get all shortForms and fullForms in the file. 0106 while (!in.atEnd()) { 0107 QString line = in.readLine(); 0108 shortForm = line.section(',', 0, 0); 0109 shortForm.remove(QChar('\"')); 0110 fullForm = line.section(',', 1, 1); 0111 fullForm.remove(QChar('\"')); 0112 shortList << shortForm; 0113 fullList << fullForm; 0114 } 0115 int length = shortList.length(); 0116 ui.pre_defined->setRowCount(length); 0117 0118 // Put all the aliases on to the table in the user interface 0119 for (i = 0; i < length; ++i) { 0120 shortForm = shortList.takeFirst(); 0121 fullForm = fullList.takeFirst(); 0122 ui.pre_defined->setItem((int)i, 0, new QTableWidgetItem(i18n("%1", shortForm + " : " + fullForm))); 0123 } 0124 } else { 0125 qCDebug(KALZIUM_LOG) << fileName << " could not be opened!"; 0126 } 0127 } 0128 } 0129 0130 MolcalcWidget::~MolcalcWidget() 0131 { 0132 delete m_parser; 0133 } 0134 0135 void MolcalcWidget::clear() 0136 { 0137 // Clear the data. 0138 m_mass = 0; 0139 m_elementMap.clear(); 0140 0141 // stop the selection in the periodic table 0142 KalziumDataObject::instance()->search()->resetSearch(); 0143 0144 // Clear the widgets. 0145 ui.resultLabel->clear(); 0146 ui.resultMass->clear(); 0147 ui.resultValue->hide(); 0148 0149 ui.resultComposition->setText(i18n("Enter a formula in the\nwidget above and\nclick on 'Calc'.\nE.g. #Et#OH")); 0150 0151 ui.resultMass->setToolTip(QString()); 0152 ui.resultComposition->setToolTip(QString()); 0153 ui.resultLabel->setToolTip(QString()); 0154 } 0155 0156 void MolcalcWidget::updateUI() 0157 { 0158 qCDebug(KALZIUM_LOG) << "MolcalcWidget::updateUI()"; 0159 0160 if (m_validInput) { 0161 qCDebug(KALZIUM_LOG) << "m_validInput == true"; 0162 0163 // The complexString stores the whole molecule like this: 0164 // 1 Seaborgium. Cumulative Mass: 263.119 u (39.2564 %) 0165 QString complexString; 0166 if (Prefs::alias()) { 0167 double mass; 0168 QString str; 0169 int i = 0; // counter 0170 int rows = m_elementMap.elements().count(); // number of columns 0171 ui.table->setRowCount(rows); 0172 0173 foreach (ElementCount *count, m_elementMap.map()) { 0174 // Update the resultLabel 0175 mass = count->element()->dataAsVariant(ChemicalDataObject::mass).toDouble(); 0176 0177 ui.table->setItem(i, 0, new QTableWidgetItem(i18n("%1", count->element()->dataAsString(ChemicalDataObject::name)))); 0178 ui.table->setItem(i, 1, new QTableWidgetItem(i18n("%1", count->count()))); 0179 ui.table->setItem(i, 2, new QTableWidgetItem(i18n("%1", count->element()->dataAsString(ChemicalDataObject::mass)))); 0180 ui.table->setItem(i, 3, new QTableWidgetItem(i18n("%1", mass * count->count()))); 0181 ui.table->setItem(i, 4, new QTableWidgetItem(i18n("%1", mass * count->count() / m_mass * 100))); 0182 0183 ++i; 0184 } 0185 // The alias list 0186 i = 0; 0187 rows = m_aliasList.count(); 0188 ui.alias_list->setRowCount(rows); 0189 foreach (const QString &alias, m_aliasList) { 0190 ui.alias_list->setItem(i++, 0, new QTableWidgetItem(alias)); 0191 } 0192 } 0193 0194 // The composition 0195 ui.resultComposition->setText(compositionString(m_elementMap)); 0196 0197 // The mass 0198 ui.resultMass->setText(i18n("Molecular mass: ")); 0199 0200 ui.resultValue->setText(QString::number(m_mass) + " u"); 0201 ui.resultValue->show(); 0202 ui.resultMass->setToolTip(complexString); 0203 ui.resultComposition->setToolTip(complexString); 0204 0205 #if 0 0206 // FIXME 0207 //select the elements in the table 0208 QList<Element*> list = m_elementMap.elements(); 0209 KalziumDataObject::instance()->findElements(list); 0210 #endif 0211 } else { // the input was invalid, so tell this the user 0212 qCDebug(KALZIUM_LOG) << "m_validInput == false"; 0213 ui.resultComposition->setText(i18n("Invalid input")); 0214 ui.resultLabel->setText(QString()); 0215 ui.resultMass->setText(QString()); 0216 0217 ui.resultMass->setToolTip(i18n("Invalid input")); 0218 ui.resultComposition->setToolTip(i18n("Invalid input")); 0219 ui.resultLabel->setToolTip(i18n("Invalid input")); 0220 } 0221 } 0222 0223 QString MolcalcWidget::compositionString(ElementCountMap &_map) 0224 { 0225 QString str; 0226 0227 foreach (ElementCount *count, _map.map()) { 0228 str += i18n("%1<sub>%2</sub> ", count->element()->dataAsString(ChemicalDataObject::symbol), count->count()); 0229 } 0230 0231 return str; 0232 } 0233 0234 // ---------------------------------------------------------------- 0235 // slots 0236 0237 void MolcalcWidget::slotCalculate() 0238 { 0239 qCDebug(KALZIUM_LOG) << "MolcalcWidget::slotCalcButtonClicked()"; 0240 QString molecule = ui.formulaEdit->text(); 0241 0242 // Parse the molecule, and at the same time calculate the total 0243 // mass, and the composition of it. 0244 if (!molecule.isEmpty()) { 0245 m_validInput = m_parser->weight(molecule, &m_mass, &m_elementMap); 0246 m_aliasList = m_parser->aliasList(); 0247 } 0248 qCDebug(KALZIUM_LOG) << "done calculating."; 0249 0250 updateUI(); 0251 } 0252 0253 void MolcalcWidget::keyPressEvent(QKeyEvent * /* e */) 0254 { 0255 m_timer->start(500); 0256 } 0257 0258 void MolcalcWidget::addAlias() 0259 { 0260 const QString shortForm = ui.shortForm->text(); 0261 const QString fullForm = ui.fullForm->text(); 0262 0263 // Validate the alias 0264 double x; 0265 ElementCountMap y; 0266 0267 ui.aliasMessage->setText(QLatin1String("")); 0268 if (shortForm.length() < 2) { 0269 ui.aliasMessage->setText(i18n("Symbol should consist of two or more letters.")); 0270 return; 0271 } 0272 0273 if (m_parser->weight(shortForm, &x, &y)) { 0274 ui.aliasMessage->setText(i18n("Symbol already being used")); 0275 return; 0276 } 0277 0278 if (fullForm.isEmpty() || !m_parser->weight(fullForm, &x, &y)) { 0279 ui.aliasMessage->setText(i18n("Expansion is invalid, please specify a valid expansion")); 0280 return; 0281 } 0282 0283 // Open the file to write 0284 QString fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("libkdeedu/data/symbols2.csv")); 0285 QFile file(fileName); 0286 0287 if (!(!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text))) { 0288 QTextStream out(&file); 0289 out << "\"" + shortForm + "\",\"" + fullForm + "\"\n"; 0290 qCDebug(KALZIUM_LOG) << fileName << "is the file."; 0291 qCDebug(KALZIUM_LOG) << "\"" + shortForm + "\",\"" + fullForm + "\"\n"; 0292 ui.aliasMessage->setText(i18n("done!")); 0293 return; 0294 } else { 0295 ui.aliasMessage->setText((i18n("Unable to find the user defined alias file.")) + fileName); 0296 return; 0297 } 0298 } 0299 0300 void MolcalcWidget::hideExtra() 0301 { 0302 ui.details->hide(); 0303 ui.tabWidget->removeTab(1); 0304 } 0305 0306 #include "moc_molcalcwidget.cpp"