File indexing completed on 2024-04-21 03:44:58

0001 /*
0002     SPDX-FileCopyrightText: 2009 Khudyakov Alexey <alexey.skladnoy@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "infoboxwidget.h"
0008 
0009 #include "colorscheme.h"
0010 #include "kstarsdata.h"
0011 #include "ksutils.h"
0012 
0013 #include <KLocalizedString>
0014 
0015 #include <QPainter>
0016 #include <QMouseEvent>
0017 #include <QFontMetrics>
0018 #include <QLocale>
0019 
0020 const int InfoBoxWidget::padX = 6;
0021 const int InfoBoxWidget::padY = 2;
0022 
0023 InfoBoxes::InfoBoxes(QWidget *parent) : QWidget(parent)
0024 {
0025     setMouseTracking(true);
0026 }
0027 
0028 void InfoBoxes::addInfoBox(InfoBoxWidget *ibox)
0029 {
0030     ibox->setParent(this);
0031     m_boxes.append(ibox);
0032 }
0033 
0034 void InfoBoxes::resizeEvent(QResizeEvent *)
0035 {
0036     foreach (InfoBoxWidget *w, m_boxes)
0037         w->adjust();
0038 }
0039 
0040 /* ================================================================ */
0041 
0042 InfoBoxWidget::InfoBoxWidget(bool shade, const QPoint &pos, int anchor, const QStringList &str, QWidget *parent)
0043     : QWidget(parent), m_strings(str), m_adjusted(false), m_grabbed(false), m_shaded(shade), m_anchor(anchor)
0044 {
0045     move(pos);
0046     updateSize();
0047 }
0048 
0049 void InfoBoxWidget::updateSize()
0050 {
0051     QFontMetrics fm(font());
0052     int w = 0;
0053     foreach (const QString &str, m_strings)
0054     {
0055         w = qMax(w, fm.horizontalAdvance(str));
0056     }
0057 
0058     int h = fm.height() * (m_shaded ? 1 : m_strings.size());
0059     // Add padding
0060     resize(w + 2 * padX, h + 2 * padY + 2);
0061     adjust();
0062 }
0063 
0064 void InfoBoxWidget::slotTimeChanged()
0065 {
0066     KStarsData *data = KStarsData::Instance();
0067 
0068     m_strings.clear();
0069     m_strings
0070             << i18nc("Local Time", "LT: ") + data->lt().time().toString(QLocale().timeFormat().remove('t')) +
0071             "   " + // Remove timezone, as timezone of geolocation in KStars might not be same as system locale timezone
0072             QLocale().toString(data->lt().date());
0073 
0074     m_strings << i18nc("Universal Time", "UT: ") + data->ut().time().toString("HH:mm:ss") + "   " +
0075               QLocale().toString(data->ut().date()); // Do not format UTC according to locale
0076 
0077     const QString STString = QString::asprintf("%02d:%02d:%02d   ", data->lst()->hour(), data->lst()->minute(),
0078                              data->lst()->second());
0079     //Don't use KLocale::formatNumber() for Julian Day because we don't want
0080     //thousands-place separators
0081     QString JDString = QString::number(data->ut().djd(), 'f', 2);
0082     JDString.replace('.', QLocale().decimalPoint());
0083     m_strings << i18nc("Sidereal Time", "ST: ") + STString + i18nc("Julian Day", "JD: ") + JDString;
0084     updateSize();
0085     update();
0086 }
0087 
0088 void InfoBoxWidget::slotGeoChanged()
0089 {
0090     GeoLocation *geo = KStarsData::Instance()->geo();
0091 
0092     m_strings.clear();
0093     m_strings << geo->fullName();
0094 
0095     //m_strings << i18nc("Longitude", "Long:") + ' ' + QLocale().toString(geo->lng()->Degrees(), 3) + "   " +
0096     //                 i18nc("Latitude", "Lat:") + ' ' + QLocale().toString(geo->lat()->Degrees(), 3);
0097 
0098     m_strings << i18nc("Longitude", "Long:") + ' ' + geo->lng()->toDMSString(true) + ' ' +
0099               i18nc("Latitude", "Lat:") + ' ' + geo->lat()->toDMSString(true);
0100     updateSize();
0101     update();
0102 }
0103 
0104 void InfoBoxWidget::slotObjectChanged(SkyObject *obj)
0105 {
0106     setPoint(obj->translatedLongName(), obj);
0107 }
0108 
0109 void InfoBoxWidget::slotPointChanged(SkyPoint *p)
0110 {
0111     setPoint(i18n("nothing"), p);
0112 }
0113 
0114 void InfoBoxWidget::setPoint(QString name, SkyPoint *p)
0115 {
0116     m_strings.clear();
0117     m_strings << name;
0118     m_strings << i18nc("Right Ascension", "RA") + ": " + p->ra().toHMSString() + "  " + i18nc("Declination", "Dec") +
0119               ": " + p->dec().toDMSString(true);
0120     m_strings << i18nc("Azimuth", "Az") + ": " + p->az().toDMSString(true) + "  " + i18nc("Altitude", "Alt") + ": " +
0121               p->alt().toDMSString(true);
0122 
0123     dms lst = KStarsData::Instance()->geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst());
0124     dms ha(lst - p->ra());
0125     QChar sign('+');
0126     if (ha.Hours() > 12.0)
0127     {
0128         ha.setH(24.0 - ha.Hours());
0129         sign = '-';
0130     }
0131     m_strings << i18nc("Hour Angle", "HA") + ": " + sign + ha.toHMSString() + "  " + i18nc("Zenith Angle", "ZA") + ": " +
0132               dms(90 - p->alt().Degrees()).toDMSString(true);
0133     updateSize();
0134     update();
0135 }
0136 
0137 void InfoBoxWidget::adjust()
0138 {
0139     if (!isVisible())
0140         return;
0141     // X axis
0142     int newX = x();
0143     int maxX = parentWidget()->width() - width();
0144     if (m_anchor & AnchorRight)
0145     {
0146         newX = maxX;
0147     }
0148     else
0149     {
0150         newX = KSUtils::clamp(newX, 0, maxX);
0151         if (newX == maxX)
0152             m_anchor |= AnchorRight;
0153     }
0154     // Y axis
0155     int newY = y();
0156     int maxY = parentWidget()->height() - height();
0157     if (m_anchor & AnchorBottom)
0158     {
0159         newY = maxY;
0160     }
0161     else
0162     {
0163         newY = KSUtils::clamp(newY, 0, maxY);
0164         if (newY == maxY)
0165             m_anchor |= AnchorBottom;
0166     }
0167     // Do move
0168     m_adjusted = true;
0169     move(newX, newY);
0170 }
0171 
0172 void InfoBoxWidget::paintEvent(QPaintEvent *)
0173 {
0174     // If widget contain no strings return
0175     if (m_strings.empty())
0176         return;
0177     // Start with painting
0178     ColorScheme *cs = KStarsData::Instance()->colorScheme();
0179     QPainter p;
0180     p.begin(this);
0181 
0182     // Draw background
0183     QColor colBG = cs->colorNamed("BoxBGColor");
0184     colBG.setAlpha(127);
0185     p.fillRect(contentsRect(), colBG);
0186     // Draw border
0187     if (m_grabbed)
0188     {
0189         p.setPen(cs->colorNamed("BoxGrabColor"));
0190         p.drawRect(0, 0, width() - 1, height() - 1);
0191     }
0192     // Draw text
0193     int h = QFontMetrics(font()).height();
0194     int y = 0;
0195     p.setPen(cs->colorNamed("BoxTextColor"));
0196     foreach (const QString &str, m_strings)
0197     {
0198         y += h;
0199         p.drawText(padX, padY + y, str);
0200     }
0201     // Done
0202     p.end();
0203 }
0204 
0205 void InfoBoxWidget::mouseMoveEvent(QMouseEvent *event)
0206 {
0207     m_grabbed = true;
0208     // X axis
0209     int newX = x() + event->x();
0210     int maxX = parentWidget()->width() - width();
0211     if (newX > maxX)
0212     {
0213         newX = maxX;
0214         m_anchor |= AnchorRight;
0215     }
0216     else
0217     {
0218         if (newX < 0)
0219             newX = 0;
0220         m_anchor &= ~AnchorRight;
0221     }
0222     // Y axis
0223     int newY = y() + event->y();
0224     int maxY = parentWidget()->height() - height();
0225     if (newY > maxY)
0226     {
0227         newY = maxY;
0228         m_anchor |= AnchorBottom;
0229     }
0230     else
0231     {
0232         if (newY < 0)
0233             newY = 0;
0234         m_anchor &= ~AnchorBottom;
0235     }
0236     // Do move
0237     m_adjusted = true;
0238     move(newX, newY);
0239 }
0240 
0241 void InfoBoxWidget::mousePressEvent(QMouseEvent *)
0242 {
0243     emit clicked();
0244 }
0245 
0246 void InfoBoxWidget::showEvent(QShowEvent *)
0247 {
0248     if (!m_adjusted)
0249         adjust();
0250 }
0251 
0252 void InfoBoxWidget::mouseDoubleClickEvent(QMouseEvent *)
0253 {
0254     m_shaded = !m_shaded;
0255     updateSize();
0256     update();
0257 }
0258 
0259 void InfoBoxWidget::mouseReleaseEvent(QMouseEvent *)
0260 {
0261     m_grabbed = false;
0262 }