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

Stellarium / stellarium / 15670918640

16 Jun 2025 02:08AM UTC coverage: 11.775% (-0.2%) from 11.931%
15670918640

push

github

alex-w
Updated data

14700 of 124846 relevant lines covered (11.77%)

18324.52 hits per line

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

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

20
#include "StelSkyLayerMgr.hpp"
21
#include "StelApp.hpp"
22
#include "StelCore.hpp"
23
#include "StelFileMgr.hpp"
24
#include "StelSkyImageTile.hpp"
25
#include "StelModuleMgr.hpp"
26
#include "StelPainter.hpp"
27
#include "MilkyWay.hpp"
28
#include "StelTranslator.hpp"
29
#include "StelProgressController.hpp"
30

31
#include <QNetworkAccessManager>
32
#include <stdexcept>
33
#include <QDebug>
34
#include <QString>
35
#include <QVariantMap>
36
#include <QVariantList>
37
#include <QDir>
38
#include <QSettings>
39

40
StelSkyLayerMgr::StelSkyLayerMgr(void) : flagShow(true)
×
41
{
42
        setObjectName("StelSkyLayerMgr");
×
43
}
×
44

45
StelSkyLayerMgr::~StelSkyLayerMgr()
×
46
{
47
        for (auto* s : std::as_const(allSkyLayers))
×
48
                delete s;
×
49
}
×
50

51
/*************************************************************************
52
 Reimplementation of the getCallOrder method
53
*************************************************************************/
54
double StelSkyLayerMgr::getCallOrder(StelModuleActionName actionName) const
×
55
{
56
        if (actionName==StelModule::ActionDraw)
×
57
                return GETSTELMODULE(MilkyWay)->getCallOrder(actionName)+5;
×
58
        return 0;
×
59
}
60

61
// read from stream
62
void StelSkyLayerMgr::init()
×
63
{
64
        QSettings* conf = StelApp::getInstance().getSettings();
×
65
        const int decimation=conf->value("astro/nebula_texture_decimation", 1).toInt();
×
66
        loadCollection(decimation);
×
67

68
        conf->beginGroup("skylayers");
×
69
        for (const auto& key : conf->childKeys())
×
70
        {
71
                QString uri = conf->value(key, "").toString();
×
72
                if (!uri.isEmpty())
×
73
                {
74
                        if (key=="clilayer")
×
75
                                insertSkyImage(uri, "Command-line layer");
×
76
                        else
77
                                insertSkyImage(uri);
×
78
                }
79
        }
×
80
        conf->endGroup();
×
81

82
        setFlagShow(!conf->value("astro/flag_nebula_display_no_texture", false).toBool());
×
83
        addAction("actionShow_DSO_Textures", N_("Display Options"), N_("Deep-sky objects background images"), "flagShow", "I");
×
84
        addAction("actionShow_DSO_Textures_Reload", N_("Display Options"), N_("Reload the deep-sky objects background images"), "loadCollection()", "Ctrl+I");
×
85
}
×
86

87
void StelSkyLayerMgr::loadCollection(int decimateBy)
×
88
{
89
        if (!allSkyLayers.isEmpty())
×
90
                allSkyLayers.clear();
×
91

92
        QString path = StelFileMgr::findFile("nebulae/default/textures.json");
×
93
        if (path.isEmpty())
×
94
                qWarning() << "ERROR while loading nebula texture set default";
×
95
        else
96
                insertSkyImage(path, QString(), true, decimateBy);
×
97

98
#ifdef USE_STATIC_PLUGIN_NEBULATEXTURES
99
        // [NebulaTextures] The custom textures need to be loaded synchronously at the program startup in order to take effect
100
        QSettings* conf = StelApp::getInstance().getSettings();
×
101
        if(conf->value("plugins_load_at_startup/NebulaTextures", false).toBool()){
×
102
                path = StelFileMgr::findFile(StelFileMgr::getUserDir()+"/modules/NebulaTextures/custom_textures.json");
×
103
                if (path.isEmpty())
×
104
                        qWarning() << "[NebulaTextures] Custom Nebula Textures doesn't exist.";
×
105
                else
106
                        insertSkyImage(path, QString(), true, decimateBy);
×
107
        }
108
#endif
109
}
×
110

