Improve UX for variable fields configuration

* Redesign the toolbar buttons to be similar to port stats
* Show protocols with variable fields in bold
* Variable field list will always have a 'current', if not empty
* Adding a new variable field makes it 'current' for immediate edit
* Each protocol remembers its 'current' variable field

Also renamed UserRole to a more widget specific enum
This commit is contained in:
Srivats P 2018-02-10 12:40:10 +05:30
parent 57597fe794
commit 52a5cb0d30
5 changed files with 155 additions and 123 deletions

BIN
client/icons/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

View File

@ -1,6 +1,7 @@
<RCC> <RCC>
<qresource prefix="/" > <qresource prefix="/" >
<file>icons/about.png</file> <file>icons/about.png</file>
<file>icons/add.png</file>
<file>icons/arrow_down.png</file> <file>icons/arrow_down.png</file>
<file>icons/arrow_left.png</file> <file>icons/arrow_left.png</file>
<file>icons/arrow_right.png</file> <file>icons/arrow_right.png</file>

View File

@ -63,7 +63,6 @@ VariableFieldsWidget::VariableFieldsWidget(QWidget *parent)
stream_ = NULL; stream_ = NULL;
isProgLoad_ = false; isProgLoad_ = false;
lastSelectedProtocolIndex_ = 0; lastSelectedProtocolIndex_ = 0;
lastSelectedVariableFieldIndex_ = 0;
setupUi(this); setupUi(this);
attribGroup->setHidden(true); attribGroup->setHidden(true);
@ -109,8 +108,11 @@ void VariableFieldsWidget::load()
AbstractProtocol *proto = iter->next(); AbstractProtocol *proto = iter->next();
QListWidgetItem *protoItem = new QListWidgetItem; QListWidgetItem *protoItem = new QListWidgetItem;
protoItem->setData(Qt::UserRole, QVariant::fromValue(proto)); protoItem->setData(kProtocolPtrRole, QVariant::fromValue(proto));
protoItem->setData(kCurrentVarFieldRole,
QVariant::fromValue(proto->variableFieldCount() ? 0 : -1));
protoItem->setText(proto->shortName()); protoItem->setText(proto->shortName());
decorateProtocolItem(protoItem);
protocolList->addItem(protoItem); protocolList->addItem(protoItem);
} }
@ -121,9 +123,6 @@ void VariableFieldsWidget::load()
// XXX: protocolList->setCurrentRow() above will emit currentItemChanged // XXX: protocolList->setCurrentRow() above will emit currentItemChanged
// which will load variableFieldsList - no need to load it explicitly // which will load variableFieldsList - no need to load it explicitly
if (lastSelectedVariableFieldIndex_ < variableFieldList->count())
variableFieldList->setCurrentRow(lastSelectedVariableFieldIndex_);
} }
void VariableFieldsWidget::store() void VariableFieldsWidget::store()
@ -148,7 +147,7 @@ void VariableFieldsWidget::on_protocolList_currentItemChanged(
if (current == NULL) if (current == NULL)
goto _exit; goto _exit;
proto = current->data(Qt::UserRole).value<AbstractProtocol*>(); proto = current->data(kProtocolPtrRole).value<AbstractProtocol*>();
loadProtocolFields(proto); loadProtocolFields(proto);
variableFieldList->clear(); variableFieldList->clear();
@ -167,6 +166,9 @@ void VariableFieldsWidget::on_protocolList_currentItemChanged(
field->setCurrentIndex(-1); field->setCurrentIndex(-1);
type->setCurrentIndex(-1); type->setCurrentIndex(-1);
variableFieldList->setCurrentRow(
current->data(kCurrentVarFieldRole).value<int>());
lastSelectedProtocolIndex_ = protocolList->currentRow(); lastSelectedProtocolIndex_ = protocolList->currentRow();
_exit: _exit:
@ -185,7 +187,7 @@ void VariableFieldsWidget::on_variableFieldList_currentItemChanged(
if (current == NULL) if (current == NULL)
goto _exit; goto _exit;
vf = current->data(Qt::UserRole).value<OstProto::VariableField>(); vf = current->data(kVarFieldRole).value<OstProto::VariableField>();
isProgLoad_ = true; isProgLoad_ = true;
@ -200,8 +202,9 @@ void VariableFieldsWidget::on_variableFieldList_currentItemChanged(
isProgLoad_ = false; isProgLoad_ = false;
lastSelectedVariableFieldIndex_ = variableFieldList->currentRow(); protocolList->currentItem()->setData(
kCurrentVarFieldRole,
QVariant::fromValue(variableFieldList->currentRow()));
_exit: _exit:
attribGroup->setHidden(current == NULL); attribGroup->setHidden(current == NULL);
deleteButton->setEnabled(current != NULL); deleteButton->setEnabled(current != NULL);
@ -214,7 +217,7 @@ void VariableFieldsWidget::on_addButton_clicked()
if (!protoItem) if (!protoItem)
return; return;
AbstractProtocol *proto = protoItem->data(Qt::UserRole) AbstractProtocol *proto = protoItem->data(kProtocolPtrRole)
.value<AbstractProtocol*>(); .value<AbstractProtocol*>();
OstProto::VariableField vf; OstProto::VariableField vf;
QListWidgetItem *vfItem = new QListWidgetItem; QListWidgetItem *vfItem = new QListWidgetItem;
@ -222,6 +225,9 @@ void VariableFieldsWidget::on_addButton_clicked()
proto->appendVariableField(vf); proto->appendVariableField(vf);
setVariableFieldItem(vfItem, proto, vf); setVariableFieldItem(vfItem, proto, vf);
variableFieldList->addItem(vfItem); variableFieldList->addItem(vfItem);
variableFieldList->setCurrentItem(vfItem);
decorateProtocolItem(protoItem);
} }
void VariableFieldsWidget::on_deleteButton_clicked() void VariableFieldsWidget::on_deleteButton_clicked()
@ -232,10 +238,21 @@ void VariableFieldsWidget::on_deleteButton_clicked()
if (!protoItem || (vfIdx < 0)) if (!protoItem || (vfIdx < 0))
return; return;
AbstractProtocol *proto = protoItem->data(Qt::UserRole) AbstractProtocol *proto = protoItem->data(kProtocolPtrRole)
.value<AbstractProtocol*>(); .value<AbstractProtocol*>();
proto->removeVariableField(vfIdx); proto->removeVariableField(vfIdx);
delete variableFieldList->takeItem(vfIdx); delete variableFieldList->takeItem(vfIdx);
// XXX: takeItem() above triggers a currentChanged, but the signal
// is emitted after the "current" is changed to an item after
// or before the item(s) to be deleted but before the item(s)
// are actually deleted - so the current inside that slot is not
// correct and we need to re-save it again
protocolList->currentItem()->setData(
kCurrentVarFieldRole,
QVariant::fromValue(variableFieldList->currentRow()));
decorateProtocolItem(protoItem);
} }
void VariableFieldsWidget::on_field_currentIndexChanged(int index) void VariableFieldsWidget::on_field_currentIndexChanged(int index)
@ -268,8 +285,9 @@ void VariableFieldsWidget::on_type_currentIndexChanged(int index)
if ((index < 0) || !protocolList->currentItem()) if ((index < 0) || !protocolList->currentItem())
return; return;
AbstractProtocol *proto = protocolList->currentItem()->data(Qt::UserRole) AbstractProtocol *proto = protocolList->currentItem()
.value<AbstractProtocol*>(); ->data(kProtocolPtrRole)
.value<AbstractProtocol*>();
int protoSize = proto->protocolFrameSize(); int protoSize = proto->protocolFrameSize();
switch (index) switch (index)
@ -326,12 +344,21 @@ void VariableFieldsWidget::updateCurrentVariableField()
vf.set_step(step->value()); vf.set_step(step->value());
QListWidgetItem *protoItem = protocolList->currentItem(); QListWidgetItem *protoItem = protocolList->currentItem();
AbstractProtocol *proto = protoItem->data(Qt::UserRole) AbstractProtocol *proto = protoItem->data(kProtocolPtrRole)
.value<AbstractProtocol*>(); .value<AbstractProtocol*>();
proto->mutableVariableField(variableFieldList->currentRow())->CopyFrom(vf); proto->mutableVariableField(variableFieldList->currentRow())->CopyFrom(vf);
setVariableFieldItem(variableFieldList->currentItem(), proto, vf); setVariableFieldItem(variableFieldList->currentItem(), proto, vf);
} }
void VariableFieldsWidget::decorateProtocolItem(QListWidgetItem *item)
{
AbstractProtocol *proto = item->data(kProtocolPtrRole)
.value<AbstractProtocol*>();
QFont font = item->font();
font.setBold(proto->variableFieldCount() > 0);
item->setFont(font);
}
void VariableFieldsWidget::loadProtocolFields( void VariableFieldsWidget::loadProtocolFields(
const AbstractProtocol *protocol) const AbstractProtocol *protocol)
{ {
@ -419,7 +446,7 @@ void VariableFieldsWidget::setVariableFieldItem(
else else
to = (vf.value() + (vf.count()-1)*vf.step()) & vf.mask(); to = (vf.value() + (vf.count()-1)*vf.step()) & vf.mask();
item->setData(Qt::UserRole, QVariant::fromValue(vf)); item->setData(kVarFieldRole, QVariant::fromValue(vf));
itemText = QString("%1 %2 %3 from %4 to %5") itemText = QString("%1 %2 %3 from %4 to %5")
.arg(protocol->shortName()) .arg(protocol->shortName())
.arg(fieldName) .arg(fieldName)

View File

@ -54,6 +54,7 @@ private slots:
void on_type_currentIndexChanged(int index); void on_type_currentIndexChanged(int index);
void updateCurrentVariableField(); void updateCurrentVariableField();
private: private:
void decorateProtocolItem(QListWidgetItem *item);
void loadProtocolFields(const AbstractProtocol *protocol); void loadProtocolFields(const AbstractProtocol *protocol);
int typeSize(OstProto::VariableField::Type type); int typeSize(OstProto::VariableField::Type type);
int fieldIndex(const OstProto::VariableField &vf); int fieldIndex(const OstProto::VariableField &vf);
@ -62,6 +63,17 @@ private:
const AbstractProtocol *protocol, const AbstractProtocol *protocol,
const OstProto::VariableField &vf); const OstProto::VariableField &vf);
// Custom roles for protocol items
enum {
kProtocolPtrRole = Qt::UserRole,
kCurrentVarFieldRole,
};
// Custom roles for variable field items
enum {
kVarFieldRole = Qt::UserRole
};
Stream *stream_; Stream *stream_;
QIntValidator *valueRange_; QIntValidator *valueRange_;
bool isProgLoad_; bool isProgLoad_;

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0" > <ui version="4.0" >
<class>VariableFieldsWidget</class> <class>VariableFieldsWidget</class>
<widget class="QWidget" name="VariableFieldsWidget" > <widget class="QWidget" name="VariableFieldsWidget" >
@ -12,114 +13,104 @@
<property name="windowTitle" > <property name="windowTitle" >
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" > <property name="autoFillBackground" >
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" >
<item> <item>
<layout class="QHBoxLayout" > <widget class="QSplitter" name="splitter" >
<property name="spacing" > <property name="orientation" >
<number>0</number> <enum>Qt::Horizontal</enum>
</property> </property>
<item> <widget class="QListWidget" name="protocolList" >
<widget class="QSplitter" name="splitter" > <property name="sizePolicy" >
<property name="orientation" > <sizepolicy hsizetype="Expanding" vsizetype="Expanding" >
<enum>Qt::Horizontal</enum> <horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="QWidget" name="widget" native="true" >
<property name="sizePolicy" >
<sizepolicy hsizetype="Preferred" vsizetype="Preferred" >
<horstretch>6</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<property name="margin" >
<number>0</number>
</property> </property>
<property name="childrenCollapsible" > <item>
<bool>false</bool> <widget class="QFrame" name="frame" >
</property> <property name="frameShape" >
<widget class="QListWidget" name="protocolList" > <enum>QFrame::Panel</enum>
<property name="sizePolicy" > </property>
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" > <property name="frameShadow" >
<horstretch>2</horstretch> <enum>QFrame::Raised</enum>
<verstretch>0</verstretch> </property>
</sizepolicy> <layout class="QHBoxLayout" name="horizontalLayout" >
</property> <item>
</widget> <widget class="QToolButton" name="addButton" >
<widget class="QListWidget" name="variableFieldList" > <property name="enabled" >
<property name="sizePolicy" > <bool>false</bool>
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" > </property>
<horstretch>6</horstretch> <property name="toolTip" >
<verstretch>0</verstretch> <string>Add variable field</string>
</sizepolicy> </property>
</property> <property name="text" >
</widget> <string>+</string>
</widget> </property>
</item> <property name="icon" >
<item> <iconset resource="ostinato.qrc" >
<widget class="QFrame" name="frame" > <normaloff>:/icons/add.png</normaloff>:/icons/add.png</iconset>
<property name="frameShape" > </property>
<enum>QFrame::Panel</enum> </widget>
</property> </item>
<property name="frameShadow" > <item>
<enum>QFrame::Sunken</enum> <widget class="QToolButton" name="deleteButton" >
</property> <property name="enabled" >
<layout class="QVBoxLayout" > <bool>false</bool>
<property name="leftMargin" > </property>
<number>0</number> <property name="toolTip" >
</property> <string>Remove variable field</string>
<property name="topMargin" > </property>
<number>0</number> <property name="text" >
</property> <string> - </string>
<property name="rightMargin" > </property>
<number>0</number> <property name="icon" >
</property> <iconset resource="ostinato.qrc" >
<property name="bottomMargin" > <normaloff>:/icons/delete.png</normaloff>:/icons/delete.png</iconset>
<number>0</number> </property>
</property> </widget>
<item> </item>
<spacer> <item>
<property name="orientation" > <spacer name="horizontalSpacer" >
<enum>Qt::Vertical</enum> <property name="orientation" >
</property> <enum>Qt::Horizontal</enum>
<property name="sizeHint" > </property>
<size> <property name="sizeHint" stdset="0" >
<width>20</width> <size>
<height>40</height> <width>40</width>
</size> <height>20</height>
</property> </size>
</spacer> </property>
</item> </spacer>
<item> </item>
<widget class="QToolButton" name="addButton" > </layout>
<property name="enabled" > </widget>
<bool>false</bool> </item>
</property> <item>
<property name="text" > <widget class="QListWidget" name="variableFieldList" />
<string>+</string> </item>
</property> </layout>
</widget> </widget>
</item> </widget>
<item>
<widget class="QToolButton" name="deleteButton" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string> - </string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="attribGroup" > <widget class="QGroupBox" name="attribGroup" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" > <sizepolicy hsizetype="Preferred" vsizetype="Preferred" >
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -138,7 +129,7 @@
<item row="0" column="1" > <item row="0" column="1" >
<widget class="QComboBox" name="field" > <widget class="QComboBox" name="field" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" > <sizepolicy hsizetype="Preferred" vsizetype="Fixed" >
<horstretch>3</horstretch> <horstretch>3</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -158,7 +149,7 @@
<item row="0" column="3" > <item row="0" column="3" >
<widget class="QComboBox" name="type" > <widget class="QComboBox" name="type" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" > <sizepolicy hsizetype="Preferred" vsizetype="Fixed" >
<horstretch>2</horstretch> <horstretch>2</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -178,7 +169,7 @@
<item row="0" column="5" > <item row="0" column="5" >
<widget class="QSpinBox" name="offset" > <widget class="QSpinBox" name="offset" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Minimum" > <sizepolicy hsizetype="Minimum" vsizetype="Fixed" >
<horstretch>2</horstretch> <horstretch>2</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -201,7 +192,7 @@
<item row="0" column="7" > <item row="0" column="7" >
<widget class="QLineEdit" name="bitmask" > <widget class="QLineEdit" name="bitmask" >
<property name="sizePolicy" > <property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" > <sizepolicy hsizetype="Expanding" vsizetype="Fixed" >
<horstretch>2</horstretch> <horstretch>2</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -263,7 +254,7 @@
<property name="orientation" > <property name="orientation" >
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0" >
<size> <size>
<width>561</width> <width>561</width>
<height>41</height> <height>41</height>
@ -276,7 +267,6 @@
<tabstops> <tabstops>
<tabstop>protocolList</tabstop> <tabstop>protocolList</tabstop>
<tabstop>variableFieldList</tabstop> <tabstop>variableFieldList</tabstop>
<tabstop>addButton</tabstop>
<tabstop>deleteButton</tabstop> <tabstop>deleteButton</tabstop>
<tabstop>field</tabstop> <tabstop>field</tabstop>
<tabstop>type</tabstop> <tabstop>type</tabstop>
@ -287,6 +277,8 @@
<tabstop>count</tabstop> <tabstop>count</tabstop>
<tabstop>step</tabstop> <tabstop>step</tabstop>
</tabstops> </tabstops>
<resources/> <resources>
<include location="ostinato.qrc" />
</resources>
<connections/> <connections/>
</ui> </ui>