• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 15291801018

28 May 2025 04:52AM UTC coverage: 11.931% (-0.02%) from 11.951%
15291801018

push

github

alex-w
Added new set of navigational stars (XIX century)

0 of 6 new or added lines in 2 files covered. (0.0%)

14124 existing lines in 74 files now uncovered.

14635 of 122664 relevant lines covered (11.93%)

18291.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/core/modules/LandscapeMgr.cpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2006 Fabien Chereau
4
 * Copyright (C) 2010 Bogdan Marinov (add/remove landscapes feature)
5
 * Copyright (C) 2011 Alexander Wolf
6
 * Copyright (C) 2012 Timothy Reaves
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
21
 */
22

23
#include "LandscapeMgr.hpp"
24
#include "Landscape.hpp"
25
#include "AtmospherePreetham.hpp"
26
#include "AtmosphereShowMySky.hpp"
27
#include "StelApp.hpp"
28
#include "SolarSystem.hpp"
29
#include "StelCore.hpp"
30
#include "StelLocaleMgr.hpp"
31
#include "StelModuleMgr.hpp"
32
#include "StelFileMgr.hpp"
33
#include "Planet.hpp"
34
#include "StelIniParser.hpp"
35
#include "StelSkyDrawer.hpp"
36
#include "StelPainter.hpp"
37
#include "StelPropertyMgr.hpp"
38
#include "StelUtils.hpp"
39

40
#if USE_BUNDLED_QTCOMPRESS
41
#include "external/qtcompress/qzipreader.h"
42
#else
43
#include <private/qzipreader_p.h>
44
#endif
45
#include <QTimer>
46
#include <QDebug>
47
#include <QSettings>
48
#include <QString>
49
#include <QDir>
50
#include <QDirIterator>
51
#include <QFile>
52
#include <QTemporaryFile>
53
#include <QMouseEvent>
54
#include <QPainter>
55
#include <QElapsedTimer>
56
#include <QOpenGLPaintDevice>
57

58
namespace
59
{
60
constexpr char ATMOSPHERE_MODEL_CONFIG_KEY[]="landscape/atmosphere_model";
61
constexpr char ATMOSPHERE_MODEL_PATH_CONFIG_KEY[]="landscape/atmosphere_model_path";
62
constexpr char ATMOSPHERE_ECLIPSE_SIM_QUALITY_CONFIG_KEY[]="landscape/atmosphere_eclipse_simulation_quality";
63
constexpr char ATMOSPHERE_MODEL_CONF_VAL_PREETHAM[]="preetham";
64
constexpr char ATMOSPHERE_MODEL_CONF_VAL_SHOWMYSKY[]="showmysky";
65
constexpr char ATMOSPHERE_MODEL_CONF_VAL_DEFAULT[]="preetham";
66
}
67

UNCOV
68
Cardinals::Cardinals()
×
UNCOV
69
        : color(0.6f,0.2f,0.2f)
×
70
{
71
        propMgr = StelApp::getInstance().getStelPropertyManager();
×
72
        updateFontSizes();
×
73

74
        // English names for cardinals
75
        labels = {
UNCOV
76
                {   dN,  "N" }, {   dS,  "S" }, {   dE,  "E" }, {   dW,  "W" },
×
UNCOV
77
                {  dNE, "NE" }, {  dSE, "SE" }, {  dSW, "SW" }, {  dNW, "NW" },
×
UNCOV
78
                { dNNE,"NNE" }, { dENE,"ENE" }, { dESE,"ESE" }, { dSSE,"SSE" },
×
79
                { dSSW,"SSW" }, { dWSW,"WSW" }, { dWNW,"WNW" }, { dNNW,"NNW" },
×
80
                { dNbE,"NbE" }, {dNEbN,"NEbN"}, {dNEbE,"NEbE"}, { dEbN,"EbN" },
×
81
                { dEbS,"EbS" }, {dSEbE,"SEbE"}, {dSEbS,"SEbS"}, { dSbE,"SbE" },
×
82
                { dSbW,"SbW" }, {dSWbS,"SWbS"}, {dSWbW,"SWbW"}, { dWbS,"WbS" },
×
83
                { dWbN,"WbN" }, {dNWbW,"NWbW"}, {dNWbN,"NWbN"}, { dNbW,"NbW" }
×
84
        };
×
85
        QObject::connect(&StelApp::getInstance(), &StelApp::screenFontSizeChanged,
×
86
                         [this]{updateFontSizes();});
×
87
}
×
88

89
void Cardinals::updateFontSizes()
×
90
{
UNCOV
91
        QSettings* conf = StelApp::getInstance().getSettings();
×
92
        Q_ASSERT(conf);
×
UNCOV
93
        screenFontSize = StelApp::getInstance().getScreenFontSize();
×
94
        const float scale = StelApp::getInstance().screenFontSizeRatio();
×
95
        // Default font size is 24
96
        font4WCR.setPixelSize(conf->value("viewing/cardinal_font_size", screenFontSize+11*scale).toInt());
×
97
        // Default font size is 18
UNCOV
98
        font8WCR.setPixelSize(conf->value("viewing/ordinal_font_size", screenFontSize+5*scale).toInt());
×
99
        // Draw the principal wind points even smaller.
UNCOV
100
        font16WCR.setPixelSize(conf->value("viewing/16wcr_font_size", screenFontSize+2*scale).toInt());
×
101
        font32WCR.setPixelSize(conf->value("viewing/32wcr_font_size", screenFontSize).toInt());
×
UNCOV
102
}
×
103

104
Cardinals::~Cardinals()
×
105
{
UNCOV
106
}
×
107

108
const float Cardinals::sp8 = sin(M_PIf/8.f); // dimension for intercardinals
109
const float Cardinals::cp8 = cos(M_PIf/8.f); // dimension for intercardinals
110
const float Cardinals::s1p16 = sin(M_PIf/16.f);     // dimension for rose32
111
const float Cardinals::c1p16 = cos(M_PIf/16.f);     // dimension for rose32
112
const float Cardinals::s3p16 = sin(3.f*M_PIf/16.f); // dimension for rose32
113
const float Cardinals::c3p16 = cos(3.f*M_PIf/16.f); // dimension for rose32
114

115
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose4winds = {
116
        { Cardinals::dN, Vec3f(-1.f, 0.f, 0.f) }, { Cardinals::dS, Vec3f(1.f,  0.f, 0.f) },
117
        { Cardinals::dE, Vec3f( 0.f, 1.f, 0.f) }, { Cardinals::dW, Vec3f(0.f, -1.f, 0.f) }
118
};
119
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose8winds = {
120
        { Cardinals::dNE, Vec3f(-q8,  q8, 0.f) }, { Cardinals::dSE, Vec3f( q8,  q8, 0.f) },
121
        { Cardinals::dSW, Vec3f( q8, -q8, 0.f) }, { Cardinals::dNW, Vec3f(-q8, -q8, 0.f) }
122
};
123
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose16winds = {
124
        { Cardinals::dNNE, Vec3f(-cp8,  sp8, 0.f) }, { Cardinals::dENE, Vec3f(-sp8,  cp8, 0.f) },
125
        { Cardinals::dESE, Vec3f( sp8,  cp8, 0.f) }, { Cardinals::dSSE, Vec3f( cp8,  sp8, 0.f) },
126
        { Cardinals::dSSW, Vec3f( cp8, -sp8, 0.f) }, { Cardinals::dWSW, Vec3f( sp8, -cp8, 0.f) },
127
        { Cardinals::dWNW, Vec3f(-sp8, -cp8, 0.f) }, { Cardinals::dNNW, Vec3f(-cp8, -sp8, 0.f) }
128
};
129
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose32winds = {
130
        { Cardinals::dNbE,  Vec3f(-c1p16, s1p16, 0.f) }, { Cardinals::dNbW,  Vec3f(-c1p16, -s1p16, 0.f) },
131
        { Cardinals::dSbE,  Vec3f( c1p16, s1p16, 0.f) }, { Cardinals::dSbW,  Vec3f( c1p16, -s1p16, 0.f) },
132
        { Cardinals::dEbS,  Vec3f( s1p16, c1p16, 0.f) }, { Cardinals::dEbN,  Vec3f(-s1p16,  c1p16, 0.f) },
133
        { Cardinals::dWbN,  Vec3f(-s1p16,-c1p16, 0.f) }, { Cardinals::dWbS,  Vec3f( s1p16, -c1p16, 0.f) },
134
        { Cardinals::dNEbN, Vec3f(-c3p16, s3p16, 0.f) }, { Cardinals::dNWbN, Vec3f(-c3p16, -s3p16, 0.f) },
135
        { Cardinals::dSEbS, Vec3f( c3p16, s3p16, 0.f) }, { Cardinals::dSWbS, Vec3f( c3p16, -s3p16, 0.f) },
136
        { Cardinals::dSEbE, Vec3f( s3p16, c3p16, 0.f) }, { Cardinals::dNEbE, Vec3f(-s3p16,  c3p16, 0.f) },
137
        { Cardinals::dNWbW, Vec3f(-s3p16,-c3p16, 0.f) }, { Cardinals::dSWbW, Vec3f( s3p16, -c3p16, 0.f) }
138
};
139

UNCOV
140
void Cardinals::update(double deltaTime)
×
141
{
UNCOV
142
        fader4WCR.update(static_cast<int>(deltaTime*1000));
×
143
        fader8WCR.update(static_cast<int>(deltaTime*1000));
×
UNCOV
144
        fader16WCR.update(static_cast<int>(deltaTime*1000));
×
145
        fader32WCR.update(static_cast<int>(deltaTime*1000));
×
146
}
×
147

148
void Cardinals::setFadeDuration(float duration)
×
149
{
UNCOV
150
        fader4WCR.setDuration(static_cast<int>(duration*1000.f));
×
151
        fader8WCR.setDuration(static_cast<int>(duration*1000.f));
×
UNCOV
152
        fader16WCR.setDuration(static_cast<int>(duration*1000.f));
×
153
        fader32WCR.setDuration(static_cast<int>(duration*1000.f));
×
154
}
×
155

156
// Draw the cardinals points : N S E W and the subcardinal and sub-subcardinal.
157
// Handles special cases at poles
UNCOV
158
void Cardinals::draw(const StelCore* core, double latitude) const
×
159
{
160
        // fun polar special cases: no cardinals!
161
        if ((fabs(latitude - 90.0) < 1e-10) || (fabs(latitude + 90.0) < 1e-10))
×
UNCOV
162
                return;
×
163

164
        if (fader4WCR.getInterstate()>0.f)
×
165
        {
UNCOV
166
                const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
167
                const float ppx = prj->getDevicePixelsPerPixel();
×
UNCOV
168
                const float fontSizeRatio = StelApp::getInstance().screenFontSizeRatio();
×
169
                StelPainter sPainter(prj);
×
170
                sPainter.setFont(font4WCR);
×
171
                const bool flagMask = (core->getProjection(StelCore::FrameJ2000)->getMaskType() != StelProjector::MaskDisk);
×
172
                float vshift=1.f;
×
173
                if (propMgr->getProperty("SpecialMarkersMgr.compassMarksDisplayed")->getValue().toBool())
×
174
                        vshift = static_cast<float>(screenFontSize + 12*fontSizeRatio)*ppx;
×
175

176
                Vec3f xy;
×
177
                sPainter.setColor(color, fader4WCR.getInterstate());
×
UNCOV
178
                sPainter.setBlending(true);
×
179
                QMapIterator<Cardinals::CompassDirection, Vec3f> it4w(rose4winds);
×
180
                while(it4w.hasNext())
×
181
                {
182
                        it4w.next();
×
183
                        QString directionLabel = labels.value(it4w.key(), "");
×
184

185
                        const float sshift = (flagMask ? ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f : 0.0f);
×
186

UNCOV
187
                        if (prj->project(it4w.value(), xy))
×
188
                        {
189
                                Vec3f up(it4w.value()[0], it4w.value()[1], 1.f*M_PI_180f);
×
UNCOV
190
                                Vec3f upPrj;
×
191
                                prj->project(up, upPrj);
×
UNCOV
192
                                float dx=upPrj[0]-xy[0];
×
193
                                float dy=upPrj[1]-xy[1];
×
194
                                float textAngle=atan2(dx, dy);
×
195
                                sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -sshift, vshift, true);
×
196
                        }
197
                }
×
198

199
                if (fader8WCR.getInterstate()>0.f)
×
200
                {
201
                        float minFader = qMin(fader4WCR.getInterstate(), fader8WCR.getInterstate());
×
UNCOV
202
                        sPainter.setColor(color, minFader);
×
203
                        sPainter.setFont(font8WCR);
×
204

205
                        QMapIterator<Cardinals::CompassDirection, Vec3f> it8w(rose8winds);
×
206
                        while(it8w.hasNext())
×
207
                        {
UNCOV
208
                                it8w.next();
×
209
                                QString directionLabel = labels.value(it8w.key(), "");
×
210
                                const float bshift = (flagMask ? ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f : 0.0f);
×
211

212
                                if (prj->project(it8w.value(), xy))
×
213
                                {
UNCOV
214
                                        Vec3f up(it8w.value()[0], it8w.value()[1], 1.f*M_PI_180f);
×
215
                                        Vec3f upPrj;
×
216
                                        prj->project(up, upPrj);
×
UNCOV
217
                                        float dx=upPrj[0]-xy[0];
×
218
                                        float dy=upPrj[1]-xy[1];
×
UNCOV
219
                                        float textAngle=atan2(dx, dy);
×
220
                                        sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -bshift, vshift, true);
×
221
                                }
222
                        }
×
223

224
                        if (fader16WCR.getInterstate()>0.f)
×
225
                        {
226
                                sPainter.setColor(color, qMin(minFader, fader16WCR.getInterstate()));
×
UNCOV
227
                                sPainter.setFont(font16WCR);
×
228

UNCOV
229
                                QMapIterator<Cardinals::CompassDirection, Vec3f> it16w(rose16winds);
×
230
                                while(it16w.hasNext())
×
231
                                {
232
                                        it16w.next();
×
233
                                        QString directionLabel = labels.value(it16w.key(), "");
×
234

235
                                        const float cshift = (flagMask ? ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f : 0.0f);
×
236

UNCOV
237
                                        if (prj->project(it16w.value(), xy))
×
238
                                        {
239
                                                Vec3f up(it16w.value()[0], it16w.value()[1], 1.f*M_PI_180f);
×
UNCOV
240
                                                Vec3f upPrj;
×
241
                                                prj->project(up, upPrj);
×
242
                                                float dx=upPrj[0]-xy[0];
×
UNCOV
243
                                                float dy=upPrj[1]-xy[1];
×
244
                                                float textAngle=atan2(dx, dy);
×
UNCOV
245
                                                sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -cshift, vshift, true);
×
246
                                        }
247
                                }
×
248

249
                                if (fader32WCR.getInterstate()>0.f)
×
250
                                {
251
                                        sPainter.setColor(color, qMin(minFader, fader32WCR.getInterstate()));
×
252
                                        sPainter.setFont(font32WCR);
×
253

254
                                        QMapIterator<Cardinals::CompassDirection, Vec3f> it32w(rose32winds);
×
UNCOV
255
                                        while(it32w.hasNext())
×
256
                                        {
UNCOV
257
                                                it32w.next();
×
258
                                                QString directionLabel = labels.value(it32w.key(), "");
×
259

UNCOV
260
                                                const float dshift = (flagMask ? ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f : 0.0f);
×
261

262
                                                if (prj->project(it32w.value(), xy))
×
263
                                                {
264
                                                        Vec3f up(it32w.value()[0], it32w.value()[1], 1.f*M_PI_180f);
×
265
                                                        Vec3f upPrj;
×
UNCOV
266
                                                        prj->project(up, upPrj);
×
267
                                                        float dx=upPrj[0]-xy[0];
×
268
                                                        float dy=upPrj[1]-xy[1];
×
UNCOV
269
                                                        float textAngle=atan2(dx, dy);
×
270
                                                        sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -dshift, vshift, true);
×
271
                                                }
272
                                        }
×
273
                                }
