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