00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "indiproperty.h"
00025 #include "indigroup.h"
00026 #include "indidevice.h"
00027 #include "devicemanager.h"
00028 #include "indimenu.h"
00029 #include "indidriver.h"
00030 #include "indistd.h"
00031 #include "indi/indicom.h"
00032 #include "kstars.h"
00033 #include "skyobject.h"
00034 #include "timedialog.h"
00035 #include "geolocation.h"
00036 #include "indi/base64.h"
00037
00038 #include <sys/socket.h>
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041 #include <netdb.h>
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044 #include <termios.h>
00045 #include <zlib.h>
00046
00047 #include <qlineedit.h>
00048 #include <qtextedit.h>
00049 #include <qframe.h>
00050 #include <qtabwidget.h>
00051 #include <qcheckbox.h>
00052 #include <qlabel.h>
00053 #include <qpushbutton.h>
00054 #include <qlayout.h>
00055 #include <qtooltip.h>
00056 #include <qwhatsthis.h>
00057 #include <qbuttongroup.h>
00058 #include <qscrollview.h>
00059 #include <qsocketnotifier.h>
00060 #include <qvbox.h>
00061 #include <qdatetime.h>
00062 #include <qtable.h>
00063 #include <qstring.h>
00064 #include <qptrlist.h>
00065
00066 #include <kled.h>
00067 #include <klineedit.h>
00068 #include <kpushbutton.h>
00069 #include <kapplication.h>
00070 #include <klocale.h>
00071 #include <kmessagebox.h>
00072 #include <klistview.h>
00073 #include <kdebug.h>
00074 #include <kcombobox.h>
00075 #include <knuminput.h>
00076 #include <kdialogbase.h>
00077 #include <kstatusbar.h>
00078 #include <kpopupmenu.h>
00079
00080 #define NINDI_STD 26
00081
00082
00083 const char * indi_std[NINDI_STD] =
00084 {"CONNECTION", "DEVICE_PORT", "TIME", "SDTIME", "GEOGRAPHIC_COORD", "EQUATORIAL_COORD", "EQUATORIAL_EOD_COORD", "HORIZONTAL_COORD", "ABORT_MOTION", "ON_COORD_SET", "SOLAR_SYSTEM", "MOVEMENT", "PARK", "CCD_EXPOSE_DURATION", "CCD_TEMPERATURE", "CCD_FRAME", "CCD_FRAME_TYPE", "CCD_BINNING", "CCD_INFO", "CCDPREVIEW_STREAM", "CCDPREVIEW_CTRL", "VIDEO_STREAM", "FOCUS_SPEED", "FOCUS_MOTION", "FOCUS_TIMER", "FILTER_SLOT" };
00085
00086
00087
00088
00089
00090 INDI_D::INDI_D(INDIMenu *menuParent, DeviceManager *parentManager, QString inName, QString inLabel)
00091 {
00092 name = inName;
00093 label = inLabel;
00094 parent = menuParent;
00095 parentMgr = parentManager;
00096
00097 gl.setAutoDelete(true);
00098
00099 deviceVBox = menuParent->addVBoxPage(inLabel);
00100 groupContainer = new QTabWidget(deviceVBox);
00101
00102 msgST_w = new QTextEdit(deviceVBox);
00103 msgST_w->setReadOnly(true);
00104 msgST_w->setMaximumHeight(100);
00105
00106 dataBuffer = (unsigned char *) malloc (1);
00107
00108 stdDev = new INDIStdDevice(this, parent->ksw);
00109
00110 curGroup = NULL;
00111
00112 INDIStdSupport = false;
00113
00114 }
00115
00116 INDI_D::~INDI_D()
00117 {
00118 gl.clear();
00119 delete(deviceVBox);
00120 delete (stdDev);
00121 free (dataBuffer);
00122 dataBuffer = NULL;
00123 deviceVBox = NULL;
00124 stdDev = NULL;
00125 }
00126
00127 void INDI_D::registerProperty(INDI_P *pp)
00128 {
00129
00130 if (isINDIStd(pp))
00131 pp->pg->dp->INDIStdSupport = true;
00132
00133 stdDev->registerProperty(pp);
00134
00135 }
00136
00137 bool INDI_D::isINDIStd(INDI_P *pp)
00138 {
00139 for (uint i=0; i < NINDI_STD; i++)
00140 if (!strcmp(pp->name.ascii(), indi_std[i]))
00141 {
00142 pp->stdID = i;
00143 return true;
00144 }
00145
00146 return false;
00147 }
00148
00149
00150
00151 int INDI_D::removeProperty(INDI_P *pp)
00152 {
00153 for (unsigned int i=0; i < gl.count(); i++)
00154 if (gl.at(i)->removeProperty(pp))
00155 {
00156 if (gl.at(i)->pl.count() == 0)
00157 gl.remove(i);
00158 return 0;
00159 }
00160
00161
00162 kdDebug() << "INDI: Device " << name << " has no property named " << pp->name << endl;
00163 return (-1);
00164 }
00165
00166
00167
00168
00169 int INDI_D::setAnyCmd (XMLEle *root, char errmsg[])
00170 {
00171 XMLAtt *ap;
00172 INDI_P *pp;
00173
00174 ap = findAtt (root, "name", errmsg);
00175 if (!ap)
00176 return (-1);
00177
00178 pp = findProp (valuXMLAtt(ap));
00179 if (!pp)
00180 {
00181 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.32s> device %.32s has no property named %.64s",
00182 tagXMLEle(root), name.ascii(), valuXMLAtt(ap));
00183 return (-1);
00184 }
00185
00186 parentMgr->checkMsg (root, this);
00187
00188 return (setValue (pp, root, errmsg));
00189 }
00190
00191
00192
00193
00194 int INDI_D::setValue (INDI_P *pp, XMLEle *root, char errmsg[])
00195 {
00196 XMLAtt *ap;
00197
00198
00199 ap = findXMLAtt (root, "state");
00200 if (ap)
00201 {
00202 if (crackLightState (valuXMLAtt(ap), &pp->state) == 0)
00203 pp->drawLt (pp->state);
00204 else
00205 {
00206 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> bogus state %.64s for %.64s %.64s",
00207 tagXMLEle(root), valuXMLAtt(ap), name.ascii(), pp->name.ascii());
00208 return (-1);
00209 }
00210 }
00211
00212
00213 ap = findXMLAtt (root, "timeout");
00214 if (ap)
00215 pp->timeout = atof(valuXMLAtt(ap));
00216
00217
00218 switch (pp->guitype)
00219 {
00220 case PG_NONE:
00221 break;
00222
00223 case PG_NUMERIC:
00224 case PG_TEXT:
00225 return (setTextValue (pp, root, errmsg));
00226 break;
00227
00228 case PG_BUTTONS:
00229 case PG_LIGHTS:
00230 case PG_RADIO:
00231 case PG_MENU:
00232 return (setLabelState (pp, root, errmsg));
00233 break;
00234
00235 case PG_BLOB:
00236 return (setBLOB(pp, root, errmsg));
00237 break;
00238
00239 default:
00240 break;
00241 }
00242
00243 return (0);
00244 }
00245
00246
00247
00248
00249
00250
00251 int INDI_D::setTextValue (INDI_P *pp, XMLEle *root, char errmsg[])
00252 {
00253 XMLEle *ep;
00254 XMLAtt *ap;
00255 INDI_E *lp;
00256 QString elementName;
00257 char iNumber[32];
00258 double min, max;
00259
00260 for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
00261 {
00262 if (strcmp (tagXMLEle(ep), "oneText") && strcmp(tagXMLEle(ep), "oneNumber"))
00263 continue;
00264
00265 ap = findXMLAtt(ep, "name");
00266 if (!ap)
00267 {
00268 kdDebug() << "Error: unable to find attribute 'name' for property " << pp->name << endl;
00269 return (-1);
00270 }
00271
00272 elementName = valuXMLAtt(ap);
00273
00274 lp = pp->findElement(elementName);
00275
00276 if (!lp)
00277 {
00278 snprintf(errmsg, ERRMSG_SIZE, "Error: unable to find element '%.64s' in property '%.64s'", elementName.ascii(), pp->name.ascii());
00279 return (-1);
00280 }
00281
00282
00283 switch (pp->perm)
00284 {
00285 case PP_RW:
00286 case PP_RO:
00287 if (pp->guitype == PG_TEXT)
00288 {
00289 lp->text = QString(pcdataXMLEle(ep));
00290 lp->read_w->setText(lp->text);
00291 }
00292 else if (pp->guitype == PG_NUMERIC)
00293 {
00294 lp->value = atof(pcdataXMLEle(ep));
00295 numberFormat(iNumber, lp->format.ascii(), lp->value);
00296 lp->text = iNumber;
00297 lp->read_w->setText(lp->text);
00298
00299 ap = findXMLAtt (ep, "min");
00300 if (ap) { min = atof(valuXMLAtt(ap)); lp->setMin(min); }
00301 ap = findXMLAtt (ep, "max");
00302 if (ap) { max = atof(valuXMLAtt(ap)); lp->setMax(max); }
00303
00304
00305
00306
00307
00308
00309
00310 }
00311 break;
00312
00313 case PP_WO:
00314 if (pp->guitype == PG_TEXT)
00315 lp->write_w->setText(QString(pcdataXMLEle(ep)));
00316 else if (pp->guitype == PG_NUMERIC)
00317 {
00318 lp->value = atof(pcdataXMLEle(ep));
00319 numberFormat(iNumber, lp->format.ascii(), lp->value);
00320 lp->text = iNumber;
00321
00322 if (lp->spin_w)
00323 lp->spin_w->setValue(lp->value);
00324 else
00325 lp->write_w->setText(lp->text);
00326
00327 ap = findXMLAtt (ep, "min");
00328 if (ap) { min = (int) atof(valuXMLAtt(ap)); lp->setMin(min); }
00329 ap = findXMLAtt (ep, "max");
00330 if (ap) { max = (int) atof(valuXMLAtt(ap)); lp->setMax(max); }
00331 }
00332 break;
00333
00334 }
00335 }
00336
00337
00338 stdDev->setTextValue(pp);
00339
00340
00341 errmsg = errmsg;
00342
00343 return (0);
00344 }
00345
00346
00347
00348
00349
00350 int INDI_D::setLabelState (INDI_P *pp, XMLEle *root, char errmsg[])
00351 {
00352 int menuChoice=0;
00353 unsigned i=0;
00354 XMLEle *ep;
00355 XMLAtt *ap;
00356 INDI_E *lp = NULL;
00357 int islight;
00358 PState state;
00359
00360
00361 for (ep = nextXMLEle (root, 1), i=0; ep != NULL; ep = nextXMLEle (root, 0), i++)
00362 {
00363
00364
00365 islight = !strcmp (tagXMLEle(ep), "oneLight");
00366 if (!islight && strcmp (tagXMLEle(ep), "oneSwitch"))
00367 continue;
00368
00369 ap = findXMLAtt (ep, "name");
00370
00371 if (!ap)
00372 {
00373 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> %.64s %.64s %.64s requires name",
00374 tagXMLEle(root), name.ascii(), pp->name.ascii(), tagXMLEle(ep));
00375 return (-1);
00376 }
00377
00378 if ((islight && crackLightState (pcdataXMLEle(ep), &state) < 0)
00379 || (!islight && crackSwitchState (pcdataXMLEle(ep), &state) < 0))
00380 {
00381 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> unknown state %.64s for %.64s %.64s %.64s",
00382 tagXMLEle(root), pcdataXMLEle(ep), name.ascii(), pp->name.ascii(), tagXMLEle(ep));
00383 return (-1);
00384 }
00385
00386
00387
00388 lp = pp->findElement(QString(valuXMLAtt(ap)));
00389
00390 if (!lp)
00391 {
00392 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> %.64s %.64s has no choice named %.64s",
00393 tagXMLEle(root), name.ascii(), pp->name.ascii(), valuXMLAtt(ap));
00394 return (-1);
00395 }
00396
00397 QFont buttonFont;
00398
00399 lp->state = state;
00400
00401 switch (pp->guitype)
00402 {
00403 case PG_BUTTONS:
00404 if (islight)
00405 break;
00406
00407 lp->push_w->setDown(state == PS_ON ? true : false);
00408 buttonFont = lp->push_w->font();
00409 buttonFont.setBold(state == PS_ON ? TRUE : FALSE);
00410 lp->push_w->setFont(buttonFont);
00411
00412 break;
00413
00414 case PG_RADIO:
00415 lp->check_w->setChecked(state == PS_ON ? true : false);
00416 break;
00417 case PG_MENU:
00418 if (state == PS_ON)
00419 {
00420 if (menuChoice)
00421 {
00422 snprintf(errmsg, ERRMSG_SIZE, "INDI: <%.64s> %.64s %.64s has multiple ON states", tagXMLEle(root), name.ascii(), pp->name.ascii());
00423 return (-1);
00424 }
00425 menuChoice = 1;
00426 pp->om_w->setCurrentItem(i);
00427 }
00428 break;
00429
00430 case PG_LIGHTS:
00431 lp->drawLt();
00432 break;
00433
00434 default:
00435 break;
00436 }
00437
00438 }
00439
00440 stdDev->setLabelState(pp);
00441
00442 return (0);
00443 }
00444
00445
00446
00447
00448 int INDI_D::setBLOB(INDI_P *pp, XMLEle * root, char errmsg[])
00449 {
00450
00451 XMLEle *ep;
00452 INDI_E *blobEL;
00453
00454 for (ep = nextXMLEle(root,1); ep; ep = nextXMLEle(root,0))
00455 {
00456
00457 if (strcmp(tagXMLEle(ep), "oneBLOB") == 0)
00458 {
00459
00460 blobEL = pp->findElement(QString(findXMLAttValu (ep, "name")));
00461
00462 if (blobEL)
00463 return processBlob(blobEL, ep, errmsg);
00464 else
00465 {
00466 sprintf (errmsg, "INDI: set %64s.%64s.%64s not found", name.ascii(), pp->name.ascii(), findXMLAttValu(ep, "name"));
00467 return (-1);
00468 }
00469 }
00470 }
00471
00472 return (0);
00473
00474 }
00475
00476
00477
00478
00479 int INDI_D::processBlob(INDI_E *blobEL, XMLEle *ep, char errmsg[])
00480 {
00481 XMLAtt *ap;
00482 int blobSize=0, r=0, dataType=0;
00483 uLongf dataSize=0;
00484 QString dataFormat;
00485 char *baseBuffer;
00486 unsigned char *blobBuffer(NULL);
00487 bool iscomp(false);
00488
00489 ap = findXMLAtt(ep, "size");
00490 if (!ap)
00491 {
00492 sprintf (errmsg, "INDI: set %64s size not found", blobEL->name.ascii());
00493 return (-1);
00494 }
00495
00496 dataSize = atoi(valuXMLAtt(ap));
00497
00498 ap = findXMLAtt(ep, "format");
00499 if (!ap)
00500 {
00501 sprintf (errmsg, "INDI: set %64s format not found", blobEL->name.ascii());
00502 return (-1);
00503 }
00504
00505 dataFormat = QString(valuXMLAtt(ap));
00506
00507 baseBuffer = (char *) malloc ( (3*pcdatalenXMLEle(ep)/4) * sizeof (char));
00508 blobSize = from64tobits (baseBuffer, pcdataXMLEle(ep));
00509 blobBuffer = (unsigned char *) baseBuffer;
00510
00511
00512 if (dataSize == 0)
00513 {
00514 free (blobBuffer);
00515 return (0);
00516 }
00517 else if (blobSize < 0)
00518 {
00519 free (blobBuffer);
00520 sprintf (errmsg, "INDI: %64s.%64s.%64s bad base64", name.ascii(), blobEL->pp->name.ascii(), blobEL->name.ascii());
00521 return (-1);
00522 }
00523
00524 iscomp = (dataFormat.find(".z") != -1);
00525
00526 dataFormat.remove(".z");
00527
00528 if (dataFormat == ".fits") dataType = DATA_FITS;
00529 else if (dataFormat == ".stream") dataType = DATA_STREAM;
00530 else if (dataFormat == ".ccdpreview") dataType = DATA_CCDPREVIEW;
00531 else dataType = DATA_OTHER;
00532
00533
00534
00535
00536 if (iscomp)
00537 {
00538
00539 dataBuffer = (unsigned char *) realloc (dataBuffer, (dataSize * sizeof(unsigned char)));
00540 r = uncompress(dataBuffer, &dataSize, blobBuffer, (uLong) blobSize);
00541 if (r != Z_OK)
00542 {
00543 sprintf(errmsg, "INDI: %64s.%64s.%64s compression error: %d", name.ascii(), blobEL->pp->name.ascii(), blobEL->name.ascii(), r);
00544 free (blobBuffer);
00545 return -1;
00546 }
00547
00548
00549 }
00550 else
00551 {
00552
00553 dataBuffer = (unsigned char *) realloc (dataBuffer, (dataSize * sizeof(unsigned char)));
00554 memcpy(dataBuffer, blobBuffer, dataSize);
00555 }
00556
00557 stdDev->handleBLOB(dataBuffer, dataSize, dataFormat);
00558
00559 free (blobBuffer);
00560
00561 return (0);
00562
00563 }
00564
00565 bool INDI_D::isOn()
00566 {
00567
00568 INDI_P *prop;
00569
00570 prop = findProp(QString("CONNECTION"));
00571 if (!prop)
00572 return false;
00573
00574 return (prop->isOn(QString("CONNECT")));
00575 }
00576
00577 INDI_P * INDI_D::addProperty (XMLEle *root, char errmsg[])
00578 {
00579 INDI_P *pp = NULL;
00580 INDI_G *pg = NULL;
00581 XMLAtt *ap = NULL;
00582
00583
00584 ap = findAtt (root, "group", errmsg);
00585 if (!ap)
00586 {
00587 kdDebug() << QString(errmsg) << endl;
00588 return NULL;
00589 }
00590
00591 pg = findGroup(QString(valuXMLAtt(ap)), 1, errmsg);
00592
00593 if (!pg)
00594 return NULL;
00595
00596
00597 ap = findAtt (root, "name", errmsg);
00598 if (ap == NULL)
00599 return NULL;
00600
00601 if (findProp (valuXMLAtt(ap)))
00602 {
00603 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s %.64s %.64s> already exists.\n", tagXMLEle(root),
00604 name.ascii(), valuXMLAtt(ap));
00605 return NULL;
00606 }
00607
00608
00609
00610
00611 pg->propertyLayout->removeItem(pg->VerticalSpacer);
00612
00613 pp = new INDI_P(pg, QString(valuXMLAtt(ap)));
00614
00615
00616 ap = findAtt (root, "state", errmsg);
00617 if (!ap)
00618 {
00619 delete(pp);
00620 return (NULL);
00621 }
00622
00623 if (crackLightState (valuXMLAtt(ap), &pp->state) < 0)
00624 {
00625 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> bogus state %.64s for %.64s %.64s",
00626 tagXMLEle(root), valuXMLAtt(ap), pp->pg->dp->name.ascii(), pp->name.ascii());
00627 delete(pp);
00628 return (NULL);
00629 }
00630
00631
00632 ap = findAtt (root, "timeout", NULL);
00633
00634 pp->timeout = ap ? atof(valuXMLAtt(ap)) : 0;
00635
00636
00637 parentMgr->checkMsg (root, this);
00638
00639 pp->addGUI(root);
00640
00641
00642 return (pp);
00643 }
00644
00645 INDI_P * INDI_D::findProp (QString name)
00646 {
00647 for (unsigned int i = 0; i < gl.count(); i++)
00648 for (unsigned int j = 0; j < gl.at(i)->pl.count(); j++)
00649 if (name == gl.at(i)->pl.at(j)->name)
00650 return (gl.at(i)->pl.at(j));
00651
00652 return NULL;
00653 }
00654
00655 INDI_G * INDI_D::findGroup (QString grouptag, int create, char errmsg[])
00656 {
00657 INDI_G *ig;
00658
00659 for (ig = gl.first(); ig != NULL; ig = gl.next() )
00660 if (ig->name == grouptag)
00661 {
00662 curGroup = ig;
00663 return ig;
00664 }
00665
00666
00667 if (create)
00668 {
00669 if (grouptag.isEmpty())
00670 grouptag = "Group_1";
00671
00672 curGroup = new INDI_G(this, grouptag);
00673 gl.append(curGroup);
00674 return curGroup;
00675 }
00676
00677 snprintf (errmsg, ERRMSG_SIZE, "INDI: group %.64s not found in %.64s", grouptag.ascii(), name.ascii());
00678 return NULL;
00679 }
00680
00681
00682
00683
00684
00685
00686 int INDI_D::findPerm (INDI_P *pp, XMLEle *root, PPerm *permp, char errmsg[])
00687 {
00688 XMLAtt *ap;
00689
00690 ap = findXMLAtt(root, "perm");
00691 if (!ap) {
00692 snprintf (errmsg, ERRMSG_SIZE,"INDI: <%.64s %.64s %.64s> missing attribute 'perm'",
00693 tagXMLEle(root), pp->pg->dp->name.ascii(), pp->name.ascii());
00694 return (-1);
00695 }
00696 if (!strcmp(valuXMLAtt(ap), "ro") || !strcmp(valuXMLAtt(ap), "r"))
00697 *permp = PP_RO;
00698 else if (!strcmp(valuXMLAtt(ap), "wo"))
00699 *permp = PP_WO;
00700 else if (!strcmp(valuXMLAtt(ap), "rw") || !strcmp(valuXMLAtt(ap), "w"))
00701 *permp = PP_RW;
00702 else {
00703 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> unknown perm %.64s for %.64s %.64s",
00704 tagXMLEle(root), valuXMLAtt(ap), pp->pg->dp->name.ascii(), pp->name.ascii());
00705 return (-1);
00706 }
00707
00708 return (0);
00709 }
00710
00711
00712
00713
00714 int INDI_D::crackLightState (char *name, PState *psp)
00715 {
00716 typedef struct
00717 {
00718 PState s;
00719 const char *name;
00720 } PSMap;
00721
00722 PSMap psmap[] =
00723 {
00724 {PS_IDLE, "Idle"},
00725 {PS_OK, "Ok"},
00726 {PS_BUSY, "Busy"},
00727 {PS_ALERT, "Alert"},
00728 };
00729
00730 for (int i = 0; i < 4; i++)
00731 if (!strcmp (psmap[i].name, name)) {
00732 *psp = psmap[i].s;
00733 return (0);
00734 }
00735
00736 return (-1);
00737 }
00738
00739
00740
00741
00742 int INDI_D::crackSwitchState (char *name, PState *psp)
00743 {
00744 typedef struct
00745 {
00746 PState s;
00747 const char *name;
00748 } PSMap;
00749
00750 PSMap psmap[] =
00751 {
00752 {PS_ON, "On"},
00753 {PS_OFF, "Off"},
00754 };
00755
00756
00757 for (int i = 0; i < 2; i++)
00758 if (!strcmp (psmap[i].name, name))
00759 {
00760 *psp = psmap[i].s;
00761 return (0);
00762 }
00763
00764 return (-1);
00765 }
00766
00767 int INDI_D::buildTextGUI(XMLEle *root, char errmsg[])
00768 {
00769 INDI_P *pp = NULL;
00770 PPerm p;
00771
00772
00773 pp = addProperty (root, errmsg);
00774
00775 if (pp == NULL)
00776 return (-1);
00777
00778
00779 if (findPerm (pp, root, &p, errmsg))
00780 {
00781 delete(pp);
00782 return (-1);
00783 }
00784
00785
00786 pp->guitype = PG_TEXT;
00787 pp->perm = p;
00788
00789 if (pp->buildTextGUI(root, errmsg) < 0)
00790 {
00791 delete (pp);
00792 return (-1);
00793 }
00794
00795 pp->pg->addProperty(pp);
00796
00797 return (0);
00798 }
00799
00800
00801
00802
00803 int INDI_D::buildNumberGUI (XMLEle *root, char *errmsg)
00804 {
00805 INDI_P *pp = NULL;
00806 PPerm p;
00807
00808
00809 pp = addProperty (root, errmsg);
00810
00811 if (pp == NULL)
00812 return (-1);
00813
00814
00815 if (findPerm (pp, root, &p, errmsg))
00816 {
00817 delete(pp);
00818 return (-1);
00819 }
00820
00821
00822 pp->guitype = PG_NUMERIC;
00823 pp->perm = p;
00824
00825 if (pp->buildNumberGUI(root, errmsg) < 0)
00826 {
00827 delete (pp);
00828 return (-1);
00829 }
00830
00831 pp->pg->addProperty(pp);
00832
00833 return (0);
00834 }
00835
00836
00837
00838
00839
00840 int INDI_D::buildSwitchesGUI (XMLEle *root, char errmsg[])
00841 {
00842 INDI_P *pp;
00843 XMLAtt *ap;
00844 XMLEle *ep;
00845 int n, err;
00846
00847
00848 pp = addProperty (root, errmsg);
00849 if (!pp)
00850 return (-1);
00851
00852 ap = findAtt (root, "rule", errmsg);
00853 if (!ap)
00854 {
00855 delete(pp);
00856 return (-1);
00857 }
00858
00859
00860 if (!strcmp (valuXMLAtt(ap), "OneOfMany") || !strcmp (valuXMLAtt(ap), "AtMostOne"))
00861 {
00862
00863 for ( ep = nextXMLEle(root, 1) , n = 0 ; ep != NULL; ep = nextXMLEle(root, 0))
00864 if (!strcmp (tagXMLEle(ep), "defSwitch"))
00865 n++;
00866
00867 if (n > MAXRADIO)
00868 {
00869 pp->guitype = PG_MENU;
00870 err = pp->buildMenuGUI (root, errmsg);
00871 if (err < 0)
00872 {
00873 delete(pp);
00874 pp=0;
00875 return err;
00876 }
00877
00878 pp->pg->addProperty(pp);
00879 return (err);
00880 }
00881
00882
00883 pp->guitype = PG_BUTTONS;
00884
00885 err = pp->buildSwitchesGUI(root, errmsg);
00886 if (err < 0)
00887 {
00888 delete (pp);
00889 pp=0;
00890 return err;
00891 }
00892
00893 pp->pg->addProperty(pp);
00894 return (err);
00895
00896 }
00897 else if (!strcmp (valuXMLAtt(ap), "AnyOfMany"))
00898 {
00899
00900 pp->guitype = PG_RADIO;
00901
00902 err = pp->buildSwitchesGUI(root, errmsg);
00903 if (err < 0)
00904 {
00905 delete (pp);
00906 pp=0;
00907 return err;
00908 }
00909
00910 pp->pg->addProperty(pp);
00911 return (err);
00912 }
00913
00914 snprintf (errmsg, ERRMSG_SIZE, "INDI: <%.64s> unknown rule %.64s for %.64s %.64s",
00915 tagXMLEle(root), valuXMLAtt(ap), name.ascii(), pp->name.ascii());
00916
00917 delete(pp);
00918 return (-1);
00919 }
00920
00921
00922
00923
00924
00925 int INDI_D::buildLightsGUI (XMLEle *root, char errmsg[])
00926 {
00927 INDI_P *pp;
00928
00929
00930 pp = addProperty (root, errmsg);
00931 if (!pp)
00932 return (-1);
00933
00934 pp->guitype = PG_LIGHTS;
00935
00936 if (pp->buildLightsGUI(root, errmsg) < 0)
00937 {
00938 delete (pp);
00939 return (-1);
00940 }
00941
00942 pp->pg->addProperty(pp);
00943 return (0);
00944 }
00945
00946
00947
00948 int INDI_D::buildBLOBGUI (XMLEle *root, char errmsg[])
00949 {
00950 INDI_P *pp;
00951 PPerm p;
00952
00953
00954 pp = addProperty (root, errmsg);
00955 if (!pp)
00956 return (-1);
00957
00958
00959 if (findPerm (pp, root, &p, errmsg))
00960 {
00961 delete(pp);
00962 return (-1);
00963 }
00964
00965
00966 pp->perm = p;
00967 pp->guitype = PG_BLOB;
00968
00969 if (pp->buildBLOBGUI(root, errmsg) < 0)
00970 {
00971 delete (pp);
00972 return (-1);
00973 }
00974
00975 pp->pg->addProperty(pp);
00976 return (0);
00977 }
00978
00979 INDI_E * INDI_D::findElem(QString name)
00980 {
00981 INDI_G *grp;
00982 INDI_P *prop;
00983 INDI_E *el;
00984
00985 for (grp = gl.first(); grp != NULL; grp = gl.next())
00986 {
00987 for (prop = grp->pl.first(); prop != NULL; prop = grp->pl.next())
00988 {
00989 el = prop->findElement(name);
00990 if (el != NULL) return el;
00991 }
00992 }
00993
00994 return NULL;
00995
00996 }
00997
00998
00999 #include "indidevice.moc"