Kstars

indidevice.cpp
1/*
2 SPDX-FileCopyrightText: 2012 Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include <indicom.h>
8#include <base64.h>
9#include <basedevice.h>
10
11#include <QFrame>
12#include <QCheckBox>
13#include <QLabel>
14#include <QPushButton>
15#include <QLayout>
16#include <QButtonGroup>
17#include <QSocketNotifier>
18#include <QDateTime>
19#include <QSplitter>
20#include <QLineEdit>
21#include <QDebug>
22#include <QComboBox>
23#include <QStatusBar>
24#include <QMenu>
25#include <QTabWidget>
26#include <QTextEdit>
27
28#include <KLed>
29#include <KLocalizedString>
30#include <KMessageBox>
31
32#include "kstars.h"
33#include "skymap.h"
34#include "Options.h"
35#include "skyobjects/skyobject.h"
36#include "dialogs/timedialog.h"
37#include "geolocation.h"
38
39#include "indiproperty.h"
40#include "indidevice.h"
41#include "indigroup.h"
42#include "indielement.h"
43
44#include <indi_debug.h>
45
46const char *libindi_strings_context = "string from libindi, used in the config dialog";
47
48INDI_D::INDI_D(QWidget *parent, INDI::BaseDevice baseDevice, ClientManager *in_cm) : QWidget(parent)
49{
50#ifdef Q_OS_OSX
51 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
52#endif
53 m_BaseDevice = baseDevice;
54 m_ClientManager = in_cm;
55
56 m_Name = m_BaseDevice.getDeviceName();
57
58 QHBoxLayout *layout = new QHBoxLayout(this);
59
60 deviceVBox = new QSplitter(Qt::Vertical, this);
61
62 groupContainer = new QTabWidget(this);
63
64 msgST_w = new QTextEdit(this);
65 msgST_w->setReadOnly(true);
66 msgST_w->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
67
68 deviceVBox->addWidget(groupContainer);
69 deviceVBox->addWidget(msgST_w);
70 deviceVBox->setStretchFactor(0, 2);
71
72 layout->addWidget(deviceVBox);
73}
74
75bool INDI_D::buildProperty(INDI::Property prop)
76{
77 if (!prop.isValid())
78 return false;
79
80 QString groupName(prop.getGroupName());
81
82 if (prop.getDeviceName() != m_Name)
83 return false;
84
85 INDI_G *pg = getGroup(groupName);
86
87 if (pg == nullptr)
88 {
89 pg = new INDI_G(this, groupName);
90 groupsList.append(pg);
91 groupContainer->addTab(pg, i18nc(libindi_strings_context, groupName.toUtf8()));
92 }
93
94 return pg->addProperty(prop);
95}
96
97#if 0
98bool INDI_D::removeProperty(INDI::Property prop)
99{
100 if (prop == nullptr)
101 return false;
102
103 QString groupName(prop->getGroupName());
104
105 if (strcmp(prop->getDeviceName(), m_BaseDevice->getDeviceName()))
106 {
107 // qDebug() << Q_FUNC_INFO << "Ignoring property " << prop->getName() << " for device " << prop->getgetDeviceName() << " because our device is "
108 // << dv->getDeviceName() << Qt::endl;
109 return false;
110 }
111
112 // qDebug() << Q_FUNC_INFO << "Received new property " << prop->getName() << " for our device " << dv->getDeviceName() << Qt::endl;
113
114 INDI_G *pg = getGroup(groupName);
115
116 if (pg == nullptr)
117 return false;
118
119 bool removeResult = pg->removeProperty(prop->getName());
120
121 if (pg->size() == 0 && removeResult)
122 {
123 //qDebug() << Q_FUNC_INFO << "Removing tab for group " << pg->getName() << " with an index of " << groupsList.indexOf(pg) << Qt::endl;
124 groupContainer->removeTab(groupsList.indexOf(pg));
125 groupsList.removeOne(pg);
126 delete (pg);
127 }
128
129 return removeResult;
130}
131#endif
132
133bool INDI_D::removeProperty(INDI::Property prop)
134{
135 if (prop.getDeviceName() != m_Name)
136 return false;
137
138 for (auto &oneGroup : groupsList)
139 {
140 for (auto &oneProperty : oneGroup->getProperties())
141 {
142 if (prop.getName() == oneProperty->getName())
143 {
144 bool rc = oneGroup->removeProperty(prop.getName());
145 if (oneGroup->size() == 0)
146 {
147 int index = groupsList.indexOf(oneGroup);
148 groupContainer->removeTab(index);
149 delete groupsList.takeAt(index);
150 }
151 return rc;
152 }
153 }
154 }
155
156 return false;
157}
158
159bool INDI_D::updateProperty(INDI::Property prop)
160{
161 switch (prop.getType())
162 {
163 case INDI_SWITCH:
164 return updateSwitchGUI(prop);
165 case INDI_NUMBER:
166 return updateNumberGUI(prop);
167 case INDI_TEXT:
168 return updateTextGUI(prop);
169 case INDI_LIGHT:
170 return updateLightGUI(prop);
171 case INDI_BLOB:
172 return updateBLOBGUI(prop);
173 default:
174 return false;
175 }
176}
177
178bool INDI_D::updateSwitchGUI(INDI::Property prop)
179{
180 INDI_P *guiProp = nullptr;
181
182 if (m_Name != prop.getDeviceName())
183 return false;
184
185 for (const auto &pg : groupsList)
186 {
187 if ((guiProp = pg->getProperty(prop.getName())) != nullptr)
188 break;
189 }
190
191 if (guiProp == nullptr || guiProp->isRegistered() == false)
192 return false;
193
194 guiProp->updateStateLED();
195
196 if (guiProp->getGUIType() == PG_MENU)
197 guiProp->updateMenuGUI();
198 else
199 {
200 for (const auto &lp : guiProp->getElements())
201 lp->syncSwitch();
202 }
203
204 return true;
205}
206
207bool INDI_D::updateTextGUI(INDI::Property prop)
208{
209 INDI_P *guiProp = nullptr;
210
211 if (m_Name != prop.getDeviceName())
212 return false;
213
214 for (const auto &pg : groupsList)
215 {
216 auto p = pg->getProperty(prop.getName());
217 if (p != nullptr)
218 {
219 guiProp = p;
220 break;
221 }
222 }
223
224 if (guiProp == nullptr)
225 return false;
226
227 guiProp->updateStateLED();
228
229 for (const auto &lp : guiProp->getElements())
230 lp->syncText();
231
232 return true;
233}
234
235bool INDI_D::updateNumberGUI(INDI::Property prop)
236{
237 INDI_P *guiProp = nullptr;
238
239 if (m_Name != prop.getDeviceName())
240 return false;
241
242 for (const auto &pg : groupsList)
243 {
244 auto p = pg->getProperty(prop.getName());
245 if (p != nullptr)
246 {
247 guiProp = p;
248 break;
249 }
250 }
251
252 if (guiProp == nullptr)
253 return false;
254
255 guiProp->updateStateLED();
256
257 for (const auto &lp : guiProp->getElements())
258 lp->syncNumber();
259
260 return true;
261}
262
263bool INDI_D::updateLightGUI(INDI::Property prop)
264{
265 INDI_P *guiProp = nullptr;
266
267 if (m_Name != prop.getDeviceName())
268 return false;
269
270 for (const auto &pg : groupsList)
271 {
272 auto p = pg->getProperty(prop.getName());
273 if (p != nullptr)
274 {
275 guiProp = p;
276 break;
277 }
278 }
279
280 if (guiProp == nullptr)
281 return false;
282
283 guiProp->updateStateLED();
284
285 for (const auto &lp : guiProp->getElements())
286 lp->syncLight();
287
288 return true;
289}
290
291bool INDI_D::updateBLOBGUI(INDI::Property prop)
292{
293 INDI_P *guiProp = nullptr;
294
295 if (m_Name != prop.getDeviceName())
296 return false;
297
298 for (const auto &pg : groupsList)
299 {
300 auto p = pg->getProperty(prop.getName());
301 if (p != nullptr)
302 {
303 guiProp = p;
304 break;
305 }
306 }
307
308 if (guiProp == nullptr)
309 return false;
310
311 guiProp->updateStateLED();
312
313 return true;
314}
315
316void INDI_D::updateMessageLog(INDI::BaseDevice idv, int messageID)
317{
318 if (idv.getDeviceName() != m_BaseDevice.getDeviceName())
319 return;
320
321 QString message = QString::fromStdString(m_BaseDevice.messageQueue(messageID));
322 QString formatted = message;
323
324 // TODO the colors should be from the color scheme
325 if (message.mid(21, 2) == "[E")
326 formatted = QString("<span style='color:red'>%1</span>").arg(message);
327 else if (message.mid(21, 2) == "[W")
328 formatted = QString("<span style='color:orange'>%1</span>").arg(message);
329 else if (message.mid(21, 2) != "[I")
330 {
331 // Debug message
332 qCDebug(KSTARS_INDI) << idv.getDeviceName() << ":" << message.mid(21);
333 return;
334 }
335
336 if (Options::showINDIMessages())
337 KStars::Instance()->statusBar()->showMessage(i18nc("INDI message shown in status bar", "%1", message), 0);
338
339 msgST_w->ensureCursorVisible();
340 msgST_w->insertHtml(i18nc("Message shown in INDI control panel", "%1", formatted));
341 msgST_w->insertPlainText("\n");
342 QTextCursor c = msgST_w->textCursor();
344 msgST_w->setTextCursor(c);
345
346 qCInfo(KSTARS_INDI) << idv.getDeviceName() << ": " << message.mid(21);
347}
348
349//INDI_D::~INDI_D()
350//{
351// while (!groupsList.isEmpty())
352// delete groupsList.takeFirst();
353//}
354
355INDI_G *INDI_D::getGroup(const QString &groupName) const
356{
357 for (const auto &pg : groupsList)
358 {
359 if (pg->getName() == groupName)
360 return pg;
361 }
362
363 return nullptr;
364}
365
366void INDI_D::clearMessageLog()
367{
368 msgST_w->clear();
369}
ClientManager manages connection to INDI server, creation of devices, and receiving/sending propertie...
INDI_G represents a collection of INDI properties that share a common group.
Definition indigroup.h:31
INDI_P represents a single INDI property (Switch, Text, Number, Light, or BLOB).
static KStars * Instance()
Definition kstars.h:123
QString i18nc(const char *context, const char *text, const TYPE &arg...)
KDB_EXPORT void getProperties(const KDbLookupFieldSchema *lookup, QMap< QByteArray, QVariant > *values)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void append(QList< T > &&value)
qsizetype indexOf(const AT &value, qsizetype from) const const
bool removeOne(const AT &t)
T takeAt(qsizetype i)
QString arg(Args &&... args) const const
QString fromStdString(const std::string &str)
QString mid(qsizetype position, qsizetype n) const const
Vertical
int addTab(QWidget *page, const QIcon &icon, const QString &label)
void removeTab(int index)
bool movePosition(MoveOperation operation, MoveMode mode, int n)
void clear()
void ensureCursorVisible()
void insertHtml(const QString &text)
void insertPlainText(const QString &text)
void setTextCursor(const QTextCursor &cursor)
QTextCursor textCursor() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:03 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.