File indexing completed on 2024-07-07 07:09:17

0001 /*
0002     SPDX-FileCopyrightText: 2002 Jason Harris <kstars@30doradus.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "timespinbox.h"
0008 
0009 #include "kstars_debug.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 #include <QDebug>
0014 #include <QLineEdit>
0015 
0016 #include <cmath>
0017 
0018 #define SECS_PER_DAY  86400.
0019 #define SIDEREAL_YEAR 31558149.77
0020 
0021 //Time steps:
0022 //0-9:   0 sec, 0.1, 0.25, 0.5, 1, 2, 5, 10, 20, 30 sec
0023 //10-14: 1 minute, 2, 5, 10, 15, 30 min
0024 //15-19: 1 hour, 2, 4, 6, 12 hours
0025 //20-23: 1 day, 2, 3, 5 days
0026 //24-26: 1 week, 2, 3 weeks
0027 //27-32: 1 month, 2, 3, 4, 6, 9 months
0028 //33-41: 1 year, 2, 3, 4, 5, 10, 25, 50, 100 years
0029 
0030 TimeSpinBox::TimeSpinBox(QWidget *parent, bool _daysonly) : QSpinBox(parent)
0031 {
0032     setDaysOnly(_daysonly);
0033 
0034     setMinimum(-41);
0035     setMaximum(41);
0036     setSingleStep(1);
0037 
0038     setButtonSymbols(QSpinBox::PlusMinus);
0039     lineEdit()->setReadOnly(true);
0040     setValue(4); //1 second (real time)
0041 
0042     //Set width:
0043     QFontMetrics fm(font());
0044     int extra = width() - lineEdit()->width();
0045     uint wmax = 0;
0046     for (int i = 0; i < maximum(); ++i)
0047     {
0048         uint w = fm.horizontalAdvance('-' + TimeString[i]);
0049 
0050         if (w > wmax)
0051             wmax = w;
0052     }
0053     setFixedWidth(wmax + extra);
0054 
0055     connect(this, SIGNAL(valueChanged(int)), this, SLOT(reportChange()));
0056     //  updateDisplay();
0057 }
0058 
0059 void TimeSpinBox::setDaysOnly(bool daysonly)
0060 {
0061     DaysOnly = daysonly;
0062 
0063     int i        = 0;   //index for TimeScale values
0064     TimeScale[0] = 0.0; // 0.0 sec
0065     if (!daysOnly())
0066     {
0067         TimeScale[1]  = 0.1;     // 0.1 sec
0068         TimeScale[2]  = 0.25;    // 0.25 sec
0069         TimeScale[3]  = 0.5;     // 0.5 sec
0070         TimeScale[4]  = 1.0;     // 1 sec (real-time)
0071         TimeScale[5]  = 2.0;     // 2 sec
0072         TimeScale[6]  = 5.0;     // 5 sec
0073         TimeScale[7]  = 10.0;    // 10 sec
0074         TimeScale[8]  = 20.0;    // 20 sec
0075         TimeScale[9]  = 30.0;    // 30 sec
0076         TimeScale[10] = 60.0;    // 1 min
0077         TimeScale[11] = 120.0;   // 2 min
0078         TimeScale[12] = 300.0;   // 5 min
0079         TimeScale[13] = 600.0;   // 10 min
0080         TimeScale[14] = 900.0;   // 15 min
0081         TimeScale[15] = 1800.0;  // 30 min
0082         TimeScale[16] = 3600.0;  // 1 hr
0083         TimeScale[17] = 7200.0;  // 2 hr
0084         TimeScale[18] = 10800.0; // 3 hr
0085         TimeScale[19] = 21600.0; // 6 hr
0086         TimeScale[20] = 43200.0; // 12 hr
0087         i             = 20;
0088     }
0089     TimeScale[i + 1] = 86164.1;            // 23 hr 56 min
0090     TimeScale[i + 2] = SECS_PER_DAY;       // 1 day
0091     TimeScale[i + 3] = 2. * SECS_PER_DAY;  // 2 days
0092     TimeScale[i + 4] = 3. * SECS_PER_DAY;  // 3 days
0093     TimeScale[i + 5] = 5. * SECS_PER_DAY;  // 5 days
0094     TimeScale[i + 6] = 7. * SECS_PER_DAY;  // 1 week
0095     TimeScale[i + 7] = 14. * SECS_PER_DAY; //2 weeks
0096     TimeScale[i + 8] = 21. * SECS_PER_DAY; //3 weeks
0097     //Months aren't a simple measurement of time; I'll just use fractions of a year
0098     TimeScale[i + 9]  = SIDEREAL_YEAR / 12.0;  // 1 month
0099     TimeScale[i + 10] = SIDEREAL_YEAR / 6.0;   // 2 months
0100     TimeScale[i + 11] = 0.25 * SIDEREAL_YEAR;  // 3 months
0101     TimeScale[i + 12] = SIDEREAL_YEAR / 3.0;   // 4 months
0102     TimeScale[i + 13] = 0.5 * SIDEREAL_YEAR;   // 6 months
0103     TimeScale[i + 14] = 0.75 * SIDEREAL_YEAR;  // 9 months
0104     TimeScale[i + 15] = SIDEREAL_YEAR;         // 1 year
0105     TimeScale[i + 16] = 2.0 * SIDEREAL_YEAR;   // 2 years
0106     TimeScale[i + 17] = 3.0 * SIDEREAL_YEAR;   // 3 years
0107     TimeScale[i + 18] = 5.0 * SIDEREAL_YEAR;   // 5 years
0108     TimeScale[i + 19] = 10.0 * SIDEREAL_YEAR;  // 10 years
0109     TimeScale[i + 20] = 25.0 * SIDEREAL_YEAR;  // 25 years
0110     TimeScale[i + 21] = 50.0 * SIDEREAL_YEAR;  // 50 years
0111     TimeScale[i + 22] = 100.0 * SIDEREAL_YEAR; // 100 years
0112 
0113     TimeString.clear();
0114     if (!daysOnly())
0115     {
0116         TimeString.append("0 " + i18nc("seconds", "secs"));
0117         TimeString.append("0.1 " + i18nc("seconds", "secs"));
0118         TimeString.append("0.25 " + i18nc("seconds", "secs"));
0119         TimeString.append("0.5 " + i18nc("seconds", "secs"));
0120         TimeString.append("1 " + i18nc("second", "sec"));
0121         TimeString.append("2 " + i18nc("seconds", "secs"));
0122         TimeString.append("5 " + i18nc("seconds", "secs"));
0123         TimeString.append("10 " + i18nc("seconds", "secs"));
0124         TimeString.append("20 " + i18nc("seconds", "secs"));
0125         TimeString.append("30 " + i18nc("seconds", "secs"));
0126         TimeString.append("1 " + i18nc("minute", "min"));
0127         TimeString.append("2 " + i18nc("minutes", "mins"));
0128         TimeString.append("5 " + i18nc("minutes", "mins"));
0129         TimeString.append("10 " + i18nc("minutes", "mins"));
0130         TimeString.append("15 " + i18nc("minutes", "mins"));
0131         TimeString.append("30 " + i18nc("minutes", "mins"));
0132         TimeString.append("1 " + i18n("hour"));
0133         TimeString.append("2 " + i18nc("hours", "hrs"));
0134         TimeString.append("3 " + i18nc("hours", "hrs"));
0135         TimeString.append("6 " + i18nc("hours", "hrs"));
0136         TimeString.append("12 " + i18nc("hours", "hrs"));
0137     }
0138     else
0139     {
0140         TimeString.append("0 " + i18n("days"));
0141     }
0142     TimeString.append("1 " + i18nc("sidereal day", "sid day"));
0143     TimeString.append("1 " + i18n("day"));
0144     TimeString.append("2 " + i18n("days"));
0145     TimeString.append("3 " + i18n("days"));
0146     TimeString.append("5 " + i18n("days"));
0147     TimeString.append("1 " + i18n("week"));
0148     TimeString.append("2 " + i18nc("weeks", "wks"));
0149     TimeString.append("3 " + i18nc("weeks", "wks"));
0150     TimeString.append("1 " + i18n("month"));
0151     TimeString.append("2 " + i18nc("months", "mths"));
0152     TimeString.append("3 " + i18nc("months", "mths"));
0153     TimeString.append("4 " + i18nc("months", "mths"));
0154     TimeString.append("6 " + i18nc("months", "mths"));
0155     TimeString.append("9 " + i18nc("months", "mths"));
0156     TimeString.append("1 " + i18n("year"));
0157     TimeString.append("2 " + i18nc("years", "yrs"));
0158     TimeString.append("3 " + i18nc("years", "yrs"));
0159     TimeString.append("5 " + i18nc("years", "yrs"));
0160     TimeString.append("10 " + i18nc("years", "yrs"));
0161     TimeString.append("25 " + i18nc("years", "yrs"));
0162     TimeString.append("50 " + i18nc("years", "yrs"));
0163     TimeString.append("100 " + i18nc("years", "yrs"));
0164 
0165     if (!daysOnly())
0166     {
0167         setMinimum(-41);
0168         setMaximum(41);
0169     }
0170     else
0171     {
0172         setMinimum(-21);
0173         setMaximum(21);
0174     }
0175 }
0176 
0177 int TimeSpinBox::valueFromText(const QString &text) const
0178 {
0179     for (int i = 0; i < TimeString.size(); i++)
0180     {
0181         if (text == TimeString[i])
0182         {
0183             return i;
0184         }
0185         if (text.mid(1, text.length()) == TimeString[i])
0186         {
0187             return -1 * i;
0188         }
0189     }
0190 
0191     return 0;
0192 }
0193 
0194 QString TimeSpinBox::textFromValue(int value) const
0195 {
0196     QString result;
0197     int posval(abs(value));
0198 
0199     if (posval > TimeString.size() - 1)
0200         posval = 4;
0201 
0202     result = TimeString[posval];
0203 
0204     if (value < 0)
0205     {
0206         result = '-' + result;
0207     }
0208     return result;
0209 }
0210 
0211 void TimeSpinBox::changeScale(float x)
0212 {
0213     //Pick the closest value
0214     int imin = 0;
0215     float dxlast(10000000000.0), dxmin(10000000000.0);
0216 
0217     for (unsigned int i = 0; i < 42; ++i)
0218     {
0219         float dx = fabs(TimeScale[i] - fabs(x));
0220 
0221         if (dx < dxmin)
0222         {
0223             imin  = i;
0224             dxmin = dx;
0225         }
0226         if (dx > dxlast)
0227             break; //we have passed the minimum dx
0228 
0229         dxlast = dx;
0230     }
0231 
0232     if (x < 0.0)
0233         imin *= -1;
0234     setValue(imin);
0235 }
0236 
0237 float TimeSpinBox::timeScale(void) const
0238 {
0239     return value() > 0 ? TimeScale[value()] : -1. * TimeScale[abs(value())];
0240 }
0241 
0242 void TimeSpinBox::reportChange()
0243 {
0244     qCDebug(KSTARS) << "Reporting new timestep value: " << timeScale();
0245     emit scaleChanged(timeScale());
0246 }