Replace Port Stats Link/Tx/Capture state text with icons
* All 3 icons are combined into a single row instead of 3 separate rows * Tooltip to clarify meaning of icons * Qt Model-View displays icon left-aligned, so use a custom delegate to center-align it * Add a icon for "Transmit On" * Edit icons for "Start/Stop Capture"
This commit is contained in:
parent
48721cece4
commit
496e044bdd
40
client/icononlydelegate.h
Normal file
40
client/icononlydelegate.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2018 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ICON_ONLY_DELEGATE
|
||||||
|
#define _ICON_ONLY_DELEGATE
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
class IconOnlyDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
using QStyledItemDelegate::QStyledItemDelegate;
|
||||||
|
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
opt.decorationPosition = QStyleOptionViewItem::Top;
|
||||||
|
opt.features.setFlag(QStyleOptionViewItem::HasDisplay, false);
|
||||||
|
QStyledItemDelegate::paint(painter, opt, index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 514 B |
Binary file not shown.
Before Width: | Height: | Size: 417 B After Width: | Height: | Size: 435 B |
BIN
client/icons/transmit_on.png
Normal file
BIN
client/icons/transmit_on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 749 B |
@ -1,48 +1,49 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/" >
|
<qresource prefix="/">
|
||||||
<file>icons/about.png</file>
|
<file>icons/transmit_on.png</file>
|
||||||
<file>icons/add.png</file>
|
<file>icons/about.png</file>
|
||||||
<file>icons/arrow_down.png</file>
|
<file>icons/add.png</file>
|
||||||
<file>icons/arrow_left.png</file>
|
<file>icons/arrow_down.png</file>
|
||||||
<file>icons/arrow_right.png</file>
|
<file>icons/arrow_left.png</file>
|
||||||
<file>icons/arrow_up.png</file>
|
<file>icons/arrow_right.png</file>
|
||||||
<file>icons/bullet_error.png</file>
|
<file>icons/arrow_up.png</file>
|
||||||
<file>icons/bullet_green.png</file>
|
<file>icons/bullet_error.png</file>
|
||||||
<file>icons/bullet_orange.png</file>
|
<file>icons/bullet_green.png</file>
|
||||||
<file>icons/bullet_red.png</file>
|
<file>icons/bullet_orange.png</file>
|
||||||
<file>icons/bullet_white.png</file>
|
<file>icons/bullet_red.png</file>
|
||||||
<file>icons/bullet_yellow.png</file>
|
<file>icons/bullet_white.png</file>
|
||||||
<file>icons/control_play.png</file>
|
<file>icons/bullet_yellow.png</file>
|
||||||
<file>icons/control_stop.png</file>
|
<file>icons/control_play.png</file>
|
||||||
<file>icons/deco_exclusive.png</file>
|
<file>icons/control_stop.png</file>
|
||||||
<file>icons/delete.png</file>
|
<file>icons/deco_exclusive.png</file>
|
||||||
<file>icons/devicegroup_add.png</file>
|
<file>icons/delete.png</file>
|
||||||
<file>icons/devicegroup_delete.png</file>
|
<file>icons/devicegroup_add.png</file>
|
||||||
<file>icons/devicegroup_edit.png</file>
|
<file>icons/devicegroup_delete.png</file>
|
||||||
<file>icons/exit.png</file>
|
<file>icons/devicegroup_edit.png</file>
|
||||||
<file>icons/gaps.png</file>
|
<file>icons/exit.png</file>
|
||||||
<file>icons/help.png</file>
|
<file>icons/gaps.png</file>
|
||||||
<file>icons/logo.png</file>
|
<file>icons/help.png</file>
|
||||||
<file>icons/magnifier.png</file>
|
<file>icons/logo.png</file>
|
||||||
<file>icons/name.png</file>
|
<file>icons/magnifier.png</file>
|
||||||
<file>icons/neighbor_clear.png</file>
|
<file>icons/name.png</file>
|
||||||
<file>icons/neighbor_resolve.png</file>
|
<file>icons/neighbor_clear.png</file>
|
||||||
<file>icons/portgroup_add.png</file>
|
<file>icons/neighbor_resolve.png</file>
|
||||||
<file>icons/portgroup_connect.png</file>
|
<file>icons/portgroup_add.png</file>
|
||||||
<file>icons/portgroup_delete.png</file>
|
<file>icons/portgroup_connect.png</file>
|
||||||
<file>icons/portgroup_disconnect.png</file>
|
<file>icons/portgroup_delete.png</file>
|
||||||
<file>icons/portstats_clear.png</file>
|
<file>icons/portgroup_disconnect.png</file>
|
||||||
<file>icons/portstats_clear_all.png</file>
|
<file>icons/portstats_clear.png</file>
|
||||||
<file>icons/portstats_filter.png</file>
|
<file>icons/portstats_clear_all.png</file>
|
||||||
<file>icons/preferences.png</file>
|
<file>icons/portstats_filter.png</file>
|
||||||
<file>icons/qt.png</file>
|
<file>icons/preferences.png</file>
|
||||||
<file>icons/refresh.png</file>
|
<file>icons/qt.png</file>
|
||||||
<file>icons/sound_mute.png</file>
|
<file>icons/refresh.png</file>
|
||||||
<file>icons/sound_none.png</file>
|
<file>icons/sound_mute.png</file>
|
||||||
<file>icons/stream_add.png</file>
|
<file>icons/sound_none.png</file>
|
||||||
<file>icons/stream_delete.png</file>
|
<file>icons/stream_add.png</file>
|
||||||
<file>icons/stream_duplicate.png</file>
|
<file>icons/stream_delete.png</file>
|
||||||
<file>icons/stream_edit.png</file>
|
<file>icons/stream_duplicate.png</file>
|
||||||
<file>icons/stream_stats.png</file>
|
<file>icons/stream_edit.png</file>
|
||||||
</qresource>
|
<file>icons/stream_stats.png</file>
|
||||||
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "portstatsmodel.h"
|
#include "portstatsmodel.h"
|
||||||
#include "portgrouplist.h"
|
#include "portgrouplist.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPixmapCache>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -94,15 +96,12 @@ void PortStatsModel::getDomainIndexes(const QModelIndex &index,
|
|||||||
|
|
||||||
QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
uint pgidx, pidx;
|
|
||||||
int row;
|
|
||||||
|
|
||||||
// Check for a valid index
|
// Check for a valid index
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
// Check for row/column limits
|
// Check for row/column limits
|
||||||
row = index.row();
|
int row = index.row();
|
||||||
if (row >= e_STAT_MAX)
|
if (row >= e_STAT_MAX)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
@ -112,15 +111,22 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
if (index.column() >= (numPorts.last()))
|
if (index.column() >= (numPorts.last()))
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
|
if (role == Qt::TextAlignmentRole)
|
||||||
|
{
|
||||||
|
if (row >= e_STATISTICS_START && row <= e_STATISTICS_END)
|
||||||
|
return Qt::AlignRight; // right-align numbers
|
||||||
|
else
|
||||||
|
return Qt::AlignHCenter; // center-align everything else
|
||||||
|
}
|
||||||
|
|
||||||
|
uint pgidx, pidx;
|
||||||
getDomainIndexes(index, pgidx, pidx);
|
getDomainIndexes(index, pgidx, pidx);
|
||||||
|
|
||||||
|
OstProto::PortStats stats = pgl->mPortGroups.at(pgidx)
|
||||||
|
->mPorts[pidx]->getStats();
|
||||||
// Check role
|
// Check role
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
{
|
{
|
||||||
OstProto::PortStats stats;
|
|
||||||
|
|
||||||
stats = pgl->mPortGroups.at(pgidx)->mPorts[pidx]->getStats();
|
|
||||||
|
|
||||||
switch(row)
|
switch(row)
|
||||||
{
|
{
|
||||||
// Info
|
// Info
|
||||||
@ -128,14 +134,8 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
return pgl->mPortGroups.at(pgidx)->mPorts[pidx]->userName();
|
return pgl->mPortGroups.at(pgidx)->mPorts[pidx]->userName();
|
||||||
|
|
||||||
// States
|
// States
|
||||||
case e_LINK_STATE:
|
case e_COMBO_STATE:
|
||||||
return LinkStateName.at(stats.state().link_state());
|
return QVariant();
|
||||||
|
|
||||||
case e_TRANSMIT_STATE:
|
|
||||||
return BoolStateName.at(stats.state().is_transmit_on());
|
|
||||||
|
|
||||||
case e_CAPTURE_STATE:
|
|
||||||
return BoolStateName.at(stats.state().is_capture_on());
|
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
case e_STAT_FRAMES_RCVD:
|
case e_STAT_FRAMES_RCVD:
|
||||||
@ -201,12 +201,26 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (role == Qt::TextAlignmentRole)
|
else if (role == Qt::DecorationRole)
|
||||||
{
|
{
|
||||||
if (row >= e_STATISTICS_START && row <= e_STATISTICS_END)
|
if (row == e_COMBO_STATE)
|
||||||
return Qt::AlignRight; // right-align numbers
|
return statusIcons(
|
||||||
|
stats.state().link_state(),
|
||||||
|
stats.state().is_transmit_on(),
|
||||||
|
stats.state().is_capture_on());
|
||||||
else
|
else
|
||||||
return Qt::AlignHCenter; // center-align everything else
|
return QVariant();
|
||||||
|
}
|
||||||
|
else if (role == Qt::ToolTipRole)
|
||||||
|
{
|
||||||
|
if (row == e_COMBO_STATE)
|
||||||
|
return QString("Transmit:<b><i>%1</i></b> Link:<b><i>%2</i></b> "
|
||||||
|
"Capture:<b><i>%3</i></b>")
|
||||||
|
.arg(BoolStateName.at(stats.state().is_transmit_on()))
|
||||||
|
.arg(LinkStateName.at(stats.state().link_state()))
|
||||||
|
.arg(BoolStateName.at(stats.state().is_capture_on()));
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@ -351,3 +365,49 @@ void PortStatsModel::when_portGroup_stats_update(quint32 /*portGroupId*/)
|
|||||||
|
|
||||||
emit dataChanged(topLeft, bottomRight);
|
emit dataChanged(topLeft, bottomRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap PortStatsModel::statusIcons(
|
||||||
|
int linkState, bool transmit, bool capture) const
|
||||||
|
{
|
||||||
|
QPixmap pixmap;
|
||||||
|
QString key = QString("$ost:statusList:%1:%2:%3")
|
||||||
|
.arg(linkState).arg(transmit).arg(capture);
|
||||||
|
|
||||||
|
if (QPixmapCache::find(key, pixmap))
|
||||||
|
return pixmap;
|
||||||
|
|
||||||
|
static int sz = QPixmap(":/icons/transmit_on.png").width();
|
||||||
|
|
||||||
|
// Assume all icons are of same size and are square
|
||||||
|
QPixmap blank(sz, sz);
|
||||||
|
blank.fill(Qt::transparent);
|
||||||
|
|
||||||
|
pixmap = QPixmap(sz*3, sz);
|
||||||
|
pixmap.fill(Qt::transparent);
|
||||||
|
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
|
||||||
|
painter.drawPixmap(0, 0,
|
||||||
|
transmit ? QPixmap(":/icons/transmit_on.png") : blank);
|
||||||
|
|
||||||
|
switch (linkState) {
|
||||||
|
case OstProto::LinkStateUp:
|
||||||
|
painter.drawPixmap(sz, 0, QPixmap(":/icons/bullet_green.png"));
|
||||||
|
break;
|
||||||
|
case OstProto::LinkStateDown:
|
||||||
|
painter.drawPixmap(sz, 0, QPixmap(":/icons/bullet_red.png"));
|
||||||
|
break;
|
||||||
|
case OstProto::LinkStateUnknown:
|
||||||
|
painter.drawPixmap(sz, 0, QPixmap(":/icons/bullet_white.png"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
painter.drawPixmap(sz, 0, blank);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawPixmap(sz*2, 0,
|
||||||
|
capture ? QPixmap(":/icons/sound_none.png") : blank);
|
||||||
|
|
||||||
|
|
||||||
|
QPixmapCache::insert(key, pixmap);
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
@ -36,11 +36,9 @@ typedef enum {
|
|||||||
// State
|
// State
|
||||||
e_STATE_START,
|
e_STATE_START,
|
||||||
|
|
||||||
e_LINK_STATE = e_STATE_START,
|
e_COMBO_STATE = e_STATE_START,
|
||||||
e_TRANSMIT_STATE,
|
|
||||||
e_CAPTURE_STATE,
|
|
||||||
|
|
||||||
e_STATE_END = e_CAPTURE_STATE,
|
e_STATE_END = e_COMBO_STATE,
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
e_STATISTICS_START,
|
e_STATISTICS_START,
|
||||||
@ -77,9 +75,7 @@ typedef enum {
|
|||||||
static QStringList PortStatName = (QStringList()
|
static QStringList PortStatName = (QStringList()
|
||||||
<< "User"
|
<< "User"
|
||||||
|
|
||||||
<< "Link State"
|
<< "Status"
|
||||||
<< "Transmit State"
|
|
||||||
<< "Capture State"
|
|
||||||
|
|
||||||
<< "Frames Received"
|
<< "Frames Received"
|
||||||
<< "Frames Sent"
|
<< "Frames Sent"
|
||||||
@ -160,6 +156,7 @@ class PortStatsModel : public QAbstractTableModel
|
|||||||
|
|
||||||
void getDomainIndexes(const QModelIndex &index,
|
void getDomainIndexes(const QModelIndex &index,
|
||||||
uint &portGroupIdx, uint &portIdx) const;
|
uint &portGroupIdx, uint &portIdx) const;
|
||||||
|
QPixmap statusIcons(int linkState, bool transmit, bool capture) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "portstatswindow.h"
|
#include "portstatswindow.h"
|
||||||
|
|
||||||
|
#include "icononlydelegate.h"
|
||||||
#include "portstatsfilterdialog.h"
|
#include "portstatsfilterdialog.h"
|
||||||
#include "portstatsmodel.h"
|
#include "portstatsmodel.h"
|
||||||
#include "portstatsproxymodel.h"
|
#include "portstatsproxymodel.h"
|
||||||
@ -54,6 +55,24 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
tvPortStats->verticalHeader()->setDefaultSectionSize(
|
tvPortStats->verticalHeader()->setDefaultSectionSize(
|
||||||
tvPortStats->verticalHeader()->minimumSectionSize());
|
tvPortStats->verticalHeader()->minimumSectionSize());
|
||||||
|
|
||||||
|
statusDelegate = new IconOnlyDelegate(this);
|
||||||
|
#if 0
|
||||||
|
// XXX: Ideally we should use this, but it doesn't work because in
|
||||||
|
// this constructor, the port model is empty and model->index() returns
|
||||||
|
// an invalid index ...
|
||||||
|
tvPortStats->setItemDelegateForRow(
|
||||||
|
proxyStatsModel ?
|
||||||
|
proxyStatsModel->mapFromSource(model->index(e_COMBO_STATE, 0))
|
||||||
|
.row() :
|
||||||
|
e_COMBO_STATE,
|
||||||
|
statusDelegate);
|
||||||
|
#else
|
||||||
|
// ... so we use this hard-coded hack
|
||||||
|
tvPortStats->setItemDelegateForRow(
|
||||||
|
proxyStatsModel ? e_COMBO_STATE-1 : e_COMBO_STATE,
|
||||||
|
statusDelegate);
|
||||||
|
#endif
|
||||||
|
|
||||||
connect(tvPortStats->selectionModel(),
|
connect(tvPortStats->selectionModel(),
|
||||||
SIGNAL(selectionChanged(
|
SIGNAL(selectionChanged(
|
||||||
const QItemSelection&, const QItemSelection&)),
|
const QItemSelection&, const QItemSelection&)),
|
||||||
@ -65,6 +84,7 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
PortStatsWindow::~PortStatsWindow()
|
PortStatsWindow::~PortStatsWindow()
|
||||||
{
|
{
|
||||||
delete proxyStatsModel;
|
delete proxyStatsModel;
|
||||||
|
delete statusDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------- SLOTS (public) -------------- */
|
/* ------------- SLOTS (public) -------------- */
|
||||||
|
@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "portstatsmodel.h"
|
#include "portstatsmodel.h"
|
||||||
|
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
|
class QStyledItemDelegate;
|
||||||
|
|
||||||
class PortStatsWindow : public QWidget, public Ui::PortStatsWindow
|
class PortStatsWindow : public QWidget, public Ui::PortStatsWindow
|
||||||
{
|
{
|
||||||
@ -63,6 +64,7 @@ private:
|
|||||||
PortGroupList *pgl;
|
PortGroupList *pgl;
|
||||||
PortStatsModel *model;
|
PortStatsModel *model;
|
||||||
QSortFilterProxyModel *proxyStatsModel;
|
QSortFilterProxyModel *proxyStatsModel;
|
||||||
|
QStyledItemDelegate *statusDelegate;
|
||||||
QModelIndexList selectedColumns;
|
QModelIndexList selectedColumns;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user