Extract streamsWidget code out of portsWindow

All functionality seems to be working, so hopefully no regressions!

It does appear to me that portWidget can be extracted out of
streamsWidget
This commit is contained in:
Srivats P 2021-11-05 15:27:37 +05:30
parent 214c774fc6
commit 0a825a0aa3
6 changed files with 123 additions and 1260 deletions

View File

@ -65,6 +65,7 @@ HEADERS += \
streamstatsfiltermodel.h \
streamstatsmodel.h \
streamstatswindow.h \
streamswidget.h \
variablefieldswidget.h \
xtableview.h
@ -116,6 +117,7 @@ SOURCES += \
streammodel.cpp \
streamstatsmodel.cpp \
streamstatswindow.cpp \
streamswidget.cpp \
variablefieldswidget.cpp

View File

@ -20,52 +20,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "portswindow.h"
#include "applymsg.h"
#include "clipboardhelper.h"
#include "deviceswidget.h"
#include "portconfigdialog.h"
#include "settings.h"
#include "streamconfigdialog.h"
#include "streamfileformat.h"
#include "streamlistdelegate.h"
#include "fileformat.pb.h"
#include "portconfigdialog.h"
#include "portgrouplist.h"
#include "settings.h"
#include "streamswidget.h"
#include "xqlocale.h"
#include <QFileInfo>
#include <QInputDialog>
#include <QItemSelectionModel>
#include <QMainWindow>
#include <QMessageBox>
#include <QProgressDialog>
#include <QSortFilterProxyModel>
extern ClipboardHelper *clipboardHelper;
extern QMainWindow *mainWindow;
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
: QWidget(parent), proxyPortModel(NULL)
{
QAction *sep;
delegate = new StreamListDelegate;
proxyPortModel = new QSortFilterProxyModel(this);
//slm = new StreamListModel();
//plm = new PortGroupList();
plm = pgl;
Ui::PortsWindow::setupUi(this);
Ui::StreamsWidget::setupUi(streamsWidget);
setupUi(this);
applyMsg_ = new ApplyMessage();
streamsWidget->setPortGroupList(plm);
devicesWidget->setPortGroupList(plm);
tvPortList->header()->hide();
tvStreamList->setItemDelegate(delegate);
tvStreamList->verticalHeader()->setDefaultSectionSize(
tvStreamList->verticalHeader()->minimumSectionSize());
// Populate PortList Context Menu Actions
tvPortList->addAction(actionNew_Port_Group);
tvPortList->addAction(actionDelete_Port_Group);
@ -75,41 +58,18 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
tvPortList->addAction(actionExclusive_Control);
tvPortList->addAction(actionPort_Configuration);
// Populate StreamList Context Menu Actions
tvStreamList->addAction(actionNew_Stream);
tvStreamList->addAction(actionEdit_Stream);
tvStreamList->addAction(actionDuplicate_Stream);
tvStreamList->addAction(actionDelete_Stream);
QAction *sep2 = new QAction(this);
sep2->setSeparator(true);
tvStreamList->addAction(sep2);
tvStreamList->addAction(actionOpen_Streams);
tvStreamList->addAction(actionSave_Streams);
// PortList, StreamList, DeviceWidget actions combined
// make this window's actions
addActions(tvPortList->actions());
sep = new QAction(this);
QAction *sep = new QAction(this);
sep->setSeparator(true);
addAction(sep);
addActions(tvStreamList->actions());
addActions(streamsWidget->actions());
sep = new QAction(this);
sep->setSeparator(true);
addAction(sep);
addActions(devicesWidget->actions());
// Add the clipboard actions to the context menu of streamList
// but not to PortsWindow's actions since they are already available
// in the global Edit Menu
sep = new QAction("Clipboard", this);
sep->setSeparator(true);
tvStreamList->insertAction(sep2, sep);
tvStreamList->insertActions(sep2, clipboardHelper->actions());
tvStreamList->setModel(plm->getStreamModel());
// XXX: It would be ideal if we only needed to do the below to
// get the proxy model to do its magic. However, the QModelIndex
// used by the source model and the proxy model are different
@ -139,52 +99,20 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_portView_currentChanged(const QModelIndex&,
const QModelIndex&)));
connect(this,
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
streamsWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
connect(this,
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
devicesWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
connect(plm->getStreamModel(), SIGNAL(rowsInserted(QModelIndex, int, int)),
SLOT(updateStreamViewActions()));
connect(plm->getStreamModel(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
SLOT(updateStreamViewActions()));
connect(tvStreamList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
SLOT(updateStreamViewActions()));
connect(tvStreamList->selectionModel(),
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
SLOT(updateStreamViewActions()));
tvStreamList->resizeColumnToContents(StreamModel::StreamIcon);
tvStreamList->resizeColumnToContents(StreamModel::StreamStatus);
// Initially we don't have any ports/streams/devices
// - so send signal triggers
when_portView_currentChanged(QModelIndex(), QModelIndex());
updateStreamViewActions();
connect(plm->getStreamModel(),
SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(streamModelDataChanged()));
connect(plm->getStreamModel(),
SIGNAL(modelReset()),
this, SLOT(streamModelDataChanged()));
}
void PortsWindow::streamModelDataChanged()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (plm->isPort(current))
plm->port(current).recalculateAverageRates();
}
PortsWindow::~PortsWindow()
{
delete delegate;
delete proxyPortModel;
delete applyMsg_;
}
@ -322,30 +250,6 @@ void PortsWindow::showMyReservedPortsOnly(bool enabled)
proxyPortModel->setFilterRegExp(QRegExp(""));
}
void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
{
if (!index.isValid())
{
qDebug("%s: invalid index", __FUNCTION__);
return;
}
qDebug("stream list activated\n");
Port &curPort = plm->port(proxyPortModel ?
proxyPortModel->mapToSource(tvPortList->currentIndex()) :
tvPortList->currentIndex());
QList<Stream*> 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,
const QModelIndex& previousIndex)
{
@ -357,16 +261,12 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
previous = proxyPortModel->mapToSource(previous);
}
plm->getStreamModel()->setCurrentPortIndex(current);
updatePortViewActions(currentIndex);
updateStreamViewActions();
qDebug("In %s", __FUNCTION__);
if (previous.isValid() && plm->isPort(previous))
{
disconnect(&(plm->port(previous)), SIGNAL(portRateChanged(int, int)),
this, SLOT(updatePortRates()));
disconnect(&(plm->port(previous)),
SIGNAL(localConfigChanged(int, int, bool)),
this,
@ -387,9 +287,6 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
else if (plm->isPort(current))
{
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)));
@ -447,139 +344,6 @@ void PortsWindow::when_portModel_reset()
when_portView_currentChanged(QModelIndex(), tvPortList->currentIndex());
}
void PortsWindow::on_startTx_clicked()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
QModelIndex curPortGroup = plm->getPortModel()->parent(current);
Q_ASSERT(curPortGroup.isValid());
Q_ASSERT(plm->isPortGroup(curPortGroup));
QList<uint> portList({plm->port(current).id()});
plm->portGroup(curPortGroup).startTx(&portList);
}
void PortsWindow::on_stopTx_clicked()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
QModelIndex curPortGroup = plm->getPortModel()->parent(current);
Q_ASSERT(curPortGroup.isValid());
Q_ASSERT(plm->isPortGroup(curPortGroup));
QList<uint> portList({plm->port(current).id()});
plm->portGroup(curPortGroup).stopTx(&portList);
}
void PortsWindow::on_averagePacketsPerSec_editingFinished()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
bool isOk;
double pps = XLocale().toDouble(averagePacketsPerSec->text(), &isOk);
plm->port(current).setAveragePacketRate(pps);
}
void PortsWindow::on_averageBitsPerSec_editingFinished()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
bool isOk;
double bps = XLocale().toDouble(averageBitsPerSec->text(), &isOk);
plm->port(current).setAverageBitRate(bps);
}
void PortsWindow::updatePortRates()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (!current.isValid())
return;
if (!plm->isPort(current))
return;
averagePacketsPerSec->setText(QString("%L1")
.arg(plm->port(current).averagePacketRate(), 0, 'f', 4));
averageBitsPerSec->setText(QString("%L1")
.arg(plm->port(current).averageBitRate(), 0, 'f', 0));
}
void PortsWindow::updateStreamViewActions()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
// For some reason hasSelection() returns true even if selection size is 0
// so additional check for size introduced
if (tvStreamList->selectionModel()->hasSelection() &&
(tvStreamList->selectionModel()->selection().size() > 0))
{
qDebug("Has selection %d",
tvStreamList->selectionModel()->selection().size());
// If more than one non-contiguous ranges selected,
// disable "New" and "Edit"
if (tvStreamList->selectionModel()->selection().size() > 1)
{
actionNew_Stream->setDisabled(true);
actionEdit_Stream->setDisabled(true);
}
else
{
actionNew_Stream->setEnabled(true);
actionEdit_Stream->setEnabled(true);
}
// Duplicate/Delete are always enabled as long as we have a selection
actionDuplicate_Stream->setEnabled(true);
actionDelete_Stream->setEnabled(true);
}
else
{
qDebug("No selection");
if (plm->isPort(current))
actionNew_Stream->setEnabled(true);
else
actionNew_Stream->setDisabled(true);
actionEdit_Stream->setDisabled(true);
actionDuplicate_Stream->setDisabled(true);
actionDelete_Stream->setDisabled(true);
}
actionOpen_Streams->setEnabled(plm->isPort(current));
actionSave_Streams->setEnabled(tvStreamList->model()->rowCount() > 0);
startTx->setEnabled(tvStreamList->model()->rowCount() > 0);
stopTx->setEnabled(tvStreamList->model()->rowCount() > 0);
}
void PortsWindow::updateApplyHint(int /*portGroupId*/, int /*portId*/,
bool configChanged)
{
@ -587,7 +351,7 @@ void PortsWindow::updateApplyHint(int /*portGroupId*/, int /*portId*/,
applyHint->setText("Configuration has changed - "
"<font color='red'><b>click Apply</b></font> "
"to activate the changes");
else if (tvStreamList->model()->rowCount() > 0)
else if (plm->getStreamModel()->rowCount() > 0)
applyHint->setText("Configuration activated - "
"click <img src=':/icons/control_play'/> "
"to transmit packets");
@ -839,259 +603,3 @@ void PortsWindow::on_actionPort_Configuration_triggered()
if (dialog.exec() == QDialog::Accepted)
plm->portGroup(current.parent()).modifyPort(current.row(), config);
}
void PortsWindow::on_actionNew_Stream_triggered()
{
qDebug("New Stream Action");
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 (selectionModel->selection().size() == 1)
{
row = selectionModel->selection().at(0).top();
count = selectionModel->selection().at(0).height();
}
Port &curPort = plm->port(proxyPortModel ?
proxyPortModel->mapToSource(tvPortList->currentIndex()) :
tvPortList->currentIndex());
QList<Stream*> 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");
QItemSelectionModel* streamModel = tvStreamList->selectionModel();
if (!streamModel->hasSelection())
return;
Port &curPort = plm->port(proxyPortModel ?
proxyPortModel->mapToSource(tvPortList->currentIndex()) :
tvPortList->currentIndex());
QList<Stream*> 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);
}
}
void PortsWindow::on_actionDuplicate_Stream_triggered()
{
QItemSelectionModel* model = tvStreamList->selectionModel();
QModelIndex current = tvPortList->selectionModel()->currentIndex();
qDebug("Duplicate Stream Action");
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (model->hasSelection())
{
bool isOk;
int count = QInputDialog::getInt(this, "Duplicate Streams",
"Count", 1, 1, 9999, 1, &isOk);
if (!isOk)
return;
QList<int> list;
foreach(QModelIndex index, model->selectedRows())
list.append(index.row());
plm->port(current).duplicateStreams(list, count);
}
else
qDebug("No selection");
}
void PortsWindow::on_actionDelete_Stream_triggered()
{
qDebug("Delete Stream Action");
QModelIndex index;
if (tvStreamList->selectionModel()->hasSelection())
{
qDebug("SelectedIndexes %d",
tvStreamList->selectionModel()->selectedRows().size());
while(tvStreamList->selectionModel()->selectedRows().size())
{
index = tvStreamList->selectionModel()->selectedRows().at(0);
plm->getStreamModel()->removeRows(index.row(), 1);
}
}
else
qDebug("No selection");
}
void PortsWindow::on_actionOpen_Streams_triggered()
{
qDebug("Open Streams Action");
QStringList fileTypes = StreamFileFormat::supportedFileTypes(
StreamFileFormat::kOpenFile);
QString fileType;
QModelIndex current = tvPortList->selectionModel()->currentIndex();
static QString dirName;
QString fileName;
QString errorStr;
bool append = true;
bool ret;
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
if (fileTypes.size())
fileType = fileTypes.at(0);
fileName = QFileDialog::getOpenFileName(this, tr("Open Streams"),
dirName, fileTypes.join(";;"), &fileType);
if (fileName.isEmpty())
goto _exit;
if (tvStreamList->model()->rowCount())
{
QMessageBox msgBox(QMessageBox::Question, qApp->applicationName(),
tr("Append to existing streams? Or overwrite?"),
QMessageBox::NoButton, this);
QPushButton *appendBtn = msgBox.addButton(tr("Append"),
QMessageBox::ActionRole);
QPushButton *overwriteBtn = msgBox.addButton(tr("Overwrite"),
QMessageBox::ActionRole);
QPushButton *cancelBtn = msgBox.addButton(QMessageBox::Cancel);
msgBox.exec();
if (msgBox.clickedButton() == cancelBtn)
goto _exit;
else if (msgBox.clickedButton() == appendBtn)
append = true;
else if (msgBox.clickedButton() == overwriteBtn)
append = false;
else
Q_ASSERT(false);
}
ret = plm->port(current).openStreams(fileName, append, errorStr);
if (!ret || !errorStr.isEmpty())
{
QMessageBox msgBox(this);
QStringList str = errorStr.split("\n\n\n\n");
msgBox.setIcon(ret ? QMessageBox::Warning : QMessageBox::Critical);
msgBox.setWindowTitle(qApp->applicationName());
msgBox.setText(str.at(0));
if (str.size() > 1)
msgBox.setDetailedText(str.at(1));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
}
dirName = QFileInfo(fileName).absolutePath();
updateStreamViewActions();
_exit:
return;
}
void PortsWindow::on_actionSave_Streams_triggered()
{
qDebug("Save Streams Action");
QModelIndex current = tvPortList->selectionModel()->currentIndex();
static QString fileName;
QStringList fileTypes = StreamFileFormat::supportedFileTypes(
StreamFileFormat::kSaveFile);
QString fileType;
QString errorStr;
QFileDialog::Options options;
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
// On Mac OS with Native Dialog, getSaveFileName() ignores fileType
// which we need
#if defined(Q_OS_MAC)
options |= QFileDialog::DontUseNativeDialog;
#endif
if (fileTypes.size())
fileType = fileTypes.at(0);
Q_ASSERT(plm->isPort(current));
_retry:
fileName = QFileDialog::getSaveFileName(this, tr("Save Streams"),
fileName, fileTypes.join(";;"), &fileType, options);
if (fileName.isEmpty())
goto _exit;
if (QFileInfo(fileName).suffix().isEmpty()) {
QString fileExt = fileType.section(QRegExp("[\\*\\)]"), 1, 1);
qDebug("Adding extension '%s' to '%s'",
qPrintable(fileExt), qPrintable(fileName));
fileName.append(fileExt);
if (QFileInfo(fileName).exists()) {
if (QMessageBox::warning(this, tr("Overwrite File?"),
QString("The file \"%1\" already exists.\n\n"
"Do you wish to overwrite it?")
.arg(QFileInfo(fileName).fileName()),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No) != QMessageBox::Yes)
goto _retry;
}
}
fileType = fileType.remove(QRegExp("\\(.*\\)")).trimmed();
if (!fileType.startsWith("Ostinato")
&& !fileType.startsWith("Python"))
{
if (QMessageBox::warning(this, tr("Ostinato"),
QString("You have chosen to save in %1 format. All stream "
"attributes may not be saved in this format.\n\n"
"It is recommended to save in native Ostinato format.\n\n"
"Continue to save in %2 format?").arg(fileType).arg(fileType),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No) != QMessageBox::Yes)
goto _retry;
}
// TODO: all or selected?
if (!plm->port(current).saveStreams(fileName, fileType, errorStr))
QMessageBox::critical(this, qApp->applicationName(), errorStr);
else if (!errorStr.isEmpty())
QMessageBox::warning(this, qApp->applicationName(), errorStr);
fileName = QFileInfo(fileName).absolutePath();
_exit:
return;
}

