File indexing completed on 2024-04-21 03:41:42

0001 /*
0002     SPDX-FileCopyrightText: 2006 Carsten Niehaus <cniehaus@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "gradientwidget_impl.h"
0007 #include "kalziumelementproperty.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include "kalzium_debug.h"
0012 #include <QIcon>
0013 #include <QTimer>
0014 
0015 #include <cmath>
0016 #include <element.h>
0017 
0018 #include "kalziumdataobject.h"
0019 #include "prefs.h"
0020 
0021 // used to convert the double variables to int's. (slider <-> spinbox)
0022 #define MULTIPLIKATOR 1000
0023 
0024 GradientWidgetImpl::GradientWidgetImpl(QWidget *parent)
0025     : QWidget(parent)
0026     , m_timer(new QTimer(this))
0027 {
0028     setupUi(this);
0029 
0030     scheme_combo->addItems(KalziumElementProperty::instance()->schemeList());
0031     gradient_combo->addItems(KalziumElementProperty::instance()->gradientList());
0032 
0033     connect(gradient_spinbox, SIGNAL(valueChanged(double)), this, SLOT(doubleToSlider(double)));
0034     connect(gradient_slider, &QAbstractSlider::valueChanged, this, &GradientWidgetImpl::intToSpinbox);
0035 
0036     connect(Play, &QAbstractButton::clicked, this, &GradientWidgetImpl::play);
0037     connect(m_timer, &QTimer::timeout, this, &GradientWidgetImpl::tick);
0038 
0039     Play->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
0040 }
0041 
0042 GradientWidgetImpl::~GradientWidgetImpl()
0043 {
0044     delete m_timer;
0045 }
0046 
0047 void GradientWidgetImpl::slotGradientChanged()
0048 {
0049     if (!gradient_slider->isEnabled()) {
0050         gradient_spinbox->setEnabled(true);
0051         gradient_slider->setEnabled(true);
0052         Play->setEnabled(true);
0053     }
0054 
0055     KalziumElementProperty *elementProperty = KalziumElementProperty::instance();
0056     double dblMax = elementProperty->gradient()->maxValue();
0057     double dblMin = elementProperty->gradient()->minValue();
0058 
0059     // saving the decimals in the int
0060     const int intMax = dblMax * MULTIPLIKATOR;
0061     const int intMin = dblMin * MULTIPLIKATOR;
0062 
0063     // now we have the slider numbers, so put the speed to a adequate value.
0064     Speed->setMaximum(intMax / 100);
0065     Speed->setValue((intMax / 100) / 2);
0066 
0067     gradient_slider->setMaximum(intMax);
0068     gradient_slider->setMinimum(intMin);
0069 
0070     lblUnit->setText(elementProperty->gradient()->unit());
0071 
0072     gradient_spinbox->setMaximum(dblMax);
0073     gradient_spinbox->setMinimum(dblMin);
0074     gradient_spinbox->setDecimals(elementProperty->gradient()->decimals());
0075 
0076     switch (elementProperty->gradientId()) {
0077     case KalziumElementProperty::DISCOVERYDATE:
0078         gradient_spinbox->setValue(dblMax);
0079         break;
0080 
0081     case KalziumElementProperty::SOMGradientType:
0082         gradient_spinbox->setValue(dblMin + 293);
0083         break;
0084 
0085     default:
0086         gradient_spinbox->setValue(dblMin);
0087         break;
0088     }
0089 
0090     // Disable Gradient widgets if no gradient is selected.
0091     if (gradient_combo->currentIndex() == KalziumElementProperty::NOGRADIENT) {
0092         gradient_spinbox->setEnabled(false);
0093         gradient_slider->setEnabled(false);
0094         Play->setEnabled(false);
0095         text->clear();
0096     }
0097 }
0098 
0099 void GradientWidgetImpl::doubleToSlider(double doubleVar)
0100 {
0101     // the signals need to be blocked as both will return to this slot. But no
0102     // matter which UI elements (slider oder spinbox) was changed, the other
0103     // has to be set to the same value
0104 
0105     gradient_slider->blockSignals(true);
0106 
0107     // setting the decimals in int
0108     int intvar = doubleVar * MULTIPLIKATOR;
0109 
0110     gradient_slider->setValue(intvar);
0111 
0112     gradient_slider->blockSignals(false);
0113 
0114     Q_EMIT gradientValueChanged(doubleVar);
0115 
0116     setNewValue(doubleVar);
0117 }
0118 
0119 void GradientWidgetImpl::intToSpinbox(int var)
0120 {
0121     gradient_spinbox->blockSignals(true);
0122 
0123     // put int back to double with decimals
0124     double doublevar = var;
0125     doublevar = doublevar / MULTIPLIKATOR;
0126 
0127     gradient_spinbox->setValue(doublevar);
0128 
0129     gradient_spinbox->blockSignals(false);
0130 
0131     Q_EMIT gradientValueChanged(doublevar);
0132 
0133     setNewValue(doublevar);
0134 }
0135 
0136 void GradientWidgetImpl::setNewValue(double newValue)
0137 {
0138     // Info text currently only for State of mater typ available.
0139     if (gradient_combo->currentIndex() != KalziumElementProperty::SOMGradientType) {
0140         text->clear();
0141         return;
0142     }
0143 
0144     static const int threshold = 25;
0145 
0146     const QString unitSymbol = lblUnit->text();
0147 
0148     QStringList listMeltingPoint;
0149     QStringList listBoilingPoint;
0150     QStringList listBoilingPointValue;
0151     QStringList listMeltingPointValue;
0152 
0153     foreach (Element *element, KalziumDataObject::instance()->ElementList) {
0154         double melting = element->dataAsVariant(ChemicalDataObject::meltingpoint, Prefs::temperatureUnit()).toDouble();
0155         if ((melting > 0.0) && fabs(melting - newValue) <= threshold) {
0156             listMeltingPoint << element->dataAsString(ChemicalDataObject::name);
0157             listMeltingPointValue << QString::number(melting);
0158         }
0159 
0160         double boiling = element->dataAsVariant(ChemicalDataObject::boilingpoint, Prefs::temperatureUnit()).toDouble();
0161         if ((boiling > 0.0) && fabs(boiling - newValue) <= threshold) {
0162             listBoilingPoint << element->dataAsString(ChemicalDataObject::name);
0163             listBoilingPointValue << QString::number(boiling);
0164         }
0165     }
0166     QString htmlcode;
0167     if (!listMeltingPoint.isEmpty()) {
0168         htmlcode += i18n("Elements with melting point around this temperature:") + '\n';
0169         for (int i = 0; i < listMeltingPoint.count(); ++i) {
0170             htmlcode += " - " + i18nc("For example: Carbon (300K)", "%1 (%2%3)", listMeltingPoint.at(i), listMeltingPointValue.at(i), unitSymbol) + '\n';
0171         }
0172         htmlcode += '\n';
0173     } else {
0174         htmlcode += i18n("No elements with a melting point around this temperature");
0175         htmlcode += QLatin1String("\n\n");
0176     }
0177     if (!listBoilingPoint.isEmpty()) {
0178         htmlcode += i18n("Elements with boiling point around this temperature:") + '\n';
0179         for (int i = 0; i < listBoilingPoint.count(); ++i) {
0180             htmlcode += " - " + i18nc("For example: Carbon (300K)", "%1 (%2%3)", listBoilingPoint.at(i), listBoilingPointValue.at(i), unitSymbol) + '\n';
0181         }
0182         htmlcode += '\n';
0183     } else {
0184         htmlcode += i18n("No elements with a boiling point around this temperature");
0185         htmlcode += '\n';
0186     }
0187 
0188     text->setText(/*m_htmlBegin +*/ htmlcode /*+ m_htmlEnd*/);
0189 }
0190 
0191 void GradientWidgetImpl::play()
0192 {
0193     if (m_play) { // Currently playing
0194         // The Mode is 'Play' so stop
0195         stop();
0196         return;
0197     }
0198 
0199     // The mode is not 'play'
0200     // If the slider is at the maximum position bring it to the minimum
0201     if ((gradient_slider)->value() >= gradient_slider->maximum()) {
0202         gradient_slider->setValue(gradient_slider->minimum());
0203     }
0204     // start the timer at 200 millisecond time interval with single shot disabled
0205     m_timer->start(200);
0206 
0207     m_play = true; // start playing
0208     Play->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
0209 }
0210 
0211 void GradientWidgetImpl::stop()
0212 {
0213     // Currently playing, stop the timer.
0214     m_timer->stop();
0215     Play->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
0216     m_play = false; // Stop
0217 }
0218 
0219 void GradientWidgetImpl::tick()
0220 {
0221     int increment = Speed->value();
0222     int temp = gradient_slider->value();
0223     int max = gradient_slider->maximum();
0224     if (temp + increment > max) {
0225         stop();
0226     }
0227     gradient_slider->setValue(temp + increment);
0228 }
0229 
0230 #include "moc_gradientwidget_impl.cpp"