111
QString StelSkyLayerMgr::insertSkyLayer(StelSkyLayerP tile, const QString& keyHint, bool ashow)
×
112
{
113
        SkyLayerElem* bEl = new SkyLayerElem(tile, ashow);
×
114
        QString key = tile->getKeyHint();
×
115
        if (key.isEmpty() || key=="no name")
×
116
        {
117
                if (!keyHint.isEmpty())
×
118
                {
119
                        key = keyHint;
×
120
                }
121
                else
122
                {
123
                        key = "no name";
×
124
                }
125
        }
126
        if (allSkyLayers.contains(key))
×
127
        {
128
                QString suffix = "_01";
×
129
                int i=1;
×
130
                while (allSkyLayers.contains(key+suffix))
×
131
                {
132
                        suffix=QString("_%1").arg(i);
×
133
                        ++i;
×
134
                }
135
                key+=suffix;
×
136
        }
×
137
        allSkyLayers.insert(key,bEl);
×
138
        connect(bEl->layer.data(), SIGNAL(loadingStateChanged(bool)), this, SLOT(loadingStateChanged(bool)));
×
139
        connect(bEl->layer.data(), SIGNAL(percentLoadedChanged(int)), this, SLOT(percentLoadedChanged(int)));
×
140
        return key;
×
141
}
×
142

143
// Add a new image from its URI (URL or local file name)
144
QString StelSkyLayerMgr::insertSkyImage(const QString& uri, const QString& keyHint, bool ashow, int decimateBy)
×
145
{
146
        return insertSkyLayer(StelSkyLayerP(new StelSkyImageTile(uri, Q_NULLPTR, decimateBy)), keyHint, ashow);
×
147
}
148

149
// Remove a sky image tile from the list of background images
150
void StelSkyLayerMgr::removeSkyLayer(const QString& key)
×
151
{
152
        //qDebug() << "StelSkyLayerMgr::removeSkyImage removing image:" << key;
153
        if (allSkyLayers.contains(key))
×
154
        {
155
                SkyLayerElem* bEl = allSkyLayers[key];
×
156
                disconnect(bEl->layer.data(), SIGNAL(loadingStateChanged(bool)), this, SLOT(loadingStateChanged(bool)));
×
157
                disconnect(bEl->layer.data(), SIGNAL(percentLoadedChanged(int)), this, SLOT(percentLoadedChanged(int)));
×
158
                delete bEl;
×
159
                allSkyLayers.remove(key);
×
160
        }
161
        else
162
        {
163
                qDebug() << "StelSkyLayerMgr::removeSkyLayer there is no such key" << key << "nothing is removed";
×
164
        }
165
}
×
166

167
// Remove a sky image tile from the list of background images
168
void StelSkyLayerMgr::removeSkyLayer(StelSkyLayerP l)
×
169
{
170
        const QString k = keyForLayer(l.data());
×
171
        if (!k.isEmpty())
×
172
                removeSkyLayer(k);
×
173
}
×
174

175
// Draw all the multi-res images collection
176
void StelSkyLayerMgr::draw(StelCore* core)
×
177
{
178
        if (!flagShow)
×
179
                return;
×
180

181
        StelPainter sPainter(core->getProjection(StelCore::FrameJ2000));
×
182
        sPainter.setBlending(true, GL_ONE, GL_ONE); //additive blending
×
183
        for (auto* s : std::as_const(allSkyLayers))
×
184
        {
185
                if (s->show) 
×
186
                {
187
                        sPainter.setProjector(core->getProjection(s->layer->getFrameType()));
×
188
                        s->layer->draw(core, sPainter, 1.);
×
189
                }
190
        }
191
}
×
192

193
void noDelete(StelSkyLayer*) {}
×
194

