1 /*
2  * Copyright (C) 2009 Matthew Gates
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
17  */
18 
19 #include "TextUserInterface.hpp"
20 #include "TuiNode.hpp"
21 #include "TuiNodeActivate.hpp"
22 #include "TuiNodeBool.hpp"
23 #include "TuiNodeInt.hpp"
24 #include "TuiNodeDouble.hpp"
25 #include "TuiNodeFloat.hpp"
26 #include "TuiNodeDateTime.hpp"
27 #include "TuiNodeColor.hpp"
28 #include "TuiNodeEnum.hpp"
29 
30 #include "StelProjector.hpp"
31 #include "StelPainter.hpp"
32 #include "StelApp.hpp"
33 #include "StelCore.hpp"
34 #include "StelLocaleMgr.hpp"
35 #include "StelModuleMgr.hpp"
36 #include "StarMgr.hpp"
37 #include "StelMovementMgr.hpp"
38 #include "StelObjectMgr.hpp"
39 #include "StelSkyDrawer.hpp"
40 #include "ConstellationMgr.hpp"
41 #include "NebulaMgr.hpp"
42 #include "SolarSystem.hpp"
43 #include "LandscapeMgr.hpp"
44 #include "GridLinesMgr.hpp"
45 #include "MilkyWay.hpp"
46 #include "ZodiacalLight.hpp"
47 #include "StelLocation.hpp"
48 #include "StelMainView.hpp"
49 #include "StelSkyCultureMgr.hpp"
50 #include "StelFileMgr.hpp"
51 #ifdef ENABLE_SCRIPTING
52 #include "StelScriptMgr.hpp"
53 #endif
54 #include "StelGui.hpp"
55 #include "StelGuiItems.hpp"// Funny thing to include in a TEXT user interface...
56 
57 #include <QKeyEvent>
58 #include <QDebug>
59 #include <QLabel>
60 #include <QTime>
61 #include <QProcess>
62 #include <QDir>
63 #include <QSettings>
64 
65 
66 /*************************************************************************
67  Utility functions
68 *************************************************************************/
colToConf(const Vec3f & c)69 QString colToConf(const Vec3f& c)
70 {
71 	return QString("%1,%2,%3").arg(c[0],2,'f',2).arg(c[1],2,'f',2).arg(c[2],2,'f',2);
72 }
73 
74 /*************************************************************************
75  This method is the one called automatically by the StelModuleMgr just
76  after loading the dynamic library
77 *************************************************************************/
getStelModule() const78 StelModule* TextUserInterfaceStelPluginInterface::getStelModule() const
79 {
80 	return new TextUserInterface();
81 }
82 
getPluginInfo() const83 StelPluginInfo TextUserInterfaceStelPluginInterface::getPluginInfo() const
84 {
85 	StelPluginInfo info;
86 	info.id = "TextUserInterface";
87 	info.displayedName = N_("Text User Interface");
88 	info.authors = "Matthew Gates";
89 	info.contact = STELLARIUM_DEV_URL;
90 	info.description = N_("Plugin implementation of 0.9.x series Text User Interface (TUI), used in planetarium systems");
91 	info.version = TUI_PLUGIN_VERSION;
92 	info.license = TUI_PLUGIN_LICENSE;
93 	return info;
94 }
95 
96 
97 /*************************************************************************
98  Constructor
99 *************************************************************************/
TextUserInterface()100 TextUserInterface::TextUserInterface()
101 	: dummyDialog(this)
102 	, tuiActive(false)
103 	, tuiDateTime(false)
104 	, tuiObjInfo(false)
105 	, tuiGravityUi(false)
106 	, currentNode(Q_NULLPTR)
107 {
108 	setObjectName("TextUserInterface");
109 }
110 
111 /*************************************************************************
112  Destructor
113 *************************************************************************/
~TextUserInterface()114 TextUserInterface::~TextUserInterface()
115 {
116 }
117 
118 /*************************************************************************
119  Reimplementation of the getCallOrder method
120 *************************************************************************/
getCallOrder(StelModuleActionName actionName) const121 double TextUserInterface::getCallOrder(StelModuleActionName actionName) const
122 {
123 	if (actionName==StelModule::ActionDraw)
124 		return StelApp::getInstance().getModuleMgr().getModule("LandscapeMgr")->getCallOrder(actionName)+10.;
125 	if (actionName==StelModule::ActionHandleKeys)
126 		return -1;
127 	return 0;
128 }
129 
130 
131 /*************************************************************************
132  Init our module
133 *************************************************************************/
init()134 void TextUserInterface::init()
135 {
136 	//Reusing translations: The translators will have to do less work if the
137 	//strings used here match strings used elsewhere. Do not change strings
138 	//unless you have a good reason. --BM
139 
140 	StelCore* core = StelApp::getInstance().getCore();
141 	// Main config.
142 	loadConfiguration();
143 	//Reusing strings from the location dialog
144 	TuiNode* m1 = new TuiNode(N_("Location"));
145 	m1->setParent(this);
146 	TuiNode* m1_1 = new TuiNodeDouble(N_("Latitude:"),
147 	                                  this, SLOT(setLatitude(double)),
148 					  getLatitude(), -90, 90, 0.5, m1);
149 	TuiNode* m1_2 = new TuiNodeDouble(N_("Longitude:"),
150 	                                  this, SLOT(setLongitude(double)),
151 	                                  getLongitude(), -180, 180, 0.5, m1, m1_1);
152 	TuiNode* m1_3 = new TuiNodeInt(N_("Altitude:"),
153 	                               this, SLOT(setAltitude(int)),
154 	                               core->getCurrentLocation().altitude,
155 				       -450, 200000, 100, m1, m1_2);
156 
157 	// TODO: Now new Solar System bodies can be added at runtime, so the list
158 	// needs to be populated every time this happens. --BM
159 	SolarSystem* solarSystem = GETSTELMODULE(SolarSystem);
160 	TuiNode* m1_4 = new TuiNodeEnum(N_("Solar System body"),
161 	                                this, SLOT(setHomePlanet(QString)),
162 	                                solarSystem->getAllPlanetEnglishNames(),
163 	                                core->getCurrentLocation().planetName,
164 	                                m1, m1_3);
165 	m1_1->setNextNode(m1_2);
166 	m1_2->setNextNode(m1_3);
167 	m1_3->setNextNode(m1_4);
168 	m1_4->setNextNode(m1_1);
169 	m1_1->loopToTheLast();
170 	m1->setChildNode(m1_1);
171 
172 	TuiNode* m2 = new TuiNode(N_("Date and Time"), Q_NULLPTR, m1);
173 	m2->setParent(this);
174 	m1->setNextNode(m2);
175 	TuiNode* m2_1 = new TuiNodeDateTime(N_("Current date/time"),
176 	                                    core,
177 					    SLOT(setJD(double)),
178 					    core->getJD(),
179 	                                    m2);
180 	TuiNode* m2_2 = new TuiNode(N_("Set time zone"), m2, m2_1); // GZ This is inactive(?)
181 	TuiNode* m2_3 = new TuiNode(N_("Day keys"), m2, m2_2);      // GZ This is inactive(?)
182 	TuiNode* m2_4 = new TuiNodeDateTime(N_("Startup date/time preset"),
183 					    core,
184 	                                    SLOT(setPresetSkyTime(double)),
185 					    core->getPresetSkyTime(),
186 					    m2, m2_3);
187 	QStringList startupModes;
188 	// TRANSLATORS: The current system time is used at startup
189 	startupModes << N_("system");
190 	// TRANSLATORS: A pre-set time is used at startup
191 	startupModes << N_("preset");
192 	TuiNode* m2_5 = new TuiNodeEnum(N_("Startup date and time"),
193 	                                this, SLOT(setStartupDateMode(QString)),
194 	                                startupModes,
195 									core->getStartupTimeMode(),
196 	                                m2, m2_4);
197 	StelLocaleMgr& localeMgr = StelApp::getInstance().getLocaleMgr();
198 	QStringList dateFormats;
199 	dateFormats << "system_default" << N_("mmddyyyy") << N_("ddmmyyyy") << N_("yyyymmdd");
200 	TuiNode* m2_6 = new TuiNodeEnum(N_("Date display format"), //Used in Time Zone plugin
201 	                                this, SLOT(setDateFormat(QString)),
202 	                                dateFormats,
203 	                                localeMgr.getDateFormatStr(),
204 	                                m2, m2_5);
205 	QStringList timeFormats;
206 	timeFormats << "system_default";
207 	// TRANSLATORS: 12-hour time format
208 	timeFormats << N_("12h");
209 	// TRANSLATORS: 24-hour time format
210 	timeFormats << N_("24h");
211 	TuiNode* m2_7 = new TuiNodeEnum(N_("Time display format"), //Used in Time Zone plugin
212 	                                this, SLOT(setTimeFormat(QString)),
213 	                                timeFormats,
214 	                                localeMgr.getTimeFormatStr(),
215 	                                m2, m2_6);
216 	m2_1->setNextNode(m2_2);
217 	m2_2->setNextNode(m2_3);
218 	m2_3->setNextNode(m2_4);
219 	m2_4->setNextNode(m2_5);
220 	m2_5->setNextNode(m2_6);
221 	m2_6->setNextNode(m2_7);
222 	m2_7->setNextNode(m2_1);
223 	m2_1->loopToTheLast();
224 	m2->setChildNode(m2_1);
225 
226 	TuiNode* m3 = new TuiNode(N_("General"), Q_NULLPTR, m2);
227 	m3->setParent(this);
228 	m2->setNextNode(m3);
229 	StelSkyCultureMgr& skyCultureMgr = StelApp::getInstance().getSkyCultureMgr();
230 	TuiNode* m3_1 = new TuiNodeEnum(N_("Starlore"),
231 	                                this,
232 	                                SLOT(setSkyCulture(QString)),
233 	                                skyCultureMgr.getSkyCultureListI18(),
234 	                                skyCultureMgr.getCurrentSkyCultureNameI18(),
235 	                                m3);
236 	TuiNode* m3_2 = new TuiNodeEnum(N_("Sky Language"),
237 	                                this,
238 					SLOT(setSkyLanguage(QString)),
239 					StelTranslator::globalTranslator->getAvailableLanguagesNamesNative(StelFileMgr::getLocaleDir()),
240 					StelTranslator::iso639_1CodeToNativeName(localeMgr.getSkyLanguage()),
241 	                                m3, m3_1);
242 	TuiNode* m3_3 = new TuiNodeEnum(N_("App Language"),
243 					this,
244 					SLOT(setAppLanguage(QString)),
245 					StelTranslator::globalTranslator->getAvailableLanguagesNamesNative(StelFileMgr::getLocaleDir()),
246 					StelTranslator::iso639_1CodeToNativeName(localeMgr.getAppLanguage()),
247 					m3, m3_1);
248 	m3_1->setNextNode(m3_2);
249 	m3_2->setNextNode(m3_3);
250 	m3_3->setNextNode(m3_1);
251 	m3_1->loopToTheLast();
252 	m3->setChildNode(m3_1);
253 
254 	TuiNode* m4 = new TuiNode(N_("Stars"), Q_NULLPTR, m3);
255 	m4->setParent(this);
256 	m3->setNextNode(m4);
257 	StarMgr* starMgr = GETSTELMODULE(StarMgr);
258 	TuiNode* m4_1 = new TuiNodeBool(N_("Show stars"),
259 	                                starMgr, SLOT(setFlagStars(bool)),
260 	                                starMgr->getFlagStars(), m4);
261 	StelSkyDrawer* skyDrawer = core->getSkyDrawer();
262 	TuiNode* m4_2 = new TuiNodeDouble(N_("Relative scale:"),
263 	                                  skyDrawer,
264 	                                  SLOT(setRelativeStarScale(double)),
265 	                                  skyDrawer->getRelativeStarScale(),
266 	                                  0.0, 5., 0.15,
267 	                                  m4, m4_1);
268 	TuiNode* m4_3 = new TuiNodeDouble(N_("Absolute scale:"),
269 	                                  skyDrawer,
270 	                                  SLOT(setAbsoluteStarScale(double)),
271 	                                  skyDrawer->getAbsoluteStarScale(),
272 	                                  0.0, 9., 0.15,
273 	                                  m4, m4_2);
274 	TuiNode* m4_4 = new TuiNodeDouble(N_("Twinkle:"),
275 	                                  skyDrawer, SLOT(setTwinkleAmount(double)),
276 	                                  skyDrawer->getTwinkleAmount(),
277 	                                  0.0, 1.5, 0.1,
278 	                                  m4, m4_3);
279 	m4_1->setNextNode(m4_2);
280 	m4_2->setNextNode(m4_3);
281 	m4_3->setNextNode(m4_4);
282 	m4_4->setNextNode(m4_1);
283 	m4_1->loopToTheLast();
284 	m4->setChildNode(m4_1);
285 
286 	TuiNode* m5 = new TuiNode(N_("Colors"), Q_NULLPTR, m4);
287 	m5->setParent(this);
288 	m4->setNextNode(m5);
289 	ConstellationMgr* constellationMgr = GETSTELMODULE(ConstellationMgr);
290 	TuiNode* m5_1 = new TuiNodeColor(N_("Constellation lines"),
291 	                                 constellationMgr,
292 	                                 SLOT(setLinesColor(Vec3f)),
293 	                                 constellationMgr->getLinesColor(),
294 	                                 m5);
295 	TuiNode* m5_2 = new TuiNodeColor(N_("Constellation labels"),
296 	                                 constellationMgr,
297 					 SLOT(setLabelsColor(Vec3f)),
298 	                                 constellationMgr->getLabelsColor(),
299 	                                 m5, m5_1);
300 //	TuiNode* m5_3 = new TuiNode(N_("Constellation art"), m5, m5_2); // dysfunctional duplicate dummy
301 	// TRANSLATORS: Refers to constellation art
302 	TuiNode* m5_3 = new TuiNodeFloat(N_("Art brightness:"),
303 					  constellationMgr,
304 					  SLOT(setArtIntensity(float)),
305 					  constellationMgr->getArtIntensity(),
306 					  0.0, 1.0, 0.05f,
307 					  m5, m5_2);
308 	TuiNode* m5_4 = new TuiNodeColor(N_("Constellation boundaries"),
309 	                                 constellationMgr,
310 	                                 SLOT(setBoundariesColor(Vec3f)),
311 	                                 constellationMgr->getBoundariesColor(),
312                                          m5, m5_3);
313 	LandscapeMgr* landscapeMgr = GETSTELMODULE(LandscapeMgr);
314 	TuiNode* m5_5 = new TuiNodeColor(N_("Cardinal points"),
315 	                                 landscapeMgr,
316 	                                 SLOT(setColorCardinalPoints(Vec3f)),
317 	                                 landscapeMgr->getColorCardinalPoints(),
318 					 m5, m5_4);
319 	TuiNode* m5_6 = new TuiNodeColor(N_("Planet labels"),
320 	                                 solarSystem, SLOT(setLabelsColor(Vec3f)),
321 	                                 solarSystem->getLabelsColor(),
322 					 m5, m5_5);
323 	TuiNode* m5_7 = new TuiNodeColor(N_("Planet orbits"),
324 	                                 solarSystem, SLOT(setOrbitsColor(Vec3f)),
325 	                                 solarSystem->getOrbitsColor(),
326 					 m5, m5_6);
327 	TuiNode* m5_8 = new TuiNodeColor(N_("Planet trails"),
328 	                                 solarSystem, SLOT(setTrailsColor(Vec3f)),
329 	                                 solarSystem->getTrailsColor(),
330 					 m5, m5_7);
331 	GridLinesMgr* gridLinesMgr = GETSTELMODULE(GridLinesMgr);
332 	TuiNode* m5_9 = new TuiNodeColor(N_("Meridian line"),
333 	                                 gridLinesMgr,
334 	                                 SLOT(setColorMeridianLine(Vec3f)),
335 	                                 gridLinesMgr->getColorMeridianLine(),
336 					 m5, m5_8);
337 	TuiNode* m5_10 = new TuiNodeColor(N_("Azimuthal grid"),
338 	                                 gridLinesMgr,
339 	                                 SLOT(setColorAzimuthalGrid(Vec3f)),
340 	                                 gridLinesMgr->getColorAzimuthalGrid(),
341 					 m5, m5_9);
342 	TuiNode* m5_11 = new TuiNodeColor(N_("Equatorial grid"),
343 	                                 gridLinesMgr,
344 	                                 SLOT(setColorEquatorGrid(Vec3f)),
345 	                                 gridLinesMgr->getColorEquatorGrid(),
346 					 m5, m5_10);
347 	TuiNode* m5_12 = new TuiNodeColor(N_("Equatorial J2000 grid"),
348 	                                 gridLinesMgr,
349 	                                 SLOT(setColorEquatorJ2000Grid(Vec3f)),
350 	                                 gridLinesMgr->getColorEquatorJ2000Grid(),
351 					 m5, m5_11);
352 	TuiNode* m5_13 = new TuiNodeColor(N_("Equator line"),
353 	                                 gridLinesMgr,
354 	                                 SLOT(setColorEquatorLine(Vec3f)),
355 	                                 gridLinesMgr->getColorEquatorLine(),
356 					 m5, m5_12);
357 	TuiNode* m5_14 = new TuiNodeColor(N_("Ecliptic line"),
358 	                                 gridLinesMgr,
359 	                                 SLOT(setColorEclipticLine(Vec3f)),
360 	                                 gridLinesMgr->getColorEclipticLine(),
361 					 m5, m5_13);
362 	TuiNode* m5_15 = new TuiNodeColor(N_("Ecliptic line (J2000)"),
363 					 gridLinesMgr,
364 					 SLOT(setColorEclipticJ2000Line(Vec3f)),
365 					 gridLinesMgr->getColorEclipticJ2000Line(),
366 					 m5, m5_14);
367 // TODO: Add all other lines/grids, sort and label in a consistent manner, and put DSO stuff behind. Update Guide.
368 	NebulaMgr* nebulaMgr = GETSTELMODULE(NebulaMgr);
369 	TuiNode* m5_16 = new TuiNodeColor(N_("Nebula names"),
370 	                                 nebulaMgr, SLOT(setLabelsColor(Vec3f)),
371 	                                 nebulaMgr->getLabelsColor(),
372 					 m5, m5_15);
373 	TuiNode* m5_17 = new TuiNodeColor(N_("Nebula hints"),
374 	                                  nebulaMgr, SLOT(setCirclesColor(Vec3f)),
375 	                                  nebulaMgr->getCirclesColor(),
376 					  m5, m5_16);
377 	TuiNode* m5_18 = new TuiNodeColor(N_("Galaxy hints"),
378 					  nebulaMgr, SLOT(setGalaxyColor(Vec3f)),
379 					  nebulaMgr->getGalaxyColor(),
380 					  m5, m5_17);
381 	TuiNode* m5_19 = new TuiNodeColor(N_("Dark nebulae hints"),
382 					  nebulaMgr, SLOT(setDarkNebulaColor(Vec3f)),
383 					  nebulaMgr->getDarkNebulaColor(),
384 					  m5, m5_18);
385 	TuiNode* m5_20 = new TuiNodeColor(N_("Clusters hints"),
386 					  nebulaMgr, SLOT(setClusterColor(Vec3f)),
387 					  nebulaMgr->getClusterColor(),
388 					  m5, m5_19);
389 	TuiNode* m5_21 = new TuiNodeColor(N_("Horizon line"),
390 					 gridLinesMgr,
391 					 SLOT(setColorHorizonLine(Vec3f)),
392 					 gridLinesMgr->getColorHorizonLine(),
393 					 m5, m5_20);
394 	TuiNode* m5_22 = new TuiNodeColor(N_("Galactic grid"),
395 					 gridLinesMgr,
396 					 SLOT(setColorGalacticGrid(Vec3f)),
397 					 gridLinesMgr->getColorGalacticGrid(),
398 					 m5, m5_21);
399 	TuiNode* m5_23 = new TuiNodeColor(N_("Galactic equator line"),
400 					 gridLinesMgr,
401 					 SLOT(setColorGalacticEquatorLine(Vec3f)),
402 					 gridLinesMgr->getColorGalacticEquatorLine(),
403 					 m5, m5_22);
404 	TuiNode* m5_24 = new TuiNodeColor(N_("Opposition/conjunction longitude line"),
405 					 gridLinesMgr,
406 					 SLOT(setColorLongitudeLine(Vec3f)),
407 					 gridLinesMgr->getColorLongitudeLine(),
408 					 m5, m5_23);
409 	StelMainView *mainView=&StelMainView::getInstance();
410 	TuiNode* m5_25 = new TuiNodeColor(N_("Sky Background (default: black)"),
411 					 mainView,
412 					 SLOT(setSkyBackgroundColor(Vec3f)),
413 					 mainView->getSkyBackgroundColor(),
414 					 m5, m5_24);
415 	m5_1->setNextNode(m5_2);
416 	m5_2->setNextNode(m5_3);
417 	m5_3->setNextNode(m5_4);
418 	m5_4->setNextNode(m5_5);
419 	m5_5->setNextNode(m5_6);
420 	m5_6->setNextNode(m5_7);
421 	m5_7->setNextNode(m5_8);
422 	m5_8->setNextNode(m5_9);
423 	m5_9->setNextNode(m5_10);
424 	m5_10->setNextNode(m5_11);
425 	m5_11->setNextNode(m5_12);
426 	m5_12->setNextNode(m5_13);
427 	m5_13->setNextNode(m5_14);
428 	m5_14->setNextNode(m5_15);
429 	m5_15->setNextNode(m5_16);
430 	m5_16->setNextNode(m5_17);
431 	m5_17->setNextNode(m5_18);
432 	m5_18->setNextNode(m5_19);
433 	m5_19->setNextNode(m5_20);
434 	m5_20->setNextNode(m5_21);
435 	m5_21->setNextNode(m5_22);
436 	m5_22->setNextNode(m5_23);
437 	m5_23->setNextNode(m5_24);
438 	m5_24->setNextNode(m5_25);
439 	m5_25->setNextNode(m5_1);
440 	m5_1->loopToTheLast();
441 	m5->setChildNode(m5_1);
442 
443 	TuiNode* m6 = new TuiNode(N_("Effects"), Q_NULLPTR, m5);
444 	m6->setParent(this);
445 	m5->setNextNode(m6);
446 	TuiNode* m6_1 = new TuiNodeInt(N_("Light pollution:"),
447 				       skyDrawer,
448 				       SLOT(setBortleScaleIndex(int)),
449 				       skyDrawer->getBortleScaleIndex(), 1, 9, 1,
450 	                               m6);
451 	TuiNode* m6_2 = new TuiNodeEnum(N_("Landscape"),
452 	                                landscapeMgr,
453 	                                SLOT(setCurrentLandscapeName(QString)),
454 	                                landscapeMgr->getAllLandscapeNames(),
455 	                                landscapeMgr->getCurrentLandscapeName(),
456 	                                m6, m6_1);
457 	TuiNode* m6_3 = new TuiNodeBool(N_("Setting landscape sets location"),
458 					landscapeMgr,
459 					SLOT(setFlagLandscapeSetsLocation(bool)),
460 					landscapeMgr->getFlagLandscapeSetsLocation(),
461 					m6, m6_2);
462 	StelMovementMgr* movementMgr = GETSTELMODULE(StelMovementMgr);
463 	TuiNode* m6_4 = new TuiNodeBool(N_("Auto zoom out returns to initial direction of view"),
464 	                                movementMgr,
465 	                                SLOT(setFlagAutoZoomOutResetsDirection(bool)),
466 	                                movementMgr->getFlagAutoZoomOutResetsDirection(),
467 					m6, m6_3);
468 	TuiNode* m6_5 = new TuiNodeFloat(N_("Zoom duration:"),
469 					 movementMgr,
470 					 SLOT(setAutoMoveDuration(float)),
471 					 movementMgr->getAutoMoveDuration(),
472 					 0, 20.0, 0.1f,
473 					 m6, m6_4);
474 	TuiNode* m6_6 = new TuiNodeDouble(N_("Milky Way intensity:"),
475 	                                 GETSTELMODULE(MilkyWay),
476 					 SLOT(setIntensity(double)),
477 	                                 GETSTELMODULE(MilkyWay)->getIntensity(),
478 	                                 0, 10.0, 0.1,
479 					 m6, m6_5);
480 	TuiNode* m6_7 = new TuiNodeDouble(N_("Zodiacal light intensity:"),
481 					 GETSTELMODULE(ZodiacalLight),
482 					 SLOT(setIntensity(double)),
483 					 GETSTELMODULE(ZodiacalLight)->getIntensity(),
484 					 0, 10.0, 0.1,
485 					 m6, m6_6);
486 	m6_1->setNextNode(m6_2);
487 	m6_2->setNextNode(m6_3);
488 	m6_3->setNextNode(m6_4);
489 	m6_4->setNextNode(m6_5);
490 	m6_5->setNextNode(m6_6);
491 	m6_6->setNextNode(m6_7);
492 	m6_7->setNextNode(m6_1);
493 	m6_1->loopToTheLast();
494 	m6->setChildNode(m6_1);
495 
496 	#ifdef ENABLE_SCRIPTING
497 	TuiNode* m7 = new TuiNode(N_("Scripts"), Q_NULLPTR, m6);
498 	m7->setParent(this);
499 	m6->setNextNode(m7);
500 	StelScriptMgr& scriptMgr = StelApp::getInstance().getScriptMgr();
501 	TuiNode* m7_1 = new TuiNodeEnum(N_("Run local script"),
502 	                                &scriptMgr,
503 	                                SLOT(runScript(QString)),
504 	                                scriptMgr.getScriptList(),
505 	                                "",
506 	                                m7);
507 	TuiNode* m7_2 = new TuiNodeActivate(N_("Stop running script"),
508 	                                    &scriptMgr, SLOT(stopScript()),
509 	                                    m7, m7_1);
510 //	TuiNode* m7_3 = new TuiNode(N_("CD/DVD script"), m7, m7_2); // Dead node.
511 	m7_1->setNextNode(m7_2);
512 	m7_2->setNextNode(m7_1);
513 //	m7_3->setNextNode(m7_1);
514 	m7_1->loopToTheLast();
515 	m7->setChildNode(m7_1);
516 
517 
518 	TuiNode* m8 = new TuiNode(N_("Administration"), Q_NULLPTR, m7);
519 	m8->setParent(this);
520 	m7->setNextNode(m8);
521 	#else
522 	TuiNode* m8 = new TuiNode(N_("Administration"), Q_NULLPTR, m6);
523 	m8->setParent(this);
524 	m6->setNextNode(m8);
525 	#endif
526 	m8->setNextNode(m1);
527 	m1->loopToTheLast();
528 	TuiNode* m8_1 = new TuiNode(N_("Load default configuration"), m8);
529 	TuiNode* m8_2 = new TuiNodeActivate(N_("Save current configuration"),
530 	                                    this, SLOT(saveDefaultSettings()),
531 	                                    m8, m8_1);
532 	TuiNode* m8_3 = new TuiNodeActivate(N_("Shut down"), this, SLOT(shutDown()),
533 					    m8, m8_2);
534 	m8_1->setNextNode(m8_2);
535 	m8_2->setNextNode(m8_3);
536 	m8_3->setNextNode(m8_1);
537 	m8_1->loopToTheLast();
538 	m8->setChildNode(m8_1);
539 
540 
541 	currentNode = m1;
542 }
543 
544 /*************************************************************************
545  Load settings from configuration file.
546 *************************************************************************/
loadConfiguration(void)547 void TextUserInterface::loadConfiguration(void)
548 {
549 	QSettings* conf = StelApp::getInstance().getSettings();
550 	Q_ASSERT(conf);
551 
552 	font.setPixelSize(conf->value("tui/tui_font_size", 15).toInt());
553 	tuiDateTime = conf->value("tui/flag_show_tui_datetime", false).toBool();
554 	tuiObjInfo = conf->value("tui/flag_show_tui_short_obj_info", false).toBool();
555 	tuiGravityUi = conf->value("tui/flag_show_gravity_ui", false).toBool();
556 	color = Vec3f(conf->value("tui/tui_font_color", "0.3,1,0.3").toString());
557 }
558 
559 /*************************************************************************
560  Draw our module.
561 *************************************************************************/
draw(StelCore * core)562 void TextUserInterface::draw(StelCore* core)
563 {
564 	if (!tuiActive && !tuiDateTime && !tuiObjInfo)
565 		return;
566 
567 	int x = 0, y = 0;
568 	int xVc = 0, yVc = 0;
569 	int pixOffset = 15;
570 	int fovOffsetX = 0, fovOffsetY=0;
571 	bool fovMaskDisk = false;
572 
573 	StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
574 	if (gui!=Q_NULLPTR)
575 	{
576 		if (gui->getVisible())
577 		{
578 			QGraphicsItem* bottomBar = dynamic_cast<QGraphicsItem*>(gui->getButtonBar());
579 			LeftStelBar* sideBar = gui->getWindowsButtonBar();
580 			x = (sideBar) ? qRound(sideBar->boundingRectNoHelpLabel().right()) : 50;
581 			y = (bottomBar) ? qRound(bottomBar->boundingRect().height()) : 50;
582 		}
583 	}
584 
585 	// Alternate x,y for Disk viewport
586 	if (core->getProjection(StelCore::FrameJ2000)->getMaskType() == StelProjector::MaskDisk)
587 	{
588 		fovMaskDisk = true;
589 		StelProjector::StelProjectorParams projParams = core->getCurrentStelProjectorParams();
590 		xVc = qRound(projParams.viewportCenter[0]);
591 		yVc = qRound(projParams.viewportCenter[1]);
592 		fovOffsetX = qRound(projParams.viewportFovDiameter*std::sin(20.))/2;
593 		fovOffsetY = qRound(projParams.viewportFovDiameter*std::cos(20.))/2;
594 	}
595 	else
596 	{
597 		xVc = core->getProjection(StelCore::FrameJ2000)->getViewportWidth()/2;
598 	}
599 
600 	if (tuiActive)
601 	{
602 		int text_x = x + pixOffset, text_y = y + pixOffset;
603 		if (fovMaskDisk) {
604 			text_x = xVc - fovOffsetX + pixOffset;
605 			text_y = yVc - fovOffsetY + pixOffset;
606 		}
607 
608 		QString tuiText = q_("[no TUI node]");
609 		if (currentNode!=Q_NULLPTR) {
610 			tuiText = currentNode->getDisplayText();
611 		}
612 
613 		StelPainter painter(core->getProjection(StelCore::FrameJ2000));
614 		painter.setFont(font);
615 		painter.setColor(color[0],color[1],color[2]);
616 		painter.drawText(text_x, text_y, tuiText, 0, 0, 0, !tuiGravityUi);
617 	}
618 
619 	if (tuiDateTime)
620 	{
621 		double jd = core->getJD();
622 		int text_x = x + xVc*2/3, text_y = y + pixOffset;
623 
624 		QString newDate = StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(jd) + "   "
625                        +StelApp::getInstance().getLocaleMgr().getPrintableTimeLocal(jd);
626 
627 		if (fovMaskDisk) {
628 			text_x = xVc + fovOffsetY - pixOffset;
629 			text_y = yVc - fovOffsetX + pixOffset;
630 		}
631 
632 		StelPainter painter(core->getProjection(StelCore::FrameAltAz));
633 		painter.setFont(font);
634 		painter.setColor(color[0],color[1],color[2]);
635 		painter.drawText(text_x, text_y, newDate, 0, 0, 0, !tuiGravityUi);
636 	}
637 
638 	if (tuiObjInfo)
639 	{
640 		QString objInfo = "";
641 		StelObject::InfoStringGroup tuiInfo(StelObject::Name|StelObject::CatalogNumber
642 				|StelObject::Distance|StelObject::PlainText);
643 		int text_x = x + xVc*4/3, text_y = y + pixOffset;
644 
645 		QList<StelObjectP> selectedObj = GETSTELMODULE(StelObjectMgr)->getSelectedObject();
646 		if (selectedObj.isEmpty()) {
647 			objInfo = "";
648 		} else {
649 			objInfo = selectedObj[0]->getInfoString(core, tuiInfo);
650 			objInfo.replace("\n"," ");
651 			objInfo.replace("Distance:"," ");
652 			objInfo.replace("Light Years","ly");
653 		}
654 
655 		if (fovMaskDisk) {
656 			text_x = xVc + fovOffsetX - pixOffset;
657 			text_y = yVc + fovOffsetY - pixOffset;
658 		}
659 
660 		StelPainter painter(core->getProjection(StelCore::FrameJ2000));
661 		painter.setFont(font);
662 		painter.setColor(color[0],color[1],color[2]);
663 		painter.drawText(text_x, text_y, objInfo, 0, 0, 0, !tuiGravityUi);
664 	}
665 }
666 
handleKeys(QKeyEvent * event)667 void TextUserInterface::handleKeys(QKeyEvent* event)
668 {
669 	if (currentNode == Q_NULLPTR)
670 	{
671 		qWarning() << "WARNING: no current node in TextUserInterface plugin";
672 		event->setAccepted(false);
673 		return;
674 	}
675 
676 	if (event->type()==QEvent::KeyPress && (event->modifiers() & Qt::AltModifier) &&  event->key()==Qt::Key_T)
677 	{
678 		tuiActive = ! tuiActive;
679 		dummyDialog.close();
680 		event->setAccepted(true);
681 		return;
682 	}
683 
684 	if (!tuiActive)
685 	{
686 		event->setAccepted(false);
687 		return;
688 	}
689 
690 	if (event->type()==QEvent::KeyPress)
691 	{
692 		TuiNodeResponse response = currentNode->handleKey(event->key());
693 		if (response.accepted)
694 		{
695 			currentNode = response.newNode;
696 			event->setAccepted(true);
697 		}
698 		else
699 		{
700 			event->setAccepted(false);
701 		}
702 		return;
703 	}
704 }
705 
setHomePlanet(QString planetName)706 void TextUserInterface::setHomePlanet(QString planetName)
707 {
708 	StelCore* core = StelApp::getInstance().getCore();
709 	if (core->getCurrentLocation().planetName != planetName)
710 	{
711 		StelLocation newLocation = core->getCurrentLocation();
712 		newLocation.planetName = planetName;
713 		core->moveObserverTo(newLocation);
714 	}
715 }
716 
setAltitude(int altitude)717 void TextUserInterface::setAltitude(int altitude)
718 {
719 	StelCore* core = StelApp::getInstance().getCore();
720 	if (core->getCurrentLocation().altitude != altitude)
721 	{
722 		StelLocation newLocation = core->getCurrentLocation();
723 		newLocation.altitude = altitude;
724 		core->moveObserverTo(newLocation, 0.0, 0.0);
725 	}
726 }
727 
setLatitude(double latitude)728 void TextUserInterface::setLatitude(double latitude)
729 {
730 	StelCore* core = StelApp::getInstance().getCore();
731 	if (core->getCurrentLocation().latitude != latitude)
732 	{
733 		StelLocation newLocation = core->getCurrentLocation();
734 		newLocation.latitude = static_cast<float>(latitude);
735 		core->moveObserverTo(newLocation, 0.0, 0.0);
736 	}
737 }
738 
setLongitude(double longitude)739 void TextUserInterface::setLongitude(double longitude)
740 {
741 	StelCore* core = StelApp::getInstance().getCore();
742 	if (core->getCurrentLocation().longitude != longitude)
743 	{
744 		StelLocation newLocation = core->getCurrentLocation();
745 		newLocation.longitude = static_cast<float>(longitude);
746 		core->moveObserverTo(newLocation, 0.0, 0.0);
747 	}
748 }
749 
getLatitude(void)750 double TextUserInterface::getLatitude(void)
751 {
752 	return static_cast<double>(StelApp::getInstance().getCore()->getCurrentLocation().latitude);
753 }
754 
getLongitude(void)755 double TextUserInterface::getLongitude(void)
756 {
757 	return static_cast<double>(StelApp::getInstance().getCore()->getCurrentLocation().longitude);
758 }
759 
setStartupDateMode(QString mode)760 void TextUserInterface::setStartupDateMode(QString mode)
761 {
762 	StelApp::getInstance().getCore()->setStartupTimeMode(mode);
763 }
764 
setDateFormat(QString format)765 void TextUserInterface::setDateFormat(QString format)
766 {
767 	StelApp::getInstance().getLocaleMgr().setDateFormatStr(format);
768 }
769 
setTimeFormat(QString format)770 void TextUserInterface::setTimeFormat(QString format)
771 {
772 	StelApp::getInstance().getLocaleMgr().setTimeFormatStr(format);
773 }
774 
setSkyCulture(QString i18)775 void TextUserInterface::setSkyCulture(QString i18)
776 {
777 	StelApp::getInstance().getSkyCultureMgr().setCurrentSkyCultureNameI18(i18);
778 }
779 
setAppLanguage(QString lang)780 void TextUserInterface::setAppLanguage(QString lang)
781 {
782 	QString code = StelTranslator::nativeNameToIso639_1Code(lang);
783 	StelApp::getInstance().getLocaleMgr().setAppLanguage(code);
784 }
785 
setSkyLanguage(QString lang)786 void TextUserInterface::setSkyLanguage(QString lang)
787 {
788 	QString code = StelTranslator::nativeNameToIso639_1Code(lang);
789 	StelApp::getInstance().getLocaleMgr().setSkyLanguage(code);
790 }
791 
saveDefaultSettings(void)792 void TextUserInterface::saveDefaultSettings(void)
793 {
794 	QSettings* conf = StelApp::getInstance().getSettings();
795 	Q_ASSERT(conf);
796 
797 	LandscapeMgr* lmgr = GETSTELMODULE(LandscapeMgr);
798 	Q_ASSERT(lmgr);
799 	SolarSystem* ssmgr = GETSTELMODULE(SolarSystem);
800 	Q_ASSERT(ssmgr);
801 	StelSkyDrawer* skyd = StelApp::getInstance().getCore()->getSkyDrawer();
802 	Q_ASSERT(skyd);
803 	ConstellationMgr* cmgr = GETSTELMODULE(ConstellationMgr);
804 	Q_ASSERT(cmgr);
805 	StarMgr* smgr = GETSTELMODULE(StarMgr);
806 	Q_ASSERT(smgr);
807 	NebulaMgr* nmgr = GETSTELMODULE(NebulaMgr);
808 	Q_ASSERT(nmgr);
809 	GridLinesMgr* glmgr = GETSTELMODULE(GridLinesMgr);
810 	Q_ASSERT(glmgr);
811 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
812 	Q_ASSERT(mvmgr);
813 	StelCore* core = StelApp::getInstance().getCore();
814 	Q_ASSERT(core);
815 	MilkyWay* milk = GETSTELMODULE(MilkyWay);
816 	Q_ASSERT(milk);
817 	const StelProjectorP proj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameJ2000);
818 	Q_ASSERT(proj);
819 	StelLocaleMgr& lomgr = StelApp::getInstance().getLocaleMgr();
820 
821 	// MENU ITEMS
822 	// sub-menu 1: location
823 	// TODO
824 
825 
826 	// sub-menu 2: date and time
827 	conf->setValue("navigation/preset_sky_time", core->getPresetSkyTime());
828 	conf->setValue("navigation/startup_time_mode", core->getStartupTimeMode());
829 	conf->setValue("navigation/startup_time_mode", core->getStartupTimeMode());
830 	conf->setValue("localization/time_display_format", lomgr.getTimeFormatStr());
831 	conf->setValue("localization/date_display_format", lomgr.getDateFormatStr());
832 
833 
834 	// sub-menu 3: general
835 	StelApp::getInstance().getSkyCultureMgr().setDefaultSkyCultureID(StelApp::getInstance().getSkyCultureMgr().getCurrentSkyCultureID());
836 	QString langName = lomgr.getAppLanguage();
837 	conf->setValue("localization/app_locale", StelTranslator::nativeNameToIso639_1Code(langName));
838 	langName = StelApp::getInstance().getLocaleMgr().getSkyLanguage();
839 	conf->setValue("localization/sky_locale", StelTranslator::nativeNameToIso639_1Code(langName));
840 
841 	// sub-menu 4: stars
842 	conf->setValue("astro/flag_stars", smgr->getFlagStars());
843 	conf->setValue("stars/absolute_scale", skyd->getAbsoluteStarScale());
844 	conf->setValue("stars/relative_scale", skyd->getRelativeStarScale());
845 	conf->setValue("stars/flag_star_twinkle", skyd->getFlagTwinkle());
846 
847 	// sub-menu 5: colors
848 	conf->setValue("color/const_lines_color", colToConf(cmgr->getLinesColor()));
849  	conf->setValue("color/const_names_color", colToConf(cmgr->getLabelsColor()));
850 	conf->setValue("color/const_boundary_color", colToConf(cmgr->getBoundariesColor()));
851 	conf->setValue("viewing/constellation_art_intensity", cmgr->getArtIntensity());
852 	conf->setValue("color/cardinal_color", colToConf(lmgr->getColorCardinalPoints()) );
853 	conf->setValue("color/planet_names_color", colToConf(ssmgr->getLabelsColor()));
854 	conf->setValue("color/planet_orbits_color", colToConf(ssmgr->getOrbitsColor()));
855 	conf->setValue("color/object_trails_color", colToConf(ssmgr->getTrailsColor()));
856 	conf->setValue("color/meridian_color", colToConf(glmgr->getColorMeridianLine()));
857 	conf->setValue("color/oc_longitude_color", colToConf(glmgr->getColorLongitudeLine()));
858 	conf->setValue("color/azimuthal_color", colToConf(glmgr->getColorAzimuthalGrid()));
859 	conf->setValue("color/equator_color", colToConf(glmgr->getColorEquatorGrid()));
860 	conf->setValue("color/equatorial_J2000_color", colToConf(glmgr->getColorEquatorJ2000Grid()));
861 	conf->setValue("color/equator_color", colToConf(glmgr->getColorEquatorLine()));
862 	conf->setValue("color/ecliptic_color", colToConf(glmgr->getColorEclipticLine()));
863 	conf->setValue("color/nebula_label_color", colToConf(nmgr->getLabelsColor()));
864 	conf->setValue("color/nebula_circle_color", colToConf(nmgr->getCirclesColor()));
865 
866 	// sub-menu 6: effects
867 	conf->setValue("stars/init_bortle_scale", skyd->getBortleScaleIndex());
868 	lmgr->setDefaultLandscapeID(lmgr->getCurrentLandscapeID());
869 	conf->setValue("navigation/auto_zoom_out_resets_direction", mvmgr->getFlagAutoZoomOutResetsDirection());
870 	conf->setValue("astro/milky_way_intensity", milk->getIntensity());
871 	conf->setValue("navigation/auto_move_duration", mvmgr->getAutoMoveDuration());
872 	conf->setValue("landscape/flag_landscape_sets_location", lmgr->getFlagLandscapeSetsLocation());
873 
874 	// GLOBAL DISPLAY SETTINGS
875 	// TODO
876 
877 	qDebug() << "TextUserInterface::saveDefaultSettings done";
878 }
879 
shutDown()880 void TextUserInterface::shutDown()
881 {
882 	QSettings* conf = StelApp::getInstance().getSettings();
883 	QString shutdownCmd = QDir::fromNativeSeparators(conf->value("tui/admin_shutdown_cmd", "").toString());
884 	int err;
885 	if (!(err = QProcess::execute(shutdownCmd))) {
886 		qDebug() << "[TextUserInterface] shutdown error, QProcess::execute():" << err;
887 	}
888 }
889