File indexing completed on 2024-04-28 07:29:00

0001 /*
0002     SPDX-FileCopyrightText: 2005, 2006, 2007 Carsten Niehaus <cniehaus@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kalziumdataobject.h"
0008 
0009 #include <elementparser.h>
0010 #include <isotope.h>
0011 #include <isotopeparser.h>
0012 #include <spectrumparser.h>
0013 
0014 #include "kalzium_debug.h"
0015 #include <QCoreApplication>
0016 #include <QFile>
0017 #include <QPainter>
0018 #include <QStandardPaths>
0019 #include <QSvgRenderer>
0020 
0021 #include <KUnitConversion/Converter>
0022 
0023 struct StaticKalziumDataObject {
0024     KalziumDataObject kdo;
0025 };
0026 
0027 Q_GLOBAL_STATIC(StaticKalziumDataObject, s_kdo)
0028 
0029 KalziumDataObject *KalziumDataObject::instance()
0030 {
0031     return &s_kdo->kdo;
0032 }
0033 
0034 KalziumDataObject::KalziumDataObject()
0035 {
0036     // reading elements
0037     auto parser = new ElementSaxParser();
0038 
0039     QFile xmlFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("libkdeedu/data/elements.xml")));
0040     QXmlInputSource source(&xmlFile);
0041     QXmlSimpleReader reader;
0042 
0043     reader.setContentHandler(parser);
0044     reader.parse(source);
0045 
0046     ElementList = parser->getElements();
0047 
0048     // we don't need parser anymore, let's free its memory
0049     delete parser;
0050 
0051     // read the spectra
0052     auto spectrumparser = new SpectrumParser();
0053 
0054     QFile xmlSpFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("libkdeedu/data/spectra.xml")));
0055     QXmlInputSource spsource(&xmlSpFile);
0056     QXmlSimpleReader sp_reader;
0057 
0058     sp_reader.setContentHandler(spectrumparser);
0059     sp_reader.parse(spsource);
0060 
0061     m_spectra = spectrumparser->getSpectrums();
0062 
0063     // we don't need spectrumparser anymore, let's free its memory
0064     delete spectrumparser;
0065 
0066     // reading isotopes
0067     auto isoparser = new IsotopeParser();
0068 
0069     QFile xmlIsoFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("libkdeedu/data/isotopes.xml")));
0070     QXmlInputSource isosource(&xmlIsoFile);
0071     QXmlSimpleReader isoreader;
0072 
0073     isoreader.setContentHandler(isoparser);
0074     isoreader.parse(isosource);
0075 
0076     const QList<Isotope *> isotopes = isoparser->getIsotopes();
0077 
0078     // we don't need isoparser anymore, let's free its memory
0079     delete isoparser;
0080 
0081     for (Isotope *iso : isotopes) {
0082         int num = iso->parentElementNumber();
0083         if (m_isotopes.contains(num)) {
0084             m_isotopes[num].append(iso);
0085         } else {
0086             QList<Isotope *> newlist;
0087             newlist.append(iso);
0088             m_isotopes.insert(num, newlist);
0089         }
0090     }
0091 
0092     // cache it
0093     m_numOfElements = ElementList.count();
0094 
0095     qAddPostRoutine(KalziumDataObject::cleanup);
0096 }
0097 
0098 KalziumDataObject::~KalziumDataObject()
0099 {
0100     // Delete all elements
0101     qDeleteAll(ElementList);
0102 
0103     // Delete all isotopes
0104     QHashIterator<int, QList<Isotope *>> i(m_isotopes);
0105     while (i.hasNext()) {
0106         i.next();
0107         qDeleteAll(i.value());
0108     }
0109 
0110     // Delete the spectra
0111     qDeleteAll(m_spectra);
0112 }
0113 
0114 Element *KalziumDataObject::element(int number)
0115 {
0116     // checking that we are requesting a valid element
0117     if ((number <= 0) || (number > m_numOfElements))
0118         return nullptr;
0119     return ElementList[number - 1];
0120 }
0121 
0122 QString KalziumDataObject::unitAsString(const int unit) const
0123 {
0124     return KUnitConversion::Converter().unit(KUnitConversion::UnitId(unit)).symbol();
0125 }
0126 
0127 QPixmap KalziumDataObject::pixmap(int number)
0128 {
0129     // checking that we are requesting a valid element
0130     if ((number <= 0) || (number > m_numOfElements))
0131         return {};
0132     if (PixmapList.isEmpty())
0133         loadIconSet();
0134     return PixmapList[number - 1];
0135 }
0136 
0137 QList<Isotope *> KalziumDataObject::isotopes(Element *element)
0138 {
0139     return isotopes(element->dataAsVariant(ChemicalDataObject::atomicNumber).toInt());
0140 }
0141 
0142 QList<Isotope *> KalziumDataObject::isotopes(int number)
0143 {
0144     return m_isotopes.contains(number) ? m_isotopes.value(number) : QList<Isotope *>();
0145 }
0146 
0147 Spectrum *KalziumDataObject::spectrum(int number)
0148 {
0149     foreach (Spectrum *s, m_spectra) {
0150         if (s->parentElementNumber() == number) {
0151             return s;
0152         }
0153     }
0154 
0155     return nullptr;
0156 }
0157 
0158 void KalziumDataObject::setSearch(Search *srch)
0159 {
0160     m_search = srch;
0161 }
0162 
0163 Search *KalziumDataObject::search() const
0164 {
0165     return m_search;
0166 }
0167 
0168 void KalziumDataObject::cleanup()
0169 {
0170     KalziumDataObject::instance()->cleanPixmaps();
0171 }
0172 
0173 void KalziumDataObject::loadIconSet()
0174 {
0175     // FIXME in case we ever get more than one theme we need
0176     // a settings-dialog where we can select the different iconsets...
0177     const QString setname = QStringLiteral("school");
0178     const QString pathname = QStandardPaths::locate(QStandardPaths::AppLocalDataLocation, "data/iconsets/" + setname + '/', QStandardPaths::LocateDirectory);
0179     QSvgRenderer renderer;
0180 
0181     for (int i = 0; i < m_numOfElements; ++i) {
0182         const QString filename = pathname + QString::number(i + 1) + ".svg";
0183 
0184         renderer.load(filename);
0185         QPixmap pix(40, 40);
0186         pix.fill(Qt::transparent);
0187         QPainter p(&pix);
0188         renderer.render(&p);
0189 
0190         Element *e = ElementList.at(i);
0191         const QString esymbol = e->dataAsString(ChemicalDataObject::symbol);
0192         p.drawText(0, 0, 40, 40, Qt::AlignCenter | Qt::TextWordWrap, esymbol);
0193         p.end();
0194 
0195         PixmapList << pix;
0196     }
0197 }
0198 
0199 void KalziumDataObject::cleanPixmaps()
0200 {
0201     PixmapList.clear();
0202 }