File indexing completed on 2024-12-01 06:35:11
0001 /* 0002 SPDX-FileCopyrightText: 2012 Jasem Mutlaq (mutlaqja AT ikarustech DOT com) 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include <indicom.h> 0008 #include <base64.h> 0009 #include <basedevice.h> 0010 0011 #include <QFrame> 0012 #include <QCheckBox> 0013 #include <QLabel> 0014 #include <QPushButton> 0015 #include <QLayout> 0016 #include <QButtonGroup> 0017 #include <QSocketNotifier> 0018 #include <QDateTime> 0019 #include <QSplitter> 0020 #include <QLineEdit> 0021 #include <QDebug> 0022 #include <QComboBox> 0023 #include <QStatusBar> 0024 #include <QMenu> 0025 #include <QTabWidget> 0026 #include <QTextEdit> 0027 0028 #include <KLed> 0029 #include <KLocalizedString> 0030 #include <KMessageBox> 0031 0032 #include "kstars.h" 0033 #include "skymap.h" 0034 #include "Options.h" 0035 #include "skyobjects/skyobject.h" 0036 #include "dialogs/timedialog.h" 0037 #include "geolocation.h" 0038 0039 #include "indiproperty.h" 0040 #include "indidevice.h" 0041 #include "indigroup.h" 0042 #include "indielement.h" 0043 0044 #include <indi_debug.h> 0045 0046 const char *libindi_strings_context = "string from libindi, used in the config dialog"; 0047 0048 INDI_D::INDI_D(QWidget *parent, INDI::BaseDevice baseDevice, ClientManager *in_cm) : QWidget(parent) 0049 { 0050 #ifdef Q_OS_OSX 0051 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); 0052 #endif 0053 m_BaseDevice = baseDevice; 0054 m_ClientManager = in_cm; 0055 0056 m_Name = m_BaseDevice.getDeviceName(); 0057 0058 QHBoxLayout *layout = new QHBoxLayout(this); 0059 0060 deviceVBox = new QSplitter(Qt::Vertical, this); 0061 0062 groupContainer = new QTabWidget(this); 0063 0064 msgST_w = new QTextEdit(this); 0065 msgST_w->setReadOnly(true); 0066 msgST_w->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow); 0067 0068 deviceVBox->addWidget(groupContainer); 0069 deviceVBox->addWidget(msgST_w); 0070 deviceVBox->setStretchFactor(0, 2); 0071 0072 layout->addWidget(deviceVBox); 0073 } 0074 0075 bool INDI_D::buildProperty(INDI::Property prop) 0076 { 0077 if (!prop.isValid()) 0078 return false; 0079 0080 QString groupName(prop.getGroupName()); 0081 0082 if (prop.getDeviceName() != m_Name) 0083 return false; 0084 0085 INDI_G *pg = getGroup(groupName); 0086 0087 if (pg == nullptr) 0088 { 0089 pg = new INDI_G(this, groupName); 0090 groupsList.append(pg); 0091 groupContainer->addTab(pg, i18nc(libindi_strings_context, groupName.toUtf8())); 0092 } 0093 0094 return pg->addProperty(prop); 0095 } 0096 0097 #if 0 0098 bool INDI_D::removeProperty(INDI::Property prop) 0099 { 0100 if (prop == nullptr) 0101 return false; 0102 0103 QString groupName(prop->getGroupName()); 0104 0105 if (strcmp(prop->getDeviceName(), m_BaseDevice->getDeviceName())) 0106 { 0107 // qDebug() << Q_FUNC_INFO << "Ignoring property " << prop->getName() << " for device " << prop->getgetDeviceName() << " because our device is " 0108 // << dv->getDeviceName() << Qt::endl; 0109 return false; 0110 } 0111 0112 // qDebug() << Q_FUNC_INFO << "Received new property " << prop->getName() << " for our device " << dv->getDeviceName() << Qt::endl; 0113 0114 INDI_G *pg = getGroup(groupName); 0115 0116 if (pg == nullptr) 0117 return false; 0118 0119 bool removeResult = pg->removeProperty(prop->getName()); 0120 0121 if (pg->size() == 0 && removeResult) 0122 { 0123 //qDebug() << Q_FUNC_INFO << "Removing tab for group " << pg->getName() << " with an index of " << groupsList.indexOf(pg) << Qt::endl; 0124 groupContainer->removeTab(groupsList.indexOf(pg)); 0125 groupsList.removeOne(pg); 0126 delete (pg); 0127 } 0128 0129 return removeResult; 0130 } 0131 #endif 0132 0133 bool INDI_D::removeProperty(INDI::Property prop) 0134 { 0135 if (prop.getDeviceName() != m_Name) 0136 return false; 0137 0138 for (auto &oneGroup : groupsList) 0139 { 0140 for (auto &oneProperty : oneGroup->getProperties()) 0141 { 0142 if (prop.getName() == oneProperty->getName()) 0143 { 0144 bool rc = oneGroup->removeProperty(prop.getName()); 0145 if (oneGroup->size() == 0) 0146 { 0147 int index = groupsList.indexOf(oneGroup); 0148 groupContainer->removeTab(index); 0149 delete groupsList.takeAt(index); 0150 } 0151 return rc; 0152 } 0153 } 0154 } 0155 0156 return false; 0157 } 0158 0159 bool INDI_D::updateProperty(INDI::Property prop) 0160 { 0161 switch (prop.getType()) 0162 { 0163 case INDI_SWITCH: 0164 return updateSwitchGUI(prop); 0165 case INDI_NUMBER: 0166 return updateNumberGUI(prop); 0167 case INDI_TEXT: 0168 return updateTextGUI(prop); 0169 case INDI_LIGHT: 0170 return updateLightGUI(prop); 0171 case INDI_BLOB: 0172 return updateBLOBGUI(prop); 0173 default: 0174 return false; 0175 } 0176 } 0177 0178 bool INDI_D::updateSwitchGUI(INDI::Property prop) 0179 { 0180 INDI_P *guiProp = nullptr; 0181 0182 if (m_Name != prop.getDeviceName()) 0183 return false; 0184 0185 for (const auto &pg : groupsList) 0186 { 0187 if ((guiProp = pg->getProperty(prop.getName())) != nullptr) 0188 break; 0189 } 0190 0191 if (guiProp == nullptr || guiProp->isRegistered() == false) 0192 return false; 0193 0194 guiProp->updateStateLED(); 0195 0196 if (guiProp->getGUIType() == PG_MENU) 0197 guiProp->updateMenuGUI(); 0198 else 0199 { 0200 for (const auto &lp : guiProp->getElements()) 0201 lp->syncSwitch(); 0202 } 0203 0204 return true; 0205 } 0206 0207 bool INDI_D::updateTextGUI(INDI::Property prop) 0208 { 0209 INDI_P *guiProp = nullptr; 0210 0211 if (m_Name != prop.getDeviceName()) 0212 return false; 0213 0214 for (const auto &pg : groupsList) 0215 { 0216 auto p = pg->getProperty(prop.getName()); 0217 if (p != nullptr) 0218 { 0219 guiProp = p; 0220 break; 0221 } 0222 } 0223 0224 if (guiProp == nullptr) 0225 return false; 0226 0227 guiProp->updateStateLED(); 0228 0229 for (const auto &lp : guiProp->getElements()) 0230 lp->syncText(); 0231 0232 return true; 0233 } 0234 0235 bool INDI_D::updateNumberGUI(INDI::Property prop) 0236 { 0237 INDI_P *guiProp = nullptr; 0238 0239 if (m_Name != prop.getDeviceName()) 0240 return false; 0241 0242 for (const auto &pg : groupsList) 0243 { 0244 auto p = pg->getProperty(prop.getName()); 0245 if (p != nullptr) 0246 { 0247 guiProp = p; 0248 break; 0249 } 0250 } 0251 0252 if (guiProp == nullptr) 0253 return false; 0254 0255 guiProp->updateStateLED(); 0256 0257 for (const auto &lp : guiProp->getElements()) 0258 lp->syncNumber(); 0259 0260 return true; 0261 } 0262 0263 bool INDI_D::updateLightGUI(INDI::Property prop) 0264 { 0265 INDI_P *guiProp = nullptr; 0266 0267 if (m_Name != prop.getDeviceName()) 0268 return false; 0269 0270 for (const auto &pg : groupsList) 0271 { 0272 auto p = pg->getProperty(prop.getName()); 0273 if (p != nullptr) 0274 { 0275 guiProp = p; 0276 break; 0277 } 0278 } 0279 0280 if (guiProp == nullptr) 0281 return false; 0282 0283 guiProp->updateStateLED(); 0284 0285 for (const auto &lp : guiProp->getElements()) 0286 lp->syncLight(); 0287 0288 return true; 0289 } 0290 0291 bool INDI_D::updateBLOBGUI(INDI::Property prop) 0292 { 0293 INDI_P *guiProp = nullptr; 0294 0295 if (m_Name != prop.getDeviceName()) 0296 return false; 0297 0298 for (const auto &pg : groupsList) 0299 { 0300 auto p = pg->getProperty(prop.getName()); 0301 if (p != nullptr) 0302 { 0303 guiProp = p; 0304 break; 0305 } 0306 } 0307 0308 if (guiProp == nullptr) 0309 return false; 0310 0311 guiProp->updateStateLED(); 0312 0313 return true; 0314 } 0315 0316 void INDI_D::updateMessageLog(INDI::BaseDevice idv, int messageID) 0317 { 0318 if (idv.getDeviceName() != m_BaseDevice.getDeviceName()) 0319 return; 0320 0321 QString message = QString::fromStdString(m_BaseDevice.messageQueue(messageID)); 0322 QString formatted = message; 0323 0324 // TODO the colors should be from the color scheme 0325 if (message.mid(21, 2) == "[E") 0326 formatted = QString("<span style='color:red'>%1</span>").arg(message); 0327 else if (message.mid(21, 2) == "[W") 0328 formatted = QString("<span style='color:orange'>%1</span>").arg(message); 0329 else if (message.mid(21, 2) != "[I") 0330 { 0331 // Debug message 0332 qCDebug(KSTARS_INDI) << idv.getDeviceName() << ":" << message.mid(21); 0333 return; 0334 } 0335 0336 if (Options::showINDIMessages()) 0337 KStars::Instance()->statusBar()->showMessage(i18nc("INDI message shown in status bar", "%1", message), 0); 0338 0339 msgST_w->ensureCursorVisible(); 0340 msgST_w->insertHtml(i18nc("Message shown in INDI control panel", "%1", formatted)); 0341 msgST_w->insertPlainText("\n"); 0342 QTextCursor c = msgST_w->textCursor(); 0343 c.movePosition(QTextCursor::Start); 0344 msgST_w->setTextCursor(c); 0345 0346 qCInfo(KSTARS_INDI) << idv.getDeviceName() << ": " << message.mid(21); 0347 } 0348 0349 //INDI_D::~INDI_D() 0350 //{ 0351 // while (!groupsList.isEmpty()) 0352 // delete groupsList.takeFirst(); 0353 //} 0354 0355 INDI_G *INDI_D::getGroup(const QString &groupName) const 0356 { 0357 for (const auto &pg : groupsList) 0358 { 0359 if (pg->getName() == groupName) 0360 return pg; 0361 } 0362 0363 return nullptr; 0364 } 0365 0366 void INDI_D::clearMessageLog() 0367 { 0368 msgST_w->clear(); 0369 }