1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2008 Torsten Rahn <tackat@kde.org>
4 // SPDX-FileCopyrightText: 2011-2013 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
5 //
6
7 #include "StarsPlugin.h"
8
9 #include "ui_StarsConfigWidget.h"
10 #include <QRectF>
11 #include <QSize>
12 #include <QDateTime>
13 #include <QRegion>
14 #include <QContextMenuEvent>
15 #include <QMenu>
16 #include <QColorDialog>
17 #include <QPainterPath>
18 #include <qmath.h>
19
20 #include "MarbleClock.h"
21 #include "MarbleColors.h"
22 #include "MarbleDebug.h"
23 #include "MarbleDirs.h"
24 #include "MarbleModel.h"
25 #include "MarbleWidget.h"
26 #include "AbstractFloatItem.h"
27 #include "GeoPainter.h"
28 #include "Planet.h"
29 #include "PlanetFactory.h"
30 #include "SunLocator.h"
31 #include "ViewportParams.h"
32
33 #include "src/lib/astro/solarsystem.h"
34
35 namespace Marble
36 {
37
StarsPlugin(const MarbleModel * marbleModel)38 StarsPlugin::StarsPlugin( const MarbleModel *marbleModel )
39 : RenderPlugin( marbleModel ),
40 m_nameIndex( 0 ),
41 m_configDialog( nullptr ),
42 ui_configWidget( nullptr ),
43 m_renderStars( true ),
44 m_renderConstellationLines( true ),
45 m_renderConstellationLabels( true ),
46 m_renderDsos( true ),
47 m_renderDsoLabels( true ),
48 m_renderSun( true ),
49 m_renderMoon( true ),
50 m_renderEcliptic( true ),
51 m_renderCelestialEquator( true ),
52 m_renderCelestialPole( true ),
53 m_starsLoaded( false ),
54 m_starPixmapsCreated( false ),
55 m_constellationsLoaded( false ),
56 m_dsosLoaded( false ),
57 m_zoomSunMoon( true ),
58 m_viewSolarSystemLabel( true ),
59 m_magnitudeLimit( 100 ),
60 m_zoomCoefficient( 4 ),
61 m_constellationBrush( Marble::Oxygen::aluminumGray5 ),
62 m_constellationLabelBrush( Marble::Oxygen::aluminumGray5 ),
63 m_dsoLabelBrush( Marble::Oxygen::aluminumGray5 ),
64 m_eclipticBrush( Marble::Oxygen::aluminumGray5 ),
65 m_celestialEquatorBrush( Marble::Oxygen::aluminumGray5 ),
66 m_celestialPoleBrush( Marble::Oxygen::aluminumGray5 ),
67 m_contextMenu(nullptr),
68 m_constellationsAction(nullptr),
69 m_sunMoonAction(nullptr),
70 m_planetsAction(nullptr),
71 m_dsoAction(nullptr),
72 m_doRender( false )
73 {
74 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
75 if (smallScreen) m_magnitudeLimit = 5;
76
77 prepareNames();
78 }
79
~StarsPlugin()80 StarsPlugin::~StarsPlugin()
81 {
82 delete m_contextMenu;
83 }
84
backendTypes() const85 QStringList StarsPlugin::backendTypes() const
86 {
87 return QStringList(QStringLiteral("stars"));
88 }
89
renderPolicy() const90 QString StarsPlugin::renderPolicy() const
91 {
92 return QStringLiteral("SPECIFIED_ALWAYS");
93 }
94
renderPosition() const95 QStringList StarsPlugin::renderPosition() const
96 {
97 return QStringList(QStringLiteral("STARS"));
98 }
99
renderType() const100 RenderPlugin::RenderType StarsPlugin::renderType() const
101 {
102 return RenderPlugin::ThemeRenderType;
103 }
104
name() const105 QString StarsPlugin::name() const
106 {
107 return tr( "Stars" );
108 }
109
guiString() const110 QString StarsPlugin::guiString() const
111 {
112 return tr( "&Stars" );
113 }
114
nameId() const115 QString StarsPlugin::nameId() const
116 {
117 return QStringLiteral("stars");
118 }
119
version() const120 QString StarsPlugin::version() const
121 {
122 return QStringLiteral("1.2");
123 }
124
description() const125 QString StarsPlugin::description() const
126 {
127 return tr( "A plugin that shows the Starry Sky and the Sun." );
128 }
129
copyrightYears() const130 QString StarsPlugin::copyrightYears() const
131 {
132 return QStringLiteral("2008-2012");
133 }
134
pluginAuthors() const135 QVector<PluginAuthor> StarsPlugin::pluginAuthors() const
136 {
137 return QVector<PluginAuthor>()
138 << PluginAuthor(QStringLiteral("Torsten Rahn"), QStringLiteral("tackat@kde.org"))
139 << PluginAuthor(QStringLiteral("Rene Kuettner"), QStringLiteral("rene@bitkanal.net"))
140 << PluginAuthor(QStringLiteral("Timothy Lanzi"), QStringLiteral("trlanzi@gmail.com"));
141 }
142
icon() const143 QIcon StarsPlugin::icon() const
144 {
145 return QIcon(QStringLiteral(":/icons/stars.png"));
146 }
147
initialize()148 void StarsPlugin::initialize()
149 {
150 }
151
isInitialized() const152 bool StarsPlugin::isInitialized() const
153 {
154 return true;
155 }
156
configDialog()157 QDialog *StarsPlugin::configDialog()
158 {
159 if (!m_configDialog) {
160 // Initializing configuration dialog
161 m_configDialog = new QDialog;
162 ui_configWidget = new Ui::StarsConfigWidget;
163 ui_configWidget->setupUi( m_configDialog );
164
165 readSettings();
166
167 connect( ui_configWidget->m_buttonBox, SIGNAL(accepted()), SLOT(writeSettings()) );
168 connect( ui_configWidget->m_buttonBox, SIGNAL(rejected()), SLOT(readSettings()) );
169
170 connect( ui_configWidget->m_constellationColorButton, SIGNAL(clicked()), this,
171 SLOT(constellationGetColor()) );
172
173 connect( ui_configWidget->m_constellationLabelColorButton, SIGNAL(clicked()), this,
174 SLOT(constellationLabelGetColor()) );
175
176 connect( ui_configWidget->m_dsoLabelColorButton, SIGNAL(clicked()), this,
177 SLOT(dsoLabelGetColor()) );
178
179 connect( ui_configWidget->m_eclipticColorButton, SIGNAL(clicked()), this,
180 SLOT(eclipticGetColor()) );
181
182 connect( ui_configWidget->m_celestialEquatorColorButton, SIGNAL(clicked()), this,
183 SLOT(celestialEquatorGetColor()) );
184
185 connect( ui_configWidget->m_celestialPoleColorButton, SIGNAL(clicked()), this,
186 SLOT(celestialPoleGetColor()) );
187 }
188
189 return m_configDialog;
190 }
191
settings() const192 QHash<QString, QVariant> StarsPlugin::settings() const
193 {
194 QHash<QString, QVariant> settings = RenderPlugin::settings();
195
196 settings.insert(QStringLiteral("nameIndex"), m_nameIndex);
197 settings.insert(QStringLiteral("renderStars"), m_renderStars);
198 settings.insert(QStringLiteral("renderConstellationLines"), m_renderConstellationLines);
199 settings.insert(QStringLiteral("renderConstellationLabels"), m_renderConstellationLabels);
200 settings.insert(QStringLiteral("renderDsos"), m_renderDsos);
201 settings.insert(QStringLiteral("renderDsoLabels"), m_renderDsoLabels);
202 settings.insert(QStringLiteral("renderSun"), m_renderSun);
203 settings.insert(QStringLiteral("renderMoon"), m_renderMoon);
204
205 QStringList planetState;
206 for (const QString &key: m_renderPlanet.keys())
207 planetState += key + QLatin1Char(':') + QString::number((int)m_renderPlanet[key]);
208 settings.insert(QStringLiteral("renderPlanet"), planetState.join(QLatin1Char('|')));
209
210 settings.insert(QStringLiteral("renderEcliptic"), m_renderEcliptic);
211 settings.insert(QStringLiteral("renderCelestialEquator"), m_renderCelestialEquator);
212 settings.insert(QStringLiteral("renderCelestialPole"), m_renderCelestialPole);
213 settings.insert(QStringLiteral("zoomSunMoon"), m_zoomSunMoon);
214 settings.insert(QStringLiteral("viewSolarSystemLabel"), m_viewSolarSystemLabel);
215 settings.insert(QStringLiteral("magnitudeLimit"), m_magnitudeLimit);
216 settings.insert(QStringLiteral("constellationBrush"), m_constellationBrush.color().rgb());
217 settings.insert(QStringLiteral("constellationLabelBrush"), m_constellationLabelBrush.color().rgb());
218 settings.insert(QStringLiteral("dsoLabelBrush"), m_dsoLabelBrush.color().rgb());
219 settings.insert(QStringLiteral("eclipticBrush"), m_eclipticBrush.color().rgb());
220 settings.insert(QStringLiteral("celestialEaquatorBrush"), m_celestialEquatorBrush.color().rgb());
221 settings.insert(QStringLiteral("celestialPoleBrush"), m_celestialPoleBrush.color().rgb());
222
223 return settings;
224 }
225
setSettings(const QHash<QString,QVariant> & settings)226 void StarsPlugin::setSettings( const QHash<QString, QVariant> &settings )
227 {
228 RenderPlugin::setSettings( settings );
229
230 m_nameIndex = readSetting<int>(settings, QStringLiteral("nameIndex"), 0);
231 m_renderStars = readSetting<bool>(settings, QStringLiteral("renderStars"), true);
232 m_renderConstellationLines = readSetting<bool>(settings, QStringLiteral("renderConstellationLines"), true);
233 m_renderConstellationLabels = readSetting<bool>(settings, QStringLiteral("renderConstellationLabels"), true);
234 m_renderDsos = readSetting<bool>(settings, QStringLiteral("renderDsos"), true);
235 m_renderDsoLabels = readSetting<bool>(settings, QStringLiteral("renderDsoLabels"), true);
236 m_renderSun = readSetting<bool>(settings, QStringLiteral("renderSun"), true);
237 m_renderMoon = readSetting<bool>(settings, QStringLiteral("renderMoon"), true);
238
239 m_renderPlanet.clear();
240 const QString renderPlanet = readSetting<QString>(settings, QStringLiteral("renderPlanet"), QString());
241 const QStringList renderStates = renderPlanet.split(QLatin1Char('|'));
242 for(const QString &state: renderStates) {
243 const QStringList stateList = state.split(QLatin1Char(':'));
244 if (stateList.size() == 2)
245 m_renderPlanet[stateList[0]] = (bool)stateList[1].toInt();
246 }
247
248 m_renderEcliptic = readSetting<bool>(settings, QStringLiteral("renderEcliptic"), true);
249 m_renderCelestialEquator = readSetting<bool>(settings, QStringLiteral("renderCelestialEquator"), true);
250 m_renderCelestialPole = readSetting<bool>(settings, QStringLiteral("renderCelestialPole"), true);
251 m_zoomSunMoon = readSetting<bool>(settings, QStringLiteral("zoomSunMoon"), true);
252 m_viewSolarSystemLabel = readSetting<bool>(settings, QStringLiteral("viewSolarSystemLabel"), true);
253 m_magnitudeLimit = readSetting<int>(settings, QStringLiteral("magnitudeLimit"), 100);
254 QColor const defaultColor = Marble::Oxygen::aluminumGray5;
255 m_constellationBrush = QColor(readSetting<QRgb>(settings, QStringLiteral("constellationBrush"), defaultColor.rgb()));
256 m_constellationLabelBrush = QColor(readSetting<QRgb>(settings, QStringLiteral("constellationLabelBrush"), defaultColor.rgb()));
257 m_dsoLabelBrush = QColor(readSetting<QRgb>(settings, QStringLiteral("dsoLabelBrush"), defaultColor.rgb()));
258 m_eclipticBrush = QColor(readSetting<QRgb>(settings, QStringLiteral("eclipticBrush"), defaultColor.rgb()));
259 m_celestialEquatorBrush = QColor(readSetting<QRgb>(settings, QStringLiteral("celestialEquatorBrush"), defaultColor.rgb()));
260 m_celestialPoleBrush = QColor(readSetting<QRgb>(settings, QStringLiteral("celestialPoleBrush"), defaultColor.rgb()));
261 }
262
starPixmap(qreal mag,int colorId) const263 QPixmap StarsPlugin::starPixmap(qreal mag, int colorId) const
264 {
265 if ( mag < -1 ) {
266 return m_pixN1Stars.at(colorId);
267 } else if ( mag < 0 ) {
268 return m_pixP0Stars.at(colorId);
269 } else if ( mag < 1 ) {
270 return m_pixP1Stars.at(colorId);
271 } else if ( mag < 2 ) {
272 return m_pixP2Stars.at(colorId);
273 } else if ( mag < 3 ) {
274 return m_pixP3Stars.at(colorId);
275 } else if ( mag < 4 ) {
276 return m_pixP4Stars.at(colorId);
277 } else if ( mag < 5 ) {
278 return m_pixP5Stars.at(colorId);
279 } else if ( mag < 6 ) {
280 return m_pixP6Stars.at(colorId);
281 } else {
282 return m_pixP7Stars.at(colorId);
283 }
284
285 return QPixmap();
286 }
287
prepareNames()288 void StarsPlugin::prepareNames()
289 {
290
291 QFile names(MarbleDirs::path(QStringLiteral("stars/names.csv")));
292 if ( !names.open( QIODevice::ReadOnly ) ) {
293 return;
294 }
295
296 QTextStream in( &names );
297 while ( !in.atEnd() ) {
298 QString line = in.readLine();
299 const QStringList list = line.split(QLatin1Char(';'));
300 if ( list.size() == 3 ) {
301 m_nativeHash[ list.at( 0 ) ] = QCoreApplication::translate( "StarNames", list.at( 1 ).toUtf8().constData() );
302 m_abbrHash[ list.at( 0 ) ] = list.at( 2 );
303 }
304 }
305 names.close();
306
307 }
308
assembledConstellation(const QString & name)309 QString StarsPlugin::assembledConstellation(const QString &name)
310 {
311 switch (m_nameIndex) {
312 case 0:
313 return name;
314 case 1:
315 return m_nativeHash[name];
316 case 2:
317 return m_abbrHash[name];
318 default:
319 return name;
320 }
321 }
322
readSettings()323 void StarsPlugin::readSettings()
324 {
325 if ( !m_configDialog ) {
326 return;
327 }
328
329 ui_configWidget->constellationNamesComboBox->setCurrentIndex(m_nameIndex);
330
331 Qt::CheckState const constellationLineState = m_renderConstellationLines ? Qt::Checked : Qt::Unchecked;
332 ui_configWidget->m_viewConstellationLinesCheckbox->setCheckState( constellationLineState );
333
334 Qt::CheckState const constellationLabelState = m_renderConstellationLabels ? Qt::Checked : Qt::Unchecked;
335 ui_configWidget->m_viewConstellationLabelsCheckbox->setCheckState( constellationLabelState );
336
337 Qt::CheckState const dsoState = m_renderDsos ? Qt::Checked : Qt::Unchecked;
338 ui_configWidget->m_viewDsosCheckbox->setCheckState( dsoState );
339
340 Qt::CheckState const dsoLabelState = m_renderDsoLabels ? Qt::Checked : Qt::Unchecked;
341 ui_configWidget->m_viewDsoLabelCheckbox->setCheckState( dsoLabelState );
342
343 Qt::CheckState const sunState = m_renderSun ? Qt::Checked : Qt::Unchecked;
344 ui_configWidget->m_solarSystemListWidget->item( 0 )->setCheckState( sunState );
345
346 Qt::CheckState const moonState = m_renderMoon ? Qt::Checked : Qt::Unchecked;
347 ui_configWidget->m_solarSystemListWidget->item( 1 )->setCheckState( moonState );
348
349 Qt::CheckState const mercuryState = m_renderPlanet["mercury"] ? Qt::Checked : Qt::Unchecked;
350 ui_configWidget->m_solarSystemListWidget->item( 2 )->setCheckState(mercuryState);
351
352 Qt::CheckState const venusState = m_renderPlanet["venus"] ? Qt::Checked : Qt::Unchecked;
353 ui_configWidget->m_solarSystemListWidget->item( 3 )->setCheckState(venusState);
354
355 Qt::CheckState const marsState = m_renderPlanet["mars"] ? Qt::Checked : Qt::Unchecked;
356 ui_configWidget->m_solarSystemListWidget->item( 5 )->setCheckState(marsState);
357
358 Qt::CheckState const jupiterState = m_renderPlanet["jupiter"] ? Qt::Checked : Qt::Unchecked;
359 ui_configWidget->m_solarSystemListWidget->item( 6 )->setCheckState(jupiterState);
360
361 Qt::CheckState const saturnState = m_renderPlanet["saturn"] ? Qt::Checked : Qt::Unchecked;
362 ui_configWidget->m_solarSystemListWidget->item( 7 )->setCheckState(saturnState);
363
364 Qt::CheckState const uranusState = m_renderPlanet["uranus"] ? Qt::Checked : Qt::Unchecked;
365 ui_configWidget->m_solarSystemListWidget->item( 8 )->setCheckState(uranusState);
366
367 Qt::CheckState const neptuneState = m_renderPlanet["neptune"] ? Qt::Checked : Qt::Unchecked;
368 ui_configWidget->m_solarSystemListWidget->item( 9 )->setCheckState(neptuneState);
369
370 Qt::CheckState const eclipticState = m_renderEcliptic ? Qt::Checked : Qt::Unchecked;
371 ui_configWidget->m_viewEclipticCheckbox->setCheckState( eclipticState );
372
373 Qt::CheckState const celestialEquatorState = m_renderCelestialEquator ? Qt::Checked : Qt::Unchecked;
374 ui_configWidget->m_viewCelestialEquatorCheckbox->setCheckState( celestialEquatorState );
375
376 Qt::CheckState const celestialPoleState = m_renderCelestialPole ? Qt::Checked : Qt::Unchecked;
377 ui_configWidget->m_viewCelestialPoleCheckbox->setCheckState( celestialPoleState );
378
379 Qt::CheckState const zoomSunMoonState = m_zoomSunMoon ? Qt::Checked : Qt::Unchecked;
380 ui_configWidget->m_zoomSunMoonCheckbox->setCheckState( zoomSunMoonState );
381
382 Qt::CheckState const viewSolarSystemLabelState = m_viewSolarSystemLabel ? Qt::Checked : Qt::Unchecked;
383 ui_configWidget->m_viewSolarSystemLabelCheckbox->setCheckState( viewSolarSystemLabelState );
384
385 int magState = m_magnitudeLimit;
386 if ( magState < ui_configWidget->m_magnitudeSlider->minimum() ) {
387 magState = ui_configWidget->m_magnitudeSlider->minimum();
388 }
389 else if ( magState > ui_configWidget->m_magnitudeSlider->maximum() ) {
390 magState = ui_configWidget->m_magnitudeSlider->maximum();
391 }
392
393 ui_configWidget->m_magnitudeSlider->setValue(magState);
394
395 QPalette constellationPalette;
396 constellationPalette.setColor( QPalette::Button, m_constellationBrush.color() );
397 ui_configWidget->m_constellationColorButton->setPalette( constellationPalette );
398
399 QPalette constellationLabelPalette;
400 constellationLabelPalette.setColor( QPalette::Button, m_constellationLabelBrush.color() );
401 ui_configWidget->m_constellationLabelColorButton->setPalette( constellationLabelPalette );
402
403 QPalette dsoLabelPalette;
404 dsoLabelPalette.setColor( QPalette::Button, m_dsoLabelBrush.color() );
405 ui_configWidget->m_dsoLabelColorButton->setPalette( dsoLabelPalette );
406
407 QPalette eclipticPalette;
408 eclipticPalette.setColor( QPalette::Button, m_eclipticBrush.color() );
409 ui_configWidget->m_eclipticColorButton->setPalette( eclipticPalette );
410
411 QPalette celestialEquatorPalette;
412 celestialEquatorPalette.setColor( QPalette::Button, m_celestialEquatorBrush.color() );
413 ui_configWidget->m_celestialEquatorColorButton->setPalette( celestialEquatorPalette );
414
415 QPalette celestialPolePalette;
416 celestialPolePalette.setColor( QPalette::Button, m_celestialPoleBrush.color() );
417 ui_configWidget->m_celestialPoleColorButton->setPalette( celestialPolePalette );
418
419
420 }
421
writeSettings()422 void StarsPlugin::writeSettings()
423 {
424 m_nameIndex = ui_configWidget->constellationNamesComboBox->currentIndex();
425 m_renderConstellationLines = ui_configWidget->m_viewConstellationLinesCheckbox->checkState() == Qt::Checked;
426 m_renderConstellationLabels = ui_configWidget->m_viewConstellationLabelsCheckbox->checkState() == Qt::Checked;
427 m_renderDsos = ui_configWidget->m_viewDsosCheckbox->checkState() == Qt::Checked;
428 m_renderDsoLabels = ui_configWidget->m_viewDsoLabelCheckbox->checkState() == Qt::Checked;
429 m_renderSun = ui_configWidget->m_solarSystemListWidget->item( 0 )->checkState() == Qt::Checked;
430 m_renderMoon = ui_configWidget->m_solarSystemListWidget->item( 1 )->checkState() == Qt::Checked;
431
432 m_renderPlanet["mercury"] = ui_configWidget->m_solarSystemListWidget->item( 2 )->checkState()
433 == Qt::Checked;
434 m_renderPlanet["venus"] = ui_configWidget->m_solarSystemListWidget->item( 3 )->checkState()
435 == Qt::Checked;
436 m_renderPlanet["mars"] = ui_configWidget->m_solarSystemListWidget->item( 5 )->checkState()
437 == Qt::Checked;
438 m_renderPlanet["jupiter"] = ui_configWidget->m_solarSystemListWidget->item( 6 )->checkState()
439 == Qt::Checked;
440 m_renderPlanet["saturn"] = ui_configWidget->m_solarSystemListWidget->item( 7 )->checkState()
441 == Qt::Checked;
442 m_renderPlanet["uranus"] = ui_configWidget->m_solarSystemListWidget->item( 8 )->checkState()
443 == Qt::Checked;
444 m_renderPlanet["neptune"] = ui_configWidget->m_solarSystemListWidget->item( 9 )->checkState()
445 == Qt::Checked;
446
447 m_renderEcliptic = ui_configWidget->m_viewEclipticCheckbox->checkState() == Qt::Checked;
448 m_renderCelestialEquator = ui_configWidget->m_viewCelestialEquatorCheckbox->checkState() == Qt::Checked;
449 m_renderCelestialPole = ui_configWidget->m_viewCelestialPoleCheckbox->checkState() == Qt::Checked;
450 m_zoomSunMoon = ui_configWidget->m_zoomSunMoonCheckbox->checkState() == Qt::Checked;
451 m_viewSolarSystemLabel = ui_configWidget->m_viewSolarSystemLabelCheckbox->checkState() == Qt::Checked;
452 m_magnitudeLimit = ui_configWidget->m_magnitudeSlider->value();
453 m_constellationBrush = QBrush( ui_configWidget->m_constellationColorButton->palette().color( QPalette::Button) );
454 m_constellationLabelBrush = QBrush( ui_configWidget->m_constellationLabelColorButton->palette().color( QPalette::Button) );
455 m_dsoLabelBrush = QBrush( ui_configWidget->m_dsoLabelColorButton->palette().color( QPalette::Button) );
456 m_eclipticBrush = QBrush( ui_configWidget->m_eclipticColorButton->palette().color( QPalette::Button) );
457 m_celestialEquatorBrush = QBrush( ui_configWidget->m_celestialEquatorColorButton->palette().color( QPalette::Button) );
458 m_celestialPoleBrush = QBrush( ui_configWidget->m_celestialPoleColorButton->palette().color( QPalette::Button) );
459 emit settingsChanged( nameId() );
460 }
461
constellationGetColor()462 void StarsPlugin::constellationGetColor()
463 {
464 const QColor c = QColorDialog::getColor( m_constellationBrush.color(), nullptr, tr("Please choose the color for the constellation lines.") );
465
466 if ( c.isValid() ) {
467 QPalette palette = ui_configWidget->m_constellationColorButton->palette();
468 palette.setColor( QPalette::Button, c );
469 ui_configWidget->m_constellationColorButton->setPalette( palette );
470 }
471 }
472
constellationLabelGetColor()473 void StarsPlugin::constellationLabelGetColor()
474 {
475 const QColor c = QColorDialog::getColor( m_constellationLabelBrush.color(), nullptr, tr("Please choose the color for the constellation labels.") );
476
477 if ( c.isValid() ) {
478 QPalette palette = ui_configWidget->m_constellationLabelColorButton->palette();
479 palette.setColor( QPalette::Button, c );
480 ui_configWidget->m_constellationLabelColorButton->setPalette( palette );
481 }
482 }
483
dsoLabelGetColor()484 void StarsPlugin::dsoLabelGetColor()
485 {
486 const QColor c = QColorDialog::getColor( m_dsoLabelBrush.color(), nullptr, tr("Please choose the color for the dso labels.") );
487
488 if ( c.isValid() ) {
489 QPalette palette = ui_configWidget->m_dsoLabelColorButton->palette();
490 palette.setColor( QPalette::Button, c );
491 ui_configWidget->m_dsoLabelColorButton->setPalette( palette );
492 }
493 }
494
eclipticGetColor()495 void StarsPlugin::eclipticGetColor()
496 {
497 const QColor c = QColorDialog::getColor( m_eclipticBrush.color(), nullptr, tr("Please choose the color for the ecliptic.") );
498
499 if ( c.isValid() ) {
500 QPalette palette = ui_configWidget->m_eclipticColorButton->palette();
501 palette.setColor( QPalette::Button, c );
502 ui_configWidget->m_eclipticColorButton->setPalette( palette );
503 }
504 }
505
celestialEquatorGetColor()506 void StarsPlugin::celestialEquatorGetColor()
507 {
508 const QColor c = QColorDialog::getColor( m_celestialEquatorBrush.color(), nullptr, tr("Please choose the color for the celestial equator.") );
509
510 if ( c.isValid() ) {
511 QPalette palette = ui_configWidget->m_celestialEquatorColorButton->palette();
512 palette.setColor( QPalette::Button, c );
513 ui_configWidget->m_celestialEquatorColorButton->setPalette( palette );
514 }
515 }
516
celestialPoleGetColor()517 void StarsPlugin::celestialPoleGetColor()
518 {
519 const QColor c = QColorDialog::getColor( m_celestialPoleBrush.color(), nullptr, tr("Please choose the color for the celestial equator.") );
520
521 if ( c.isValid() ) {
522 QPalette palette = ui_configWidget->m_celestialPoleColorButton->palette();
523 palette.setColor( QPalette::Button, c );
524 ui_configWidget->m_celestialPoleColorButton->setPalette( palette );
525 }
526 }
527
loadStars()528 void StarsPlugin::loadStars()
529 {
530 //mDebug() << Q_FUNC_INFO;
531 // Load star data
532 m_stars.clear();
533
534 QFile starFile(MarbleDirs::path(QStringLiteral("stars/stars.dat")));
535 starFile.open( QIODevice::ReadOnly );
536 QDataStream in( &starFile );
537
538 // Read and check the header
539 quint32 magic;
540 in >> magic;
541 if ( magic != 0x73746172 ) {
542 return;
543 }
544
545 // Read the version
546 qint32 version;
547 in >> version;
548 if ( version > 004 ) {
549 mDebug() << "stars.dat: file too new.";
550 return;
551 }
552
553 if ( version == 003 ) {
554 mDebug() << "stars.dat: file version no longer supported.";
555 return;
556 }
557
558 int maxid = 0;
559 int id = 0;
560 int starIndex = 0;
561 double ra;
562 double de;
563 double mag;
564 int colorId = 2;
565
566 mDebug() << "Star Catalog Version " << version;
567
568 while ( !in.atEnd() ) {
569 if ( version >= 2 ) {
570 in >> id;
571 }
572 if ( id > maxid ) {
573 maxid = id;
574 }
575 in >> ra;
576 in >> de;
577 in >> mag;
578
579 if ( version >= 4 ) {
580 in >> colorId;
581 }
582
583 StarPoint star( id, ( qreal )( ra ), ( qreal )( de ), ( qreal )( mag ), colorId );
584 // Create entry in stars database
585 m_stars << star;
586 // Create key,value pair in idHash table to map from star id to
587 // index in star database vector
588 m_idHash[id] = starIndex;
589 // Increment Index for use in hash
590 ++starIndex;
591 }
592
593 // load the Sun pixmap
594 // TODO: adjust pixmap size according to distance
595 m_pixmapSun.load(MarbleDirs::path(QStringLiteral("svg/sun.png")));
596 m_pixmapMoon.load(MarbleDirs::path(QStringLiteral("svg/moon.png")));
597
598 m_starsLoaded = true;
599 }
600
createStarPixmaps()601 void StarsPlugin::createStarPixmaps()
602 {
603 // Load star pixmaps
604 QVector<QPixmap> pixBigStars;
605 pixBigStars.clear();
606 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_blue.png"))));
607 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_bluewhite.png"))));
608 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_white.png"))));
609 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_yellow.png"))));
610 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_orange.png"))));
611 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_red.png"))));
612 pixBigStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_0_garnetred.png"))));
613
614 QVector<QPixmap> pixSmallStars;
615 pixSmallStars.clear();
616 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_blue.png"))));
617 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_bluewhite.png"))));
618 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_white.png"))));
619 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_yellow.png"))));
620 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_orange.png"))));
621 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_red.png"))));
622 pixSmallStars.append(QPixmap(MarbleDirs::path(QStringLiteral("bitmaps/stars/star_3_garnetred.png"))));
623
624
625 // Pre-Scale Star Pixmaps
626 m_pixN1Stars.clear();
627 for ( int p=0; p < pixBigStars.size(); ++p) {
628 int width = 1.0*pixBigStars.at(p).width();
629 m_pixN1Stars.append(pixBigStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
630 }
631
632 m_pixP0Stars.clear();
633 for ( int p=0; p < pixBigStars.size(); ++p) {
634 int width = 0.90*pixBigStars.at(p).width();
635 m_pixP0Stars.append(pixBigStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
636 }
637
638 m_pixP1Stars.clear();
639 for ( int p=0; p < pixBigStars.size(); ++p) {
640 int width = 0.80*pixBigStars.at(p).width();
641 m_pixP1Stars.append(pixBigStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
642 }
643
644 m_pixP2Stars.clear();
645 for ( int p=0; p < pixBigStars.size(); ++p) {
646 int width = 0.70*pixBigStars.at(p).width();
647 m_pixP2Stars.append(pixBigStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
648 }
649
650 m_pixP3Stars.clear();
651 for ( int p=0; p < pixSmallStars.size(); ++p) {
652 int width = 14;
653 m_pixP3Stars.append(pixSmallStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
654 }
655
656 m_pixP4Stars.clear();
657 for ( int p=0; p < pixSmallStars.size(); ++p) {
658 int width = 10;
659 m_pixP4Stars.append(pixSmallStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
660 }
661
662 m_pixP5Stars.clear();
663 for ( int p=0; p < pixSmallStars.size(); ++p) {
664 int width = 6;
665 m_pixP5Stars.append(pixSmallStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
666 }
667
668 m_pixP6Stars.clear();
669 for ( int p=0; p < pixSmallStars.size(); ++p) {
670 int width = 4;
671 m_pixP6Stars.append(pixSmallStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
672 }
673
674 m_pixP7Stars.clear();
675 for ( int p=0; p < pixSmallStars.size(); ++p) {
676 int width = 1;
677 m_pixP7Stars.append(pixSmallStars.at(p).scaledToWidth(width,Qt::SmoothTransformation));
678 }
679
680 m_starPixmapsCreated = true;
681 }
682
loadConstellations()683 void StarsPlugin::loadConstellations()
684 {
685 // Load star data
686 m_constellations.clear();
687
688 QFile constellationFile(MarbleDirs::path(QStringLiteral("stars/constellations.dat")));
689 constellationFile.open( QIODevice::ReadOnly );
690 QTextStream in( &constellationFile );
691 QString line;
692 QString indexList;
693
694 while ( !in.atEnd() ) {
695 line = in.readLine();
696
697 // Check for null line at end of file
698 if ( line.isNull() ) {
699 continue;
700 }
701
702 // Ignore Comment lines in header and
703 // between constellation entries
704 if (line.startsWith(QLatin1Char('#'))) {
705 continue;
706 }
707
708 indexList = in.readLine();
709
710 // Make sure we have a valid label and indexList
711 if ( indexList.isNull() ) {
712 break;
713 }
714
715 Constellation constellation( this, line, indexList );
716 m_constellations << constellation;
717
718 }
719 m_constellationsLoaded = true;
720
721 }
722
loadDsos()723 void StarsPlugin::loadDsos()
724 {
725 // Load star data
726 m_dsos.clear();
727
728 QFile dsoFile(MarbleDirs::path(QStringLiteral("stars/dso.dat")));
729 dsoFile.open( QIODevice::ReadOnly );
730 QTextStream in( &dsoFile );
731 QString line;
732
733 while ( !in.atEnd() ) {
734 line = in.readLine();
735
736 // Check for null line at end of file
737 if ( line.isNull() ) {
738 continue;
739 }
740
741 // Ignore Comment lines in header and
742 // between dso entries
743 if (line.startsWith(QLatin1Char('#'))) {
744 continue;
745 }
746
747 QStringList entries = line.split( QLatin1Char( ',' ) );
748
749 QString id = entries.at( 0 );
750
751 double raH = entries.at( 1 ).toDouble();
752 double raM = entries.at( 2 ).toDouble();
753 double raS = entries.at( 3 ).toDouble();
754 double decD = entries.at( 4 ).toDouble();
755 double decM = entries.at( 5 ).toDouble();
756 double decS = entries.at( 6 ).toDouble();
757
758 double raRad = ( raH+raM/60.0+raS/3600.0 )*15.0*M_PI/180.0;
759 double decRad;
760
761 if ( decD >= 0.0 ) {
762 decRad = ( decD+decM/60.0+decS/3600.0 )*M_PI/180.0;
763 }
764 else {
765 decRad = ( decD-decM/60.0-decS/3600.0 )*M_PI/180.0;
766 }
767
768 DsoPoint dso( id, ( qreal )( raRad ), ( qreal )( decRad ) );
769 // Create entry in stars database
770 m_dsos << dso;
771 }
772
773 m_dsoImage.load(MarbleDirs::path(QStringLiteral("stars/deepsky.png")));
774 m_dsosLoaded = true;
775 }
776
render(GeoPainter * painter,ViewportParams * viewport,const QString & renderPos,GeoSceneLayer * layer)777 bool StarsPlugin::render( GeoPainter *painter, ViewportParams *viewport,
778 const QString& renderPos, GeoSceneLayer * layer )
779 {
780 Q_UNUSED( renderPos )
781 Q_UNUSED( layer )
782
783 QString planetId = marbleModel()->planetId();
784 const bool doRender = !viewport->mapCoversViewport() &&
785 ( (viewport->projection() == Spherical || viewport->projection() == VerticalPerspective) &&
786 planetId == QLatin1String("earth")); // So far displaying stars is only supported on earth.
787
788 if ( doRender != m_doRender ) {
789 if ( doRender ) {
790 connect( marbleModel()->clock(), SIGNAL(timeChanged()),
791 this, SLOT(requestRepaint()) );
792 } else {
793 disconnect( marbleModel()->clock(), SIGNAL(timeChanged()),
794 this, SLOT(requestRepaint()) );
795 }
796
797 m_doRender = doRender;
798 }
799
800 painter->save();
801
802 SolarSystem sys;
803 QDateTime dateTime = marbleModel()->clock()->dateTime();
804 sys.setCurrentMJD(
805 dateTime.date().year(), dateTime.date().month(), dateTime.date().day(),
806 dateTime.time().hour(), dateTime.time().minute(),
807 (double)dateTime.time().second());
808 QString const pname = planetId.at(0).toUpper() + planetId.right(planetId.size() - 1);
809 QByteArray name = pname.toLatin1();
810 sys.setCentralBody( name.data() );
811
812 Vec3 skyVector = sys.getPlanetocentric (0.0, 0.0);
813 qreal skyRotationAngle = -atan2(skyVector[1], skyVector[0]);
814
815 const qreal centerLon = viewport->centerLongitude();
816 const qreal centerLat = viewport->centerLatitude();
817
818 const qreal skyRadius = 0.6 * sqrt( ( qreal )viewport->width() * viewport->width() + viewport->height() * viewport->height() );
819
820 if ( doRender ) {
821 if (!m_starPixmapsCreated) {
822 createStarPixmaps();
823 m_starPixmapsCreated = true;
824 }
825
826 // Delayed initialization:
827 // Load the star database only if the sky is actually being painted...
828 if ( !m_starsLoaded ) {
829 loadStars();
830 m_starsLoaded = true;
831 }
832
833 if ( !m_constellationsLoaded ) {
834 loadConstellations();
835 m_constellationsLoaded = true;
836 }
837
838 if ( !m_dsosLoaded ) {
839 loadDsos();
840 m_dsosLoaded = true;
841 }
842
843 const qreal earthRadius = viewport->radius();
844
845 // List of Pens used to draw the sky
846 QPen polesPen( m_celestialPoleBrush, 2, Qt::SolidLine );
847 QPen constellationPenSolid( m_constellationBrush, 1, Qt::SolidLine );
848 QPen constellationPenDash( m_constellationBrush, 1, Qt::DashLine );
849 QPen constellationLabelPen( m_constellationLabelBrush, 1, Qt::SolidLine );
850 QPen eclipticPen( m_eclipticBrush, 1, Qt::DotLine );
851 QPen equatorPen( m_celestialEquatorBrush, 1, Qt::DotLine );
852 QPen dsoLabelPen (m_dsoLabelBrush, 1, Qt::SolidLine);
853
854
855 const Quaternion skyAxis = Quaternion::fromEuler( -centerLat , centerLon + skyRotationAngle, 0.0 );
856 matrix skyAxisMatrix;
857 skyAxis.inverse().toMatrix( skyAxisMatrix );
858
859 if ( m_renderCelestialPole ) {
860
861 polesPen.setWidth( 2 );
862 painter->setPen( polesPen );
863
864 Quaternion qpos1;
865 qpos1 = Quaternion::fromSpherical( 0, 90 * DEG2RAD );
866 qpos1.rotateAroundAxis( skyAxisMatrix );
867
868 if ( qpos1.v[Q_Z] < 0 ) {
869 const int x1 = ( int )( viewport->width() / 2 + skyRadius * qpos1.v[Q_X] );
870 const int y1 = ( int )( viewport->height() / 2 - skyRadius * qpos1.v[Q_Y] );
871 painter->drawLine( x1, y1, x1+10, y1 );
872 painter->drawLine( x1+5, y1-5, x1+5, y1+5 );
873 painter->drawText( x1+8, y1+12, "NP" );
874 }
875
876 Quaternion qpos2;
877 qpos2 = Quaternion::fromSpherical( 0, -90 * DEG2RAD );
878 qpos2.rotateAroundAxis( skyAxisMatrix );
879 if ( qpos2.v[Q_Z] < 0 ) {
880 const int x1 = ( int )( viewport->width() / 2 + skyRadius * qpos2.v[Q_X] );
881 const int y1 = ( int )( viewport->height() / 2 - skyRadius * qpos2.v[Q_Y] );
882 painter->drawLine( x1, y1, x1+10, y1 );
883 painter->drawLine( x1+5, y1-5, x1+5, y1+5 );
884 painter->drawText( x1+8, y1+12, "SP" );
885 }
886 }
887
888 if( m_renderEcliptic ) {
889 const Quaternion eclipticAxis = Quaternion::fromEuler( 0.0, 0.0, -marbleModel()->planet()->epsilon() );
890 matrix eclipticAxisMatrix;
891 (eclipticAxis * skyAxis).inverse().toMatrix( eclipticAxisMatrix );
892
893 painter->setPen(eclipticPen);
894
895 int previousX = -1;
896 int previousY = -1;
897 for ( int i = 0; i <= 36; ++i) {
898 Quaternion qpos;
899 qpos = Quaternion::fromSpherical( i * 10 * DEG2RAD, 0 );
900 qpos.rotateAroundAxis( eclipticAxisMatrix );
901
902 int x = ( int )( viewport->width() / 2 + skyRadius * qpos.v[Q_X] );
903 int y = ( int )( viewport->height() / 2 - skyRadius * qpos.v[Q_Y] );
904
905 if ( qpos.v[Q_Z] < 0 && previousX >= 0 ) painter->drawLine(previousX, previousY, x, y);
906
907 previousX = x;
908 previousY = y;
909 }
910 }
911
912 if( m_renderCelestialEquator ) {
913 painter->setPen(equatorPen);
914
915 int previousX = -1;
916 int previousY = -1;
917 for ( int i = 0; i <= 36; ++i) {
918 Quaternion qpos;
919 qpos = Quaternion::fromSpherical( i * 10 * DEG2RAD, 0 );
920 qpos.rotateAroundAxis( skyAxisMatrix );
921
922 int x = ( int )( viewport->width() / 2 + skyRadius * qpos.v[Q_X] );
923 int y = ( int )( viewport->height() / 2 - skyRadius * qpos.v[Q_Y] );
924
925 if ( qpos.v[Q_Z] < 0 && previousX > 0 ) painter->drawLine(previousX, previousY, x, y);
926
927 previousX = x;
928 previousY = y;
929 }
930 }
931
932 if ( m_renderDsos ) {
933 painter->setPen(dsoLabelPen);
934 // Render Deep Space Objects
935 for ( int d = 0; d < m_dsos.size(); ++d ) {
936 Quaternion qpos = m_dsos.at( d ).quaternion();
937 qpos.rotateAroundAxis( skyAxisMatrix );
938
939 if ( qpos.v[Q_Z] > 0 ) {
940 continue;
941 }
942
943 qreal earthCenteredX = qpos.v[Q_X] * skyRadius;
944 qreal earthCenteredY = qpos.v[Q_Y] * skyRadius;
945
946 // Don't draw high placemarks (e.g. satellites) that aren't visible.
947 if ( qpos.v[Q_Z] < 0
948 && ( ( earthCenteredX * earthCenteredX
949 + earthCenteredY * earthCenteredY )
950 < earthRadius * earthRadius ) ) {
951 continue;
952 }
953
954 // Let (x, y) be the position on the screen of the placemark..
955 const int x = ( int )( viewport->width() / 2 + skyRadius * qpos.v[Q_X] );
956 const int y = ( int )( viewport->height() / 2 - skyRadius * qpos.v[Q_Y] );
957
958 // Skip placemarks that are outside the screen area
959 if ( x < 0 || x >= viewport->width() ||
960 y < 0 || y >= viewport->height() ) {
961 continue;
962 }
963
964 // Hard Code DSO Size for now
965 qreal size = 20;
966
967 // Center Image on x,y location
968 painter->drawImage( QRectF( x-size/2, y-size/2, size, size ),m_dsoImage );
969 if (m_renderDsoLabels) {
970 painter->drawText( x+8, y+12, m_dsos.at( d ).id() );
971 }
972 }
973 }
974
975 if ( m_renderConstellationLines || m_renderConstellationLabels )
976 {
977 // Render Constellations
978 for ( int c = 0; c < m_constellations.size(); ++c ) {
979 int xMean = 0;
980 int yMean = 0;
981 int endptCount = 0;
982 painter->setPen( constellationPenSolid );
983
984 for ( int s = 0; s < ( m_constellations.at( c ).size() - 1 ); ++s ) {
985 int starId1 = m_constellations.at( c ).at( s );
986 int starId2 = m_constellations.at( c ).at( s + 1 );
987
988 if ( starId1 == -1 || starId2 == -1 ) {
989 // starId == -1 means we don't draw this segment
990 continue;
991 } else if ( starId1 == -2 || starId2 == -2 ) {
992 painter->setPen( constellationPenDash );
993 } else if ( starId1 == -3 || starId2 == -3 ) {
994 painter->setPen( constellationPenSolid );
995 }
996
997 int idx1 = m_idHash.value( starId1,-1 );
998 int idx2 = m_idHash.value( starId2,-1 );
999
1000
1001 if ( idx1 < 0 ) {
1002 mDebug() << "unknown star, "
1003 << starId1 << ", in constellation "
1004 << m_constellations.at( c ).name();
1005 continue;
1006 }
1007
1008 if ( idx2 < 0 ) {
1009 mDebug() << "unknown star, "
1010 << starId1 << ", in constellation "
1011 << m_constellations.at( c ).name();
1012 continue;
1013 }
1014 // Fetch quaternion from star s in constellation c
1015 Quaternion q1 = m_stars.at( idx1 ).quaternion();
1016 // Fetch quaternion from star s+1 in constellation c
1017 Quaternion q2 = m_stars.at( idx2 ).quaternion();
1018
1019 q1.rotateAroundAxis( skyAxisMatrix );
1020 q2.rotateAroundAxis( skyAxisMatrix );
1021
1022 if ( q1.v[Q_Z] > 0 || q2.v[Q_Z] > 0 ) {
1023 continue;
1024 }
1025
1026
1027 // Let (x, y) be the position on the screen of the placemark..
1028 int x1 = ( int )( viewport->width() / 2 + skyRadius * q1.v[Q_X] );
1029 int y1 = ( int )( viewport->height() / 2 - skyRadius * q1.v[Q_Y] );
1030 int x2 = ( int )( viewport->width() / 2 + skyRadius * q2.v[Q_X] );
1031 int y2 = ( int )( viewport->height() / 2 - skyRadius * q2.v[Q_Y] );
1032
1033
1034 xMean = xMean + x1 + x2;
1035 yMean = yMean + y1 + y2;
1036 endptCount = endptCount + 2;
1037
1038 if ( m_renderConstellationLines ) {
1039 painter->drawLine( x1, y1, x2, y2 );
1040 }
1041
1042 }
1043
1044 // Skip constellation labels that are outside the screen area
1045 if ( endptCount > 0 ) {
1046 xMean = xMean / endptCount;
1047 yMean = yMean / endptCount;
1048 }
1049
1050 if ( endptCount < 1 || xMean < 0 || xMean >= viewport->width()
1051 || yMean < 0 || yMean >= viewport->height() )
1052 continue;
1053
1054 painter->setPen( constellationLabelPen );
1055 if ( m_renderConstellationLabels ) {
1056 painter->drawText( xMean, yMean, m_constellations.at( c ).name() );
1057 }
1058
1059 }
1060 }
1061
1062 // Render Stars
1063
1064 for ( int s = 0; s < m_stars.size(); ++s ) {
1065 Quaternion qpos = m_stars.at(s).quaternion();
1066
1067 qpos.rotateAroundAxis( skyAxisMatrix );
1068
1069 if ( qpos.v[Q_Z] > 0 ) {
1070 continue;
1071 }
1072
1073 qreal earthCenteredX = qpos.v[Q_X] * skyRadius;
1074 qreal earthCenteredY = qpos.v[Q_Y] * skyRadius;
1075
1076 // Don't draw high placemarks (e.g. satellites) that aren't visible.
1077 if ( qpos.v[Q_Z] < 0
1078 && ( ( earthCenteredX * earthCenteredX
1079 + earthCenteredY * earthCenteredY )
1080 < earthRadius * earthRadius ) ) {
1081 continue;
1082 }
1083
1084 // Let (x, y) be the position on the screen of the placemark..
1085 const int x = ( int )( viewport->width() / 2 + skyRadius * qpos.v[Q_X] );
1086 const int y = ( int )( viewport->height() / 2 - skyRadius * qpos.v[Q_Y] );
1087
1088 // Skip placemarks that are outside the screen area
1089 if ( x < 0 || x >= viewport->width()
1090 || y < 0 || y >= viewport->height() )
1091 continue;
1092
1093 // Show star if it is brighter than magnitude threshold
1094 if ( m_stars.at(s).magnitude() < m_magnitudeLimit ) {
1095
1096 // colorId is used to select which pixmap in vector to display
1097 int colorId = m_stars.at(s).colorId();
1098 QPixmap s_pixmap = starPixmap(m_stars.at(s).magnitude(), colorId);
1099 int sizeX = s_pixmap.width();
1100 int sizeY = s_pixmap.height();
1101 painter->drawPixmap( x-sizeX/2, y-sizeY/2 ,s_pixmap );
1102 }
1103 }
1104
1105 if ( m_renderSun ) {
1106 // sun
1107 double ra = 0.0;
1108 double decl = 0.0;
1109 sys.getSun( ra, decl );
1110 ra = 15.0 * sys.DmsDegF( ra );
1111 decl = sys.DmsDegF( decl );
1112
1113 Quaternion qpos = Quaternion::fromSpherical( ra * DEG2RAD, decl * DEG2RAD );
1114 qpos.rotateAroundAxis( skyAxisMatrix );
1115
1116 if ( qpos.v[Q_Z] <= 0 ) {
1117 QPixmap glow(MarbleDirs::path(QStringLiteral("svg/glow.png")));
1118 qreal deltaX = glow.width() / 2.;
1119 qreal deltaY = glow.height() / 2.;
1120 int x = (int)(viewport->width() / 2 + skyRadius * qpos.v[Q_X]);
1121 int y = (int)(viewport->height() / 2 - skyRadius * qpos.v[Q_Y]);
1122
1123 bool glowDrawn = false;
1124 if (!(x < -glow.width() || x >= viewport->width() ||
1125 y < -glow.height() || y >= viewport->height())) {
1126 painter->drawPixmap( x - deltaX, y - deltaY, glow );
1127 glowDrawn = true;
1128 }
1129
1130 if (glowDrawn) {
1131 double diameter = 0.0, mag = 0.0;
1132 sys.getPhysSun(diameter, mag);
1133 const int coefficient = m_zoomSunMoon ? m_zoomCoefficient : 1;
1134 const qreal size = skyRadius * qSin(diameter) * coefficient;
1135 const qreal factor = size/m_pixmapSun.width();
1136 QPixmap sun = m_pixmapSun.transformed(QTransform().scale(factor, factor),
1137 Qt::SmoothTransformation);
1138 deltaX = sun.width() / 2.;
1139 deltaY = sun.height() / 2.;
1140 x = (int)(viewport->width() / 2 + skyRadius * qpos.v[Q_X]);
1141 y = (int)(viewport->height() / 2 - skyRadius * qpos.v[Q_Y]);
1142
1143 painter->drawPixmap( x - deltaX, y - deltaY, sun );
1144 }
1145
1146 // It's labels' time!
1147 if (m_viewSolarSystemLabel)
1148 painter->drawText(x+deltaX*1.5, y+deltaY*1.5, tr("Sun"));
1149 }
1150 }
1151
1152 if ( m_renderMoon && marbleModel()->planetId() == QLatin1String("earth")) {
1153 // moon
1154 double ra=0.0;
1155 double decl=0.0;
1156 sys.getMoon(ra, decl);
1157 ra = 15.0 * sys.DmsDegF(ra);
1158 decl = sys.DmsDegF(decl);
1159
1160 Quaternion qpos = Quaternion::fromSpherical( ra * DEG2RAD,
1161 decl * DEG2RAD );
1162 qpos.rotateAroundAxis( skyAxisMatrix );
1163
1164 if ( qpos.v[Q_Z] <= 0 ) {
1165 // If zoom Sun and Moon is enabled size is multiplied by zoomCoefficient.
1166 const int coefficient = m_zoomSunMoon ? m_zoomCoefficient : 1;
1167
1168 QPixmap moon = m_pixmapMoon.copy();
1169
1170 const qreal size = skyRadius * qSin(sys.getDiamMoon()) * coefficient;
1171 qreal deltaX = size / 2.;
1172 qreal deltaY = size / 2.;
1173 const int x = (int)(viewport->width() / 2 + skyRadius * qpos.v[Q_X]);
1174 const int y = (int)(viewport->height() / 2 - skyRadius * qpos.v[Q_Y]);
1175
1176
1177 if (!(x < -size || x >= viewport->width() ||
1178 y < -size || y >= viewport->height())) {
1179 // Moon phases
1180 double phase = 0.0, ildisk = 0.0, amag = 0.0;
1181 sys.getLunarPhase(phase, ildisk, amag);
1182
1183 QPainterPath path;
1184
1185 QRectF fullMoonRect = moon.rect();
1186 if (ildisk < 0.05) {
1187 // small enough, so it's not visible
1188 path.addEllipse(fullMoonRect);
1189 } else if (ildisk < 0.95) { // makes sense to do smth
1190 QRectF halfEllipseRect;
1191 qreal ellipseWidth = 2 * qAbs(ildisk-0.5) * moon.width();
1192 halfEllipseRect.setX((fullMoonRect.width() - ellipseWidth) * 0.5);
1193 halfEllipseRect.setWidth(ellipseWidth);
1194 halfEllipseRect.setHeight(moon.height());
1195
1196 if (phase < 0.5) {
1197 if (ildisk < 0.5) {
1198 path.moveTo(fullMoonRect.width()/2, moon.height());
1199 path.arcTo(fullMoonRect, -90, -180);
1200 path.arcTo(halfEllipseRect, 90, -180);
1201 } else {
1202 path.moveTo(fullMoonRect.width()/2, 0);
1203 path.arcTo(fullMoonRect, 90, 180);
1204 path.arcTo(halfEllipseRect, -90, -180);
1205 }
1206 } else {
1207 if (ildisk < 0.5) {
1208 path.moveTo(fullMoonRect.width()/2, moon.height());
1209 path.arcTo(fullMoonRect, -90, 180);
1210 path.arcTo(halfEllipseRect, 90, 180);
1211 } else {
1212 path.moveTo(fullMoonRect.width()/2, 0);
1213 path.arcTo(fullMoonRect, 90, -180);
1214 path.arcTo(halfEllipseRect, -90, 180);
1215 }
1216 }
1217
1218 path.closeSubpath();
1219 }
1220
1221 QPainter overlay;
1222 overlay.begin(&moon);
1223 overlay.setPen(Qt::NoPen);
1224 overlay.setBrush(QBrush(QColor(0, 0, 0, 180)));
1225 overlay.setRenderHint(QPainter::Antialiasing, true);
1226 overlay.drawPath(path);
1227 overlay.end();
1228
1229 qreal angle = marbleModel()->planet()->epsilon() * qCos(ra * DEG2RAD) * RAD2DEG;
1230 if (viewport->polarity() < 0) angle += 180;
1231
1232 QTransform form;
1233 const qreal factor = size / moon.size().width();
1234 moon = moon.transformed(form.rotate(angle).scale(factor, factor),
1235 Qt::SmoothTransformation);
1236
1237 painter->drawPixmap( x - deltaX, y - deltaY, moon );
1238
1239 // It's labels' time!
1240 if (m_viewSolarSystemLabel)
1241 painter->drawText(x+deltaX, y+deltaY, PlanetFactory::localizedName("moon"));
1242 }
1243 }
1244 }
1245
1246 for(const QString &planet: m_renderPlanet.keys()) {
1247 if (m_renderPlanet[planet])
1248 renderPlanet(planet, painter, sys, viewport, skyRadius, skyAxisMatrix);
1249 }
1250 }
1251
1252 painter->restore();
1253
1254 return true;
1255 }
1256
renderPlanet(const QString & planetId,GeoPainter * painter,SolarSystem & sys,ViewportParams * viewport,qreal skyRadius,matrix & skyAxisMatrix) const1257 void StarsPlugin::renderPlanet(const QString &planetId,
1258 GeoPainter *painter,
1259 SolarSystem &sys,
1260 ViewportParams *viewport,
1261 qreal skyRadius,
1262 matrix &skyAxisMatrix) const
1263 {
1264 double ra(.0), decl(.0), diam(.0), mag(.0), phase(.0);
1265 int color=0;
1266
1267 // venus, mars, jupiter, uranus, neptune, saturn
1268 if (planetId == QLatin1String("venus")) {
1269 sys.getVenus(ra, decl);
1270 sys.getPhysVenus(diam, mag, phase);
1271 color = 2;
1272 } else if (planetId == QLatin1String("mars")) {
1273 sys.getMars(ra, decl);
1274 sys.getPhysMars(diam, mag, phase);
1275 color = 5;
1276 } else if (planetId == QLatin1String("jupiter")) {
1277 sys.getJupiter(ra, decl);
1278 sys.getPhysJupiter(diam, mag, phase);
1279 color = 2;
1280 } else if (planetId == QLatin1String("mercury")) {
1281 sys.getMercury(ra, decl);
1282 sys.getPhysMercury(diam, mag, phase);
1283 color = 3;
1284 } else if (planetId == QLatin1String("saturn")) {
1285 sys.getSaturn(ra, decl);
1286 sys.getPhysSaturn(diam, mag, phase);
1287 color = 3;
1288 } else if (planetId == QLatin1String("uranus")) {
1289 sys.getUranus(ra, decl);
1290 sys.getPhysUranus(diam, mag, phase);
1291 color = 0;
1292 } else if (planetId == QLatin1String("neptune")) {
1293 sys.getNeptune(ra, decl);
1294 sys.getPhysNeptune(diam, mag, phase);
1295 color = 0;
1296 } else {
1297 return;
1298 }
1299
1300 ra = 15.0 * sys.DmsDegF(ra);
1301 decl = sys.DmsDegF(decl);
1302
1303 Quaternion qpos = Quaternion::fromSpherical( ra * DEG2RAD,
1304 decl * DEG2RAD );
1305 qpos.rotateAroundAxis( skyAxisMatrix );
1306
1307 if ( qpos.v[Q_Z] <= 0 ) {
1308 QPixmap planetPixmap = starPixmap(mag, color);
1309
1310 qreal deltaX = planetPixmap.width() / 2.;
1311 qreal deltaY = planetPixmap.height() / 2.;
1312 const int x = (int)(viewport->width() / 2 + skyRadius * qpos.v[Q_X]);
1313 const int y = (int)(viewport->height() / 2 - skyRadius * qpos.v[Q_Y]);
1314
1315 if (!(x < 0 || x >= viewport->width() ||
1316 y < 0 || y >= viewport->height())) {
1317 painter->drawPixmap( x - deltaX, y - deltaY, planetPixmap );
1318 }
1319
1320 // It's labels' time!
1321 if (m_viewSolarSystemLabel)
1322 painter->drawText(x+deltaX, y+deltaY, PlanetFactory::localizedName(planetId));
1323 }
1324 }
1325
requestRepaint()1326 void StarsPlugin::requestRepaint()
1327 {
1328 emit repaintNeeded( QRegion() );
1329 }
1330
toggleSunMoon(bool on)1331 void StarsPlugin::toggleSunMoon(bool on)
1332 {
1333 m_renderSun = on;
1334 m_renderMoon = on;
1335 if (on) {
1336 m_viewSolarSystemLabel = true;
1337 }
1338
1339 const Qt::CheckState state = on ? Qt::Checked : Qt::Unchecked;
1340 if ( m_configDialog ) {
1341 ui_configWidget->m_solarSystemListWidget->item( 0 )->setCheckState( state );
1342 ui_configWidget->m_solarSystemListWidget->item( 1 )->setCheckState( state );
1343 ui_configWidget->m_viewSolarSystemLabelCheckbox->setChecked(m_viewSolarSystemLabel);
1344 }
1345 emit settingsChanged( nameId() );
1346 requestRepaint();
1347 }
1348
toggleDsos(bool on)1349 void StarsPlugin::toggleDsos(bool on)
1350 {
1351 m_renderDsos = on;
1352 // only enable labels if set to true
1353 if (on) {
1354 m_renderDsoLabels = true;
1355 }
1356
1357 const Qt::CheckState state = on ? Qt::Checked : Qt::Unchecked;
1358 if ( m_configDialog ) {
1359 ui_configWidget->m_viewDsosCheckbox->setChecked(state);
1360 ui_configWidget->m_viewDsoLabelCheckbox->setChecked(state);
1361 }
1362 emit settingsChanged( nameId() );
1363 requestRepaint();
1364 }
1365
toggleConstellations(bool on)1366 void StarsPlugin::toggleConstellations(bool on)
1367 {
1368 m_renderConstellationLines = on;
1369 m_renderConstellationLabels = on;
1370
1371 const Qt::CheckState state = on ? Qt::Checked : Qt::Unchecked;
1372 if ( m_configDialog ) {
1373 ui_configWidget->m_viewConstellationLinesCheckbox->setChecked( state );
1374 ui_configWidget->m_viewConstellationLabelsCheckbox->setChecked( state );
1375 }
1376 emit settingsChanged( nameId() );
1377 requestRepaint();
1378 }
1379
togglePlanets(bool on)1380 void StarsPlugin::togglePlanets(bool on)
1381 {
1382 m_renderPlanet["venus"] = on;
1383 m_renderPlanet["mars"] = on;
1384 m_renderPlanet["jupiter"] = on;
1385 m_renderPlanet["mercury"] = on;
1386 m_renderPlanet["saturn"] = on;
1387 m_renderPlanet["uranus"] = on;
1388 m_renderPlanet["neptune"] = on;
1389
1390 const Qt::CheckState state = on ? Qt::Checked : Qt::Unchecked;
1391 if ( m_configDialog ) {
1392 // Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune
1393 ui_configWidget->m_solarSystemListWidget->item(2)->setCheckState(state);
1394 ui_configWidget->m_solarSystemListWidget->item(3)->setCheckState(state);
1395 ui_configWidget->m_solarSystemListWidget->item(5)->setCheckState(state);
1396 ui_configWidget->m_solarSystemListWidget->item(6)->setCheckState(state);
1397 ui_configWidget->m_solarSystemListWidget->item(7)->setCheckState(state);
1398 ui_configWidget->m_solarSystemListWidget->item(8)->setCheckState(state);
1399 ui_configWidget->m_solarSystemListWidget->item(9)->setCheckState(state);
1400 }
1401
1402 emit settingsChanged( nameId() );
1403 requestRepaint();
1404 }
1405
executeConfigDialog()1406 void StarsPlugin::executeConfigDialog()
1407 {
1408 QDialog *dialog = configDialog();
1409 Q_ASSERT( dialog );
1410 dialog->exec();
1411 }
1412
eventFilter(QObject * object,QEvent * e)1413 bool StarsPlugin::eventFilter( QObject *object, QEvent *e )
1414 {
1415 if ( !enabled() || !visible() ) {
1416 return false;
1417 }
1418
1419 if( e->type() == QEvent::ContextMenu )
1420 {
1421 MarbleWidget *widget = dynamic_cast<MarbleWidget *>( object );
1422 QContextMenuEvent *menuEvent = dynamic_cast<QContextMenuEvent *> ( e );
1423 if( widget && menuEvent )
1424 {
1425 qreal mouseLon, mouseLat;
1426 const bool aboveMap = widget->geoCoordinates( menuEvent->x(), menuEvent->y(),
1427 mouseLon, mouseLat, GeoDataCoordinates::Radian );
1428 if ( aboveMap ) {
1429 return false;
1430 }
1431
1432 for ( AbstractFloatItem *floatItem: widget->floatItems() ) {
1433 if ( floatItem->enabled() && floatItem->visible()
1434 && floatItem->contains( menuEvent->pos() ) )
1435 {
1436 return false;
1437 }
1438 }
1439
1440 if (!m_contextMenu) {
1441 m_contextMenu = new QMenu;
1442 m_constellationsAction = m_contextMenu->addAction(tr("Show &Constellations"),
1443 this, SLOT(toggleConstellations(bool)));
1444 m_constellationsAction->setCheckable(true);
1445
1446 m_sunMoonAction = m_contextMenu->addAction(tr("Show &Sun and Moon"),
1447 this, SLOT(toggleSunMoon(bool)));
1448 m_sunMoonAction->setCheckable(true);
1449
1450 m_planetsAction = m_contextMenu->addAction(tr("Show &Planets"),
1451 this, SLOT(togglePlanets(bool)));
1452 m_planetsAction->setCheckable(true);
1453
1454 m_dsoAction = m_contextMenu->addAction(tr("Show &Deep Sky Objects"),
1455 this, SLOT(toggleDsos(bool)) );
1456 m_dsoAction->setCheckable(true);
1457
1458 m_contextMenu->addSeparator();
1459 m_contextMenu->addAction(tr("&Configure..."),
1460 this, SLOT(executeConfigDialog()));
1461 }
1462
1463 // update action states
1464 m_constellationsAction->setChecked(m_renderConstellationLines || m_renderConstellationLabels);
1465 m_sunMoonAction->setChecked(m_renderSun || m_renderMoon);
1466 m_dsoAction->setChecked(m_renderDsos);
1467 const bool isAnyPlanetRendered =
1468 m_renderPlanet["venus"] || m_renderPlanet["mars"] ||
1469 m_renderPlanet["jupiter"] || m_renderPlanet["mercury"] ||
1470 m_renderPlanet["saturn"] || m_renderPlanet["uranus"] ||
1471 m_renderPlanet["neptune"];
1472 m_planetsAction->setChecked(isAnyPlanetRendered);
1473
1474 m_contextMenu->exec(widget->mapToGlobal(menuEvent->pos()));
1475 return true;
1476 }
1477 return false;
1478 } else {
1479 return RenderPlugin::eventFilter( object, e );
1480 }
1481 }
1482
1483 }
1484
1485 #include "moc_StarsPlugin.cpp"
1486