11 #include <basedevice.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
19 #include <QRadioButton>
22 #include <QTextStream>
23 #include <QTreeWidget>
29 #include <KMessageBox>
30 #include <KPushButton>
34 #include <KActionCollection>
35 #include <KIconLoader>
37 #include <kstandarddirs.h>
42 #include "ui_indihostconf.h"
55 #include <config-kstars.h>
57 #define INDI_MAX_TRIES 3
58 #define ERRMSG_SIZE 1024
64 localTreeWidget->setSortingEnabled(
false);
65 localTreeWidget->setRootIsDecorated(
true);
67 clientTreeWidget->setSortingEnabled(
false);
70 stopPix = KIcon(
"dialog-cancel" );
77 connect(localTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,
int)),
this, SLOT(
makePortEditable(QTreeWidgetItem*,
int)));
84 selectedItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled);
89 DriverManager * DriverManager::_DriverManager = NULL;
93 if (_DriverManager == NULL)
94 _DriverManager =
new DriverManager();
96 return _DriverManager;
99 DriverManager::DriverManager()
111 setCaption( i18n(
"Device Manager" ) );
112 setButtons( KDialog::Close );
116 QObject::connect(ui->addB, SIGNAL(clicked()),
this, SLOT(
addINDIHost()));
117 QObject::connect(ui->modifyB, SIGNAL(clicked()),
this, SLOT(
modifyINDIHost()));
118 QObject::connect(ui->removeB, SIGNAL(clicked()),
this, SLOT(
removeINDIHost()));
122 QObject::connect(ui->runServiceB, SIGNAL(clicked()),
this, SLOT(
activateRunService()));
124 QObject::connect(ui->localTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *,
int)),
this, SLOT(
updateLocalTab()));
125 QObject::connect(ui->clientTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *,
int)),
this, SLOT(
updateClientTab()));
126 QObject::connect(ui->localTreeWidget, SIGNAL(expanded(
const QModelIndex &)),
this, SLOT(
resizeDeviceColumn()));
143 QString currentDriver;
151 if (ui->localTreeWidget->currentItem())
152 currentDriver = ui->localTreeWidget->currentItem()->text(LOCAL_NAME_COLUMN);
154 foreach (QTreeWidgetItem *item, ui->localTreeWidget->findItems(dv->
getTreeLabel(), Qt::MatchExactly | Qt::MatchRecursive))
157 item->setText(LOCAL_VERSION_COLUMN, dv->
getVersion());
170 ui->runServiceB->setEnabled(!dState);
171 ui->stopServiceB->setEnabled(dState);
172 item->setIcon(LOCAL_STATUS_COLUMN, dState ? ui->runningPix : ui->stopPix);
175 item->setIcon(LOCAL_MODE_COLUMN, ui->serverMode);
177 item->setText(LOCAL_PORT_COLUMN, QString(manager->
getPort()));
181 item->setIcon(LOCAL_MODE_COLUMN, QIcon());
182 item->setText(LOCAL_PORT_COLUMN, dv->
getUserPort());
188 ui->runServiceB->setEnabled(!cState);
189 ui->stopServiceB->setEnabled(cState);
190 item->setIcon(LOCAL_STATUS_COLUMN, cState ? ui->runningPix : ui->stopPix);
193 item->setIcon(LOCAL_MODE_COLUMN, ui->localMode);
196 item->setText(LOCAL_PORT_COLUMN, QString(manager->
getPort()));
200 item->setIcon(LOCAL_MODE_COLUMN, QIcon());
201 item->setText(LOCAL_PORT_COLUMN, dv->
getUserPort());
210 ui->serverLogText->clear();
218 foreach (QTreeWidgetItem *item, ui->clientTreeWidget->findItems(dv->
getName(), Qt::MatchExactly, HOST_NAME_COLUMN))
222 item->setIcon(HOST_STATUS_COLUMN, ui->connected);
223 ui->connectHostB->setEnabled(
false);
224 ui->disconnectHostB->setEnabled(
true);
228 item->setIcon(HOST_STATUS_COLUMN, ui->disconnected);
229 ui->connectHostB->setEnabled(
true);
230 ui->disconnectHostB->setEnabled(
false);
254 int ans = KMessageBox::warningContinueCancel(0, i18n(
"Driver %1 is already running, do you want to restart it?", dv->
getTreeLabel()));
255 if (ans == KMessageBox::Cancel)
261 stopDevices(stopList);
285 if (uList.empty() ==
false)
286 uHosts.append(uList);
299 bool connectionToServer=
false;
301 getUniqueHosts(dList, uHosts);
309 port = qdv.at(0)->getPort().toInt();
313 port = getINDIPort(port);
317 KMessageBox::error(0, i18n(
"Cannot start INDI server: port error."));
321 serverManager =
new ServerManager(qdv.at(0)->getHost(), ((uint) port));
323 if (serverManager == NULL)
325 kWarning() <<
"Warning: device manager has not been established properly";
329 serverManager->
setMode(connectionMode);
331 connect(serverManager, SIGNAL(newServerLog()),
this, SLOT(updateLocalTab()));
336 if (serverManager->
start())
337 servers.append(serverManager);
340 delete serverManager;
349 servers.removeOne(serverManager);
350 serverManager->
stop();
351 delete serverManager;
369 clientManager->setServer(qdv.at(0)->getHost().toLatin1().constData(), ((uint) port));
376 connectionToServer= clientManager->connectServer();
378 if (connectionToServer)
384 if (connectionToServer)
386 clients.append(clientManager);
391 QString errMsg = i18n(
"Connection to INDI server locally on port %1 failed.", port);
392 KMessageBox::error(NULL, errMsg);
394 processDeviceStatus(dv);
423 if (cm->
count() == 0)
427 cm->disconnectServer();
428 clients.removeOne(cm);
445 servers.removeOne(sm);
460 serverManager->
stop();
467 processLocalTree(
true);
472 processLocalTree(
false);
477 processRemoteTree(
true);
482 processRemoteTree(
false);
492 if (ui->localTreeWidget->currentItem() == NULL)
495 QString currentDriver = ui->localTreeWidget->currentItem()->text(LOCAL_NAME_COLUMN);
501 processDeviceStatus(device);
510 if (ui->clientTreeWidget->currentItem() == NULL)
515 if (ui->clientTreeWidget->currentItem()->text(HOST_NAME_COLUMN) == dv->
getName() &&
516 ui->clientTreeWidget->currentItem()->text(HOST_PORT_COLUMN) == dv->
getPort())
518 processDeviceStatus(dv);
534 foreach(QTreeWidgetItem *item, ui->localTreeWidget->selectedItems())
543 processed_devices.append(device);
548 if (port == -1 && item->text(LOCAL_PORT_COLUMN).isEmpty() ==
false)
550 port = item->text(LOCAL_PORT_COLUMN).toInt(&portOK);
554 KMessageBox::error(0, i18n(
"Invalid port entry: %1", item->text(LOCAL_PORT_COLUMN)));
564 if (processed_devices.empty())
return;
567 startDevices(processed_devices);
569 stopDevices(processed_devices);
580 QString errMsg = i18n(
"Connection to INDI host at %1 on port %2 lost. Server disconnected.", client->getHost(), client->getPort());
581 KMessageBox::error(NULL, errMsg);
585 servers.removeOne(manager);
592 clients.removeOne(client);
615 QString errMsg = i18n(
"Connection to INDI host at %1 on port %2 encountered an error: %3.", server->
getHost(), server->
getPort(), server->
errorString());
616 KMessageBox::error(NULL, errMsg);
619 servers.removeOne(server);
629 QTreeWidgetItem *currentItem = ui->clientTreeWidget->currentItem();
630 if (!currentItem)
return;
640 if (currentItem->text(HOST_NAME_COLUMN) == dv->
getName() && currentItem->text(HOST_PORT_COLUMN) == dv->
getPort())
648 connectRemoteHost(dv);
651 disconnectRemoteHost(dv);
659 bool hostPortOk =
false;
660 bool connectionToServer=
false;
663 dv->
getPort().toInt(&hostPortOk);
665 if (hostPortOk ==
false)
667 QString errMsg = QString(
"Invalid host port %1").arg(dv->
getPort());
668 KMessageBox::error(NULL, errMsg);
678 clientManager->setServer(dv->
getHost().toLatin1().constData(), (uint) (dv->
getPort().toInt()));
685 connectionToServer= clientManager->connectServer();
687 if (connectionToServer)
693 if (connectionToServer)
695 clients.append(clientManager);
702 QString errMsg = i18n(
"Connection to INDI server at host %1 with port %2 failed.", dv->
getHost(), dv->
getPort());
703 KMessageBox::error(NULL, errMsg);
704 processDeviceStatus(dv);
719 clientManager->disconnectServer();
722 clients.removeOne(clientManager);
723 delete clientManager;
735 ui->localTreeWidget->resizeColumnToContents(0);
743 QAction *tmpAction = NULL;
744 bool activeDevice =
false;
746 if (clients.size() > 0)
750 if (tmpAction != NULL)
753 tmpAction->setEnabled(activeDevice);
761 bool success =
false;
767 QTcpServer temp_server;
769 if (customPort != -1)
771 success = temp_server.listen(QHostAddress::LocalHost, customPort);
781 for(; currentPort <= lastPort; currentPort++)
783 success = temp_server.listen(QHostAddress::LocalHost, currentPort);
796 QString indiFile(
"indihosts.xml");
801 LilXML *xmlParser = newLilXML();
804 QString hName, hHost, hPort;
808 file.setFileName( KStandardDirs::locate(
"appdata", indiFile ) );
809 if ( file.fileName().isEmpty() || !file.open( QIODevice::ReadOnly ) )
812 while ( file.getChar( &c ) )
814 root = readXMLEle(xmlParser, c, errmsg);
819 ap = findXMLAtt(root,
"name");
822 delLilXML(xmlParser);
826 hName = QString(valuXMLAtt(ap));
829 ap = findXMLAtt(root,
"hostname");
833 delLilXML(xmlParser);
837 hHost = QString(valuXMLAtt(ap));
839 ap = findXMLAtt(root,
"port");
843 delLilXML(xmlParser);
847 hPort = QString(valuXMLAtt(ap));
853 connect(dv, SIGNAL(deviceStateChanged(
DriverInfo*)),
this, SLOT(processDeviceStatus(
DriverInfo*)));
855 driversList.append(dv);
857 QTreeWidgetItem *item =
new QTreeWidgetItem(ui->clientTreeWidget, lastGroup);
859 item->setIcon(HOST_STATUS_COLUMN, ui->disconnected);
860 item->setText(HOST_NAME_COLUMN, hName);
861 item->setText(HOST_PORT_COLUMN, hPort);
869 delLilXML(xmlParser);
874 delLilXML(xmlParser);
891 KMessageBox::error(0, i18n(
"Unable to find INDI Drivers directory: %1\nPlease make sure to set the correct path in KStars configuration",
Options::indiDriversDir()));
895 indiDir.setNameFilters(QStringList(
"*.xml"));
896 indiDir.setFilter(QDir::Files | QDir::NoSymLinks);
897 QFileInfoList list = indiDir.entryInfoList();
899 foreach (QFileInfo fileInfo, list)
902 if (fileInfo.fileName().endsWith(
"_sk.xml"))
905 if (fileInfo.fileName() ==
"drivers.xml")
908 driverName = KStandardDirs::locateLocal(
"appdata",
"drivers.xml");
911 if (driverName.isEmpty() ==
false && QFile(driverName).exists())
913 processXMLDriver(driverName);
919 processXMLDriver(driverName);
929 QFile file(driverName);
930 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
932 KMessageBox::error(0, i18n(
"Failed to open INDI Driver file: %1", driverName));
938 LilXML *xmlParser = newLilXML();
941 if (driverName.endsWith(
"drivers.xml"))
946 while ( file.getChar(&c))
948 root = readXMLEle(xmlParser, c, errmsg);
952 if (!buildDeviceGroup(root, errmsg))
953 prXMLEle(stderr, root, 0);
959 kDebug() << QString(errmsg) << endl;
960 delLilXML(xmlParser);
965 delLilXML(xmlParser);
975 QTreeWidgetItem *group;
979 if (strlen(tagXMLEle(root)) > 1024)
983 ap = findXMLAtt(root,
"group");
987 snprintf(errmsg,
ERRMSG_SIZE,
"Tag %.64s does not have a group attribute", tagXMLEle(root));
991 groupName = valuXMLAtt(ap);
993 if (groupName.indexOf(
"Telescopes") != -1)
995 else if (groupName.indexOf(
"CCDs") != -1)
997 else if (groupName.indexOf(
"Filter") != -1)
999 else if (groupName.indexOf(
"Video") != -1)
1001 else if (groupName.indexOf(
"Focusers") != -1)
1003 else if (groupName.indexOf(
"Domes") != -1)
1005 else if (groupName.indexOf(
"Receivers") != -1)
1007 else if (groupName.indexOf(
"GPS") != -1)
1009 else if (groupName.indexOf(
"Auxiliary") != -1)
1014 #ifndef HAVE_CFITSIO_H
1022 if (!treeList.isEmpty())
1023 group = treeList[0];
1025 group =
new QTreeWidgetItem(ui->localTreeWidget, lastGroup);
1027 group->setText(0, groupName);
1030 for (ep = nextXMLEle(root, 1) ; ep != NULL ; ep = nextXMLEle(root, 0))
1031 if (!buildDriverElement(ep, group, groupType, errmsg))
1052 ap = findXMLAtt(root,
"label");
1055 snprintf(errmsg,
ERRMSG_SIZE,
"Tag %.64s does not have a label attribute", tagXMLEle(root));
1059 label = valuXMLAtt(ap);
1062 ap = findXMLAtt(root,
"port");
1064 port = valuXMLAtt(ap);
1068 ap = findXMLAtt(root,
"skel");
1070 skel = valuXMLAtt(ap);
1081 el = findXMLEle(root,
"driver");
1086 driver = pcdataXMLEle(el);
1088 ap = findXMLAtt(el,
"name");
1091 snprintf(errmsg,
ERRMSG_SIZE,
"Tag %.64s does not have a name attribute", tagXMLEle(el));
1095 name = valuXMLAtt(ap);
1097 el = findXMLEle(root,
"version");
1102 version = pcdataXMLEle(el);
1104 QTreeWidgetItem *device =
new QTreeWidgetItem(DGroup);
1107 device->setText(LOCAL_NAME_COLUMN, label);
1108 device->setIcon(LOCAL_STATUS_COLUMN, ui->stopPix);
1109 device->setText(LOCAL_VERSION_COLUMN, version);
1110 device->setText(LOCAL_PORT_COLUMN, port);
1112 lastDevice = device;
1114 if ((driverSource ==
PRIMARY_XML) && driversStringList.contains(driver) ==
false)
1115 driversStringList.append(driver);
1129 connect(dv, SIGNAL(deviceStateChanged(
DriverInfo*)),
this, SLOT(processDeviceStatus(
DriverInfo*)));
1131 driversList.append(dv);
1144 QTreeWidgetItem *group, *widgetDev;
1149 if (!treeList.isEmpty())
1150 group = treeList[0];
1157 name = label = s->
name();
1159 if (findDriverByLabel(label) || s->
driver() == i18n(
"None"))
1163 version = QString(
"1.0");
1165 QTreeWidgetItem *device =
new QTreeWidgetItem(group);
1166 device->setText(LOCAL_NAME_COLUMN, QString(label));
1167 device->setIcon(LOCAL_STATUS_COLUMN, ui->stopPix);
1168 device->setText(LOCAL_VERSION_COLUMN, QString(version));
1178 connect(dv, SIGNAL(deviceStateChanged(
DriverInfo*)),
this, SLOT(processDeviceStatus(
DriverInfo*)));
1179 driversList.append(dv);
1194 if (!devList.isEmpty())
1196 widgetDev = devList[0];
1197 group->removeChild(widgetDev);
1201 driversList.removeOne(dev);
1210 Ui::INDIHostConf hostConf;
1211 hostConf.setupUi(&hostConfDialog);
1212 hostConfDialog.setWindowTitle(i18n(
"Add Host"));
1213 bool portOk =
false;
1215 if (hostConfDialog.exec() == QDialog::Accepted)
1219 hostConf.portnumber->text().toInt(&portOk);
1221 if (portOk ==
false)
1223 KMessageBox::error(0, i18n(
"Error: the port number is invalid."));
1228 hostItem->
setHostParameters(hostConf.hostname->text(), hostConf.portnumber->text());
1235 KMessageBox::error(0, i18n(
"Host: %1 Port: %2 already exists.", hostItem->
getName(), hostItem->
getPort()));
1242 driversList.append(hostItem);
1244 QTreeWidgetItem *item =
new QTreeWidgetItem(ui->clientTreeWidget);
1245 item->setIcon(HOST_STATUS_COLUMN, ui->disconnected);
1246 item->setText(HOST_NAME_COLUMN, hostConf.nameIN->text());
1247 item->setText(HOST_PORT_COLUMN, hostConf.portnumber->text());
1258 Ui::INDIHostConf hostConf;
1259 hostConf.setupUi(&hostConfDialog);
1260 hostConfDialog.setWindowTitle(i18n(
"Modify Host"));
1262 QTreeWidgetItem *currentItem = ui->clientTreeWidget->currentItem();
1264 if (currentItem == NULL)
1269 if (currentItem->text(HOST_NAME_COLUMN) == host->
getName() && currentItem->text(HOST_PORT_COLUMN) == host->
getPort())
1271 hostConf.nameIN->setText(host->
getName());
1272 hostConf.hostname->setText(host->
getHost());
1273 hostConf.portnumber->setText(host->
getPort());
1275 if (hostConfDialog.exec() == QDialog::Accepted)
1278 host->
setName(hostConf.nameIN->text());
1279 host->
setHostParameters(hostConf.hostname->text(), hostConf.portnumber->text());
1281 currentItem->setText(HOST_NAME_COLUMN, hostConf.nameIN->text());
1282 currentItem->setText(HOST_PORT_COLUMN, hostConf.portnumber->text());
1298 if (ui->clientTreeWidget->currentItem() == NULL)
1302 if (ui->clientTreeWidget->currentItem()->text(HOST_NAME_COLUMN) == host->
getName() &&
1303 ui->clientTreeWidget->currentItem()->text(HOST_PORT_COLUMN) == host->
getPort())
1307 KMessageBox::error( 0, i18n(
"You need to disconnect the client before removing it."));
1311 if (KMessageBox::warningContinueCancel( 0, i18n(
"Are you sure you want to remove the %1 client?", ui->clientTreeWidget->currentItem()->text(HOST_NAME_COLUMN)), i18n(
"Delete Confirmation"),KStandardGuiItem::del())!=KMessageBox::Continue)
1314 driversList.removeOne(host);
1316 delete (ui->clientTreeWidget->currentItem());
1328 file.setFileName( KStandardDirs::locateLocal(
"appdata",
"indihosts.xml" ) );
1330 if ( !file.open( QIODevice::WriteOnly))
1332 QString message = i18n(
"Unable to write to file 'indihosts.xml'\nAny changes to INDI hosts configurations will not be saved." );
1333 KMessageBox::sorry( 0, message, i18n(
"Could Not Open File" ) );
1346 hostData =
"<INDIHost name='";
1348 hostData +=
"' hostname='";
1350 hostData +=
"' port='";
1352 hostData +=
"' />\n";
1354 outstream << hostData;
1386 QString uniqueLabel = label;
1389 foreach(INDI::BaseDevice *dv, cm->getDevices())
1391 if (label == QString(dv->getDeviceName()))
1396 uniqueLabel = QString(
"%1 %2").arg(label).arg(nset);
1401 #include "drivermanager.moc"
static QString serverPortStart()
Get INDI Server Start Port.
void setUserPort(const QString &inUserPort)
QTreeWidgetItem * lastGroup
void resizeDeviceColumn()
static INDIListener * Instance()
void setSkeletonFile(const QString &inSkeleton)
void setName(const QString &newName)
OAL::Log * logObject()
Return log object.
bool startDriver(DriverInfo *dv)
bool disconnectRemoteHost(DriverInfo *dv)
void stopDevices(const QList< DriverInfo * > &dList)
QTreeWidgetItem * lastDevice
static KStarsData * Instance()
const QString & getUserPort()
void getUniqueHosts(QList< DriverInfo * > &dList, QList< QList< DriverInfo * > > &uHosts)
static KStars * Instance()
const QString & getPort()
void setVersion(const QString &newVersion)
DriverInfo * findDriverByLabel(const QString &label)
void removeManagedDriver(DriverInfo *dv)
This is the main window for KStars.
void activateHostConnection()
void processServerTermination(ServerManager *server)
void processDeviceStatus(DriverInfo *dv)
void stopDriver(DriverInfo *dv)
bool connectRemoteHost(DriverInfo *dv)
void setTreeLabel(const QString &inTreeLabel)
void appendManagedDriver(DriverInfo *dv)
DriverManagerUI(QWidget *parent=0)
ClientManager * getClientManager()
bool buildDeviceGroup(XMLEle *root, char errmsg[])
void addClient(ClientManager *cm)
ServerManager * getServerManager()
bool buildDriverElement(XMLEle *root, QTreeWidgetItem *DGroup, DeviceFamily groupType, char errmsg[])
DriverSource getDriverSource()
const QString & getPort()
void processRemoteTree(bool dState)
void addClient(ClientManager *cm)
void activateHostDisconnection()
const QString & getHost()
static QString indiDriversDir()
Get PATH to indi drivers directory.
ServerManager * getServerManager()
static QString serverPortEnd()
Get INDI Server Final Port.
DriverInfo * findDriverByName(const QString &name)
void processXMLDriver(QString &driverName)
void removeClient(ClientManager *cm)
const QString & getTreeLabel()
ClientManager * getClientManager(DriverInfo *dv)
void makePortEditable(QTreeWidgetItem *selectedItem, int column)
int getINDIPort(int customPort)
QString getServerBuffer()
static GUIManager * Instance()
void updateCustomDrivers()
const QString & getHost()
const QString & getName()
void activateRunService()
QString getUniqueDeviceLabel(const QString &label)
void setDriverSource(DriverSource newDriverSource)
void processClientTermination(ClientManager *client)
void setType(DeviceFamily newType)
bool startDevices(QList< DriverInfo * > &dList)
OAL::Scope * findScopeByName(QString name)
void removeClient(ClientManager *cm)
void activateStopService()
void setServerState(bool inState)
void processLocalTree(bool dState)
const QString & getVersion()
void setMode(ServerMode inMode)
void setDriver(const QString &newDriver)
static DriverManager * Instance()
void setHostParameters(const QString &inHost, const QString &inPort)