Kstars

ekosliveclient.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "Options.h"
8
9#include "ekosliveclient.h"
10#include "ekos/manager.h"
11
12#include "kspaths.h"
13#include "Options.h"
14#include "ekos_debug.h"
15#include "QProgressIndicator.h"
16
17#include <config-kstars.h>
18
19#ifdef HAVE_KEYCHAIN
20#include <qt5keychain/keychain.h>
21#endif
22
23#include <QJsonDocument>
24#include <QJsonObject>
25#include <QNetworkAccessManager>
26#include <QNetworkReply>
27
28namespace EkosLive
29{
30Client::Client(Ekos::Manager *manager) : QDialog(manager), m_Manager(manager)
31{
32 setupUi(this);
33
34 connect(closeB, &QPushButton::clicked, this, &Client::close);
35
36 QPixmap im;
37 if (im.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "ekoslive.png")))
38 leftBanner->setPixmap(im);
39
40 pi = new QProgressIndicator(this);
41 bottomLayout->insertWidget(1, pi);
42
43 connectionState->setPixmap(QIcon::fromTheme("state-offline").pixmap(QSize(64, 64)));
44
45 username->setText(Options::ekosLiveUsername());
46 connect(username, &QLineEdit::editingFinished, this, [this]()
47 {
48 Options::setEkosLiveUsername(username->text());
49 });
50
51 // Initialize node managers
52 QSharedPointer<NodeManager> onlineManager(new NodeManager(NodeManager::Message | NodeManager::Media | NodeManager::Cloud));
53 connect(onlineManager.get(), &NodeManager::authenticationError, this, [this](const QString & message)
54 {
55 onlineLabel->setToolTip(message);
56 });
57
58 QSharedPointer<NodeManager> offlineManager(new NodeManager(NodeManager::Message | NodeManager::Media));
59
60 connect(offlineManager.get(), &NodeManager::authenticationError, this, [this](const QString & message)
61 {
62 offlineLabel->setToolTip(message);
63 });
64
65 m_NodeManagers.append(std::move(onlineManager));
66 m_NodeManagers.append(std::move(offlineManager));
67 syncURLs();
68
69 connect(selectServersB, &QPushButton::clicked, this, &Client::showSelectServersDialog);
70 connect(connectB, &QPushButton::clicked, this, [this]()
71 {
72 if (m_isConnected)
73 {
74 for (auto &oneManager : m_NodeManagers)
75 oneManager->disconnectNodes();
76 }
77 else
78 {
79 for (auto &oneManager : m_NodeManagers)
80 {
81 oneManager->setCredentials(username->text(), password->text());
82 oneManager->authenticate();
83 }
84 }
85 });
86
87 connect(password, &QLineEdit::returnPressed, this, [this]()
88 {
89 if (!m_isConnected)
90 {
91 for (auto &oneManager : m_NodeManagers)
92 {
93 oneManager->setCredentials(username->text(), password->text());
94 oneManager->authenticate();
95 }
96 }
97 });
98
99 rememberCredentialsCheck->setChecked(Options::rememberCredentials());
101 {
102 Options::setRememberCredentials(toggled);
103 });
104 autoStartCheck->setChecked(Options::autoStartEkosLive());
105 connect(autoStartCheck, &QCheckBox::toggled, [ = ](bool toggled)
106 {
107 Options::setAutoStartEkosLive(toggled);
108 });
109
110#ifdef HAVE_KEYCHAIN
112 job->setAutoDelete(false);
113 job->setKey(QLatin1String("ekoslive"));
114 connect(job, &QKeychain::Job::finished, this, [&](QKeychain::Job * job)
115 {
116 if (job->error() == false)
117 {
118 const auto passwordText = dynamic_cast<QKeychain::ReadPasswordJob*>(job)->textData().toLatin1();
119
120 // Only set and attempt connection if the data is not empty
121 if (passwordText.isEmpty() == false && username->text().isEmpty() == false)
122 {
123 password->setText(passwordText);
124 if (autoStartCheck->isChecked())
125 {
126 for (auto &oneManager : m_NodeManagers)
127 {
128 oneManager->setCredentials(username->text(), password->text());
129 oneManager->authenticate();
130 }
131 }
132 }
133 }
134 else
135 {
136 if (autoStartCheck->isChecked())
137 qCWarning(KSTARS_EKOS) << "Failed to automatically connect due to missing EkosLive credentials:" << job->errorString();
138 }
139 job->deleteLater();
140 });
141 job->start();
142#endif
143
144 m_Message = new Message(m_Manager, m_NodeManagers);
145 connect(m_Message, &Message::connected, this, &Client::onConnected);
146 connect(m_Message, &Message::disconnected, this, &Client::onDisconnected);
147 connect(m_Message, &Message::expired, this, [&](const QUrl & url)
148 {
149 // If token expired, disconnect and reconnect again.
150 for (auto &oneManager : m_NodeManagers)
151 {
152 if (oneManager->property("websocketURL").toUrl() == url)
153 {
154 oneManager->disconnectNodes();
155 oneManager->setCredentials(username->text(), password->text());
156 oneManager->authenticate();
157 }
158 }
159 });
160
161 m_Media = new Media(m_Manager, m_NodeManagers);
162 connect(m_Media, &Media::connected, this, &Client::onConnected);
163 m_Cloud = new Cloud(m_Manager, m_NodeManagers);
164 connect(m_Cloud, &Cloud::connected, this, &Client::onConnected);
165}
166
167Client::~Client()
168{
169 for (auto &oneManager : m_NodeManagers)
170 oneManager->disconnectNodes();
171}
172
173void Client::onConnected()
174{
175 pi->stopAnimation();
176
177 m_isConnected = true;
178
179 connectB->setText(i18n("Disconnect"));
180 connectionState->setPixmap(QIcon::fromTheme("state-ok").pixmap(QSize(64, 64)));
181
182 auto disconnected = QIcon(":/icons/AlignFailure.svg").pixmap(QSize(32, 32));
183 auto connected = QIcon(":/icons/AlignSuccess.svg").pixmap(QSize(32, 32));
184
185 onlineLabel->setStyleSheet(m_NodeManagers[0]->isConnected() ? "color:white" : "color:gray");
186 onlineIcon->setPixmap(m_NodeManagers[0]->isConnected() ? connected : disconnected);
187 if (m_NodeManagers[0]->isConnected())
188 onlineLabel->setToolTip(QString());
189
190 selectServersB->setEnabled(false);
191 offlineLabel->setStyleSheet(m_NodeManagers[1]->isConnected() ? "color:white" : "color:gray");
192 offlineIcon->setPixmap(m_NodeManagers[1]->isConnected() ? connected : disconnected);
193 if (m_NodeManagers[1]->isConnected())
194 offlineLabel->setToolTip(QString());
195
196 if (rememberCredentialsCheck->isChecked())
197 {
198#ifdef HAVE_KEYCHAIN
200 job->setAutoDelete(true);
201 job->setKey(QLatin1String("ekoslive"));
202 job->setTextData(password->text());
203 job->start();
204#endif
205 }
206}
207
208void Client::onDisconnected()
209{
210 connectionState->setPixmap(QIcon::fromTheme("state-offline").pixmap(QSize(64, 64)));
211 m_isConnected = false;
212 connectB->setText(i18n("Connect"));
213
214 auto disconnected = QIcon(":/icons/AlignFailure.svg").pixmap(QSize(32, 32));
215 auto connected = QIcon(":/icons/AlignSuccess.svg").pixmap(QSize(32, 32));
216
217 onlineLabel->setStyleSheet(m_NodeManagers[0]->isConnected() ? "color:white" : "color:gray");
218 onlineIcon->setPixmap(m_NodeManagers[0]->isConnected() ? connected : disconnected);
219
220 offlineLabel->setStyleSheet(m_NodeManagers[1]->isConnected() ? "color:white" : "color:gray");
221 offlineIcon->setPixmap(m_NodeManagers[1]->isConnected() ? connected : disconnected);
222
223 selectServersB->setEnabled(true);
224}
225
226void Client::setConnected(bool enabled)
227{
228 // Return if there is no change.
229 if (enabled == m_isConnected)
230 return;
231
232 connectB->click();
233}
234
235void Client::setConfig(bool rememberCredentials, bool autoConnect)
236{
238 autoStartCheck->setChecked(autoConnect);
239}
240
241void Client::setUser(const QString &user, const QString &pass)
242{
243 username->setText(user);
244 Options::setEkosLiveUsername(user);
245
246 password->setText(pass);
247}
248
249void Client::showSelectServersDialog()
250{
251 QDialog dialog(this);
252 dialog.setMinimumWidth(300);
253 dialog.setWindowTitle(i18nc("@title:window", "Select EkosLive Servers"));
254
255 QLabel offline(i18n("Offline:"));
256 QLabel online(i18n("Online:"));
257
258 QLineEdit offlineEdit(&dialog);
259 QLineEdit onlineEdit(&dialog);
260 offlineEdit.setText(Options::ekosLiveOfflineServer());
261 onlineEdit.setText(Options::ekosLiveOnlineServer());
262
263 QFormLayout * layout = new QFormLayout;
264 layout->addRow(&offline, &offlineEdit);
265 layout->addRow(&online, &onlineEdit);
266 dialog.setLayout(layout);
267 dialog.exec();
268
269 Options::setEkosLiveOfflineServer(offlineEdit.text());
270 Options::setEkosLiveOnlineServer(onlineEdit.text());
271
272 syncURLs();
273}
274
275void Client::syncURLs()
276{
277 auto onlineSSL = QUrl(Options::ekosLiveOnlineServer()).scheme() == "https";
278 auto onlineURL = QUrl(Options::ekosLiveOnlineServer()).url(QUrl::RemoveScheme);
279 if (onlineSSL)
280 m_NodeManagers[Online]->setURLs(QUrl("https:" + onlineURL), QUrl("wss:" + onlineURL));
281 else
282 m_NodeManagers[Online]->setURLs(QUrl("http:" + onlineURL), QUrl("ws:" + onlineURL));
283
284 auto offlineSSL = QUrl(Options::ekosLiveOfflineServer()).scheme() == "https";
285 auto offlineURL = QUrl(Options::ekosLiveOfflineServer()).url(QUrl::RemoveScheme);
286 if (offlineSSL)
287 m_NodeManagers[Offline]->setURLs(QUrl("https:" + offlineURL), QUrl("wss:" + offlineURL));
288 else
289 m_NodeManagers[Offline]->setURLs(QUrl("http:" + offlineURL), QUrl("ws:" + offlineURL));
290}
291}
The QProgressIndicator class lets an application display a progress indicator to show that a long tas...
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Generic record interfaces and implementations.
Definition cloud.cpp:23
void clicked(bool checked)
void toggled(bool checked)
void addRow(QLayout *layout)
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
void editingFinished()
void returnPressed()
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
RemoveScheme
QString scheme() const const
QString url(FormattingOptions options) 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:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.