×
274
                        }
×
275
                }
×
276
        }
×
277
}
278

279
// Translate cardinal labels with gettext to current sky language and update font for the language
280
void Cardinals::updateI18n()
×
281
{
282
        labels = {
283
                // TRANSLATORS: North
284
                { dN,        qc_("N",   "compass direction") },
×
285
                // TRANSLATORS: South
UNCOV
286
                { dS,        qc_("S",   "compass direction") },
×
287
                // TRANSLATORS: East
288
                { dE,        qc_("E",   "compass direction") },
×
289
                // TRANSLATORS: West
UNCOV
290
                { dW,        qc_("W",   "compass direction") },
×
291
                // TRANSLATORS: Northeast
292
                { dNE,        qc_("NE",  "compass direction") },
×
293
                // TRANSLATORS: Southeast
294
                { dSE,        qc_("SE",  "compass direction") },
×
295
                // TRANSLATORS: Southwest
296
                { dSW,        qc_("SW",  "compass direction") },
×
297
                // TRANSLATORS: Northwest
298
                { dNW,        qc_("NW",  "compass direction") },
×
299
                // TRANSLATORS: North-northeast
300
                { dNNE,        qc_("NNE", "compass direction") },
×
301
                // TRANSLATORS: East-northeast
302
                { dENE,        qc_("ENE", "compass direction") },
×
303
                // TRANSLATORS: East-southeast
304
                { dESE,        qc_("ESE", "compass direction") },
×
305
                // TRANSLATORS: South-southeast
306
                { dSSE,        qc_("SSE", "compass direction") },
×
307
                // TRANSLATORS: South-southwest
308
                { dSSW,        qc_("SSW", "compass direction") },
×
309
                // TRANSLATORS: West-southwest
310
                { dWSW,        qc_("WSW", "compass direction") },
×
311
                // TRANSLATORS: West-northwest
312
                { dWNW, qc_("WNW", "compass direction") },
×
313
                // TRANSLATORS: North-northwest
314
                { dNNW,        qc_("NNW", "compass direction") },
×
315
                // TRANSLATORS: North by east
316
                { dNbE, qc_("NbE", "compass direction") },
×
317
                // TRANSLATORS: Northeast by north
318
                {dNEbN, qc_("NEbN","compass direction") },
×
319
                // TRANSLATORS: Northeast by east
320
                {dNEbE, qc_("NEbE","compass direction") },
×
321
                // TRANSLATORS: East by north
322
                { dEbN, qc_("EbN", "compass direction") },
×
323
                // TRANSLATORS: East by south
324
                { dEbS, qc_("EbS", "compass direction") },
×
325
                // TRANSLATORS: Southeast by east
326
                {dSEbE, qc_("SEbE","compass direction") },
×
327
                // TRANSLATORS: Southeast by south
328
                {dSEbS, qc_("SEbS","compass direction") },
×
329
                // TRANSLATORS: South by east
330
                { dSbE, qc_("SbE", "compass direction") },
×
331
                // TRANSLATORS: South by west
332
                { dSbW, qc_("SbW", "compass direction") },
×
333
                // TRANSLATORS: Southwest by south
334
                {dSWbS, qc_("SWbS","compass direction") },
×
335
                // TRANSLATORS: Southwest by west
336
                {dSWbW, qc_("SWbW","compass direction") },
×
337
                // TRANSLATORS: West by south
338
                { dWbS, qc_("WbS", "compass direction") },
×
339
                // TRANSLATORS: West by north
340
                { dWbN, qc_("WbN", "compass direction") },
×
341
                // TRANSLATORS: Northwest by west
342
                {dNWbW, qc_("NWbW","compass direction") },
×
343
                // TRANSLATORS: Northwest by north
344
                {dNWbN, qc_("NWbN","compass direction") },
×
345
                // TRANSLATORS: North by west
346
                { dNbW, qc_("NbW", "compass direction") }
×
UNCOV
347
        };
×
348
}
×
349

350
LandscapeMgr::LandscapeMgr()
×
351
        : StelModule()
352
        , atmosphere(Q_NULLPTR)
×
UNCOV
353
        , cardinalPoints(Q_NULLPTR)
×
354
        , landscape(Q_NULLPTR)
×
355
        , oldLandscape(Q_NULLPTR)
×
356
        , messageTimer(new QTimer(this))
×
UNCOV
357
        , flagLandscapeSetsLocation(false)
×
358
        , flagLandscapeAutoSelection(false)
×
UNCOV
359
        , flagLightPollutionFromDatabase(false)
×
360
        , atmosphereNoScatter(false)
×
361
        , flagPolyLineDisplayedOnly(false)
×
362
        , flagLandscapeUseMinimalBrightness(false)
×
363
        , defaultMinimalBrightness(0.01)
×
364
        , flagLandscapeSetsMinimalBrightness(false)
×
365
        , flagEnvironmentAutoEnabling(false)
×
366
        , flagLandscapeUseTransparency(false)
×
367
        , landscapeTransparency(0.)
×
368
        , landscapeTint(1.f, 1.f, 1.f)
