File indexing completed on 2022-11-29 12:50:41

0001 /*
0002     SPDX-FileCopyrightText: 2009 Kashyap R Puranik <kashthealien@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "concCalculator.h"
0008 
0009 
0010 #include <KLocalizedString>
0011 
0012 #include "kalziumutils.h"
0013 #include "prefs.h"
0014 
0015 using namespace KUnitConversion;
0016 
0017 concCalculator::concCalculator(QWidget *parent)
0018     : QFrame(parent)
0019 {
0020     ui.setupUi(this);
0021 
0022     /**************************************************************************/
0023     //                       concentration Calculator set up
0024     /**************************************************************************/
0025 
0026     // initialise the initially selected values
0027     init();
0028 
0029     // Connect signals with slots (when a change of selection in the UI takes place,
0030     // corresponding quantity should be updated in the class.)
0031 
0032     // Amount of solute changed
0033     connect(ui.amtSolute, SIGNAL(valueChanged(double)), this, SLOT(amtSoluteChanged()));
0034     connect(ui.amtSltType, SIGNAL(activated(int)), this, SLOT(amtSoluteTypeChanged()));
0035     connect(ui.amtSlt_unit, SIGNAL(activated(int)), this, SLOT(amtSoluteChanged()));
0036     // Molar mass and equivalent mass change for solvent
0037     connect(ui.molarMass, SIGNAL(valueChanged(double)), this, SLOT(molarMassChanged(double)));
0038     connect(ui.eqtMass, SIGNAL(valueChanged(double)), this, SLOT(eqtMassChanged(double)));
0039     // Density change for solute
0040     connect(ui.densitySolute, SIGNAL(valueChanged(double)), this, SLOT(densitySoluteChanged()));
0041     connect(ui.densSlt_unit, SIGNAL(activated(int)), this, SLOT(densitySoluteChanged()));
0042     // Amount of solvent changed
0043     connect(ui.amtSolvent, SIGNAL(valueChanged(double)), this, SLOT(amtSolventChanged()));
0044     connect(ui.amtSlvtType, SIGNAL(activated(int)), this, SLOT(amtSolventTypeChanged()));
0045     connect(ui.amtSlvt_unit, SIGNAL(activated(int)), this, SLOT(amtSolventChanged()));
0046     // Molar mass change for solvent
0047     connect(ui.molarMassSolvent, SIGNAL(valueChanged(double)), this, SLOT(molarMassSolventChanged(double)));
0048     // Density changed
0049     connect(ui.densitySolvent, SIGNAL(valueChanged(double)), this, SLOT(densitySolventChanged()));
0050     connect(ui.densSlvt_unit, SIGNAL(activated(int)), this, SLOT(densitySolventChanged()));
0051     // concentration change
0052     connect(ui.concentration, SIGNAL(valueChanged(double)), this, SLOT(concentrationChanged()));
0053     connect(ui.conc_unit, SIGNAL(activated(int)), this, SLOT(concentrationChanged()));
0054     // Mode change
0055     connect(ui.mode, SIGNAL(activated(int)), this, SLOT(setMode(int)));
0056 
0057     connect(ui.reset, &QAbstractButton::clicked, this, &concCalculator::init);
0058 
0059     /**************************************************************************/
0060     //              concentration Calculator setup complete
0061     /**************************************************************************/
0062     if (Prefs::soluteMass()) {
0063         ui.amtSltType->setCurrentIndex(0);
0064     }
0065     if (Prefs::solventVolume()) {
0066         ui.amtSlvtType->setCurrentIndex(0);
0067     }
0068 }
0069 
0070 concCalculator::~concCalculator() = default;
0071 
0072 // Initialises values and GUI.
0073 void concCalculator::init()
0074 {
0075     error(RESET_CONC_MESSAGE);
0076 
0077     ui.amtSltType->addItems({"Mass", "Volume", "Moles"});
0078     ui.amtSlvtType->addItems({"Volume", "Mass", "Moles"});
0079     ui.densSlt_unit->addItems({"grams per liter"});
0080     ui.densSlvt_unit->addItems({"grams per liter"});
0081     ui.conc_unit->addItems({"molar", "Normal", "% (mass)", "% (volume)", "% (moles)"});
0082 
0083     amtSoluteTypeChanged();
0084     amtSolventTypeChanged();
0085 
0086     ui.amtSolute->setValue(117.0);
0087     ui.molarMass->setValue(58.5);
0088     ui.eqtMass->setValue(58.5);
0089     ui.densitySolute->setValue(2.7);
0090     ui.amtSolvent->setValue(1.0);
0091     ui.molarMassSolvent->setValue(18.0);
0092     ui.densitySolvent->setValue(1000.0);
0093     ui.concentration->setValue(2.0);
0094 
0095     ui.amtSltType->setCurrentIndex(0);
0096     ui.amtSlt_unit->setCurrentIndex(0);
0097     ui.densSlt_unit->setCurrentIndex(0);
0098     ui.amtSlvtType->setCurrentIndex(0);
0099     ui.amtSlvt_unit->setCurrentIndex(0);
0100     ui.densSlvt_unit->setCurrentIndex(0);
0101     ui.conc_unit->setCurrentIndex(0);
0102 
0103     // Initialise values
0104     m_amtSolute = Value(117.0, KUnitConversion::Gram);
0105     m_amtSolvent = Value(1.0, KUnitConversion::Liter);
0106     m_molarMass = 58.5;
0107     m_eqtMass = 58.5;
0108     m_molesSolute = 2.0;
0109     m_molesSolvent = 55.5;
0110     m_molarMassSolvent = 18.0;
0111     m_densitySolute = Value(2.7, KUnitConversion::GramPerMilliliter);
0112     m_concentration = 2.0;
0113     m_densitySolvent = Value(1000.0, KUnitConversion::GramPerLiter);
0114     // Initialisation of values done
0115 
0116     setMode(5);
0117 }
0118 
0119 // Calculates the amount of solute
0120 void concCalculator::calculateAmtSolute()
0121 {
0122     int type1 = ui.conc_unit->currentIndex();
0123     int type2 = ui.amtSltType->currentIndex();
0124 
0125     double molesSolute, eqtsSolute, massSolute, volSolute; // variables
0126     int mode = 0;
0127     /*
0128      * mode = 1 (molesSolute) mode = 2 eqtsSolute, mode = 3 mass, 4 volume
0129      */
0130     // Calculate the number of moles of the solute
0131     switch (type1) {
0132         // calculate the number of moles of solute
0133     case 0: // molarity specified
0134         molesSolute = m_concentration * volumeSolvent();
0135         mode = 1;
0136         break;
0137         // Calculate the number of equivalents of solute
0138     case 1: // Normality specified
0139         eqtsSolute = m_concentration * volumeSolvent();
0140         mode = 2;
0141         break;
0142         // Calculate the number of moles of solute
0143     case 2: // molality specified
0144         molesSolute = m_concentration * massSolvent() / 1000.0;
0145         mode = 1;
0146         break;
0147         // Calculate the mass of solute
0148     case 3: // mass percentage specified
0149         if (m_concentration >= 100.0) {
0150             error(PERCENTAGE);
0151         }
0152         massSolute = m_concentration / (100.0 - m_concentration) * massSolvent();
0153         mode = 3;
0154         break;
0155         // Calculate the volume of solute
0156     case 4: // volume percentage specified
0157         if (m_concentration >= 100.0) {
0158             error(PERCENTAGE);
0159         }
0160         volSolute = m_concentration / (100.0 - m_concentration) * volumeSolvent();
0161         mode = 4;
0162         break;
0163         // Calculate the moles of solute
0164     case 5: // mole percentage specified
0165         if (m_concentration >= 100.0) {
0166             error(PERCENTAGE);
0167         }
0168         molesSolute = m_concentration / (100.0 - m_concentration) * molesSolvent();
0169         mode = 1;
0170         break;
0171     default:
0172         break;
0173     }
0174 
0175     // We have the amount of solvent in some form (moles, equivalents, mass, volume etc)
0176     // Now we have to present it in the UI
0177     switch (type2) {
0178     case 0: // amount should be specified in terms of mass
0179         switch (mode) {
0180         case 1: // we should get mass from moles
0181             massSolute = molesSolute * m_molarMass;
0182             break;
0183         case 2: // we should obtain mass from number of equivalents
0184             massSolute = eqtsSolute * m_eqtMass;
0185             break;
0186         case 3: // we already know the mass of the solute
0187             break;
0188         case 4: // we should get the mass from volume
0189             massSolute = volSolute * densitySolute();
0190             break;
0191         }
0192         // update mass of solute
0193         m_amtSolute = Value(massSolute, KUnitConversion::Gram);
0194         m_amtSolute = m_amtSolute.convertTo(ui.amtSlt_unit->currentText());
0195         ui.amtSolute->setValue(m_amtSolute.number());
0196         break;
0197 
0198     case 1: // amount should be specified in terms of volume
0199         // validate density
0200         if (densitySolute() == 0) {
0201             error(DENSITY_ZERO);
0202             return;
0203         }
0204         switch (mode) {
0205         case 1: // we should get the volume from moles
0206             volSolute = molesSolute * m_molarMass / densitySolute();
0207             break;
0208         case 2: // we should get the volume from equivalents
0209             volSolute = eqtsSolute * m_eqtMass / densitySolute();
0210             break;
0211         case 3: // we should get the volume from mass
0212             volSolute = massSolute / densitySolute();
0213             break;
0214         case 4: // we already know the volume
0215             break;
0216         }
0217         // update volume of solute
0218         m_amtSolute = Value(volSolute, KUnitConversion::Liter);
0219         m_amtSolute = m_amtSolute.convertTo(ui.amtSlt_unit->currentText());
0220         ui.amtSolute->setValue(m_amtSolute.number());
0221         break;
0222 
0223     case 2: // amount should be specified in terms of moles
0224         switch (mode) {
0225         case 1: // we already know the moles of solute
0226             break;
0227         case 2: // we should obtain moles from equivalents (not possible)
0228             molesSolute = 0.0;
0229             break;
0230         case 3: // we should obtain moles from mass
0231             molesSolute = massSolute / m_molarMass;
0232             break;
0233         case 4: // we should obtain moles from volume
0234             molesSolute = volSolute * densitySolute() / m_molarMass;
0235             break;
0236         }
0237         // Update the number of moles
0238         m_molesSolute = molesSolute;
0239         ui.amtSolute->setValue(molesSolute);
0240         break;
0241     }
0242     return;
0243 }
0244 
0245 // Calculates the molar mass
0246 void concCalculator::calculateMolarMass()
0247 {
0248     // molarity / molality / mole fraction required
0249     int type = ui.conc_unit->currentIndex();
0250     int type2 = ui.amtSlvtType->currentIndex();
0251     double numMoles;
0252     switch (type) {
0253     case 0: // molarity specified
0254         // number of moles = volume * concentration
0255         numMoles = volumeSolvent() * m_concentration;
0256         break;
0257     case 1: // cannot be calculated (insufficient data)
0258         error(INSUFFICIENT_DATA_MOLE);
0259         return;
0260     case 2: // molality specified
0261         numMoles = massSolvent() / 1000.0 * m_concentration;
0262         break;
0263     case 3: // cannot be calculated (insufficient data)
0264     case 4:
0265         error(INSUFFICIENT_DATA_MOLE);
0266         return;
0267     case 5: // mole fraction specified
0268         numMoles = m_concentration / (100.0 - m_concentration) * molesSolvent();
0269         break;
0270     }
0271 
0272     if (type2 == 2) { // amount of solute is specified in moles, cannot calculate
0273         error(INSUFFICIENT_DATA_MOLES);
0274         return;
0275     } else {
0276         if (numMoles == 0.0) {
0277             error(MOLES_ZERO);
0278             return;
0279         }
0280         m_molarMass = massSolute() / numMoles;
0281         ui.molarMass->setValue(m_molarMass);
0282     }
0283 }
0284 
0285 // Calculates the equivalent mass
0286 void concCalculator::calculateEqtMass()
0287 {
0288     // Normality required
0289     int type = ui.conc_unit->currentIndex();
0290     int type2 = ui.amtSltType->currentIndex();
0291 
0292     double numEqts;
0293     switch (type) {
0294         // Normality required
0295     case 0: // molarity not sufficient
0296         error(INSUFFICIENT_DATA_EQT);
0297         return;
0298     case 1: // normality specified
0299         numEqts = volumeSolvent() * m_concentration;
0300         break;
0301     case 2:
0302     case 3:
0303     case 4:
0304     case 5:
0305         error(INSUFFICIENT_DATA_EQT);
0306         return;
0307     }
0308 
0309     if (type2 == 2) { // Amount of solute specified in moles, cannot calculate
0310         error(INSUFFICIENT_DATA_MOLES);
0311     } else {
0312         if (numEqts == 0.0) {
0313             error(EQTS_ZERO);
0314             return;
0315         }
0316         m_eqtMass = massSolute() / numEqts;
0317         ui.eqtMass->setValue(m_eqtMass);
0318     }
0319     return;
0320 }
0321 
0322 // Calculates the calculate molar mass of the solvent
0323 void concCalculator::calculateMolarMassSolvent()
0324 {
0325     // molarity / molality / mole fraction required
0326     int type = ui.conc_unit->currentIndex();
0327     int type2 = ui.amtSlvtType->currentIndex();
0328     double numMoles;
0329     switch (type) {
0330     case 0: // molarity specified
0331     case 1: // normality specified
0332     case 2: // molality specified
0333     case 3: // mass fraction specified
0334     case 4: // volume fraction specified
0335         error(INSUFFICIENT_DATA_SOLVENT);
0336         return; // cannot be calculated (insufficient data)
0337     case 5: // mole fraction specified
0338         numMoles = (100.0 - m_concentration) / m_concentration * molesSolute();
0339         break;
0340     }
0341 
0342     if (type2 == 2) { // amount specified in moles
0343         error(INSUFFICIENT_DATA_MOLES);
0344     } else {
0345         m_molarMassSolvent = massSolvent() / numMoles;
0346         ui.molarMassSolvent->setValue(m_molarMassSolvent);
0347     }
0348 
0349     return;
0350 }
0351 
0352 // Calculates the amount of solvent
0353 void concCalculator::calculateAmtSolvent()
0354 {
0355     int type1 = ui.conc_unit->currentIndex();
0356     int type2 = ui.amtSlvtType->currentIndex();
0357 
0358     double moleSolvent, massSolvent, volSolvent;
0359 
0360     int mode = 0; // Indicates the mode in which we have calculated the amount of solvent
0361     /*
0362      * mode = 1 (molessolvent) mode = 2 eqtssolvent, mode = 3 mass, 4 volume
0363      */
0364     // Calculate the number of moles of the solvent
0365     if (m_concentration == 0.0) {
0366         error(CONC_ZERO);
0367         return;
0368     }
0369 
0370     switch (type1) {
0371         // calculate the number of moles of solvent
0372     case 0: // molarity specified
0373         volSolvent = molesSolute() / m_concentration;
0374         mode = 3;
0375         break;
0376         // Calculate the number of equivalents of solvent
0377     case 1: // Normality specified
0378         volSolvent = eqtsSolute() / m_concentration;
0379         mode = 3;
0380         break;
0381         // Calculate the number of moles of solvent
0382     case 2: // molality specified
0383         massSolvent = molesSolute() * 1000.0 / m_concentration;
0384         mode = 2;
0385         break;
0386         // Calculate the mass of solvent
0387     case 3: // mass percentage specified
0388         massSolvent = (100.0 - m_concentration) / m_concentration;
0389         massSolvent *= massSolute();
0390         mode = 2;
0391         break;
0392         // Calculate the volume of solvent
0393     case 4: // volume percentage specified
0394         volSolvent = (100.0 - m_concentration) / m_concentration;
0395         volSolvent *= volumeSolute();
0396         mode = 3;
0397         break;
0398         // Calculate the moles of solvent
0399     case 5: // mole percentage specified
0400         moleSolvent = (100.0 - m_concentration) / m_concentration;
0401         moleSolvent *= molesSolute();
0402         mode = 1;
0403         break;
0404     default:
0405         break;
0406     }
0407 
0408     // We have the amount of solvent in some form (moles, equivalents, mass, volume etc)
0409     // Now we have to present it in the UI
0410     if (densitySolvent() == 0.0) {
0411         error(DENSITY_ZERO);
0412         return;
0413     }
0414     if (m_molarMassSolvent == 0.0) {
0415         error(MOLAR_SOLVENT_ZERO);
0416         return;
0417     }
0418     switch (type2) {
0419     case 0: // amount should be specified interms of volume
0420         switch (mode) {
0421         case 1: // obtain volume from moles
0422             volSolvent = moleSolvent * m_molarMassSolvent / densitySolvent();
0423             break;
0424         case 2: // obtain volume from mass
0425             volSolvent = massSolvent / densitySolvent();
0426             break;
0427         case 3: // volume already known
0428             break;
0429         }
0430         m_amtSolvent = Value(volSolvent, KUnitConversion::Liter);
0431         m_amtSolvent = m_amtSolvent.convertTo(ui.amtSlvt_unit->currentText());
0432         ui.amtSolvent->setValue(m_amtSolvent.number());
0433         break;
0434 
0435     case 1: // amount should be specified in terms of mass
0436         switch (mode) {
0437         case 1: // obtain mass from moles
0438             massSolvent = moleSolvent / m_molarMassSolvent;
0439             break;
0440         case 2: // mass already known
0441             break;
0442         case 3: // obtain mass from volume
0443             massSolvent = volSolvent / densitySolvent();
0444             break;
0445         }
0446         m_amtSolvent = Value(massSolvent, KUnitConversion::Gram);
0447         m_amtSolvent = m_amtSolvent.convertTo(ui.amtSlvt_unit->currentText());
0448         ui.amtSolvent->setValue(m_amtSolvent.number());
0449         break;
0450 
0451     case 2: // amount should be specified in terms of moles
0452         switch (mode) {
0453         case 1: // moles already known
0454             break;
0455         case 2: // obtain moles from mass
0456             moleSolvent = massSolvent / m_molarMassSolvent;
0457             break;
0458         case 3: // obtain moles from volume
0459             moleSolvent = volSolvent * densitySolvent() / m_molarMassSolvent;
0460             break;
0461         }
0462         m_molesSolvent = moleSolvent;
0463         ui.amtSolvent->setValue(moleSolvent);
0464         break;
0465     }
0466     return;
0467 }
0468 
0469 // calculates the concentration
0470 void concCalculator::calculateConcentration()
0471 {
0472     int type = ui.conc_unit->currentIndex();
0473 
0474     if (volumeSolvent() == 0.0) {
0475         error(SOLVENT_VOLUME_ZERO);
0476         return;
0477     }
0478     if (massSolvent() == 0.0) {
0479         error(SOLVENT_MASS_ZERO);
0480         return;
0481     }
0482     if (molesSolvent() == 0.0) {
0483         error(SOLVENT_MOLES_ZERO);
0484         return;
0485     }
0486     switch (type) {
0487     case 0: // molarity
0488         m_concentration = molesSolute() / volumeSolvent();
0489         break;
0490     case 1: // normality
0491         m_concentration = eqtsSolute() / volumeSolvent();
0492         break;
0493     case 2: // molality
0494         m_concentration = molesSolute() * 1000.0 / massSolvent();
0495         break;
0496     case 3: // mass fraction
0497         m_concentration = massSolute() / (massSolute() + massSolvent()) * 100.0;
0498         break;
0499     case 4: // volume fraction
0500         m_concentration = volumeSolute() / (volumeSolute() + volumeSolvent()) * 100.0;
0501         break;
0502     case 5: // mole fraction
0503         m_concentration = molesSolute() / (molesSolute() + molesSolvent()) * 100.0;
0504         break;
0505     default:
0506         m_concentration = 0;
0507         break;
0508     }
0509     ui.concentration->setValue(m_concentration);
0510     return;
0511 }
0512 
0513 double concCalculator::volumeSolvent()
0514 {
0515     int type = ui.amtSlvtType->currentIndex();
0516     switch (type) {
0517     case 0: // If volume is specified, return it in liters
0518         return m_amtSolvent.convertTo(KUnitConversion::Liter).number();
0519     case 1: // If mass is specified, calculate volume and return it.
0520         return massSolvent() / densitySolvent();
0521     case 2: // If moles are specified, calculated volume and return it.
0522         return massSolvent() / densitySolvent();
0523     default:
0524         return 0;
0525     }
0526     Q_UNREACHABLE();
0527 }
0528 
0529 double concCalculator::molesSolvent()
0530 {
0531     int type = ui.amtSlvtType->currentIndex();
0532 
0533     double moles;
0534     switch (type) {
0535     case 0:
0536         moles = massSolvent() / m_molarMassSolvent;
0537         break;
0538     case 1:
0539         moles = massSolvent() / m_molarMassSolvent;
0540         break;
0541     case 2:
0542         moles = m_molesSolvent;
0543         break;
0544     default:
0545         moles = 0;
0546         break;
0547     }
0548     return moles;
0549 }
0550 double concCalculator::massSolvent()
0551 {
0552     int type = ui.amtSlvtType->currentIndex();
0553     double mass;
0554     switch (type) {
0555     case 0:
0556         mass = volumeSolvent() * densitySolvent();
0557         break;
0558     case 1:
0559         mass = m_amtSolvent.convertTo(KUnitConversion::Gram).number();
0560         break;
0561     case 2:
0562         mass = m_molesSolvent * m_molarMassSolvent;
0563         break;
0564     default:
0565         mass = 0;
0566         break;
0567     }
0568     return mass;
0569 }
0570 
0571 double concCalculator::densitySolvent()
0572 {
0573     return (m_densitySolvent.convertTo(KUnitConversion::GramPerLiter).number());
0574 }
0575 
0576 double concCalculator::volumeSolute()
0577 {
0578     int type = ui.amtSltType->currentIndex();
0579     double volume;
0580     switch (type) {
0581     case 0:
0582         volume = massSolute() / densitySolute();
0583         break;
0584     case 1:
0585         volume = m_amtSolute.convertTo(KUnitConversion::Liter).number();
0586         break;
0587     case 2:
0588         volume = massSolute() / densitySolute();
0589         break;
0590     default:
0591         volume = 0;
0592         break;
0593     }
0594     return volume;
0595 }
0596 
0597 double concCalculator::molesSolute()
0598 {
0599     int type = ui.amtSltType->currentIndex();
0600 
0601     double moles;
0602     if (m_molarMass == 0.0) {
0603         error(MOLAR_MASS_ZERO);
0604         return 1.0;
0605     }
0606     switch (type) {
0607     case 0:
0608         moles = massSolute() / m_molarMass;
0609         break;
0610     case 1:
0611         moles = massSolute() / m_molarMass;
0612         break;
0613     case 2:
0614         moles = m_molesSolute;
0615         break;
0616     default:
0617         moles = 0;
0618         break;
0619     }
0620     return moles;
0621 }
0622 
0623 double concCalculator::eqtsSolute()
0624 {
0625     int type = ui.amtSltType->currentIndex();
0626     double eqts;
0627     if (m_eqtMass == 0.0) {
0628         error(EQT_MASS_ZERO);
0629         return 1.0;
0630     }
0631     switch (type) {
0632     case 0:
0633         eqts = massSolute() / m_eqtMass;
0634         break;
0635     case 1:
0636         eqts = massSolute() / m_eqtMass;
0637         break;
0638     case 2:
0639         // Cannot be calculated
0640         error(INSUFFICIENT_DATA_MOLES);
0641         eqts = 1.0;
0642         break;
0643     default:
0644         eqts = 0;
0645         break;
0646     }
0647     return eqts;
0648 }
0649 
0650 double concCalculator::massSolute()
0651 {
0652     int type = ui.amtSltType->currentIndex();
0653     double mass;
0654     switch (type) {
0655     case 0:
0656         mass = m_amtSolute.convertTo(KUnitConversion::Gram).number();
0657         break;
0658     case 1:
0659         mass = volumeSolute() * densitySolute();
0660         break;
0661     case 2:
0662         mass = m_molesSolute * m_molarMass;
0663         break;
0664     default:
0665         mass = 0;
0666         break;
0667     }
0668     return mass;
0669 }
0670 
0671 double concCalculator::densitySolute()
0672 {
0673     return (m_densitySolute.convertTo(KUnitConversion::GramPerLiter).number());
0674 }
0675 
0676 // occurs when the type in which amount of solute is specified is changed
0677 void concCalculator::amtSoluteTypeChanged()
0678 {
0679     int type = ui.amtSltType->currentIndex();
0680     if (type == 0) {
0681         // amount of solute specified in terms of mass
0682         massUnitCombobox(ui.amtSlt_unit);
0683 
0684         m_amtSolute = Value(ui.amtSolute->value(), ui.amtSlt_unit->currentText());
0685     } else if (type == 1) {
0686         // amount of solute is specified in terms of volume
0687         volumeUnitCombobox(ui.amtSlt_unit);
0688 
0689         m_amtSolute = Value(ui.amtSolute->value(), ui.amtSlt_unit->currentText());
0690     } else { // amount of solute is specified in terms of moles
0691         m_molesSolute = ui.amtSolute->value();
0692         ui.amtSlt_unit->hide();
0693     }
0694     calculate();
0695 }
0696 
0697 void concCalculator::massUnitCombobox(QComboBox *comboBox)
0698 {
0699     comboBox->show();
0700 
0701     QList<int> units;
0702     units << Gram << Milligram << Kilogram << Ton << Carat << Pound << Ounce << TroyOunce;
0703     KalziumUtils::populateUnitCombobox(comboBox, units);
0704 
0705     comboBox->setCurrentIndex(0);
0706 }
0707 
0708 void concCalculator::volumeUnitCombobox(QComboBox *comboBox)
0709 {
0710     comboBox->show();
0711 
0712     QList<int> units;
0713     units << Liter << Milliliter << CubicMeter << CubicFoot << CubicInch << CubicMile << FluidOunce << Cup << GallonUS << PintImperial;
0714     KalziumUtils::populateUnitCombobox(comboBox, units);
0715 
0716     comboBox->setCurrentIndex(0);
0717 }
0718 
0719 void concCalculator::amtSoluteChanged()
0720 {
0721     int type = ui.amtSltType->currentIndex();
0722     switch (type) {
0723     case 0:
0724     case 1:
0725         m_amtSolute = Value(ui.amtSolute->value(), ui.amtSlt_unit->currentText());
0726         break;
0727     case 2:
0728         m_molesSolute = ui.amtSolute->value();
0729         break;
0730     }
0731     calculate();
0732 }
0733 // occurs when the type in which amount of solvent is specified is changed
0734 void concCalculator::amtSolventTypeChanged()
0735 {
0736     int type = ui.amtSlvtType->currentIndex();
0737     if (type == 0) {
0738         // amount of solvent specified in terms of volume
0739         volumeUnitCombobox(ui.amtSlvt_unit);
0740 
0741         m_amtSolvent = Value(ui.amtSolvent->value(), ui.amtSlvt_unit->currentText());
0742     } else if (type == 1) {
0743         // amount of solvent is specified in terms of mass
0744         massUnitCombobox(ui.amtSlvt_unit);
0745 
0746         m_amtSolvent = Value(ui.amtSolvent->value(), ui.amtSlvt_unit->currentText());
0747     } else {
0748         ui.amtSlvt_unit->hide();
0749         m_molesSolvent = ui.amtSolvent->value();
0750     }
0751     calculate();
0752 }
0753 
0754 // Occurs when the amount of solute is changed
0755 void concCalculator::amtSolventChanged()
0756 {
0757     int type = ui.amtSlvtType->currentIndex();
0758     switch (type) { // amount of solvent specified in terms of volume
0759     case 0:
0760     case 1:
0761         m_amtSolvent = Value(ui.amtSolvent->value(), ui.amtSlvt_unit->currentText());
0762         break;
0763     case 2:
0764         m_molesSolvent = ui.amtSolvent->value();
0765         break;
0766     }
0767     calculate();
0768 }
0769 // occurs when the molar mass of solute is changed
0770 void concCalculator::molarMassChanged(double value)
0771 {
0772     m_molarMass = value;
0773     calculate();
0774 }
0775 
0776 // occurs when the equivalent mass of solute is changed
0777 void concCalculator::eqtMassChanged(double value)
0778 {
0779     m_eqtMass = value;
0780     calculate();
0781 }
0782 
0783 // occurs when the molar mass of solvent is changed
0784 void concCalculator::molarMassSolventChanged(double value)
0785 {
0786     m_molarMassSolvent = value;
0787     calculate();
0788 }
0789 
0790 // occurs when the number of moles is changed
0791 void concCalculator::densitySoluteChanged()
0792 {
0793     m_densitySolute = Value(ui.densitySolute->value(), ui.densSlt_unit->currentText());
0794     calculate();
0795 }
0796 
0797 // occurs when the density of solvent is changed
0798 void concCalculator::densitySolventChanged()
0799 {
0800     m_densitySolvent = Value(ui.densitySolvent->value(), ui.densSlvt_unit->currentText());
0801     calculate();
0802 }
0803 
0804 // occurs when the concentration is changed
0805 void concCalculator::concentrationChanged()
0806 {
0807     m_concentration = ui.concentration->value();
0808     calculate();
0809 }
0810 
0811 // occurs when mode is changed. eg Concentration to molarMass
0812 void concCalculator::setMode(int mode)
0813 {
0814     // If there is no change, return.
0815     if (m_mode == mode) {
0816         return;
0817     }
0818 
0819     // set all to writable
0820     ui.amtSolute->setReadOnly(false);
0821     ui.molarMass->setReadOnly(false);
0822     ui.eqtMass->setReadOnly(false);
0823     ui.amtSolvent->setReadOnly(false);
0824     ui.molarMassSolvent->setReadOnly(false);
0825     ui.concentration->setReadOnly(false);
0826 
0827     // set the value that should be calculated to readOnly
0828     switch (mode) {
0829     case AMT_SOLUTE: // Calculate the amount of solute
0830         ui.amtSolute->setReadOnly(true);
0831         break;
0832     case MOLAR_MASS: // Calculate the molar mass of solute
0833         ui.molarMass->setReadOnly(true);
0834         break;
0835     case EQT_MASS: // Calculate the equivalent mass of solute
0836         ui.eqtMass->setReadOnly(true);
0837         break;
0838     case AMT_SOLVENT: // Calculate the amount of solvent
0839         ui.amtSolvent->setReadOnly(true);
0840         break;
0841     case MOLAR_MASS_SOLVENT: // Calculate the molar mass of solvent
0842         ui.molarMassSolvent->setReadOnly(true);
0843         break;
0844     case CONCENTRATION: // Calculate the concentration of the solution
0845         ui.concentration->setReadOnly(true);
0846         break;
0847     }
0848 
0849     m_mode = mode;
0850     calculate();
0851 }
0852 // occurs when any quantity is changed
0853 void concCalculator::calculate()
0854 {
0855     error(RESET_CONC_MESSAGE);
0856     // Calculate the amount of solute
0857     switch (m_mode) {
0858     case AMT_SOLUTE: // Calculate the amount of solute
0859         if (ui.conc_unit->currentIndex() > 2 && ui.concentration->value() > 100) {
0860             error(PERCENTAGE);
0861             return;
0862         }
0863         calculateAmtSolute();
0864         break;
0865     case MOLAR_MASS: // Calculate the molar mass of solute
0866         calculateMolarMass();
0867         break;
0868     case EQT_MASS: // Calculate the equivalent mass of solute
0869         calculateEqtMass();
0870         break;
0871     case AMT_SOLVENT: // Calculate the amount of solvent
0872         calculateAmtSolvent();
0873         break;
0874     case MOLAR_MASS_SOLVENT: // Calculate the molar mass of solvent
0875         calculateMolarMassSolvent();
0876         break;
0877     case CONCENTRATION: // Calculate the concentration of the solution
0878         calculateConcentration();
0879         break;
0880     }
0881     return;
0882 }
0883 
0884 // This function puts the error messages on the screen depending on the mode.
0885 void concCalculator::error(int mode)
0886 {
0887     switch (mode) { // Depending on the mode, set the error messages.
0888     case RESET_CONC_MESSAGE:
0889         ui.error->setText(QLatin1String(""));
0890         break;
0891     case PERCENTAGE:
0892         ui.error->setText(i18n("Percentage should be less than 100.0, please enter a valid value."));
0893         break;
0894     case DENSITY_ZERO:
0895         ui.error->setText(i18n("Density cannot be zero, please enter a valid value."));
0896         break;
0897     case MASS_ZERO:
0898         ui.error->setText(i18n("Mass cannot be zero, please enter a valid value."));
0899         break;
0900     case VOLUME_ZERO:
0901         ui.error->setText(i18n("Volume cannot be zero, please enter a valid value."));
0902         break;
0903     case MOLES_ZERO:
0904         ui.error->setText(i18n("Number of moles cannot be zero, please enter a valid value."));
0905         break;
0906     case MOLAR_SOLVENT_ZERO:
0907         ui.error->setText(i18n("Molar mass of solvent is zero, please enter a valid value."));
0908         break;
0909     case EQTS_ZERO:
0910         ui.error->setText(i18n("Number of equivalents is zero. Cannot calculate equivalent mass."));
0911         break;
0912     case CONC_ZERO:
0913         ui.error->setText(i18n("Concentration is zero, please enter a valid value."));
0914         break;
0915     case SOLVENT_VOLUME_ZERO:
0916         ui.error->setText(i18n("The volume of the solvent cannot be zero."));
0917         break;
0918     case SOLVENT_MOLES_ZERO:
0919         ui.error->setText(i18n("The number of moles of the solvent cannot be zero."));
0920         break;
0921     case SOLVENT_MASS_ZERO:
0922         ui.error->setText(i18n("The mass of the solvent cannot be zero."));
0923         break;
0924     case INSUFFICIENT_DATA_EQT:
0925         ui.error->setText(i18n("Insufficient data to calculate the required value, please specify normality."));
0926         break;
0927     case INSUFFICIENT_DATA_MOLE:
0928         ui.error->setText(i18n("Insufficient data, specify molarity / mole fraction / molality to calculate."));
0929         break;
0930     case INSUFFICIENT_DATA_MOLES:
0931         ui.error->setText(i18n("The amount is specified in moles, cannot calculate molar/equivalent masses. Please specify mass/volume."));
0932         break;
0933     case INSUFFICIENT_DATA_SOLVENT:
0934         ui.error->setText(i18n("You can calculate the molar mass of solvent only if the mole fraction is specified."));
0935         break;
0936     case MOLAR_MASS_ZERO:
0937         ui.error->setText(i18n("Molar mass cannot be zero, please enter a valid value."));
0938         break;
0939     case EQT_MASS_ZERO:
0940         ui.error->setText(i18n("Equivalent mass cannot be zero, please enter a valid value."));
0941         break;
0942     default:
0943         break;
0944     }
0945 }