ostinato/client/portstatswindow.cpp
Srivats P ea31cf30fb Select previous tab when a stream stats tab is closed
The default behaviour was to select the tab to the right of the
closed tab which is not very useful for us since the right tab
will be the Logs tab.

Fixes #331
2020-12-27 11:16:39 +05:30

400 lines
12 KiB
C++

/*
Copyright (C) 2010 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 <http://www.gnu.org/licenses/>
*/
#include "portstatswindow.h"
#include "icononlydelegate.h"
#include "portstatsfilterdialog.h"
#include "portstatsmodel.h"
#include "portstatsproxymodel.h"
#include "streamstatsmodel.h"
#include "streamstatswindow.h"
#include "settings.h"
#include <QDockWidget>
#include <QHeaderView>
#include <QMainWindow>
extern QMainWindow *mainWindow;
PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
: QWidget(parent), proxyStatsModel(NULL)
{
setupUi(this);
this->pgl = pgl;
model = pgl->getPortStatsModel();
proxyStatsModel = new PortStatsProxyModel(this);
if (proxyStatsModel) {
proxyStatsModel->setSourceModel(model);
tvPortStats->setModel(proxyStatsModel);
}
else
tvPortStats->setModel(model);
tvPortStats->setAlternatingRowColors(true);
tvPortStats->verticalHeader()->setHighlightSections(false);
tvPortStats->verticalHeader()->setDefaultSectionSize(
tvPortStats->verticalHeader()->minimumSectionSize());
statusDelegate = new IconOnlyDelegate(this);
#if 0
// XXX: Ideally we should use this, but it doesn't work because in
// this constructor, the port model is empty and model->index() returns
// an invalid index ...
tvPortStats->setItemDelegateForRow(
proxyStatsModel ?
proxyStatsModel->mapFromSource(model->index(e_COMBO_STATE, 0))
.row() :
e_COMBO_STATE,
statusDelegate);
#else
// ... so we use this hard-coded hack
tvPortStats->setItemDelegateForRow(
proxyStatsModel ? e_COMBO_STATE-1 : e_COMBO_STATE,
statusDelegate);
#endif
connect(tvPortStats->selectionModel(),
SIGNAL(selectionChanged(
const QItemSelection&, const QItemSelection&)),
SLOT(when_tvPortStats_selectionChanged(
const QItemSelection&, const QItemSelection&)));
when_tvPortStats_selectionChanged(QItemSelection(), QItemSelection());
}
PortStatsWindow::~PortStatsWindow()
{
delete proxyStatsModel;
delete statusDelegate;
}
/* ------------- SLOTS (public) -------------- */
void PortStatsWindow::clearCurrentSelection()
{
tvPortStats->selectionModel()->clearCurrentIndex();
tvPortStats->clearSelection();
}
void PortStatsWindow::showMyReservedPortsOnly(bool enabled)
{
if (!proxyStatsModel)
return;
if (enabled) {
QString rx(appSettings->value(kUserKey, kUserDefaultValue).toString());
proxyStatsModel->setFilterRegExp(QRegExp::escape(rx));
}
else
proxyStatsModel->setFilterRegExp(QRegExp(".*")); // match all
}
/* ------------- SLOTS (private) -------------- */
void PortStatsWindow::when_tvPortStats_selectionChanged(
const QItemSelection& /*selected*/,
const QItemSelection& /*deselected*/)
{
QModelIndexList indexList =
tvPortStats->selectionModel()->selectedColumns();
if (proxyStatsModel) {
selectedColumns.clear();
foreach(QModelIndex index, indexList)
selectedColumns.append(proxyStatsModel->mapToSource(index));
}
else
selectedColumns = indexList;
bool isEmpty = selectedColumns.isEmpty();
tbStartTransmit->setDisabled(isEmpty);
tbStopTransmit->setDisabled(isEmpty);
tbStartCapture->setDisabled(isEmpty);
tbStopCapture->setDisabled(isEmpty);
tbViewCapture->setDisabled(isEmpty);
tbClear->setDisabled(isEmpty);
tbGetStreamStats->setDisabled(isEmpty);
tbResolveNeighbors->setDisabled(isEmpty);
tbClearNeighbors->setDisabled(isEmpty);
}
void PortStatsWindow::on_tbStartTransmit_clicked()
{
QList<PortStatsModel::PortGroupAndPortList> pgpl;
// Get selected ports
model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
startTx(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbStopTransmit_clicked()
{
QList<PortStatsModel::PortGroupAndPortList> pgpl;
// Get selected ports
model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
stopTx(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbStartCapture_clicked()
{
// TODO(MED)
QList<PortStatsModel::PortGroupAndPortList> pgpl;
// Get selected ports
model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
startCapture(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbStopCapture_clicked()
{
// TODO(MED)
QList<PortStatsModel::PortGroupAndPortList> pgpl;
// Get selected ports
model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
stopCapture(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbViewCapture_clicked()
{
// TODO(MED)
QList<PortStatsModel::PortGroupAndPortList> pgpl;
// Get selected ports
model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
{
pgl->portGroupByIndex(pgpl.at(i).portGroupId).
viewCapture(&pgpl[i].portList);
}
}
void PortStatsWindow::on_tbResolveNeighbors_clicked()
{
QList<PortStatsModel::PortGroupAndPortList> portList;
// Get selected ports
model->portListFromIndex(selectedColumns, portList);
// Resolve ARP/ND for selected ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId).
resolveDeviceNeighbors(&portList[i].portList);
// Update device info for the just processed portgroup
for (int j = 0; j < portList[i].portList.size(); j++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId).
getDeviceInfo(portList[i].portList[j]);
}
}
}
void PortStatsWindow::on_tbClearNeighbors_clicked()
{
QList<PortStatsModel::PortGroupAndPortList> portList;
// Get selected ports
model->portListFromIndex(selectedColumns, portList);
// Clear ARP/ND for ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId).
clearDeviceNeighbors(&portList[i].portList);
// Update device info for the just processed portgroup
for (int j = 0; j < portList[i].portList.size(); j++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId).
getDeviceInfo(portList[i].portList[j]);
}
}
}
void PortStatsWindow::on_tbClear_clicked()
{
QList<PortStatsModel::PortGroupAndPortList> portList;
// Get selected ports
model->portListFromIndex(selectedColumns, portList);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId).
clearPortStats(&portList[i].portList);
pgl->portGroupByIndex(portList.at(i).portGroupId).
clearStreamStats(&portList[i].portList);
}
}
// 'All' => all ports currently visible, not all ports in all portgroups
void PortStatsWindow::on_tbClearAll_clicked()
{
QAbstractItemModel *mdl = tvPortStats->model();
QModelIndexList shownColumns;
QList<PortStatsModel::PortGroupAndPortList> portList;
// Find the 'visible' columns
for(int vi = 0; vi < mdl->columnCount(); vi++) {
int li = tvPortStats->horizontalHeader()->logicalIndex(vi);
if (!tvPortStats->isColumnHidden(li)) {
shownColumns.append(mdl->index(0, li));
}
}
if (proxyStatsModel) {
for(QModelIndex &index : shownColumns)
index = proxyStatsModel->mapToSource(index);
}
// Get ports corresponding to the shown columns
model->portListFromIndex(shownColumns, portList);
// Clear shown ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
{
pgl->portGroupByIndex(portList.at(i).portGroupId)
.clearPortStats(&portList[i].portList);
pgl->portGroupByIndex(portList.at(i).portGroupId)
.clearStreamStats(&portList[i].portList);
}
}
void PortStatsWindow::on_tbGetStreamStats_clicked()
{
QList<PortStatsModel::PortGroupAndPortList> portList;
StreamStatsModel *streamStatsModel;
// Get selected ports
model->portListFromIndex(selectedColumns, portList);
if (portList.size()) {
QDockWidget *dock = new QDockWidget(mainWindow);
streamStatsModel = new StreamStatsModel(dock);
dock->setWidget(new StreamStatsWindow(streamStatsModel, dock));
dock->setWindowTitle(dock->widget()->windowTitle());
dock->setObjectName("streamStatsDock");
dock->setAttribute(Qt::WA_DeleteOnClose);
QDockWidget *statsDock = mainWindow->findChild<QDockWidget*>(
"statsDock");
mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
// Add stream stats tab to the immediate right of port-stats ...
mainWindow->tabifyDockWidget(statsDock, dock);
mainWindow->splitDockWidget(statsDock, dock, Qt::Horizontal);
// ... make it the currently visible tab ...
dock->show();
dock->raise();
// ... and set tab remove behaviour
// XXX: unfortunately, there's no direct way to get the TabBar
QList<QTabBar*> tabBars = mainWindow->findChildren<QTabBar*>();
foreach(QTabBar* tabBar, tabBars) {
if (tabBar->tabText(tabBar->currentIndex())
== dock->widget()->windowTitle())
tabBar->setSelectionBehaviorOnRemove(
QTabBar::SelectPreviousTab);
}
}
// 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;
QList<uint> currentColumns, newColumns;
PortStatsFilterDialog dialog;
QAbstractItemModel *mdl = tvPortStats->model();
// create the input list for the filter dialog -
// list of logical-indexes ordered by their current visual indexes
for(int vi = 0; vi < mdl->columnCount(); vi++) {
int li = tvPortStats->horizontalHeader()->logicalIndex(vi);
if (!tvPortStats->isColumnHidden(li)) {
currentColumns.append(li);
}
}
// return list from the filter dialog -
// list of logical-indexes ordered by their new visual indexes
newColumns = dialog.getItemList(&ok, mdl, Qt::Horizontal, currentColumns);
if (ok)
{
QHeaderView *hv = tvPortStats->horizontalHeader();
// hide/show sections first ...
for(int li = 0; li < mdl->columnCount(); li++)
tvPortStats->setColumnHidden(li, !newColumns.contains(li));
// ... then for the 'shown' columns, set the visual index
for(int vi = 0; vi < newColumns.size(); vi++)
hv->moveSection(hv->visualIndex(newColumns.at(vi)), vi);
}
}