×
369
{
370
        setObjectName("LandscapeMgr"); // should be done by StelModule's constructor.
×
371

372
        //Note: The first entry in the list is used as the default 'default landscape' in removeLandscape().
373
        packagedLandscapeIDs = (QStringList() << "guereins");
×
374
        QDirIterator directories(StelFileMgr::getInstallationDir()+"/landscapes/", QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
×
375
        while(directories.hasNext())
×
376
        {
UNCOV
377
                directories.next();
×
378
                packagedLandscapeIDs << directories.fileName();
×
379
        }
UNCOV
380
        packagedLandscapeIDs.removeDuplicates();
×
381
        landscapeCache.clear();
×
382

383
        messageTimer->setInterval(5000);
×
UNCOV
384
        messageTimer->setSingleShot(true);
×
385
        connect(messageTimer, &QTimer::timeout, this, &LandscapeMgr::clearMessage);
×
386
}
×
387

388
LandscapeMgr::~LandscapeMgr()
×
389
{
UNCOV
390
        delete cardinalPoints;
×
391
        if (oldLandscape)
×
392
        {
393
                delete oldLandscape;
×
394
                oldLandscape=Q_NULLPTR;
×
395
        }
396
        delete landscape;
×
UNCOV
397
        landscape = Q_NULLPTR;
×
398
        qInfo() << "LandscapeMgr: Clearing cache of" << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
399
        landscapeCache.clear(); // deletes all objects within.
×
UNCOV
400
}
×
401

402
/*************************************************************************
403
 Reimplementation of the getCallOrder method
404
*************************************************************************/
405
double LandscapeMgr::getCallOrder(StelModuleActionName actionName) const
×
406
{
407
        if (actionName==StelModule::ActionDraw)
×
408
                return StelApp::getInstance().getModuleMgr().getModule("SporadicMeteorMgr")->getCallOrder(actionName)+20;
×
UNCOV
409
        if (actionName==StelModule::ActionUpdate)
×
UNCOV
410
                return StelApp::getInstance().getModuleMgr().getModule("SolarSystem")->getCallOrder(actionName)+10;
×
411
        // GZ The next 2 lines are only required to test landscape transparency. They should be commented away for releases.
UNCOV
412
        if (actionName==StelModule::ActionHandleMouseClicks)
×
413
                return StelApp::getInstance().getModuleMgr().getModule("StelMovementMgr")->getCallOrder(actionName)-1;
×
UNCOV
414
        return 0.;
×
415
}
416

417
void LandscapeMgr::update(double deltaTime)
×
418
{
UNCOV
419
        if(needToRecreateAtmosphere && !loadingAtmosphere)
×
420
                createAtmosphere();
×
421

422
        const auto core = StelApp::getInstance().getCore();
×
UNCOV
423
        const auto drawer = core->getSkyDrawer();
×
424

425
        if(loadingAtmosphere && loadingAtmosphere->isLoading())
×
426
        {
427
                try
428
                {
429
                        // Use no more than 1/60th of a second for this batch of loading
430
                        QElapsedTimer timer;
×
431
                        timer.start();
×
UNCOV
432
                        Atmosphere::LoadingStatus status={1,1};
×
433
                        while(loadingAtmosphere->isLoading() && timer.elapsed() < 1000/60)
×
UNCOV
434
                                status = loadingAtmosphere->stepDataLoading();
×
UNCOV
435
                        if(loadingAtmosphere->isLoading())
×
436
                        {
UNCOV
437
                                setAtmosphereShowMySkyStoppedWithError(false);
×
438
                                const auto percentDone = std::lround(100.*status.stepsDone/status.stepsToDo);
×
439
                                setAtmosphereShowMySkyStatusText(QString("%1 %2% %3").arg(q_("Loading..."), QString::number(percentDone), qc_("done","percentage of done")));
×
440
                                qInfo() << "Finished this batch of loading at" << percentDone << "%, will continue in the next frame";
×
441
                        }
442
                        else
443
                        {
UNCOV
444
                                setAtmosphereShowMySkyStatusText(q_("Switching models..."));
×
445
                        }
446
                }
447
                catch(Atmosphere::InitFailure const& error)
×
448
                {
UNCOV
449
                        qInfo() << "ERROR: Failed to load atmosphere model data:" << error.what();
×
UNCOV
450
                        qWarning() << "Falling back to the Preetham's model";
×
UNCOV
451
                        setAtmosphereShowMySkyStoppedWithError(true);
×
452
                        setAtmosphereShowMySkyStatusText(error.what());
×
UNCOV
453
                        loadingAtmosphere.reset();
×
UNCOV
454
                }
×
455
        }
456

457
        if(loadingAtmosphere && loadingAtmosphere->isReadyToRender())
×
458
        {
459
                bool loaded = false;
×
460
                if(drawer->getFlagHasAtmosphere())
×
461
                {
462
                        // Fade out current atmosphere, then fade in the new one
UNCOV
463
                        if(atmosphere->getFlagShow())
×
464
                        {
465
                                atmosphere->setFlagShow(false);
×
466
                        }
467
                        else if(atmosphere->getFadeIntensity() == 0)
×
468
                        {
UNCOV
469
                                loadingAtmosphere->setFlagShow(true);
×
UNCOV
470
                                loadingAtmosphere->setFadeDuration(atmosphere->getFadeDuration());
×
471
                                loadingAtmosphere->setLightPollutionLuminance(atmosphere->getLightPollutionLuminance());
×
UNCOV
472
                                loaded = true;
×
473
                        }
474
                }
475
                else
476
                {
477
                        loaded = true;
×
478
                }
479

480
                if(loaded)
×
481
                {
UNCOV
482
                        atmosphere = std::move(loadingAtmosphere);
×
483
#ifdef ENABLE_SHOWMYSKY
UNCOV
484
                        if(dynamic_cast<AtmosphereShowMySky*>(atmosphere.get()))
×
485
                                setAtmosphereShowMySkyStatusText(q_("Loaded successfully"));
×
486
#endif
UNCOV
487
                        emit atmosphereModelChanged(getAtmosphereModel());
×
488
                }
489
        }
490

UNCOV
491
        atmosphere->update(deltaTime);
×
492

493
        if (oldLandscape)
×
494
        {
495
                // This is only when transitioning to newly loaded landscape. We must draw the old one until the new one is faded in completely.
UNCOV
496
                oldLandscape->update(deltaTime);
×
UNCOV
497
                if (getIsLandscapeFullyVisible())
×
498
                {
499
                        oldLandscape->setFlagShow(false);
×
500

501
                        if (oldLandscape->getEffectiveLandFadeValue()< 0.01f)
×
502
                        {
503
                                // new logic: try to put old landscape to cache.
504
                                //qDebug() << "LandscapeMgr::update: moving oldLandscape " << oldLandscape->getId() << "to Cache. Cost:" << oldLandscape->getMemorySize()/(1024*1024)+1;
505
                                landscapeCache.insert(oldLandscape->getId(), oldLandscape, oldLandscape->getMemorySize()/(1024*1024)+1);
×
506
                                //qDebug() << "--> LandscapeMgr::update(): cache now contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
507
                                oldLandscape=Q_NULLPTR;
×
508
                        }
509
                }
510
        }
UNCOV
511
        landscape->update(deltaTime);
×
UNCOV
512
        cardinalPoints->update(deltaTime);
×
513
        Landscape::illumFader.update(static_cast<int>(deltaTime*1000));
×
UNCOV
514
        Landscape::labelFader.update(static_cast<int>(deltaTime*1000));
×
515

516
        // Compute the atmosphere color and intensity
517
        // Compute the sun position in local coordinate
UNCOV
518
        SolarSystem* ssystem = static_cast<SolarSystem*>(StelApp::getInstance().getModuleMgr().getModule("SolarSystem"));
×
519

520
        // Compute the moon position in local coordinate
521
        const auto sun   = ssystem->getSun();
×
522
        const auto moon  = ssystem->getMoon();
×
UNCOV
523
        const auto earth = ssystem->getEarth();
×
UNCOV
524
        const auto currentPlanet = core->getCurrentPlanet();
×
UNCOV
525
        const bool currentIsEarth = currentPlanet->getID() == earth->getID();
×
526
        // First parameter in next call is used for particularly earth-bound computations in Schaefer's sky brightness model. Difference DeltaT makes no difference here.
527
        // Temperature = 15°C, relative humidity = 40%
528
        try
529
        {
530
                atmosphere->computeColor(core, core->getJDE(), *currentPlanet, *sun,
×
531
                                                                 currentIsEarth ? moon.data() : nullptr, core->getCurrentLocation(),
×
532
                                                                 15.f, 40.f, static_cast<float>(drawer->getExtinctionCoefficient()), atmosphereNoScatter);
×
533
        }
UNCOV
534
        catch(Atmosphere::InitFailure const& error)
×
535
        {
UNCOV
536
                qWarning().noquote() << "ShowMySky atmosphere model crashed:" << error.what();
×
UNCOV
537
                qInfo().noquote() << "Loading Preetham model";
×
538
                showMessage(q_("ShowMySky atmosphere model crashed. Loading Preetham model as a fallback."));
×
539
                resetToFallbackAtmosphere();
×
540
        }
×
541

542
        core->getSkyDrawer()->reportLuminanceInFov(3.75f+atmosphere->getAverageLuminance()*3.5f, true);
×
543

544
        // NOTE: Simple workaround for brightness of landscape when observing from the Sun.
545
        if (currentPlanet->getID() == sun->getID())
×
546
        {
547
                landscape->setBrightness(1.0, 1.0);
×
548
                landscape->setTint(Vec3f(1.f));
×
UNCOV
549
                return;
×
550
        }
551

552
        // Compute the ground luminance based on every planets around
553
        // TBD: Reactivate and verify this code!? Source, reference?
554
//        float groundLuminance = 0;
555
//        const vector<Planet*>& allPlanets = ssystem->getAllPlanets();
556
//        for (auto i=allPlanets.begin();i!=allPlanets.end();++i)
557
//        {
558
//                Vec3d pos = (*i)->getAltAzPos(core);
559
//                pos.normalize();
560
//                if (pos[2] <= 0)
561
//                {
562
//                        // No need to take this body into the landscape illumination computation
563
//                        // because it is under the horizon
564
//                }
565
//                else
566
//                {
567
//                        // Compute the Illuminance E of the ground caused by the planet in lux = lumen/m^2
568
//                        float E = pow10(((*i)->get_mag(core)+13.988)/-2.5);
569
//                        //qDebug() << "mag=" << (*i)->get_mag(core) << " illum=" << E;
570
//                        // Luminance in cd/m^2
571
//                        groundLuminance += E/0.44*pos[2]*pos[2]; // 1m^2 from 1.5 m above the ground is 0.44 sr.
572
//                }
573
//        }
574
//        groundLuminance*=atmosphere->getFadeIntensity();
575
//        groundLuminance=atmosphere->getAverageLuminance()/50;
576
//        qDebug() << "Atmosphere lum=" << atmosphere->getAverageLuminance() << " ground lum=" <<  groundLuminance;
577
//        qDebug() << "Adapted Atmosphere lum=" << eye->adaptLuminance(atmosphere->getAverageLuminance()) << " Adapted ground lum=" << eye->adaptLuminance(groundLuminance);
578

579
        // compute global ground brightness in a simplistic way, directly in RGB
580

UNCOV
581
        double landscapeBrightness=0.0;
×
UNCOV
582
        if (getFlagLandscapeUseMinimalBrightness())
×
583
        {
584
                // Setting from landscape.ini has priority if enabled
UNCOV
585
                if (getFlagLandscapeSetsMinimalBrightness() && landscape->getLandscapeMinimalBrightness()>=0)
×
UNCOV
586
                        landscapeBrightness = landscape->getLandscapeMinimalBrightness();
×
587
                else
UNCOV
588
                        landscapeBrightness = getDefaultMinimalBrightness();
×
589
        }
590

UNCOV
591
        Vec3d sunPos = sun->getAltAzPosAuto(core);
×
UNCOV
592
        sunPos.normalize();
×
593
        Vec3d moonPos = moon->getAltAzPosAuto(core);
×
594
        moonPos.normalize();
×
595

596
        // With atmosphere on, we define the solar brightness contribution zero when the sun is 8 degrees below the horizon.
597
        // The multiplier of 1.5 just looks better, it somehow represents illumination by scattered sunlight.
598
        // Else, we should account for sun's diameter but else just apply Lambertian Cos-rule and check with landscape opacity.
599
        double sinSunAngle = 0.0;
×
600
        if(atmosphere->getFlagShow())
×
601
        {
602
                sinSunAngle=sin(qMin(M_PI_2, asin(sunPos[2])+8.*M_PI/180.));
×
UNCOV
603
                if(sinSunAngle > -0.1/1.5 )
×
UNCOV
604
                        landscapeBrightness +=  1.5*(sinSunAngle+0.1/1.5);
×
605
        }
606
        else
607
        {
608
                // In case we have exceptionally deep horizons ("Little Prince planet"), the sun will rise somehow over that line and demand light on the landscape.
UNCOV
609
                sinSunAngle=sin(qMin(M_PI_2, asin(qBound(-1.0, sunPos[2]-landscape->getSinMinAltitudeLimit(), 1.0) ) + (0.25 *M_PI_180)));
×
610
                if(sinSunAngle > 0.0)
×
611
                        landscapeBrightness +=  (1.0-static_cast<double>(landscape->getOpacity(sunPos)))*sinSunAngle;
×
612
        }
613

614
        // GZ: 2013-09-25 Take light pollution into account!
UNCOV
615
        const float nelm = StelCore::luminanceToNELM(drawer->getLightPollutionLuminance());
×
UNCOV
616
        float pollutionAddonBrightness=(15.5f-2*nelm)*0.025f; // 0..8, so we assume empirical linear brightening 0..0.02
×
617
        float lunarAddonBrightness=0.f;
×
618
        if (currentIsEarth && moonPos[2] > -0.1/1.5)
×
619
                lunarAddonBrightness = qMax(0.2f/-12.f*moon->getVMagnitudeWithExtinction(core),0.f)*static_cast<float>(moonPos[2]);
×
620

UNCOV
621
        landscapeBrightness += static_cast<double>(qMax(lunarAddonBrightness, pollutionAddonBrightness));
×
622

623
        // TODO make this more generic for non-atmosphere planets
624
        if(atmosphere->getFadeIntensity() > 0.99999f )
×
625
        {
626
                // If the atmosphere is on, a solar eclipse might darken the sky
627
                // otherwise we just use the sun position calculation above
UNCOV
628
                landscapeBrightness *= static_cast<double>(atmosphere->getRealDisplayIntensityFactor()+0.1f);
×
629
        }
630
        // TODO: should calculate dimming with solar eclipse even without atmosphere on
631

632
        // Brightness can't be over 1.f (see https://bugs.launchpad.net/stellarium/+bug/1115364)
UNCOV
633
        if (landscapeBrightness>0.95)
×
UNCOV
634
                landscapeBrightness = 0.95;
×
635

636
        // GZ's rules and intentions for lightscape brightness:
637
        // lightscapeBrightness >0 makes sense only for sun below horizon.
638
        // If atmosphere on, we mix it in with darkening twilight. If atmosphere off, we can switch on more apruptly.
639
        // Note however that lightscape rendering does not per se depend on atmosphere on/off.
640
        // This allows for illuminated windows or light panels on spaceships. If a landscape's lightscape
641
        // contains light smog of a city, it should also be shown if atmosphere is switched off.
642
        // (Configure another landscape without light smog to avoid, or just switch off lightscape.)
UNCOV
643
        double lightscapeBrightness=0.0;
×
UNCOV
644
        const double sinSunAlt = sunPos[2];
×
UNCOV
645
        if (atmosphere->getFlagShow())
×
646
        {
647
                // light pollution layer is mixed in at -3...-8 degrees.
UNCOV
648
                if (sinSunAlt<-0.14)
×
UNCOV
649
                        lightscapeBrightness=1.0;
×
UNCOV
650
                else if (sinSunAlt<-0.05)
×
651
                        lightscapeBrightness = 1.0-(sinSunAlt+0.14)/(-0.05+0.14);
×
652
        }
653
        else
654
        {
655
                // If we have no atmosphere, we can assume windows and panels on spaceships etc. are switched on whenever the sun does not shine, i.e. when sun is blocked by landscape.
656
                lightscapeBrightness= static_cast<double>(landscape->getOpacity(sunPos));
×
657
        }
658
        landscape->setBrightness(landscapeBrightness, lightscapeBrightness);
×
659

660
        // extra colorful sunrise/sunset management.
UNCOV
661
        landscape->setTint(landscapeTint);
×
662

UNCOV
663
        messageFader.update(static_cast<int>(deltaTime*1000));
×
664
}
×
665

666
void LandscapeMgr::draw(StelCore* core)
×
667
{
668
        // For observers we never draw anything of landscape, atmosphere, cardinals.
669
        if (core->getCurrentPlanet()->getPlanetType()==Planet::isObserver)
×
UNCOV
670
                return;
×
671

672
        StelSkyDrawer* drawer=core->getSkyDrawer();
×
673

674
        // Draw the atmosphere
UNCOV
675
        if (!getFlagAtmosphereNoScatter())
×
UNCOV
676
            atmosphere->draw(core);
×
677

678
        // GZ 2016-01: When we draw the atmosphere with a low sun, it is possible that the glaring red ball is overpainted and thus invisible.
679
        // Attempt to draw the sun only here while not having drawn it by SolarSystem:
680
        //if (atmosphere->getFlagShow())
UNCOV
681
        if (drawer->getFlagDrawSunAfterAtmosphere())
×
682
        {
683
                static SolarSystem* ssys = GETSTELMODULE(SolarSystem);
×
684
                PlanetP sun=ssys->getSun();
×
UNCOV
685
                QFont font;
×
UNCOV
686
                font.setPixelSize(StelApp::getInstance().getScreenFontSize());
×
UNCOV
687
                sun->draw(core, 0, font, 1.0);
×
UNCOV
688
        }
×
689

690
        // Draw the landscape
691
        Landscape::setTransparency( getFlagLandscapeUseTransparency() ? landscapeTransparency : 0.0);
×
692

693
        if (oldLandscape)
×
694
        {
695
                oldLandscape->draw(core, flagPolyLineDisplayedOnly);
×
696
        }
UNCOV
697
        landscape->draw(core, flagPolyLineDisplayedOnly);
×
698

699
        // Draw the cardinal points
UNCOV
700
        cardinalPoints->draw(core, static_cast<double>(StelApp::getInstance().getCore()->getCurrentLocation().getLatitude()));
×
701

UNCOV
702
        if(messageFader.getInterstate())
×
703
        {
UNCOV
704
                const StelProjectorP prj = core->getProjection(StelCore::FrameEquinoxEqu);
×
705
                StelPainter painter(prj);
×
UNCOV
706
                QFont font;
×
UNCOV
707
                font.setPixelSize(16);
×
708
                painter.setFont(font);
×
UNCOV
709
                painter.setColor(1, 0, 0, messageFader.getInterstate());
×
710
                painter.drawText(83, 70, messageToShow);
×
UNCOV
711
        }
×
712
}
713

714
// Some element in drawing order behind LandscapeMgr can call this at the end of its own draw() to overdraw with the polygon line and gazetteer.
715
void LandscapeMgr::drawPolylineOnly(StelCore* core)
×
716
{
717
        // For observers we never draw anything of landscape, atmosphere, cardinals.
718
        if (core->getCurrentPlanet()->getPlanetType()==Planet::isObserver)
×
719
                return;
×
720

721
        // Draw the landscape
UNCOV
722
        if (oldLandscape && oldLandscape->hasLandscapePolygon())
×
723
                oldLandscape->draw(core, true);
×
UNCOV
724
        if (landscape->hasLandscapePolygon())
×
UNCOV
725
                landscape->draw(core, true);
×
726

727
        // Draw the cardinal points
UNCOV
728
        cardinalPoints->draw(core, static_cast<double>(StelApp::getInstance().getCore()->getCurrentLocation().getLatitude()));
×
729
}
730

731
void LandscapeMgr::createAtmosphere()
×
732
{
733
        const auto modelName=getAtmosphereModel();
×
UNCOV
734
        const auto modelConfig=modelName.toLower();
×
UNCOV
735
        bool needResetConfig=false;
×
736
        if(modelConfig==ATMOSPHERE_MODEL_CONF_VAL_PREETHAM)
×
737
        {
UNCOV
738
                loadingAtmosphere.reset(new AtmospherePreetham(skylight));
×
739
        }
740
#ifdef ENABLE_SHOWMYSKY
741
        else if(modelConfig==ATMOSPHERE_MODEL_CONF_VAL_SHOWMYSKY)
×
742
        {
743
                try
744
                {
745
                        // Clear status so that if a repeated error happens, we do emit a signal that will update the GUI.
746
                        setAtmosphereShowMySkyStatusText("");
×
UNCOV
747
                        setAtmosphereShowMySkyStoppedWithError(false);
×
748

749
                        const auto core = StelApp::getInstance().getCore();
×
UNCOV
750
                        loadingAtmosphere.reset(new AtmosphereShowMySky(core->getCurrentLocation().altitude));
×
UNCOV
751
                        if(!atmosphere)
×
752
                        {
753
                                // We're just loading the first atmosphere in the run of Stellarium. Initialize it synchronously.
754
                                while(loadingAtmosphere->isLoading())
×
755
                                        loadingAtmosphere->stepDataLoading();
×
756

757
                                setAtmosphereShowMySkyStoppedWithError(false);
×
758
                                setAtmosphereShowMySkyStatusText(q_("Loaded successfully"));
×
759
                        }
760
                        else
761
                        {
762
                                setAtmosphereShowMySkyStoppedWithError(false);
×
763
                                setAtmosphereShowMySkyStatusText(QString("%1 0% %2").arg(q_("Loading..."), qc_("done","percentage of done")));
×
764
                        }
765
                }
766
                catch(Atmosphere::InitFailure const& error)
×
767
                {
UNCOV
768
                        qInfo() << "ERROR: Failed to initialize ShowMySky atmosphere model:" << error.what();
×
UNCOV
769
                        qWarning() << "Falling back to the Preetham's model";
×
770
                        loadingAtmosphere.reset(new AtmospherePreetham(skylight));
×
771
                        needResetConfig=true;
×
772

UNCOV
773
                        setAtmosphereShowMySkyStoppedWithError(true);
×
774
                        setAtmosphereShowMySkyStatusText(error.what());
×
UNCOV
775
                }
×
776
        }
777
#endif
778
        else
779
        {
UNCOV
780
                qWarning() << "Unsupported atmosphere model" << modelName;
×
781
                loadingAtmosphere.reset(new AtmospherePreetham(skylight));
×
782
                needResetConfig=true;
×
783
        }
UNCOV
784
        if(!atmosphere)
×
785
        {
786
                // We're just loading the first atmosphere in the run of Stellarium. The atmosphere is fully loaded by this point.
UNCOV
787
                atmosphere = std::move(loadingAtmosphere);
×
788

789
                const auto conf=StelApp::getInstance().getSettings();
×
790
                setFlagAtmosphere(conf->value("landscape/flag_atmosphere", true).toBool());
×
UNCOV
791
                setAtmosphereFadeDuration(conf->value("landscape/atmosphere_fade_duration",0.5).toFloat());
×
792

UNCOV
793
                const auto drawer = StelApp::getInstance().getCore()->getSkyDrawer();
×
UNCOV
794
                setAtmosphereLightPollutionLuminance(drawer->getLightPollutionLuminance());
×
795
        }
796

797
        if(needResetConfig)
×
798
        {
799
                // We've failed to apply the setting, so reset to the fallback value
UNCOV
800
                const auto conf=StelApp::getInstance().getSettings();
×
801
                conf->setValue(ATMOSPHERE_MODEL_CONFIG_KEY, ATMOSPHERE_MODEL_CONF_VAL_PREETHAM);
×
802
        }
803

UNCOV
804
        needToRecreateAtmosphere=false;
×
805
}
×
806

UNCOV
807
void LandscapeMgr::resetToFallbackAtmosphere()
×
808
{
809
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_MODEL_CONFIG_KEY, ATMOSPHERE_MODEL_CONF_VAL_PREETHAM);
×
UNCOV
810
        atmosphere.reset();
×
UNCOV
811
        createAtmosphere();
×
812
}
×
813