195
// Called when loading of data started or stopped for one collection
196
void StelSkyLayerMgr::loadingStateChanged(bool b)
×
197
{
198
        StelSkyLayer* tile = qobject_cast<StelSkyLayer*>(QObject::sender());
×
199
        Q_ASSERT(tile!=Q_NULLPTR);
×
200
        SkyLayerElem* elem = skyLayerElemForLayer(tile);
×
201
        Q_ASSERT(elem!=Q_NULLPTR);
×
202
        if (b)
×
203
        {
204
                Q_ASSERT(elem->progressBar==Q_NULLPTR);
×
205
                elem->progressBar = StelApp::getInstance().addProgressBar();
×
206
                QString serverStr = elem->layer->getShortServerCredits();
×
207
                QString shortName = elem->layer->getShortName();
×
208
                if (serverStr.isEmpty())
×
209
                {
210
                        // TRANSLATORS: The full phrase is "Loading '%SHORT_NAME%'" in progress bar
211
                        elem->progressBar->setFormat(q_("Loading '%1'").arg(shortName));
×
212
                }
213
                else
214
                {
215
                        // TRANSLATORS: The full phrase is "Loading '%SHORT_NAME%' from %URL%" in progress bar
216
                        elem->progressBar->setFormat(q_("Loading '%1' from %2").arg(shortName, serverStr));
×
217
                }
218
                elem->progressBar->setRange(0,100);
×
219
        }
×
220
        else
221
        {
222
                Q_ASSERT(elem->progressBar!=Q_NULLPTR);
×
223
                StelApp::getInstance().removeProgressBar(elem->progressBar);
×
224
                elem->progressBar = Q_NULLPTR;
×
225
                emit collectionLoaded();
×
226
        }
227
}
×
228

229
// Called when the percentage of loading tiles/tiles to be displayed changed for one collection
230
void StelSkyLayerMgr::percentLoadedChanged(int percentage)
×
231
{
232
        StelSkyLayer* tile = qobject_cast<StelSkyLayer*>(QObject::sender());
×
233
        Q_ASSERT(tile!=Q_NULLPTR);
×
234
        SkyLayerElem* elem = skyLayerElemForLayer(tile);
×
235
        Q_ASSERT(elem!=Q_NULLPTR);
×
236
        Q_ASSERT(elem->progressBar!=Q_NULLPTR);
×
237
        elem->progressBar->setValue(percentage);
×
238
}
×
239

240
StelSkyLayerMgr::SkyLayerElem* StelSkyLayerMgr::skyLayerElemForLayer(const StelSkyLayer* t)
×
241
{
242
    for (auto* e : std::as_const(allSkyLayers))
×
243
        {
244
                if (e->layer==t)
×
245
                {
246
                        return e;
×
247
                }
248
        }
249
        return Q_NULLPTR;
×
250
}
251

252
QString StelSkyLayerMgr::keyForLayer(const StelSkyLayer* t)
×
253
{
254
        return allSkyLayers.key(skyLayerElemForLayer(t));
×
255
}
256

257
StelSkyLayerMgr::SkyLayerElem::SkyLayerElem(StelSkyLayerP t, bool ashow) : layer(t), progressBar(Q_NULLPTR), show(ashow)
×
258
{}
×
259

260
StelSkyLayerMgr::SkyLayerElem::~SkyLayerElem()
×
261
{
262
        if (progressBar)
×
263
                StelApp::getInstance().removeProgressBar(progressBar);
×
264
        progressBar = Q_NULLPTR;
×
265
}
×
266

267
bool StelSkyLayerMgr::loadSkyImage(const QString& id, const QString& filename,
×
268
                                   double long0, double lat0,
269
                                   double long1, double lat1,
270
                                   double long2, double lat2,
271
                                   double long3, double lat3,
272
                                   double minRes, double maxBright,
273
                                   bool visible, StelCore::FrameType frameType,
274
                                   bool withAberration, int decimateBy)
