1e1e0b0c48
This is done for all top level windows - ports, stats, logs At startup, the local portgroup would automatically become current with the result that the welcome page would not be visible. Not sure why but an explicit setFocus of ports window seems to avoid it.
385 lines
12 KiB
C++
385 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);
|
|
mainWindow->tabifyDockWidget(statsDock, dock);
|
|
dock->show();
|
|
dock->raise();
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|