UNCOV
814
void LandscapeMgr::init()
×
815
{
UNCOV
816
        QSettings* conf = StelApp::getInstance().getSettings();
×
817
        Q_ASSERT(conf);
×
818
        StelApp *app = &StelApp::getInstance();
×
819
        Q_ASSERT(app);
×
820

UNCOV
821
        landscapeCache.setMaxCost(conf->value("landscape/cache_size_mb", 100).toInt());
×
822
        qInfo() << "LandscapeMgr: initialized Cache for" << landscapeCache.maxCost() << "MB.";
×
823

824
        // SET SIMPLE PROPERTIES FIRST, before loading the landscape (Loading may already make use of them! GH#1237)
825
        setFlagLandscapeSetsLocation(conf->value("landscape/flag_landscape_sets_location",false).toBool());
×
826
        setFlagLandscapeAutoSelection(conf->value("viewing/flag_landscape_autoselection", false).toBool());
×
827
        setFlagEnvironmentAutoEnable(conf->value("viewing/flag_environment_auto_enable",true).toBool());
×
828
        // Set minimal brightness for landscape. This feature has been added for folks which say "landscape is super dark, please add light". --AW
829
        setDefaultMinimalBrightness(conf->value("landscape/minimal_brightness", 0.01).toDouble());
×
830
        setFlagLandscapeUseMinimalBrightness(conf->value("landscape/flag_minimal_brightness", false).toBool());
×
UNCOV
831
        setFlagLandscapeSetsMinimalBrightness(conf->value("landscape/flag_landscape_sets_minimal_brightness",false).toBool());
×
832

833
        const auto var = conf->value(ATMOSPHERE_MODEL_PATH_CONFIG_KEY);
×
834
        if(!var.isValid())
×
835
                conf->setValue(ATMOSPHERE_MODEL_PATH_CONFIG_KEY, getDefaultAtmosphereModelPath());
×
836

837
        createAtmosphere();
×
838
        // Put the atmosphere's Skylight under the StelProperty system (simpler and more consistent GUI)
839
        StelApp::getInstance().getStelPropertyManager()->registerObject(&skylight);
×
840

841
        defaultLandscapeID = conf->value("init_location/landscape_name").toString();
×
842

843
        // We must make sure to allow auto location or command-line location even if landscape usually should set location.
UNCOV
844
        StelCore *core = StelApp::getInstance().getCore();
×
845
        const bool setLocationFromIPorCLI=((conf->value("init_location/location", "auto").toString() == "auto") || (core->getCurrentLocation().state=="CLI"));
×
UNCOV
846
        const bool shouldThenSetLocation=getFlagLandscapeSetsLocation();
×
847
        if (setLocationFromIPorCLI) setFlagLandscapeSetsLocation(false);
×
UNCOV
848
        setCurrentLandscapeID(defaultLandscapeID);
×
849
        setFlagLandscapeSetsLocation(shouldThenSetLocation);
×
UNCOV
850
        setFlagUseLightPollutionFromDatabase(conf->value("viewing/flag_light_pollution_database", false).toBool());
×
UNCOV
851
        setFlagLandscape(conf->value("landscape/flag_landscape", conf->value("landscape/flag_ground", true).toBool()).toBool());
×
852
        setFlagFog(conf->value("landscape/flag_fog",true).toBool());
×
853
        setFlagIllumination(conf->value("landscape/flag_enable_illumination_layer", true).toBool());
×
854
        setFlagLabels(conf->value("landscape/flag_enable_labels", true).toBool());
×
855
        setFlagPolyLineOnlyDisplayed(conf->value("landscape/flag_polyline_only", false).toBool());
×
856
        setPolyLineThickness(conf->value("landscape/polyline_thickness", 1).toInt());
×
857
        setPolyLineColor(Vec3f(conf->value("landscape/polyline_color", "1.0,0.0,0.0").toString()));
×
858
        setLabelFontSize(conf->value("landscape/label_font_size", 18).toInt());
×
859
        setLabelColor(Vec3f(conf->value("landscape/label_color", "0.2,0.8,0.2").toString()));
×
860
        setLabelAngle(conf->value("landscape/label_angle", 45).toInt());
×
861

862
        setFlagLandscapeUseTransparency(conf->value("landscape/flag_transparency", false).toBool());
×
863
        setLandscapeTransparency(conf->value("landscape/transparency", 0.5).toDouble());
×
864

865
        cardinalPoints = new Cardinals();
×
866
        cardinalPoints->setFlagShow4WCRLabels(conf->value("viewing/flag_cardinal_points", true).toBool());
×
867
        cardinalPoints->setFlagShow8WCRLabels(conf->value("viewing/flag_ordinal_points", true).toBool());
×
868
        cardinalPoints->setFlagShow16WCRLabels(conf->value("viewing/flag_16wcr_points", false).toBool());
×
UNCOV
869
        cardinalPoints->setFlagShow32WCRLabels(conf->value("viewing/flag_32wcr_points", false).toBool());
×
870
        // Load colors from config file
871
        QString defaultColor = conf->value("color/default_color").toString();
×
UNCOV
872
        setColorCardinalPoints(Vec3f(conf->value("color/cardinal_color", defaultColor).toString()));
×
873

874
        currentPlanetName = app->getCore()->getCurrentLocation().planetName;
×
875
        //Bortle scale is managed by SkyDrawer
876
        StelSkyDrawer* drawer = app->getCore()->getSkyDrawer();
×
877
        Q_ASSERT(drawer);
×
UNCOV
878
        setAtmosphereLightPollutionLuminance(drawer->getLightPollutionLuminance());
×
879
        connect(app->getCore(), SIGNAL(locationChanged(StelLocation)), this, SLOT(onLocationChanged(StelLocation)));
×
880
        connect(app->getCore(), SIGNAL(targetLocationChanged(const StelLocation&, const QString&)), this, SLOT(onTargetLocationChanged(const StelLocation&, const QString&)));
×
UNCOV
881
        connect(drawer, &StelSkyDrawer::lightPollutionLuminanceChanged, this, &LandscapeMgr::setAtmosphereLightPollutionLuminance);
×
882
        connect(app, SIGNAL(languageChanged()), this, SLOT(updateI18n()));
×
883

884
        QString displayGroup = N_("Display Options");
×
885
        addAction("actionShow_Atmosphere", displayGroup, N_("Atmosphere"), "atmosphereDisplayed", "A");
×
886
        addAction("actionShow_Fog", displayGroup, N_("Fog"), "fogDisplayed", "F");
×
887
        addAction("actionShow_Cardinal_Points", displayGroup, N_("Cardinal points"), "cardinalPointsDisplayed", "Q");
×
888
        addAction("actionShow_Intercardinal_Points", displayGroup, N_("Ordinal (Intercardinal) points"), "ordinalPointsDisplayed");
×
889
        addAction("actionShow_Secondary_Intercardinal_Points", displayGroup, N_("Secondary Intercardinal points"), "ordinal16WRPointsDisplayed");
×
890
        addAction("actionShow_Tertiary_Intercardinal_Points", displayGroup, N_("Tertiary Intercardinal points"), "ordinal32WRPointsDisplayed");
×
UNCOV
891
        addAction("actionShow_Ground", displayGroup, N_("Ground"), "landscapeDisplayed", "G");
×
892
        addAction("actionShow_LandscapeIllumination", displayGroup, N_("Landscape illumination"), "illuminationDisplayed", "Shift+G");
×
893
        addAction("actionShow_LandscapeLabels", displayGroup, N_("Landscape labels"), "labelsDisplayed", "Ctrl+Shift+G");
×
894
        addAction("actionShow_LightPollutionFromDatabase", displayGroup, N_("Light pollution data from locations database"), "flagUseLightPollutionFromDatabase");
×
895
        // Details: https://github.com/Stellarium/stellarium/issues/171
896
        addAction("actionShow_LightPollutionIncrease", displayGroup, N_("Increase light pollution"), "increaseLightPollution()");
×
897
        addAction("actionShow_LightPollutionReduce", displayGroup, N_("Reduce light pollution"), "reduceLightPollution()");
×
898
        addAction("actionShow_LightPollutionCyclicChange", displayGroup, N_("Cyclic change in light pollution"), "cyclicChangeLightPollution()");
×
899
}
×
900

901
bool LandscapeMgr::setCurrentLandscapeID(const QString& id, const double changeLocationDuration)
×
902
{
UNCOV
903
        if (id.isEmpty())
×
904
                return false;
×
905

906
        //prevent unnecessary changes/file access
907
        if(id==currentLandscapeID)
×
UNCOV
908
                return false;
×
909

UNCOV
910
        if (!getAllLandscapeIDs().contains(id))
×
911
        {
912
                qDebug() << "LandscapeMgr::setCurrentLandscapeID: unknown landscape" << id << ", using 'zero'";
×
UNCOV
913
                return setCurrentLandscapeID("zero", changeLocationDuration);
×
914
        }
915

916
        Landscape* newLandscape;
917

918
        // There is a slight chance that we switch back to oldLandscape while oldLandscape is still fading away.
919
        // in this case it is not yet stored in cache, but obviously available. So we just swap places.
920
        if (oldLandscape && oldLandscape->getId()==id)
×
921
        {
UNCOV
922
                newLandscape=oldLandscape;
×
923
        }
924
        else
925
        {
926
                // We want to lookup the landscape ID (dir) from the name.
UNCOV
927
                newLandscape= landscapeCache.take(id);
×
928

UNCOV
929
                if (newLandscape)
×
930
                {
931
#ifndef NDEBUG
UNCOV
932
                        qDebug() << "LandscapeMgr::setCurrentLandscapeID():: taken " << id << "from cache...";
×
UNCOV
933
                        qDebug() << ".-->LandscapeMgr::setCurrentLandscapeID(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
934
#endif
935
                }
936
                else
937
                {
938
#ifndef NDEBUG
UNCOV
939
                        qDebug() << "LandscapeMgr::setCurrentLandscapeID: Loading from file:" << id ;
×
940
#endif
941
                        newLandscape = createFromFile(StelFileMgr::findFile("landscapes/" + id + "/landscape.ini"), id);
×
942
                }
943

UNCOV
944
                if (!newLandscape)
×
945
                {
UNCOV
946
                        qWarning() << "ERROR while loading landscape " << "landscapes/" + id + "/landscape.ini";
×
947
                        return false;
×
948
                }
949
        }
950

951
        // Keep current landscape for a while, while new landscape fades in!
952
        // This prevents subhorizon sun or grid becoming briefly visible.
UNCOV
953
        if (landscape)
×
954
        {
955
                // Copy display parameters from previous landscape to new one.
UNCOV
956
                newLandscape->setFlagShow(landscape->getFlagShow());
×
UNCOV
957
                newLandscape->setFlagShowFog(landscape->getFlagShowFog());
×
958

959
                // If we have an oldLandscape that is not just swapped back, put that into cache.
UNCOV
960
                if (oldLandscape && oldLandscape!=newLandscape)
×
961
                {
962
#ifndef NDEBUG
UNCOV
963
                        qDebug() << "LandscapeMgr::setCurrent: moving oldLandscape " << oldLandscape->getId() << "to Cache. Cost:" << oldLandscape->getMemorySize()/(1024*1024)+1;
×
964
#endif
965
                        landscapeCache.insert(oldLandscape->getId(), oldLandscape, oldLandscape->getMemorySize()/(1024*1024)+1);
×
966
#ifndef NDEBUG
UNCOV
967
                        qDebug() << "-->LandscapeMgr::setCurrentLandscapeId(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
968
#endif
969
                }
UNCOV
970
                oldLandscape = landscape; // keep old while transitioning!
×
971
        }
UNCOV
972
        landscape=newLandscape;
×
973
        currentLandscapeID = id;
×
974

975
        if (getFlagLandscapeSetsLocation() && landscape->hasLocation())
×
976
        {
UNCOV
977
                StelCore *core = StelApp::getInstance().getCore();
×
978
                core->moveObserverTo(landscape->getLocation(), changeLocationDuration, changeLocationDuration, id);
×
UNCOV
979
                StelSkyDrawer* drawer=core->getSkyDrawer();
×
980

981
                if (landscape->getLocation().ianaTimeZone.length())
×
982
                {
983
                        core->setCurrentTimeZone(landscape->getLocation().ianaTimeZone);
×
984
                }
985
                if (landscape->getDefaultFogSetting() >-1)
×
986
                {
987
                        setFlagFog(static_cast<bool>(landscape->getDefaultFogSetting()));
×
UNCOV
988
                        landscape->setFlagShowFog(static_cast<bool>(landscape->getDefaultFogSetting()));
×
989
                }
UNCOV
990
                if (landscape->getDefaultLightPollutionLuminance().isValid())
×
991
                {
UNCOV
992
                        drawer->setLightPollutionLuminance(landscape->getDefaultLightPollutionLuminance().toFloat());
×
993
                }
UNCOV
994
                if (landscape->getDefaultAtmosphericExtinction() >= 0.0)
×
995
                {
996
                        drawer->setExtinctionCoefficient(landscape->getDefaultAtmosphericExtinction());
×
997
                }
998
                if (landscape->getDefaultAtmosphericTemperature() > -273.15)
×
999
                {
1000
                        drawer->setAtmosphereTemperature(landscape->getDefaultAtmosphericTemperature());
×
1001
                }
1002
                if (landscape->getDefaultAtmosphericPressure() >= 0.0)
×
1003
                {
1004
                        drawer->setAtmospherePressure(landscape->getDefaultAtmosphericPressure());
×
1005
                }
1006
                else if (landscape->getDefaultAtmosphericPressure() < 0.0 && landscape->getDefaultAtmosphericPressure() > -1.5)
×
1007
                {
1008
                        // compute standard pressure for standard atmosphere in given altitude if landscape.ini coded as atmospheric_pressure=-1
1009
                        // International altitude formula found in Wikipedia.
1010
                        double alt=landscape->getLocation().altitude;
×
UNCOV
1011
                        double p=1013.25*std::pow(1-(0.0065*alt)/288.15, 5.255);
×
1012
                        drawer->setAtmospherePressure(p);
×
1013
                }
1014
        }
1015

UNCOV
1016
        emit currentLandscapeChanged(currentLandscapeID,getCurrentLandscapeName());
×
1017

1018
        // else qDebug() << "Will not set new location; Landscape location: planet: " << landscape->getLocation().planetName << "name: " << landscape->getLocation().name;
1019
        return true;
×
1020
}
1021

UNCOV
1022
bool LandscapeMgr::setCurrentLandscapeName(const QString& name, const double changeLocationDuration)
×
1023
{
1024
        if (name.isEmpty())
×
UNCOV
1025
                return false;
×
1026
        
1027
        QMap<QString,QString> nameToDirMap = getNameToDirMap();
×
UNCOV
1028
        if (nameToDirMap.find(name)!=nameToDirMap.end())
×
1029
        {
1030
                //qDebug() << "Resolving " << name << "as" << nameToDirMap[name];
UNCOV
1031
                return setCurrentLandscapeID(nameToDirMap[name], changeLocationDuration);
×
1032
        }
1033
        // Legacy mess-up: e.g. Scenery3D calls name but should mean ID.
UNCOV
1034
        else if (!setCurrentLandscapeID(name, changeLocationDuration))
×
1035
        {
1036
                qWarning() << "Can't find a landscape with name=" << name << StelUtils::getEndLineChar();
×
UNCOV
1037
                return false;
×
1038
        }
1039
        qInfo().noquote() << "Loading landscapeID" << name;
×
UNCOV
1040
        return true;
×
UNCOV
1041
}
×
1042

1043
// Load a landscape into cache.
1044
// @param id the ID of a landscape
1045
// @param replace true if existing landscape entry should be replaced (useful during development to reload after edit)
1046
// @return false if landscape could not be found, or existed already and replace was false.
1047
bool LandscapeMgr::precacheLandscape(const QString& id, const bool replace)
×
1048
{
1049
        if (landscapeCache.contains(id) && (!replace))
×
UNCOV
1050
                return false;
×
1051

UNCOV
1052
        Landscape* newLandscape = createFromFile(StelFileMgr::findFile("landscapes/" + id + "/landscape.ini"), id);
×
UNCOV
1053
        if (!newLandscape)
×
1054
        {
1055
                qWarning() << "ERROR while preloading landscape " << "landscapes/" + id + "/landscape.ini";
×
UNCOV
1056
                return false;
×
1057
        }
1058

UNCOV
1059
        bool res=landscapeCache.insert(id, newLandscape, newLandscape->getMemorySize()/(1024*1024)+1);
×
1060
#ifndef NDEBUG
1061
        if (res)
×
1062
        {
1063
                qDebug() << "LandscapeMgr::precacheLandscape(): Successfully added landscape with ID " << id << "to cache";
×
1064
        }
UNCOV
1065
        qDebug() << "LandscapeMgr::precacheLandscape(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
1066
#endif
1067
        return res;
×
1068
}
1069

