1 #include <libintl.h>
2 #include <qradiobutton.h>
3 #include <klistview.h>
4 #include <kpopupmenu.h>
5 #include <klocale.h>
6 #include <qstatusbar.h>
7 
8 #include <vector>
9 
10 #include "celestiacore.h"
11 #include "celengine/simulation.h"
12 #include "celengine/stardb.h"
13 #include "celengine/starbrowser.h"
14 #include "celengine/selection.h"
15 
16 #include "celestialbrowser.h"
17 #include "cellistviewitem.h"
18 #include "selectionpopup.h"
19 #include "celutil/utf8.h"
20 
21 /*
22  *  Constructs a CelestialBrowser which is a child of 'parent', with the
23  *  name 'name' and widget flags set to 'f'
24  *
25  *  The dialog will by default be modeless, unless you set 'modal' to
26  *  TRUE to construct a modal dialog.
27  */
CelestialBrowser(QWidget * parent,CelestiaCore * appCore)28 CelestialBrowser::CelestialBrowser( QWidget* parent, CelestiaCore* appCore)
29     : CelestialBrowserBase( parent, i18n("Celestial Browser"))
30 {
31     this->parent = dynamic_cast<KdeApp*>(parent);
32     this->appCore = appCore;
33     this->appSim = appCore->getSimulation();
34     listStars->setAllColumnsShowFocus(true);
35     listStars->setRootIsDecorated(true);
36     listStars->setColumnAlignment(1, Qt::AlignRight);
37     listStars->setColumnAlignment(2, Qt::AlignRight);
38     listStars->setColumnAlignment(3, Qt::AlignRight);
39     listStars->setShowSortIndicator(true);
40 
41     sbrowser.setSimulation(appSim);
42     radioNearest->setChecked(true);
43     statusBar()->hide();
44 }
45 
46 /*
47  *  Destroys the object and frees any allocated resources
48  */
~CelestialBrowser()49 CelestialBrowser::~CelestialBrowser()
50 {
51     // no need to delete child widgets, Qt does it all for us
52 }
53 
54 /*
55  * public slot
56  */
slotNearest(bool)57 void CelestialBrowser::slotNearest(bool)
58 {
59     sbrowser.setPredicate(StarBrowser::NearestStars);
60     listStars->setSorting(1);
61     slotRefresh();
62 }
63 
64 /*
65  * public slot
66  */
slotBrightest(bool)67 void CelestialBrowser::slotBrightest(bool)
68 {
69     sbrowser.setPredicate(StarBrowser::BrightestStars);
70     listStars->setSorting(3);
71     slotRefresh();
72 }
73 
74 /*
75  * public slot
76  */
slotBrighter(bool)77 void CelestialBrowser::slotBrighter(bool)
78 {
79     sbrowser.setPredicate(StarBrowser::BrighterStars);
80     listStars->setSorting(2);
81     slotRefresh();
82 }
83 
84 /*
85  * public slot
86  */
slotWithPlanets(bool)87 void CelestialBrowser::slotWithPlanets(bool)
88 {
89     sbrowser.setPredicate(StarBrowser::StarsWithPlanets);
90     listStars->setSorting(1);
91     slotRefresh();
92 }
93 
94 /*
95  * public slot
96  */
slotRefresh()97 void CelestialBrowser::slotRefresh()
98 {
99     StarDatabase* stardb = appSim->getUniverse()->getStarCatalog();
100     sbrowser.refresh();
101 
102     std::vector<const Star*> *stars = sbrowser.listStars(100);
103 
104     listStars->clear();
105     browserSel.obj = const_cast<Star*>((*stars)[0]);
106     browserSel.type = Selection::Type_Star;
107 
108     SolarSystemCatalog* solarSystemCatalog = appSim->getUniverse()->getSolarSystemCatalog();
109 
110     UniversalCoord ucPos = appSim->getObserver().getPosition();
111     Point3f obsPos( (double)ucPos.x * 1e-6,
112                     (double)ucPos.y * 1e-6,
113                     (double)ucPos.z * 1e-6);
114 
115     setlocale(LC_NUMERIC, "");
116 
117     for (std::vector<const Star*>::iterator i = stars->begin();
118          i != stars->end() ;
119          i++ )
120     {
121         const Star *star=(Star *)(*i);
122 
123         QString starClass(star->getSpectralType());
124 
125         if (starClass == "Bary") continue;
126 
127         Point3f starPos = star->getPosition();
128         Vec3d v(starPos.x - obsPos.x,
129                 starPos.y - obsPos.y,
130                 starPos.z - obsPos.z);
131         float dist = v.length();
132 
133         CelListViewItem *starItem = new CelListViewItem(listStars, stardb->getStarName(*star), dist, _("ly"),
134                 astro::absToAppMag(star->getAbsoluteMagnitude(), dist),
135                 star->getAbsoluteMagnitude(), starClass);
136 
137         SolarSystemCatalog::iterator iter = solarSystemCatalog->find(star->getCatalogNumber());
138         if (iter != solarSystemCatalog->end())
139         {
140             addPlanetarySystem(starItem, iter->second->getPlanets());
141         }
142     }
143 
144     setlocale(LC_NUMERIC, "C");
145 
146     delete(stars);
147 }
148 
addPlanetarySystem(CelListViewItem * parentItem,const PlanetarySystem * system,const Point3d * parentBodyPos)149 void CelestialBrowser::addPlanetarySystem(CelListViewItem* parentItem, const PlanetarySystem* system, const Point3d* parentBodyPos)
150 {
151     if (parentItem == NULL || system == NULL) return;
152     for ( int i = 0; i < system->getSystemSize(); i++ )
153     {
154         const Body* body = system->getBody(i);
155         if (body->getClassification() & (Body::Barycenter | Body::Invisible)) continue;
156         Point3d bodyPos = body->getAstrocentricPosition(appSim->getTime());
157         CelListViewItem* item = NULL;
158         if (parentBodyPos == NULL)
159         {
160             double bodyDist = bodyPos.distanceFromOrigin();
161             item = new CelListViewItem(parentItem, body->getName(true),
162                                        bodyDist / KM_PER_AU, _("au"),
163                                        0, 0, getClassification(body->getClassification()));
164         }
165         else
166         {
167             Vec3d bodyVec(parentBodyPos->x - bodyPos.x, parentBodyPos->y - bodyPos.y, parentBodyPos->z - bodyPos.z);
168             double bodyDist = bodyVec.length();
169             item = new CelListViewItem(parentItem, body->getName(true),
170                                        bodyDist, "km",
171                                        0, 0, getClassification(body->getClassification()));
172         }
173         addPlanetarySystem(item, body->getSatellites(), &bodyPos);
174     }
175 }
176 
getClassification(int c) const177 QString CelestialBrowser::getClassification(int c) const{
178     QString cl;
179     switch(c)
180         {
181         case Body::Planet:
182             cl = i18n("Planet");
183             break;
184         case Body::Moon:
185             cl = i18n("Moon");
186             break;
187         case Body::Asteroid:
188             cl = i18n("Asteroid");
189             break;
190         case Body::Comet:
191             cl = i18n("Comet");
192             break;
193         case Body::Spacecraft:
194             cl = i18n("Spacecraft");
195             break;
196         case Body::Invisible:
197             cl = i18n("Invisible");
198             break;
199         case Body::Barycenter:
200             cl = i18n("Barycenter");
201             break;
202         case Body::SmallBody:
203             cl = i18n("Small Body");
204             break;
205         case Body::DwarfPlanet:
206             cl = i18n("Dwarf Planet");
207             break;
208         case Body::Unknown:
209         default:
210             cl = i18n("-");
211             break;
212         }
213     return cl;
214 }
215 
216 
slotRightClickOnStar(QListViewItem * item,const QPoint & p,int)217 void CelestialBrowser::slotRightClickOnStar(QListViewItem* item, const QPoint& p, int /*col*/) {
218     CelListViewItem *i = dynamic_cast<CelListViewItem*>(item);
219     std::string name = i->getName();
220     while ( (i = dynamic_cast<CelListViewItem*>(i->parent())) ) {
221         name = i->getName() + "/" + name;
222     }
223     Selection sel = appSim->findObjectFromPath(name, true);
224 
225     SelectionPopup popup(this, appCore, sel);
226     popup.init();
227     int id = popup.exec(p);
228     popup.process(id);
229 }
230 
231 
CelListViewItem(QListView * parent,std::string _name,double _dist,const char * _dist_unit,double _app_mag,double _abs_mag,QString _type)232 CelListViewItem::CelListViewItem( QListView * parent, std::string _name, double _dist, const char* _dist_unit, double _app_mag, double _abs_mag, QString _type )
233     : QListViewItem(parent),
234     name(_name),
235     dist(_dist),
236     dist_unit(_dist_unit),
237     app_mag(_app_mag),
238     abs_mag(_abs_mag),
239     type(_type)
240 {
241     char buf[20];
242     QString label;
243     this->setText(0, QString::fromUtf8(ReplaceGreekLetterAbbr(_name).c_str()));
244 
245     sprintf(buf, " %'.2f %s", _dist, _dist_unit);
246     label = QString::fromUtf8(buf);
247     this->setText(1, label);
248 
249     if (_app_mag != 0) {
250         sprintf(buf, " %'.2f ", _app_mag);
251         label = QString::fromUtf8(buf);
252         this->setText(2, label);
253     }
254 
255     if (_abs_mag != 0) {
256         sprintf(buf, " %'.2f ", _abs_mag);
257         label = QString::fromUtf8(buf);
258         this->setText(3, label);
259     }
260 
261     this->setText(4, _type);
262 }
263 
CelListViewItem(QListViewItem * parent,std::string _name,double _dist,const char * _dist_unit,double _app_mag,double _abs_mag,QString _type)264 CelListViewItem::CelListViewItem( QListViewItem * parent, std::string _name, double _dist, const char* _dist_unit, double _app_mag, double _abs_mag, QString _type )
265     : QListViewItem(parent),
266     name(_name),
267     dist(_dist),
268     dist_unit(_dist_unit),
269     app_mag(_app_mag),
270     abs_mag(_abs_mag),
271     type(_type)
272 {
273     char buf[20];
274     QString label;
275 
276     this->setText(0, QString::fromUtf8(ReplaceGreekLetterAbbr(_name).c_str()));
277 
278     sprintf(buf, " %'.2f %s", _dist, _dist_unit);
279     label = QString::fromUtf8(buf);
280     this->setText(1, label);
281 
282     if (_app_mag != 0) {
283         sprintf(buf, " %'.2f ", _app_mag);
284         label = QString::fromUtf8(buf);
285         this->setText(2, label);
286     }
287 
288     if (_abs_mag != 0) {
289         sprintf(buf, " %'.2f ", _abs_mag);
290         label = QString::fromUtf8(buf);
291         this->setText(3, label);
292     }
293 
294     this->setText(4, _type);
295 }
296 
~CelListViewItem()297 CelListViewItem::~CelListViewItem() {
298 
299 }
300 
compare(QListViewItem * i,int col,bool ascending) const301 int CelListViewItem::compare ( QListViewItem * i, int col, bool ascending ) const {
302     if (col == 0 || col > 3) {
303         return key(col, ascending).localeAwareCompare(i->key(col, ascending));
304     } else {
305         if (col == 1) return (dist > dynamic_cast<CelListViewItem*>(i)->getDist()) * 2 - 1;
306         if (col == 2) return (app_mag > dynamic_cast<CelListViewItem*>(i)->getAppMag()) * 2 - 1;
307         if (col == 3) return (abs_mag > dynamic_cast<CelListViewItem*>(i)->getAbsMag()) * 2 - 1;
308         else return -1; // NOTE: Control should never reach here
309     }
310 }
311