File indexing completed on 2022-11-29 18:11:58

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