1070
// Remove a landscape from the cache of loaded landscapes.
1071
// @param id the ID of a landscape
1072
// @return false if landscape could not be found
1073
bool LandscapeMgr::removeCachedLandscape(const QString& id)
×
1074
{
1075
        bool res= landscapeCache.remove(id);
×
1076
#ifndef NDEBUG
UNCOV
1077
        qDebug() << "LandscapeMgr::removeCachedLandscape(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
1078
#endif
UNCOV
1079
        return res;
×
1080
}
1081

1082

1083
// Change the default landscape to the landscape with the ID specified.
UNCOV
1084
bool LandscapeMgr::setDefaultLandscapeID(const QString& id)
×
1085
{
UNCOV
1086
        if (id.isEmpty())
×
1087
                return false;
×
UNCOV
1088
        defaultLandscapeID = id;
×
UNCOV
1089
        QSettings* conf = StelApp::getInstance().getSettings();
×
UNCOV
1090
        conf->setValue("init_location/landscape_name", id);
×
UNCOV
1091
        emit defaultLandscapeChanged(id);
×
1092
        return true;
×
1093
}
1094

1095
void LandscapeMgr::updateI18n()
×
1096
{
1097
        // Translate all labels with the new language
1098
        if (cardinalPoints) cardinalPoints->updateI18n();
×
1099
        landscape->loadLabels(getCurrentLandscapeID());
×
1100
}
×
1101

UNCOV
1102
void LandscapeMgr::setFlagLandscape(const bool displayed)
×
1103
{
UNCOV
1104
        if (oldLandscape && !displayed)
×
UNCOV
1105
                oldLandscape->setFlagShow(false);
×
1106
        if(landscape->getFlagShow() != displayed) {
×
1107
                landscape->setFlagShow(displayed);
×
1108
                emit landscapeDisplayedChanged(displayed);
×
1109
        }
1110
        StelApp::immediateSave("landscape/flag_landscape", displayed);
×
UNCOV
1111
}
×
1112

1113
bool LandscapeMgr::getFlagLandscape() const
×
1114
{
1115
        return landscape->getFlagShow();
×
1116
}
1117

1118
bool LandscapeMgr::getIsLandscapeFullyVisible() const
×
1119
{
UNCOV
1120
        return landscape->getIsFullyVisible();
×
1121
}
1122

1123
double LandscapeMgr::getLandscapeSinMinAltitudeLimit() const
×
1124
{
UNCOV
1125
        if (flagLandscapeUseTransparency && landscapeTransparency>0.)
×
1126
                return -1.;
×
1127
        else
1128
                return landscape->getSinMinAltitudeLimit();
×
1129
}
1130

1131
bool LandscapeMgr::getFlagUseLightPollutionFromDatabase() const
×
1132
{
1133
        return flagLightPollutionFromDatabase;
×
1134
}
1135

1136
void LandscapeMgr::setFlagUseLightPollutionFromDatabase(const bool usage)
×
1137
{
UNCOV
1138
        if (flagLightPollutionFromDatabase != usage)
×
1139
        {
UNCOV
1140
                flagLightPollutionFromDatabase = usage;
×
1141
                StelApp::immediateSave("viewing/flag_light_pollution_database", usage);
×
1142

UNCOV
1143
                StelCore* core = StelApp::getInstance().getCore();
×
1144

1145
                //this was previously logic in ViewDialog, but should really be on a non-GUI layer
1146
                if (usage)
×
1147
                {
1148
                        StelLocation loc = core->getCurrentLocation();
×
1149
                        onLocationChanged(loc);
×
UNCOV
1150
                }
×
1151

UNCOV
1152
                emit flagUseLightPollutionFromDatabaseChanged(usage);
×
1153
        }
1154
}
×
1155

1156
void LandscapeMgr::onLocationChanged(const StelLocation &loc)
×
1157
{
1158
        if(flagLightPollutionFromDatabase)
×
1159
        {
1160
                //this was previously logic in ViewDialog, but should really be on a non-GUI layer
UNCOV
1161
                StelCore* core = StelApp::getInstance().getCore();
×
1162
                float lum=0.; // location not on Earth...
×
UNCOV
1163
                if (loc.planetName.contains("Earth"))
×
1164
                {
UNCOV
1165
                        if(loc.lightPollutionLuminance.isValid())
×
1166
                                lum = loc.lightPollutionLuminance.toFloat();
×
1167
                        else // ...or it is an observatory, or it is an unknown location
UNCOV
1168
                                lum = loc.DEFAULT_LIGHT_POLLUTION_LUMINANCE;
×
1169
                }
1170
                core->getSkyDrawer()->setLightPollutionLuminance(lum);
×
1171
        }
UNCOV
1172
}
×
1173

1174
// Load landscapeID, but do not load its associated location.
1175
// If landscapeID is empty but flagLandscapeAutoSelection is true, load a location fitting to loc's planet.
1176
void LandscapeMgr::onTargetLocationChanged(const StelLocation &loc, const QString& landscapeID)
×
1177
{
1178
        //qDebug() << "LandscapeMgr::onTargetLocationChanged:" << loc.serializeToLine().replace('\t', '|') << "Landscape requested:" << landscapeID;
UNCOV
1179
        if (!landscapeID.isEmpty() && getAllLandscapeIDs().contains(landscapeID))
×
1180
        {
UNCOV
1181
                const bool landscapeSetsLocation = getFlagLandscapeSetsLocation();
×
UNCOV
1182
                setFlagLandscapeSetsLocation(false);
×
UNCOV
1183
                setCurrentLandscapeID(landscapeID);
×
1184
                setFlagLandscapeSetsLocation(landscapeSetsLocation);
×
1185
        }
UNCOV
1186
        else if(landscapeID.startsWith("ZeroColor("))
×
1187
        {
1188
                // Load a zero landscape and recolor it.
1189
                // This can happen when clicking on the map. The point on the map can be sampled for color (e.g., desert, greengrass, ocean blue, polar white, ...)
1190
                const bool landscapeSetsLocation = getFlagLandscapeSetsLocation();
×
1191
                setFlagLandscapeSetsLocation(false);
×
1192
                setCurrentLandscapeID("zero");
×
UNCOV
1193
                Vec3f color(0.3);
×
1194
                static const QRegularExpression zeroColor("^ZeroColor\\(([0-9].[0-9]+,[0-9].[0-9]+,[0-9].[0-9]+)\\)$");
×
UNCOV
1195
                QRegularExpressionMatch match=zeroColor.match(landscapeID);
×
UNCOV
1196
                if (match.hasMatch())
×
UNCOV
1197
                        color=Vec3f(match.captured(1));
×
1198
                else
1199
                        qDebug() << "Cannot extract color from landscapeID" << landscapeID;
×
1200
                LandscapePolygonal *l=static_cast<LandscapePolygonal*>(landscape);
×
1201
                l->setGroundColor(color);
×
1202
                setFlagLandscapeSetsLocation(landscapeSetsLocation);
×
1203
        }
×
1204
        else if (flagLandscapeAutoSelection && (loc.planetName != currentPlanetName))
×
1205
        {
1206
                //qDebug() << "landscapeID empty. Try planet name" << loc.planetName << "or zero";
1207
                // If we have a landscape for selected planet then set it, otherwise use zero horizon landscape
1208
                const bool landscapeSetsLocation = getFlagLandscapeSetsLocation();
×
1209
                setFlagLandscapeSetsLocation(false);
×
1210
                if (getAllLandscapeNames().indexOf(loc.planetName)>0)
×
1211
                        setCurrentLandscapeName(loc.planetName);
×
1212
                else
UNCOV
1213
                        setCurrentLandscapeID("zero");
×
UNCOV
1214
                setFlagLandscapeSetsLocation(landscapeSetsLocation);
×
1215
        }
1216

1217
        if (loc.role==QChar('o')) // observer?
×
1218
        {
1219
                if (flagEnvironmentAutoEnabling)
×
1220
                {
1221
                        setFlagAtmosphere(false);
×
1222
                        setFlagFog(false);
×
UNCOV
1223
                        setFlagLandscape(false);
×
UNCOV
1224
                        setFlagCardinalPoints(false); // suppresses all
×
1225
                }
1226
        }
1227
        else
1228
        {
1229
                SolarSystem* ssystem = static_cast<SolarSystem*>(StelApp::getInstance().getModuleMgr().getModule("SolarSystem"));
×
1230
                PlanetP pl = ssystem->searchByEnglishName(loc.planetName);
×
1231
                if (pl && flagEnvironmentAutoEnabling && currentPlanetName!=loc.planetName)
×
1232
                {
UNCOV
1233
                        QSettings* conf = StelApp::getInstance().getSettings();
×
UNCOV
1234
                        setFlagAtmosphere(pl->hasAtmosphere() && conf->value("landscape/flag_atmosphere", true).toBool());
×
UNCOV
1235
                        setFlagFog(pl->hasAtmosphere() && conf->value("landscape/flag_fog", true).toBool());
×
UNCOV
1236
                        setFlagLandscape(conf->value("landscape/flag_landscape", true).toBool());
×
1237
                        setFlagCardinalPoints(conf->value("viewing/flag_cardinal_points", true).toBool());
×
1238
                        setFlagOrdinalPoints(conf->value("viewing/flag_ordinal_points", true).toBool());
×
1239
                        setFlagOrdinal16WRPoints(conf->value("viewing/flag_16wcr_points", false).toBool());
×
UNCOV
1240
                        setFlagOrdinal32WRPoints(conf->value("viewing/flag_32wcr_points", false).toBool());
×
1241
                }
1242
        }
×
1243
        currentPlanetName = loc.planetName;
×
1244
        //qDebug() << "LandscapeMgr::onTargetLocationChanged done" ;
1245
}
×
1246

1247
void LandscapeMgr::setFlagFog(const bool displayed)
×
1248
{
UNCOV
1249
        if (landscape->getFlagShowFog() != displayed) {
×
1250
                landscape->setFlagShowFog(displayed);
×
1251
                StelApp::immediateSave("landscape/flag_fog", displayed);
×
UNCOV
1252
                emit fogDisplayedChanged(displayed);
×
1253
        }
UNCOV
1254
}
×
1255

UNCOV
1256
bool LandscapeMgr::getFlagFog() const
×
1257
{
1258
        return landscape->getFlagShowFog();
×
1259
}
1260

UNCOV
1261
void LandscapeMgr::setFlagIllumination(const bool displayed)
×
1262
{
UNCOV
1263
        if (Landscape::getFlagShowIllumination() != displayed) {
×
1264
                Landscape::setFlagShowIllumination(displayed);
×
UNCOV
1265
                StelApp::immediateSave("landscape/flag_enable_illumination_layer", displayed);
×
1266
                emit illuminationDisplayedChanged(displayed);
×
1267
        }
UNCOV
1268
}
×
1269

UNCOV
1270
bool LandscapeMgr::getFlagIllumination() const
×
1271
{
1272
        return landscape->getFlagShowIllumination();
×
1273
}
1274

UNCOV
1275
void LandscapeMgr::setLandscapeTransparency(const double f)
×
1276
{
UNCOV
1277
        landscapeTransparency = f;
×
1278
        StelApp::immediateSave("landscape/transparency", f);
×
UNCOV
1279
        emit landscapeTransparencyChanged(f);
×
1280
}
×
1281

UNCOV
1282
double LandscapeMgr::getLandscapeTransparency() const
×
1283
{
UNCOV
1284
        return landscapeTransparency;
×
1285
}
1286

1287
// Return the value of the flag determining if a transparency should be used.
1288
bool LandscapeMgr::getFlagLandscapeUseTransparency() const
×
1289
{
1290
        return flagLandscapeUseTransparency;
×
1291
}
1292
// Set the value of the flag determining if a transparency should be used.
UNCOV
1293
void LandscapeMgr::setFlagLandscapeUseTransparency(bool b)
×
1294
{
UNCOV
1295
        if (b!=flagLandscapeUseTransparency)
×
1296
        {
UNCOV
1297
                flagLandscapeUseTransparency=b;
×
1298
                StelApp::immediateSave("landscape/flag_transparency", b);
×
UNCOV
1299
                emit flagLandscapeUseTransparencyChanged(b);
×
1300
        }
1301
}
×
1302

1303
void LandscapeMgr::setFlagLabels(const bool displayed)
×
1304
{
1305
        if (static_cast<bool>(Landscape::labelFader) != displayed) {
×
1306
                Landscape::labelFader=displayed;
×
1307
                StelApp::immediateSave("landscape/flag_enable_labels", displayed);
×
UNCOV
1308
                emit labelsDisplayedChanged(displayed);
×
1309
        }
UNCOV
1310
}
×
1311

UNCOV
1312
bool LandscapeMgr::getFlagLabels() const
×
1313
{
1314
        return static_cast<bool>(Landscape::labelFader);
×
1315
}
1316

UNCOV
1317
void LandscapeMgr::setLabelFontSize(const int size)
×
1318
{
UNCOV
1319
        Landscape::fontSize=size;
×
1320
        StelApp::immediateSave("landscape/label_font_size", size);
×
UNCOV
1321
        emit labelFontSizeChanged(size);
×
1322
}
×
1323

UNCOV
1324
int LandscapeMgr::getLabelFontSize() const
×
1325
{
UNCOV
1326
        return Landscape::fontSize;
×
1327
}
1328

1329
void LandscapeMgr::setLabelAngle(const int angleDeg)
×
1330
{
UNCOV
1331
        Landscape::labelAngle = angleDeg;
×
1332
        StelApp::immediateSave("landscape/label_angle", angleDeg);
×
UNCOV
1333
        emit labelAngleChanged(angleDeg);
×
1334
}
×
1335

UNCOV
1336
int LandscapeMgr::getLabelAngle() const
×
1337
{
UNCOV
1338
        return Landscape::labelAngle;
×
1339
}
1340

1341
void LandscapeMgr::setLabelColor(const Vec3f& c)
×
1342
{
UNCOV
1343
        Landscape::labelColor=c;
×
1344
        emit labelColorChanged(c);
×
UNCOV
1345
}
×
1346

UNCOV
1347
Vec3f LandscapeMgr::getLabelColor() const
×
1348
{
1349
        return Landscape::labelColor;
×
1350
}
1351

1352
//! Retrieve flag for rendering polygonal line (if one is defined)
1353
bool LandscapeMgr::getFlagPolyLineOnlyDisplayed() const
×
1354
{
1355
        return flagPolyLineDisplayedOnly;
×
1356
}
1357
//! Set flag for rendering polygonal line (if one is defined)
UNCOV
1358
void LandscapeMgr::setFlagPolyLineOnlyDisplayed(bool b)
×
1359
{
UNCOV
1360
        if(b!=flagPolyLineDisplayedOnly)
×
1361
        {
UNCOV
1362
                flagPolyLineDisplayedOnly=b;
×
1363
                StelApp::immediateSave("landscape/flag_polyline_only", b);
×
UNCOV
1364
                emit flagPolyLineOnlyDisplayedChanged(b);
×
1365
        }
1366
}
×
1367

1368
//! Retrieve thickness for rendering polygonal line (if one is defined)
UNCOV
1369
int LandscapeMgr::getPolyLineThickness() const
×
1370
{
1371
        return Landscape::horizonPolygonLineThickness;
×
1372
}
1373

1374
//! Set thickness for rendering polygonal line (if one is defined)
UNCOV
1375
void LandscapeMgr::setPolyLineThickness(int thickness)
×
1376
{
1377
        Landscape::horizonPolygonLineThickness=thickness;
×
UNCOV
1378
        StelApp::immediateSave("landscape/polyline_thickness", thickness);
×
1379
        emit polyLineThicknessChanged(thickness);
×
UNCOV
1380
}
×
1381

UNCOV
1382
void LandscapeMgr::setPolyLineColor(const Vec3f& c)
×
1383
{
UNCOV
1384
        Landscape::horizonPolygonLineColor = c;
×
1385
        emit polyLineColorChanged(c);
×
1386
}
×
1387

