1 /*
2 * Stellarium
3 * Copyright (C) 2017 Alexander Wolf
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
21 #include "AsterismMgr.hpp"
22 #include "Asterism.hpp"
23 #include "StarMgr.hpp"
24 #include "StelApp.hpp"
25 #include "StelProjector.hpp"
26 #include "StelObjectMgr.hpp"
27 #include "StelLocaleMgr.hpp"
28 #include "StelSkyCultureMgr.hpp"
29 #include "StelModuleMgr.hpp"
30 #include "StelMovementMgr.hpp"
31 #include "StelFileMgr.hpp"
32 #include "StelCore.hpp"
33 #include "StelPainter.hpp"
34 #include "StelSkyDrawer.hpp"
35 #include "SolarSystem.hpp"
36
37 #include <vector>
38 #include <QDebug>
39 #include <QFile>
40 #include <QSettings>
41 #include <QRegularExpression>
42 #include <QString>
43 #include <QStringList>
44 #include <QDir>
45
46 using namespace std;
47
48 // constructor which loads all data from appropriate files
AsterismMgr(StarMgr * _hip_stars)49 AsterismMgr::AsterismMgr(StarMgr *_hip_stars)
50 : hipStarMgr(_hip_stars)
51 , linesDisplayed(false)
52 , rayHelpersDisplayed(false)
53 , namesDisplayed(false)
54 , hasAsterism(false)
55 , isolateAsterismSelected(false)
56 , asterismLineThickness(1)
57 , rayHelperThickness(1)
58 {
59 setObjectName("AsterismMgr");
60 Q_ASSERT(hipStarMgr);
61 }
62
~AsterismMgr()63 AsterismMgr::~AsterismMgr()
64 {
65 for (auto* asterism : asterisms)
66 {
67 delete asterism;
68 }
69 }
70
init()71 void AsterismMgr::init()
72 {
73 QSettings* conf = StelApp::getInstance().getSettings();
74 Q_ASSERT(conf);
75
76 lastLoadedSkyCulture = "dummy";
77 asterFont.setPixelSize(conf->value("viewing/asterism_font_size", 14).toInt());
78 setFlagLines(conf->value("viewing/flag_asterism_drawing").toBool());
79 setFlagRayHelpers(conf->value("viewing/flag_rayhelper_drawing").toBool());
80 setFlagLabels(conf->value("viewing/flag_asterism_name").toBool());
81 setAsterismLineThickness(conf->value("viewing/asterism_line_thickness", 1).toInt());
82 setRayHelperThickness(conf->value("viewing/rayhelper_line_thickness", 1).toInt());
83
84 // Load colors from config file
85 QString defaultColor = conf->value("color/default_color").toString();
86 setLinesColor(Vec3f(conf->value("color/asterism_lines_color", defaultColor).toString()));
87 setLabelsColor(Vec3f(conf->value("color/asterism_names_color", defaultColor).toString()));
88 setRayHelpersColor(Vec3f(conf->value("color/rayhelper_lines_color", defaultColor).toString()));
89
90 StelObjectMgr *objectManager = GETSTELMODULE(StelObjectMgr);
91 objectManager->registerStelObjectMgr(this);
92 connect(objectManager, SIGNAL(selectedObjectChanged(StelModule::StelModuleSelectAction)),
93 this, SLOT(selectedObjectChange(StelModule::StelModuleSelectAction)));
94 StelApp *app = &StelApp::getInstance();
95 connect(app, SIGNAL(languageChanged()), this, SLOT(updateI18n()));
96 connect(&app->getSkyCultureMgr(), SIGNAL(currentSkyCultureChanged(QString)), this, SLOT(updateSkyCulture(const QString&)));
97
98 QString displayGroup = N_("Display Options");
99 addAction("actionShow_Asterism_Lines", displayGroup, N_("Asterism lines"), "linesDisplayed", "Alt+A");
100 addAction("actionShow_Asterism_Labels", displayGroup, N_("Asterism labels"), "namesDisplayed", "Alt+V");
101 addAction("actionShow_Asterism_Isolated", displayGroup, N_("Toggle single asterism selection mode"), "switchSelectionMode()");
102 addAction("actionShow_Ray_Helpers", displayGroup, N_("Ray helpers"), "rayHelpersDisplayed", "Alt+R");
103 }
104
105 /*************************************************************************
106 Reimplementation of the getCallOrder method
107 *************************************************************************/
getCallOrder(StelModuleActionName actionName) const108 double AsterismMgr::getCallOrder(StelModuleActionName actionName) const
109 {
110 if (actionName==StelModule::ActionDraw)
111 return StelApp::getInstance().getModuleMgr().getModule("GridLinesMgr")->getCallOrder(actionName)+11;
112 return 0;
113 }
114
updateSkyCulture(const QString & skyCultureDir)115 void AsterismMgr::updateSkyCulture(const QString& skyCultureDir)
116 {
117 currentSkyCultureID = skyCultureDir;
118
119 StelObjectMgr* objMgr = GETSTELMODULE(StelObjectMgr);
120 const QList<StelObjectP> selectedObject = objMgr->getSelectedObject("Asterism");
121 if (!selectedObject.isEmpty()) // Unselect asterism
122 objMgr->unSelect();
123
124 // Check if the sky culture changed since last load, if not don't load anything
125 if (lastLoadedSkyCulture == skyCultureDir)
126 return;
127
128 QString fic = StelFileMgr::findFile("skycultures/"+skyCultureDir+"/asterism_lines.fab");
129 if (fic.isEmpty())
130 {
131 hasAsterism = false;
132 qWarning() << "No asterisms for skyculture" << currentSkyCultureID;
133 }
134 else
135 {
136 hasAsterism = true;
137 loadLines(fic);
138 }
139
140 // load asterism names
141 fic = StelFileMgr::findFile("skycultures/" + skyCultureDir + "/asterism_names.eng.fab");
142 if (!fic.isEmpty())
143 loadNames(fic);
144
145 // Translate asterism names for the new sky culture
146 updateI18n();
147
148 lastLoadedSkyCulture = skyCultureDir;
149 }
150
setLinesColor(const Vec3f & color)151 void AsterismMgr::setLinesColor(const Vec3f& color)
152 {
153 if (color != Asterism::lineColor)
154 {
155 Asterism::lineColor = color;
156 emit linesColorChanged(color);
157 }
158 }
159
getLinesColor() const160 Vec3f AsterismMgr::getLinesColor() const
161 {
162 return Asterism::lineColor;
163 }
164
setRayHelpersColor(const Vec3f & color)165 void AsterismMgr::setRayHelpersColor(const Vec3f& color)
166 {
167 if (color != Asterism::rayHelperColor)
168 {
169 Asterism::rayHelperColor = color;
170 emit rayHelpersColorChanged(color);
171 }
172 }
173
getRayHelpersColor() const174 Vec3f AsterismMgr::getRayHelpersColor() const
175 {
176 return Asterism::rayHelperColor;
177 }
178
179
setLabelsColor(const Vec3f & color)180 void AsterismMgr::setLabelsColor(const Vec3f& color)
181 {
182 if (Asterism::labelColor != color)
183 {
184 Asterism::labelColor = color;
185 emit namesColorChanged(color);
186 }
187 }
188
getLabelsColor() const189 Vec3f AsterismMgr::getLabelsColor() const
190 {
191 return Asterism::labelColor;
192 }
193
setFontSize(const float newFontSize)194 void AsterismMgr::setFontSize(const float newFontSize)
195 {
196 if ((static_cast<float>(asterFont.pixelSize()) - newFontSize) != 0.0f)
197 {
198 asterFont.setPixelSize(static_cast<int>(newFontSize));
199 emit fontSizeChanged(newFontSize);
200 }
201 }
202
getFontSize() const203 float AsterismMgr::getFontSize() const
204 {
205 return asterFont.pixelSize();
206 }
207
setAsterismLineThickness(const int thickness)208 void AsterismMgr::setAsterismLineThickness(const int thickness)
209 {
210 if(thickness!=asterismLineThickness)
211 {
212 asterismLineThickness = thickness;
213 if (asterismLineThickness<=0) // The line can not be negative or zero thickness
214 asterismLineThickness = 1;
215
216 emit asterismLineThicknessChanged(thickness);
217 }
218 }
219
setRayHelperThickness(const int thickness)220 void AsterismMgr::setRayHelperThickness(const int thickness)
221 {
222 if(thickness!=rayHelperThickness)
223 {
224 rayHelperThickness = thickness;
225 if (rayHelperThickness<=0) // The line can not be negative or zero thickness
226 rayHelperThickness = 1;
227
228 emit rayHelperThicknessChanged(thickness);
229 }
230 }
231
loadLines(const QString & fileName)232 void AsterismMgr::loadLines(const QString &fileName)
233 {
234 QFile in(fileName);
235 if (!in.open(QIODevice::ReadOnly | QIODevice::Text))
236 {
237 qWarning() << "Can't open asterism data file" << QDir::toNativeSeparators(fileName) << "for culture" << currentSkyCultureID;
238 Q_ASSERT(0);
239 }
240
241 int totalRecords=0;
242 QString record;
243 QRegularExpression commentRx("^(\\s*#.*|\\s*)$");
244 while (!in.atEnd())
245 {
246 record = QString::fromUtf8(in.readLine());
247 if (!commentRx.match(record).hasMatch())
248 totalRecords++;
249 }
250 in.seek(0);
251
252 // delete existing data, if any
253 for (auto* asterism : asterisms)
254 delete asterism;
255
256 asterisms.clear();
257 Asterism *aster = Q_NULLPTR;
258
259 // read the file of line patterns, adding a record per non-comment line
260 int currentLineNumber = 0; // line in file
261 int readOk = 0; // count of records processed OK
262 while (!in.atEnd())
263 {
264 record = QString::fromUtf8(in.readLine());
265 currentLineNumber++;
266 if (commentRx.match(record).hasMatch())
267 continue;
268
269 aster = new Asterism;
270 if(aster->read(record, hipStarMgr))
271 {
272 aster->setFlagLines(linesDisplayed);
273 aster->setFlagLabels(namesDisplayed);
274 aster->setFlagRayHelpers(rayHelpersDisplayed);
275 asterisms.push_back(aster);
276 ++readOk;
277 }
278 else
279 {
280 qWarning() << "ERROR reading asterism lines record at line " << currentLineNumber << "for culture" << currentSkyCultureID;
281 delete aster;
282 }
283 }
284 in.close();
285 qDebug() << "Loaded" << readOk << "/" << totalRecords << "asterism records successfully for culture" << currentSkyCultureID;
286
287 // Set current states
288 setFlagLines(linesDisplayed);
289 setFlagLabels(namesDisplayed);
290 setFlagRayHelpers(rayHelpersDisplayed);
291 }
292
draw(StelCore * core)293 void AsterismMgr::draw(StelCore* core)
294 {
295 const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
296 StelPainter sPainter(prj);
297 sPainter.setFont(asterFont);
298 drawLines(sPainter, core);
299 drawRayHelpers(sPainter, core);
300 drawNames(sPainter);
301 }
302
303 // Draw asterisms lines
drawLines(StelPainter & sPainter,const StelCore * core) const304 void AsterismMgr::drawLines(StelPainter& sPainter, const StelCore* core) const
305 {
306 if (!hasAsterism)
307 return;
308
309 const float ppx = static_cast<float>(sPainter.getProjector()->getDevicePixelsPerPixel());
310 sPainter.setBlending(true);
311 if (asterismLineThickness>1 || ppx>1.f)
312 sPainter.setLineWidth(asterismLineThickness*ppx); // set line thickness
313 sPainter.setLineSmooth(true);
314
315 const SphericalCap& viewportHalfspace = sPainter.getProjector()->getBoundingCap();
316 for (auto* asterism : asterisms)
317 {
318 if (asterism->isAsterism())
319 asterism->drawOptim(sPainter, core, viewportHalfspace);
320 }
321 if (asterismLineThickness>1 || ppx>1.f)
322 sPainter.setLineWidth(1); // restore line thickness
323 sPainter.setLineSmooth(false);
324 }
325
326 // Draw asterisms lines
drawRayHelpers(StelPainter & sPainter,const StelCore * core) const327 void AsterismMgr::drawRayHelpers(StelPainter& sPainter, const StelCore* core) const
328 {
329 if (!hasAsterism)
330 return;
331
332 const float ppx = static_cast<float>(sPainter.getProjector()->getDevicePixelsPerPixel());
333 sPainter.setBlending(true);
334 if (rayHelperThickness>1 || ppx>1.f)
335 sPainter.setLineWidth(rayHelperThickness*ppx); // set line thickness
336 sPainter.setLineSmooth(true);
337
338 const SphericalCap& viewportHalfspace = sPainter.getProjector()->getBoundingCap();
339 for (auto* asterism : asterisms)
340 {
341 if (!asterism->isAsterism())
342 asterism->drawOptim(sPainter, core, viewportHalfspace);
343 }
344 if (rayHelperThickness>1 || ppx>1.f)
345 sPainter.setLineWidth(1); // restore line thickness
346 sPainter.setLineSmooth(false);
347 }
348
349 // Draw the names of all the asterisms
drawNames(StelPainter & sPainter) const350 void AsterismMgr::drawNames(StelPainter& sPainter) const
351 {
352 if (!hasAsterism)
353 return;
354
355 StelCore *core=StelApp::getInstance().getCore();
356 Vec3d vel=core->getCurrentPlanet()->getHeliocentricEclipticVelocity();
357 vel=StelCore::matVsop87ToJ2000*vel;
358 vel*=core->getAberrationFactor() * (AU/(86400.0*SPEED_OF_LIGHT));
359
360 sPainter.setBlending(true);
361 for (auto* asterism : asterisms)
362 {
363 if (!asterism->flagAsterism) continue;
364 // Check if in the field of view
365 Vec3d XYZname=asterism->XYZname;
366 if (core->getUseAberration())
367 {
368 XYZname.normalize();
369 XYZname+=vel;
370 XYZname.normalize();
371 }
372
373 if (sPainter.getProjector()->projectCheck(XYZname, asterism->XYname))
374 asterism->drawName(sPainter);
375 }
376 }
377
findFromAbbreviation(const QString & abbreviation) const378 Asterism* AsterismMgr::findFromAbbreviation(const QString& abbreviation) const
379 {
380 for (auto* asterism : asterisms)
381 {
382 if (asterism->abbreviation.compare(abbreviation, Qt::CaseInsensitive) == 0)
383 return asterism;
384 }
385 return Q_NULLPTR;
386 }
387
388
389 // Can't find asterism from a position because it's not well localized
searchAround(const Vec3d &,double,const StelCore *) const390 QList<StelObjectP> AsterismMgr::searchAround(const Vec3d&, double, const StelCore*) const
391 {
392 return QList<StelObjectP>();
393 }
394
loadNames(const QString & namesFile)395 void AsterismMgr::loadNames(const QString& namesFile)
396 {
397 // Asterism not loaded yet
398 if (asterisms.empty()) return;
399
400 // clear previous names
401 for (auto* asterism : asterisms)
402 {
403 asterism->englishName.clear();
404 }
405
406 // Open file
407 QFile commonNameFile(namesFile);
408 if (!commonNameFile.open(QIODevice::ReadOnly | QIODevice::Text))
409 {
410 qDebug() << "Cannot open file" << QDir::toNativeSeparators(namesFile);
411 return;
412 }
413
414 // Now parse the file
415 // lines to ignore which start with a # or are empty
416 QRegularExpression commentRx("^(\\s*#.*|\\s*)$");
417 QRegularExpression recRx("^\\s*(\\w+)\\s+_[(]\"(.*)\"[)]\\s*([\\,\\d\\s]*)\\n");
418 QRegularExpression ctxRx("(.*)\",\\s*\"(.*)");
419
420 // keep track of how many records we processed.
421 int totalRecords=0;
422 int readOk=0;
423 int lineNumber=0;
424 while (!commonNameFile.atEnd())
425 {
426 QString record = QString::fromUtf8(commonNameFile.readLine());
427 lineNumber++;
428
429 // Skip comments
430 if (commentRx.match(record).hasMatch())
431 continue;
432
433 totalRecords++;
434
435 QRegularExpressionMatch recMatch=recRx.match(record);
436 if (!recMatch.hasMatch())
437 {
438 qWarning() << "ERROR - cannot parse record at line" << lineNumber << "in asterism names file" << QDir::toNativeSeparators(namesFile) << ":" << record;
439 }
440 else
441 {
442 QString shortName = recMatch.captured(1);
443 Asterism *aster = findFromAbbreviation(shortName);
444 // If the asterism exists, set the English name
445 if (aster != Q_NULLPTR)
446 {
447 QString ctxt = recMatch.captured(2);
448 QRegularExpressionMatch ctxMatch=ctxRx.match(ctxt);
449 if (ctxMatch.hasMatch())
450 {
451 aster->englishName = ctxMatch.captured(1);
452 aster->context = ctxMatch.captured(2);
453 }
454 else
455 {
456 aster->englishName = ctxt;
457 aster->context = "";
458 }
459 readOk++;
460 }
461 else
462 {
463 qWarning() << "WARNING - asterism abbreviation" << shortName << "not found when loading asterism names";
464 }
465 }
466 }
467 commonNameFile.close();
468 qDebug() << "Loaded" << readOk << "/" << totalRecords << "asterism names";
469 }
470
updateI18n()471 void AsterismMgr::updateI18n()
472 {
473 const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
474 for (auto* asterism : asterisms)
475 {
476 asterism->nameI18 = trans.qtranslate(asterism->englishName, asterism->context);
477 }
478 }
479
480 // update faders
update(double deltaTime)481 void AsterismMgr::update(double deltaTime)
482 {
483 const int delta = static_cast<int>(deltaTime*1000);
484 for (auto* asterism : asterisms)
485 {
486 asterism->update(delta);
487 }
488 }
489
setFlagLines(const bool displayed)490 void AsterismMgr::setFlagLines(const bool displayed)
491 {
492 if(linesDisplayed != displayed)
493 {
494 linesDisplayed = displayed;
495 if (!selected.empty() && getFlagIsolateAsterismSelected())
496 {
497 for (auto* asterism : selected)
498 asterism->setFlagLines(linesDisplayed);
499 }
500 else
501 {
502 for (auto* asterism : asterisms)
503 asterism->setFlagLines(linesDisplayed);
504 }
505 emit linesDisplayedChanged(displayed);
506 }
507 }
508
getFlagLines(void) const509 bool AsterismMgr::getFlagLines(void) const
510 {
511 return linesDisplayed;
512 }
513
setFlagRayHelpers(const bool displayed)514 void AsterismMgr::setFlagRayHelpers(const bool displayed)
515 {
516 if(rayHelpersDisplayed != displayed)
517 {
518 rayHelpersDisplayed = displayed;
519 for (auto* asterism : asterisms)
520 {
521 asterism->setFlagRayHelpers(rayHelpersDisplayed);
522 }
523 emit rayHelpersDisplayedChanged(displayed);
524 }
525 }
526
getFlagRayHelpers(void) const527 bool AsterismMgr::getFlagRayHelpers(void) const
528 {
529 return rayHelpersDisplayed;
530 }
531
setFlagLabels(const bool displayed)532 void AsterismMgr::setFlagLabels(const bool displayed)
533 {
534 if (namesDisplayed != displayed)
535 {
536 namesDisplayed = displayed;
537 if (!selected.empty() && getFlagIsolateAsterismSelected())
538 {
539 for (auto* asterism : selected)
540 asterism->setFlagLabels(namesDisplayed);
541 }
542 else
543 {
544 for (auto* asterism : asterisms)
545 asterism->setFlagLabels(namesDisplayed);
546 }
547 emit namesDisplayedChanged(displayed);
548 }
549 }
550
getFlagLabels(void) const551 bool AsterismMgr::getFlagLabels(void) const
552 {
553 return namesDisplayed;
554 }
555
searchByNameI18n(const QString & nameI18n) const556 StelObjectP AsterismMgr::searchByNameI18n(const QString& nameI18n) const
557 {
558 QString objw = nameI18n.toUpper();
559
560 for (auto* asterism : asterisms)
561 {
562 QString objwcap = asterism->nameI18.toUpper();
563 if (objwcap == objw) return asterism;
564 }
565 return Q_NULLPTR;
566 }
567
searchByName(const QString & name) const568 StelObjectP AsterismMgr::searchByName(const QString& name) const
569 {
570 QString objw = name.toUpper();
571 for (auto* asterism : asterisms)
572 {
573 QString objwcap = asterism->englishName.toUpper();
574 if (objwcap == objw) return asterism;
575
576 objwcap = asterism->abbreviation.toUpper();
577 if (objwcap == objw) return asterism;
578 }
579 return Q_NULLPTR;
580 }
581
listAllObjects(bool inEnglish) const582 QStringList AsterismMgr::listAllObjects(bool inEnglish) const
583 {
584 QStringList result;
585 if (inEnglish)
586 {
587 for (auto* asterism : asterisms)
588 {
589 if (asterism->isAsterism())
590 result << asterism->getEnglishName();
591 }
592 }
593 else
594 {
595 for (auto* asterism : asterisms)
596 {
597 if (asterism->isAsterism())
598 result << asterism->getNameI18n();
599 }
600 }
601 return result;
602 }
603
searchByID(const QString & id) const604 StelObjectP AsterismMgr::searchByID(const QString &id) const
605 {
606 for (auto* asterism : asterisms)
607 {
608 if (asterism->getID() == id) return asterism;
609 }
610 return Q_NULLPTR;
611 }
612
getStelObjectType() const613 QString AsterismMgr::getStelObjectType() const
614 {
615 return Asterism::ASTERISM_TYPE;
616 }
617
setFlagIsolateAsterismSelected(const bool isolate)618 void AsterismMgr::setFlagIsolateAsterismSelected(const bool isolate)
619 {
620 if (isolateAsterismSelected != isolate)
621 {
622 isolateAsterismSelected = isolate;
623
624 // when turning off isolated selection mode, clear existing isolated selections.
625 if (!isolateAsterismSelected)
626 {
627 for (auto* asterism : asterisms)
628 {
629 asterism->setFlagLines(getFlagLines());
630 asterism->setFlagLabels(getFlagLabels());
631 }
632 }
633 emit isolateAsterismSelectedChanged(isolate);
634 }
635 }
636
getFlagIsolateAsterismSelected(void) const637 bool AsterismMgr::getFlagIsolateAsterismSelected(void) const
638 {
639 return isolateAsterismSelected;
640 }
641
setSelectedAsterism(Asterism * a)642 void AsterismMgr::setSelectedAsterism(Asterism *a)
643 {
644 // update states for other asterisms to fade them out
645 if (a != Q_NULLPTR)
646 {
647 selected.push_back(a);
648
649 if (getFlagIsolateAsterismSelected())
650 {
651 // Propagate current settings to newly selected asterism
652 a->setFlagLines(getFlagLines());
653 a->setFlagLabels(getFlagLabels());
654
655 for (auto* asterism : asterisms)
656 {
657 bool match = false;
658 for (auto* selected_asterisms : selected)
659 {
660 if (asterism == selected_asterisms)
661 {
662 match=true; // this is a selected asterism
663 break;
664 }
665 }
666
667 if(!match)
668 {
669 // Not selected asterism
670 asterism->setFlagLines(false);
671 asterism->setFlagLabels(false);
672 }
673 }
674 }
675 else
676 {
677 for (auto* asterism : asterisms)
678 {
679 asterism->setFlagLines(false);
680 asterism->setFlagLabels(false);
681 }
682
683 // Propagate current settings to newly selected asterism
684 a->setFlagLines(getFlagLines());
685 a->setFlagLabels(getFlagLabels());
686 }
687 }
688 else
689 {
690 if (selected.empty()) return;
691
692 // Otherwise apply standard flags to all asterisms
693 for (auto* asterism : asterisms)
694 {
695 asterism->setFlagLines(getFlagLines());
696 asterism->setFlagLabels(getFlagLabels());
697 }
698
699 // And remove all selections
700 selected.clear();
701 }
702 }
703
704 //! Remove a asterism from the selected asterism list
unsetSelectedAsterism(Asterism * a)705 void AsterismMgr::unsetSelectedAsterism(Asterism *a)
706 {
707 if (a != Q_NULLPTR)
708 {
709 for (auto iter = selected.begin(); iter != selected.end();)
710 {
711 if( (*iter)->getEnglishName().toLower() == a->getEnglishName().toLower() )
712 iter = selected.erase(iter);
713 else
714 ++iter;
715 }
716
717 // If no longer any selection, restore all flags on all asterisms
718 if (selected.empty())
719 {
720 // Otherwise apply standard flags to all asterisms
721 for (auto* asterism : asterisms)
722 {
723 asterism->setFlagLines(getFlagLines());
724 asterism->setFlagLabels(getFlagLabels());
725 }
726 }
727 else if(isolateAsterismSelected)
728 {
729 // No longer selected asterism
730 a->setFlagLines(false);
731 a->setFlagLabels(false);
732 }
733 }
734 }
735
selectAsterism(const QString & englishName)736 void AsterismMgr::selectAsterism(const QString &englishName)
737 {
738 if (!getFlagIsolateAsterismSelected())
739 setFlagIsolateAsterismSelected(true); // Enable isolated selection
740
741 bool found = false;
742 for (auto* asterism : asterisms)
743 {
744 if (asterism->getEnglishName().toLower()==englishName.toLower())
745 {
746 setSelectedAsterism(asterism);
747 found = true;
748 break;
749 }
750 }
751 if (!found)
752 qDebug() << "The asterism" << englishName << "is not found";
753 }
754
deselectAsterism(const QString & englishName)755 void AsterismMgr::deselectAsterism(const QString &englishName)
756 {
757 if (!getFlagIsolateAsterismSelected())
758 setFlagIsolateAsterismSelected(true); // Enable isolated selection
759
760 bool found = false;
761 for (auto* asterism : asterisms)
762 {
763 if (asterism->getEnglishName().toLower()==englishName.toLower())
764 {
765 unsetSelectedAsterism(asterism);
766 found = true;
767 break;
768 }
769 }
770
771 if (selected.size()==0 && found)
772 {
773 // Let's remove the selection for all asterisms if the list of selected asterisms is empty
774 for (auto* asterism : asterisms)
775 {
776 asterism->setFlagLines(false);
777 asterism->setFlagLabels(false);
778 }
779 }
780
781 if (!found)
782 qDebug() << "The asterism" << englishName << "is not found";
783 }
784
deselectAsterisms(void)785 void AsterismMgr::deselectAsterisms(void)
786 {
787 StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
788 Q_ASSERT(omgr);
789 if (getFlagIsolateAsterismSelected())
790 {
791 // The list of selected asterisms is empty, but...
792 if (selected.size()==0)
793 {
794 // ...let's unselect all asterisms for guarantee
795 for (auto* asterism : asterisms)
796 {
797 asterism->setFlagLines(false);
798 asterism->setFlagLabels(false);
799 }
800 }
801
802 // If any asterism is selected at the moment, then let's do not touch to it!
803 if (omgr->getWasSelected() && selected.size()>0)
804 selected.pop_back();
805
806 // Let's hide all previously selected asterisms
807 for (auto* asterism : selected)
808 {
809 asterism->setFlagLines(false);
810 asterism->setFlagLabels(false);
811 }
812 }
813 else
814 {
815 const QList<StelObjectP> newSelectedConst = omgr->getSelectedObject("Asterism");
816 if (!newSelectedConst.empty())
817 omgr->unSelect();
818 }
819 selected.clear();
820 }
821
selectAllAsterisms()822 void AsterismMgr::selectAllAsterisms()
823 {
824 for (auto* asterism : asterisms)
825 setSelectedAsterism(asterism);
826 }
827
selectedObjectChange(StelModule::StelModuleSelectAction action)828 void AsterismMgr::selectedObjectChange(StelModule::StelModuleSelectAction action)
829 {
830 StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
831 Q_ASSERT(omgr);
832 const QList<StelObjectP> newSelected = omgr->getSelectedObject();
833 if (newSelected.empty())
834 return;
835
836 const QList<StelObjectP> newSelectedAsterisms = omgr->getSelectedObject("Asterism");
837 if (!newSelectedAsterisms.empty())
838 {
839 // If removing this selection
840 if(action == StelModule::RemoveFromSelection)
841 unsetSelectedAsterism(static_cast<Asterism *>(newSelectedAsterisms[0].data()));
842 else // Add asterism to selected list (do not select a star, just the constellation)
843 setSelectedAsterism(static_cast<Asterism *>(newSelectedAsterisms[0].data()));
844 }
845 }
846
switchSelectionMode()847 void AsterismMgr::switchSelectionMode()
848 {
849 bool state = getFlagIsolateAsterismSelected();
850 setFlagIsolateAsterismSelected(!state);
851 if (!state)
852 deselectAsterisms();
853 }
854