diff --git a/client/icons/stream_stats.png b/client/icons/stream_stats.png new file mode 100644 index 0000000..ab92010 Binary files /dev/null and b/client/icons/stream_stats.png differ diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 212fdcf..782717a 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -76,7 +76,7 @@ MainWindow::MainWindow(QWidget *parent) portsDock->setObjectName("portsDock"); portsDock->setFeatures( portsDock->features() & ~QDockWidget::DockWidgetClosable); - statsDock = new QDockWidget(tr("Statistics"), this); + statsDock = new QDockWidget(tr("Port Statistics"), this); statsDock->setObjectName("statsDock"); statsDock->setFeatures( statsDock->features() & ~QDockWidget::DockWidgetClosable); @@ -133,6 +133,12 @@ MainWindow::~MainWindow() delete pgl; + // We don't want to save state for Stream Stats Docks - so close them + QList streamStatsDocks + = findChildren("streamStatsDock"); + foreach(QDockWidget *dock, streamStatsDocks) + dock->close(); // this dock is already set to delete on close + QByteArray layout = saveState(0); appSettings->setValue(kApplicationWindowLayout, layout); appSettings->setValue(kApplicationWindowGeometryKey, geometry()); diff --git a/client/ostinato.pro b/client/ostinato.pro index e4773ea..800f91a 100644 --- a/client/ostinato.pro +++ b/client/ostinato.pro @@ -58,6 +58,8 @@ HEADERS += \ streamconfigdialog.h \ streamlistdelegate.h \ streammodel.h \ + streamstatsmodel.h \ + streamstatswindow.h \ variablefieldswidget.h FORMS += \ @@ -71,6 +73,7 @@ FORMS += \ portswindow.ui \ preferences.ui \ streamconfigdialog.ui \ + streamstatswindow.ui \ variablefieldswidget.ui SOURCES += \ @@ -99,6 +102,8 @@ SOURCES += \ streamconfigdialog.cpp \ streamlistdelegate.cpp \ streammodel.cpp \ + streamstatsmodel.cpp \ + streamstatswindow.cpp \ variablefieldswidget.cpp diff --git a/client/ostinato.qrc b/client/ostinato.qrc index a8c6c5c..df7075b 100644 --- a/client/ostinato.qrc +++ b/client/ostinato.qrc @@ -41,5 +41,6 @@ icons/stream_delete.png icons/stream_duplicate.png icons/stream_edit.png + icons/stream_stats.png diff --git a/client/portgroup.cpp b/client/portgroup.cpp index 8ebe1f5..fe2fe77 100644 --- a/client/portgroup.cpp +++ b/client/portgroup.cpp @@ -1594,3 +1594,46 @@ void PortGroup::processClearStatsAck(PbRpcController *controller) delete controller; } +bool PortGroup::getStreamStats(QList *portList) +{ + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + return false; + + OstProto::StreamGuidList *guidList = new OstProto::StreamGuidList; + OstProto::StreamStatsList *statsList = new OstProto::StreamStatsList; + PbRpcController *controller = new PbRpcController(guidList, statsList); + + if (portList == NULL) + guidList->mutable_port_id_list()->CopyFrom(*portIdList_); + else + for (int i = 0; i < portList->size(); i++) + guidList->mutable_port_id_list()->add_port_id() + ->set_id(portList->at(i)); + + serviceStub->getStreamStats(controller, guidList, statsList, + NewCallback(this, &PortGroup::processStreamStatsList, controller)); + + return true; +} + +void PortGroup::processStreamStatsList(PbRpcController *controller) +{ + using OstProto::StreamStatsList; + + qDebug("In %s", __FUNCTION__); + + StreamStatsList *streamStatsList = + static_cast(controller->response()); + + // XXX: It is required to emit the signal even if the returned + // streamStatsList contains no records since the recipient + // StreamStatsModel slot needs to disconnect this signal-slot + // connection to prevent future stream stats for this portgroup + // to be sent to it + emit streamStatsReceived(mPortGroupId, streamStatsList); + + delete controller; +} + diff --git a/client/portgroup.h b/client/portgroup.h index ef60f09..1f9ab11 100644 --- a/client/portgroup.h +++ b/client/portgroup.h @@ -39,6 +39,7 @@ LOW namespace OstProto { class PortContent; class PortGroupContent; + class StreamStatsList; } class QFile; @@ -164,12 +165,16 @@ public: void processPortStatsList(); void clearPortStats(QList *portList = NULL); void processClearStatsAck(PbRpcController *controller); + bool getStreamStats(QList *portList = NULL); + void processStreamStatsList(PbRpcController *controller); signals: void portGroupDataChanged(int portGroupId, int portId = 0xFFFF); void portListAboutToBeChanged(quint32 portGroupId); void portListChanged(quint32 portGroupId); void statsChanged(quint32 portGroupId); + void streamStatsReceived(quint32 portGroupId, + const OstProto::StreamStatsList *stats); private slots: void on_reconnectTimer_timeout(); diff --git a/client/portstatswindow.cpp b/client/portstatswindow.cpp index 0e7b73f..df9cf3a 100644 --- a/client/portstatswindow.cpp +++ b/client/portstatswindow.cpp @@ -23,9 +23,15 @@ along with this program. If not, see #include "portstatsfilterdialog.h" #include "portstatsmodel.h" #include "portstatsproxymodel.h" +#include "streamstatsmodel.h" +#include "streamstatswindow.h" #include "settings.h" +#include #include +#include + +extern QMainWindow *mainWindow; PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent) : QWidget(parent), proxyStatsModel(NULL) @@ -219,6 +225,38 @@ void PortStatsWindow::on_tbClearAll_clicked() } } +void PortStatsWindow::on_tbGetStreamStats_clicked() +{ + QList portList; + StreamStatsModel *streamStatsModel; + + // Get selected ports + model->portListFromIndex(selectedColumns(), portList); + + if (portList.size()) { + QDockWidget *dock = new QDockWidget(tr("Stream Statistics"), + mainWindow); + streamStatsModel = new StreamStatsModel(dock); + dock->setWidget(new StreamStatsWindow(streamStatsModel, dock)); + dock->setObjectName("streamStatsDock"); + dock->setFloating(true); + dock->setAttribute(Qt::WA_DeleteOnClose); + mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock); + } + + // Get stream stats for selected ports, portgroup by portgroup + for (int i = 0; i < portList.size(); i++) + { + PortGroup &pg = pgl->portGroupByIndex(portList.at(i).portGroupId); + if (pg.getStreamStats(&portList[i].portList)) { + connect(&pg,SIGNAL(streamStatsReceived( + quint32, const OstProto::StreamStatsList*)), + streamStatsModel, SLOT(appendStreamStatsList( + quint32, const OstProto::StreamStatsList*))); + } + } +} + void PortStatsWindow::on_tbFilter_clicked() { bool ok; diff --git a/client/portstatswindow.h b/client/portstatswindow.h index dfb5fbf..717d913 100644 --- a/client/portstatswindow.h +++ b/client/portstatswindow.h @@ -49,6 +49,7 @@ private slots: void on_tbClear_clicked(); void on_tbClearAll_clicked(); + void on_tbGetStreamStats_clicked(); void on_tbResolveNeighbors_clicked(); void on_tbClearNeighbors_clicked(); diff --git a/client/portstatswindow.ui b/client/portstatswindow.ui index 870633e..5d9e986 100644 --- a/client/portstatswindow.ui +++ b/client/portstatswindow.ui @@ -86,6 +86,22 @@ + + + + Fetch Selected Port Stream Stats + + + Fetches stream statistics from the selected port(s) + + + Fetch Stream Stats + + + :/icons/stream_stats.png + + + diff --git a/client/streamstatsmodel.cpp b/client/streamstatsmodel.cpp new file mode 100644 index 0000000..d7946de --- /dev/null +++ b/client/streamstatsmodel.cpp @@ -0,0 +1,44 @@ +/* +Copyright (C) 2016 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +#include "streamstatsmodel.h" + +#include "protocol.pb.h" + +StreamStatsModel::StreamStatsModel(QObject *parent) + : QStringListModel(parent) +{ +} + +void StreamStatsModel::clearStats() +{ + stats_.clear(); + setStringList(stats_); +} + +void StreamStatsModel::appendStreamStatsList( + quint32 /*portGroupId*/, + const OstProto::StreamStatsList *stats) +{ + stats_.append(stats->DebugString().c_str()); + setStringList(stats_); + + // Prevent receiving any future updates from this sender + disconnect(sender(), 0, this, 0); +} diff --git a/client/streamstatsmodel.h b/client/streamstatsmodel.h new file mode 100644 index 0000000..934fded --- /dev/null +++ b/client/streamstatsmodel.h @@ -0,0 +1,43 @@ +/* +Copyright (C) 2016 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +#ifndef _STREAM_STATS_MODEL_H +#define _STREAM_STATS_MODEL_H + +#include // FIXME: remove + +namespace OstProto { + class StreamStatsList; +} + +class StreamStatsModel: public QStringListModel // FIXME: change to TableModel +{ + Q_OBJECT +public: + StreamStatsModel(QObject *parent = 0); + +public slots: + void clearStats(); + void appendStreamStatsList(quint32 portGroupId, + const OstProto::StreamStatsList *stats); +private: + QList stats_; // FIXME: remove +}; +#endif + diff --git a/client/streamstatswindow.cpp b/client/streamstatswindow.cpp new file mode 100644 index 0000000..b41184a --- /dev/null +++ b/client/streamstatswindow.cpp @@ -0,0 +1,30 @@ +/* +Copyright (C) 2016 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +#include "streamstatswindow.h" + +#include + +StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + + streamStats->setModel(model); +} diff --git a/client/streamstatswindow.h b/client/streamstatswindow.h new file mode 100644 index 0000000..c5c894e --- /dev/null +++ b/client/streamstatswindow.h @@ -0,0 +1,35 @@ +/* +Copyright (C) 2016 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +#ifndef _STREAM_STATS_WINDOW_H +#define _STREAM_STATS_WINDOW_H + +#include "ui_streamstatswindow.h" + +class QAbstractItemModel; + +class StreamStatsWindow: public QWidget, private Ui::StreamStatsWindow +{ + Q_OBJECT +public: + StreamStatsWindow(QAbstractItemModel *model, QWidget *parent = 0); +}; + +#endif + diff --git a/client/streamstatswindow.ui b/client/streamstatswindow.ui new file mode 100644 index 0000000..ffebeba --- /dev/null +++ b/client/streamstatswindow.ui @@ -0,0 +1,23 @@ + + StreamStatsWindow + + + + 0 + 0 + 551 + 452 + + + + Form + + + + + + + + + +