1388
Vec3f LandscapeMgr::getPolyLineColor() const
×
1389
{
1390
        return Landscape::horizonPolygonLineColor;
×
1391
}
1392

1393
// Return the value of the flag determining if a change of landscape will update the observer location.
1394
bool LandscapeMgr::getFlagLandscapeSetsLocation() const
×
1395
{
1396
        return flagLandscapeSetsLocation;
×
1397
}
1398
// Set the value of the flag determining if a change of landscape will update the observer location.
UNCOV
1399
void LandscapeMgr::setFlagLandscapeSetsLocation(bool b)
×
1400
{
UNCOV
1401
        if(b!=flagLandscapeSetsLocation)
×
1402
        {
UNCOV
1403
                flagLandscapeSetsLocation=b;
×
1404
                StelApp::immediateSave("landscape/flag_landscape_sets_location", b);
×
UNCOV
1405
                emit flagLandscapeSetsLocationChanged(b);
×
1406
        }
1407
}
×
1408

1409
// Return the value of the flag determining if a minimal brightness should be used to keep landscape visible.
UNCOV
1410
bool LandscapeMgr::getFlagLandscapeUseMinimalBrightness() const
×
1411
{
1412
        return flagLandscapeUseMinimalBrightness;
×
1413
}
1414

1415
// Set the value of the flag determining if a minimal brightness should be used to keep landscape visible.
UNCOV
1416
void LandscapeMgr::setFlagLandscapeUseMinimalBrightness(bool b)
×
1417
{
1418
        if(b!=flagLandscapeUseMinimalBrightness)
×
1419
        {
1420
                flagLandscapeUseMinimalBrightness=b;
×
UNCOV
1421
                StelApp::immediateSave("landscape/flag_minimal_brightness", b);
×
UNCOV
1422
                emit flagLandscapeUseMinimalBrightnessChanged(b);
×
1423
        }
1424
}
×
1425

1426
// Return the value of the flag determining if the minimal brightness should be taken from landscape.ini
UNCOV
1427
bool LandscapeMgr::getFlagLandscapeSetsMinimalBrightness() const
×
1428
{
1429
        return flagLandscapeSetsMinimalBrightness;
×
1430
}
1431
// Sets the value of the flag determining if the minimal brightness should be taken from landscape.ini
1432
void LandscapeMgr::setFlagLandscapeSetsMinimalBrightness(bool b)
×
1433
{
UNCOV
1434
        if(b!=flagLandscapeSetsMinimalBrightness)
×
1435
        {
UNCOV
1436
                flagLandscapeSetsMinimalBrightness=b;
×
1437
                StelApp::immediateSave("landscape/flag_landscape_sets_minimal_brightness", b);
×
UNCOV
1438
                emit flagLandscapeSetsMinimalBrightnessChanged(b);
×
1439
        }
1440
}
×
1441

1442

UNCOV
1443
void LandscapeMgr::setFlagLandscapeAutoSelection(bool enableAutoSelect)
×
1444
{
1445
        if(enableAutoSelect != flagLandscapeAutoSelection)
×
1446
        {
UNCOV
1447
                flagLandscapeAutoSelection = enableAutoSelect;
×
1448
                StelApp::immediateSave("viewing/flag_landscape_autoselection", enableAutoSelect);
×
UNCOV
1449
                emit flagLandscapeAutoSelectionChanged(enableAutoSelect);
×
1450
        }
1451
}
×
1452

1453
bool LandscapeMgr::getFlagLandscapeAutoSelection() const
×
1454
{
1455
        return flagLandscapeAutoSelection;
×
1456
}
1457

UNCOV
1458
void LandscapeMgr::setFlagEnvironmentAutoEnable(bool b)
×
1459
{
UNCOV
1460
        if(b != flagEnvironmentAutoEnabling)
×
1461
        {
UNCOV
1462
                flagEnvironmentAutoEnabling = b;
×
1463
                StelApp::immediateSave("viewing/flag_environment_auto_enable", b);
×
UNCOV
1464
                emit setFlagEnvironmentAutoEnableChanged(b);
×
1465
        }
1466
}
×
1467

1468
bool LandscapeMgr::getFlagEnvironmentAutoEnable() const
×
1469
{
1470
        return flagEnvironmentAutoEnabling;
×
1471
}
1472

1473
// Return the minimal brightness value of the landscape
1474
double LandscapeMgr::getDefaultMinimalBrightness() const
×
1475
{
1476
        return defaultMinimalBrightness;
×
1477
}
1478
// Set the minimal brightness value of the landscape.
UNCOV
1479
void LandscapeMgr::setDefaultMinimalBrightness(const double b)
×
1480
{
UNCOV
1481
        if(fabs(b-defaultMinimalBrightness)>0.0)
×
1482
        {
UNCOV
1483
                defaultMinimalBrightness=b;
×
1484
                StelApp::immediateSave("landscape/minimal_brightness", b);
×
UNCOV
1485
                emit defaultMinimalBrightnessChanged(b);
×
1486
        }
1487
}
×
1488

1489
/*********************************************************************
1490
 Retrieve list of the names of all the available landscapes
1491
 *********************************************************************/
1492
QStringList LandscapeMgr::getAllLandscapeNames() const
×
1493
{
UNCOV
1494
        return getNameToDirMap().keys();
×
1495
}
1496

UNCOV
1497
QStringList LandscapeMgr::getAllLandscapeIDs() const
×
1498
{
UNCOV
1499
        return getNameToDirMap().values();
×
1500
}
1501

1502
QStringList LandscapeMgr::getUserLandscapeIDs() const
×
1503
{
UNCOV
1504
        QStringList result;
×
1505
        QMapIterator<QString, QString> it(getNameToDirMap());
×
UNCOV
1506
        while (it.hasNext())
×
1507
        {
UNCOV
1508
                it.next();
×
UNCOV
1509
                if(!packagedLandscapeIDs.contains(it.value()))
×
1510
                        result.append(it.value());
×
1511
        }
1512
        return result;
×
1513
}
×
1514

UNCOV
1515
QString LandscapeMgr::getCurrentLandscapeName() const
×
1516
{
1517
        return landscape->getName();
×
1518
}
1519

1520
QString LandscapeMgr::getCurrentLandscapeHtmlDescription() const
×
1521
{
UNCOV
1522
        QString desc = getDescription();
×
1523

UNCOV
1524
        QString author = landscape->getAuthorName();
×
1525

UNCOV
1526
        desc += "<p>";
×
UNCOV
1527
        if (!author.isEmpty())
×
1528
                desc += QString("<b>%1</b>: %2<br />").arg(q_("Author"), author);
×
1529

1530
        // This previously showed 0/0 for locationless landscapes!
UNCOV
1531
        if (landscape->hasLocation())
×
1532
        {
1533
                //TRANSLATORS: Unit of measure for distance - meter
1534
                QString alt = qc_("m", "distance");
×
1535

1536
                desc += QString("<b>%1</b>: %2, %3, %4 %5").arg(
×
UNCOV
1537
                                q_("Location"),
×
UNCOV
1538
                                StelUtils::radToDmsStrAdapt(static_cast<double>(landscape->getLocation().getLatitude()) *M_PI_180),
×
1539
                                StelUtils::radToDmsStrAdapt(static_cast<double>(landscape->getLocation().getLongitude()) * M_PI_180),
×
UNCOV
1540
                                QString::number(landscape->getLocation().altitude),
×
UNCOV
1541
                                alt);
×
1542

UNCOV
1543
                QString planetName = landscape->getLocation().planetName;                
×
1544
                if (!planetName.isEmpty())
×
1545
                {
1546
                        const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
×
1547
                        desc += QString(", %1").arg(trans.qtranslate(planetName, "major planet")); // TODO: Enhance the context support
×
1548
                }
1549
                desc += "<br />";
×
1550

1551
                QStringList atmosphere;
×
1552
                //atmosphere.clear(); // Huh?
1553

1554
                double pressure = landscape->getDefaultAtmosphericPressure();
×
1555
                if (pressure>0.)
×
1556
                {
1557
                        // 1 mbar = 1 hPa
1558
                        //TRANSLATORS: Unit of measure for pressure - hectopascals
1559
                        QString hPa = qc_("hPa", "pressure");
×
UNCOV
1560
                        atmosphere.append(QString("%1 %2").arg(QString::number(pressure, 'f', 1), hPa));
×
UNCOV
1561
                }
×
1562

1563
                double temperature = landscape->getDefaultAtmosphericTemperature();
×
UNCOV
1564
                if (temperature>-1000.0)
×
UNCOV
1565
                        atmosphere.append(QString("%1 %2C").arg(QString::number(temperature, 'f', 1)).arg(QChar(0x00B0)));
×
1566

1567
                double extcoeff = landscape->getDefaultAtmosphericExtinction();
×
1568
                if (extcoeff>-1.0)
×
1569
                        atmosphere.append(QString("%1: %2").arg(q_("extinction coefficient"), QString::number(extcoeff, 'f', 2)));
×
1570

1571
                if (!atmosphere.isEmpty())
×
1572
                        desc += QString("<b>%1</b>: %2<br />").arg(q_("Atmospheric conditions"), atmosphere.join(", "));
×
1573

UNCOV
1574
                const auto lightPollutionLum = landscape->getDefaultLightPollutionLuminance();
×
1575
                if (lightPollutionLum.isValid())
×
1576
                {
1577
                        const auto lum = lightPollutionLum.toFloat();
×
UNCOV
1578
                        auto scaledLum = lum;
×
1579
                        QString unit = q_("cd/m<sup>2</sup>");
×
1580
                        if(lum < 1e-6f)
×
1581
                        {
1582
                                scaledLum = lum*1e9f;
×
1583
                                unit = q_("ncd/m<sup>2</sup>");
×
1584
                        }
1585
                        else if(lum < 1e-3f)
×
1586
                        {
1587
                                scaledLum = lum*1e6f;
×
1588
                                unit = q_("&mu;cd/m<sup>2</sup>");
×
1589
                        }
1590
                        else if(lum < 1)
×
1591
                        {
UNCOV
1592
                                scaledLum = lum*1e3f;
×
1593
                                unit = q_("mcd/m<sup>2</sup>");
×
1594
                        }
1595
                        desc += q_("<b>Light pollution</b>: %1 %2 (NELM: %3; Bortle class: %4)")
×
1596
                                                .arg(scaledLum).arg(unit).arg(StelCore::luminanceToNELM(lum))
×
UNCOV
1597
                                                .arg(StelCore::luminanceToBortleScaleIndex(lum));
×
1598
                }
×
UNCOV
1599
        }        
×
1600
        return desc;
×
1601
}
×
1602

1603
//! Set flag for displaying cardinal points
1604
void LandscapeMgr::setFlagCardinalPoints(const bool displayed)
×
1605
{
1606
        if (cardinalPoints->getFlagShow4WCRLabels() != displayed)
×
1607
        {
1608
                cardinalPoints->setFlagShow4WCRLabels(displayed);
×
1609
                emit cardinalPointsDisplayedChanged(displayed);
×
1610
        }
UNCOV
1611
}
×
1612

1613
//! Get flag for displaying cardinal points
1614
bool LandscapeMgr::getFlagCardinalPoints() const
×
1615
{
1616
        return cardinalPoints->getFlagShowCardinals();
×
1617
}
1618

1619
//! Set flag for displaying ordinal points
UNCOV
1620
void LandscapeMgr::setFlagOrdinalPoints(const bool displayed)
×
1621
{
1622
        if (cardinalPoints->getFlagShow8WCRLabels() != displayed)
×
1623
        {
1624
                cardinalPoints->setFlagShow8WCRLabels(displayed);
×
UNCOV
1625
                emit ordinalPointsDisplayedChanged(displayed);
×
1626
        }
UNCOV
1627
}
×
1628

1629
//! Get flag for displaying ordinal points
1630
bool LandscapeMgr::getFlagOrdinalPoints() const
×
1631
{
1632
        return cardinalPoints->getFlagShow8WCRLabels();
×
1633
}
1634

1635
//! Set flag for displaying ordinal points
UNCOV
1636
void LandscapeMgr::setFlagOrdinal16WRPoints(const bool displayed)
×
1637
{
1638
        if (cardinalPoints->getFlagShow16WCRLabels() != displayed)
×
1639
        {
1640
                cardinalPoints->setFlagShow16WCRLabels(displayed);
×
UNCOV
1641
                emit ordinal16WRPointsDisplayedChanged(displayed);
×
1642
        }
UNCOV
1643
}
×
1644

1645
//! Get flag for displaying ordinal points
1646
bool LandscapeMgr::getFlagOrdinal16WRPoints() const
×
1647
{
1648
        return cardinalPoints->getFlagShow16WCRLabels();
×
1649
}
1650

1651
//! Set flag for displaying ordinal points
UNCOV
1652
void LandscapeMgr::setFlagOrdinal32WRPoints(const bool displayed)
×
1653
{
1654
        if (cardinalPoints->getFlagShow32WCRLabels() != displayed)
×
1655
        {
1656
                cardinalPoints->setFlagShow32WCRLabels(displayed);
×
UNCOV
1657
                emit ordinal32WRPointsDisplayedChanged(displayed);
×
1658
        }
UNCOV
1659
}
×
1660

1661
//! Get flag for displaying ordinal points
1662
bool LandscapeMgr::getFlagOrdinal32WRPoints() const
×
1663
{
1664
        return cardinalPoints->getFlagShow32WCRLabels();
×
1665
}
1666

1667
//! Set Cardinals Points color
UNCOV
1668
void LandscapeMgr::setColorCardinalPoints(const Vec3f& v)
×
1669
{
1670
        if(v != getColorCardinalPoints())
×
1671
        {
1672
                cardinalPoints->setColor(v);
×
UNCOV
1673
                emit cardinalPointsColorChanged(v);
×
1674
        }
UNCOV
1675
}
×
1676

1677
//! Get Cardinals Points color
1678
Vec3f LandscapeMgr::getColorCardinalPoints() const
×
1679
{
1680
        return cardinalPoints->getColor();
×
1681
}
1682

1683
///////////////////////////////////////////////////////////////////////////////////////
1684
// Atmosphere
1685
//! Set flag for displaying Atmosphere
1686
void LandscapeMgr::setFlagAtmosphere(const bool displayed)
×
1687
{
1688
        if (atmosphere->getFlagShow() != displayed) {
×
UNCOV
1689
                atmosphere->setFlagShow(displayed);
×
UNCOV
1690
                StelApp::getInstance().getCore()->getSkyDrawer()->setFlagHasAtmosphere(displayed);
×
UNCOV
1691
                StelApp::immediateSave("landscape/flag_atmosphere", displayed);
×
UNCOV
1692
                emit atmosphereDisplayedChanged(displayed);
×
1693
                //if (StelApp::getInstance().getSettings()->value("landscape/flag_fog", true).toBool())
1694
                //        setFlagFog(displayed); // sync of visibility of fog because this is atmospheric phenomena
1695
                // GZ This did not work as it may have been intended. Switch off fog, switch off atmosphere. Switch on atmosphere, and you have fog?
1696
                // --> Fog is only drawn in Landscape if atmosphere is switched on!
1697
        }
1698
}
×
1699

1700
void LandscapeMgr::setAtmosphereModel(const QString& model)
×
1701
{
UNCOV
1702
        const auto modelToSet = model.toLower();
×
UNCOV
1703
        const auto oldModel = getAtmosphereModel().toLower();
×
UNCOV
1704
        if(modelToSet == oldModel)
×
UNCOV
1705
                return;
×
1706

UNCOV
1707
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_MODEL_CONFIG_KEY, model);
×
1708

