1 /*
2     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include "indicommon.h"
10 #include "customdrivers.h"
11 #include "ui_drivermanager.h"
12 
13 #include <QDialog>
14 #include <QFrame>
15 #include <QIcon>
16 #include <QString>
17 #include <QPointer>
18 #include <QJsonArray>
19 
20 #include <lilxml.h>
21 
22 class QStringList;
23 class QTreeWidgetItem;
24 
25 class DriverManager;
26 class ServerManager;
27 class ClientManager;
28 class DriverInfo;
29 
30 class DriverManagerUI : public QFrame, public Ui::DriverManager
31 {
32         Q_OBJECT
33 
34     public:
35         explicit DriverManagerUI(QWidget *parent = nullptr);
36 
37     public slots:
38         void makePortEditable(QTreeWidgetItem *selectedItem, int column);
39 
40     public:
41         QIcon runningPix;
42         QIcon stopPix;
43         QIcon connected;
44         QIcon disconnected;
45         QIcon localMode;
46         QIcon serverMode;
47 };
48 
49 /**
50  * @brief DriverManager is the primary class to handle all operations related to starting and stopping INDI drivers.
51  *
52  * INDI drivers can be local or remote drivers. For remote hosts, driver information is not known and devices are built
53  * as they arrive dynamically. The class parses INDI primary devices XML file (drivers.xml) and any 3rd party INDI Driver
54  * XML file to build a tree of devices grouped by driver family type.
55  *
56  * When starting local drivers, DriverManager also establishes an INDI server with the requested drivers and then connect to
57  * the local server to receive the devices dynamically.
58  *
59  * The class also handles INDI hosts which can be added in order to connect to a local or remote INDI server.
60  *
61  * @author Jasem Mutlaq
62  */
63 class DriverManager : public QDialog
64 {
65         Q_OBJECT
66 
67     public:
68         static DriverManager *Instance();
69 
70         enum
71         {
72             LOCAL_NAME_COLUMN = 0,
73             LOCAL_STATUS_COLUMN,
74             LOCAL_MODE_COLUMN,
75             LOCAL_VERSION_COLUMN,
76             LOCAL_PORT_COLUMN
77         };
78         enum
79         {
80             HOST_STATUS_COLUMN = 0,
81             HOST_NAME_COLUMN,
82             HOST_PORT_COLUMN
83         };
84 
85         bool readXMLDrivers();
86         bool readINDIHosts();
87         void processXMLDriver(const QString &driverName);
88         bool buildDeviceGroup(XMLEle *root, char errmsg[]);
89         bool buildDriverElement(XMLEle *root, QTreeWidgetItem *DGroup, DeviceFamily groupType, char errmsg[]);
90 
91         int getINDIPort(int customPort);
92         bool isDeviceRunning(const QString &deviceLabel);
93 
94         void saveHosts();
95 
96         void processLocalTree(bool dState);
97         void processRemoteTree(bool dState);
98 
99         DriverInfo *findDriverByName(const QString &name);
100         DriverInfo *findDriverByLabel(const QString &label);
101         DriverInfo *findDriverByExec(const QString &exec);
102 
103         ClientManager *getClientManager(DriverInfo *dv);
104 
getDrivers()105         const QList<DriverInfo *> &getDrivers() const
106         {
107             return driversList;
108         }
getCustomDrivers()109         const QList<QVariantMap> &getCustomDrivers() const
110         {
111             return m_CustomDrivers->customDrivers();
112         }
113         QJsonArray getDriverList() const;
114 
getDriversStringList()115         const QStringList &getDriversStringList()
116         {
117             return driversStringList;
118         }
119 
120         /**
121          * @brief getUniqueHosts Given a list of DriverInfos, extract all the host:port information from all the drivers.
122          * and then consolidate each groups of drivers that belong to the same server & port to a specific list
123          * e.g. If we have driver1 (localhost:7624), driver2(192.168.1.90:7624), driver3(localhost:7624) then this would create
124          * two lists. First list contains [driver1,driver3] and second list contains [driver2] making each list _unique_ in terms of host params.
125          * @param dList list of driver to examine
126          * @param uHosts List of unique hosts, each with a group of drivers that belong to it.
127          */
128         void getUniqueHosts(QList<DriverInfo *> &dList, QList<QList<DriverInfo *>> &uHosts);
129 
addDriver(DriverInfo * di)130         void addDriver(DriverInfo *di)
131         {
132             driversList.append(di);
133         }
removeDriver(DriverInfo * di)134         void removeDriver(DriverInfo *di)
135         {
136             driversList.removeOne(di);
137         }
138 
139         bool startDevices(QList<DriverInfo *> &dList);
140         void stopDevices(const QList<DriverInfo *> &dList);
stopAllDevices()141         void stopAllDevices()
142         {
143             stopDevices(driversList);
144         }
145         bool restartDriver(DriverInfo *dv);
146 
147         bool connectRemoteHost(DriverInfo *dv);
148         bool disconnectRemoteHost(DriverInfo *dv);
149 
150         QString getUniqueDeviceLabel(const QString &label);
151 
152         void clearServers();
153 
154     private:
155         DriverManager(QWidget *parent);
156         ~DriverManager();
157 
158         bool checkDriverAvailability(const QString &driver);
159 
160         static DriverManager *_DriverManager;
161 
162         ServerMode connectionMode { SERVER_CLIENT };
163         QTreeWidgetItem *lastGroup { nullptr };
164         int currentPort;
165         //DriverInfo::XMLSource xmlSource;
166         DriverSource driverSource;
167         DriverManagerUI *ui { nullptr };
168         QList<DriverInfo *> driversList;
169         QList<ServerManager *> servers;
170         QList<ClientManager *> clients;
171         QStringList driversStringList;
172         QPointer<CustomDrivers> m_CustomDrivers;
173 
174     public slots:
175         //void enableDevice(INDI_D *device);
176         //void disableDevice(INDI_D *device);
177 
178         void resizeDeviceColumn();
179         void updateLocalTab();
180         void updateClientTab();
181 
182         void updateMenuActions();
183 
184         void addINDIHost();
185         void modifyINDIHost();
186         void removeINDIHost();
187         void activateRunService();
188         void activateStopService();
189         void activateHostConnection();
190         void activateHostDisconnection();
191 
192         void updateCustomDrivers();
193 
194         void processClientTermination(ClientManager *client);
195         void processServerTermination(ServerManager *server);
196 
197         void processDeviceStatus(DriverInfo *dv);
198 
showCustomDrivers()199         void showCustomDrivers()
200         {
201             m_CustomDrivers->show();
202         }
203 
204     signals:
205         void clientTerminated(ClientManager *);
206         void serverTerminated(const QString &host, const QString &port);
207         void serverStarted(const QString &host, const QString &port);
208 
209         /*
210             signals:
211             void newDevice();
212             void newTelescope();
213             void newCCD();
214             */
215 };
216