275
{
276
        Q_UNUSED(decimateBy)
277
        if (allSkyLayers.contains(id))
×
278
        {
279
                qWarning() << "Image ID" << id << "already exists, removing old image before loading";
×
280
                removeSkyLayer(id);
×
281
        }
282

283
        QString path = StelFileMgr::findFile(filename);
×
284
        if (path.isEmpty())
×
285
        {
286
                qWarning() << "Could not find image" << QDir::toNativeSeparators(filename);
×
287
                return false;
×
288
        }
289
        QVariantMap vm;
×
290
        QVariantList cl; // coordinates list for adding worldCoords and textureCoords
×
291
        QVariantList c;  // a list for a pair of coordinates
×
292
        QVariantList ol; // outer list - we want a structure 3 levels deep...
×
293
        vm["imageUrl"] = QVariant(path);
×
294
        vm["maxBrightness"] = QVariant(maxBright);
×
295
        vm["minResolution"] = QVariant(minRes);
×
296
        vm["shortName"] = QVariant(id);
×
297
        vm["withAberration"] = QVariant(withAberration);
×
298

299
        // textureCoords (define the ordering of worldCoords)
300
        cl.clear();
×
301
        ol.clear();
×
302
        c.clear(); c.append(0); c.append(0); cl.append(QVariant(c));
×
303
        c.clear(); c.append(1); c.append(0); cl.append(QVariant(c));
×
304
        c.clear(); c.append(1); c.append(1); cl.append(QVariant(c));
×
305
        c.clear(); c.append(0); c.append(1); cl.append(QVariant(c));
×
306
        ol.append(QVariant(cl));
×
307
        vm["textureCoords"] = ol;
×
308

309
        // world coordinates
310
        cl.clear();
×
311
        ol.clear();
×
312
        c.clear(); c.append(long0); c.append(lat0); cl.append(QVariant(c));
×
313
        c.clear(); c.append(long1); c.append(lat1); cl.append(QVariant(c));
×
314
        c.clear(); c.append(long2); c.append(lat2); cl.append(QVariant(c));
×
315
        c.clear(); c.append(long3); c.append(lat3); cl.append(QVariant(c));
×
316
        ol.append(QVariant(cl));
×
317
        vm["worldCoords"] = ol;
×
318

319
        vm["alphaBlend"] = true; // new 2017-3: Make black correctly see-through.
×
320

321
        StelSkyLayerP tile = StelSkyLayerP(new StelSkyImageTile(vm, Q_NULLPTR));
×
322
        tile->setFrameType(frameType);
×
323
        
324
        try
325
        {
326
                QString key = insertSkyLayer(tile, filename, visible);
×
327
                if (key == id)
×
328
                        return true;
×
329
                else
330
                        return false;
×
331
        }
×
332
        catch (std::runtime_error& e)
×
333
        {
334
                qWarning() << e.what();
×
335
                return false;
×
336
        }
×
337
}
×
338

339
void StelSkyLayerMgr::showLayer(const QString& id, bool b)
×
340
{
341
        if (allSkyLayers.contains(id))
×
342
        {
343
                if (allSkyLayers[id]!=Q_NULLPTR)
×
344
                        allSkyLayers[id]->show = b;
×
345
        }
346
}
×
347

348
bool StelSkyLayerMgr::getShowLayer(const QString& id) const
×
349
{
350
        if (allSkyLayers.contains(id))
×
351
        {
352
                if (allSkyLayers[id]!=Q_NULLPTR)
×
353
                        return allSkyLayers[id]->show;
×
354
        }
355
        return false;
×
356
}
357

358

359
//! Get the list of all the currently loaded layers.
360
QMap<QString, StelSkyLayerP> StelSkyLayerMgr::getAllSkyLayers() const
×
361
{
362
        QMap<QString, StelSkyLayerP> res;
×
363
        for (QMap<QString, StelSkyLayerMgr::SkyLayerElem*>::ConstIterator iter=allSkyLayers.constBegin();iter!=allSkyLayers.constEnd();++iter)
×
364
        {
365
                //qDebug() << iter.key() << iter.value()->layer->getShortName();
366
                res.insert(iter.key(), iter.value()->layer);
×
367
        }
368
        return res;
×
369
}
×
370

371
StelSkyLayerP StelSkyLayerMgr::getSkyLayer(const QString& key) const
×
372
{
373
        if (allSkyLayers.contains(key))
×
374
                return allSkyLayers[key]->layer;
×
375
        return StelSkyLayerP();
×
376
}
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