1 /*
2 * Stellarium Telescope Control Plug-in
3 *
4 * Copyright (C) 2009-2011 Bogdan Marinov (this file)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
19 */
20
21 #include "Dialog.hpp"
22 #include "StelApp.hpp"
23 #include "StelCore.hpp"
24 #include "StelModuleMgr.hpp"
25 #include "StelFileMgr.hpp"
26 #include "StelLocaleMgr.hpp"
27 #include "StelStyle.hpp"
28 #include "StelTranslator.hpp"
29 #include "TelescopeControl.hpp"
30 #include "TelescopeConfigurationDialog.hpp"
31 #include "TelescopeDialog.hpp"
32 #include "ui_telescopeDialog.h"
33 #include "StelGui.hpp"
34 #include <QDebug>
35 #include <QFrame>
36 #include <QTimer>
37 #include <QFile>
38 #include <QFileDialog>
39 #include <QHash>
40 #include <QHeaderView>
41 #include <QSettings>
42 #include <QStandardItem>
43 #include <QRegularExpression>
44
45 using namespace TelescopeControlGlobals;
46
47
TelescopeDialog()48 TelescopeDialog::TelescopeDialog()
49 : StelDialog("TelescopeControl")
50 , telescopeCount(0)
51 , configuredSlot(0)
52 , configuredTelescopeIsNew(false)
53 {
54 telescopeStatus[0] = StatusNA;
55 telescopeType[0] = ConnectionNA;
56
57 ui = new Ui_telescopeDialogForm;
58
59 //TODO: Fix this - it's in the same plugin
60 telescopeManager = GETSTELMODULE(TelescopeControl);
61 telescopeListModel = new QStandardItemModel(0, ColumnCount);
62
63 //TODO: This shouldn't be a hash...
64 statusString[StatusNA] = QString(N_("N/A"));
65 statusString[StatusStarting] = QString(N_("Starting"));
66 statusString[StatusConnecting] = QString(N_("Connecting"));
67 statusString[StatusConnected] = QString(N_("Connected"));
68 statusString[StatusDisconnected] = QString(N_("Disconnected"));
69 statusString[StatusStopped] = QString(N_("Stopped"));
70 }
71
~TelescopeDialog()72 TelescopeDialog::~TelescopeDialog()
73 {
74 delete ui;
75
76 delete telescopeListModel;
77 }
78
retranslate()79 void TelescopeDialog::retranslate()
80 {
81 if (dialog)
82 {
83 ui->retranslateUi(dialog);
84 setAboutText();
85 setHeaderNames();
86 updateWarningTexts();
87
88 //Retranslate type strings
89 for (int i = 0; i < telescopeListModel->rowCount(); i++)
90 {
91 QStandardItem* item = telescopeListModel->item(i, ColumnType);
92 QString original = item->data(Qt::UserRole).toString();
93 QModelIndex index = telescopeListModel->index(i, ColumnType);
94 telescopeListModel->setData(index, q_(original), Qt::DisplayRole);
95 }
96 }
97 }
98
99 // Initialize the dialog widgets and connect the signals/slots
createDialogContent()100 void TelescopeDialog::createDialogContent()
101 {
102 ui->setupUi(dialog);
103
104 // Kinetic scrolling
105 kineticScrollingList << ui->telescopeTreeView << ui->textBrowserHelp << ui->textBrowserAbout;
106 StelGui* gui= dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
107 if (gui)
108 {
109 enableKineticScrolling(gui->getFlagUseKineticScrolling());
110 connect(gui, SIGNAL(flagUseKineticScrollingChanged(bool)), this, SLOT(enableKineticScrolling(bool)));
111 }
112
113 //Inherited connect
114 connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslate()));
115 connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close()));
116 connect(ui->TitleBar, SIGNAL(movedTo(QPoint)), this, SLOT(handleMovedTo(QPoint)));
117
118 //Connect: sender, signal, receiver, method
119 //Page: Telescopes
120 connect(ui->pushButtonChangeStatus, SIGNAL(clicked()), this, SLOT(buttonChangeStatusPressed()));
121 connect(ui->pushButtonConfigure, SIGNAL(clicked()), this, SLOT(buttonConfigurePressed()));
122 connect(ui->pushButtonAdd, SIGNAL(clicked()), this, SLOT(buttonAddPressed()));
123 connect(ui->pushButtonRemove, SIGNAL(clicked()), this, SLOT(buttonRemovePressed()));
124
125 connect(ui->telescopeTreeView, SIGNAL(clicked (const QModelIndex &)), this, SLOT(selectTelecope(const QModelIndex &)));
126 //connect(ui->telescopeTreeView, SIGNAL(activated (const QModelIndex &)), this, SLOT(configureTelescope(const QModelIndex &)));
127
128 //Page: Options:
129 connect(ui->checkBoxReticles, SIGNAL(clicked(bool)),
130 telescopeManager, SLOT(setFlagTelescopeReticles(bool)));
131 connect(ui->checkBoxLabels, SIGNAL(clicked(bool)),
132 telescopeManager, SLOT(setFlagTelescopeLabels(bool)));
133 connect(ui->checkBoxCircles, SIGNAL(clicked(bool)),
134 telescopeManager, SLOT(setFlagTelescopeCircles(bool)));
135
136 connect(ui->checkBoxEnableLogs, SIGNAL(toggled(bool)), telescopeManager, SLOT(setFlagUseTelescopeServerLogs(bool)));
137
138 connect(ui->checkBoxUseExecutables, SIGNAL(toggled(bool)), ui->labelExecutablesDirectory, SLOT(setEnabled(bool)));
139 connect(ui->checkBoxUseExecutables, SIGNAL(toggled(bool)), ui->lineEditExecutablesDirectory, SLOT(setEnabled(bool)));
140 connect(ui->checkBoxUseExecutables, SIGNAL(toggled(bool)), ui->pushButtonPickExecutablesDirectory, SLOT(setEnabled(bool)));
141 connect(ui->checkBoxUseExecutables, SIGNAL(toggled(bool)), this, SLOT(checkBoxUseExecutablesToggled(bool)));
142
143 connect(ui->pushButtonPickExecutablesDirectory, SIGNAL(clicked()), this, SLOT(buttonBrowseServerDirectoryPressed()));
144
145 //In other dialogs:
146 connect(&configurationDialog, SIGNAL(changesDiscarded()), this, SLOT(discardChanges()));
147 connect(&configurationDialog, SIGNAL(changesSaved(QString, ConnectionType)), this, SLOT(saveChanges(QString, ConnectionType)));
148
149 //Initialize the style
150 updateStyle();
151
152 //Initializing the list of telescopes
153 telescopeListModel->setColumnCount(ColumnCount);
154 setHeaderNames();
155
156 ui->telescopeTreeView->setModel(telescopeListModel);
157 ui->telescopeTreeView->header()->setSectionsMovable(false);
158 ui->telescopeTreeView->header()->setSectionResizeMode(ColumnSlot, QHeaderView::ResizeToContents);
159 ui->telescopeTreeView->header()->setStretchLastSection(true);
160
161 //Populating the list
162 //Cycle the slots
163 for (int slotNumber = MIN_SLOT_NUMBER; slotNumber < SLOT_NUMBER_LIMIT; slotNumber++)
164 {
165 //Slot #
166 //int slotNumber = (i+1)%SLOT_COUNT;//Making sure slot 0 is last
167
168 //Make sure that this is initialized for all slots
169 telescopeStatus[slotNumber] = StatusNA;
170
171 //Read the telescope properties
172 QString name;
173 ConnectionType connectionType;
174 QString equinox;
175 QString host;
176 int portTCP;
177 int delay;
178 bool connectAtStartup;
179 QList<double> circles;
180 QString serverName;
181 QString portSerial;
182 QString rts2Url;
183 QString rts2Username;
184 QString rts2Password;
185 int rts2Refresh;
186 QString ascomDeviceId;
187 bool ascomUseDeviceEqCoordType;
188
189 if(!telescopeManager->getTelescopeAtSlot(slotNumber, connectionType, name, equinox, host, portTCP, delay, connectAtStartup, circles, serverName, portSerial, rts2Url, rts2Username, rts2Password, rts2Refresh, ascomDeviceId, ascomUseDeviceEqCoordType))
190 continue;
191
192 //Determine the server type
193 telescopeType[slotNumber] = connectionType;
194
195 //Determine the telescope's status
196 if (telescopeManager->isConnectedClientAtSlot(slotNumber))
197 {
198 telescopeStatus[slotNumber] = StatusConnected;
199 }
200 else
201 {
202 //TODO: Fix this!
203 //At startup everything exists and attempts to connect
204 telescopeStatus[slotNumber] = StatusConnecting;
205 }
206
207 addModelRow(slotNumber, connectionType, telescopeStatus[slotNumber], name);
208
209 //After everything is done, count this as loaded
210 telescopeCount++;
211 }
212
213 //Finished populating the table, let's sort it by slot number
214 //ui->telescopeTreeView->setSortingEnabled(true);//Set in the .ui file
215 ui->telescopeTreeView->sortByColumn(ColumnSlot, Qt::AscendingOrder);
216 //(Works even when the table is empty)
217 //(Makes redundant the delay of 0 above)
218
219 //TODO: Reuse code.
220 if(telescopeCount > 0)
221 {
222 ui->telescopeTreeView->setFocus();
223 ui->telescopeTreeView->header()->setSectionResizeMode(ColumnType, QHeaderView::ResizeToContents);
224 }
225 else
226 {
227 ui->pushButtonChangeStatus->setEnabled(false);
228 ui->pushButtonConfigure->setEnabled(false);
229 ui->pushButtonRemove->setEnabled(false);
230 ui->pushButtonAdd->setFocus();
231 }
232 updateWarningTexts();
233
234 if(telescopeCount >= SLOT_COUNT)
235 ui->pushButtonAdd->setEnabled(false);
236
237 //Checkboxes
238 ui->checkBoxReticles->setChecked(telescopeManager->getFlagTelescopeReticles());
239 ui->checkBoxLabels->setChecked(telescopeManager->getFlagTelescopeLabels());
240 ui->checkBoxCircles->setChecked(telescopeManager->getFlagTelescopeCircles());
241 ui->checkBoxEnableLogs->setChecked(telescopeManager->getFlagUseTelescopeServerLogs());
242
243 //Telescope server directory
244 ui->checkBoxUseExecutables->setChecked(telescopeManager->getFlagUseServerExecutables());
245 ui->lineEditExecutablesDirectory->setText(telescopeManager->getServerExecutablesDirectoryPath());
246
247 //About page
248 setAboutText();
249
250 //Everything must be initialized by now, start the updateTimer
251 //TODO: Find if it's possible to run it only when the dialog is visible
252 QTimer* updateTimer = new QTimer(this);
253 connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateTelescopeStates()));
254 updateTimer->start(200);
255 }
256
setAboutText()257 void TelescopeDialog::setAboutText()
258 {
259 // Regexp to replace {text} with an HTML link.
260 QRegularExpression a_rx("[{]([^{]*)[}]");
261
262 //TODO: Expand
263 QString aboutPage = "<html><head></head><body>";
264 aboutPage += "<h2>" + q_("Telescope Control plug-in") + "</h2><table width=\"90%\">";
265 aboutPage += "<tr width=\"30%\"><td><strong>" + q_("Version") + ":</strong></td><td>" + TELESCOPE_CONTROL_PLUGIN_VERSION + "</td></tr>";
266 aboutPage += "<tr><td><strong>" + q_("License") + ":</strong></td><td>" + TELESCOPE_CONTROL_PLUGIN_LICENSE + "</td></tr>";
267 aboutPage += "<tr><td rowspan=5><strong>" + q_("Authors") + "</strong></td><td>Johannes Gajdosik</td></td>";
268 aboutPage += "<tr><td>Bogdan Marinov <bogdan.marinov84@gmail.com> (" + q_("Plug-in and GUI programming") + ")</td></tr>";
269 aboutPage += "<tr><td>Gion Kunz <gion.kunz@gmail.com> (" + q_("ASCOM Telescope Client") + ")</td></tr>";
270 aboutPage += "<tr><td>Petr Kubánek (" + q_("RTS2 support") + ")</td></tr>";
271 aboutPage += "<tr><td>Alessandro Siniscalchi <asiniscalchi@gmail.com> (" + q_("INDI Telescope Client") + ")</td></tr>";
272 aboutPage += "<tr><td rowspan=3><strong>" + q_("Contributors") + ":</strong></td><td>Alexander Wolf</td></tr>";
273 aboutPage += "<tr><td>Michael Heinz</td></tr>";
274 aboutPage += "<tr><td>Alexandros Kosiaris</td></tr>";
275 aboutPage += "</table>";
276
277 aboutPage += "<p>" + q_("This plug-in is based on and reuses a lot of code under the GNU General Public License:") + "</p><ul>";
278 aboutPage += "<li>" + q_("the Telescope, TelescopeDummy, TelescopeTcp and TelescopeMgr classes in Stellarium's code (the client side of Stellarium's original telescope control feature);") + "</li>";
279 aboutPage += "<li>" + q_("the telescope server core code (licensed under the LGPL)") + "</li>";
280 aboutPage += "<li>" + q_("the TelescopeServerLx200 telescope server core code (originally licensed under the LGPL)");
281 aboutPage += "<br/>" + q_("Author of all of the above - the client, the server core, and the LX200 server, along with the Stellarium telescope control network protocol (over TCP/IP), is <b>Johannes Gajdosik</b>.") + "</li>";
282 aboutPage += "<li>" + q_("the TelescopeServerNexStar telescope server core code (originally licensed under the LGPL, based on TelescopeServerLx200) by <b>Michael Heinz</b>.") + "</li>";
283 aboutPage += "<li>" + q_("INDI by <b>Alessandro Siniscalchi</b>.") + "</li></ul>";
284
285 aboutPage += StelApp::getInstance().getModuleMgr().getStandardSupportLinksInfo("Telescope Control plugin");
286 aboutPage += "</body></html>";
287
288 QString helpPage = "<html><head></head><body>";
289 // TRANSLATORS: The text between braces is the text of an HTML link.
290 helpPage += "<p>" + q_("A more complete and up-to-date documentation for this plug-in can be found on the {Telescope Control} page in the Stellarium Wiki.").replace(a_rx, "<a href=\"http://stellarium.sourceforge.net/wiki/index.php/Telescope_Control_plug-in\">\\1</a>") + "</p>";
291 helpPage += "<h3><a name=\"top\" />" + q_("Contents") + "</h3><ul>";
292 helpPage += "<li><a href=\"#Abilities_and_limitations\">" + q_("Abilities and limitations") + "</a></li>";
293 helpPage += "<li><a href=\"#originalfeature\">" + q_("The original telescope control feature") + "</a></li>";
294 helpPage += "<li><a href=\"#usingthisplugin\">" + q_("Using this plug-in") + "</a></li>";
295 helpPage += "<li><a href=\"#mainwindow\">" + q_("Main window ('Telescopes')") + "</a></li>";
296 helpPage += "<li><a href=\"#configwindow\">" + q_("Telescope configuration window") + "</a><ul>";
297 helpPage += "<li><a href=\"#connection_type\">" + q_("Connection type") + "</a></li>";
298 helpPage += "<li><a href=\"#telescope_properties\">" + q_("Telescope properties") + "</a></li>";
299 helpPage += "<li><a href=\"#device_settings\">" + q_("Device settings") + "</a></li>";
300 helpPage += "<li><a href=\"#connection_settings\">" + q_("Connection settings") + "</a></li>";
301 helpPage += "<li><a href=\"#fovcircles\">" + q_("Field of view indicators") + "</a></li></ul></li>";
302 helpPage += "<li><a href=\"#slew_to\">" + q_("'Slew telescope to' window") + "</a></li>";
303 helpPage += "<li><a href=\"#commands\">" + q_("Telescope commands") + "</a></li>";
304 helpPage += "<li><a href=\"#devices\">" + q_("Supported devices") + "</a></li>";
305 helpPage += "<li><a href=\"#virtual_telescope\">" + q_("Virtual telescope") + "</a></li></ul>";
306
307 helpPage += "<h3><a name=\"Abilities_and_limitations\" />" + q_("Abilities and limitations") + "</h3>";
308 helpPage += "<p>" + q_("This plug-in allows Stellarium to send only '<b>slew</b>' ('go to') commands to the device and to receive its current position. It cannot issue any other commands, so users should be aware of the possibility for mount collisions and similar situations. (To abort a slew, you can start another one to a safe position.)") + "</p>";
309 helpPage += "<p>" + q_("As of the current version, this plug-in doesn't allow satellite tracking, and is not very suitable for lunar or planetary observations.") + "</p>";
310 helpPage += "<p><span style=\"color: red; font-weight: bolder;\">" + q_("WARNING: Stellarium CANNOT prevent your telescope from being pointed at the Sun.") + "</span></p><ul>";
311 helpPage += "<li>" + q_("Never point your telescope at the Sun without a proper solar filter installed. The powerful light amplified by the telescope WILL cause irreversible damage to your eyes and/or your equipment.") + "</li>";
312 helpPage += "<li>" + q_("Even if you don't do it deliberately, a slew during daylight hours may cause your telescope to point at the sun on its way to the given destination, so it is strongly recommended to avoid using the telescope control feature before sunset without appropriate protection.") + "</li></ul>";
313 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
314
315 helpPage += "<h3><a name=\"originalfeature\" />" + q_("The original telescope control feature") + "</h3>";
316 helpPage += "<p>" + q_("As of Stellarium 0.10.5, the original telescope control feature has been removed. There is no longer a way to control a telescope with Stellarium without this plug-in.") + "</p>";
317 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
318
319 helpPage += "<h3><a name=\"usingthisplugin\" />" + q_("Using this plug-in") + "</h3>";
320 helpPage += "<p>" + q_("Here are two general ways to control a device with this plug-in, depending on the situation:") + "</p><ul>";
321 helpPage += "<li><b>" + q_("DIRECT CONNECTION") + "</b>: ";
322
323 // TRANSLATORS: The text between braces is the text of an HTML link.
324 helpPage += q_("A {device supported by the plug-in} is connected with a cable to the computer running Stellarium;").replace(a_rx, "<a href=\"#devices\">\\1</a>");
325 helpPage += "</li>";
326 helpPage += "<li><b>" + q_("INDIRECT CONNECTION") + "</b>: <ul>";
327 helpPage += "<li>";
328 // TRANSLATORS: The text between braces is the text of an HTML link.
329 helpPage += q_("A device is connected to the same computer but it is driven by a {stand-alone telescope server program}").replace(a_rx, "<a href=\"http://stellarium.sourceforge.net/wiki/index.php/Telescope_Control_%28client-server%29\">\\1</a>") + " ";
330 // TRANSLATORS: The text between braces is the text of an HTML link.
331 helpPage += q_("or a {third-party application} <b>that can 'talk' to Stellarium</b>;").replace(a_rx, "<a href=\"http://stellarium.sourceforge.net/wiki/index.php/Telescope_Control#Third_party_applications\">\\1</a>");
332 helpPage += "</li>";
333 helpPage += "<li>" + q_("A device is connected to a remote computer and the software that drives it can 'talk' to Stellarium <i>over the network</i>; this software can be either one of Stellarium's stand-alone telescope servers, or a third party application.") + "</li></ul></li></ul>";
334 helpPage += "<p>";
335 // TRANSLATORS: The text between braces is the text of an HTML link.
336 helpPage += "<p>" + q_("Most older telescopes use cables that connect to a {serial port} (RS-232), the newer ones use USB (Universal Serial Bus).").replace(a_rx, "<a href=\"http://meta.wikimedia.org/wiki/wikipedia:en:serial_port\">\\1</a>")
337 + " " + q_("On Linux and Mac OS X both cases are handled identically by the plug-in. On Windows, a USB connection may require a 'virtual serial port' software, if it is not supplied with the cable or the telescope.")
338 + " " + q_("Such a software creates a virtual ('fake') COM port that corresponds to the real USB port so it can be used by the plug-in.")
339 + " " + q_("On all three platforms, if the computer has no 'classic' serial ports and the telescope can connect only to a serial port, a serial-to-USB (RS-232-to-USB) adapter may be necessary.") + "</p>";
340 helpPage += "<p>" + q_("Telescope set-up (setting geographical coordinates, performing alignment, etc.) should be done before connecting the telescope to Stellarium.") + "</p>";
341 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
342
343 helpPage += "<h3><a name=\"mainwindow\" />" + q_("Main window ('Telescopes')") + "</h3>";
344 helpPage += "<p>" + q_("The plug-in's main window can be opened:") + "</p><ul>";
345 helpPage += "<li>" + q_("By pressing the 'configure' button for the plug-in in the 'Plugins' tab of Stellarium's Configuration window (opened by pressing <b>F2</b> or the respective button in the left toolbar).") + "</li>";
346 helpPage += "<li>";
347 // TRANSLATORS: The text between braces is the text of an HTML link.
348 helpPage += q_("By pressing the 'Configure telescopes...' button in the {'Slew to' window} (opened by pressing <b>Ctrl+0</b> or the respective button on the bottom toolbar).").replace(a_rx, "<a href=\"#slew_to\">\\1</a>");
349 helpPage += "</li></ul>";
350 helpPage += "<p>" + q_("The <b>Telescopes</b> tab displays a list of the telescope connections that have been set up:") + "</p><ul>";
351 helpPage += "<li>" + q_("The number (<b>#</b>) column shows the number used to control this telescope. For example, for telescope #2, the shortcut is Ctrl+2.") + "</li>";
352 helpPage += "<li>" + q_("The <b>Status</b> column indicates if this connection is currently active or not. Unfortunately, there are some cases in which 'Connected' is displayed when no working connection exists.") + "</li>";
353 helpPage += "<li>" + q_("The <b>Type</b> field indicates what kind of connection is this:") + "</li><ul>";
354 helpPage += "<li>";
355 // TRANSLATORS: The text between braces is the text of an HTML link.
356 helpPage += q_("<b>virtual</b> means a {virtual telescope};").replace(a_rx, "<a href=\"#virtual_telescope\">\\1</a>");
357 helpPage += "</li>";
358 helpPage += "<li>";
359 // TRANSLATORS: The text between braces is the text of an HTML link.
360 helpPage += q_("<b>local, Stellarium</b> means a DIRECT connection to the telescope (see {above});").replace(a_rx, "<a href=\"#usingthisplugin\">\\1</a>");
361 helpPage += "</li>";
362 helpPage += "<li>" + q_("<b>local, external</b> means an INDIRECT connection to a program running on the same computer;") + "</li>";
363 helpPage += "<li>" + q_("<b>remote, unknown</b> means an INDIRECT connection over a network to a remote machine.") + "</li></ul></li></ul>";
364 helpPage += "<p>" + q_("To set up a new telescope connection, press the <b>Add</b> button. To modify the configuration of an existing connection, select it in the list and press the <b>Configure</b> button. In both cases, a telescope connection configuration window will open.") + "</p>";
365 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
366
367 helpPage += "<h3><a name=\"configwindow\" />" + q_("Telescope configuration window") + "</h3>";
368
369 helpPage += "<h4><a name=\"connection_type\" />" + q_("Connection type") + "</h4>";
370 helpPage += "<p>";
371 // TRANSLATORS: The text between braces is the text of an HTML link.
372 helpPage += q_("The topmost field represents the choice between the two types of connections (see {above}):").replace(a_rx, "<a href=\"#usingthisplugin\">\\1</a>");
373 helpPage += "</p>";
374 helpPage += "<p><b>" + q_("Telescope controlled by:") + "</b></p><ul>";
375 helpPage += "<li>" + q_("<b>Stellarium, directly through a serial port</b> is the DIRECT case") + "</li>";
376 helpPage += "<li>" + q_("<b>External software or a remote computer</b> is the INDIRECT case") + "</li>";
377 helpPage += "<li>";
378 // TRANSLATORS: The text between braces is the text of an HTML link.
379 helpPage += q_("<b>Nothing, just simulate one (a moving reticle)</b> is a {virtual telescope} (no connection)").replace(a_rx, "<a href=\"#virtual_telescope\">\\1</a>");
380 helpPage += "</li></ul>";
381 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
382
383 helpPage += "<h4><a name=\"telescope_properties\" />" + q_("Telescope properties") + "</h4>";
384 helpPage += "<p>" + q_("<b>Name</b> is the label that will be displayed on the screen next to the telescope reticle.") + "</p>";
385 helpPage += "<p>" + q_("<b>Connection delay</b>: If the movement of the telescope reticle on the screen is uneven, you can try increasing or decreasing this value.") + "</p>";
386 helpPage += "<p>" + q_("<b>Coordinate system</b>: Some Celestron telescopes have had their firmware updated and now interpret the coordinates they receive as coordinates that use the equinox of the date (EOD, also known as JNow), making necessary this override.") + "</p>";
387 helpPage += "<p>" + q_("<b>Start/connect at startup</b>: Check this option if you want Stellarium to attempt to connect to the telescope immediately after it starts.")
388 + " " + q_("Otherwise, to start the telescope, you need to open the main window, select that telescope and press the 'Start/Connect' button.") + "</p>";
389 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
390
391 helpPage += "<h4><a name=\"device_settings\" />" + q_("Device settings") + "</h4>";
392 helpPage += "<p>";
393 // TRANSLATORS: The text between braces is the text of an HTML link.
394 helpPage += q_("This section is active only for DIRECT connections (see {above}).").replace(a_rx, "<a href=\"#usingthisplugin\">\\1</a>");
395 helpPage += "</p>";
396 helpPage += "<p>" + q_("<b>Serial port</b> sets the serial port used by the telescope.") + "</p>";
397 helpPage += "<p>" + q_("There is a pop-up box that suggests some default values:") + "</p><ul>";
398 helpPage += "<li>" + q_("On Windows, serial ports COM1 to COM10;") + "</li>";
399 helpPage += "<li>" + q_("On Linux, serial ports /dev/ttyS0 to /dev/ttyS3 and USB ports /dev/ttyUSB0 to /dev/ttyUSB3;") + "</li>";
400 helpPage += "<li>" + q_("On Mac OS X, the list is empty as it names its ports in a peculiar way.") + "</li></ul>";
401 helpPage += "<p>" + q_("If you are using an USB cable, the default serial port of your telescope most probably is not in the list of suggestions.") + "</p>";
402 helpPage += "<p>" + q_("To list all valid serial port names in Mac OS X, open a terminal and type:") + "<br /><samp>ls /dev/*</samp></p>";
403 helpPage += "<p>" + q_("This will list all devices, the full name of your serial port should be somewhere in the list (for example, '/dev/cu.usbserial-FTDFZVMK').") + "</p>";
404 helpPage += "<p>";
405 // TRANSLATORS: The text between braces is the text of an HTML link.
406 helpPage += q_("<b>Device model</b>: see {Supported devices} below.").replace(a_rx, "<a href=\"#devices\">\\1</a>");
407 helpPage += "</p>";
408 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
409
410 helpPage += "<h4><a name=\"connection_settings\" />" + q_("Connection settings") + "</h4>";
411 helpPage += "<p>";
412 // TRANSLATORS: The text between braces is the text of an HTML link.
413 helpPage += q_("Both fields here refer to communication over a network ({TCP/IP}).").replace(a_rx, "<a href=\"http://meta.wikimedia.org/wiki/wikipedia:en:TCP/IP\">\\1</a>") + " ";
414 // TRANSLATORS: The text between braces is the text of an HTML link.
415 helpPage += q_("Doing something with them is necessary only for INDIRECT connections (see {above}).").replace(a_rx, "<a href=\"#usingthisplugin\">\\1</a>") + " ";
416 helpPage += "</p>";
417 helpPage += "<p>";
418 // TRANSLATORS: The text between braces is the text of an HTML link.
419 helpPage += q_("<b>Host</b> can be either a host name or an {IPv4} address such as '127.0.0.1'. The default value of 'localhost' means 'this computer'.").replace(a_rx, "<a href=\"http://meta.wikimedia.org/wiki/wikipedia:en:IPv4\">\\1</a>");
420 helpPage += "</p>";
421 helpPage += "<p>" + q_("<b>Port</b> refers to the TCP port used for communication. The default value depends on the telescope number and ranges between 10001 and 10009.") + "</p>";
422 helpPage += "<p>" + q_("Both values are ignored for DIRECT connections.") + "</p>";
423 helpPage += "<p>" + q_("For INDIRECT connections, modifying the default host name value makes sense only if you are attempting a remote connection over a network.")
424 + " " + q_("In this case, it should be the name or IP address of the computer that runs a program that runs the telescope.") + "</p>";
425 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
426
427 helpPage += "<h4><a name=\"fovcircles\" />" + q_("Field of view indicators") + "</h4>";
428 helpPage += "<p>" + q_("A series of circles representing different fields of view can be added around the telescope marker. This is a relic from the times before the <strong>Oculars</strong> plug-in existed.") + "</p>";
429 helpPage += "<p>" + q_("In the telescope configuration window, click on 'User Interface Settings'.")
430 + " " + q_("Mark the 'Use field of view indicators' option, then enter a list of values separated with commas in the field below.")
431 + " " + q_("The values are interpreted as degrees of arc.") + "</p>";
432 helpPage += "<p>";
433 // TRANSLATORS: The text between braces is the text of an HTML link.
434 helpPage += q_("This can be used in combination with a {virtual telescope} to display a moving reticle with the Telrad circles.").replace(a_rx, "<a href=\"#virtual_telescope\">\\1</a>");
435 helpPage += "</p>";
436 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
437
438 helpPage += "<h3><a name=\"slew_to\" />" + q_("'Slew telescope to' window") + "</h3>";
439 helpPage += "<p>" + q_("The 'Slew telescope to' window can be opened by pressing <b>Ctrl+0</b> or the respective button in the bottom toolbar.") + "</p>";
440 helpPage += "<p>" + q_("It contains two fields for entering celestial coordinates, selectors for the preferred format (Hours-Minutes-Seconds, Degrees-Minutes-Seconds, or Decimal degrees), a drop-down list and two buttons.") + "</p>";
441 helpPage += "<p>" + q_("The drop-down list contains the names of the currently connected devices.") + " ";
442 helpPage += q_("If no devices are connected, it will remain empty, and the 'Slew' button will be disabled.") + "</p>";
443 helpPage += "<p>" + q_("Pressing the <b>Slew</b> button slews the selected device to the selected set of coordinates.") + " ";
444 // TRANSLATORS: The text between braces is the text of an HTML link.
445 helpPage += q_("See the section about {keyboard commands} below for other ways of controlling the device.").replace(a_rx, "<a href=\"#commands\">\\1</a>");
446 helpPage += "</p>";
447 helpPage += "<p>";
448 // TRANSLATORS: The text between braces is the text of an HTML link.
449 helpPage += q_("Pressing the <b>Configure telescopes...</b> button opens the {main window} of the plug-in.").replace(a_rx, "<a href=\"#mainwindow\">\\1</a>");
450 helpPage += "</p>";
451 helpPage += "<p>" + q_("<b>TIP:</b> Inside the 'Slew' window, underlined letters indicate that pressing 'Alt + underlined letter' can be used instead of clicking.") + " ";
452 helpPage += q_("For example, pressing <b>Alt+S</b> is equivalent to clicking the 'Slew' button, pressing <b>Alt+E</b> switches to decimal degree format, etc.") + "</p>";
453 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
454
455 helpPage += "<h3><a name=\"commands\" />" + q_("Sending commands") + "</h3>";
456 helpPage += "<p>" + q_("Once a telescope is successfully started/connected, Stellarium displays a telescope reticle labelled with the telescope's name on its current position in the sky.")
457 + " " + q_("The reticle is an object like every other in Stellarium - it can be selected with the mouse, it can be tracked and it appears as an object in the 'Search' window.") + "</p>";
458 helpPage += "<p>" + q_("<b>To point a device to an object:</b> Select an object (e.g. a star) and press the number of the device while holding down the <b>Ctrl</b> key.")
459 + " (" + q_("For example, Ctrl+1 for telescope #1.") + ") "
460 + q_("This will move the telescope to the selected object.") + "</p>";
461 helpPage += "<p>" + q_("<b>To point a device to the center of the view:</b> Press the number of the device while holding down the <b>Alt</b> key.")
462 + " (" + q_("For example, Alt+1 for telescope #1.") + ") "
463 + q_("This will slew the device to the point in the center of the current view.")
464 + " (" + q_("If you move the view after issuing the command, the target won't change unless you issue another command.") + ")</p>";
465 helpPage += "<p>";
466 // TRANSLATORS: The text between braces is the text of an HTML link.
467 helpPage += q_("<b>To point a device to a given set of coordinates:</b> Use the {'Slew to' window} (press <b>Ctrl+0</b>).").replace(a_rx, "<a href=\"#slew_to\">\\1</a>");
468 helpPage += "</p>";
469 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
470
471 helpPage += "<h3><a name=\"devices\" />" + q_("Supported devices") + "</h3>";
472 helpPage += "<p>";
473 // TRANSLATORS: The text between braces is the text of an HTML link.
474 helpPage += q_("All devices listed in the {'Device model' list} are convenience definitions using one of the two built-in interfaces: the Meade LX200 (the Meade Autostar controller) interface and the Celestron NexStar interface.").replace(a_rx, "<a href=\"#device_settings\">\\1</a>");
475 helpPage += "</p>";
476 helpPage += "<p>" + q_("The device list contains the following:") + "</p><dl>";
477 helpPage += "<dt><b>Celestron NexStar (compatible)</b></dt><dd>" + q_("Any device using the NexStar interface.") + "</dd>";
478 helpPage += "<dt><b>Losmandy G-11</b></dt><dd>" + q_("A computerized telescope mount made by Losmandy (Meade LX-200/Autostar interface).") + "</dd>";
479 helpPage += "<dt><b>Meade Autostar compatible</b></dt><dd>" + q_("Any device using the LX-200/Autostar interface.") + "</dd>";
480 helpPage += "<dt><b>Meade ETX-70 (#494 Autostar, #506 CCS)</b></dt><dd>" + q_("The Meade ETX-70 telescope with the #494 Autostar controller and the #506 Connector Cable Set.") + " ";
481 // TRANSLATORS: The text between braces is the text of an HTML link.
482 helpPage += q_("According to the tester, it is a bit slow, so its default setting of %1'Connection delay'%2 is 1.5 seconds instead of 0.5 seconds.").replace(a_rx, "<a href=\"#telescope_properties\">\\1</a>");
483 helpPage += "</dd>";
484 helpPage += "<dt><b>Meade LX200 (compatible)</b></dt><dd>" + q_("Any device using the LX-200/Autostar interface.") + "</dd>";
485 helpPage += "<dt><b>Sky-Watcher SynScan AZ mount</b></dt><dd>" + q_("The Sky-Watcher SynScan AZ GoTo mount is used in a number of telescopes.") + "</dd>";
486 helpPage += "<dt><b>Sky-Watcher SynScan (version 3 or later)</b></dt><dd>" + q_("<b>SynScan</b> is also the name of the hand controller used in other Sky-Watcher GoTo mounts, and it seems that any mount that uses a SynScan controller version 3.0 or greater is supported by the plug-in, as it uses the NexStar protocol.") + "</dd>";
487 helpPage += "<dt><b>Wildcard Innovations Argo Navis (Meade mode)</b></dt><dd>" + q_("Argo Navis is a 'Digital Telescope Computer' by Wildcard Innovations.")
488 + " " + q_("It is an advanced digital setting circle that turns an ordinary telescope (for example, a dobsonian) into a 'Push To' telescope (a telescope that uses a computer to find targets and human power to move the telescope itself).")
489 + " " + q_("Just don't forget to set it to Meade compatibility mode and set the baud rate to 9600B")
490 + "<sup><a href=\"http://www.iceinspace.com.au/forum/showpost.php?p=554948&postcount=18\">1</a></sup>.</dd></dl>";
491 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
492
493 helpPage += "<h3><a name=\"virtual_telescope\" />" + q_("Virtual telescope") + "</h3>";
494 helpPage += "<p>" + q_("If you want to test this plug-in without an actual device connected to the computer, choose <b>Nothing, just simulate one (a moving reticle)</b> in the <b>Telescope controlled by:</b> field. It will show a telescope reticle that will react in the same way as the reticle of a real telescope controlled by the plug-in.") + "</p>";
495 helpPage += "<p>";
496 // TRANSLATORS: The text between braces is the text of an HTML link.
497 helpPage += q_("See the section above about {field of view indicators} for a possible practical application (emulating 'Telrad' circles).").replace(a_rx, "<a href=\"#fovcircles\">\\1</a>");
498 helpPage += "</p>";
499 helpPage += "<p>";
500 // TRANSLATORS: The text between braces is the text of an HTML link.
501 helpPage += q_("This feature is equivalent to the 'Dummy' type of telescope supported by {Stellarium's original telescope control feature}.").replace(a_rx, "<a href=\"http://stellarium.sourceforge.net/wiki/index.php/Telescope_Control_%28client-server%29\">\\1</a>");
502 helpPage += "</p>";
503 helpPage += "<p><a href=\"#top\"><small>[" + q_("Back to top") + "]</small></a></p>";
504
505 helpPage += "</body></html>";
506
507 StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
508 if (gui)
509 {
510 ui->textBrowserAbout->document()->setDefaultStyleSheet(QString(gui->getStelStyle().htmlStyleSheet));
511 ui->textBrowserHelp->document()->setDefaultStyleSheet(QString(gui->getStelStyle().htmlStyleSheet));
512 }
513 ui->textBrowserAbout->setHtml(aboutPage);
514 ui->textBrowserHelp->setHtml(helpPage);
515 }
516
setHeaderNames()517 void TelescopeDialog::setHeaderNames()
518 {
519 QStringList headerStrings;
520 // TRANSLATORS: Symbol for "number"
521 headerStrings << q_("#");
522 //headerStrings << "Start";
523 headerStrings << q_("Status");
524 headerStrings << q_("Type");
525 headerStrings << q_("Name");
526 telescopeListModel->setHorizontalHeaderLabels(headerStrings);
527 }
528
updateWarningTexts()529 void TelescopeDialog::updateWarningTexts()
530 {
531 QString text;
532 if (telescopeCount > 0)
533 {
534 #ifdef Q_OS_MAC
535 QString modifierName = "Command";
536 #else
537 QString modifierName = "Ctrl";
538 #endif
539
540 text = QString(q_("To slew a connected telescope to an object (for example, a star), select that object, then hold down the %1 key and press the key with that telescope's number. To slew it to the center of the current view, hold down the Alt key and press the key with that telescope's number.")).arg(modifierName);
541 }
542 else
543 {
544 if (telescopeManager->getDeviceModels().isEmpty())
545 {
546 // TRANSLATORS: Currently, it is very unlikely if not impossible to actually see this text. :)
547 text = q_("No device model descriptions are available. Stellarium will not be able to control a telescope on its own, but it is still possible to do it through an external application or to connect to a remote host.");
548 }
549 else
550 {
551 // TRANSLATORS: The translated name of the Add button is automatically inserted.
552 text = QString(q_("Press the \"%1\" button to set up a new telescope connection.")).arg(ui->pushButtonAdd->text());
553 }
554 }
555
556 ui->labelWarning->setText(text);
557 }
558
getTypeLabel(ConnectionType type)559 QString TelescopeDialog::getTypeLabel(ConnectionType type)
560 {
561 QString typeLabel;
562 switch (type)
563 {
564 case ConnectionInternal:
565 // TRANSLATORS: Telescope connection type
566 typeLabel = N_("local, Stellarium");
567 break;
568 case ConnectionLocal:
569 // TRANSLATORS: Telescope connection type
570 typeLabel = N_("local, external");
571 break;
572 case ConnectionRemote:
573 // TRANSLATORS: Telescope connection type
574 typeLabel = N_("remote, unknown");
575 break;
576 case ConnectionVirtual:
577 // TRANSLATORS: Telescope connection type
578 typeLabel = N_("virtual");
579 break;
580 case ConnectionRTS2:
581 // TRANSLATORS: Telescope connection type
582 typeLabel = N_("remote, RTS2");
583 break;
584 case ConnectionINDI:
585 // TRANSLATORS: Telescope connection type
586 typeLabel = N_("remote, INDI/INDIGO");
587 break;
588 case ConnectionASCOM:
589 // TRANSLATORS: Telescope connection type
590 typeLabel = N_("local, ASCOM");
591 break;
592 default:
593 ;
594 }
595 return typeLabel;
596 }
597
addModelRow(int number,ConnectionType type,TelescopeStatus status,const QString & name)598 void TelescopeDialog::addModelRow(int number,
599 ConnectionType type,
600 TelescopeStatus status,
601 const QString& name)
602 {
603 Q_ASSERT(telescopeListModel);
604
605 QStandardItem* tempItem = Q_NULLPTR;
606 int lastRow = telescopeListModel->rowCount();
607 // Number
608 tempItem = new QStandardItem(QString::number(number));
609 tempItem->setEditable(false);
610 telescopeListModel->setItem(lastRow, ColumnSlot, tempItem);
611
612 // Checkbox
613 //TODO: This is not updated, because it was commented out
614 //tempItem = new QStandardItem;
615 //tempItem->setEditable(false);
616 //tempItem->setCheckable(true);
617 //tempItem->setCheckState(Qt::Checked);
618 //tempItem->setData("If checked, this telescope will start when Stellarium is started", Qt::ToolTipRole);
619 //telescopeListModel->setItem(lastRow, ColumnStartup, tempItem);//Start-up checkbox
620
621 //Status
622 tempItem = new QStandardItem(q_(statusString[status]));
623 tempItem->setEditable(false);
624 telescopeListModel->setItem(lastRow, ColumnStatus, tempItem);
625
626 //Type
627 QString typeLabel = getTypeLabel(type);
628 tempItem = new QStandardItem(q_(typeLabel));
629 tempItem->setEditable(false);
630 tempItem->setData(typeLabel, Qt::UserRole);
631 telescopeListModel->setItem(lastRow, ColumnType, tempItem);
632
633 //Name
634 tempItem = new QStandardItem(name);
635 tempItem->setEditable(false);
636 telescopeListModel->setItem(lastRow, ColumnName, tempItem);
637 }
638
updateModelRow(int rowNumber,ConnectionType type,TelescopeStatus status,const QString & name)639 void TelescopeDialog::updateModelRow(int rowNumber,
640 ConnectionType type,
641 TelescopeStatus status,
642 const QString& name)
643 {
644 Q_ASSERT(telescopeListModel);
645 if (rowNumber > telescopeListModel->rowCount())
646 return;
647
648 //The slot number doesn't need to be updated. :)
649 //Status
650 QString statusLabel = q_(statusString[status]);
651 QModelIndex index = telescopeListModel->index(rowNumber, ColumnStatus);
652 telescopeListModel->setData(index, statusLabel, Qt::DisplayRole);
653
654 //Type
655 QString typeLabel = getTypeLabel(type);
656 index = telescopeListModel->index(rowNumber, ColumnType);
657 telescopeListModel->setData(index, typeLabel, Qt::UserRole);
658 telescopeListModel->setData(index, q_(typeLabel), Qt::DisplayRole);
659
660 //Name
661 index = telescopeListModel->index(rowNumber, ColumnName);
662 telescopeListModel->setData(index, name, Qt::DisplayRole);
663 }
664
665
selectTelecope(const QModelIndex & index)666 void TelescopeDialog::selectTelecope(const QModelIndex & index)
667 {
668 //Extract selected item index
669 int selectedSlot = telescopeListModel->data( telescopeListModel->index(index.row(),0) ).toInt();
670 updateStatusButtonForSlot(selectedSlot);
671
672 //In all cases
673 ui->pushButtonRemove->setEnabled(true);
674 }
675
configureTelescope(const QModelIndex & currentIndex)676 void TelescopeDialog::configureTelescope(const QModelIndex & currentIndex)
677 {
678 configuredTelescopeIsNew = false;
679 configuredSlot = telescopeListModel->data( telescopeListModel->index(currentIndex.row(), ColumnSlot) ).toInt();
680
681 //Stop the telescope first if necessary
682 if(telescopeType[configuredSlot] != ConnectionInternal && telescopeStatus[configuredSlot] != StatusDisconnected)
683 {
684 if(telescopeManager->stopTelescopeAtSlot(configuredSlot)) //Act as "Disconnect"
685 telescopeStatus[configuredSlot] = StatusDisconnected;
686 else
687 return;
688 }
689 else if(telescopeStatus[configuredSlot] != StatusStopped)
690 {
691 if(telescopeManager->stopTelescopeAtSlot(configuredSlot)) //Act as "Stop"
692 telescopeStatus[configuredSlot] = StatusStopped;
693 }
694 //Update the status in the list
695 int curRow = ui->telescopeTreeView->currentIndex().row();
696 QModelIndex curIndex = telescopeListModel->index(curRow, ColumnStatus);
697 QString string = q_(statusString[telescopeStatus[configuredSlot]]);
698 telescopeListModel->setData(curIndex, string, Qt::DisplayRole);
699
700 setVisible(false);
701 configurationDialog.setVisible(true); //This should be called first to actually create the dialog content
702
703 configurationDialog.initExistingTelescopeConfiguration(configuredSlot);
704 }
705
buttonChangeStatusPressed()706 void TelescopeDialog::buttonChangeStatusPressed()
707 {
708 if(!ui->telescopeTreeView->currentIndex().isValid())
709 return;
710
711 //Extract selected slot
712 int selectedSlot = telescopeListModel->data( telescopeListModel->index(ui->telescopeTreeView->currentIndex().row(), ColumnSlot) ).toInt();
713
714 //TODO: As most of these are asynchronous actions, it looks like that there should be a queue...
715
716 if(telescopeType[selectedSlot] != ConnectionInternal)
717 {
718 //Can't be launched by Stellarium -> can't be stopped by Stellarium
719 //Can be only connected/disconnected
720 if(telescopeStatus[selectedSlot] == StatusDisconnected)
721 {
722 if(telescopeManager->startTelescopeAtSlot(selectedSlot)) //Act as "Connect"
723 telescopeStatus[selectedSlot] = StatusConnecting;
724 }
725 else
726 {
727 if(telescopeManager->stopTelescopeAtSlot(selectedSlot)) //Act as "Disconnect"
728 telescopeStatus[selectedSlot] = StatusDisconnected;
729 }
730 }
731 else
732 {
733 switch(telescopeStatus[selectedSlot]) //Why the switch?
734 {
735 case StatusNA:
736 case StatusStopped:
737 {
738 if(telescopeManager->startTelescopeAtSlot(selectedSlot)) //Act as "Start"
739 telescopeStatus[selectedSlot] = StatusConnecting;
740 }
741 break;
742 case StatusConnecting:
743 case StatusConnected:
744 {
745 if(telescopeManager->stopTelescopeAtSlot(selectedSlot)) //Act as "Stop"
746 telescopeStatus[selectedSlot] = StatusStopped;
747 }
748 break;
749 default:
750 break;
751 }
752 }
753
754 //Update the status in the list
755 int curRow = ui->telescopeTreeView->currentIndex().row();
756 QModelIndex curIndex = telescopeListModel->index(curRow, ColumnStatus);
757 QString string = q_(statusString[telescopeStatus[selectedSlot]]);
758 telescopeListModel->setData(curIndex, string, Qt::DisplayRole);
759 }
760
buttonConfigurePressed()761 void TelescopeDialog::buttonConfigurePressed()
762 {
763 if(ui->telescopeTreeView->currentIndex().isValid())
764 configureTelescope(ui->telescopeTreeView->currentIndex());
765 }
766
buttonAddPressed()767 void TelescopeDialog::buttonAddPressed()
768 {
769 if(telescopeCount >= SLOT_COUNT)
770 return;
771
772 configuredTelescopeIsNew = true;
773
774 //Find the first unoccupied slot (there is at least one)
775 for (configuredSlot = MIN_SLOT_NUMBER; configuredSlot < SLOT_NUMBER_LIMIT; configuredSlot++)
776 {
777 //configuredSlot = (i+1)%SLOT_COUNT;
778 if(telescopeStatus[configuredSlot] == StatusNA)
779 break;
780 }
781
782 setVisible(false);
783 configurationDialog.setVisible(true); //This should be called first to actually create the dialog content
784 configurationDialog.initNewTelescopeConfiguration(configuredSlot);
785 }
786
buttonRemovePressed()787 void TelescopeDialog::buttonRemovePressed()
788 {
789 if(!ui->telescopeTreeView->currentIndex().isValid())
790 return;
791
792 //Extract selected slot
793 int selectedSlot = telescopeListModel->data( telescopeListModel->index(ui->telescopeTreeView->currentIndex().row(),0) ).toInt();
794
795 //Stop the telescope if necessary and remove it
796 if(telescopeManager->stopTelescopeAtSlot(selectedSlot))
797 {
798 //TODO: Update status?
799 if(!telescopeManager->removeTelescopeAtSlot(selectedSlot))
800 {
801 //TODO: Add debug
802 return;
803 }
804 }
805 else
806 {
807 //TODO: Add debug
808 return;
809 }
810
811 //Save the changes to file
812 telescopeManager->saveTelescopes();
813
814 telescopeStatus[selectedSlot] = StatusNA;
815 telescopeCount -= 1;
816
817 //Update the interface to reflect the changes:
818
819 //Make sure that the header section keeps it size
820 if(telescopeCount == 0)
821 ui->telescopeTreeView->header()->setSectionResizeMode(ColumnType, QHeaderView::Interactive);
822
823 //Remove the telescope from the table/tree
824 telescopeListModel->removeRow(ui->telescopeTreeView->currentIndex().row());
825
826 //If there are less than the maximal number of telescopes now, new ones can be added
827 if(telescopeCount < SLOT_COUNT)
828 ui->pushButtonAdd->setEnabled(true);
829
830 //If there are no telescopes left, disable some buttons
831 if(telescopeCount == 0)
832 {
833 //TODO: Fix the phantom text of the Status button (reuse code?)
834 //IDEA: Vsible/invisible instead of enabled/disabled?
835 //The other buttons expand to take the place (delete spacers)
836 ui->pushButtonChangeStatus->setEnabled(false);
837 ui->pushButtonConfigure->setEnabled(false);
838 ui->pushButtonRemove->setEnabled(false);
839 }
840 else
841 {
842 ui->telescopeTreeView->setCurrentIndex(telescopeListModel->index(0,0));
843 }
844 updateWarningTexts();
845 }
846
saveChanges(QString name,ConnectionType type)847 void TelescopeDialog::saveChanges(QString name, ConnectionType type)
848 {
849 //Save the changes to file
850 telescopeManager->saveTelescopes();
851
852 //Type and server properties
853 telescopeType[configuredSlot] = type;
854 switch (type)
855 {
856 case ConnectionVirtual:
857 telescopeStatus[configuredSlot] = StatusStopped;
858 break;
859
860 case ConnectionInternal:
861 if(configuredTelescopeIsNew)
862 telescopeStatus[configuredSlot] = StatusStopped;//TODO: Is there a point? Isn't it better to force the status update method?
863 break;
864
865 case ConnectionLocal:
866 telescopeStatus[configuredSlot] = StatusDisconnected;
867 break;
868
869 case ConnectionRemote:
870 default:
871 telescopeStatus[configuredSlot] = StatusDisconnected;
872 }
873
874 //Update the model/list
875 TelescopeStatus status = telescopeStatus[configuredSlot];
876 if(configuredTelescopeIsNew)
877 {
878 addModelRow(configuredSlot, type, status, name);
879 telescopeCount++;
880 }
881 else
882 {
883 int currentRow = ui->telescopeTreeView->currentIndex().row();
884 updateModelRow(currentRow, type, status, name);
885 }
886 //Sort the updated table by slot number
887 ui->telescopeTreeView->sortByColumn(ColumnSlot, Qt::AscendingOrder);
888
889 //Can't add more telescopes if they have reached the maximum number
890 if (telescopeCount >= SLOT_COUNT)
891 ui->pushButtonAdd->setEnabled(false);
892
893 //
894 if (telescopeCount == 0)
895 {
896 ui->pushButtonChangeStatus->setEnabled(false);
897 ui->pushButtonConfigure->setEnabled(false);
898 ui->pushButtonRemove->setEnabled(false);
899 ui->telescopeTreeView->header()->setSectionResizeMode(ColumnType, QHeaderView::Interactive);
900 }
901 else
902 {
903 ui->telescopeTreeView->setFocus();
904 ui->telescopeTreeView->setCurrentIndex(telescopeListModel->index(0,0));
905 ui->pushButtonConfigure->setEnabled(true);
906 ui->pushButtonRemove->setEnabled(true);
907 ui->telescopeTreeView->header()->setSectionResizeMode(ColumnType, QHeaderView::ResizeToContents);
908 }
909 updateWarningTexts();
910
911 configuredTelescopeIsNew = false;
912 configurationDialog.setVisible(false);
913 setVisible(true);//Brings the current window to the foreground
914 }
915
discardChanges()916 void TelescopeDialog::discardChanges()
917 {
918 configurationDialog.setVisible(false);
919 setVisible(true);//Brings the current window to the foreground
920
921 if (telescopeCount >= SLOT_COUNT)
922 ui->pushButtonAdd->setEnabled(false);
923 if (telescopeCount == 0)
924 ui->pushButtonRemove->setEnabled(false);
925
926 configuredTelescopeIsNew = false;
927 }
928
updateTelescopeStates()929 void TelescopeDialog::updateTelescopeStates()
930 {
931 if(telescopeCount == 0)
932 return;
933
934 int slotNumber = -1;
935 for (int i=0; i<(telescopeListModel->rowCount()); i++)
936 {
937 slotNumber = telescopeListModel->data( telescopeListModel->index(i, ColumnSlot) ).toInt();
938 //TODO: Check if these cover all possibilites
939 if (telescopeManager->isConnectedClientAtSlot(slotNumber))
940 {
941 telescopeStatus[slotNumber] = StatusConnected;
942 }
943 else if(telescopeManager->isExistingClientAtSlot(slotNumber))
944 {
945 telescopeStatus[slotNumber] = StatusConnecting;
946 }
947 else
948 {
949 if(telescopeType[slotNumber] == ConnectionInternal)
950 telescopeStatus[slotNumber] = StatusStopped;
951 else
952 telescopeStatus[slotNumber] = StatusDisconnected;
953 }
954
955 //Update the status in the list
956 QModelIndex index = telescopeListModel->index(i, ColumnStatus);
957 QString statusStr = q_(statusString[telescopeStatus[slotNumber]]);
958 telescopeListModel->setData(index, statusStr, Qt::DisplayRole);
959 }
960
961 if(ui->telescopeTreeView->currentIndex().isValid())
962 {
963 int selectedSlot = telescopeListModel->data( telescopeListModel->index(ui->telescopeTreeView->currentIndex().row(), ColumnSlot) ).toInt();
964 //Update the ChangeStatus button
965 updateStatusButtonForSlot(selectedSlot);
966 }
967 }
968
updateStatusButtonForSlot(int selectedSlot)969 void TelescopeDialog::updateStatusButtonForSlot(int selectedSlot)
970 {
971 if(telescopeType[selectedSlot] != ConnectionInternal)
972 {
973 //Can't be launched by Stellarium => can't be stopped by Stellarium
974 //Can be only connected/disconnected
975 if(telescopeStatus[selectedSlot] == StatusDisconnected)
976 {
977 setStatusButtonToConnect();
978 ui->pushButtonChangeStatus->setEnabled(true);
979 }
980 else
981 {
982 setStatusButtonToDisconnect();
983 ui->pushButtonChangeStatus->setEnabled(true);
984 }
985 }
986 else
987 {
988 switch(telescopeStatus[selectedSlot])
989 {
990 case StatusNA:
991 case StatusStopped:
992 setStatusButtonToStart();
993 ui->pushButtonChangeStatus->setEnabled(true);
994 break;
995 case StatusConnected:
996 case StatusConnecting:
997 setStatusButtonToStop();
998 ui->pushButtonChangeStatus->setEnabled(true);
999 break;
1000 default:
1001 setStatusButtonToStart();
1002 ui->pushButtonChangeStatus->setEnabled(false);
1003 ui->pushButtonConfigure->setEnabled(false);
1004 ui->pushButtonRemove->setEnabled(false);
1005 break;
1006 }
1007 }
1008 }
1009
setStatusButtonToStart()1010 void TelescopeDialog::setStatusButtonToStart()
1011 {
1012 ui->pushButtonChangeStatus->setText(q_("Start"));
1013 ui->pushButtonChangeStatus->setIcon(QIcon(":/graphicGui/uibtStart.png"));
1014 ui->pushButtonChangeStatus->setToolTip(q_("Start the selected local telescope"));
1015 }
1016
setStatusButtonToStop()1017 void TelescopeDialog::setStatusButtonToStop()
1018 {
1019 ui->pushButtonChangeStatus->setText(q_("Stop"));
1020 ui->pushButtonChangeStatus->setIcon(QIcon(":/graphicGui/uibtStop.png"));
1021 ui->pushButtonChangeStatus->setToolTip(q_("Stop the selected local telescope"));
1022 }
1023
setStatusButtonToConnect()1024 void TelescopeDialog::setStatusButtonToConnect()
1025 {
1026 ui->pushButtonChangeStatus->setText(q_("Connect"));
1027 ui->pushButtonChangeStatus->setIcon(QIcon(":/graphicGui/uibtStart.png"));
1028 ui->pushButtonChangeStatus->setToolTip(q_("Connect to the selected telescope"));
1029 }
1030
setStatusButtonToDisconnect()1031 void TelescopeDialog::setStatusButtonToDisconnect()
1032 {
1033 ui->pushButtonChangeStatus->setText(q_("Disconnect"));
1034 ui->pushButtonChangeStatus->setIcon(QIcon(":/graphicGui/uibtStop.png"));
1035 ui->pushButtonChangeStatus->setToolTip(q_("Disconnect from the selected telescope"));
1036 }
1037
updateStyle()1038 void TelescopeDialog::updateStyle()
1039 {
1040 if (dialog)
1041 {
1042 StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
1043 if (gui)
1044 ui->textBrowserAbout->document()->setDefaultStyleSheet(gui->getStelStyle().htmlStyleSheet);
1045 }
1046 }
1047
checkBoxUseExecutablesToggled(bool useExecutables)1048 void TelescopeDialog::checkBoxUseExecutablesToggled(bool useExecutables)
1049 {
1050 telescopeManager->setFlagUseServerExecutables(useExecutables);
1051 }
1052
buttonBrowseServerDirectoryPressed()1053 void TelescopeDialog::buttonBrowseServerDirectoryPressed()
1054 {
1055 QString newPath = QFileDialog::getExistingDirectory (Q_NULLPTR, QString(q_("Select a directory")), telescopeManager->getServerExecutablesDirectoryPath());
1056 //TODO: Validation? Directory exists and contains servers?
1057 if(!newPath.isEmpty())
1058 {
1059 ui->lineEditExecutablesDirectory->setText(newPath);
1060 telescopeManager->setServerExecutablesDirectoryPath(newPath);
1061 telescopeManager->setFlagUseServerExecutables(true);
1062 }
1063 }
1064