1 /*
2     SPDX-FileCopyrightText: 2003 Jasem Mutlaq <mutlaqja@ikarustech.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "telescopewizardprocess.h"
8 
9 #include "driverinfo.h"
10 #include "drivermanager.h"
11 #include "guimanager.h"
12 #include "indidevice.h"
13 #include "indielement.h"
14 #include "indilistener.h"
15 #include "indiproperty.h"
16 #include "kstars.h"
17 #include "kstarsdata.h"
18 #include "ksutils.h"
19 #include "Options.h"
20 #include "dialogs/timedialog.h"
21 
22 #include <QProgressDialog>
23 #include <QStatusBar>
24 
telescopeWizardProcess(QWidget * parent)25 telescopeWizardProcess::telescopeWizardProcess(QWidget *parent) : QDialog(parent)
26 {
27     QFile sideIMG;
28 
29     ui.reset(new Ui::telescopeWizard());
30     ui->setupUi(this);
31 
32     if (KSUtils::openDataFile(sideIMG, "wzscope.png"))
33         ui->wizardPix->setPixmap(QPixmap(sideIMG.fileName()));
34 
35     ui->backB->hide();
36     currentPage = INTRO_P;
37 
38     INDIMessageBar = Options::showINDIMessages();
39     Options::setShowINDIMessages(false);
40 
41     QTime newTime(KStars::Instance()->data()->lt().time());
42     QDate newDate(KStars::Instance()->data()->lt().date());
43 
44     ui->timeOut->setText(QString().sprintf("%02d:%02d:%02d", newTime.hour(), newTime.minute(), newTime.second()));
45     ui->dateOut->setText(QString().sprintf("%d-%02d-%02d", newDate.year(), newDate.month(), newDate.day()));
46 
47     // FIXME is there a better way to check if a translated message is empty?
48     //if (KStars::Instance()->data()->geo()->translatedProvince().isEmpty())
49     if (KStars::Instance()->data()->geo()->translatedProvince() == QString("(I18N_EMPTY_MESSAGE)"))
50         ui->locationOut->setText(QString("%1, %2")
51                                      .arg(KStars::Instance()->data()->geo()->translatedName(),
52                                           KStars::Instance()->data()->geo()->translatedCountry()));
53     else
54         ui->locationOut->setText(QString("%1, %2, %3")
55                                      .arg(KStars::Instance()->data()->geo()->translatedName(),
56                                           KStars::Instance()->data()->geo()->translatedProvince(),
57                                           KStars::Instance()->data()->geo()->translatedCountry()));
58 
59     for (DriverInfo *dv : DriverManager::Instance()->getDrivers())
60     {
61         if (dv->getType() == KSTARS_TELESCOPE)
62         {
63             ui->telescopeCombo->addItem(dv->getTreeLabel());
64             driversList[dv->getTreeLabel()] = dv;
65         }
66     }
67 
68     portList << "/dev/ttyS0"
69              << "/dev/ttyS1"
70              << "/dev/ttyS2"
71              << "/dev/ttyS3"
72              << "/dev/ttyS4"
73              << "/dev/ttyUSB0"
74              << "/dev/ttyUSB1"
75              << "/dev/ttyUSB2"
76              << "/dev/ttyUSB3";
77 
78     connect(ui->helpB, SIGNAL(clicked()), parent, SLOT(appHelpActivated()));
79     connect(ui->cancelB, SIGNAL(clicked()), this, SLOT(cancelCheck()));
80     connect(ui->nextB, SIGNAL(clicked()), this, SLOT(processNext()));
81     connect(ui->backB, SIGNAL(clicked()), this, SLOT(processBack()));
82     connect(ui->setTimeB, SIGNAL(clicked()), this, SLOT(newTime()));
83     connect(ui->setLocationB, SIGNAL(clicked()), this, SLOT(newLocation()));
84 
85     //newDeviceTimer = new QTimer(this);
86     //QObject::connect( newDeviceTimer, SIGNAL(timeout()), this, SLOT(processPort()) );
87 }
88 
~telescopeWizardProcess()89 telescopeWizardProcess::~telescopeWizardProcess()
90 {
91     Options::setShowINDIMessages(INDIMessageBar);
92     //Reset();
93 }
94 
95 //Called when cancel is clicked, gives a warning if past the first couple of steps
cancelCheck(void)96 void telescopeWizardProcess::cancelCheck(void)
97 {
98     switch (currentPage)
99     {
100         case TELESCOPE_P:
101         case LOCAL_P:
102         case PORT_P:
103             if (KMessageBox::warningYesNo(0, i18n("Are you sure you want to cancel?")) == KMessageBox::Yes)
104                 emit rejected();
105             break;
106         default:
107             emit rejected();
108             break;
109     }
110 }
111 
processNext(void)112 void telescopeWizardProcess::processNext(void)
113 {
114     switch (currentPage)
115     {
116         case INTRO_P:
117             currentPage++;
118             ui->backB->show();
119             ui->wizardContainer->setCurrentIndex(currentPage);
120             break;
121         case MODEL_P:
122             currentPage++;
123             ui->wizardContainer->setCurrentIndex(currentPage);
124             break;
125         case TELESCOPE_P:
126             currentPage++;
127             ui->wizardContainer->setCurrentIndex(currentPage);
128             break;
129         case LOCAL_P:
130             currentPage++;
131             ui->wizardContainer->setCurrentIndex(currentPage);
132             break;
133         case PORT_P:
134             establishLink();
135             break;
136         default:
137             break;
138     }
139 }
140 
processBack(void)141 void telescopeWizardProcess::processBack(void)
142 {
143     // for now, just display the next page, and restart once we reached the end
144 
145     switch (currentPage)
146     {
147         case INTRO_P:
148             // we shouldn't be here!
149             break;
150             break;
151         case MODEL_P:
152             currentPage--;
153             ui->backB->hide();
154             ui->wizardContainer->setCurrentIndex(currentPage);
155             break;
156         case TELESCOPE_P:
157             currentPage--;
158             ui->wizardContainer->setCurrentIndex(currentPage);
159             break;
160         case LOCAL_P:
161             currentPage--;
162             ui->wizardContainer->setCurrentIndex(currentPage);
163             break;
164         case PORT_P:
165             currentPage--;
166             ui->wizardContainer->setCurrentIndex(currentPage);
167             break;
168         default:
169             break;
170     }
171 }
172 
newTime()173 void telescopeWizardProcess::newTime()
174 {
175     TimeDialog timedialog(KStars::Instance()->data()->lt(), KStars::Instance()->data()->geo(), KStars::Instance());
176 
177     if (timedialog.exec() == QDialog::Accepted)
178     {
179         KStarsDateTime dt(timedialog.selectedDate(), timedialog.selectedTime());
180         KStars::Instance()->data()->changeDateTime(dt);
181 
182         ui->timeOut->setText(
183             QString().sprintf("%02d:%02d:%02d", dt.time().hour(), dt.time().minute(), dt.time().second()));
184         ui->dateOut->setText(QString().sprintf("%d-%02d-%02d", dt.date().year(), dt.date().month(), dt.date().day()));
185     }
186 }
187 
newLocation()188 void telescopeWizardProcess::newLocation()
189 {
190     KStars::Instance()->slotGeoLocator();
191     GeoLocation *geo = KStars::Instance()->data()->geo();
192     ui->locationOut->setText(
193         QString("%1, %2, %3").arg(geo->translatedName(),geo->translatedProvince(), geo->translatedCountry()));
194     ui->timeOut->setText(QString().sprintf("%02d:%02d:%02d", KStars::Instance()->data()->lt().time().hour(),
195                                            KStars::Instance()->data()->lt().time().minute(),
196                                            KStars::Instance()->data()->lt().time().second()));
197     ui->dateOut->setText(QString().sprintf("%d-%02d-%02d", KStars::Instance()->data()->lt().date().year(),
198                                            KStars::Instance()->data()->lt().date().month(),
199                                            KStars::Instance()->data()->lt().date().day()));
200 }
201 
establishLink()202 void telescopeWizardProcess::establishLink()
203 {
204     managedDevice.clear();
205 
206     DriverInfo *dv = driversList.value(ui->telescopeCombo->currentText());
207 
208     if (dv == nullptr)
209         return;
210 
211     managedDevice.append(dv);
212     connect(INDIListener::Instance(), SIGNAL(newDevice(ISD::GDInterface*)), this,
213             SLOT(processTelescope(ISD::GDInterface*)));
214 
215     if (ui->portIn->text().isEmpty())
216     {
217         progressScan = new QProgressDialog(i18n("Please wait while KStars scan communication ports for attached "
218                                                 "telescopes.\nThis process might take few minutes to complete."),
219                                            i18n("Cancel"), 0, portList.count());
220         progressScan->setValue(0);
221         //qDebug() << "KProgressDialog for automatic search has been initiated";
222     }
223     else
224     {
225         progressScan = new QProgressDialog(i18n("Please wait while KStars tries to connect to your telescope..."),
226                                            i18n("Cancel"), portList.count(), portList.count());
227         progressScan->setValue(portList.count());
228         //qDebug() << "KProgressDialog for manual search has been initiated";
229     }
230 
231     progressScan->setAutoClose(true);
232     progressScan->setAutoReset(true);
233     progressScan->show();
234 
235     if (dv->getClientState() == false)
236     {
237         if (DriverManager::Instance()->startDevices(managedDevice) == false)
238         {
239             Reset();
240             close();
241             return;
242         }
243     }
244     else
245         processTelescope(INDIListener::Instance()->getDevice(dv->getName()));
246 }
247 
processTelescope(ISD::GDInterface * telescope)248 void telescopeWizardProcess::processTelescope(ISD::GDInterface *telescope)
249 {
250     if (telescope == nullptr)
251         return;
252 
253     scopeDevice = telescope;
254 
255     // port empty, start autoscan
256     if (ui->portIn->text().isEmpty())
257     {
258         //newDeviceTimer->stop();
259         linkRejected = false;
260         connect(scopeDevice, SIGNAL(Connected()), this, SLOT(linkSuccess()), Qt::QueuedConnection);
261         connect(scopeDevice, SIGNAL(Disconnected()), this, SLOT(scanPorts()), Qt::QueuedConnection);
262         scanPorts();
263     }
264     else
265     {
266         QString scopePort = ui->portIn->text();
267 
268         scopeDevice->runCommand(INDI_SET_PORT, &scopePort);
269 
270         scopeDevice->runCommand(INDI_CONNECT);
271 
272         Options::setShowINDIMessages(INDIMessageBar);
273 
274         close();
275     }
276 
277     /*
278     pp = indiDev->findProp("DEVICE_PORT");
279     if (!pp) return;
280     lp = pp->findElement("PORT");
281     if (!lp) return;
282 
283     lp->write_w->setText(ui->portIn->text());
284 
285     pp = indiDev->findProp("CONNECTION");
286     if (!pp) return;
287 
288     //newDeviceTimer->stop();
289     */
290 
291     /*lp = pp->findElement("CONNECT");
292     pp->newSwitch(lp);
293 
294     Reset();
295 
296     indimenu->show();*/
297 }
298 
scanPorts()299 void telescopeWizardProcess::scanPorts()
300 {
301     if (progressScan == nullptr)
302     {
303         close();
304         return;
305     }
306 
307     currentPort++;
308 
309     if (progressScan->wasCanceled())
310     {
311         if (linkRejected)
312             return;
313 
314         disconnect(this, SLOT(linkSuccess()));
315         disconnect(this, SLOT(scanPorts()));
316 
317         DriverManager::Instance()->stopDevices(managedDevice);
318         linkRejected = true;
319         Reset();
320         return;
321     }
322 
323     progressScan->setValue(currentPort);
324 
325     //qDebug() << "Current port is " << currentPort << " and port count is " << portList.count() << endl;
326 
327     if (currentPort >= portList.count())
328     {
329         if (linkRejected)
330             return;
331 
332         disconnect(this, SLOT(scanPorts()));
333         disconnect(this, SLOT(linkSuccess()));
334         linkRejected = true;
335         DriverManager::Instance()->stopDevices(managedDevice);
336         Reset();
337 
338         KMessageBox::sorry(
339             0,
340             i18n("Sorry. KStars failed to detect any attached telescopes, please check your settings and try again."));
341         return;
342     }
343 
344     QString scopePort = portList[currentPort];
345     scopeDevice->runCommand(INDI_SET_PORT, &scopePort);
346 
347     scopeDevice->runCommand(INDI_CONNECT);
348 }
349 
linkSuccess()350 void telescopeWizardProcess::linkSuccess()
351 {
352     Reset();
353 
354     KStars::Instance()->statusBar()->showMessage(i18n("Telescope Wizard completed successfully."), 0);
355 
356     close();
357 
358     GUIManager::Instance()->show();
359 }
360 
Reset()361 void telescopeWizardProcess::Reset()
362 {
363     currentPort  = -1;
364     linkRejected = false;
365 
366     delete (progressScan);
367     progressScan = nullptr;
368 }
369