File indexing completed on 2024-04-14 03:40:22

0001 /*
0002     SPDX-FileCopyrightText: 2005, 2006, 2007 Carsten Niehaus <cniehaus@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "kalziumutils.h"
0007 
0008 #include <config-kalzium.h>
0009 
0010 #include "kalzium_debug.h"
0011 #include <QFont>
0012 #include <QPainter>
0013 #include <QRect>
0014 
0015 #include <KLocalizedString>
0016 #include <KUnitConversion/Converter>
0017 
0018 #include <element.h>
0019 
0020 #include "prefs.h"
0021 
0022 #include <cmath>
0023 #if defined(HAVE_IEEEFP_H)
0024 #include <ieeefp.h>
0025 #endif
0026 
0027 int KalziumUtils::maxSize(const QString &string, const QRect &rect, QFont font, QPainter *p, int minFontSize, int maxFontSize)
0028 {
0029     bool goodSizeFound = false;
0030     int size = maxFontSize;
0031     QRect r;
0032 
0033     do {
0034         font.setPointSize(size);
0035         p->setFont(font);
0036         r = p->boundingRect(QRect(), Qt::AlignTop | Qt::AlignLeft, string);
0037         r.translate(rect.left(), rect.top());
0038 
0039         if (rect.contains(r)) {
0040             goodSizeFound = true;
0041         } else {
0042             --size;
0043         }
0044     } while (!goodSizeFound && (size > minFontSize));
0045 
0046     return size;
0047 }
0048 
0049 int KalziumUtils::StringHeight(const QString &string, const QFont &font, QPainter *p)
0050 {
0051     Q_UNUSED(font);
0052     return p->boundingRect(QRect(), Qt::AlignTop | Qt::AlignLeft, string).height();
0053 }
0054 
0055 int KalziumUtils::StringWidth(const QString &string, const QFont &font, QPainter *p)
0056 {
0057     Q_UNUSED(font);
0058     return p->boundingRect(QRect(), Qt::AlignTop | Qt::AlignLeft, string).width();
0059 }
0060 
0061 double KalziumUtils::strippedValue(double num)
0062 {
0063     if (!std::isfinite(num)) {
0064         return num;
0065     }
0066 
0067     double power;
0068     power = 1e-6;
0069     while (power < num) {
0070         power *= 10;
0071     }
0072 
0073     num = num / power * 10000;
0074     num = qRound(num);
0075 
0076     return num * power / 10000;
0077 }
0078 
0079 QString KalziumUtils::prettyUnit(const Element *el, ChemicalDataObject::BlueObelisk kind)
0080 {
0081     if (!el) {
0082         return i18n("Error");
0083     }
0084 
0085     QString result;
0086     double val = 0.0; // the value to convert
0087 
0088     switch (kind) {
0089     case ChemicalDataObject::meltingpoint: // a temperature
0090     case ChemicalDataObject::boilingpoint:
0091         result = el->dataAsStringWithUnit(kind, Prefs::temperatureUnit());
0092         break;
0093 
0094     case ChemicalDataObject::electronegativityPauling: // electronegativity
0095     {
0096         val = el->dataAsVariant(kind).toDouble();
0097         if (val <= 0.0) {
0098             result = i18n("Value not defined");
0099         } else {
0100             result = i18nc("Just a number", "%1", val);
0101         }
0102         break;
0103     }
0104     case ChemicalDataObject::electronAffinity: // an energy
0105     case ChemicalDataObject::ionization:
0106         result = el->dataAsStringWithUnit(kind, Prefs::energiesUnit());
0107         break;
0108 
0109     case ChemicalDataObject::mass: // a mass
0110     {
0111         val = el->dataAsVariant(kind).toDouble();
0112         if (val <= 0.0) {
0113             result = i18n("Unknown Value");
0114         } else {
0115             result = i18nc("x u (units). The atomic mass.", "%1 u", val);
0116         }
0117         break;
0118     }
0119     case ChemicalDataObject::date: // a date
0120     {
0121         int v_int = el->dataAsVariant(kind).toInt();
0122         if (v_int > 1600) {
0123             result = i18n("This element was discovered in the year %1.", QString::number(v_int));
0124         } else if (v_int == -1) {
0125             result = i18n("The element has not yet been officially recognized by the IUPAC.");
0126         } else { // this should now really be 0. If not there is a bug in the database
0127             result = i18n("This element was known to ancient cultures.");
0128         }
0129         break;
0130     }
0131     case ChemicalDataObject::radiusCovalent:
0132     case ChemicalDataObject::radiusVDW: {
0133         result = el->dataAsStringWithUnit(kind, Prefs::lengthUnit());
0134         break;
0135     }
0136     case ChemicalDataObject::electronicConfiguration: {
0137         QString newOrbit = el->dataAsString(kind);
0138 
0139         QRegularExpression reg("(.*)([spdf])(\\d+)(.*)");
0140 
0141         while (newOrbit.contains(reg)) {
0142             newOrbit = newOrbit.replace(reg, R"(\1\2<sup>\3</sup>\4)");
0143         }
0144         result = newOrbit;
0145         break;
0146     }
0147     case ChemicalDataObject::oxidation: {
0148         QStringList oxidationList = el->dataAsString(kind).split(',');
0149         result = oxidationList.join(QStringLiteral(", "));
0150         break;
0151     }
0152     default:
0153         result = el->dataAsVariant(kind).toString();
0154     }
0155 
0156     if (result.isEmpty()) {
0157         result = i18n("No Data");
0158     }
0159     return result;
0160 }
0161 
0162 void KalziumUtils::populateUnitCombobox(QComboBox *comboBox, const QList<int> &unitList)
0163 {
0164     comboBox->clear();
0165 
0166     QString unitString;
0167 
0168     for (int unit : unitList) {
0169         unitString = KUnitConversion::Converter().unit(KUnitConversion::UnitId(unit)).description();
0170         unitString.append(" (");
0171         unitString.append(KUnitConversion::Converter().unit(KUnitConversion::UnitId(unit)).symbol());
0172         unitString.append(")");
0173         comboBox->addItem(unitString, unit);
0174     }
0175 }