SXXXXXXX_PyBusMonitor1553/cpp/GrifoScope/GrifoMCS/GADS/GrifoADS/admdebug.cpp
2025-12-17 07:59:30 +01:00

524 lines
13 KiB
C++

#include "AdsDebug.h"
#include <QDockWidget>
#include <QTreeWidget>
#include <QAction>
#include <QMainWindow>
#include <QStatusBar>
#include <QLabel>
#include <QHBoxLayout>
#include <QPlainTextEdit>
#include <QDebug>
#include "time_metrics.h"
#include "itc_multibuffer.h"
//static metricRegistered mShowUpd("dbg-update", 20000);
class MWidget;
class MbWidget;
class StsLed: public QLabel
{
public:
StsLed(const QString& lbl):
QLabel(lbl)
{
level=0;
}
void setLevel(int lvl)
{
if (level==lvl)
return;
level=lvl;
if (level<1)
setStyleSheet("");
if (level<2)
setStyleSheet("background-color: green");
else if (level<3)
setStyleSheet("background-color: yellow");
else
setStyleSheet("background-color: red");
}
int level;
};
struct dbg_widgets_t
{
QDockWidget* dockMetrics;
QDockWidget* dockLog;
QDockWidget* dockBuffers;
MWidget* metricW;
MbWidget* bufferW;
QPlainTextEdit* logW;
StsLed* dlLabel;
int timer_id;
//QWidget* stsLineWidget;
//QHBoxLayout* stsLayout;
StsLed* logErrLabel;
AdsDebug* instance;
int last_log_level;
};
static dbg_widgets_t dbg;
static QPlainTextEdit* dbgQtOutput;
static void my_qdebug_output(QtMsgType type, const char *msg)
{
if (dbgQtOutput)
{
QString tmp;
switch (type) {
case QtDebugMsg:
tmp=QString("[QT]D: %1").arg(msg);
break;
case QtWarningMsg:
tmp=QString("[QT]W: %1").arg(msg);
break;
case QtCriticalMsg:
tmp=QString("[QT]C: %1").arg(msg);
break;
case QtFatalMsg:
tmp=QString("[QT]F: %1").arg(msg);
break;
default:
tmp=QString("[QT]: %1").arg(msg);
}
dbgQtOutput->appendPlainText(tmp);
}
}
class MbWidget: public QTreeWidget
{
public:
int t_id;
MbWidget(QWidget* parent):
QTreeWidget(parent)
{
setObjectName("MOnMbTreeWidget");
this->setHeaderLabels(
QStringList()
<<QString("Name")
<<QString("Produced")
<<QString("Consumed")
<<QString("Not Prod.")
<<QString("Not Cons."));
this->setAlternatingRowColors(true);
{
itc_multibuffer_register* mb=itc_multibuffer_register::root();
for( ; mb; mb=mb->next())
{
QTreeWidgetItem* item=new QTreeWidgetItem(this);
item->setText(0, mb->name());
item->setData(0, Qt::UserRole, (unsigned int)mb);
}
}
//t_id=startTimer(1000);
}
void update()
{
if (!isHidden())
{
QTreeWidgetItem* r=invisibleRootItem();
for(int i=0; i<r->childCount(); ++i)
{
QTreeWidgetItem* c=r->child(i);
itc_multibuffer_register* mb=(itc_multibuffer_register*)c->data(0, Qt::UserRole).toUInt();
if (!mb)
continue;
c->setData(1, Qt::DisplayRole, mb->mb()->produced());
c->setData(2, Qt::DisplayRole, mb->mb()->consumed());
c->setData(3, Qt::DisplayRole, mb->mb()->not_produced());
c->setData(4, Qt::DisplayRole, mb->mb()->not_consumed());
}
}
}
};
class MWidget: public QObject /*: public QTreeWidget*/
{
public:
QTreeWidget w;
QAction* actReset;
QAction* actResetAll;
QAction* actRefresh;
QAction* actResize;
//QLabel stsLabel;
int some_dl_miss;
MWidget(QWidget* parent):
w(parent)
{
setObjectName("MonMetricsWidget");
w.setHeaderLabels(
QStringList()
<<QString("Name")
<<QString("samples")
<<QString("Last")
<<QString("avg")
<<QString("min")
<<QString("max")
<<QString("miss")
<<QString("p-last")
<<QString("p-avg")
<<QString("p-min")
<<QString("p-max")
<<QString("dl-miss")
);
m_update_turn=false;
/*
QTreeWidgetItem* root=new QTreeWidgetItem(this);
root->setText(0, "Time Metrics");
root->setText(1, "");
root->setExpanded(true);
*/
w.setAlternatingRowColors(true);
fillMetrics(metricRegistered::first(), w.invisibleRootItem());
//t_id=startTimer(1000);
actReset=new QAction(QString("Reset Selected"), &w);
actResetAll=new QAction(QString("Reset All"), &w);
actRefresh=new QAction(QString("Refresh"), &w);
actResize=new QAction(QString("Resize"), &w);
w.addAction(actReset);
w.addAction(actResetAll);
w.addAction(actRefresh);
w.addAction(actResize);
w.setContextMenuPolicy(Qt::ActionsContextMenu);
//stsLabel.setText("DL");
//dbg.stsLayout.addWidget(&stsLabel);
some_dl_miss=0;
}
void resize()
{
for(int i=0; i<12; ++i)
w.resizeColumnToContents(i);
}
void fillMetrics(metricRegistered* m, QTreeWidgetItem* p)
{
static int level;
for(; m; m=m->next())
{
QTreeWidgetItem* item=new QTreeWidgetItem(p);
item->setText(0, m->name());
item->setData(0, Qt::UserRole, /*QVariant((unsigned int)m)*/(unsigned int)m);
item->setData(0, Qt::UserRole+1, 0);
item->setToolTip(0,
QString("Deadlines: %1, %2").arg(m->time().get_deadline()).arg(m->period().get_deadline())
);
for(int i=1; i<12; ++i)
item->setData(i, Qt::TextAlignmentRole, Qt::AlignRight);
//if (p)
// p->addChild(item);
++level;
fillMetrics(m->sons(), item);
--level;
}
}
void resetTimes(QTreeWidgetItem* i)
{
if (!i)
return;
QVariant v=i->data(0, Qt::UserRole);
metricRegistered* m=(metricRegistered*)v.toUInt();
if (m)
{
m->reset();
i->setData(0, Qt::UserRole+1, 0);
i->setBackground(0, Qt::NoBrush);
}
for(int c=0; c<i->childCount(); ++c)
{
resetTimes(i->child(c));
}
}
bool updateM(QTreeWidgetItem* i)
{
if (!i)
return false;
unsigned long miss=0;
QVariant v=i->data(0, Qt::UserRole);
metricRegistered* m=(metricRegistered*)v.toUInt();
if (m)
{
i->setData(1, Qt::DisplayRole, (unsigned int)m->samples());
miss=m->time().dl_miss() + m->period().dl_miss();
if (miss)
{
//some_dl_miss=true;
unsigned long n=i->data(0, Qt::UserRole+1).toInt();
if (n==miss)
{
i->setData(0, Qt::BackgroundRole, Qt::yellow);
if (some_dl_miss<3)
some_dl_miss=2;
}
else
{
i->setData(0, Qt::BackgroundRole, Qt::red);
i->setData(0, Qt::UserRole+1, (unsigned int)miss);
some_dl_miss=3;
}
}
i->setData(2, Qt::DisplayRole, m->time().last_us());
i->setData(3, Qt::DisplayRole, m->time().avg_us());
i->setData(4, Qt::DisplayRole, m->time().min_us());
i->setData(5, Qt::DisplayRole, m->time().max_us());
i->setData(6, Qt::DisplayRole, (unsigned int)m->time().dl_miss());
i->setData(7, Qt::DisplayRole, m->period().last_us());
i->setData(8, Qt::DisplayRole, m->period().avg_us());
i->setData(9, Qt::DisplayRole, m->period().min_us());
i->setData(10, Qt::DisplayRole, m->period().max_us());
i->setData(11, Qt::DisplayRole, (unsigned int)m->period().dl_miss());
}
for(int c=0; c<i->childCount(); ++c)
{
bool xx=updateM(i->child(c));
if (xx && miss==0)
{
i->setData(0, Qt::BackgroundRole, Qt::lightGray);
}
}
return miss!=0;
}
void update()
{
if (some_dl_miss>2)
some_dl_miss=2;
if (1) //!w.isHidden())
{
//metricMeasure xx(mShowUpd);
//blockSignals(true);
//setUpdatesEnabled(false);
updateM(w.invisibleRootItem());
m_update_turn=!m_update_turn;
//setUpdatesEnabled(true);
//blockSignals(false);
}
}
bool m_update_turn;
};
AdsDebug::AdsDebug(QObject *parent) :
QObject(parent)
{
}
AdsDebug& AdsDebug::instance()
{
return *dbg.instance;
}
bool AdsDebug::createDebugWindows(QMainWindow *parent)
{
if (dbg.instance)
return false;
dbg.instance=new AdsDebug(parent);
return dbg.instance->create(parent);
}
static void log_(QString msg, int lvl=0)
{
if (!dbg.logW)
{
dbg.logW=new QPlainTextEdit;
dbg.logW->setReadOnly(true);
dbg.logW->setLineWrapMode(QPlainTextEdit::NoWrap);
dbg.logW->setMaximumBlockCount(1000);
dbg.logW->setCenterOnScroll(true);
dbg.logW->setUndoRedoEnabled(false);
dbgQtOutput=dbg.logW;
qInstallMsgHandler(my_qdebug_output);
qDebug()<<"debug log ready";
if (!dbg.logErrLabel)
dbg.logErrLabel=new StsLed("LOG");
}
dbg.logW->appendPlainText(msg);
if (lvl>0)
{
//dbg.logW->setStyleSheet("");
}
dbg.logW->ensureCursorVisible();
//dbg.logErrLabel->setBackgroundRole(QPalette::Highlight);
//dbg.logErrLabel->setForegroundRole(QPalette::HighlightedText);
//dbg.logErrLabel->setStyleSheet("background-color: red;");
//dbg.logErrLabel->setLevel(1);
//dbg.logW->appendPlainText("\n");
if (lvl)
dbg.last_log_level=5;
}
void AdsDebug::log_qmsg(int level, const char* const msg)
{
log_(QString("[%1] %2").arg(level).arg(msg), level);
}
void AdsDebug::log_print(const QString& msg)
{
log_(msg);
}
bool AdsDebug::create(QMainWindow *parent)
{
//dbg.stsLineWidget.setLayout(&dbg.stsLayout);
dbg.dlLabel=new StsLed("DL");
dbg.dockMetrics=new QDockWidget("Dbg: Time Metrics", parent);
dbg.dockMetrics->setObjectName("MonMetricsDockWindow");
dbg.metricW=new MWidget(dbg.dockMetrics);
dbg.dockMetrics->setWidget(&(dbg.metricW->w));
parent->addDockWidget(Qt::BottomDockWidgetArea, dbg.dockMetrics);
dbg.dockBuffers=new QDockWidget("Dbg: Shared Buffers", parent);
dbg.dockBuffers->setObjectName("MonBuffersDockWindow");
dbg.bufferW=new MbWidget(dbg.dockBuffers);
dbg.dockBuffers->setWidget(dbg.bufferW);
parent->addDockWidget(Qt::BottomDockWidgetArea, dbg.dockBuffers);
dbg.dockLog=new QDockWidget("Dbg: Log", parent);
dbg.dockLog->setObjectName("MonLogDockWindow");
if (!dbg.logW)
log_print(" ");
// log_print(QString("Hello fomr Adm Debug Monitor"));
dbg.logW->setParent(dbg.dockLog);
dbg.dockLog->setWidget(dbg.logW);
parent->addDockWidget(Qt::BottomDockWidgetArea, dbg.dockLog);
if (!dbg.logErrLabel)
{
dbg.logErrLabel=new StsLed("LOG");
}
//dbg.logErrLabel.setFrameShape(QFrame::Panel);
//dbg.stsLayout.addWidget(&dbg.logErrLabel);
//dbg.stsLayout.setContentsMargins(0, 0, 0, 0);
QStatusBar* sBar=parent->statusBar();
//sBar->addPermanentWidget(&dbg.metricW->stsLabel);
sBar->addPermanentWidget(dbg.dlLabel);
sBar->addPermanentWidget(dbg.logErrLabel);
//Connection:
connect(dbg.metricW->actResetAll, SIGNAL(triggered()), SLOT(resetAllTimesMetrics()));
connect(dbg.metricW->actReset, SIGNAL(triggered()), SLOT(resetSelectedTimesMetrics()));
connect(dbg.metricW->actResize, SIGNAL(triggered()), SLOT(resizeTimesMetrics()));
//dbgQtOutput=dbg.logW;
//qInstallMsgHandler(my_qdebug_output);
//qDebug()<<"debug log ready";
return true;
}
void AdsDebug::resizeTimesMetrics()
{
dbg.metricW->resize();
}
void AdsDebug::resetAllTimesMetrics()
{
log_print(QString("Reset all time metrics"));
dbg.metricW->resetTimes(dbg.metricW->w.invisibleRootItem());
}
void AdsDebug::resetSelectedTimesMetrics()
{
dbg.metricW->resetTimes(dbg.metricW->w.currentItem());
}
void AdsDebug::startMonitoring(unsigned int interval_ms)
{
dbg.timer_id=dbg.instance->startTimer(interval_ms);
}
void AdsDebug::timerEvent(QTimerEvent *)
{
dbg.metricW->update();
dbg.bufferW->update();
if (dbg.metricW->some_dl_miss)
{
dbg.dlLabel->setLevel(dbg.metricW->some_dl_miss);
//dbg.dlLabel->setBackgroundRole(QPalette::Highlight);
//dbg.dlLabel->setForegroundRole(QPalette::HighlightedText);
}
if (dbg.last_log_level>3)
{
dbg.logErrLabel->setLevel(3);
--dbg.last_log_level;
}
else if (dbg.last_log_level>2)
{
dbg.logErrLabel->setLevel(2);
--dbg.last_log_level;
}
}
AdsDebug::~AdsDebug()
{
}
void AdsDebug::destroyDebugWindow()
{
qInstallMsgHandler(0);
if (!dbg.instance)
return;
dbg.instance->killTimer(dbg.timer_id);
delete dbg.instance;
dbg.instance=0;
}