(
+ deviceGroupById(deviceGroupId));
if (!devGrp) {
qDebug("%s: deviceGroup id %u does not exist", __FUNCTION__,
diff --git a/client/port.h b/client/port.h
index 3421cbd..d794480 100644
--- a/client/port.h
+++ b/client/port.h
@@ -50,6 +50,7 @@ class Port : public QObject {
quint32 mPortId;
quint32 mPortGroupId;
QString mUserAlias; // user defined
+ bool dirty_;
double avgPacketsPerSec_;
double avgBitsPerSec_;
@@ -70,6 +71,7 @@ class Port : public QObject {
void updateStreamOrdinalsFromIndex();
void reorderStreamsByOrdinals();
+ void setDirty(bool dirty);
public:
enum AdminStatus { AdminDisable, AdminEnable };
@@ -92,17 +94,17 @@ public:
{ return QString().fromStdString(d.notes()); }
const QString userName() const
{ return QString().fromStdString(d.user_name()); }
- AdminStatus adminStatus()
+ AdminStatus adminStatus() const
{ return (d.is_enabled()?AdminEnable:AdminDisable); }
- bool hasExclusiveControl()
+ bool hasExclusiveControl() const
{ return d.is_exclusive_control(); }
- OstProto::TransmitMode transmitMode()
+ OstProto::TransmitMode transmitMode() const
{ return d.transmit_mode(); }
- bool trackStreamStats()
+ bool trackStreamStats() const
{ return d.is_tracking_stream_stats(); }
- double averagePacketRate()
+ double averagePacketRate() const
{ return avgPacketsPerSec_; }
- double averageBitRate()
+ double averageBitRate() const
{ return avgBitsPerSec_; }
//void setAdminEnable(AdminStatus status) { mAdminStatus = status; }
@@ -110,11 +112,22 @@ public:
//void setExclusive(bool flag);
int numStreams() { return mStreams.size(); }
- Stream* streamByIndex(int index)
+ const Stream* streamByIndex(int index) const
{
Q_ASSERT(index < mStreams.size());
return mStreams[index];
}
+ Stream* mutableStreamByIndex(int index, bool assumeChange = true)
+ {
+ Q_ASSERT(index < mStreams.size());
+ if (assumeChange)
+ setDirty(true);
+ return mStreams[index];
+ }
+ void setLocalConfigChanged(bool changed)
+ {
+ setDirty(changed);
+ }
OstProto::LinkState linkState()
{ return stats.state().link_state(); }
@@ -131,6 +144,7 @@ public:
void protoDataCopyInto(OstProto::Port *data);
+ //! Used when config received from server
// FIXME(MED): naming inconsistency - PortConfig/Stream; also retVal
void updatePortConfig(OstProto::Port *port);
@@ -146,6 +160,7 @@ public:
bool updateStream(uint streamId, OstProto::Stream *stream);
//@}
+ bool isDirty() { return dirty_; }
void getDeletedStreamsSinceLastSync(OstProto::StreamIdList &streamIdList);
void getNewStreamsSinceLastSync(OstProto::StreamIdList &streamIdList);
void getModifiedStreamsSinceLastSync(
@@ -180,7 +195,7 @@ public:
int numDeviceGroups() const;
const OstProto::DeviceGroup* deviceGroupByIndex(int index) const;
OstProto::DeviceGroup* mutableDeviceGroupByIndex(int index);
- OstProto::DeviceGroup* deviceGroupById(uint deviceGroupId);
+ const OstProto::DeviceGroup* deviceGroupById(uint deviceGroupId) const;
//! Used by StreamModel
//@{
@@ -218,11 +233,20 @@ public:
void deviceInfoRefreshed();
signals:
+ //! Used when local config changed and when config received from server
void portRateChanged(int portGroupId, int portId);
- void portDataChanged(int portGroupId, int portId);
- void streamListChanged(int portGroupId, int portId);
- void deviceInfoChanged();
+ //! Used by MyService::Stub to update from config received from server
+ //@{
+ void portDataChanged(int portGroupId, int portId);
+ void deviceInfoChanged();
+ //@}
+
+ //! Used when local config changed
+ //@{
+ void streamListChanged(int portGroupId, int portId);
+ void localConfigChanged(int portGroupId, int portId, bool changed);
+ //@}
};
#endif
diff --git a/client/portgroup.cpp b/client/portgroup.cpp
index 23d4d33..f52ee05 100644
--- a/client/portgroup.cpp
+++ b/client/portgroup.cpp
@@ -19,6 +19,7 @@ along with this program. If not, see
#include "portgroup.h"
+#include "jumpurl.h"
#include "settings.h"
#include "emulproto.pb.h"
@@ -200,6 +201,19 @@ void PortGroup::processVersionCompatibility(PbRpcController *controller)
qPrintable(QString::fromStdString(verCompat->notes())));
compat = kIncompatible;
emit portGroupDataChanged(mPortGroupId);
+
+ QMessageBox msgBox;
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.setTextFormat(Qt::RichText);
+ msgBox.setStyleSheet("messagebox-text-interaction-flags: 5");
+ msgBox.setText(tr("The Drone agent at %1:%2 is incompatible with this "
+ "Ostinato version - %3")
+ .arg(serverName())
+ .arg(int(serverPort()))
+ .arg(version));
+ msgBox.setInformativeText(QString::fromStdString(verCompat->notes()));
+ msgBox.exec();
+
goto _error_exit;
}
@@ -302,23 +316,22 @@ void PortGroup::on_rpcChannel_notification(int notifType,
void PortGroup::when_portListChanged(quint32 /*portGroupId*/)
{
- QString faq("http://ostinato.org/docs/faq#q-port-group-has-no-interfaces");
if (state() == QAbstractSocket::ConnectedState && numPorts() <= 0)
{
- if (QMessageBox::warning(NULL, tr("No ports in portgroup"),
- QString("The portgroup %1:%2 does not contain any ports!\n\n"
- "Packet Transmit/Capture requires elevated privileges. "
- "Please ensure that you are running 'drone' - the server "
- "component of Ostinato with admin/root OR setuid privilege.\n\n"
- "For help see the Ostinato FAQ (%3)")
+ QMessageBox msgBox;
+ msgBox.setIcon(QMessageBox::Warning);
+ msgBox.setTextFormat(Qt::RichText);
+ msgBox.setStyleSheet("messagebox-text-interaction-flags: 5");
+ QString msg = tr("The portgroup %1:%2 does not contain any ports!
"
+ "
Packet Transmit/Capture requires special privileges. "
+ "Please ensure that you are running 'drone' - the agent "
+ "component of Ostinato with required privileges.
")
.arg(serverName())
- .arg(int(serverPort()))
- .arg(faq.remove(QRegExp("#.*$"))),
- QMessageBox::Ok | QMessageBox::Help,
- QMessageBox::Ok) == QMessageBox::Help)
- {
- QDesktopServices::openUrl(QUrl(faq));
- }
+ .arg(int(serverPort()));
+ msgBox.setText(msg);
+ msgBox.setInformativeText(tr("See the Ostinato FAQ "
+ "for instructions to fix this problem").arg(jumpUrl("noports")));
+ msgBox.exec();
}
}
@@ -347,6 +360,8 @@ void PortGroup::processPortIdList(PbRpcController *controller)
p = new Port(portIdList->port_id(i).id(), mPortGroupId);
connect(p, SIGNAL(portDataChanged(int, int)),
this, SIGNAL(portGroupDataChanged(int, int)));
+ connect(p, SIGNAL(localConfigChanged(int, int, bool)),
+ this, SIGNAL(portGroupDataChanged(int, int)));
qDebug("before port append\n");
mPorts.append(p);
atConnectPortConfig_.append(NULL); // will be filled later
diff --git a/client/portgrouplist.cpp b/client/portgrouplist.cpp
index 6e380a0..79f500d 100644
--- a/client/portgrouplist.cpp
+++ b/client/portgrouplist.cpp
@@ -19,6 +19,8 @@ along with this program. If not, see
#include "portgrouplist.h"
+#include "params.h"
+
// TODO(LOW): Remove
#include
@@ -29,8 +31,6 @@ PortGroupList::PortGroupList()
mDeviceGroupModel(this),
mDeviceModel(this)
{
- PortGroup *pg;
-
#ifdef QT_NO_DEBUG
streamModelTester_ = NULL;
portModelTester_ = NULL;
@@ -46,8 +46,10 @@ PortGroupList::PortGroupList()
#endif
// Add the "Local" Port Group
- pg = new PortGroup;
- addPortGroup(*pg);
+ if (appParams.optLocalDrone()) {
+ PortGroup *pg = new PortGroup;
+ addPortGroup(*pg);
+ }
}
PortGroupList::~PortGroupList()
diff --git a/client/portmodel.cpp b/client/portmodel.cpp
index cd1c9d7..e1e0f06 100644
--- a/client/portmodel.cpp
+++ b/client/portmodel.cpp
@@ -187,6 +187,10 @@ QVariant PortModel::data(const QModelIndex &index, int role) const
{
return portIconFactory[port->linkState()][port->hasExclusiveControl()];
}
+ else if ((role == Qt::ForegroundRole))
+ {
+ return port->isDirty() ? QBrush(Qt::red) : QVariant();
+ }
else
{
DBG0("Exit PortModel data 6\n");
diff --git a/client/portstatswindow.cpp b/client/portstatswindow.cpp
index 079cc8d..42092a1 100644
--- a/client/portstatswindow.cpp
+++ b/client/portstatswindow.cpp
@@ -53,6 +53,12 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
tvPortStats->verticalHeader()->setDefaultSectionSize(
tvPortStats->verticalHeader()->minimumSectionSize());
+ connect(tvPortStats->selectionModel(),
+ SIGNAL(selectionChanged(
+ const QItemSelection&, const QItemSelection&)),
+ SLOT(when_tvPortStats_selectionChanged(
+ const QItemSelection&, const QItemSelection&)));
+ when_tvPortStats_selectionChanged(QItemSelection(), QItemSelection());
}
PortStatsWindow::~PortStatsWindow()
@@ -76,12 +82,43 @@ void PortStatsWindow::showMyReservedPortsOnly(bool enabled)
}
/* ------------- 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);
+
+ tbResolveNeighbors->setDisabled(isEmpty);
+ tbClearNeighbors->setDisabled(isEmpty);
+}
+
void PortStatsWindow::on_tbStartTransmit_clicked()
{
QList pgpl;
// Get selected ports
- model->portListFromIndex(selectedColumns(), pgpl);
+ model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
@@ -96,7 +133,7 @@ void PortStatsWindow::on_tbStopTransmit_clicked()
QList pgpl;
// Get selected ports
- model->portListFromIndex(selectedColumns(), pgpl);
+ model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
@@ -112,7 +149,7 @@ void PortStatsWindow::on_tbStartCapture_clicked()
QList pgpl;
// Get selected ports
- model->portListFromIndex(selectedColumns(), pgpl);
+ model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
@@ -128,7 +165,7 @@ void PortStatsWindow::on_tbStopCapture_clicked()
QList pgpl;
// Get selected ports
- model->portListFromIndex(selectedColumns(), pgpl);
+ model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
@@ -144,7 +181,7 @@ void PortStatsWindow::on_tbViewCapture_clicked()
QList pgpl;
// Get selected ports
- model->portListFromIndex(selectedColumns(), pgpl);
+ model->portListFromIndex(selectedColumns, pgpl);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < pgpl.size(); i++)
@@ -159,7 +196,7 @@ void PortStatsWindow::on_tbResolveNeighbors_clicked()
QList portList;
// Get selected ports
- model->portListFromIndex(selectedColumns(), portList);
+ model->portListFromIndex(selectedColumns, portList);
// Resolve ARP/ND for selected ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
@@ -174,7 +211,7 @@ void PortStatsWindow::on_tbClearNeighbors_clicked()
QList portList;
// Get selected ports
- model->portListFromIndex(selectedColumns(), portList);
+ model->portListFromIndex(selectedColumns, portList);
// Clear ARP/ND for ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
@@ -189,7 +226,7 @@ void PortStatsWindow::on_tbClear_clicked()
QList portList;
// Get selected ports
- model->portListFromIndex(selectedColumns(), portList);
+ model->portListFromIndex(selectedColumns, portList);
// Clear selected ports, portgroup by portgroup
for (int i = 0; i < portList.size(); i++)
@@ -235,7 +272,7 @@ void PortStatsWindow::on_tbGetStreamStats_clicked()
StreamStatsModel *streamStatsModel;
// Get selected ports
- model->portListFromIndex(selectedColumns(), portList);
+ model->portListFromIndex(selectedColumns, portList);
if (portList.size()) {
QDockWidget *dock = new QDockWidget(mainWindow);
@@ -298,20 +335,3 @@ void PortStatsWindow::on_tbFilter_clicked()
hv->moveSection(hv->visualIndex(newColumns.at(vi)), vi);
}
}
-
-/* ------------ Private Methods -------------- */
-
-QModelIndexList PortStatsWindow::selectedColumns()
-{
- QModelIndexList indexList =
- tvPortStats->selectionModel()->selectedColumns();
- QModelIndexList sourceIndexList;
-
- if (!proxyStatsModel)
- return indexList;
-
- foreach(QModelIndex index, indexList)
- sourceIndexList.append(proxyStatsModel->mapToSource(index));
-
- return sourceIndexList;
-}
diff --git a/client/portstatswindow.h b/client/portstatswindow.h
index 717d913..6efb263 100644
--- a/client/portstatswindow.h
+++ b/client/portstatswindow.h
@@ -40,6 +40,9 @@ public slots:
void showMyReservedPortsOnly(bool enabled);
private slots:
+ void when_tvPortStats_selectionChanged(const QItemSelection &selected,
+ const QItemSelection &deselected);
+
void on_tbStartTransmit_clicked();
void on_tbStopTransmit_clicked();
@@ -57,11 +60,10 @@ private slots:
void on_tbFilter_clicked();
private:
- QModelIndexList selectedColumns();
-
PortGroupList *pgl;
PortStatsModel *model;
QSortFilterProxyModel *proxyStatsModel;
+ QModelIndexList selectedColumns;
};
diff --git a/client/portstatswindow.ui b/client/portstatswindow.ui
index 5d9e986..7c9b8e1 100644
--- a/client/portstatswindow.ui
+++ b/client/portstatswindow.ui
@@ -1,7 +1,8 @@
-
+
+
PortStatsWindow
-
-
+
+
0
0
@@ -9,80 +10,105 @@
415
-
+
Form
-
+
-
-
-
+
+
QFrame::Panel
-
+
QFrame::Raised
-
+
-
-
-
+
+
+ Transmit
+
+
+
+ -
+
+
Start Tx
-
+
Starts transmit on selected port(s)
-
- Start Transmit
+
+ Start
-
- :/icons/control_play.png
+
+
+ :/icons/control_play.png:/icons/control_play.png
-
-
-
+
+
Stop Tx
-
+
Stops transmit on selected port(s)
-
- Stop Trasmit
+
+ Stop
-
- :/icons/control_stop.png
+
+
+ :/icons/control_stop.png:/icons/control_stop.png
-
-
-
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+ Stats
+
+
+
+ -
+
+
Clear Selected Port Stats
-
+
Clears statistics of the selected port(s)
-
+
Clear
-
- :/icons/portstats_clear.png
+
+
+ :/icons/portstats_clear.png:/icons/portstats_clear.png
-
-
-
+
+
Clear All Ports Stats
-
+
Clears statistics of all ports
-
+
Clear All
-
- :/icons/portstats_clear_all.png
+
+
+ :/icons/portstats_clear_all.png:/icons/portstats_clear_all.png
@@ -103,105 +129,131 @@
-
-
-
- Start Capture
-
-
- Captures packets on the selected port(s)
-
-
- Start Capture
-
-
- :/icons/sound_none.png
-
-
-
- -
-
-
- Stop Capture
-
-
- End capture on selecteed port(s)
-
-
- Stop Capture
-
-
- :/icons/sound_mute.png
-
-
-
- -
-
-
- View Capture Buffer
-
-
- View captured packets on selected port(s)
-
-
- View Capture
-
-
- :/icons/magnifier.png
-
-
-
- -
-
-
+
+
Qt::Vertical
-
-
+
+
+ Capture
+
+
+
+ -
+
+ Start Capture
+
+
+ Captures packets on the selected port(s)
+
+
+ Start
+
+
+
+ :/icons/sound_none.png:/icons/sound_none.png
+
+
+
+ -
+
+
+ Stop Capture
+
+
+ End capture on selecteed port(s)
+
+
+ Stop
+
+
+
+ :/icons/sound_mute.png:/icons/sound_mute.png
+
+
+
+ -
+
+
+ View Capture Buffer
+
+
+ View captured packets on selected port(s)
+
+
+ View
+
+
+
+ :/icons/magnifier.png:/icons/magnifier.png
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+ ARP/ND
+
+
+
+ -
+
+
Resolve Neighbors
-
+
Resolve Device Neighbors on selected port(s)
-
+
Resolve Neighbors
-
- :/icons/neighbor_resolve.png
+
+
+ :/icons/neighbor_resolve.png:/icons/neighbor_resolve.png
-
-
-
+
+
Clear Neighbors
-
+
Clear Device Neighbors on selected port(s)
-
+
Clear Neighbors
-
- :/icons/neighbor_clear.png
+
+
+ :/icons/neighbor_clear.png:/icons/neighbor_clear.png
-
-
-
+
+
Qt::Vertical
-
-
+
Qt::Horizontal
-
+
40
20
@@ -210,15 +262,16 @@
-
-
-
+
+
Select which ports to view
-
+
Filter
-
- :/icons/portstats_filter.png
+
+
+ :/icons/portstats_filter.png:/icons/portstats_filter.png
@@ -226,12 +279,16 @@
-
-
+
+
+ QAbstractItemView::SelectColumns
+
+
-
+
diff --git a/client/portswindow.cpp b/client/portswindow.cpp
index 7679fe3..10fb3b7 100644
--- a/client/portswindow.cpp
+++ b/client/portswindow.cpp
@@ -302,26 +302,26 @@ void PortsWindow::showMyReservedPortsOnly(bool enabled)
void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
{
- QModelIndex currentPort = tvPortList->currentIndex();
- StreamConfigDialog *scd;
- int ret;
-
- if (proxyPortModel)
- currentPort = proxyPortModel->mapToSource(currentPort);
-
if (!index.isValid())
{
qDebug("%s: invalid index", __FUNCTION__);
return;
}
- scd = new StreamConfigDialog(plm->port(currentPort), index.row(), this);
+
qDebug("stream list activated\n");
- ret = scd->exec();
- if (ret == QDialog::Accepted)
- plm->port(currentPort).recalculateAverageRates();
+ Port &curPort = plm->port(proxyPortModel ?
+ proxyPortModel->mapToSource(tvPortList->currentIndex()) :
+ tvPortList->currentIndex());
- delete scd;
+ QList streams;
+ streams.append(curPort.mutableStreamByIndex(index.row(), false));
+
+ StreamConfigDialog scd(streams, curPort, this);
+ if (scd.exec() == QDialog::Accepted) {
+ curPort.recalculateAverageRates();
+ curPort.setLocalConfigChanged(true);
+ }
}
void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
@@ -345,12 +345,16 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
{
disconnect(&(plm->port(previous)), SIGNAL(portRateChanged(int, int)),
this, SLOT(updatePortRates()));
+ disconnect(&(plm->port(previous)),
+ SIGNAL(localConfigChanged(int, int, bool)),
+ this,
+ SLOT(updateApplyHint(int, int, bool)));
}
if (!current.isValid())
{
- qDebug("setting stacked widget to blank page");
- swDetail->setCurrentIndex(2); // blank page
+ qDebug("setting stacked widget to welcome page");
+ swDetail->setCurrentIndex(0); // welcome page
}
else
{
@@ -360,10 +364,21 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
}
else if (plm->isPort(current))
{
- swDetail->setCurrentIndex(0); // port detail page
+ swDetail->setCurrentIndex(2); // port detail page
updatePortRates();
connect(&(plm->port(current)), SIGNAL(portRateChanged(int, int)),
SLOT(updatePortRates()));
+ connect(&(plm->port(current)),
+ SIGNAL(localConfigChanged(int, int, bool)),
+ SLOT(updateApplyHint(int, int, bool)));
+ if (plm->port(current).isDirty())
+ updateApplyHint(plm->port(current).portGroupId(),
+ plm->port(current).id(), true);
+ else if (plm->port(current).numStreams())
+ applyHint->setText("Use the Statistics window to transmit "
+ "packets");
+ else
+ applyHint->setText("");
}
}
@@ -373,7 +388,22 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
void PortsWindow::when_portModel_dataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
- qDebug("In %s", __FUNCTION__);
+ qDebug("In %s %d:(%d, %d) - %d:(%d, %d)", __FUNCTION__,
+ topLeft.parent().isValid(), topLeft.row(), topLeft.column(),
+ bottomRight.parent().isValid(), bottomRight.row(), bottomRight.column());
+
+ if (!topLeft.isValid() || !bottomRight.isValid())
+ return;
+
+ if (topLeft.parent() != bottomRight.parent())
+ return;
+
+ // If a port has changed, expand the port group
+ if (topLeft.parent().isValid())
+ tvPortList->expand(proxyPortModel ?
+ proxyPortModel->mapFromSource(topLeft.parent()) :
+ topLeft.parent());
+
#if 0 // not sure why the >= <= operators are not overloaded in QModelIndex
if ((tvPortList->currentIndex() >= topLeft) &&
(tvPortList->currentIndex() <= bottomRight))
@@ -469,12 +499,7 @@ void PortsWindow::updateStreamViewActions()
else
{
actionNew_Stream->setEnabled(true);
-
- // Enable "Edit" only if the single range has a single row
- if (tvStreamList->selectionModel()->selection().at(0).height() > 1)
- actionEdit_Stream->setDisabled(true);
- else
- actionEdit_Stream->setEnabled(true);
+ actionEdit_Stream->setEnabled(true);
}
// Duplicate/Delete are always enabled as long as we have a selection
@@ -496,6 +521,18 @@ void PortsWindow::updateStreamViewActions()
actionSave_Streams->setEnabled(tvStreamList->model()->rowCount() > 0);
}
+void PortsWindow::updateApplyHint(int /*portGroupId*/, int /*portId*/,
+ bool configChanged)
+{
+ if (configChanged)
+ applyHint->setText("Configuration has changed - "
+ "click Apply "
+ "to activate the changes");
+ else
+ applyHint->setText("Configuration activated. Use the Statistics "
+ "window to transmit packets");
+}
+
void PortsWindow::updatePortViewActions(const QModelIndex& currentIndex)
{
QModelIndex current = currentIndex;
@@ -740,30 +777,59 @@ void PortsWindow::on_actionNew_Stream_triggered()
{
qDebug("New Stream Action");
- // In case nothing is selected, insert 1 row at the top
- int row = 0, count = 1;
+ QItemSelectionModel* selectionModel = tvStreamList->selectionModel();
+ if (selectionModel->selection().size() > 1) {
+ qDebug("%s: Unexpected selection size %d, can't add", __FUNCTION__,
+ selectionModel->selection().size());
+ return;
+ }
+
+ // In case nothing is selected, insert 1 row at the end
+ StreamModel *streamModel = plm->getStreamModel();
+ int row = streamModel->rowCount(), count = 1;
// In case we have a single range selected; insert as many rows as
// in the singe selected range before the top of the selected range
- if (tvStreamList->selectionModel()->selection().size() == 1)
+ if (selectionModel->selection().size() == 1)
{
- row = tvStreamList->selectionModel()->selection().at(0).top();
- count = tvStreamList->selectionModel()->selection().at(0).height();
+ row = selectionModel->selection().at(0).top();
+ count = selectionModel->selection().at(0).height();
}
- plm->getStreamModel()->insertRows(row, count);
+ Port &curPort = plm->port(proxyPortModel ?
+ proxyPortModel->mapToSource(tvPortList->currentIndex()) :
+ tvPortList->currentIndex());
+
+ QList streams;
+ for (int i = 0; i < count; i++)
+ streams.append(new Stream);
+
+ StreamConfigDialog scd(streams, curPort, this);
+ scd.setWindowTitle(tr("Add Stream"));
+ if (scd.exec() == QDialog::Accepted)
+ streamModel->insert(row, streams);
}
void PortsWindow::on_actionEdit_Stream_triggered()
{
qDebug("Edit Stream Action");
- // Ensure we have only one range selected which contains only one row
- if ((tvStreamList->selectionModel()->selection().size() == 1) &&
- (tvStreamList->selectionModel()->selection().at(0).height() == 1))
- {
- on_tvStreamList_activated(tvStreamList->selectionModel()->
- selection().at(0).topLeft());
+ QItemSelectionModel* streamModel = tvStreamList->selectionModel();
+ if (!streamModel->hasSelection())
+ return;
+
+ Port &curPort = plm->port(proxyPortModel ?
+ proxyPortModel->mapToSource(tvPortList->currentIndex()) :
+ tvPortList->currentIndex());
+
+ QList streams;
+ foreach(QModelIndex index, streamModel->selectedRows())
+ streams.append(curPort.mutableStreamByIndex(index.row(), false));
+
+ StreamConfigDialog scd(streams, curPort, this);
+ if (scd.exec() == QDialog::Accepted) {
+ curPort.recalculateAverageRates();
+ curPort.setLocalConfigChanged(true);
}
}
diff --git a/client/portswindow.h b/client/portswindow.h
index b407270..f072cc7 100644
--- a/client/portswindow.h
+++ b/client/portswindow.h
@@ -66,6 +66,7 @@ public slots:
void showMyReservedPortsOnly(bool enabled);
private slots:
+ void updateApplyHint(int portGroupId, int portId, bool configChanged);
void updatePortViewActions(const QModelIndex& currentIndex);
void updateStreamViewActions();
diff --git a/client/portswindow.ui b/client/portswindow.ui
index cbab508..d6de594 100644
--- a/client/portswindow.ui
+++ b/client/portswindow.ui
@@ -1,7 +1,8 @@
-
+
+
PortsWindow
-
-
+
+
0
0
@@ -9,83 +10,138 @@
352
-
+
Form
-
- -
-
-
+
+
-
+
+
Qt::Horizontal
-
+
false
-
-
-
+
+
+
1
0
-
+
Qt::ActionsContextMenu
-
+
QAbstractItemView::SingleSelection
-
-
-
+
+
+
2
0
-
- 0
+
+ 2
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
+
+
+
-
+
+
+ <p><b>Welcome to Ostinato</b></p>
+<p>The port list on the left contains all the ports on which you can transmit packets.</p>
+<p>Ports belong to a port group. Make sure the Port Group has a <img src=":/icons/bullet_green.png"/> next to it, then double click the port group to show or hide the ports in the port group.</p>
+<p>To generate packets, you need to create and configure packet streams. A stream is a sequence of one or more packets.</p>
+<p>To create a stream, select the port on which you want to send packets.</p>
+<hr/>
+<p>Don't see the port that you want (or any ports at all) inside the port group? <a href="http://jump.ostinato.org/noports">Get Help!</a></p>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ -
+
+
+ <p>You have selected a port group in the port list on the left.</p>
+<p>You can transmit packets on any of the ports within the port group.</p>
+<p>Make sure the port group has a <img src=":/icons/bullet_green.png"/> next to it and then double click the port group to show or hide the ports in the port group.</p>
+<p>To generate packets, you need to create and configure packet streams. A stream is a sequence of one or more packets.</p>
+<p>To create a stream, select the port on which you want to send packets. </p>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 177
+
+
+
+
+
+
+
+
+
0
-
-
-
+
+
QFrame::Panel
-
+
QFrame::Raised
-
-
- 3
-
-
- 3
-
-
- 3
-
-
+
+
3
-
-
+
Qt::Horizontal
-
+
40
20
@@ -94,8 +150,28 @@
-
-
-
+
+
+ Apply Hint
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
Apply
@@ -104,50 +180,50 @@
-
-
-
+
+
0
-
-
+
+
Streams
-
+
-
-
+
-
-
-
+
+
Avg pps
-
+
true
-
-
+
-
-
-
+
+
Avg bps
-
-
-
+
+
false
-
-
+
Qt::Horizontal
-
+
40
20
@@ -158,39 +234,46 @@
-
-
-
-
+
+
+
0
1
-
+
Qt::ActionsContextMenu
-
+
+ This is the stream list for the selected port
+
+A stream is a sequence of one or more packets
+
+Right-click to create a stream
+
+
QFrame::StyledPanel
-
+
1
-
+
QAbstractItemView::ExtendedSelection
-
+
QAbstractItemView::SelectRows
-
-
+
+
Devices
-
+
-
-
+
@@ -198,109 +281,102 @@
-
-
- -
-
-
- Select a port to configure streams
-
-
- Qt::AlignCenter
-
-
-
-
-
-
-
-
- :/icons/portgroup_add.png
+
+
+
+ :/icons/portgroup_add.png:/icons/portgroup_add.png
-
+
New Port Group
-
-
- :/icons/portgroup_delete.png
+
+
+
+ :/icons/portgroup_delete.png:/icons/portgroup_delete.png
-
+
Delete Port Group
-
-
- :/icons/portgroup_connect.png
+
+
+
+ :/icons/portgroup_connect.png:/icons/portgroup_connect.png
-
+
Connect Port Group
-
-
- :/icons/portgroup_disconnect.png
+
+
+
+ :/icons/portgroup_disconnect.png:/icons/portgroup_disconnect.png
-
+
Disconnect Port Group
-
-
- :/icons/stream_add.png
+
+
+
+ :/icons/stream_add.png:/icons/stream_add.png
-
+
New Stream
-
-
- :/icons/stream_delete.png
+
+
+
+ :/icons/stream_delete.png:/icons/stream_delete.png
-
+
Delete Stream
-
-
- :/icons/stream_edit.png
+
+
+
+ :/icons/stream_edit.png:/icons/stream_edit.png
-
+
Edit Stream
-
-
+
+
true
-
+
Exclusive Port Control (EXPERIMENTAL)
-
-
+
+
Open Streams ...
-
-
+
+
Save Streams ...
-
-
+
+
Port Configuration ...
-
-
- :/icons/stream_duplicate.png
+
+
+
+ :/icons/stream_duplicate.png:/icons/stream_duplicate.png
-
+
Duplicate Stream
@@ -312,9 +388,19 @@
1
+
+ XTreeView
+ QTreeView
+
+
+
+ XTableView
+ QTableView
+
+
-
+
@@ -323,11 +409,11 @@
averagePacketsPerSec
setEnabled(bool)
-
+
326
80
-
+
454
79
@@ -339,11 +425,11 @@
averageBitsPerSec
setEnabled(bool)
-
+
523
80
-
+
651
88
diff --git a/client/streamconfigdialog.cpp b/client/streamconfigdialog.cpp
index 46f0dae..6fb378c 100644
--- a/client/streamconfigdialog.cpp
+++ b/client/streamconfigdialog.cpp
@@ -39,20 +39,36 @@ int StreamConfigDialog::lastProtocolDataIndex = 0;
static const uint kEthFrameOverHead = 20;
-StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
- QWidget *parent) : QDialog (parent), mPort(port)
+StreamConfigDialog::StreamConfigDialog(
+ QList &streamList,
+ const Port &port,
+ QWidget *parent)
+ : QDialog (parent), _userStreamList(streamList), mPort(port)
{
- OstProto::Stream s;
- mCurrentStreamIndex = streamIndex;
- mpStream = new Stream;
- mPort.streamByIndex(mCurrentStreamIndex)->protoDataCopyInto(s);
- mpStream->protoDataCopyFrom(s);
+ mCurrentStreamIndex = 0;
+
+ Q_ASSERT(_userStreamList.size() > 0);
+
+ // Create a copy of the user provided stream list
+ // We need a copy because user may edit multiple streams and then
+ // discard the edit - in this case the user provided stream list
+ // should not be modified on return
+ foreach(Stream* stm, _userStreamList) {
+ OstProto::Stream s;
+ stm->protoDataCopyInto(s);
+ _streamList.append(new Stream());
+ _streamList.last()->protoDataCopyFrom(s);
+ }
+
+ mpStream = _streamList.at(mCurrentStreamIndex);
_iter = mpStream->createProtocolListIterator();
isUpdateInProgress = false;
setupUi(this);
setupUiExtra();
+ _windowTitle = windowTitle();
+
for (int i = ProtoMin; i < ProtoMax; i++)
{
bgProto[i]->setProperty("ProtocolLevel", i);
@@ -154,8 +170,6 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
this, SLOT(when_lvSelectedProtocols_currentChanged(const QModelIndex&,
const QModelIndex&)));
- variableFieldsWidget->setStream(mpStream);
-
LoadCurrentStream();
mpPacketModel = new PacketModel(this);
tvPacketTree->setModel(mpPacketModel);
@@ -168,10 +182,9 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex,
vwPacketDump->setModel(mpPacketModel);
vwPacketDump->setSelectionModel(tvPacketTree->selectionModel());
- // TODO(MED):
- //! \todo Enable navigation of streams
- pbPrev->setHidden(true);
- pbNext->setHidden(true);
+ pbPrev->setDisabled(mCurrentStreamIndex == 0);
+ pbNext->setDisabled(int(mCurrentStreamIndex) == (_streamList.size()-1));
+
//! \todo Support Goto Stream Id
leStreamId->setHidden(true);
disconnect(rbActionGotoStream, SIGNAL(toggled(bool)), leStreamId, SLOT(setEnabled(bool)));
@@ -332,7 +345,14 @@ StreamConfigDialog::~StreamConfigDialog()
}
delete _iter;
- delete mpStream;
+ while (!_streamList.isEmpty())
+ delete _streamList.takeFirst();
+}
+
+void StreamConfigDialog::setWindowTitle(const QString &title)
+{
+ _windowTitle = title;
+ QDialog::setWindowTitle(title);
}
void StreamConfigDialog::loadProtocolWidgets()
@@ -413,30 +433,6 @@ void StreamConfigDialog::on_cmbPktLenMode_currentIndexChanged(QString mode)
}
}
-void StreamConfigDialog::on_pbPrev_clicked()
-{
-#if 0
- StoreCurrentStream(currStreamIdx);
- currStreamIdx--;
- LoadCurrentStream(currStreamIdx);
-
- pbPrev->setDisabled((currStreamIdx == 0));
- pbNext->setDisabled((currStreamIdx == 2));
-#endif
-}
-
-void StreamConfigDialog::on_pbNext_clicked()
-{
-#if 0
- StoreCurrentStream(currStreamIdx);
- currStreamIdx++;
- LoadCurrentStream(currStreamIdx);
-
- pbPrev->setDisabled((currStreamIdx == 0));
- pbNext->setDisabled((currStreamIdx == 2));
-#endif
-}
-
void StreamConfigDialog::on_tbSelectProtocols_currentChanged(int index)
{
qDebug("%s, index = %d", __FUNCTION__, index);
@@ -990,9 +986,16 @@ void StreamConfigDialog::LoadCurrentStream()
QString str;
qDebug("loading mpStream %p", mpStream);
+ variableFieldsWidget->setStream(mpStream);
+
+ QDialog::setWindowTitle(QString("%1 [%2]").arg(_windowTitle)
+ .arg(mpStream->name().isEmpty() ?
+ tr("") : mpStream->name()));
// Meta Data
{
+ name->setText(mpStream->name());
+ enabled->setChecked(mpStream->isEnabled());
cmbPktLenMode->setCurrentIndex(mpStream->lenMode());
lePktLen->setText(str.setNum(mpStream->frameLen()));
lePktLenMin->setText(str.setNum(mpStream->frameLenMin()));
@@ -1009,6 +1012,7 @@ void StreamConfigDialog::LoadCurrentStream()
// Variable Fields
{
+ variableFieldsWidget->clear();
variableFieldsWidget->load();
}
@@ -1077,6 +1081,8 @@ void StreamConfigDialog::StoreCurrentStream()
qDebug("storing pStream %p", pStream);
// Meta Data
+ pStream->setName(name->text());
+ pStream->setEnabled(enabled->isChecked());
pStream->setLenMode((Stream::FrameLengthMode) cmbPktLenMode->currentIndex());
pStream->setFrameLen(lePktLen->text().toULong(&isOk));
pStream->setFrameLenMin(lePktLenMin->text().toULong(&isOk));
@@ -1225,41 +1231,99 @@ void StreamConfigDialog::on_leBitsPerSec_textEdited(const QString &text)
}
}
-void StreamConfigDialog::on_pbOk_clicked()
+bool StreamConfigDialog::isCurrentStreamValid()
{
- QString log;
- OstProto::Stream s;
-
- // Store dialog contents into stream
- StoreCurrentStream();
+ QStringList log;
if ((mPort.transmitMode() == OstProto::kInterleavedTransmit)
&& (mpStream->isFrameVariable()))
{
- log += "* In 'Interleaved Streams' transmit mode, the count for "
- "varying fields at transmit time may not be same as configured\n";
+ log << tr("In 'Interleaved Streams' transmit mode, the count for "
+ "varying fields at transmit time may not be same as configured");
}
if (!mPort.trackStreamStats()
&& mpStream->hasProtocol(OstProto::Protocol::kSignFieldNumber))
{
- log += "* Stream contains special signature, but per stream statistics "
- "will not be available till it is enabled on the port\n";
+ log << tr("Stream contains special signature, but per stream statistics "
+ "will not be available till it is enabled on the port");
}
mpStream->preflightCheck(log);
- if (log.length())
+ if (log.size())
{
- if (QMessageBox::warning(this, "Preflight Check", log + "\nContinue?",
+ if (QMessageBox::warning(this, "Preflight Check",
+ tr("We found possible problems with this stream -
")
+ + ""
+ + log.replaceInStrings(QRegExp("(.*)"), "- \\1
")
+ .join("\n")
+ + "
"
+ + tr("Ignore?
"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
== QMessageBox::No)
- return;
+ return false;
}
- // Copy the data from the "local working copy of stream" to "actual stream"
- mpStream->protoDataCopyInto(s);
- mPort.streamByIndex(mCurrentStreamIndex)->protoDataCopyFrom(s);
+ return true;
+}
+
+void StreamConfigDialog::on_pbPrev_clicked()
+{
+ Q_ASSERT(mCurrentStreamIndex > 0);
+
+ StoreCurrentStream();
+
+ if (!isCurrentStreamValid())
+ return;
+
+ delete _iter;
+ mpStream = _streamList.at(--mCurrentStreamIndex);
+ _iter = mpStream->createProtocolListIterator();
+
+ LoadCurrentStream();
+ on_twTopLevel_currentChanged(twTopLevel->currentIndex());
+
+ pbPrev->setDisabled(mCurrentStreamIndex == 0);
+ pbNext->setDisabled(int(mCurrentStreamIndex) == (_streamList.size()-1));
+}
+
+void StreamConfigDialog::on_pbNext_clicked()
+{
+ Q_ASSERT(int(mCurrentStreamIndex) < (_streamList.size()-1));
+
+ StoreCurrentStream();
+
+ if (!isCurrentStreamValid())
+ return;
+
+ delete _iter;
+ mpStream = _streamList.at(++mCurrentStreamIndex);
+ _iter = mpStream->createProtocolListIterator();
+
+ LoadCurrentStream();
+ on_twTopLevel_currentChanged(twTopLevel->currentIndex());
+
+ pbPrev->setDisabled(mCurrentStreamIndex == 0);
+ pbNext->setDisabled(int(mCurrentStreamIndex) == (_streamList.size()-1));
+
+}
+
+void StreamConfigDialog::on_pbOk_clicked()
+{
+ // Store dialog contents into current stream
+ StoreCurrentStream();
+
+ if (!isCurrentStreamValid())
+ return;
+
+ // Copy the working copy of streams to user provided streams
+ Q_ASSERT(_userStreamList.size() == _streamList.size());
+ for (int i = 0; i < _streamList.size(); i++) {
+ OstProto::Stream s;
+ _streamList.at(i)->protoDataCopyInto(s);
+ _userStreamList[i]->protoDataCopyFrom(s);
+ }
qDebug("stream stored");
diff --git a/client/streamconfigdialog.h b/client/streamconfigdialog.h
index 399f7ba..ffe1039 100644
--- a/client/streamconfigdialog.h
+++ b/client/streamconfigdialog.h
@@ -43,9 +43,12 @@ class StreamConfigDialog : public QDialog, public Ui::StreamConfigDialog
{
Q_OBJECT
public:
- StreamConfigDialog(Port &port, uint streamIndex, QWidget *parent = 0);
+ StreamConfigDialog(QList &streamList, const Port &port,
+ QWidget *parent = 0);
~StreamConfigDialog();
+ void setWindowTitle(const QString &title);
+
private:
enum ButtonId
@@ -74,7 +77,10 @@ private:
QStringListModel *mpAvailableProtocolsModel;
QStringListModel *mpSelectedProtocolsModel;
- Port& mPort;
+ QList _userStreamList;
+ QList _streamList;
+ const Port& mPort;
+ QString _windowTitle;
uint mCurrentStreamIndex;
Stream *mpStream;
@@ -94,6 +100,7 @@ private:
static int lastProtocolDataIndex;
void setupUiExtra();
+ bool isCurrentStreamValid();
void LoadCurrentStream();
void StoreCurrentStream();
void loadProtocolWidgets();
diff --git a/client/streamconfigdialog.ui b/client/streamconfigdialog.ui
index d81d68d..a5fbc90 100644
--- a/client/streamconfigdialog.ui
+++ b/client/streamconfigdialog.ui
@@ -1,10 +1,11 @@
-
+
+
StreamConfigDialog
-
-
+
+
Qt::ApplicationModal
-
+
0
0
@@ -12,123 +13,140 @@
549
-
-
+
+
0
0
-
+
Edit Stream
-
- :/icons/stream_edit.png
+
+
+ :/icons/stream_edit.png:/icons/stream_edit.png
-
- QLineEdit:enabled[inputMask = "HH; "],
-QLineEdit:enabled[inputMask = "HH HH; "],
-QLineEdit:enabled[inputMask = "HH HH HH; "],
-QLineEdit:enabled[inputMask = "HH HH HH HH; "],
-QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff }
+
+ QLineEdit:enabled[inputMask = "HH; "],
+QLineEdit:enabled[inputMask = "HH HH; "],
+QLineEdit:enabled[inputMask = "HH HH HH; "],
+QLineEdit:enabled[inputMask = "HH HH HH HH; "],
+QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff }
-
+
true
-
- -
-
-
+
+
-
+
+
-
+
0
-
-
+
+
Protocol Selection
-
-
-
-
-
- Qt::Horizontal
+
+
-
+
+
+ Basics
-
-
- 241
- 20
-
-
-
+
+ -
+
+
+ Name
+
+
+ name
+
+
+
+ -
+
+
+ -
+
+
+ Enabled
+
+
+
+
+
- -
-
-
+
-
+
+
Frame Length (including FCS)
-
-
-
-
+
+
-
+
-
-
+
Fixed
-
-
+
Increment
-
-
+
Decrement
-
-
+
Random
- -
-
-
+
-
+
+
Min
- -
-
-
+
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
+
-
+
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
+
-
+
+
Max
- -
-
-
+
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -136,13 +154,13 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
0
-
-
+
+
0
0
@@ -150,42 +168,42 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
311
-
+
Simple
-
-
-
-
-
+
+
-
+
+
L1
-
+
-
-
-
+
+
None
-
+
true
-
-
-
+
+
Mac
-
+
false
-
-
-
+
+
false
-
+
Other
@@ -198,60 +216,60 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
true
-
+
L2
-
+
-
-
-
+
+
None
-
+
true
-
-
-
+
+
Ethernet II
-
+
false
-
-
-
+
+
802.3 Raw
-
-
-
+
+
802.3 LLC
-
+
false
-
-
-
+
+
802.3 LLC SNAP
-
-
-
+
+
false
-
+
Other
@@ -259,116 +277,116 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
true
-
+
L3
-
-
-
-
-
+
+
-
+
+
None
-
+
true
- -
-
-
+
-
+
+
false
-
+
ARP
- -
-
-
+
-
+
+
false
-
+
IPv4
-
+
false
- -
-
-
+
-
+
+
false
-
+
IPv6
- -
-
-
+
-
+
+
false
-
+
IP 6over4
-
+
false
- -
-
-
+
-
+
+
false
-
+
IP 4over6
-
+
false
- -
-
-
+
-
+
+
false
-
+
IP 4over4
-
+
false
- -
-
-
+
-
+
+
false
-
+
IP 6over6
-
+
false
- -
-
-
+
-
+
+
false
-
+
Other
@@ -381,36 +399,36 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
true
-
+
VLAN
-
+
false
-
+
false
-
+
-
-
-
+
+
Untagged
-
+
true
-
-
-
+
+
Tagged
-
-
-
+
+
Stacked
@@ -418,81 +436,81 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
true
-
+
L4
-
-
-
-
-
+
+
-
+
+
None
-
+
true
- -
-
-
+
-
+
+
false
-
+
ICMP
- -
-
-
+
-
+
+
false
-
+
IGMP
- -
-
-
+
-
+
+
false
-
+
TCP
- -
-
-
+
-
+
+
false
-
+
UDP
- -
-
-
+
-
+
+
false
-
+
Other
- -
-
-
+
-
+
+
false
-
+
MLD
@@ -547,43 +565,43 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
true
-
+
Payload
-
+
-
-
-
+
+
None
-
+
true
-
-
-
+
+
Pattern
-
+
false
-
-
-
+
+
Hex Dump
-
-
-
+
+
false
-
+
Other
@@ -654,8 +672,8 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
+
+
0
0
@@ -663,28 +681,28 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
135
-
+
Advanced
-
+
-
-
+
-
-
-
+
+
Available Protocols
-
-
-
+
+
true
-
+
QAbstractItemView::ExtendedSelection
-
+
QAbstractItemView::SelectRows
@@ -692,13 +710,13 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
+
-
-
+
Qt::Vertical
-
+
20
40
@@ -707,24 +725,25 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
-
+
+
false
-
- >
+
+ >
-
- :/icons/arrow_right.png
+
+
+ :/icons/arrow_right.png:/icons/arrow_right.png
-
-
+
Qt::Vertical
-
+
20
40
@@ -735,61 +754,64 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
+
-
-
-
+
+
Selected Protocols
-
-
+
-
-
-
+
+
false
-
+
^
-
- :/icons/arrow_up.png
+
+
+ :/icons/arrow_up.png:/icons/arrow_up.png
-
-
-
+
+
false
-
+
v
-
- :/icons/arrow_down.png
+
+
+ :/icons/arrow_down.png:/icons/arrow_down.png
-
-
-
+
+
false
-
+
-
-
- :/icons/delete.png
+
+
+ :/icons/delete.png:/icons/delete.png
-
-
+
Qt::Horizontal
-
+
40
20
@@ -800,8 +822,8 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
-
+
+
QAbstractItemView::SelectRows
@@ -814,54 +836,54 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
+
+
Protocol Data
-
+
-
-
-
+
+
-1
-
-
+
+
Variable Fields
-
+
-
-
+
-
-
+
+
Stream Control
-
- -
-
-
+
+
-
+
+
Send
-
+
-
-
-
+
+
Packets
-
+
true
-
-
-
+
+
Bursts
@@ -869,71 +891,71 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
Numbers
-
+
-
-
-
+
+
Number of Packets
-
+
leNumPackets
-
-
-
+
+
-
+
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
+
+
Number of Bursts
-
+
leNumBursts
-
-
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
+
+
Packets per Burst
-
+
lePacketsPerBurst
-
-
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -941,68 +963,68 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
Rate
-
+
false
-
+
false
-
+
-
-
-
+
+
Packets/Sec
-
+
true
-
-
-
+
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
+
+
false
-
+
Bursts/Sec
-
-
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
+
+
Bits/Sec
-
-
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -1010,42 +1032,42 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
After this stream
-
+
-
-
-
+
+
Stop
-
-
-
+
+
Goto Next Stream
-
+
true
-
-
-
+
+
Goto First
-
-
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -1053,12 +1075,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
+
-
-
+
Qt::Horizontal
-
+
20
41
@@ -1066,25 +1088,25 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
Mode
-
+
-
-
-
+
+
Fixed
-
+
true
-
-
-
+
+
Continuous
@@ -1092,87 +1114,87 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
-
-
+
-
+
+
true
-
+
Gaps (in seconds)
-
+
false
-
+
false
-
-
-
-
-
+
+
-
+
+
-
- :/icons/gaps.png
+
+ :/icons/gaps.png
- -
-
-
+
-
+
+
ISG
-
+
leGapIsg
- -
-
-
+
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
+
-
+
+
IBG
-
+
leGapIbg
- -
-
-
+
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
+
-
+
+
IPG
-
+
leGapIpg
- -
-
-
+
-
+
+
false
-
+
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -1180,12 +1202,12 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
- -
+
-
-
+
Qt::Vertical
-
+
153
21
@@ -1195,56 +1217,56 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
+
+
Packet View
-
+
-
-
-
+
+
Qt::Vertical
-
-
+
+
QAbstractItemView::SelectItems
-
+
QAbstractItemView::ScrollPerPixel
-
+
true
-
+
- -
-
+
-
+
-
-
-
+
+
Prev
-
-
-
+
+
Next
-
-
+
Qt::Horizontal
-
+
191
20
@@ -1253,18 +1275,18 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
-
-
-
+
+
OK
-
+
true
-
-
-
+
+
Cancel
@@ -1359,7 +1381,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
pbCancel
-
+
@@ -1368,11 +1390,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
StreamConfigDialog
reject()
-
+
623
496
-
+
533
466
@@ -1384,11 +1406,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
leStreamId
setEnabled(bool)
-
+
463
143
-
+
463
177
@@ -1400,11 +1422,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
rbPacketsPerSec
setEnabled(bool)
-
+
30
68
-
+
299
82
@@ -1416,11 +1438,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
rbBurstsPerSec
setEnabled(bool)
-
+
30
95
-
+
299
132
@@ -1432,11 +1454,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
lePacketsPerBurst
setEnabled(bool)
-
+
30
95
-
+
134
189
@@ -1448,11 +1470,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
lePacketsPerSec
setEnabled(bool)
-
+
299
82
-
+
299
108
@@ -1464,11 +1486,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
leBurstsPerSec
setEnabled(bool)
-
+
299
132
-
+
299
158
@@ -1480,11 +1502,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
leBitsPerSec
setEnabled(bool)
-
+
299
182
-
+
299
208
@@ -1496,11 +1518,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
rbPacketsPerSec
setChecked(bool)
-
+
95
70
-
+
299
82
@@ -1512,11 +1534,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
rbBurstsPerSec
setChecked(bool)
-
+
96
98
-
+
299
132
@@ -1528,11 +1550,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
leNumPackets
setDisabled(bool)
-
+
73
196
-
+
164
108
@@ -1544,11 +1566,11 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
leNumBursts
setDisabled(bool)
-
+
96
199
-
+