File indexing completed on 2024-04-14 03:42:16
0001 /* 0002 SPDX-FileCopyrightText: 2017 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "profilewizard.h" 0008 0009 #include <QDesktopServices> 0010 #include <QUrl> 0011 #include <QTcpSocket> 0012 #include <QTimer> 0013 0014 #include "kstars.h" 0015 #include "auxiliary/kspaths.h" 0016 #include "ksnotification.h" 0017 #include "qMDNS.h" 0018 0019 ProfileWizard::ProfileWizard() : QDialog(KStars::Instance()) 0020 { 0021 setupUi(this); 0022 0023 #ifdef Q_OS_OSX 0024 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); 0025 #endif 0026 0027 QPixmap im; 0028 if (im.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "wzekos.png"))) 0029 wizardPix->setPixmap(im); 0030 0031 remoteEquipmentSVG->load(QString(":/icons/pi.svg")); 0032 0033 connect(buttonBox, SIGNAL(rejected()), this, SLOT(close())); 0034 connect(buttonBox, &QDialogButtonBox::helpRequested, this, []() 0035 { 0036 KStars::Instance()->appHelpActivated(); 0037 }); 0038 connect(buttonBox, &QDialogButtonBox::clicked, this, [this](QAbstractButton * button) 0039 { 0040 if (button == buttonBox->button(QDialogButtonBox::Reset)) 0041 reset(); 0042 }); 0043 0044 connect(discoverEkosB, &QPushButton::clicked, this, 0045 []() 0046 { 0047 QDesktopServices::openUrl(QUrl("https://www.indilib.org/about/ekos.html")); 0048 }); 0049 connect(videoTutorialsB, &QPushButton::clicked, this, 0050 []() 0051 { 0052 QDesktopServices::openUrl(QUrl("https://www.youtube.com/user/QAstronomy")); 0053 }); 0054 connect(INDIInfoB, &QPushButton::clicked, this, 0055 []() 0056 { 0057 QDesktopServices::openUrl(QUrl("https://indilib.org/about/discover-indi.html")); 0058 }); 0059 0060 // Intro actions 0061 connect(introNextB, &QPushButton::clicked, this, 0062 [this]() 0063 { 0064 wizardContainer->setCurrentIndex(EQUIPMENT_LOCATION); 0065 }); 0066 0067 // Equipment Location actions 0068 connect(localEquipmentB, SIGNAL(clicked()), this, SLOT(processLocalEquipment())); 0069 connect(remoteEquipmentB, &QPushButton::clicked, this, 0070 [this]() 0071 { 0072 wizardContainer->setCurrentIndex(REMOTE_EQUIPMENT_SELECTION); 0073 }); 0074 equipmentStellarmateB->setIcon(QIcon(":/icons/stellarmate.svg")); 0075 connect(equipmentStellarmateB, &QPushButton::clicked, this, &ProfileWizard::processRemoteEquipmentSelection); 0076 0077 equipmentAtikbaseB->setIcon(QIcon(":/icons/atikbase.svg")); 0078 connect(equipmentAtikbaseB, &QPushButton::clicked, this, &ProfileWizard::processRemoteEquipmentSelection); 0079 0080 connect(equipmentOtherB, &QPushButton::clicked, this, &ProfileWizard::processRemoteEquipmentSelection); 0081 0082 // Remote Equipment Action 0083 connect(remoteEquipmentNextB, SIGNAL(clicked()), this, SLOT(processRemoteEquipment())); 0084 0085 // StellarMate Equipment Action 0086 connect(stellarMateEquipmentNextB, SIGNAL(clicked()), this, SLOT(processPiEquipment())); 0087 #ifdef Q_OS_WIN 0088 // Auto Detect does not work on Windows yet for some reason. 0089 // Packet is sent correctly, but no replies are received from anything on the LAN outside of PC. 0090 PiAutoDetectB->setEnabled(false); 0091 #else 0092 connect(PiAutoDetectB, SIGNAL(clicked()), this, SLOT(detectStellarMate())); 0093 #endif 0094 0095 // Local Mac 0096 connect(useExternalINDIB, SIGNAL(clicked()), this, SLOT(processLocalMac())); 0097 connect(useInternalINDIB, SIGNAL(clicked()), this, SLOT(processLocalMac())); 0098 0099 // Create Profile 0100 connect(createProfileB, SIGNAL(clicked()), this, SLOT(createProfile())); 0101 } 0102 0103 void ProfileWizard::reset() 0104 { 0105 useInternalServer = true; 0106 useWebManager = false; 0107 useJoystick = false; 0108 useRemoteAstrometry = false; 0109 useSkySafari = false; 0110 useWatchDog = false; 0111 useGuiderType = INTERNAL_GUIDER; 0112 0113 host.clear(); 0114 port = "7624"; 0115 0116 wizardContainer->setCurrentIndex(INTRO); 0117 } 0118 0119 void ProfileWizard::processLocalEquipment() 0120 { 0121 #if defined(Q_OS_OSX) 0122 wizardContainer->setCurrentIndex(MAC_LOCAL); 0123 #elif defined(Q_OS_WIN) 0124 wizardContainer->setCurrentIndex(WINDOWS_LOCAL); 0125 #else 0126 useInternalServer = true; 0127 useJoystickCheck->setEnabled(true); 0128 useRemoteAstrometryCheck->setEnabled(false); 0129 useWatchDogCheck->setEnabled(false); 0130 useSkySafariCheck->setEnabled(true); 0131 wizardContainer->setCurrentIndex(CREATE_PROFILE); 0132 #endif 0133 } 0134 0135 void ProfileWizard::processRemoteEquipment() 0136 { 0137 bool portOK = false; 0138 remotePortEdit->text().toInt(&portOK); 0139 0140 if (portOK == false) 0141 { 0142 KSNotification::error(i18n("Invalid port.")); 0143 return; 0144 } 0145 0146 if (remoteHostEdit->text().isEmpty()) 0147 { 0148 KSNotification::error(i18n("Host name cannot be empty.")); 0149 return; 0150 } 0151 0152 useInternalServer = false; 0153 0154 host = remoteHostEdit->text(); 0155 port = remotePortEdit->text(); 0156 0157 if (webManagerNotSureB->isChecked()) 0158 { 0159 QTcpSocket socket; 0160 // Should probably make 8624 configurable too? 0161 socket.connectToHost(host, 8624); 0162 useWebManager = socket.waitForConnected(); 0163 } 0164 else 0165 useWebManager = webManagerYesR->isChecked(); 0166 0167 useJoystickCheck->setEnabled(true); 0168 useRemoteAstrometryCheck->setEnabled(true); 0169 useWatchDogCheck->setEnabled(true); 0170 useSkySafariCheck->setEnabled(true); 0171 0172 wizardContainer->setCurrentIndex(CREATE_PROFILE); 0173 } 0174 0175 void ProfileWizard::processPiEquipment() 0176 { 0177 if (PiHost->text().isEmpty()) 0178 { 0179 KSNotification::error(i18n("Host name cannot be empty.")); 0180 return; 0181 } 0182 0183 host = PiHost->text(); 0184 port = PiPort->text(); 0185 0186 useInternalServer = false; 0187 useWebManager = true; 0188 0189 useJoystickCheck->setEnabled(true); 0190 useRemoteAstrometryCheck->setEnabled(true); 0191 useWatchDogCheck->setEnabled(true); 0192 useSkySafariCheck->setEnabled(true); 0193 0194 wizardContainer->setCurrentIndex(CREATE_PROFILE); 0195 } 0196 0197 void ProfileWizard::processLocalMac() 0198 { 0199 QPushButton *button = qobject_cast<QPushButton *>(sender()); 0200 0201 if (button == nullptr) 0202 return; 0203 0204 host = "localhost"; 0205 port = "7624"; 0206 0207 useInternalServer = (button == useInternalINDIB); 0208 0209 useJoystickCheck->setEnabled(false); 0210 useRemoteAstrometryCheck->setEnabled(false); 0211 useWatchDogCheck->setEnabled(false); 0212 useSkySafariCheck->setEnabled(true); 0213 0214 wizardContainer->setCurrentIndex(CREATE_PROFILE); 0215 } 0216 0217 void ProfileWizard::createProfile() 0218 { 0219 if (profileNameEdit->text().isEmpty()) 0220 { 0221 KSNotification::error(i18n("Profile name cannot be empty.")); 0222 return; 0223 } 0224 0225 useJoystick = useJoystickCheck->isEnabled() && useJoystickCheck->isChecked(); 0226 useWatchDog = useWatchDogCheck->isEnabled() && useWatchDogCheck->isChecked(); 0227 useSkySafari = useSkySafariCheck->isEnabled() && useSkySafariCheck->isChecked(); 0228 useRemoteAstrometry = useRemoteAstrometryCheck->isEnabled() && useRemoteAstrometryCheck->isChecked(); 0229 if (useInternalGuiderR->isChecked()) 0230 useGuiderType = INTERNAL_GUIDER; 0231 else if (usePHD2R->isChecked()) 0232 useGuiderType = PHD2_GUIDER; 0233 else 0234 useGuiderType = LIN_GUIDER; 0235 0236 profileName = profileNameEdit->text(); 0237 0238 if (useInternalServer) 0239 { 0240 host.clear(); 0241 port.clear(); 0242 } 0243 0244 accept(); 0245 } 0246 0247 QStringList ProfileWizard::selectedAuxDrivers() 0248 { 0249 QStringList auxList; 0250 0251 if (useJoystick) 0252 auxList << "Joystick"; 0253 if (useWatchDog) 0254 auxList << "WatchDog"; 0255 if (useSkySafari) 0256 auxList << "SkySafari"; 0257 if (useRemoteAstrometry) 0258 auxList << "Astrometry"; 0259 0260 return auxList; 0261 } 0262 0263 int ProfileWizard::selectedExternalGuider() 0264 { 0265 return useGuiderType; 0266 } 0267 0268 void ProfileWizard::detectStellarMate() 0269 { 0270 stellarMateDetectDialog = new QProgressDialog(this); 0271 stellarMateDetectDialog->setMinimum(0); 0272 stellarMateDetectDialog->setMaximum(0); 0273 stellarMateDetectDialog->setWindowTitle(i18nc("@title:window", "Detecting StellarMate...")); 0274 stellarMateDetectDialog->setLabelText(i18n("Please wait while searching for StellarMate...")); 0275 0276 stellarMateDetectDialog->show(); 0277 0278 connect(stellarMateDetectDialog.data(), &QProgressDialog::canceled, [&]() 0279 { 0280 qMDNS::getInstance()->disconnect(); 0281 }); 0282 connect(qMDNS::getInstance(), SIGNAL(hostFound(QHostInfo)), this, SLOT(processHostInfo(QHostInfo))); 0283 QTimer::singleShot(120 * 1000, this, SLOT(detectStellarMateTimeout())); 0284 0285 qMDNS::getInstance()->lookup("stellarmate"); 0286 } 0287 0288 void ProfileWizard::processHostInfo(QHostInfo info) 0289 { 0290 PiHost->setText(info.hostName()); 0291 qMDNS::getInstance()->disconnect(); 0292 stellarMateDetectDialog->close(); 0293 } 0294 0295 void ProfileWizard::detectStellarMateTimeout() 0296 { 0297 if (stellarMateDetectDialog->isHidden() == false) 0298 { 0299 KSNotification::error(i18n("Failed to detect any StellarMate gadget. Make sure it is powered and on the same network.")); 0300 stellarMateDetectDialog->close(); 0301 } 0302 } 0303 0304 void ProfileWizard::processRemoteEquipmentSelection() 0305 { 0306 QToolButton *button = qobject_cast<QToolButton*>(sender()); 0307 if (!button) 0308 wizardContainer->setCurrentIndex(GENERIC_EQUIPMENT); 0309 else if (button == equipmentStellarmateB) 0310 { 0311 PiHost->setText("stellarmate.local"); 0312 wizardContainer->setCurrentIndex(PI_EQUIPMENT); 0313 } 0314 else if (button == equipmentAtikbaseB) 0315 { 0316 PiHost->setText("atikbase.local"); 0317 wizardContainer->setCurrentIndex(PI_EQUIPMENT); 0318 } 0319 }