swift
infobarstatuscomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QLabel>
7 #include <QList>
8 #include <QMenu>
9 #include <QPoint>
10 #include <QPointer>
11 #include <QStringBuilder>
12 #include <QTimer>
13 #include <QWidget>
14 #include <Qt>
15 #include <QtGlobal>
16 
17 #include "ui_infobarstatuscomponent.h"
18 
19 #include "config/buildconfig.h"
24 #include "core/simulator.h"
26 #include "gui/guiapplication.h"
27 #include "gui/guiutility.h"
28 #include "gui/led.h"
29 #include "misc/network/server.h"
31 
32 using namespace swift::config;
33 using namespace swift::core;
34 using namespace swift::core::context;
35 using namespace swift::gui;
36 using namespace swift::misc;
37 using namespace swift::misc::audio;
38 using namespace swift::misc::network;
39 
40 namespace swift::gui::components
41 {
42  CInfoBarStatusComponent::CInfoBarStatusComponent(QWidget *parent)
43  : QFrame(parent), ui(new Ui::CInfoBarStatusComponent)
44  {
45  ui->setupUi(this);
46  this->initLeds();
47  this->adjustTextSize();
48 
49  connect(ui->comp_XpdrMode, &CTransponderModeComponent::changed, this,
51 
52  Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui");
54  {
55  connect(sGui->getIContextSimulator(), &IContextSimulator::simulatorStatusChanged, this,
56  &CInfoBarStatusComponent::onSimulatorStatusChanged, Qt::QueuedConnection);
57  connect(sGui->getIContextSimulator(), &IContextSimulator::modelSetChanged, this,
58  &CInfoBarStatusComponent::onMapperReady);
59 
60  // initial values
61  this->onMapperReady();
62  this->onSimulatorStatusChanged(sGui->getIContextSimulator()->getSimulatorStatus());
63  }
64 
65  if (sGui->getIContextNetwork())
66  {
67  connect(sGui->getIContextNetwork(), &IContextNetwork::connectionStatusChanged, this,
68  &CInfoBarStatusComponent::onNetworkConnectionChanged, Qt::QueuedConnection);
69  }
70 
72  {
73  ui->led_DBus->setOn(sGui->getIContextApplication()->isUsingImplementingObject());
74  }
75 
76  ui->led_Audio->setOn(CInfoBarStatusComponent::isAudioAvailableAndNotMuted());
78  {
79  connect(sGui->getCContextAudioBase(), &CContextAudioBase::changedOutputMute, this,
80  &CInfoBarStatusComponent::onOutputMuteChanged, Qt::QueuedConnection);
81  connect(sGui->getCContextAudioBase(), &CContextAudioBase::startedAudio, this,
82  &CInfoBarStatusComponent::onAudioStarted, Qt::QueuedConnection);
83  connect(sGui->getCContextAudioBase(), &CContextAudioBase::stoppedAudio, this,
84  &CInfoBarStatusComponent::onAudioStopped, Qt::QueuedConnection);
85 
86  // PTT as received on audio
87  // that also would need to be reconnected if audio is disabled/enabled
88  // connect(sGui->getCContextAudioBase(), &CContextAudioBase::ptt, this,
89  // &CInfoBarStatusComponent::onPttChanged, Qt::QueuedConnection);
90  }
91 
92  QPointer<CInfoBarStatusComponent> myself(this);
93  QTimer::singleShot(5000, this, [=] {
94  if (!sGui || sGui->isShuttingDown() || !myself) { return; }
95  this->updateValues();
96  });
97  }
98 
100 
101  void CInfoBarStatusComponent::initLeds()
102  {
103  this->updateSpacing();
104  CLedWidget::LedShape shape = CLedWidget::Circle;
105  ui->led_DBus->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "DBus connected", "DBus disconnected",
106  14);
107  ui->led_Network->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "Network connected",
108  "Network disconnected", 14);
109  ui->led_Simulator->setValues(CLedWidget::Yellow, CLedWidget::Black, CLedWidget::Blue, shape,
110  "Simulator running", "Simulator disconnected", "Simulator connected", 14);
111  ui->led_MapperReady->setValues(CLedWidget::Yellow, CLedWidget::Black, CLedWidget::Blue, shape, "Mapper ready",
112  "Mappings not yet loaded", "Mappings not yet loaded", 14);
113 
114  shape = CLedWidget::Rounded;
115  ui->led_Ptt->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "Ptt", "Silence", 18);
116  ui->led_Audio->setValues(CLedWidget::Yellow, CLedWidget::Black, shape, "On", "Muted", 18);
117  }
118 
119  void CInfoBarStatusComponent::adjustTextSize()
120  {
121  CGuiUtility::setElidedText(ui->lbl_Audio, QStringLiteral("audio"), Qt::ElideRight);
122  CGuiUtility::setElidedText(ui->lbl_Network, QStringLiteral("network"), Qt::ElideRight);
123  CGuiUtility::setElidedText(ui->lbl_DBus, QStringLiteral("DBus"), {}, Qt::ElideRight);
124  CGuiUtility::setElidedText(ui->lbl_MapperReady, QStringLiteral("mapper ready"), Qt::ElideRight);
125  CGuiUtility::setElidedText(ui->lbl_Ptt, QStringLiteral("PTT"), Qt::ElideRight);
126  CGuiUtility::setElidedText(ui->lbl_Simulator, QStringLiteral("simulator"), Qt::ElideRight);
127  }
128 
129  void CInfoBarStatusComponent::setDBusStatus(bool dbus) { ui->led_DBus->setOn(dbus); }
130 
131  void CInfoBarStatusComponent::setDBusTooltip(const QString &tooltip) { ui->led_DBus->setOnToolTip(tooltip); }
132 
134  {
135  if (this->layout()) { this->layout()->setSpacing(spacing); }
136  }
137 
138  void CInfoBarStatusComponent::resizeEvent(QResizeEvent *event)
139  {
140  QFrame::resizeEvent(event);
141  m_dsResize.inputSignal();
142  }
143 
144  void CInfoBarStatusComponent::onSimulatorStatusChanged(int status)
145  {
146  if (!sGui || sGui->isShuttingDown()) { return; }
147  const ISimulator::SimulatorStatus simStatus = static_cast<ISimulator::SimulatorStatus>(status);
148  if (simStatus.testFlag(ISimulator::Connected))
149  {
150  // at least connected
151  const QString s(sGui->getIContextSimulator()->getSimulatorPluginInfo().getDescription() % u": " %
152  ISimulator::statusToString(simStatus));
153 
154  if (simStatus.testFlag(ISimulator::Paused))
155  {
156  ui->led_Simulator->setTriState();
157  ui->led_Simulator->setTriStateToolTip(s);
158  }
159  else if (simStatus.testFlag(ISimulator::Simulating))
160  {
161  ui->led_Simulator->setOn(true);
162  ui->led_Simulator->setOnToolTip(s);
163  }
164  else
165  {
166  // connected only
167  ui->led_Simulator->setTriState();
168  ui->led_Simulator->setTriStateToolTip(s);
169  }
170  }
171  else { ui->led_Simulator->setOn(false); }
172 
173  // simulator status has impact on model set available
174  this->onMapperReady();
175  }
176 
177  void CInfoBarStatusComponent::onNetworkConnectionChanged(const CConnectionStatus &from, const CConnectionStatus &to)
178  {
179  Q_UNUSED(from)
180  switch (to.getConnectionStatus())
181  {
182  case CConnectionStatus::Disconnected: ui->led_Network->setOn(false); break;
183  case CConnectionStatus::Connected:
184  ui->led_Network->setOn(true);
185  ui->led_Network->setOnToolTip(u"Connected: " % sGui->getIContextNetwork()->getConnectedServer().getName());
186  break;
187  case CConnectionStatus::Connecting: ui->led_Network->setTriStateColor(CLedWidget::Yellow); break;
188  default: ui->led_Network->setOn(false); break;
189  }
190  }
191 
192  void CInfoBarStatusComponent::onOutputMuteChanged(bool muted)
193  {
194  const bool on = !muted && isAudioAvailableAndNotMuted(); // make sure audio is started
195  ui->led_Audio->setOn(on);
196  }
197 
198  void CInfoBarStatusComponent::onAudioStarted(const CAudioDeviceInfo &input, const CAudioDeviceInfo &output)
199  {
200  Q_UNUSED(input)
201  Q_UNUSED(output)
202  this->updateValues();
203  }
204 
205  void CInfoBarStatusComponent::onAudioStopped() { this->updateValues(); }
206 
207  void CInfoBarStatusComponent::onMapperReady()
208  {
209  if (sGui && sGui->isShuttingDown()) { return; }
210  if (!sGui || !sGui->getIContextSimulator())
211  {
212  ui->led_MapperReady->setOn(false);
213  return;
214  }
215 
216  const int models = sGui->getIContextSimulator()->getModelSetCount();
217  const bool on = (models > 0);
218  ui->led_MapperReady->setOn(on);
219  if (on)
220  {
221  const QString m = QStringLiteral("Mapper with %1 models").arg(models);
222  ui->led_MapperReady->setToolTip(m);
223  }
224  }
225 
226  void CInfoBarStatusComponent::onPttChanged(bool enabled) { ui->led_Ptt->setOn(enabled); }
227 
228  void CInfoBarStatusComponent::updateValues()
229  {
230  if (!sGui || sGui->isShuttingDown()) { return; }
231 
232  const IContextSimulator *simCon = sGui->getIContextSimulator();
233  if (simCon)
234  {
235 
236  this->onSimulatorStatusChanged(simCon->getSimulatorStatus());
237  if (simCon->getModelSetCount() > 0) { this->onMapperReady(); }
238  }
239 
240  if (sGui->getIContextNetwork()) { ui->led_Network->setOn(sGui->getIContextNetwork()->isConnected()); }
241 
243  {
244  ui->led_DBus->setOn(sGui->getIContextApplication()->isUsingImplementingObject());
245  }
246 
247  // audio context can be empty depending on which side it is called
248  ui->led_Audio->setOn(CInfoBarStatusComponent::isAudioAvailableAndNotMuted());
249  }
250 
251  void CInfoBarStatusComponent::updateSpacing()
252  {
253  if (!sGui || sGui->isShuttingDown() || !sGui->mainApplicationWidget()) { return; }
254  const int w = sGui->mainApplicationWidget()->width();
255  const int s = (w >= 400) ? 6 : 2;
256  this->setSpacing(s);
257  }
258 
259  bool CInfoBarStatusComponent::isAudioAvailableAndNotMuted()
260  {
261  if (!sGui || !sGui->getCContextAudioBase() || sGui->isShuttingDown()) { return false; }
262  if (!sGui->getCContextAudioBase()->isAudioStarted()) { return false; }
264  }
265 } // namespace swift::gui::components
const context::IContextApplication * getIContextApplication() const
Direct access to contexts if a CCoreFacade has been initialized.
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
const context::CContextAudioBase * getCContextAudioBase() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isAudioStarted() const
Is audio started?
bool isUsingImplementingObject() const
Using local implementing object?
Definition: context.h:45
virtual swift::misc::network::CServer getConnectedServer() const =0
Server which is connected, if not connected empty default object.
virtual bool isConnected() const =0
Network connected?
virtual swift::misc::simulation::CSimulatorPluginInfo getSimulatorPluginInfo() const =0
Simulator info, currently loaded plugin.
virtual int getModelSetCount() const =0
Number of installed models in simulator eco system.
virtual ISimulator::SimulatorStatus getSimulatorStatus() const =0
Simulator combined status.
static QWidget * mainApplicationWidget()
Main application window widget.
static void setElidedText(QLabel *label, const QString &text, Qt::TextElideMode mode=Qt::ElideMiddle)
Set elided text.
Definition: guiutility.cpp:893
LedShape
Shapes.
Definition: led.h:51
Info bar displaying status (Network, Simulator, DBus)
void setDBusTooltip(const QString &tooltip)
Tooltip for DBus.
void inputSignal()
Received input signal, or manually trigger.
Value object encapsulating information of a audio device.
Value object encapsulating information about a connection status.
ConnectionStatus getConnectionStatus() const
Get status.
const QString & getName() const
Get name.
Definition: server.h:92
const QString & getDescription() const
Description.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:13
GUI related classes.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30