UNCOV
1709
        if(!(oldModel.isEmpty() && modelToSet == ATMOSPHERE_MODEL_CONF_VAL_DEFAULT))
×
1710
        {
1711
                // Can't call createAtmosphere() right now, because we likely have wrong OpenGL context (or even none).
1712
                // So just schedule it for the next draw.
1713
                needToRecreateAtmosphere=true;
×
1714
        }
1715
}
×
1716

1717
void LandscapeMgr::setAtmosphereModelPath(const QString& path)
×
1718
{
UNCOV
1719
        if(getAtmosphereModelPath()==path)
×
UNCOV
1720
                return;
×
1721

UNCOV
1722
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_MODEL_PATH_CONFIG_KEY, path);
×
1723
        setAtmosphereModel(ATMOSPHERE_MODEL_CONF_VAL_SHOWMYSKY); // This is the only relevant model for this property
×
UNCOV
1724
        needToRecreateAtmosphere=true;
×
1725

UNCOV
1726
        emit atmosphereModelPathChanged(path);
×
1727
}
1728

UNCOV
1729
void LandscapeMgr::setAtmosphereShowMySkyStoppedWithError(const bool error)
×
1730
{
1731
        if(atmosphereShowMySkyStoppedWithError == error)
×
1732
                return;
×
UNCOV
1733
        atmosphereShowMySkyStoppedWithError = error;
×
1734
        emit atmosphereStoppedWithErrorChanged(error);
×
1735
}
1736

1737
void LandscapeMgr::setAtmosphereShowMySkyStatusText(const QString& text)
×
1738
{
1739
        if(atmosphereShowMySkyStatusText == text)
×
1740
                return;
×
1741
        atmosphereShowMySkyStatusText = text;
×
1742
        emit atmosphereStatusTextChanged(text);
×
1743
}
1744

1745
void LandscapeMgr::setFlagAtmosphereZeroOrderScattering(const bool enable)
×
1746
{
1747
        atmosphereZeroOrderScatteringEnabled=enable;
×
1748
        emit flagAtmosphereZeroOrderScatteringChanged(enable);
×
1749
}
×
1750

UNCOV
1751
void LandscapeMgr::setFlagAtmosphereSingleScattering(const bool enable)
×
1752
{
1753
        atmosphereSingleScatteringEnabled=enable;
×
UNCOV
1754
        emit flagAtmosphereSingleScatteringChanged(enable);
×
1755
}
×
1756

1757
void LandscapeMgr::setFlagAtmosphereMultipleScattering(const bool enable)
×
1758
{
1759
        atmosphereMultipleScatteringEnabled=enable;
×
UNCOV
1760
        emit flagAtmosphereMultipleScatteringChanged(enable);
×
1761
}
×
1762

1763
void LandscapeMgr::setFlagAtmospherePseudoMirror(const bool enable)
×
1764
{
1765
        atmospherePseudoMirrorEnabled=enable;
×
UNCOV
1766
        emit flagAtmospherePseudoMirrorChanged(enable);
×
1767
}
×
1768

1769
void LandscapeMgr::setAtmosphereEclipseSimulationQuality(const int quality)
×
1770
{
1771
        if(getAtmosphereEclipseSimulationQuality() == quality)
×
UNCOV
1772
                return;
×
1773

1774
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_ECLIPSE_SIM_QUALITY_CONFIG_KEY, quality);
×
1775

UNCOV
1776
        emit atmosphereEclipseSimulationQualityChanged(quality);
×
1777
}
1778

1779
//! Get flag for displaying Atmosphere
1780
bool LandscapeMgr::getFlagAtmosphere() const
×
1781
{
1782
        return atmosphere->getFlagShow();
×
1783
}
1784

1785
//! Set flag for displaying Atmosphere
UNCOV
1786
void LandscapeMgr::setFlagAtmosphereNoScatter(const bool noScatter)
×
1787
{
1788
        atmosphereNoScatter=noScatter;
×
UNCOV
1789
        emit atmosphereNoScatterChanged(noScatter);
×
1790
}
×
1791

1792
//! Get flag for displaying Atmosphere
UNCOV
1793
bool LandscapeMgr::getFlagAtmosphereNoScatter() const
×
1794
{
UNCOV
1795
        return atmosphereNoScatter;
×
1796
}
1797

1798
QString LandscapeMgr::getAtmosphereModel() const
×
1799
{
UNCOV
1800
        const auto conf=StelApp::getInstance().getSettings();
×
1801
        return conf->value(ATMOSPHERE_MODEL_CONFIG_KEY, ATMOSPHERE_MODEL_CONF_VAL_DEFAULT).toString();
×
1802
}
1803

UNCOV
1804
QString LandscapeMgr::getAtmosphereModelPath() const
×
1805
{
1806
        const auto conf=StelApp::getInstance().getSettings();
×
1807

1808
        const auto var = conf->value(ATMOSPHERE_MODEL_PATH_CONFIG_KEY);
×
1809
        if(var.isValid()) return var.toString();
×
1810

UNCOV
1811
        return getDefaultAtmosphereModelPath();
×
1812
}
×
1813

1814
QString LandscapeMgr::getDefaultAtmosphereModelPath() const
×
1815
{
1816
        return QDir::toNativeSeparators(QString("%1/atmosphere/default").arg(StelFileMgr::getInstallationDir()));
×
1817
}
1818

1819
bool LandscapeMgr::getAtmosphereShowMySkyStoppedWithError() const
×
1820
{
UNCOV
1821
        return atmosphereShowMySkyStoppedWithError;
×
1822
}
1823

1824
QString LandscapeMgr::getAtmosphereShowMySkyStatusText() const
×
1825
{
UNCOV
1826
        return atmosphereShowMySkyStatusText;
×
1827
}
1828

1829
bool LandscapeMgr::getFlagAtmosphereZeroOrderScattering() const
×
1830
{
UNCOV
1831
        return atmosphereZeroOrderScatteringEnabled;
×
1832
}
1833

1834
bool LandscapeMgr::getFlagAtmosphereSingleScattering() const
×
1835
{
UNCOV
1836
        return atmosphereSingleScatteringEnabled;
×
1837
}
1838

1839
bool LandscapeMgr::getFlagAtmosphereMultipleScattering() const
×
1840
{
UNCOV
1841
        return atmosphereMultipleScatteringEnabled;
×
1842
}
1843

1844
bool LandscapeMgr::getFlagAtmospherePseudoMirror() const
×
1845
{
UNCOV
1846
        return atmospherePseudoMirrorEnabled;
×
1847
}
1848

1849
int LandscapeMgr::getAtmosphereEclipseSimulationQuality() const
×
1850
{
UNCOV
1851
        const auto conf=StelApp::getInstance().getSettings();
×
1852
        return conf->value(ATMOSPHERE_ECLIPSE_SIM_QUALITY_CONFIG_KEY, 1).toInt();
×
1853
}
1854

UNCOV
1855
float LandscapeMgr::getAtmosphereFadeIntensity() const
×
1856
{
1857
        return atmosphere->getFadeIntensity();
×
1858
}
1859

1860
//! Set atmosphere fade duration in s
UNCOV
1861
void LandscapeMgr::setAtmosphereFadeDuration(const float f)
×
1862
{
1863
        atmosphere->setFadeDuration(f);
×
UNCOV
1864
}
×
1865

1866
//! Get atmosphere fade duration in s
UNCOV
1867
float LandscapeMgr::getAtmosphereFadeDuration() const
×
1868
{
1869
        return atmosphere->getFadeDuration();
×
1870
}
1871

1872
//! Set light pollution luminance level
UNCOV
1873
void LandscapeMgr::setAtmosphereLightPollutionLuminance(const float f)
×
1874
{
1875
        atmosphere->setLightPollutionLuminance(f);
×
UNCOV
1876
}
×
1877

1878
//! Get light pollution luminance level
UNCOV
1879
float LandscapeMgr::getAtmosphereLightPollutionLuminance() const
×
1880
{
1881
        return atmosphere->getLightPollutionLuminance();
×
1882
}
1883

1884
void LandscapeMgr::setZRotation(const float d)
×
1885
{
UNCOV
1886
        if (landscape)
×
1887
                landscape->setZRotation(d);
×
UNCOV
1888
}
×
1889

UNCOV
1890
float LandscapeMgr::getLuminance() const
×
1891
{
1892
        return atmosphere->getRealDisplayIntensityFactor();
×
1893
}
1894

1895
float LandscapeMgr::getAtmosphereAverageLuminance() const
×
1896
{
UNCOV
1897
        return atmosphere->getAverageLuminance();
×
1898
}
1899

1900
// Override auto-computed luminance. Only use when you know what you are doing, and don't forget to unfreeze the average by calling this function with a negative value.
UNCOV
1901
void LandscapeMgr::setAtmosphereAverageLuminance(const float overrideLum)
×
1902
{
1903
        atmosphere->setAverageLuminance(overrideLum);
×
UNCOV
1904
}
×
1905

UNCOV
1906
Landscape* LandscapeMgr::createFromFile(const QString& landscapeFile, const QString& landscapeId)
×
1907
{
UNCOV
1908
        QSettings landscapeIni(landscapeFile, StelIniFormat);
×
1909
        QString s;
×
UNCOV
1910
        if (landscapeIni.status() != QSettings::NoError)
×
1911
        {
1912
                qWarning() << "ERROR parsing landscape.ini file: " << QDir::toNativeSeparators(landscapeFile);
×
UNCOV
1913
                s = "";
×
1914
        }
1915
        else
1916
                s = landscapeIni.value("landscape/type").toString();
×
1917

1918
        Landscape* landscape = Q_NULLPTR;
×
UNCOV
1919
        if (s=="old_style")
×
1920
                landscape = new LandscapeOldStyle();
×
1921
        else if (s=="spherical")
×
UNCOV
1922
                landscape = new LandscapeSpherical();
×
UNCOV
1923
        else if (s=="fisheye")
×
1924
                landscape = new LandscapeFisheye();
×
UNCOV
1925
        else if (s=="polygonal")
×
1926
                landscape = new LandscapePolygonal();
×
1927
        else
1928
        {
1929
                qDebug() << "Unknown landscape type: \"" << s << "\"";
×
1930

1931
                // to avoid making this a fatal error, will load as a fisheye
1932
                // if this fails, it just won't draw
1933
                landscape = new LandscapeFisheye();
×
1934
        }
1935

UNCOV
1936
        landscape->load(landscapeIni, landscapeId);
×
1937
        return landscape;
×
UNCOV
1938
}
×
1939

1940

1941
QString LandscapeMgr::nameToID(const QString& name)
×
1942
{
UNCOV
1943
        QMap<QString,QString> nameToDirMap = getNameToDirMap();
×
1944

1945
        if (nameToDirMap.find(name)!=nameToDirMap.end())
×
1946
        {
UNCOV
1947
                Q_ASSERT(0);
×
1948
                return "error";
1949
        }
1950
        else
1951
        {
UNCOV
1952
                return nameToDirMap[name];
×
1953
        }
UNCOV
1954
}
×
1955

1956
/****************************************************************************
1957
 get a map of landscape names (from landscape.ini name field) to ID (dir name)
1958
 ****************************************************************************/
UNCOV
1959
QMap<QString,QString> LandscapeMgr::getNameToDirMap()
×
1960
{
UNCOV
1961
        QMap<QString,QString> result;
×
1962
        const QSet<QString> landscapeDirs = StelFileMgr::listContents("landscapes",StelFileMgr::Directory);
×
1963

UNCOV
1964
        for (const auto& dir : landscapeDirs)
×
1965
        {
UNCOV
1966
                QString fName = StelFileMgr::findFile("landscapes/" + dir + "/landscape.ini");
×
1967
                if (!fName.isEmpty())
×
1968
                {
1969
                        QSettings landscapeIni(fName, StelIniFormat);
×
1970
                        QString k = landscapeIni.value("landscape/name").toString();
×
UNCOV
1971
                        result[k] = dir;
×
1972
                }
×
UNCOV
1973
        }
×
1974
        return result;
×
1975
}
×
1976

1977
QString LandscapeMgr::installLandscapeFromArchive(QString sourceFilePath, const bool display, const bool toMainDirectory)
×
1978
{
1979
        Q_UNUSED(toMainDirectory)
1980
        if (!QFile::exists(sourceFilePath))
×
1981
        {
1982
                qDebug() << "LandscapeMgr: File does not exist:" << QDir::toNativeSeparators(sourceFilePath);
×
1983
                emit errorUnableToOpen(sourceFilePath);
×
UNCOV
1984
                return QString();
×
1985
        }
1986

UNCOV
1987
        QDir parentDestinationDir;
×
1988
        parentDestinationDir.setPath(StelFileMgr::getUserDir());
×
1989

1990
        if (!parentDestinationDir.exists("landscapes"))
×
1991
        {
1992
                //qDebug() << "LandscapeMgr: No 'landscapes' subdirectory exists in" << parentDestinationDir.absolutePath();
UNCOV
1993
                if (!parentDestinationDir.mkdir("landscapes"))
×
1994
                {
1995
                        qWarning() << "LandscapeMgr: Unable to install landscape: Unable to create sub-directory 'landscapes' in" << QDir::toNativeSeparators(parentDestinationDir.absolutePath());
×
1996
                        emit errorUnableToOpen(QDir::cleanPath(parentDestinationDir.filePath("landscapes")));//parentDestinationDir.absolutePath()
×
UNCOV
1997
                        return QString();
×
1998
                }
1999
        }
UNCOV
2000
        QDir destinationDir (parentDestinationDir.absoluteFilePath("landscapes"));
×
2001

2002
        #if USE_BUNDLED_QTCOMPRESS
2003
        Stel::QZipReader reader(sourceFilePath);
×
2004
        if (reader.status() != Stel::QZipReader::NoError)
×
2005
        #else
2006
        QZipReader reader(sourceFilePath);
2007
        if (reader.status() != QZipReader::NoError)
2008
        #endif
2009
        {
UNCOV
2010
                qWarning() << "LandscapeMgr: Unable to open as a ZIP archive:" << QDir::toNativeSeparators(sourceFilePath);
×
2011
                emit errorNotArchive();
×
2012
                return QString();
×
2013
        }
2014

2015
        //Detect top directory
UNCOV
2016
        QString topDir, iniPath;
×
UNCOV
2017
        const auto infoList = reader.fileInfoList();
×
2018
        for (const auto& info : infoList)
×
2019
        {
2020
                QFileInfo fileInfo(info.filePath);
×
UNCOV
2021
                if (fileInfo.fileName() == "landscape.ini")
×
2022
                {
UNCOV
2023
                        iniPath = info.filePath;
×
2024
                        topDir = fileInfo.dir().path();
×
2025
                        break;
×
2026
                }
UNCOV
2027
        }
×
2028
        if (topDir.isEmpty())
×
2029
        {
UNCOV
2030
                qWarning() << "LandscapeMgr: Unable to install landscape. There is no directory that contains a 'landscape.ini' file in the source archive.";
×
2031
                emit errorNotArchive();
×
2032
                return QString();
×
2033
        }
2034
        //Determine the landscape's identifier
2035
        QString landscapeID = QFileInfo(topDir).fileName();
×
2036
        if (landscapeID.length() < 2)
×
2037
        {
2038
                // If the archive has no top level directory
2039
                // use the first 65 characters of its file name for an identifier
2040
                QFileInfo sourceFileInfo(sourceFilePath);
×
UNCOV
2041
                landscapeID = sourceFileInfo.baseName().left(65);
×
UNCOV
2042
        }
×
2043

2044
        //Check for duplicate IDs
UNCOV
2045
        if (getAllLandscapeIDs().contains(landscapeID))
×
2046
        {
UNCOV
2047
                qWarning() << "LandscapeMgr: Unable to install landscape. A landscape with the ID" << landscapeID << "already exists.";
×
2048
                emit errorNotUnique(landscapeID);
×
2049
                return QString();
×
2050
        }
2051

2052
        //Read the .ini file and check if the landscape name is unique
2053
        QTemporaryFile tempLandscapeIni("landscapeXXXXXX.ini");
×
UNCOV
2054
        if (tempLandscapeIni.open())
×
2055
        {
2056
                QByteArray iniData = reader.fileData(iniPath);
×
2057
                tempLandscapeIni.write(iniData);
×
UNCOV
2058
                tempLandscapeIni.close();
×
UNCOV
2059
                QSettings confLandscapeIni(tempLandscapeIni.fileName(), StelIniFormat);
×
UNCOV
2060
                QString landscapeName = confLandscapeIni.value("landscape/name").toString();
×
2061
                if (getAllLandscapeNames().contains(landscapeName))
×
2062
                {
UNCOV
2063
                        qWarning() << "LandscapeMgr: Unable to install landscape. There is already a landscape named" << landscapeName;
×
2064
                        emit errorNotUnique(landscapeName);
×
2065
                        return QString();
×
2066
                }
2067
        }
×
2068

2069
        //Copy the landscape directory to the target
2070
        //This case already has been handled - and commented out - above. :)
2071
        if(destinationDir.exists(landscapeID))
×
2072
        {
2073
                qWarning() << "LandscapeMgr: A subdirectory" << landscapeID << "already exists in" << QDir::toNativeSeparators(destinationDir.absolutePath()) << "Its contents may be overwritten.";
×
2074
        }
2075
        else if(!destinationDir.mkdir(landscapeID))
×
2076
        {
UNCOV
2077
                qWarning() << "LandscapeMgr: Unable to install landscape. Unable to create" << landscapeID << "directory in" << QDir::toNativeSeparators(destinationDir.absolutePath());
×
UNCOV
2078
                emit errorUnableToOpen(QDir::cleanPath(destinationDir.filePath(landscapeID)));
×
2079
                return QString();
×
2080
        }
2081
        destinationDir.cd(landscapeID);
×
UNCOV
2082
        for (const auto& info : infoList)
×
2083
        {
UNCOV
2084
                QFileInfo fileInfo(info.filePath);
×
2085
                if (info.isFile && fileInfo.dir().path() == topDir)
×
2086
                {
2087
                        QByteArray data = reader.fileData(info.filePath);
×
UNCOV
2088
                        QFile out(destinationDir.filePath(fileInfo.fileName()));
×
2089
                        if (out.open(QIODevice::WriteOnly))
×
2090
                        {
UNCOV
2091
                                out.write(data);
×
2092
                                out.close();
×
2093
                        }
2094
                        else
2095
                        {
2096
                                qWarning() << "LandscapeMgr: cannot open " << QDir::toNativeSeparators(fileInfo.absoluteFilePath());
×
2097
                        }
UNCOV
2098
                }
×
2099
        }
×
2100
        reader.close();
×
2101
        //If necessary, make the new landscape the current landscape
UNCOV
2102
        if (display)
×
2103
        {
2104
                setCurrentLandscapeID(landscapeID);
×
2105
        }
2106

2107
        //Make sure that everyone knows that the list of available landscapes has changed
2108
        emit landscapesChanged();
×
2109

2110
        qDebug() << "LandscapeMgr: Successfully installed landscape directory" << landscapeID << "to" << QDir::toNativeSeparators(destinationDir.absolutePath());
×
UNCOV
2111
        return landscapeID;
×
2112
}
×
2113