View File

@ -20,14 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#ifndef _PORTS_WINDOW_H
#define _PORTS_WINDOW_H
#include <QWidget>
#include <QAbstractItemModel>
#include "ui_portswindow.h"
#include "ui_streamswidget.h"
#include "portgrouplist.h"
#include <QWidget>
class ApplyMessage;
class QAbstractItemDelegate;
class PortGroupList;
class QProgressDialog;
class QSortFilterProxyModel;
@ -35,13 +33,10 @@ namespace OstProto {
class SessionContent;
}
class PortsWindow : public QWidget, private Ui::PortsWindow, private Ui::StreamsWidget
class PortsWindow : public QWidget, private Ui::PortsWindow
{
Q_OBJECT
//QAbstractItemModel *slm; // stream list model
PortGroupList *plm;
public:
PortsWindow(PortGroupList *pgl, QWidget *parent = 0);
~PortsWindow();
@ -59,12 +54,6 @@ signals:
void currentPortChanged(const QModelIndex &current,
const QModelIndex &previous);
private:
QString lastNewPortGroup;
QAbstractItemDelegate *delegate;
QSortFilterProxyModel *proxyPortModel;
ApplyMessage *applyMsg_;
public slots:
void clearCurrentSelection();
void showMyReservedPortsOnly(bool enabled);
@ -72,14 +61,7 @@ public slots:
private slots:
void updateApplyHint(int portGroupId, int portId, bool configChanged);
void updatePortViewActions(const QModelIndex& currentIndex);
void updateStreamViewActions();
void on_startTx_clicked();
void on_stopTx_clicked();
void on_averagePacketsPerSec_editingFinished();
void on_averageBitsPerSec_editingFinished();
void updatePortRates();
void on_tvStreamList_activated(const QModelIndex & index);
void when_portView_currentChanged(const QModelIndex& currentIndex,
const QModelIndex& previousIndex);
void when_portModel_dataChanged(const QModelIndex& topLeft,
@ -96,15 +78,11 @@ private slots:
void on_actionExclusive_Control_triggered(bool checked);
void on_actionPort_Configuration_triggered();
void on_actionNew_Stream_triggered();
void on_actionEdit_Stream_triggered();
void on_actionDuplicate_Stream_triggered();
void on_actionDelete_Stream_triggered();
void on_actionOpen_Streams_triggered();
void on_actionSave_Streams_triggered();
void streamModelDataChanged();
private:
PortGroupList *plm;
QString lastNewPortGroup;
QSortFilterProxyModel *proxyPortModel;
ApplyMessage *applyMsg_;
};
#endif

View File

@ -213,7 +213,7 @@
</attribute>
<layout class="QVBoxLayout">
<item>
<widget class="QWidget" name="streamsWidget" native="true"/>
<widget class="StreamsWidget" name="streamsWidget" native="true"/>
</item>
</layout>
</widget>
@ -297,6 +297,12 @@
<extends>QTreeView</extends>
<header>xtreeview.h</header>
</customwidget>
<customwidget>
<class>StreamsWidget</class>
<extends>QWidget</extends>
<header>streamswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="ostinato.qrc"/>

View File

@ -17,64 +17,32 @@ 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 "portswindow.h"
#include "streamswidget.h"
#include "applymsg.h"
#include "clipboardhelper.h"
#include "deviceswidget.h"
#include "portconfigdialog.h"
#include "settings.h"
#include "portgrouplist.h"
#include "streamconfigdialog.h"
#include "streamfileformat.h"
#include "streamlistdelegate.h"
#include "fileformat.pb.h"
#include "xqlocale.h"
#include <QFileInfo>
#include <QInputDialog>
#include <QItemSelectionModel>
#include <QMainWindow>
#include <QMessageBox>
#include <QSortFilterProxyModel>
extern ClipboardHelper *clipboardHelper;
extern QMainWindow *mainWindow;
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
: QWidget(parent), proxyPortModel(NULL)
StreamsWidget::StreamsWidget(QWidget *parent)
: QWidget(parent)
{
QAction *sep;
setupUi(this);
delegate = new StreamListDelegate;
proxyPortModel = new QSortFilterProxyModel(this);
//slm = new StreamListModel();
//plm = new PortGroupList();
plm = pgl;
Ui::PortsWindow::setupUi(this);
Ui::StreamsWidget::setupUi(streamsWidget);
applyMsg_ = new ApplyMessage();
devicesWidget->setPortGroupList(plm);
tvPortList->header()->hide();
tvStreamList->setItemDelegate(delegate);
tvStreamList->verticalHeader()->setDefaultSectionSize(
tvStreamList->verticalHeader()->minimumSectionSize());
// Populate PortList Context Menu Actions
tvPortList->addAction(actionNew_Port_Group);
tvPortList->addAction(actionDelete_Port_Group);
tvPortList->addAction(actionConnect_Port_Group);
tvPortList->addAction(actionDisconnect_Port_Group);
tvPortList->addAction(actionExclusive_Control);
tvPortList->addAction(actionPort_Configuration);
// Populate StreamList Context Menu Actions
tvStreamList->addAction(actionNew_Stream);
tvStreamList->addAction(actionEdit_Stream);
@ -88,61 +56,24 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
tvStreamList->addAction(actionOpen_Streams);
tvStreamList->addAction(actionSave_Streams);
// PortList, StreamList, DeviceWidget actions combined
// make this window's actions
addActions(tvPortList->actions());
sep = new QAction(this);
sep->setSeparator(true);
addAction(sep);
// StreamWidget's actions is an aggegate of all sub-widget's actions
addActions(tvStreamList->actions());
sep = new QAction(this);
sep->setSeparator(true);
addAction(sep);
addActions(devicesWidget->actions());
// Add the clipboard actions to the context menu of streamList
// but not to PortsWindow's actions since they are already available
// but not to StreamsWidget's actions since they are already available
// in the global Edit Menu
sep = new QAction("Clipboard", this);
sep->setSeparator(true);
tvStreamList->insertAction(sep2, sep);
QAction *sep3 = new QAction("Clipboard", this);
sep3->setSeparator(true);
tvStreamList->insertAction(sep2, sep3);
tvStreamList->insertActions(sep2, clipboardHelper->actions());
}
void StreamsWidget::setPortGroupList(PortGroupList *portGroups)
{
plm = portGroups;
tvStreamList->setModel(plm->getStreamModel());
// XXX: It would be ideal if we only needed to do the below to
// get the proxy model to do its magic. However, the QModelIndex
// used by the source model and the proxy model are different
// i.e. the row, column, internalId/internalPtr used by both
// will be different. Since our domain objects - PortGroupList,
// PortGroup, Port etc. use these attributes, we need to map the
// proxy's index to the source's index before invoking any domain
// object methods
// TODO: research if we can skip the mapping when the domain
// objects' design is reviewed
if (proxyPortModel) {
proxyPortModel->setSourceModel(plm->getPortModel());
tvPortList->setModel(proxyPortModel);
}
else
tvPortList->setModel(plm->getPortModel());
connect( plm->getPortModel(),
SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_portModel_dataChanged(const QModelIndex&,
const QModelIndex&)));
connect(plm->getPortModel(), SIGNAL(modelReset()),
SLOT(when_portModel_reset()));
connect( tvPortList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_portView_currentChanged(const QModelIndex&,
const QModelIndex&)));
connect(this,
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
devicesWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
connect(plm->getStreamModel(), SIGNAL(rowsInserted(QModelIndex, int, int)),
SLOT(updateStreamViewActions()));
connect(plm->getStreamModel(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
@ -158,9 +89,6 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
tvStreamList->resizeColumnToContents(StreamModel::StreamIcon);
tvStreamList->resizeColumnToContents(StreamModel::StreamStatus);
// Initially we don't have any ports/streams/devices
// - so send signal triggers
when_portView_currentChanged(QModelIndex(), QModelIndex());
updateStreamViewActions();
connect(plm->getStreamModel(),
@ -171,158 +99,18 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
this, SLOT(streamModelDataChanged()));
}
void PortsWindow::streamModelDataChanged()
void StreamsWidget::streamModelDataChanged()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (plm->isPort(current))
plm->port(current).recalculateAverageRates();
if (plm->isPort(currentPortIndex_))
plm->port(currentPortIndex_).recalculateAverageRates();
}
PortsWindow::~PortsWindow()
StreamsWidget::~StreamsWidget()
{
delete delegate;
delete proxyPortModel;
delete applyMsg_;
}
int PortsWindow::portGroupCount()
{
return plm->numPortGroups();
}
int PortsWindow::reservedPortCount()
{
int count = 0;
int n = portGroupCount();
for (int i = 0; i < n; i++)
count += plm->portGroupByIndex(i).numReservedPorts();
return count;
}
//! Always return true
bool PortsWindow::openSession(
const OstProto::SessionContent *session,
QString & /*error*/)
{
QProgressDialog progress("Opening Session", NULL,
0, session->port_groups_size(), mainWindow);
progress.show();
progress.setEnabled(true); // since parent (mainWindow) is disabled
plm->removeAllPortGroups();
for (int i = 0; i < session->port_groups_size(); i++) {
const OstProto::PortGroupContent &pgc = session->port_groups(i);
PortGroup *pg = new PortGroup(QString::fromStdString(
pgc.server_name()),
quint16(pgc.server_port()));
pg->setConfigAtConnect(&pgc);
plm->addPortGroup(*pg);
progress.setValue(i+1);
}
return true;
}
/*!
* Prepare content to be saved for a session
*
* If port reservation is in use, saves only 'my' reserved ports
*
* Returns false, if user cancels op; true, otherwise
*/
bool PortsWindow::saveSession(
OstProto::SessionContent *session, // OUT param
QString & /*error*/,
QProgressDialog *progress)
{
int n = portGroupCount();
QString myself;
if (progress) {
progress->setLabelText("Preparing Ports and PortGroups ...");
progress->setRange(0, n);
}
if (reservedPortCount())
myself = appSettings->value(kUserKey, kUserDefaultValue).toString();
for (int i = 0; i < n; i++)
{
PortGroup &pg = plm->portGroupByIndex(i);
OstProto::PortGroupContent *pgc = session->add_port_groups();
pgc->set_server_name(pg.serverName().toStdString());
pgc->set_server_port(pg.serverPort());
for (int j = 0; j < pg.numPorts(); j++)
{
if (myself != pg.mPorts.at(j)->userName())
continue;
OstProto::PortContent *pc = pgc->add_ports();
OstProto::Port *p = pc->mutable_port_config();
// XXX: We save the entire OstProto::Port even though some
// fields may be ephemeral; while opening we use only relevant
// fields
pg.mPorts.at(j)->protoDataCopyInto(p);
for (int k = 0; k < pg.mPorts.at(j)->numStreams(); k++)
{
OstProto::Stream *s = pc->add_streams();
pg.mPorts.at(j)->streamByIndex(k)->protoDataCopyInto(*s);
}
for (int k = 0; k < pg.mPorts.at(j)->numDeviceGroups(); k++)
{
OstProto::DeviceGroup *dg = pc->add_device_groups();
dg->CopyFrom(*(pg.mPorts.at(j)->deviceGroupByIndex(k)));
}
}
if (progress) {
if (progress->wasCanceled())
return false;
progress->setValue(i);
}
if (i % 2 == 0)
qApp->processEvents();
}
return true;
}
void PortsWindow::clearCurrentSelection()
{
tvPortList->selectionModel()->clearCurrentIndex();
tvPortList->clearSelection();
}
void PortsWindow::showMyReservedPortsOnly(bool enabled)
{
if (!proxyPortModel)
return;
if (enabled) {
QString rx = "Port Group|\\["
+ QRegExp::escape(appSettings->value(kUserKey,
kUserDefaultValue).toString())
+ "\\]";
qDebug("%s: regexp: <%s>", __FUNCTION__, qPrintable(rx));
proxyPortModel->setFilterRegExp(QRegExp(rx));
}
else
proxyPortModel->setFilterRegExp(QRegExp(""));
}
void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
void StreamsWidget::on_tvStreamList_activated(const QModelIndex & index)
{
if (!index.isValid())
{
@ -332,9 +120,7 @@ void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
qDebug("stream list activated\n");
Port &curPort = plm->port(proxyPortModel ?
proxyPortModel->mapToSource(tvPortList->currentIndex()) :
tvPortList->currentIndex());
Port &curPort = plm->port(currentPortIndex_);
QList<Stream*> streams;
streams.append(curPort.mutableStreamByIndex(index.row(), false));
@ -346,197 +132,95 @@ void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
}
}
void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex,
const QModelIndex& previousIndex)
void StreamsWidget::setCurrentPortIndex(const QModelIndex &portIndex)
{
QModelIndex current = currentIndex;
QModelIndex previous = previousIndex;
if (!plm)
return;
if (proxyPortModel) {
current = proxyPortModel->mapToSource(current);
previous = proxyPortModel->mapToSource(previous);
}
plm->getStreamModel()->setCurrentPortIndex(current);
updatePortViewActions(currentIndex);
updateStreamViewActions();
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel
if (!plm->isPort(portIndex))
return;
qDebug("In %s", __FUNCTION__);
if (previous.isValid() && plm->isPort(previous))
{
disconnect(&(plm->port(previous)), SIGNAL(portRateChanged(int, int)),
// Disconnect previous port
if (plm->isPort(currentPortIndex_))
disconnect(&(plm->port(currentPortIndex_)),
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 welcome page");
swDetail->setCurrentIndex(0); // welcome page
}
else
{
if (plm->isPortGroup(current))
{
swDetail->setCurrentIndex(1); // portGroup detail page
}
else if (plm->isPort(current))
{
swDetail->setCurrentIndex(2); // port detail page
currentPortIndex_ = portIndex;
plm->getStreamModel()->setCurrentPortIndex(portIndex);
// Connect current port
if (plm->isPort(currentPortIndex_))
connect(&(plm->port(currentPortIndex_)),
SIGNAL(portRateChanged(int, int)),
this, SLOT(updatePortRates()));
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("Click <img src=':/icons/control_play'/> "
"to transmit packets");
else
applyHint->setText("");
}
}
emit currentPortChanged(current, previous);
updateStreamViewActions();
}
void PortsWindow::when_portModel_dataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight)
void StreamsWidget::on_startTx_clicked()
{
qDebug("In %s %d:(%d, %d) - %d:(%d, %d)", __FUNCTION__,
topLeft.parent().isValid(), topLeft.row(), topLeft.column(),
bottomRight.parent().isValid(), bottomRight.row(), bottomRight.column());
Q_ASSERT(plm->isPort(currentPortIndex_));
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))
#endif
if (((topLeft < tvPortList->currentIndex()) ||
(topLeft == tvPortList->currentIndex())) &&
(((tvPortList->currentIndex() < bottomRight)) ||
(tvPortList->currentIndex() == bottomRight)))
{
// Update UI to reflect potential change in exclusive mode,
// transmit mode et al
when_portView_currentChanged(tvPortList->currentIndex(),
tvPortList->currentIndex());
}
}
void PortsWindow::when_portModel_reset()
{
when_portView_currentChanged(QModelIndex(), tvPortList->currentIndex());
}
void PortsWindow::on_startTx_clicked()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
QModelIndex curPortGroup = plm->getPortModel()->parent(current);
QModelIndex curPortGroup = plm->getPortModel()->parent(currentPortIndex_);
Q_ASSERT(curPortGroup.isValid());
Q_ASSERT(plm->isPortGroup(curPortGroup));
QList<uint> portList({plm->port(current).id()});
QList<uint> portList({plm->port(currentPortIndex_).id()});
plm->portGroup(curPortGroup).startTx(&portList);
}
void PortsWindow::on_stopTx_clicked()
void StreamsWidget::on_stopTx_clicked()
{
QModelIndex current = tvPortList->currentIndex();
Q_ASSERT(plm->isPort(currentPortIndex_));
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
QModelIndex curPortGroup = plm->getPortModel()->parent(current);
QModelIndex curPortGroup = plm->getPortModel()->parent(currentPortIndex_);
Q_ASSERT(curPortGroup.isValid());
Q_ASSERT(plm->isPortGroup(curPortGroup));
QList<uint> portList({plm->port(current).id()});
QList<uint> portList({plm->port(currentPortIndex_).id()});
plm->portGroup(curPortGroup).stopTx(&portList);
}
void PortsWindow::on_averagePacketsPerSec_editingFinished()
void StreamsWidget::on_averagePacketsPerSec_editingFinished()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
Q_ASSERT(plm->isPort(currentPortIndex_));
bool isOk;
double pps = XLocale().toDouble(averagePacketsPerSec->text(), &isOk);
plm->port(current).setAveragePacketRate(pps);
plm->port(currentPortIndex_).setAveragePacketRate(pps);
}
void PortsWindow::on_averageBitsPerSec_editingFinished()
void StreamsWidget::on_averageBitsPerSec_editingFinished()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
Q_ASSERT(plm->isPort(currentPortIndex_));
bool isOk;
double bps = XLocale().toDouble(averageBitsPerSec->text(), &isOk);
plm->port(current).setAverageBitRate(bps);
plm->port(currentPortIndex_).setAverageBitRate(bps);
}
void PortsWindow::updatePortRates()
void StreamsWidget::updatePortRates()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (!current.isValid())
if (!currentPortIndex_.isValid())
return;
if (!plm->isPort(current))
if (!plm->isPort(currentPortIndex_))
return;
averagePacketsPerSec->setText(QString("%L1")
.arg(plm->port(current).averagePacketRate(), 0, 'f', 4));
.arg(plm->port(currentPortIndex_).averagePacketRate(), 0, 'f', 4));
averageBitsPerSec->setText(QString("%L1")
.arg(plm->port(current).averageBitRate(), 0, 'f', 0));
.arg(plm->port(currentPortIndex_).averageBitRate(), 0, 'f', 0));
}
void PortsWindow::updateStreamViewActions()
void StreamsWidget::updateStreamViewActions()
{
QModelIndex current = tvPortList->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
// For some reason hasSelection() returns true even if selection size is 0
// so additional check for size introduced
if (tvStreamList->selectionModel()->hasSelection() &&
@ -565,7 +249,7 @@ void PortsWindow::updateStreamViewActions()
else
{
qDebug("No selection");
if (plm->isPort(current))
if (plm->isPort(currentPortIndex_))
actionNew_Stream->setEnabled(true);
else
actionNew_Stream->setDisabled(true);
@ -573,274 +257,14 @@ void PortsWindow::updateStreamViewActions()
actionDuplicate_Stream->setDisabled(true);
actionDelete_Stream->setDisabled(true);
}
actionOpen_Streams->setEnabled(plm->isPort(current));
actionOpen_Streams->setEnabled(plm->isPort(currentPortIndex_));
actionSave_Streams->setEnabled(tvStreamList->model()->rowCount() > 0);
startTx->setEnabled(tvStreamList->model()->rowCount() > 0);
stopTx->setEnabled(tvStreamList->model()->rowCount() > 0);
}
void PortsWindow::updateApplyHint(int /*portGroupId*/, int /*portId*/,
bool configChanged)
{
if (configChanged)
applyHint->setText("Configuration has changed - "
"<font color='red'><b>click Apply</b></font> "
"to activate the changes");
else if (tvStreamList->model()->rowCount() > 0)
applyHint->setText("Configuration activated - "
"click <img src=':/icons/control_play'/> "
"to transmit packets");
else
applyHint->setText("Configuration activated");
}
void PortsWindow::updatePortViewActions(const QModelIndex& currentIndex)
{
QModelIndex current = currentIndex;
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (!current.isValid())
{
qDebug("current is now invalid");
actionDelete_Port_Group->setDisabled(true);
actionConnect_Port_Group->setDisabled(true);
actionDisconnect_Port_Group->setDisabled(true);
actionExclusive_Control->setDisabled(true);
actionPort_Configuration->setDisabled(true);
goto _EXIT;
}
qDebug("currentChanged %p", (void*)current.internalId());
if (plm->isPortGroup(current))
{
actionDelete_Port_Group->setEnabled(true);
actionExclusive_Control->setDisabled(true);
actionPort_Configuration->setDisabled(true);
switch(plm->portGroup(current).state())
{
case QAbstractSocket::UnconnectedState:
case QAbstractSocket::ClosingState:
qDebug("state = unconnected|closing");
actionConnect_Port_Group->setEnabled(true);
actionDisconnect_Port_Group->setDisabled(true);
break;
case QAbstractSocket::HostLookupState:
case QAbstractSocket::ConnectingState:
case QAbstractSocket::ConnectedState:
qDebug("state = lookup|connecting|connected");
actionConnect_Port_Group->setDisabled(true);
actionDisconnect_Port_Group->setEnabled(true);
break;
case QAbstractSocket::BoundState:
case QAbstractSocket::ListeningState:
default:
// FIXME(LOW): indicate error
qDebug("unexpected state");
break;
}
}
else if (plm->isPort(current))
{
actionDelete_Port_Group->setDisabled(true);
actionConnect_Port_Group->setDisabled(true);
actionDisconnect_Port_Group->setDisabled(true);
actionExclusive_Control->setEnabled(true);
if (plm->port(current).hasExclusiveControl())
actionExclusive_Control->setChecked(true);
else
actionExclusive_Control->setChecked(false);
actionPort_Configuration->setEnabled(true);
}
_EXIT:
return;
}
void PortsWindow::on_pbApply_clicked()
{
QModelIndex curPort;
QModelIndex curPortGroup;
curPort = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
curPort = proxyPortModel->mapToSource(curPort);
if (!curPort.isValid())
{
qDebug("%s: curPort is invalid", __FUNCTION__);
goto _exit;
}
if (!plm->isPort(curPort))
{
qDebug("%s: curPort is not a port", __FUNCTION__);
goto _exit;
}
if (plm->port(curPort).getStats().state().is_transmit_on())
{
QMessageBox::information(0, "Configuration Change",
"Please stop transmit on the port before applying any changes");
goto _exit;
}
curPortGroup = plm->getPortModel()->parent(curPort);
if (!curPortGroup.isValid())
{
qDebug("%s: curPortGroup is invalid", __FUNCTION__);
goto _exit;
}
if (!plm->isPortGroup(curPortGroup))
{
qDebug("%s: curPortGroup is not a portGroup", __FUNCTION__);
goto _exit;
}
disconnect(applyMsg_);
connect(&(plm->portGroup(curPortGroup)), SIGNAL(applyFinished()),
applyMsg_, SLOT(hide()));
applyMsg_->show();
// FIXME(HI): shd this be a signal?
//portGroup.when_configApply(port);
// FIXME(MED): mixing port id and index!!!
plm->portGroup(curPortGroup).when_configApply(plm->port(curPort).id());
_exit:
return;
#if 0
// TODO (LOW): This block is for testing only
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (current.isValid())
qDebug("current = %llx", current.internalId());
else
qDebug("current is invalid");
#endif
}
void PortsWindow::on_actionNew_Port_Group_triggered()
{
bool ok;
QString text = QInputDialog::getText(this,
"Add Port Group", "Port Group Address (HostName[:Port])",
QLineEdit::Normal, lastNewPortGroup, &ok);
if (ok)
{
QStringList addr = text.split(":");
quint16 port = DEFAULT_SERVER_PORT;
if (addr.size() > 2) { // IPv6 Address
// IPv6 addresses with port number SHOULD be specified as
// [2001:db8::1]:80 (RFC5952 Sec6) to avoid ambiguity due to ':'
addr = text.split("]:");
if (addr.size() > 1)
port = addr[1].toUShort();
}
else if (addr.size() == 2) // Hostname/IPv4 + Port specified
port = addr[1].toUShort();
// Play nice and remove square brackets irrespective of addr type
addr[0].remove(QChar('['));
addr[0].remove(QChar(']'));
PortGroup *pg = new PortGroup(addr[0], port);
plm->addPortGroup(*pg);
lastNewPortGroup = text;
}
}
void PortsWindow::on_actionDelete_Port_Group_triggered()
{
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (current.isValid())
plm->removePortGroup(plm->portGroup(current));
}
void PortsWindow::on_actionConnect_Port_Group_triggered()
{
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (current.isValid())
plm->portGroup(current).connectToHost();
}
void PortsWindow::on_actionDisconnect_Port_Group_triggered()
{
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (current.isValid())
plm->portGroup(current).disconnectFromHost();
}
void PortsWindow::on_actionExclusive_Control_triggered(bool checked)
{
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (plm->isPort(current))
{
OstProto::Port config;
config.set_is_exclusive_control(checked);
plm->portGroup(current.parent()).modifyPort(current.row(), config);
}
}
void PortsWindow::on_actionPort_Configuration_triggered()
{
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (!plm->isPort(current))
return;
Port &port = plm->port(current);
OstProto::Port config;
// XXX: we don't call Port::protoDataCopyInto() to get config b'coz
// we want only the modifiable fields populated to send to Drone
// TODO: extend Port::protoDataCopyInto() to accept an optional param
// which says copy only modifiable fields
//plm->port(current).protoDataCopyInto(&config);
config.set_transmit_mode(port.transmitMode());
config.set_is_tracking_stream_stats(port.trackStreamStats());
config.set_is_exclusive_control(port.hasExclusiveControl());
config.set_user_name(port.userName().toStdString());
PortConfigDialog dialog(config, port.getStats().state(), this);
if (dialog.exec() == QDialog::Accepted)
plm->portGroup(current.parent()).modifyPort(current.row(), config);
}
void PortsWindow::on_actionNew_Stream_triggered()
void StreamsWidget::on_actionNew_Stream_triggered()
{
qDebug("New Stream Action");
@ -863,9 +287,7 @@ void PortsWindow::on_actionNew_Stream_triggered()
count = selectionModel->selection().at(0).height();
}
Port &curPort = plm->port(proxyPortModel ?
proxyPortModel->mapToSource(tvPortList->currentIndex()) :
tvPortList->currentIndex());
Port &curPort = plm->port(currentPortIndex_);
QList<Stream*> streams;
for (int i = 0; i < count; i++)
@ -877,7 +299,7 @@ void PortsWindow::on_actionNew_Stream_triggered()
streamModel->insert(row, streams);
}
void PortsWindow::on_actionEdit_Stream_triggered()
void StreamsWidget::on_actionEdit_Stream_triggered()
{
qDebug("Edit Stream Action");
@ -885,9 +307,7 @@ void PortsWindow::on_actionEdit_Stream_triggered()
if (!streamModel->hasSelection())
return;
Port &curPort = plm->port(proxyPortModel ?
proxyPortModel->mapToSource(tvPortList->currentIndex()) :
tvPortList->currentIndex());
Port &curPort = plm->port(currentPortIndex_);
QList<Stream*> streams;
foreach(QModelIndex index, streamModel->selectedRows())
@ -900,16 +320,12 @@ void PortsWindow::on_actionEdit_Stream_triggered()
}
}
void PortsWindow::on_actionDuplicate_Stream_triggered()
void StreamsWidget::on_actionDuplicate_Stream_triggered()
{
QItemSelectionModel* model = tvStreamList->selectionModel();
QModelIndex current = tvPortList->selectionModel()->currentIndex();
qDebug("Duplicate Stream Action");
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
if (model->hasSelection())
{
bool isOk;
@ -922,13 +338,13 @@ void PortsWindow::on_actionDuplicate_Stream_triggered()
QList<int> list;
foreach(QModelIndex index, model->selectedRows())
list.append(index.row());
plm->port(current).duplicateStreams(list, count);
plm->port(currentPortIndex_).duplicateStreams(list, count);
}
else
qDebug("No selection");
}
void PortsWindow::on_actionDelete_Stream_triggered()
void StreamsWidget::on_actionDelete_Stream_triggered()
{
qDebug("Delete Stream Action");
@ -948,24 +364,20 @@ void PortsWindow::on_actionDelete_Stream_triggered()
qDebug("No selection");
}
void PortsWindow::on_actionOpen_Streams_triggered()
void StreamsWidget::on_actionOpen_Streams_triggered()
{
qDebug("Open Streams Action");
QStringList fileTypes = StreamFileFormat::supportedFileTypes(
StreamFileFormat::kOpenFile);
QString fileType;
QModelIndex current = tvPortList->selectionModel()->currentIndex();
static QString dirName;
QString fileName;
QString errorStr;
bool append = true;
bool ret;
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
Q_ASSERT(plm->isPort(current));
Q_ASSERT(plm->isPort(currentPortIndex_));
if (fileTypes.size())
fileType = fileTypes.at(0);
@ -998,7 +410,7 @@ void PortsWindow::on_actionOpen_Streams_triggered()
Q_ASSERT(false);
}
ret = plm->port(current).openStreams(fileName, append, errorStr);
ret = plm->port(currentPortIndex_).openStreams(fileName, append, errorStr);
if (!ret || !errorStr.isEmpty())
{
QMessageBox msgBox(this);
@ -1014,16 +426,16 @@ void PortsWindow::on_actionOpen_Streams_triggered()
msgBox.exec();
}
dirName = QFileInfo(fileName).absolutePath();
updateStreamViewActions();
_exit:
return;
}
void PortsWindow::on_actionSave_Streams_triggered()
void StreamsWidget::on_actionSave_Streams_triggered()
{
qDebug("Save Streams Action");
QModelIndex current = tvPortList->selectionModel()->currentIndex();
static QString fileName;
QStringList fileTypes = StreamFileFormat::supportedFileTypes(
StreamFileFormat::kSaveFile);
@ -1031,9 +443,6 @@ void PortsWindow::on_actionSave_Streams_triggered()
QString errorStr;
QFileDialog::Options options;
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
// On Mac OS with Native Dialog, getSaveFileName() ignores fileType
// which we need
#if defined(Q_OS_MAC)
@ -1043,7 +452,7 @@ void PortsWindow::on_actionSave_Streams_triggered()
if (fileTypes.size())
fileType = fileTypes.at(0);
Q_ASSERT(plm->isPort(current));
Q_ASSERT(plm->isPort(currentPortIndex_));
_retry:
fileName = QFileDialog::getSaveFileName(this, tr("Save Streams"),
@ -1083,7 +492,7 @@ _retry:
// TODO: all or selected?
if (!plm->port(current).saveStreams(fileName, fileType, errorStr))
if (!plm->port(currentPortIndex_).saveStreams(fileName, fileType, errorStr))
QMessageBox::critical(this, qApp->applicationName(), errorStr);
else if (!errorStr.isEmpty())
QMessageBox::warning(this, qApp->applicationName(), errorStr);

View File

@ -17,61 +17,30 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef _PORTS_WINDOW_H
#define _PORTS_WINDOW_H
#ifndef _STREAMS_WIDGET_H
#define _STREAMS_WIDGET_H
#include <QWidget>
#include <QAbstractItemModel>
#include "ui_portswindow.h"
#include "ui_streamswidget.h"
#include "portgrouplist.h"
#include <QWidget>
//#include <QAbstractItemModel>
class ApplyMessage;
class PortGroupList;
class QAbstractItemDelegate;
class QProgressDialog;
class QSortFilterProxyModel;
namespace OstProto {
class SessionContent;
}
class PortsWindow : public QWidget, private Ui::PortsWindow, private Ui::StreamsWidget
class StreamsWidget : public QWidget, private Ui::StreamsWidget
{
Q_OBJECT
//QAbstractItemModel *slm; // stream list model
PortGroupList *plm;
public:
PortsWindow(PortGroupList *pgl, QWidget *parent = 0);
~PortsWindow();
StreamsWidget(QWidget *parent = 0);
~StreamsWidget();
int portGroupCount();
int reservedPortCount();
bool openSession(const OstProto::SessionContent *session,
QString &error);
bool saveSession(OstProto::SessionContent *session,
QString &error,
QProgressDialog *progress = NULL);
signals:
void currentPortChanged(const QModelIndex &current,
const QModelIndex &previous);
private:
QString lastNewPortGroup;
QAbstractItemDelegate *delegate;
QSortFilterProxyModel *proxyPortModel;
ApplyMessage *applyMsg_;
void setPortGroupList(PortGroupList *portGroups);
public slots:
void clearCurrentSelection();
void showMyReservedPortsOnly(bool enabled);
void setCurrentPortIndex(const QModelIndex &portIndex);
private slots:
void updateApplyHint(int portGroupId, int portId, bool configChanged);
void updatePortViewActions(const QModelIndex& currentIndex);
void updateStreamViewActions();
void on_startTx_clicked();
@ -80,21 +49,6 @@ private slots:
void on_averageBitsPerSec_editingFinished();
void updatePortRates();
void on_tvStreamList_activated(const QModelIndex & index);
void when_portView_currentChanged(const QModelIndex& currentIndex,
const QModelIndex& previousIndex);
void when_portModel_dataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight);
void when_portModel_reset();
void on_pbApply_clicked();
void on_actionNew_Port_Group_triggered();
void on_actionDelete_Port_Group_triggered();
void on_actionConnect_Port_Group_triggered();
void on_actionDisconnect_Port_Group_triggered();
void on_actionExclusive_Control_triggered(bool checked);
void on_actionPort_Configuration_triggered();
void on_actionNew_Stream_triggered();
void on_actionEdit_Stream_triggered();
@ -105,6 +59,12 @@ private slots:
void on_actionSave_Streams_triggered();
void streamModelDataChanged();
private:
PortGroupList *plm{nullptr}; // FIXME: rename to portGroups_?
QModelIndex currentPortIndex_;
QAbstractItemDelegate *delegate;
};
#endif