diff --git a/kstars/indi/indidevice.cpp b/kstars/indi/indidevice.cpp index c11e9b6d6..446fc6876 100644 --- a/kstars/indi/indidevice.cpp +++ b/kstars/indi/indidevice.cpp @@ -1,341 +1,341 @@ /* GUI Device Manager Copyright (C) 2012 Jasem Mutlaq (mutlaqja AT ikarustech DOT com) This application is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kstars.h" #include "skymap.h" #include "Options.h" #include "skyobjects/skyobject.h" #include "dialogs/timedialog.h" #include "geolocation.h" #include "indiproperty.h" #include "indidevice.h" #include "indigroup.h" #include "indielement.h" #include const char *libindi_strings_context = "string from libindi, used in the config dialog"; INDI_D::INDI_D(INDI::BaseDevice *in_dv, ClientManager *in_cm) : QDialog() { #ifdef Q_OS_OSX setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); #endif m_BaseDevice = in_dv; m_ClientManager = in_cm; m_Name = m_BaseDevice->getDeviceName(); deviceVBox = new QSplitter(); deviceVBox->setOrientation(Qt::Vertical); groupContainer = new QTabWidget(); msgST_w = new QTextEdit(); msgST_w->setReadOnly(true); deviceVBox->addWidget(groupContainer); deviceVBox->addWidget(msgST_w); //parent->mainTabWidget->addTab(deviceVBox, label); } bool INDI_D::buildProperty(INDI::Property *prop) { if (!prop->getRegistered()) return false; QString groupName(prop->getGroupName()); if (prop->getDeviceName() != m_Name) return false; INDI_G *pg = getGroup(groupName); if (pg == nullptr) { pg = new INDI_G(this, groupName); groupsList.append(pg); groupContainer->addTab(pg->getScrollArea(), i18nc(libindi_strings_context, groupName.toUtf8())); } return pg->addProperty(prop); } #if 0 bool INDI_D::removeProperty(INDI::Property *prop) { if (prop == nullptr) return false; QString groupName(prop->getGroupName()); if (strcmp(prop->getDeviceName(), m_BaseDevice->getDeviceName())) { // qDebug() << "Ignoring property " << prop->getName() << " for device " << prop->getgetDeviceName() << " because our device is " // << dv->getDeviceName() << endl; return false; } // qDebug() << "Received new property " << prop->getName() << " for our device " << dv->getDeviceName() << endl; INDI_G *pg = getGroup(groupName); if (pg == nullptr) return false; bool removeResult = pg->removeProperty(prop->getName()); if (pg->size() == 0 && removeResult) { //qDebug() << "Removing tab for group " << pg->getName() << " with an index of " << groupsList.indexOf(pg) << endl; groupContainer->removeTab(groupsList.indexOf(pg)); groupsList.removeOne(pg); delete (pg); } return removeResult; } #endif bool INDI_D::removeProperty(const QString &device, const QString &name) { Q_UNUSED(device) for (auto &oneGroup : groupsList) { for (auto &oneProperty : oneGroup->getProperties()) { if (name == oneProperty->getName()) { bool rc = oneGroup->removeProperty(name); if (oneGroup->size() == 0) { int index = groupsList.indexOf(oneGroup); groupContainer->removeTab(index); delete groupsList.takeAt(index); } return rc; } } } return false; } bool INDI_D::updateSwitchGUI(ISwitchVectorProperty *svp) { INDI_P *guiProp = nullptr; QString propName(svp->name); if (m_Name != svp->device) return false; for (const auto &pg : groupsList) { if ((guiProp = pg->getProperty(propName)) != nullptr) break; } - if (guiProp == nullptr) + if (guiProp == nullptr || guiProp->isRegistered() == false) return false; guiProp->updateStateLED(); if (guiProp->getGUIType() == PG_MENU) guiProp->updateMenuGUI(); else { for (const auto &lp : guiProp->getElements()) lp->syncSwitch(); } return true; } bool INDI_D::updateTextGUI(ITextVectorProperty *tvp) { INDI_P *guiProp = nullptr; QString propName(tvp->name); if (m_Name != tvp->device) return false; for (const auto &pg : groupsList) { if ((guiProp = pg->getProperty(propName)) != nullptr) break; } if (guiProp == nullptr) return false; guiProp->updateStateLED(); for (const auto &lp : guiProp->getElements()) lp->syncText(); return true; } bool INDI_D::updateNumberGUI(INumberVectorProperty *nvp) { INDI_P *guiProp = nullptr; QString propName(nvp->name); if (m_Name != nvp->device) return false; for (const auto &pg : groupsList) { if ((guiProp = pg->getProperty(propName)) != nullptr) break; } if (guiProp == nullptr) return false; guiProp->updateStateLED(); for (const auto &lp : guiProp->getElements()) lp->syncNumber(); return true; } bool INDI_D::updateLightGUI(ILightVectorProperty *lvp) { INDI_P *guiProp = nullptr; QString propName(lvp->name); if (m_Name != lvp->device) return false; for (const auto &pg : groupsList) { if ((guiProp = pg->getProperty(propName)) != nullptr) break; } if (guiProp == nullptr) return false; guiProp->updateStateLED(); for (const auto &lp : guiProp->getElements()) lp->syncLight(); return true; } bool INDI_D::updateBLOBGUI(IBLOB *bp) { INDI_P *guiProp = nullptr; QString propName(bp->bvp->name); if (m_Name != bp->bvp->device) return false; for (const auto &pg : groupsList) { if ((guiProp = pg->getProperty(propName)) != nullptr) break; } if (guiProp == nullptr) return false; guiProp->updateStateLED(); return true; } void INDI_D::updateMessageLog(INDI::BaseDevice *idv, int messageID) { if (idv != m_BaseDevice) return; QString message = QString::fromStdString(m_BaseDevice->messageQueue(messageID)); QString formatted = message; // TODO the colors should be from the color scheme if (message.mid(21, 2) == "[E") formatted = QString("%1").arg(message); else if (message.mid(21, 2) == "[W") formatted = QString("%1").arg(message); else if (message.mid(21, 2) != "[I") { // Debug message qCDebug(KSTARS_INDI) << idv->getDeviceName() << ":" << message.mid(21); return; } if (Options::showINDIMessages()) KStars::Instance()->statusBar()->showMessage(i18nc("INDI message shown in status bar", "%1", message), 0); msgST_w->ensureCursorVisible(); msgST_w->insertHtml(i18nc("Message shown in INDI control panel", "%1", formatted)); msgST_w->insertPlainText("\n"); QTextCursor c = msgST_w->textCursor(); c.movePosition(QTextCursor::Start); msgST_w->setTextCursor(c); qCInfo(KSTARS_INDI) << idv->getDeviceName() << ": " << message.mid(21); } INDI_D::~INDI_D() { while (!groupsList.isEmpty()) delete groupsList.takeFirst(); } INDI_G *INDI_D::getGroup(const QString &groupName) { for (const auto &pg : groupsList) { if (pg->getName() == groupName) return pg; } return nullptr; } void INDI_D::clearMessageLog() { msgST_w->clear(); } diff --git a/kstars/indi/indiproperty.cpp b/kstars/indi/indiproperty.cpp index 3359f89fe..11961927a 100644 --- a/kstars/indi/indiproperty.cpp +++ b/kstars/indi/indiproperty.cpp @@ -1,683 +1,688 @@ /* INDI Property Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com) This application is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include "indiproperty.h" #include "clientmanager.h" #include "indidevice.h" #include "indielement.h" #include "indigroup.h" #include "kstars.h" #include "Options.h" #include "skymap.h" #include "dialogs/timedialog.h" #include #include #include #include #include #include #include #include #include #include #include extern const char *libindi_strings_context; /******************************************************************* ** INDI Property: contains widgets, labels, and their status *******************************************************************/ INDI_P::INDI_P(INDI_G *ipg, INDI::Property *prop) { pg = ipg; dataProp = prop; name = QString(prop->getName()); PHBox.reset(new QHBoxLayout()); PHBox->setContentsMargins(0, 0, 0, 0); PVBox = new QVBoxLayout(); PVBox->setContentsMargins(0, 0, 0, 0); initGUI(); } INDI_P::~INDI_P() { qDeleteAll(elementList); elementList.clear(); } void INDI_P::updateStateLED() { /* set state light */ switch (dataProp->getState()) { case IPS_IDLE: ledStatus->setColor(Qt::gray); break; case IPS_OK: ledStatus->setColor(Qt::green); break; case IPS_BUSY: ledStatus->setColor(Qt::yellow); break; case IPS_ALERT: ledStatus->setColor(Qt::red); break; default: break; } } /* build widgets for property pp using info in root. */ void INDI_P::initGUI() { QString label = i18nc(libindi_strings_context, dataProp->getLabel()); if (label == "(I18N_EMPTY_MESSAGE)") label = dataProp->getLabel(); /* add to GUI group */ ledStatus.reset(new KLed(pg->getContainer())); ledStatus->setMaximumSize(16, 16); ledStatus->setLook(KLed::Sunken); updateStateLED(); /* Create a horizontally layout widget around light and label */ QWidget *labelWidget = new QWidget(); QHBoxLayout *labelLayout = new QHBoxLayout(); labelLayout->setContentsMargins(0, 0, 0, 0); labelWidget->setLayout(labelLayout); /* #1 First widget is the LED status indicator */ labelLayout->addWidget(ledStatus.get()); if (label.isEmpty()) { label = i18nc(libindi_strings_context, name.toUtf8()); if (label == "(I18N_EMPTY_MESSAGE)") label = name.toUtf8(); labelW.reset(new KSqueezedTextLabel(label, pg->getContainer())); } else labelW.reset(new KSqueezedTextLabel(label, pg->getContainer())); //labelW->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); labelW->setFrameShape(QFrame::Box); labelW->setFrameShadow(QFrame::Sunken); labelW->setMargin(2); labelW->setFixedWidth(PROPERTY_LABEL_WIDTH * KStars::Instance()->devicePixelRatio()); labelW->setTextFormat(Qt::RichText); labelW->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); labelW->setWordWrap(true); labelLayout->addWidget(labelW.get()); PHBox->addWidget(labelWidget, 0, Qt::AlignTop | Qt::AlignLeft); ledStatus->show(); labelW->show(); // #3 Add the Vertical layout which may contain several elements PHBox->addLayout(PVBox); switch (dataProp->getType()) { case INDI_SWITCH: if (dataProp->getSwitch()->r == ISR_NOFMANY) guiType = PG_RADIO; else if (dataProp->getSwitch()->nsp > 4) guiType = PG_MENU; else guiType = PG_BUTTONS; if (guiType == PG_MENU) buildMenuGUI(); else buildSwitchGUI(); break; case INDI_TEXT: buildTextGUI(); break; case INDI_NUMBER: buildNumberGUI(); break; case INDI_LIGHT: buildLightGUI(); break; case INDI_BLOB: buildBLOBGUI(); break; default: break; } } void INDI_P::buildSwitchGUI() { INDI_E *lp = nullptr; ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; groupB.reset(new QButtonGroup()); if (guiType == PG_BUTTONS) { if (svp->r == ISR_1OFMANY) groupB->setExclusive(true); else groupB->setExclusive(false); } else if (guiType == PG_RADIO) groupB->setExclusive(false); if (svp->p != IP_RO) QObject::connect(groupB.get(), SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(newSwitch(QAbstractButton*))); for (int i = 0; i < svp->nsp; i++) { ISwitch *sp = &(svp->sp[i]); lp = new INDI_E(this, dataProp); lp->buildSwitch(groupB.get(), sp); elementList.append(lp); } horSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); PHBox->addItem(horSpacer); } void INDI_P::buildTextGUI() { INDI_E *lp = nullptr; ITextVectorProperty *tvp = dataProp->getText(); if (tvp == nullptr) return; for (int i = 0; i < tvp->ntp; i++) { IText *tp = &(tvp->tp[i]); lp = new INDI_E(this, dataProp); lp->buildText(tp); elementList.append(lp); } horSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); PHBox->addItem(horSpacer); if (tvp->p == IP_RO) return; // INDI STD, but we use our own controls if (name == "TIME_UTC") setupSetButton(i18n("Time")); else setupSetButton(i18n("Set")); } void INDI_P::buildNumberGUI() { INDI_E *lp = nullptr; INumberVectorProperty *nvp = dataProp->getNumber(); if (nvp == nullptr) return; for (int i = 0; i < nvp->nnp; i++) { INumber *np = &(nvp->np[i]); lp = new INDI_E(this, dataProp); lp->buildNumber(np); elementList.append(lp); } horSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); PHBox->addItem(horSpacer); if (nvp->p == IP_RO) return; setupSetButton(i18n("Set")); } void INDI_P::buildLightGUI() { INDI_E *ep = nullptr; ILightVectorProperty *lvp = dataProp->getLight(); if (lvp == nullptr) return; for (int i = 0; i < lvp->nlp; i++) { ILight *lp = &(lvp->lp[i]); ep = new INDI_E(this, dataProp); ep->buildLight(lp); elementList.append(ep); } horSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); PHBox->addItem(horSpacer); } void INDI_P::buildBLOBGUI() { INDI_E *lp = nullptr; IBLOBVectorProperty *bvp = dataProp->getBLOB(); if (bvp == nullptr) return; for (int i = 0; i < bvp->nbp; i++) { IBLOB *bp = &(bvp->bp[i]); lp = new INDI_E(this, dataProp); lp->buildBLOB(bp); elementList.append(lp); } horSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); PHBox->addItem(horSpacer); enableBLOBC = new QCheckBox(); enableBLOBC->setIcon(QIcon::fromTheme("network-modem")); enableBLOBC->setChecked(true); enableBLOBC->setToolTip(i18n("Enable binary data transfer from this property to KStars and vice-versa.")); PHBox->addWidget(enableBLOBC); connect(enableBLOBC, SIGNAL(stateChanged(int)), this, SLOT(setBLOBOption(int))); if (dataProp->getPermission() != IP_RO) setupSetButton(i18n("Upload")); } void INDI_P::setBLOBOption(int state) { pg->getDevice()->getClientManager()->setBLOBEnabled(state == Qt::Checked, dataProp->getDeviceName(), dataProp->getName()); } void INDI_P::newSwitch(QAbstractButton *button) { ISwitchVectorProperty *svp = dataProp->getSwitch(); QString buttonText = button->text(); if (svp == nullptr) return; buttonText.remove('&'); foreach (INDI_E *el, elementList) { if (el->getLabel() == buttonText) { newSwitch(el->getName()); return; } } } void INDI_P::resetSwitch() { ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; if (menuC.get() != nullptr) { menuC->setCurrentIndex(IUFindOnSwitchIndex(svp)); } } void INDI_P::newSwitch(int index) { ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; if (index >= svp->nsp) return; ISwitch *sp = &(svp->sp[index]); IUResetSwitch(svp); sp->s = ISS_ON; sendSwitch(); } void INDI_P::newSwitch(const QString &name) { ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; ISwitch *sp = IUFindSwitch(svp, name.toLatin1().constData()); if (sp == nullptr) return; if (svp->r == ISR_1OFMANY) { IUResetSwitch(svp); sp->s = ISS_ON; } else { if (svp->r == ISR_ATMOST1) { ISState prev_state = sp->s; IUResetSwitch(svp); sp->s = prev_state; } sp->s = (sp->s == ISS_ON) ? ISS_OFF : ISS_ON; } sendSwitch(); } void INDI_P::sendSwitch() { ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; svp->s = IPS_BUSY; foreach (INDI_E *el, elementList) el->syncSwitch(); updateStateLED(); // Send it to server pg->getDevice()->getClientManager()->sendNewSwitch(svp); } void INDI_P::sendText() { ITextVectorProperty *tvp = nullptr; INumberVectorProperty *nvp = nullptr; switch (dataProp->getType()) { case INDI_TEXT: tvp = dataProp->getText(); if (tvp == nullptr) return; tvp->s = IPS_BUSY; foreach (INDI_E *el, elementList) el->updateTP(); pg->getDevice()->getClientManager()->sendNewText(tvp); break; case INDI_NUMBER: nvp = dataProp->getNumber(); if (nvp == nullptr) return; nvp->s = IPS_BUSY; foreach (INDI_E *el, elementList) el->updateNP(); pg->getDevice()->getClientManager()->sendNewNumber(nvp); break; default: break; } updateStateLED(); } void INDI_P::buildMenuGUI() { QStringList menuOptions; QString oneOption; int onItem = -1; INDI_E *lp = nullptr; ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; menuC.reset(new QComboBox(pg->getContainer())); if (svp->p == IP_RO) connect(menuC.get(), SIGNAL(activated(int)), this, SLOT(resetSwitch())); else connect(menuC.get(), SIGNAL(activated(int)), this, SLOT(newSwitch(int))); for (int i = 0; i < svp->nsp; i++) { ISwitch *tp = &(svp->sp[i]); if (tp->s == ISS_ON) onItem = i; lp = new INDI_E(this, dataProp); lp->buildMenuItem(tp); oneOption = i18nc(libindi_strings_context, lp->getLabel().toUtf8()); if (oneOption == "(I18N_EMPTY_MESSAGE)") oneOption = lp->getLabel().toUtf8(); menuOptions.append(oneOption); elementList.append(lp); } menuC->addItems(menuOptions); menuC->setCurrentIndex(onItem); horSpacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); PHBox->addWidget(menuC.get()); PHBox->addItem(horSpacer); } void INDI_P::setupSetButton(const QString &caption) { setB.reset(new QPushButton(caption, pg->getContainer())); setB->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); setB->setMinimumWidth(MIN_SET_WIDTH * KStars::Instance()->devicePixelRatio()); setB->setMaximumWidth(MAX_SET_WIDTH * KStars::Instance()->devicePixelRatio()); connect(setB.get(), SIGNAL(clicked()), this, SLOT(processSetButton())); PHBox->addWidget(setB.get()); } void INDI_P::addWidget(QWidget *w) { PHBox->addWidget(w); } void INDI_P::addLayout(QHBoxLayout *layout) { PVBox->addLayout(layout); } void INDI_P::updateMenuGUI() { ISwitchVectorProperty *svp = dataProp->getSwitch(); if (svp == nullptr) return; int currentIndex = IUFindOnSwitchIndex(svp); menuC->setCurrentIndex(currentIndex); } void INDI_P::processSetButton() { switch (dataProp->getType()) { case INDI_TEXT: if (!strcmp(dataProp->getName(), "TIME_UTC")) newTime(); else sendText(); break; case INDI_NUMBER: sendText(); break; case INDI_BLOB: sendBlob(); break; default: break; } } void INDI_P::sendBlob() { //int index=0; //bool openingTag=false; IBLOBVectorProperty *bvp = dataProp->getBLOB(); if (bvp == nullptr) return; bvp->s = IPS_BUSY; pg->getDevice()->getClientManager()->startBlob(bvp->device, bvp->name, timestamp()); for (int i = 0; i < elementList.count(); i++) { IBLOB *bp = &(bvp->bp[i]); #if (INDI_VERSION_MINOR >= 4 && INDI_VERSION_RELEASE >= 2) pg->getDevice()->getClientManager()->sendOneBlob(bp); #else pg->getDevice()->getClientManager()->sendOneBlob(bp->name, bp->size, bp->format, bp->blob); #endif } // JM: Why we need dirty here? We should be able to upload multiple time /*foreach(INDI_E *ep, elementList) { if (ep->getBLOBDirty() == true) { if (openingTag == false) { pg->getDevice()->getClientManager()->startBlob(bvp->device, bvp->name, timestamp()); openingTag = true; } IBLOB *bp = &(bvp->bp[index]); ep->setBLOBDirty(false); //qDebug() << "SENDING BLOB " << bp->name << " has size of " << bp->size << " and bloblen of " << bp->bloblen << endl; pg->getDevice()->getClientManager()->sendOneBlob(bp->name, bp->size, bp->format, bp->blob); } index++; }*/ //if (openingTag) pg->getDevice()->getClientManager()->finishBlob(); updateStateLED(); } void INDI_P::newTime() { INDI_E *timeEle; INDI_E *offsetEle; timeEle = getElement("UTC"); offsetEle = getElement("OFFSET"); if (!timeEle || !offsetEle) return; TimeDialog timedialog(KStars::Instance()->data()->ut(), KStars::Instance()->data()->geo(), KStars::Instance(), true); if (timedialog.exec() == QDialog::Accepted) { QTime newTime(timedialog.selectedTime()); QDate newDate(timedialog.selectedDate()); timeEle->setText(QString("%1-%2-%3T%4:%5:%6") .arg(newDate.year()) .arg(newDate.month()) .arg(newDate.day()) .arg(newTime.hour()) .arg(newTime.minute()) .arg(newTime.second())); offsetEle->setText(QString().setNum(KStars::Instance()->data()->geo()->TZ(), 'g', 2)); sendText(); } else return; } -INDI_E *INDI_P::getElement(const QString &elementName) +INDI_E *INDI_P::getElement(const QString &elementName) const { - foreach (INDI_E *ep, elementList) + for (auto *ep : elementList) { if (ep->getName() == elementName) return ep; } return nullptr; } + +bool INDI_P::isRegistered() const +{ + return (dataProp && dataProp->getRegistered()); +} diff --git a/kstars/indi/indiproperty.h b/kstars/indi/indiproperty.h index b98fd6b38..25809f574 100644 --- a/kstars/indi/indiproperty.h +++ b/kstars/indi/indiproperty.h @@ -1,134 +1,153 @@ /* INDI Property Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com) This application is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #pragma once #include "indicommon.h" #include #include namespace INDI { class Property; } class INDI_G; class INDI_E; class QAbstractButton; class QButtonGroup; class QCheckBox; class QComboBox; class QHBoxLayout; class QPushButton; class QSpacerItem; class QVBoxLayout; class KLed; class KSqueezedTextLabel; /** * @class INDI_P * INDI_P represents a single INDI property (Switch, Text, Number, Light, or BLOB). It handles building the GUI and updating the property status and/or value as new data * arrive from INDI Serve. It also sends any changes in the property value back to INDI server via the ClientManager. * * @author Jasem Mutlaq */ class INDI_P : public QObject { - Q_OBJECT - public: - INDI_P(INDI_G *ipg, INDI::Property *prop); - ~INDI_P(); - - /* Draw state LED */ - void updateStateLED(); - - /* Update menu gui */ - void updateMenuGUI(); - - void initGUI(); - - /* First step in adding a new GUI element */ - //void addGUI(XMLEle *root); - - /* Set Property's parent group */ - //void setGroup(INDI_G *parentGroup) { pg = parentGroup; } - - void buildSwitchGUI(); - void buildMenuGUI(); - void buildTextGUI(); - void buildNumberGUI(); - void buildLightGUI(); - void buildBLOBGUI(); - - /** Setup the 'set' button in the property */ - void setupSetButton(const QString &caption); - - void newTime(); - - PGui getGUIType() { return guiType; } - - INDI_G *getGroup() { return pg; } - - QHBoxLayout *getContainer() { return PHBox.get(); } - - const QString &getName() { return name; } - - void addWidget(QWidget *w); - void addLayout(QHBoxLayout *layout); - - INDI_E *getElement(const QString &elementName); - - QList getElements() { return elementList; } - - public slots: - void processSetButton(); - void newSwitch(QAbstractButton *button); - void newSwitch(int index); - void newSwitch(const QString &name); - void resetSwitch(); - - void sendBlob(); - void sendSwitch(); - void sendText(); - - void setBLOBOption(int state); - - private: - INDI::Property *dataProp { nullptr }; - /// Parent group - INDI_G *pg { nullptr }; - QCheckBox *enableBLOBC { nullptr }; - /// Label widget - std::unique_ptr labelW; - /// Set button - std::unique_ptr setB; - /// Status LED - std::unique_ptr ledStatus; - /// GUI type - PGui guiType; - /// Horizontal spacer - QSpacerItem *horSpacer { nullptr }; - /// Horizontal container - std::unique_ptr PHBox; - /// Vertical container - QVBoxLayout *PVBox { nullptr }; - /// Group button for radio and check boxes (Elements) - std::unique_ptr groupB; - /// Combo box for menu - std::unique_ptr menuC; - QString name; - /// List of elements - QList elementList; + Q_OBJECT + public: + INDI_P(INDI_G *ipg, INDI::Property *prop); + ~INDI_P(); + + /* Draw state LED */ + void updateStateLED(); + + /* Update menu gui */ + void updateMenuGUI(); + + void initGUI(); + + /* First step in adding a new GUI element */ + //void addGUI(XMLEle *root); + + /* Set Property's parent group */ + //void setGroup(INDI_G *parentGroup) { pg = parentGroup; } + + void buildSwitchGUI(); + void buildMenuGUI(); + void buildTextGUI(); + void buildNumberGUI(); + void buildLightGUI(); + void buildBLOBGUI(); + + /** Setup the 'set' button in the property */ + void setupSetButton(const QString &caption); + + /** + * @brief newTime Display dialog to set UTC date and time to the driver. + */ + void newTime(); + + PGui getGUIType() const + { + return guiType; + } + + INDI_G *getGroup() const + { + return pg; + } + + QHBoxLayout *getContainer() const + { + return PHBox.get(); + } + + const QString &getName() const + { + return name; + } + + void addWidget(QWidget *w); + void addLayout(QHBoxLayout *layout); + + INDI_E *getElement(const QString &elementName) const; + + QList getElements() const + { + return elementList; + } + bool isRegistered() const; + + public slots: + void processSetButton(); + void newSwitch(QAbstractButton *button); + void newSwitch(int index); + void newSwitch(const QString &name); + void resetSwitch(); + + void sendBlob(); + void sendSwitch(); + void sendText(); + + void setBLOBOption(int state); + + private: + INDI::Property *dataProp { nullptr }; + /// Parent group + INDI_G *pg { nullptr }; + QCheckBox *enableBLOBC { nullptr }; + /// Label widget + std::unique_ptr labelW; + /// Set button + std::unique_ptr setB; + /// Status LED + std::unique_ptr ledStatus; + /// GUI type + PGui guiType; + /// Horizontal spacer + QSpacerItem *horSpacer { nullptr }; + /// Horizontal container + std::unique_ptr PHBox; + /// Vertical container + QVBoxLayout *PVBox { nullptr }; + /// Group button for radio and check boxes (Elements) + std::unique_ptr groupB; + /// Combo box for menu + std::unique_ptr menuC; + QString name; + /// List of elements + QList elementList; };