27 #include <QButtonGroup>  28 #include <QRadioButton>  35 #include <qwt_plot_renderer.h>  48  module_panel->updateBlockInfo();
  51  module_panel->updateBlockChannels(
  52  std::any_cast<RT::Thread*>(event->
getParam(
"thread")));
  53  module_panel->updateBlockInfo();
  56  module_panel->updateBlockChannels(
  57  std::any_cast<RT::Device*>(event->
getParam(
"device")));
  58  module_panel->updateBlockInfo();
  65 void Oscilloscope::Panel::updateChannelScale(
IO::endpoint probe_info)
  67  const auto scale = this->scalesList->currentData().value<
double>();
  68  this->scopeWindow->setChannelScale(probe_info, scale);
  71 void Oscilloscope::Panel::updateChannelOffset(
IO::endpoint probe_info)
  73  const double chanoffset = this->offsetsEdit->text().toDouble()
  74  * offsetsList->currentData().value<
double>();
  75  this->scopeWindow->setChannelOffset(probe_info, chanoffset);
  81  pen.setColor(this->colorsList->currentData().value<QColor>());
  82  pen.setWidth(this->widthsList->currentData().value<
int>());
  83  pen.setStyle(this->stylesList->currentData().value<Qt::PenStyle>());
  84  this->scopeWindow->setChannelPen(
endpoint, pen);
  87 void Oscilloscope::Panel::updateChannelLabel(
IO::endpoint probe_info)
  89  const QString chanlabel = QString::number(probe_info.
block->
getID()) + 
" "  91  + this->scalesList->currentText();
  93  this->scopeWindow->setChannelLabel(probe_info, chanlabel);
  96 void Oscilloscope::Panel::updateWindowTimeDiv()
  98  auto divt = this->timesList->currentData().value<int64_t>();
  99  this->scopeWindow->setDivT(divt);
  102 void Oscilloscope::Panel::enableChannel()
  105  if (!this->activateButton->isChecked()) {
  110  auto* oscilloscope_plugin =
  112  auto* chanblock = this->blocksListDropdown->currentData().value<
IO::Block*>();
  113  auto chanport = this->channelsList->currentData().value<
size_t>();
  114  auto chandirection = this->typesList->currentData().value<
IO::flags_t>();
  120  if (probe_fifo == 
nullptr) {
  122  "Oscilloscope::Panel::enableChannel Unable to create probing channel "  124  chanblock->getName());
  128  this->scopeWindow->createChannel(
endpoint, probe_fifo);
  131  this->updateChannelOffset(
endpoint);
  136 void Oscilloscope::Panel::disableChannel()
  139  if (!this->activateButton->isChecked()) {
  143  auto* oscilloscope_plugin =
  145  auto* chanblock = this->blocksListDropdown->currentData().value<
IO::Block*>();
  146  auto chanport = this->channelsList->currentData().value<
size_t>();
  147  auto chandirection = this->typesList->currentData().value<
IO::flags_t>();
  149  const IO::endpoint probe {chanblock, chanport, chandirection};
  151  this->scopeWindow->removeChannel(probe);
  152  oscilloscope_plugin->deleteProbe(probe);
  155 void Oscilloscope::Panel::activateChannel(
bool active)
  158  active && blocksListDropdown->count() > 0 && channelsList->count() > 0;
  159  scalesList->setEnabled(enable);
  160  offsetsEdit->setEnabled(enable);
  161  offsetsList->setEnabled(enable);
  162  colorsList->setEnabled(enable);
  163  widthsList->setEnabled(enable);
  164  stylesList->setEnabled(enable);
  165  this->activateButton->setChecked(enable);
  168 void Oscilloscope::Panel::apply()
  170  switch (tabWidget->currentIndex()) {
  178  ERROR_MSG(
"Oscilloscope::Panel::showTab : invalid tab\n");
  182 void Oscilloscope::Panel::buildChannelList()
  184  if (blocksListDropdown->count() <= 0) {
  188  if (blocksListDropdown->currentIndex() < 0) {
  189  blocksListDropdown->setCurrentIndex(0);
  192  auto* block = this->blocksListDropdown->currentData().value<
IO::Block*>();
  193  auto type = this->typesList->currentData().value<
IO::flags_t>();
  194  channelsList->clear();
  195  for (
size_t i = 0; i < block->getCount(type); ++i) {
  196  channelsList->addItem(QString(block->getChannelName(type, i).c_str()),
  197  QVariant::fromValue(i));
  199  channelsList->setCurrentIndex(0);
  203 void Oscilloscope::Panel::showTab(
int index)
  213  ERROR_MSG(
"Oscilloscope::Panel::showTab : invalid tab\n");
  223 void Oscilloscope::Panel::applyChannelTab()
  225  if (this->blocksListDropdown->count() <= 0
  226  || this->channelsList->count() <= 0) {
  230  auto* block = this->blocksListDropdown->currentData().value<
IO::Block*>();
  231  auto port = this->channelsList->currentData().value<
size_t>();
  232  auto type = this->typesList->currentData().value<
IO::flags_t>();
  236  this->scopeWindow->setPause(
true);
  237  if (!activateButton->isChecked()) {
  238  scopeWindow->removeChannel(probeInfo);
  239  host_plugin->deleteProbe(probeInfo);
  241  if (!this->scopeWindow->channelRegistered(probeInfo)) {
  242  RT::OS::Fifo* fifo = host_plugin->createProbe(probeInfo);
  243  if (fifo != 
nullptr) {
  244  this->scopeWindow->createChannel(probeInfo, fifo);
  247  this->updateChannelScale(probeInfo);
  248  this->updateChannelOffset(probeInfo);
  249  this->updateChannelPen(probeInfo);
  250  this->updateChannelLabel(probeInfo);
  252  scopeWindow->replot();
  253  this->scopeWindow->setPause(
false);
  254  this->syncChannelProperties();
  258 void Oscilloscope::Panel::applyDisplayTab()
  261  updateWindowTimeDiv();
  262  scopeWindow->replot();
  266 void Oscilloscope::Panel::buildBlockList()
  269  this->getRTXIEventManager()->postEvent(&event);
  271  std::any_cast<std::vector<IO::Block*>>(
event.getParam(
"blockList"));
  272  auto* previous_block =
  273  this->blocksListDropdown->currentData().value<
IO::Block*>();
  274  blocksListDropdown->clear();
  275  for (
auto* block : blocklist) {
  278  if (block->getName().find(
"Probe") != std::string::npos
  279  || block->getName().find(
"Recording") != std::string::npos)
  283  this->blocksListDropdown->addItem(QString(block->getName().c_str()) + 
" "  284  + QString::number(block->getID()),
  285  QVariant::fromValue(block));
  287  blocksListDropdown->setCurrentIndex(
  288  this->blocksListDropdown->findData(QVariant::fromValue(previous_block)));
  291 QWidget* Oscilloscope::Panel::createChannelTab(QWidget* parent)
  294  "<p><b>Oscilloscope: Channel Options</b><br>"  295  "Use the dropdown boxes to select the signal streams you want to plot "  297  "any loaded modules or your DAQ device. You may change the plotting "  299  "the signal, apply a DC offset, and change the color and style of the "  302  auto* page = 
new QWidget(parent);
  305  auto* bttnLayout = 
new QGridLayout(page);
  308  auto* row1Layout = 
new QHBoxLayout;
  309  auto* channelLabel = 
new QLabel(tr(
"Channel:"), page);
  310  row1Layout->addWidget(channelLabel);
  311  blocksListDropdown = 
new QComboBox(page);
  312  blocksListDropdown->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  313  blocksListDropdown->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  314  QObject::connect(blocksListDropdown,
  315  SIGNAL(activated(
int)),
  317  SLOT(buildChannelList()));
  318  row1Layout->addWidget(blocksListDropdown);
  321  typesList = 
new QComboBox(page);
  322  typesList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  323  typesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  324  typesList->addItem(
"Output", QVariant::fromValue(
IO::OUTPUT));
  325  typesList->addItem(
"Input", QVariant::fromValue(
IO::INPUT));
  326  row1Layout->addWidget(typesList);
  328  typesList, SIGNAL(activated(
int)), 
this, SLOT(buildChannelList()));
  331  channelsList = 
new QComboBox(page);
  332  channelsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  333  channelsList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  335  channelsList, SIGNAL(activated(
int)), 
this, SLOT(showChannelTab()));
  336  row1Layout->addWidget(channelsList);
  339  row1Layout->addSpacerItem(
  340  new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
  341  auto* scaleLabel = 
new QLabel(tr(
"Scale:"), page);
  342  row1Layout->addWidget(scaleLabel);
  343  scalesList = 
new QComboBox(page);
  344  row1Layout->addWidget(scalesList);
  345  const QFont scalesListFont(
"DejaVu Sans Mono");
  346  const QString postfix = 
"/div";
  347  std::array<std::string, 6> unit_array = {
"V", 
"mV", 
"µV", 
"nV", 
"pV", 
"fV"};
  348  size_t unit_array_index = 0;
  349  const std::array<double, 4> fixed_values = {10, 5, 2.5, 2};
  350  double value_scale = 1.0;
  351  scalesList->setFont(scalesListFont);
  352  const std::string formatting = 
"{:.1f} {}/div";
  353  double temp_value = 0.0;
  354  while (unit_array_index < unit_array.size()) {
  355  for (
auto current_fixed_value : fixed_values) {
  357  current_fixed_value * std::pow(1e3, unit_array_index) * value_scale;
  358  if (temp_value < 1) {
  360  if (unit_array_index >= 6) {
  364  current_fixed_value * std::pow(1e3, unit_array_index) * value_scale;
  368  formatting, temp_value, unit_array.at(unit_array_index))
  370  current_fixed_value * value_scale);
  372  value_scale = value_scale / 10.0;
  375  auto* offsetLabel = 
new QLabel(tr(
"Offset:"), page);
  376  row1Layout->addWidget(offsetLabel);
  377  offsetsEdit = 
new QLineEdit(page);
  378  offsetsEdit->setMaximumWidth(offsetsEdit->minimumSizeHint().width() * 2);
  379  offsetsEdit->setValidator(
new QDoubleValidator(offsetsEdit));
  380  row1Layout->addWidget(offsetsEdit); 
  381  offsetsList = 
new QComboBox(page);
  382  row1Layout->addWidget(offsetsList); 
  383  offsetsList->addItem(
"V", 1.0);
  384  offsetsList->addItem(
"mV", 1e-3);
  385  offsetsList->addItem(QString::fromUtf8(
"µV"), 1e-6);
  386  offsetsList->addItem(
"nV", 1e-9);
  387  offsetsList->addItem(
"pV", 1e-12);
  390  auto* row2Layout = 
new QHBoxLayout; 
  391  row2Layout->setAlignment(Qt::AlignLeft);
  392  auto* colorLabel = 
new QLabel(tr(
"Color:"), page);
  393  row2Layout->addWidget(colorLabel);
  394  colorsList = 
new QComboBox(page);
  395  colorsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  396  colorsList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  397  row2Layout->addWidget(colorsList);
  399  std::string color_name;
  400  for (
size_t i = 0; i < 
penColors.size(); i++) {
  407  auto* widthLabel = 
new QLabel(tr(
"Width:"), page);
  408  row2Layout->addWidget(widthLabel);
  409  widthsList = 
new QComboBox(page);
  410  widthsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  411  widthsList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  412  row2Layout->addWidget(widthsList);
  414  QPainter painter(&tmp);
  415  for (
int i = 1; i < 6; i++) {
  418  painter.drawLine(0, 12, 25, 12);
  419  widthsList->addItem(tmp, QString::number(i) + QString(
" Pixels"), i);
  423  auto* styleLabel = 
new QLabel(tr(
"Style:"), page);
  424  row2Layout->addWidget(styleLabel);
  425  stylesList = 
new QComboBox(page);
  426  stylesList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  427  stylesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  428  row2Layout->addWidget(stylesList);
  429  std::string temp_name;
  437  painter.drawLine(0, 12, 25, 12);
  438  stylesList->addItem(tmp,
  439  QString(temp_name.c_str()),
  444  row2Layout->addSpacerItem(
  445  new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
  446  activateButton = 
new QPushButton(
"Enable Channel", page);
  447  row2Layout->addWidget(activateButton);
  448  activateButton->setCheckable(
true);
  449  activateButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  451  activateButton, SIGNAL(toggled(
bool)), 
this, SLOT(activateChannel(
bool)));
  452  activateChannel(
false);
  454  bttnLayout->addLayout(row1Layout, 0, 0);
  455  bttnLayout->addLayout(row2Layout, 1, 0);
  457  QObject::connect(blocksListDropdown,
  458  SIGNAL(currentTextChanged(
const QString&)),
  460  SLOT(syncChannelProperties()));
  461  QObject::connect(typesList,
  462  SIGNAL(currentTextChanged(
const QString&)),
  464  SLOT(syncChannelProperties()));
  465  QObject::connect(channelsList,
  466  SIGNAL(currentTextChanged(
const QString&)),
  468  SLOT(syncChannelProperties()));
  472 QWidget* Oscilloscope::Panel::createDisplayTab(QWidget* parent)
  475  "<p><b>Oscilloscope: Display Options</b><br>"  476  "Use the dropdown box to select the time scale for the Oscilloscope. "  478  "scaling is applied to all signals plotted in the same window. You may "  480  "set a trigger on any signal that is currently plotted in the window. A "  482  "line will appear at the trigger threshold.</p>");
  484  auto* page = 
new QWidget(parent);
  487  auto* displayTabLayout = 
new QGridLayout(page);
  490  auto* row1Layout = 
new QHBoxLayout;
  491  row1Layout->addWidget(
new QLabel(tr(
"Time/Div:"), page));
  492  timesList = 
new QComboBox(page);
  493  row1Layout->addWidget(timesList);
  494  const QFont timeListFont(
"DejaVu Sans Mono");
  495  timesList->setFont(timeListFont);
  496  timesList->addItem(
"5 s/div", QVariant::fromValue(5000000000));
  497  timesList->addItem(
"2 s/div", QVariant::fromValue(2000000000));
  498  timesList->addItem(
"1 s/div", QVariant::fromValue(1000000000));
  499  timesList->addItem(
"500 ms/div", QVariant::fromValue(500000000));
  500  timesList->addItem(
"200 ms/div", QVariant::fromValue(200000000));
  501  timesList->addItem(
"100 ms/div", QVariant::fromValue(100000000));
  502  timesList->addItem(
"50 ms/div", QVariant::fromValue(50000000));
  503  timesList->addItem(
"20 ms/div", QVariant::fromValue(20000000));
  504  timesList->addItem(
"10 ms/div", QVariant::fromValue(10000000));
  505  timesList->addItem(
"5 ms/div", QVariant::fromValue(5000000));
  506  timesList->addItem(
"2 ms/div", QVariant::fromValue(2000000));
  507  timesList->addItem(
"1 ms/div", QVariant::fromValue(1000000));
  508  timesList->addItem(QString::fromUtf8(
"500 µs/div"),
  509  QVariant::fromValue(500000));
  510  timesList->addItem(QString::fromUtf8(
"200 µs/div"),
  511  QVariant::fromValue(200000));
  512  timesList->addItem(QString::fromUtf8(
"100 µs/div"),
  513  QVariant::fromValue(100000));
  514  timesList->addItem(QString::fromUtf8(
"50 µs/div"),
  515  QVariant::fromValue(50000));
  516  timesList->addItem(QString::fromUtf8(
"20 µs/div"),
  517  QVariant::fromValue(20000));
  518  timesList->addItem(QString::fromUtf8(
"10 µs/div"),
  519  QVariant::fromValue(10000));
  520  timesList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  521  timesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  523  auto* refreshLabel = 
new QLabel(tr(
"Refresh:"), page);
  524  row1Layout->addWidget(refreshLabel);
  525  refreshDropdown = 
new QComboBox(page);
  526  row1Layout->addWidget(refreshDropdown);
  527  refreshDropdown->addItem(
"60 Hz",
  529  refreshDropdown->addItem(
  531  refreshDropdown->addItem(
  535  row1Layout->addSpacerItem(
  536  new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
  537  auto* bufferLabel = 
new QLabel(tr(
"Buffer Size (MB):"), page);
  538  row1Layout->addWidget(bufferLabel);
  539  sizesEdit = 
new QLineEdit(page);
  540  sizesEdit->setMaximumWidth(sizesEdit->minimumSizeHint().width() * 3);
  541  sizesEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
  542  row1Layout->addWidget(sizesEdit);
  543  const auto total_bytes = 
static_cast<double>(scopeWindow->getDataSize()
  545  sizesEdit->setText(QString::number(total_bytes / 1e6));
  546  sizesEdit->setEnabled(
false);
  549  auto* row2Layout = 
new QHBoxLayout;
  550  row2Layout->addWidget(
new QLabel(tr(
"Edge:"), page));
  551  trigsGroup = 
new QButtonGroup(page);
  553  auto* off = 
new QRadioButton(tr(
"Off"), page);
  555  row2Layout->addWidget(off);
  556  auto* plus = 
new QRadioButton(tr(
"+"), page);
  558  row2Layout->addWidget(plus);
  559  auto* minus = 
new QRadioButton(tr(
"-"), page);
  561  row2Layout->addWidget(minus);
  563  row2Layout->addWidget(
new QLabel(tr(
"Channel:"), page));
  564  trigsChanList = 
new QComboBox(page);
  565  trigsChanList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  566  trigsChanList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  567  row2Layout->addWidget(trigsChanList);
  569  row2Layout->addWidget(
new QLabel(tr(
"Threshold:"), page));
  570  trigsThreshEdit = 
new QLineEdit(page);
  571  trigsThreshEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
  572  trigsThreshEdit->setMaximumWidth(trigsThreshEdit->minimumSizeHint().width()
  574  row2Layout->addWidget(trigsThreshEdit);
  575  trigsThreshEdit->setValidator(
new QDoubleValidator(trigsThreshEdit));
  576  trigsThreshList = 
new QComboBox(page);
  577  trigsThreshList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  578  row2Layout->addWidget(trigsThreshList);
  579  trigsThreshList->addItem(
"V", 1.0);
  580  trigsThreshList->addItem(
"mV", 1e-3);
  581  trigsThreshList->addItem(QString::fromUtf8(
"µV"), 1e-6);
  582  trigsThreshList->addItem(
"nV", 1e-9);
  583  trigsThreshList->addItem(
"pV", 1e-12);
  603  displayTabLayout->addLayout(row1Layout, 0, 0);
  604  displayTabLayout->addLayout(row2Layout, 1, 0);
  609 void Oscilloscope::Panel::syncBlockInfo()
  611  this->buildBlockList();
  612  this->buildChannelList();
  613  this->showChannelTab();
  616 void Oscilloscope::Panel::showChannelTab()
  618  auto type = 
static_cast<IO::flags_t>(this->typesList->currentData().toInt());
  619  auto* block = this->blocksListDropdown->currentData().value<
IO::Block*>();
  620  auto port = this->channelsList->currentData().value<
size_t>();
  622  const double scale = this->scopeWindow->getChannelScale(chan);
  623  double offset = this->scopeWindow->getChannelOffset(chan);
  624  scalesList->setCurrentIndex(
  625  static_cast<int>(round(4 * (log10(1 / scale) + 1))));
  627  if (offset * std::pow(10, -3 * offsetsList->count() - 3) < 1) {
  631  while (fabs(offset) < 1 && offsetUnits < offsetsList->count()) {
  636  offsetsEdit->setText(QString::number(offset));
  637  offsetsList->setCurrentIndex(offsetUnits);
  638  this->activateButton->setChecked(this->scopeWindow->channelRegistered(chan));
  641 void Oscilloscope::Panel::showDisplayTab()
  643  timesList->setCurrentIndex(
  644  timesList->findData(QVariant::fromValue(this->scopeWindow->getDivT())));
  648  auto* oscilloscope_plugin =
  650  trigger_endpoint = this->scopeWindow->getTriggerEndpoint();
  651  this->trigsGroup->button(
static_cast<int>(trigger_endpoint.
direction))
  654  trigsChanList->clear();
  655  std::vector<IO::endpoint> endpoint_list;
  656  if (oscilloscope_plugin != 
nullptr) {
  657  endpoint_list = oscilloscope_plugin->getTrackedEndpoints();
  659  std::string direction_str;
  660  for (
const auto& 
endpoint : endpoint_list) {
  663  + QString(direction_str.c_str()) + 
" "  667  trigsChanList->addItem(
"<None>");
  669  const int triglist_index =
  670  trigsChanList->findData(QVariant::fromValue(trigger_endpoint));
  671  trigsChanList->setCurrentIndex(triglist_index);
  673  int trigThreshUnits = 0;
  674  double trigThresh = this->scopeWindow->getTriggerThreshold();
  675  if (trigThresh * std::pow(10, -3 * this->trigsThreshList->count() - 1) < 1) {
  679  while (fabs(trigThresh) < 1
  680  && trigThreshUnits < this->trigsThreshList->count()) {
  685  trigsThreshList->setCurrentIndex(trigThreshUnits);
  686  trigsThreshEdit->setText(QString::number(trigThresh));
  688  sizesEdit->setText(QString::number(scopeWindow->getDataSize()));
  693  , tabWidget(new QTabWidget)
  694  , scopeWindow(new 
Scope(this))
  695  , layout(new QVBoxLayout)
  696  , scopeGroup(new QWidget(this))
  697  , setBttnGroup(new QGroupBox(this))
  700  "<p><b>Oscilloscope:</b><br>The Oscilloscope allows you to plot any "  702  "in your workspace in real-time, including signals from your DAQ card "  704  "generated by user modules. Multiple signals are overlaid in the window "  706  "different line colors and styles can be selected. When a signal is "  708  "automatically appears in the bottom of the window. Multiple "  710  "be instantiated to give you multiple data windows. To select signals "  712  "use the right-click context \"Panel\" menu item. After selecting a "  714  "click the \"Enable\" button for it to appear in the window. To change "  716  "you must click the \"Apply\" button. The right-click context \"Pause\" "  718  "allows you to start and stop real-time plotting.</p>");
  721  tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  723  tabWidget, SIGNAL(currentChanged(
int)), 
this, SLOT(showTab(
int)));
  725  auto* scopeLayout = 
new QHBoxLayout(
this);
  726  scopeLayout->addWidget(scopeWindow);
  727  scopeGroup->setLayout(scopeLayout);
  728  auto* setBttnLayout = 
new QHBoxLayout(
this);
  731  pauseButton = 
new QPushButton(
"Pause");
  732  pauseButton->setCheckable(
true);
  733  QObject::connect(pauseButton, SIGNAL(released()), 
this, SLOT(
togglePause()));
  734  setBttnLayout->addWidget(pauseButton);
  735  applyButton = 
new QPushButton(
"Apply");
  736  QObject::connect(applyButton, SIGNAL(released()), 
this, SLOT(apply()));
  737  setBttnLayout->addWidget(applyButton);
  738  settingsButton = 
new QPushButton(
"Screenshot");
  740  settingsButton, SIGNAL(released()), 
this, SLOT(screenshot()));
  741  setBttnLayout->addWidget(settingsButton);
  744  setBttnGroup->setLayout(setBttnLayout);
  747  tabWidget->setTabPosition(QTabWidget::North);
  748  tabWidget->addTab(createChannelTab(
this), 
"Channel");
  749  tabWidget->addTab(createDisplayTab(
this), 
"Display");
  752  layout->addWidget(scopeGroup);
  753  layout->addWidget(tabWidget);
  754  layout->addWidget(setBttnGroup);
  762  getMdiWindow()->setMinimumSize(this->minimumSizeHint().width(), 450);
  763  getMdiWindow()->resize(this->minimumSizeHint().width() + 50, 600);
  768  auto* otimer = 
new QTimer(
this);
  769  otimer->setTimerType(Qt::PreciseTimer);
  772  qRegisterMetaType<IO::Block*>(
"IO::Block*");
  773  QObject::connect(
this,
  776  &Oscilloscope::Panel::removeBlockChannels);
  781  this->buildChannelList();
  782  scopeWindow->replot();
  786  const std::string& probe_name)
  793  ERROR_MSG(
"Unable to create xfifo for Oscilloscope Component {}",
  802  switch (this->getState()) {
  821 void Oscilloscope::Panel::screenshot()
  823  QwtPlotRenderer renderer;
  824  renderer.exportTo(scopeWindow, 
"screenshot.pdf");
  829  this->scopeWindow->setPause(this->pauseButton->isChecked());
  858 void Oscilloscope::Panel::removeBlockChannels(
IO::Block* block)
  860  this->scopeWindow->removeBlockChannels(block);
  865 void Oscilloscope::Panel::syncChannelProperties()
  868  probe_info.
block = blocksListDropdown->currentData().value<
IO::Block*>();
  870  probe_info.
port = channelsList->currentData().value<
size_t>();
  873  if (!scopeWindow->channelRegistered(probe_info)) {
  877  const QColor color = scopeWindow->getChannelColor(probe_info);
  878  colorsList->setCurrentIndex(colorsList->findData(color));
  879  const int width = scopeWindow->getChannelWidth(probe_info);
  880  widthsList->setCurrentIndex(widthsList->findData(width));
  881  const Qt::PenStyle style = scopeWindow->getChannelStyle(probe_info);
  882  stylesList->setCurrentIndex(stylesList->findData(QVariant::fromValue(style)));
  883  double offset = scopeWindow->getChannelOffset(probe_info);
  884  const double scale = scopeWindow->getChannelScale(probe_info);
  885  scalesList->setCurrentIndex(
  886  static_cast<int>(round(4 * (log10(1 / scale) + 1))));
  888  if (offset * std::pow(10, -3 * offsetsList->count() - 3) < 1) {
  892  while (fabs(offset) < 1 && offsetUnits < offsetsList->count()) {
  897  offsetsEdit->setText(QString::number(offset));
  898  offsetsList->setCurrentIndex(offsetUnits);
  908  std::vector<Event::Object> unloadEvents;
  909  for (
auto& registry_entry : this->m_component_registry) {
  911  unloadEvents.back().setParam(
  913  std::any(
static_cast<RT::Thread*
>(registry_entry.component.get())));
  915  this->getEventManager()->postEvent(unloadEvents);
  921  auto probe_loc = std::find_if(this->m_component_registry.begin(),
  922  this->m_component_registry.end(),
  923  [&](
const registry_entry_t& entry)
  924  { return entry.endpoint == probe_info; });
  925  if (probe_loc != this->m_component_registry.end()) {
  926  return probe_loc->component->getFifoPtr();
  928  const std::string comp_name =
  929  fmt::format(
"{} Probe for Block {} Channel {} {} with Id {} ",
  935  this->m_component_registry.push_back(
  936  {probe_info, std::make_unique<Oscilloscope::Component>(
this, comp_name)});
  938  this->m_component_registry.back().component.get();
  944  connection.
dest = measuring_component;
  946  std::vector<Event::Object> events;
  948  events.back().setParam(
  949  "thread", std::any(
static_cast<RT::Thread*
>(measuring_component)));
  951  events.back().setParam(
"connection", std::any(connection));
  952  this->getEventManager()->postEvent(events);
  960  auto probe_loc = std::find_if(this->m_component_registry.begin(),
  961  this->m_component_registry.end(),
  962  [&](
const registry_entry_t& entry)
  963  { return entry.endpoint == probe_info; });
  964  if (probe_loc == this->m_component_registry.end()) {
  969  event.setParam(
"thread",
  970  std::any(
static_cast<RT::Thread*
>(measuring_component)));
  971  this->getEventManager()->postEvent(&event);
  972  this->m_component_registry.erase(probe_loc);
  977  std::vector<IO::endpoint> all_endpoints;
  978  for (
auto& entry : this->m_component_registry) {
  979  if (entry.endpoint.block == block) {
  980  all_endpoints.push_back(entry.endpoint);
  983  for (
auto endpoint : all_endpoints) {
  991  auto probe_loc = std::find_if(this->m_component_registry.begin(),
  992  this->m_component_registry.end(),
  993  [&](
const registry_entry_t& entry)
  994  { return entry.endpoint == endpoint; });
  995  if (probe_loc == this->m_component_registry.end()) {
  1003  static_cast<RT::Thread*
>(probe_loc->component.get()));
  1004  this->getEventManager()->postEvent(&activity_event);
  1009  std::vector<IO::endpoint> result;
  1010  result.reserve(this->m_component_registry.size());
  1011  for (
const auto& entry : this->m_component_registry) {
  1012  result.push_back(entry.endpoint);
  1019  std::vector<Event::Object> events;
  1020  events.reserve(this->m_component_registry.size());
  1024  for (
const auto& entry : this->m_component_registry) {
  1025  events.emplace_back(event_type);
  1026  events.back().setParam(
"thread",
  1027  static_cast<RT::Thread*
>(entry.component.get()));
  1029  this->getEventManager()->postEvent(events);
  1035  auto iter = std::find_if(this->m_component_registry.begin(),
  1036  this->m_component_registry.end(),
  1037  [&](
const registry_entry_t& entry)
  1038  { return entry.endpoint == endpoint; });
  1039  if (iter == this->m_component_registry.end()) {
  1042  return iter->component.get();
  1048  return std::make_unique<Oscilloscope::Plugin>(ev_manager);
  1061  return std::unique_ptr<Oscilloscope::Component>(
nullptr);
 void setParam(const std::string ¶m_name, const std::any ¶m_value)
Event::Type getType() const
std::any getParam(const std::string ¶m_name) const
std::string getName() const
Component(Widgets::Plugin *hplugin, const std::string &probe_name)
RT::OS::Fifo * getFifoPtr()
void updateBlockChannels(IO::Block *block)
Panel(QMainWindow *mw, Event::Manager *ev_manager)
void setActivity(IO::endpoint endpoint, bool activity)
Plugin(Event::Manager *ev_manager)
void receiveEvent(Event::Object *event) override
void setProbeActivity(IO::endpoint endpoint, bool activity)
void deleteProbe(IO::endpoint probe_info)
Oscilloscope::Component * getProbeComponentPtr(IO::endpoint endpoint)
RT::OS::Fifo * createProbe(IO::endpoint probe_info)
std::vector< IO::endpoint > getTrackedEndpoints()
void setAllProbesActivity(bool activity)
void deleteAllProbes(IO::Block *block)
virtual int64_t writeRT(void *buf, size_t data_size)=0
virtual int64_t read(void *buf, size_t data_size)=0
void ERROR_MSG(const std::string &errmsg, Args... args)
@ RT_THREAD_UNPAUSE_EVENT
struct IO::endpoint endpoint
constexpr std::array< std::string_view, 7 > color2string
constexpr std::string_view MODULE_NAME
struct Oscilloscope::sample sample
constexpr std::array< Qt::PenStyle, 5 > penStyles
std::unique_ptr< Widgets::Plugin > createRTXIPlugin(Event::Manager *ev_manager)
Widgets::FactoryMethods getFactories()
constexpr std::array< std::string_view, 5 > penstyles2string
const std::array< QColor, 7 > penColors
constexpr size_t DEFAULT_BUFFER_SIZE
std::unique_ptr< Widgets::Component > createRTXIComponent(Widgets::Plugin *host_plugin)
std::vector< Widgets::Variable::Info > get_default_vars()
Widgets::Panel * createRTXIPanel(QMainWindow *main_window, Event::Manager *ev_manager)
std::vector< IO::channel_t > get_default_channels()
int getFifo(std::unique_ptr< Fifo > &fifo, size_t fifo_size)
IO::flags_t src_port_type