UNCOV
2114
bool LandscapeMgr::removeLandscape(const QString landscapeID)
×
2115
{
2116
        if (landscapeID.isEmpty())
×
2117
        {
2118
                qWarning() << "LandscapeMgr: Error! No landscape ID passed to removeLandscape().";
×
2119
                return false;
×
2120
        }
2121

2122
        if (packagedLandscapeIDs.contains(landscapeID))
×
2123
        {
2124
                qWarning() << "LandscapeMgr: Landscapes that are part of the default installation cannot be removed.";
×
UNCOV
2125
                return false;
×
2126
        }
2127

UNCOV
2128
        qDebug() << "LandscapeMgr: Trying to remove landscape" << landscapeID;
×
2129

2130
        QString landscapePath = getLandscapePath(landscapeID);
×
UNCOV
2131
        if (landscapePath.isEmpty())
×
2132
                return false;
×
2133

UNCOV
2134
        QDir landscapeDir(landscapePath);
×
UNCOV
2135
        for (auto &fileName : landscapeDir.entryList(QDir::Files | QDir::NoDotAndDotDot))
×
2136
        {
UNCOV
2137
                if(!landscapeDir.remove(fileName))
×
2138
                {
2139
                        qWarning() << "LandscapeMgr: Unable to remove" << QDir::toNativeSeparators(fileName);
×
2140
                        emit errorRemoveManually(landscapeDir.absolutePath());
×
UNCOV
2141
                        return false;
×
2142
                }
2143
        }
×
UNCOV
2144
        landscapeDir.cdUp();
×
2145
        if(!landscapeDir.rmdir(landscapeID))
×
2146
        {
2147
                qWarning() << "LandscapeMgr: Error! Landscape" << landscapeID
×
2148
                                   << "could not be removed. "
×
2149
                                   << "Some files were deleted, but not all."
×
UNCOV
2150
                                   << StelUtils::getEndLineChar()
×
2151
                                   << "LandscapeMgr: You can delete manually" << QDir::cleanPath(landscapeDir.filePath(landscapeID));
×
2152
                emit errorRemoveManually(QDir::cleanPath(landscapeDir.filePath(landscapeID)));
×
2153
                return false;
×
2154
        }
2155

2156
        qDebug() << "LandscapeMgr: Successfully removed" << QDir::toNativeSeparators(landscapePath);
×
2157

2158
        //If the landscape has been selected, revert to the default one
2159
        //TODO: Make this optional?
2160
        if (getCurrentLandscapeID() == landscapeID)
×
2161
        {
UNCOV
2162
                if(getDefaultLandscapeID() == landscapeID)
×
2163
                {
2164
                        setDefaultLandscapeID(packagedLandscapeIDs.first());
×
2165
                        //TODO: Find what happens if a missing landscape is specified in the configuration file
2166
                }
2167

2168
                setCurrentLandscapeID(getDefaultLandscapeID());
×
2169
        }
2170

2171
        //Make sure that everyone knows that the list of available landscapes has changed
2172
        emit landscapesChanged();
×
2173

UNCOV
2174
        return true;
×
UNCOV
2175
}
×
2176

UNCOV
2177
QString LandscapeMgr::getLandscapePath(const QString landscapeID)
×
2178
{
UNCOV
2179
        QString result;
×
2180
        //Is this necessary? This function is private.
UNCOV
2181
        if (landscapeID.isEmpty())
×
2182
                return result;
×
2183

UNCOV
2184
        result = StelFileMgr::findFile("landscapes/" + landscapeID, StelFileMgr::Directory);
×
2185
        if (result.isEmpty())
×
2186
        {
2187
                qWarning() << "LandscapeMgr: Error! Unable to find" << landscapeID;
×
UNCOV
2188
                return result;
×
2189
        }
2190

UNCOV
2191
        return result;
×
2192
}
×
2193

UNCOV
2194
QString LandscapeMgr::loadLandscapeName(const QString landscapeID)
×
2195
{
2196
        QString landscapeName;
×
UNCOV
2197
        if (landscapeID.isEmpty())
×
2198
        {
2199
                qWarning() << "LandscapeMgr: Error! No landscape ID passed to loadLandscapeName().";
×
2200
                return landscapeName;
×
2201
        }
2202

UNCOV
2203
        QString landscapePath = getLandscapePath(landscapeID);
×
2204
        if (landscapePath.isEmpty())
×
2205
                return landscapeName;
×
2206

2207
        QDir landscapeDir(landscapePath);
×
2208
        if (landscapeDir.exists("landscape.ini"))
×
2209
        {
UNCOV
2210
                QString landscapeSettingsPath = landscapeDir.filePath("landscape.ini");
×
2211
                QSettings landscapeSettings(landscapeSettingsPath, StelIniFormat);
×
2212
                landscapeName = landscapeSettings.value("landscape/name").toString();
×
2213
        }
×
2214
        else
2215
        {
2216
                qWarning() << "LandscapeMgr: Error! Landscape directory" << QDir::toNativeSeparators(landscapePath) << "does not contain a 'landscape.ini' file";
×
2217
        }
2218

2219
        return landscapeName;
×
2220
}
×
2221

UNCOV
2222
quint64 LandscapeMgr::loadLandscapeSize(const QString landscapeID) const
×
2223
{
2224
        quint64 landscapeSize = 0;
×
UNCOV
2225
        if (landscapeID.isEmpty())
×
2226
        {
2227
                qWarning() << "LandscapeMgr: Error! No landscape ID passed to loadLandscapeSize().";
×
2228
                return landscapeSize;
×
2229
        }
2230

UNCOV
2231
        QString landscapePath = getLandscapePath(landscapeID);
×
2232
        if (landscapePath.isEmpty())
×
2233
                return landscapeSize;
×
2234

2235
        const QDir landscapeDir(landscapePath);
×
2236
        for (auto &file : landscapeDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot))
×
2237
        {
2238
                //qDebug() << "name:" << file.baseName() << "size:" << file.size();
2239
                landscapeSize += static_cast<quint64>(file.size());
×
2240
        }
×
2241

UNCOV
2242
        return landscapeSize;
×
2243
}
×
2244

UNCOV
2245
QString LandscapeMgr::getDescription() const
×
2246
{
2247
        QString lang, desc, descFile, locDescriptionFile, engDescriptionFile;
×
2248
        bool hasFile = true;
×
2249

2250
        lang = StelApp::getInstance().getLocaleMgr().getAppLanguage();
×
2251
        locDescriptionFile = StelFileMgr::findFile("landscapes/" + getCurrentLandscapeID(), StelFileMgr::Directory) + "/description." + lang + ".utf8";
×
UNCOV
2252
        engDescriptionFile = StelFileMgr::findFile("landscapes/" + getCurrentLandscapeID(), StelFileMgr::Directory) + "/description.en.utf8";
×
2253

2254
        // OK. Check the file with full name of locale
2255
        if (!QFileInfo::exists(locDescriptionFile))
×
2256
        {
2257
                // Oops...  File not exists! What about short name of locale?
2258
                lang = lang.split("_").at(0);
×
2259
                locDescriptionFile = StelFileMgr::findFile("landscapes/" + getCurrentLandscapeID(), StelFileMgr::Directory) + "/description." + lang + ".utf8";
×
2260
        }
2261

2262
        // Check localized description for landscape
2263
        if (!locDescriptionFile.isEmpty() && QFileInfo::exists(locDescriptionFile))
×
2264
        {                
UNCOV
2265
                descFile = locDescriptionFile;
×
2266
        }
2267
        // OK. Localized description of landscape not exists. What about english description of its?
UNCOV
2268
        else if (!engDescriptionFile.isEmpty() && QFileInfo::exists(engDescriptionFile))
×
2269
        {
UNCOV
2270
                descFile = engDescriptionFile;
×
2271
        }
2272
        // That file not exists too? OK. Will be used description from landscape.ini file.
2273
        else
2274
        {
UNCOV
2275
                hasFile = false;
×
2276
        }
2277

2278
        if (hasFile)
×
2279
        {
UNCOV
2280
                QFile file(descFile);
×
UNCOV
2281
                if(file.open(QIODevice::ReadOnly | QIODevice::Text))
×
2282
                {
2283
                        QTextStream in(&file);
×
2284
#if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
UNCOV
2285
                        in.setEncoding(QStringConverter::Utf8);
×
2286
#else
2287
                        in.setCodec("UTF-8");
2288
#endif
2289
                        desc = in.readAll();
×
UNCOV
2290
                        file.close();
×
2291
                }
×
UNCOV
2292
        }
×
2293
        else
2294
        {
UNCOV
2295
                desc = QString("<h2>%1</h2>").arg(q_(landscape->getName()));
×
UNCOV
2296
                desc += landscape->getDescription();
×
2297
        }
2298

2299
        return desc;
×
2300
}
×
2301

UNCOV
2302
void LandscapeMgr::increaseLightPollution()
×
2303
{
2304
        StelCore* core = StelApp::getInstance().getCore();
×
UNCOV
2305
        const auto lum = core->getSkyDrawer()->getLightPollutionLuminance();
×
UNCOV
2306
        auto bidx = core->luminanceToBortleScaleIndex(lum) + 1;
×
2307
        if (bidx>9)
×
2308
                bidx = 9;
×
UNCOV
2309
        const auto newLum = core->bortleScaleIndexToLuminance(bidx);
×
2310
        core->getSkyDrawer()->setLightPollutionLuminance(newLum);
×
UNCOV
2311
}
×
2312

2313
void LandscapeMgr::reduceLightPollution()
×
2314
{
2315
        StelCore* core = StelApp::getInstance().getCore();
×
2316
        const auto lum = core->getSkyDrawer()->getLightPollutionLuminance();
×
2317
        auto bidx = core->luminanceToBortleScaleIndex(lum) - 1;
×
2318
        if (bidx<1)
×
2319
                bidx = 1;
×
UNCOV
2320
        const auto newLum = core->bortleScaleIndexToLuminance(bidx);
×
2321
        core->getSkyDrawer()->setLightPollutionLuminance(newLum);
×
UNCOV
2322
}
×
2323

2324
void LandscapeMgr::cyclicChangeLightPollution()
×
2325
{
2326
        StelCore* core = StelApp::getInstance().getCore();
×
2327
        const auto lum = core->getSkyDrawer()->getLightPollutionLuminance();
×
2328
        auto bidx = core->luminanceToBortleScaleIndex(lum) + 1;
×
2329
        if (bidx>9)
×
2330
                bidx = 1;
×
UNCOV
2331
        const auto newLum = core->bortleScaleIndexToLuminance(bidx);
×
2332
        core->getSkyDrawer()->setLightPollutionLuminance(newLum);
×
UNCOV
2333
}
×
2334

2335
/*
2336
// GZ: Addition to identify landscape transparency. Used for development and debugging only, should be commented out in release builds.
2337
// Also, StelMovementMgr l.382 event->accept() must be commented out for this here to work!
2338
void LandscapeMgr::handleMouseClicks(QMouseEvent *event)
2339
{
2340
        switch (event->button())
2341
        {
2342
        case Qt::LeftButton :
2343
                if (event->type()==QEvent::MouseButtonRelease)
2344
                {
2345
                        Vec3d v;
2346
                        StelApp::getInstance().getCore()->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff)->unProject(event->x(),event->y(),v);
2347
                        v.normalize();
2348
                        float trans=landscape->getOpacity(v);
2349
                        qDebug() << "Landscape opacity at screen X=" << event->x() << ", Y=" << event->y() << ": " << trans;
2350
                }
2351
                break;
2352
        default: break;
2353

2354
        }
2355
        // do not event->accept(), so that it is forwarded to other modules.
2356
        return;
2357
}
2358
*/
2359

UNCOV
2360
void LandscapeMgr::showMessage(const QString& message)
×
2361
{
UNCOV
2362
        messageToShow=message;
×
UNCOV
2363
        messageFader=true;
×
UNCOV
2364
        messageTimer->start();
×
UNCOV
2365
}
×
2366

UNCOV
2367
void LandscapeMgr::clearMessage()
×
2368
{
UNCOV
2369
        messageFader = false;
×
2370
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc