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>
<qresource prefix="/" >
<file>icons/about.png</file>
<file>icons/add.png</file>
<file>icons/arrow_down.png</file>
<file>icons/arrow_left.png</file>
<file>icons/arrow_right.png</file>

View File

@ -63,7 +63,6 @@ VariableFieldsWidget::VariableFieldsWidget(QWidget *parent)
stream_ = NULL;
isProgLoad_ = false;
lastSelectedProtocolIndex_ = 0;
lastSelectedVariableFieldIndex_ = 0;
setupUi(this);
attribGroup->setHidden(true);
@ -109,8 +108,11 @@ void VariableFieldsWidget::load()
AbstractProtocol *proto = iter->next();
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());
decorateProtocolItem(protoItem);
protocolList->addItem(protoItem);
}
@ -121,9 +123,6 @@ void VariableFieldsWidget::load()
// XXX: protocolList->setCurrentRow() above will emit currentItemChanged
// which will load variableFieldsList - no need to load it explicitly
if (lastSelectedVariableFieldIndex_ < variableFieldList->count())
variableFieldList->setCurrentRow(lastSelectedVariableFieldIndex_);
}
void VariableFieldsWidget::store()
@ -148,7 +147,7 @@ void VariableFieldsWidget::on_protocolList_currentItemChanged(
if (current == NULL)
goto _exit;
proto = current->data(Qt::UserRole).value<AbstractProtocol*>();
proto = current->data(kProtocolPtrRole).value<AbstractProtocol*>();
loadProtocolFields(proto);
variableFieldList->clear();
@ -167,6 +166,9 @@ void VariableFieldsWidget::on_protocolList_currentItemChanged(
field->setCurrentIndex(-1);
type->setCurrentIndex(-1);
variableFieldList->setCurrentRow(
current->data(kCurrentVarFieldRole).value<int>());
lastSelectedProtocolIndex_ = protocolList->currentRow();
_exit:
@ -185,7 +187,7 @@ void VariableFieldsWidget::on_variableFieldList_currentItemChanged(
if (current == NULL)
goto _exit;
vf = current->data(Qt::UserRole).value<OstProto::VariableField>();
vf = current->data(kVarFieldRole).value<OstProto::VariableField>();
isProgLoad_ = true;
@ -200,8 +202,9 @@ void VariableFieldsWidget::on_variableFieldList_currentItemChanged(
isProgLoad_ = false;
lastSelectedVariableFieldIndex_ = variableFieldList->currentRow();
protocolList->currentItem()->setData(
kCurrentVarFieldRole,
QVariant::fromValue(variableFieldList->currentRow()));
_exit:
attribGroup->setHidden(current == NULL);
deleteButton->setEnabled(current != NULL);
@ -214,7 +217,7 @@ void VariableFieldsWidget::on_addButton_clicked()
if (!protoItem)
return;
AbstractProtocol *proto = protoItem->data(Qt::UserRole)
AbstractProtocol *proto = protoItem->data(kProtocolPtrRole)
.value<AbstractProtocol*>();
OstProto::VariableField vf;
QListWidgetItem *vfItem = new QListWidgetItem;
@ -222,6 +225,9 @@ void VariableFieldsWidget::on_addButton_clicked()
proto->appendVariableField(vf);
setVariableFieldItem(vfItem, proto, vf);
variableFieldList->addItem(vfItem);
variableFieldList->setCurrentItem(vfItem);
decorateProtocolItem(protoItem);
}
void VariableFieldsWidget::on_deleteButton_clicked()
@ -232,10 +238,21 @@ void VariableFieldsWidget::on_deleteButton_clicked()
if (!protoItem || (vfIdx < 0))
return;
AbstractProtocol *proto = protoItem->data(Qt::UserRole)
AbstractProtocol *proto = protoItem->data(kProtocolPtrRole)
.value<AbstractProtocol*>();
proto->removeVariableField(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)
@ -268,8 +285,9 @@ void VariableFieldsWidget::on_type_currentIndexChanged(int index)
if ((index < 0) || !protocolList->currentItem())
return;
AbstractProtocol *proto = protocolList->currentItem()->data(Qt::UserRole)
.value<AbstractProtocol*>();
AbstractProtocol *proto = protocolList->currentItem()
->data(kProtocolPtrRole)
.value<AbstractProtocol*>();
int protoSize = proto->protocolFrameSize();
switch (index)
@ -326,12 +344,21 @@ void VariableFieldsWidget::updateCurrentVariableField()
vf.set_step(step->value());
QListWidgetItem *protoItem = protocolList->currentItem();
AbstractProtocol *proto = protoItem->data(Qt::UserRole)
AbstractProtocol *proto = protoItem->data(kProtocolPtrRole)
.value<AbstractProtocol*>();
proto->mutableVariableField(variableFieldList->currentRow())->CopyFrom(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(
const AbstractProtocol *protocol)
{
@ -419,7 +446,7 @@ void VariableFieldsWidget::setVariableFieldItem(
else
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")
.arg(protocol->shortName())
.arg(fieldName)

View File

@ -54,6 +54,7 @@ private slots:
void on_type_currentIndexChanged(int index);
void updateCurrentVariableField();
private:
void decorateProtocolItem(QListWidgetItem *item);
void loadProtocolFields(const AbstractProtocol *protocol);
int typeSize(OstProto::VariableField::Type type);
int fieldIndex(const OstProto::VariableField &vf);
@ -62,6 +63,17 @@ private:
const AbstractProtocol *protocol,
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_;
QIntValidator *valueRange_;
bool isProgLoad_;

View File

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