Kstars

moonphasecalendarwidget.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Akarsh Simha <akarshsimha@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "moonphasecalendarwidget.h"
8
9#include "ksnumbers.h"
10#include "kstarsdatetime.h"
11#include "ksutils.h"
12#include "texturemanager.h"
13#include "skyobjects/ksmoon.h"
14#include "skyobjects/ksplanet.h"
15#include "skyobjects/kssun.h"
16
17#include <kcalendarsystem.h>
18#include <kcolorscheme.h>
19#include <kglobal.h>
20#include <kglobalsettings.h>
21#include <KLocale>
22
23#include <QActionEvent>
24#include <QDebug>
25#include <QFontDatabase>
26#include <QPainter>
27#include <QStyle>
28#include <QtGui/QStyleOptionViewItem>
29
30#include <cmath>
31
32MoonPhaseCalendar::MoonPhaseCalendar(KSMoon &moon, KSSun &sun, QWidget *parent)
33 : KDateTable(parent), m_Moon(moon), m_Sun(sun)
34{
35 // Populate moon images from disk into the hash
36 numDayColumns = calendar()->daysInWeek(QDate::currentDate());
37 numWeekRows = 7;
38 imagesLoaded = false;
39 // TODO: Set geometry.
40}
41
42MoonPhaseCalendar::~MoonPhaseCalendar()
43{
44}
45
46QSize MoonPhaseCalendar::sizeHint() const
47{
48 const int suggestedMoonImageSize = 50;
49 return QSize(qRound((suggestedMoonImageSize + 2) * numDayColumns),
50 (qRound(suggestedMoonImageSize + 4 + 12) * numWeekRows)); // FIXME: Using hard-coded fontsize
51}
52
53void MoonPhaseCalendar::loadImages()
54{
55 computeMoonImageSize();
56 qDebug() << "Loading moon images. MoonImageSize = " << MoonImageSize;
57 for (int i = 0; i < 36; ++i)
58 {
59 QString imName = QString().sprintf("moon%02d", i);
60 m_Images[i] = QPixmap::fromImage(TextureManager::getImage(imName))
61 .scaled(MoonImageSize, MoonImageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
62 }
63 imagesLoaded = true;
64}
65
66void MoonPhaseCalendar::computeMoonImageSize()
67{
68 cellWidth = width() / (double)numDayColumns;
69 cellHeight = height() / (double)numWeekRows;
70 qDebug() << cellWidth << cellHeight;
71 MoonImageSize =
72 ((cellWidth > cellHeight - 12) ? cellHeight - 12 : cellWidth) - 2; // FIXME: Using hard-coded fontsize
73}
74
75void MoonPhaseCalendar::setGeometry(int, int, int, int)
76{
77 imagesLoaded = false;
78}
79
80void MoonPhaseCalendar::setGeometry(const QRect &r)
81{
82 setGeometry(r.x(), r.y(), r.width(), r.height()); // FIXME: +1 / -1 pixel compensation. Not required at the moment.
83}
84
85void MoonPhaseCalendar::paintEvent(QPaintEvent *e)
86{
87 QPainter p(this);
88 if (!imagesLoaded)
89 loadImages();
90 KColorScheme colorScheme(palette().currentColorGroup(), KColorScheme::View);
91 const QRect &rectToUpdate = e->rect();
92 int leftCol = (int)std::floor(rectToUpdate.left() / cellWidth);
93 int topRow = (int)std::floor(rectToUpdate.top() / cellHeight);
94 int rightCol = (int)std::ceil(rectToUpdate.right() / cellWidth);
95 int bottomRow = (int)std::ceil(rectToUpdate.bottom() / cellHeight);
96 bottomRow = qMin(bottomRow, numWeekRows - 1);
97 rightCol = qMin(rightCol, numDayColumns - 1);
98 p.translate(leftCol * cellWidth, topRow * cellHeight);
99 for (int i = leftCol; i <= rightCol; ++i)
100 {
101 for (int j = topRow; j <= bottomRow; ++j)
102 {
103 this->paintCell(&p, j, i, colorScheme);
104 p.translate(0, cellHeight);
105 }
106 p.translate(cellWidth, 0);
107 p.translate(0, -cellHeight * (bottomRow - topRow + 1));
108 }
109 p.end();
110}
111
112void MoonPhaseCalendar::paintCell(QPainter *painter, int row, int col, const KColorScheme &colorScheme)
113{
114 double w = cellWidth - 1;
115 double h = cellHeight - 1;
116 QRectF cell = QRectF(0, 0, w, h);
117 QString cellText;
118 QPen pen;
119 QColor cellBackgroundColor, cellTextColor;
121 bool workingDay = false;
122 int cellWeekDay, pos;
123
124 //Calculate the position of the cell in the grid
125 pos = numDayColumns * (row - 1) + col;
126
127 //Calculate what day of the week the cell is
128 cellWeekDay = col + calendar()->weekStartDay();
129 if (cellWeekDay > numDayColumns)
130 {
131 cellWeekDay -= numDayColumns;
132 }
133
134 //See if cell day is normally a working day
135 if (KLocale::global()->workingWeekStartDay() <= KLocale::global()->workingWeekEndDay())
136 {
137 workingDay = cellWeekDay >= KLocale::global()->workingWeekStartDay() &&
138 cellWeekDay <= KLocale::global()->workingWeekEndDay();
139 }
140 else
141 {
142 workingDay = cellWeekDay >= KLocale::global()->workingWeekStartDay() ||
143 cellWeekDay <= KLocale::global()->workingWeekEndDay();
144 }
145
146 if (row == 0)
147 {
148 //We are drawing a header cell
149
150 //If not a normal working day, then use "do not work today" color
151 if (workingDay)
152 {
153 cellTextColor = palette().color(QPalette::WindowText);
154 }
155 else
156 {
157 KColorScheme colorScheme(palette().currentColorGroup(), KColorScheme::Window);
158 cellTextColor = colorScheme.foreground(KColorScheme::NegativeText).color();
159 }
160 cellBackgroundColor = palette().color(QPalette::Window);
161
162 //Set the text to the short day name and bold it
163 cellFont.setBold(true);
164 cellText = calendar()->weekDayName(cellWeekDay, KCalendarSystem::ShortDayName);
165 }
166 else
167 {
168 //We are drawing a day cell
169
170 //Calculate the date the cell represents
171 QDate cellDate = dateFromPos(pos);
172
173 bool validDay = calendar()->isValid(cellDate);
174
175 // Draw the day number in the cell, if the date is not valid then we don't want to show it
176 if (validDay)
177 {
178 cellText = calendar()->dayString(cellDate, KCalendarSystem::ShortFormat);
179 }
180 else
181 {
182 cellText = "";
183 }
184
185 if (!validDay || calendar()->month(cellDate) != calendar()->month(date()))
186 {
187 // we are either
188 // ° painting an invalid day
189 // ° painting a day of the previous month or
190 // ° painting a day of the following month or
191 cellBackgroundColor = palette().color(backgroundRole());
192 cellTextColor = colorScheme.foreground(KColorScheme::InactiveText).color();
193 }
194 else
195 {
196 //Paint a day of the current month
197
198 // Background Colour priorities will be (high-to-low):
199 // * Selected Day Background Colour
200 // * Customized Day Background Colour
201 // * Normal Day Background Colour
202
203 // Background Shape priorities will be (high-to-low):
204 // * Customized Day Shape
205 // * Normal Day Shape
206
207 // Text Colour priorities will be (high-to-low):
208 // * Customized Day Colour
209 // * Day of Pray Colour (Red letter)
210 // * Selected Day Colour
211 // * Normal Day Colour
212
213 //Determine various characteristics of the cell date
214 bool selectedDay = (cellDate == date());
215 bool currentDay = (cellDate == QDate::currentDate());
216 bool dayOfPray = (calendar()->dayOfWeek(cellDate) == KLocale::global()->weekDayOfPray());
217
218 //Default values for a normal cell
219 cellBackgroundColor = palette().color(backgroundRole());
220 cellTextColor = palette().color(foregroundRole());
221
222 // If we are drawing the current date, then draw it bold and active
223 if (currentDay)
224 {
225 cellFont.setBold(true);
226 cellTextColor = colorScheme.foreground(KColorScheme::ActiveText).color();
227 }
228
229 // if we are drawing the day cell currently selected in the table
230 if (selectedDay)
231 {
232 // set the background to highlighted
233 cellBackgroundColor = palette().color(QPalette::Highlight);
234 cellTextColor = palette().color(QPalette::HighlightedText);
235 }
236
237 //If the cell day is the day of religious observance, then always color text red unless Custom overrides
238 if (dayOfPray)
239 {
240 KColorScheme colorScheme(palette().currentColorGroup(),
241 selectedDay ? KColorScheme::Selection : KColorScheme::View);
242 cellTextColor = colorScheme.foreground(KColorScheme::NegativeText).color();
243 }
244 }
245 }
246
247 //Draw the background
248 if (row == 0)
249 {
250 painter->setPen(cellBackgroundColor);
251 painter->setBrush(cellBackgroundColor);
252 painter->drawRect(cell);
253 }
254 else if (cellBackgroundColor != palette().color(backgroundRole()))
255 {
256 QStyleOptionViewItemV4 opt;
257 opt.initFrom(this);
258 opt.rect = cell.toRect();
259 if (cellBackgroundColor != palette().color(backgroundRole()))
260 {
261 opt.palette.setBrush(QPalette::Highlight, cellBackgroundColor);
262 opt.state |= QStyle::State_Selected;
263 }
264 if (false && opt.state & QStyle::State_Enabled)
265 {
266 opt.state |= QStyle::State_MouseOver;
267 }
268 else
269 {
270 opt.state &= ~QStyle::State_MouseOver;
271 }
272 opt.showDecorationSelected = true;
273 opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
274 style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, this);
275 }
276
277 if (row != 0)
278 {
279 // Paint the moon phase
280 QDate cellDate = dateFromPos(pos);
281 if (calendar()->isValid(cellDate))
282 {
283 int iPhase = computeMoonPhase(KStarsDateTime(cellDate, QTime(0, 0, 0)));
284 QRect drawRect = cell.toRect();
285 painter->drawPixmap((drawRect.width() - MoonImageSize) / 2,
286 12 + ((drawRect.height() - 12) - MoonImageSize) / 2,
287 m_Images[iPhase]); // FIXME: Using hard coded fon
288 // + painter
289 // painter->drawPixmap( ( drawRect.width() - MoonImageSize )/2,
290 // 12 + (( drawRect.height() - 12 ) - MoonImageSize)/2,
291 // m_Images[ iPhase ] );
292 // FIXME: Using hard coded fontsize
293 // qDebug() << "Drew moon image " << iPhase;
294 }
295 }
296
297 //Draw the text
298 painter->setPen(cellTextColor);
299 painter->setFont(cellFont);
300 painter->drawText(cell, (row == 0) ? Qt::AlignCenter : (Qt::AlignTop | Qt::AlignHCenter), cellText, &cell);
301
302 //Draw the base line
303 if (row == 0)
304 {
305 painter->setPen(palette().color(foregroundRole()));
306 painter->drawLine(QPointF(0, h), QPointF(w, h));
307 }
308
309 // If the day cell we just drew is bigger than the current max cell sizes,
310 // then adjust the max to the current cell
311
312 /*
313 if ( cell.width() > d->maxCell.width() ) d->maxCell.setWidth( cell.width() );
314 if ( cell.height() > d->maxCell.height() ) d->maxCell.setHeight( cell.height() );
315 */
316}
317
318unsigned short MoonPhaseCalendar::computeMoonPhase(const KStarsDateTime &date)
319{
320 KSNumbers num(date.djd());
321 KSPlanet earth(i18n("Earth"), QString(), QColor("white"), 12756.28 /*diameter in km*/);
322 earth.findPosition(&num);
323
324 m_Sun.findPosition(
325 &num, 0, 0,
326 &earth); // Find position is overkill for this purpose. Wonder if it is worth making findGeocentricPosition public instead of protected.
327 m_Moon.findGeocentricPosition(&num, &earth);
328
329 m_Moon.findPhase(&m_Sun);
330
331 return m_Moon.getIPhase();
332}
QBrush foreground(ForegroundRole=NormalText) const
Provides necessary information about the Moon.
Definition ksmoon.h:26
bool findGeocentricPosition(const KSNumbers *num, const KSPlanetBase *) override
Reimplemented from KSPlanetBase, this function employs unique algorithms for estimating the lunar coo...
Definition ksmoon.cpp:153
short int getIPhase() const
Definition ksmoon.h:58
void findPhase(const KSSun *Sun=nullptr)
Determine the phase angle of the moon, and assign the appropriate moon image.
Definition ksmoon.cpp:268
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition ksnumbers.h:43
void findPosition(const KSNumbers *num, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, const KSPlanetBase *Earth=nullptr)
Find position, including correction for Figure-of-the-Earth.
A subclass of KSPlanetBase for seven of the major planets in the solar system (Earth and Pluto have t...
Definition ksplanet.h:33
Child class of KSPlanetBase; encapsulates information about the Sun.
Definition kssun.h:24
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
long double djd() const
static const QImage & getImage(const QString &name)
Return texture image.
QString i18n(const char *text, const TYPE &arg...)
bool isValid(QStringView ifopt)
const QColor & color() const const
QDate currentDate()
void setBold(bool enable)
QFont systemFont(SystemFont type)
void drawLine(const QLine &line)
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void drawRect(const QRect &rectangle)
void drawText(const QPoint &position, const QString &text)
void setBrush(Qt::BrushStyle style)
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
const QRect & rect() const const
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
QPixmap scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
int bottom() const const
int height() const const
int left() const const
int right() const const
int top() const const
int width() const const
int x() const const
int y() const const
QRect toRect() const const
PE_PanelItemViewItem
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
AlignCenter
KeepAspectRatio
SmoothTransformation
QPalette::ColorRole backgroundRole() const const
QPalette::ColorRole foregroundRole() const const
QStyle * style() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:59:53 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.